Anxiety Aid Tools: grounding 5-4-3-2-1 + practice picker - #207
alvinunreal wants to merge 6 commits into
Conversation
Add a self-paced "grounding" session kind (SDK types, validator, conformance): senses as steps with items and hints, no clock or pause. The grounding view shows the sense checklist, per-item dots, elapsed and noticed tiles, a 5-4-3-2-1 track, Next/Back, an orb that brightens per sense, and a per-sense summary when finished. Checking items is optional. Replace the cycle-to-next practice button with a header practice picker listing every practice with its icon. Session icons move to a shared session-icons.ts used by the Info window and the overlay; a test guards that every allowlisted icon draws. Anxiety Aid Tools gains the grounding practice (Start grounding command, Stop-only pet menu) with honest Info: the cited studies are described as what they are, not as 5-4-3-2-1 trials. Localized x7.
|
| /** Lead-in countdown in seconds (0–15, default 5); 0 is usual for grounding. */ | ||
| countdownSeconds?: number; | ||
| /** Info sheet content for the current technique. */ | ||
| info?: OpenPetsSessionInfo; |
There was a problem hiding this comment.
Grounding updates fail at runtime
Grounding sessions receive the common OpenPetsSessionHandle, whose public update() contract accepts Info updates. However, the desktop host rejects every update when the session kind is not breathing. A plugin can therefore type-check and pass mock-SDK tests with groundingHandle.update({ info }), only to receive a runtime rejection in the real app. Please either expose a kind-specific handle or make the host and test implementation support the documented grounding update contract.
Knowledge Base Used:
| /** | ||
| * Self-paced sensory grounding (e.g. 5-4-3-2-1). There is no phase clock: | ||
| * the user checks items and moves on with Next, so the overlay never pauses. | ||
| * `started`, `completed` (with `cycles` = items noticed), and `stopped` |
There was a problem hiding this comment.
The grounding contract promises that lifecycle events use patternId: "grounding", but the SDK test harness derives the ID from the optional practiceId or the first step ID. A valid descriptor that omits practiceId therefore emits values such as "see" in plugin tests, while the real renderer emits "grounding". This makes deterministic plugin tests disagree with production behavior.
Knowledge Base Used:
| for (const choice of descriptor.practices ?? []) { | ||
| const option = el("button", "session-practice-option"); | ||
| option.type = "button"; | ||
| option.setAttribute("role", "menuitemradio"); |
There was a problem hiding this comment.
The picker declares an ARIA menu containing menuitemradio controls, but opening it does not move focus into the menu or implement Arrow Up/Down, Home, or End navigation; the only menu keyboard handling is Escape. Keyboard and assistive-technology users therefore receive menu semantics without the expected interaction model. Add focus entry and return plus menu-key navigation, or use ordinary radio/button semantics instead.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
The session card now sits at the top of the carrier and the orb wraps the pet near its resting spot below it, instead of stacking the orb above a bottom card. The pet rises only as far as the orb's rim needs (~50px rather than the full card height), and the orb stays put when the card changes height. The practice picker drops down under the header. Geometry constants are renamed to the new order; the carrier height total is unchanged.
|
Added
Checks: typecheck, build and tests pass, plugin validators pass, renderer events are identical in the old-vs-new harness, and I checked static renders of all four practices. |
…menu The top-card layout exposed a large empty band between card and orb: the carrier was sized from per-practice card estimates and an assumed orb size. The overlay now measures its real card and orb and reports the height it needs; the carrier fits it with the pet anchored, and estimates only size the first frame. PMR tense/release cue boxes fit their content instead of a fixed 124px. The pet menu now lists only the four practices; the Open Anxiety Aid Tools command and the last-practice memory it relied on are removed.
The session carrier was still leaving a large band under the card. The pet page was rendering zoomed: Chromium remembers zoom per host and all file:// pages share one, so a zoom set elsewhere leaked into the pet window, which never pinned its own. The overlay measured CSS pixels while the carrier is sized in window points, so every height report was off by the zoom. Pin zoomFactor 1 at creation, on every load and on zoom-changed, lock pinch zoom, and log when a reset happens. Each session height report now logs its measurement inputs (card and sprite height, viewport, device pixel ratio, orb radius, pet lift) so a future mismatch is diagnosable from openpets.log.
AAT plays a cue pair recorded for each guided pattern (4-4-4-4, 4-7-8,
4-4-6, 3-3-3); the plugin reused the Calm 4-6 pair for all of them.
Breath patterns now take optional cues {inhale, exhale}: the bridge
resolves them on open and update, the coordinator ships them per
pattern, and the overlay plays the selected pattern's pair, falling
back to the session pair. The plugin ships AAT's eight pattern files.
PMR tense/release cue numbers now sit centred on their first text line.
Stacked on #206 (base
feat/aat-guided-breathing); retarget tomainonce #206 merges.Summary
grounding(SDK types, validator, conformance check). Each sense is a step with a label, title, prompt, icon and 1–6 items with hints.src/session-icons.ts, used by the Info window and, through the coordinator's renderer payload, the overlay. New icons: anchor, eye, hand, ear, flower, coffee.Verification
tests/session-icons.test.ts: every allowlisted icon draws, grounding validates, and unknown icons are rejected.plugins:test,plugins:locales,plugins:check,plugins:package,plugins:validate-release(18 plugins): pass.Known gaps
docs/*.mdintentionally untouched until sign-off (pertask.txt). Codemap updated.