Skip to content

Anxiety Aid Tools: grounding 5-4-3-2-1 + practice picker - #207

Open
alvinunreal wants to merge 6 commits into
feat/aat-guided-breathingfrom
feat/aat-grounding
Open

alvinunreal wants to merge 6 commits into
feat/aat-guided-breathingfrom
feat/aat-grounding

Conversation

@alvinunreal

Copy link
Copy Markdown
Collaborator

Stacked on #206 (base feat/aat-guided-breathing); retarget to main once #206 merges.

Summary

  • Grounding 5-4-3-2-1: a new self-paced session kind grounding (SDK types, validator, conformance check). Each sense is a step with a label, title, prompt, icon and 1–6 items with hints.
    • No clock and no pause. Next (Finish on the last sense) and Back replace Pause/Restart.
    • Checking items is optional, so Next never gates.
    • Card: sense checklist, per-item dots, elapsed · sense icon · "noticed" tiles, and a 5-4-3-2-1 track in sense colours. The orb brightens with each sense.
    • The finished card shows a per-sense summary.
    • Pet menu offers Stop only.
  • Practice picker: the header (icon, title and chevron) opens a menu of every practice with its icon on the idle and finished card. It replaces the cycle-to-next button. Practice choices take an allowlisted icon.
  • Shared icons: SVGs move to 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.
  • Plugin: Anxiety Aid Tools gets the grounding practice, a "Start grounding" command, and picker icons for all four practices. Localized ×7, with the new host chrome strings ×7.
  • Honest science: Info says grounding is a standard CBT/DBT/trauma-therapy skill with thin direct evidence for 5-4-3-2-1 on its own. The three cited studies are described as what they are. AAT's "meta-analysis, 82%" claim didn't match its source and isn't repeated.

Verification

  • Desktop typecheck, build and tests pass, including the new tests/session-icons.test.ts: every allowlisted icon draws, grounding validates, and unknown icons are rejected.
  • Plugin golden test: 5-4-3-2-1 structure, citation links, command, Stop-only menu, and practice icons.
  • plugins:test, plugins:locales, plugins:check, plugins:package, plugins:validate-release (18 plugins): pass.
  • Old-vs-new renderer harness: breathing and PMR events are identical. The only text/display differences come from the removed cycle button.
  • Static renders at real sizes checked visually: picker, grounding running / last sense / finished summary, and the grounding Info window.

Known gaps

  • Not yet run in the app.
  • docs/*.md intentionally untouched until sign-off (per task.txt). Codemap updated.

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.
@greptile-apps

greptile-apps Bot commented Sep 22, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 3/5

The PR is not yet safe to merge because the new public grounding SDK contract disagrees with both the production host’s update behavior and the deterministic test harness’s lifecycle events.

Fix All in Claude CodeFindings

  1. P1 Grounding updates fail at runtime
  2. P1 Mock emits wrong pattern ID
  3. P2 Picker lacks menu navigation

Summary

This PR adds a self-paced 5-4-3-2-1 grounding session, a practice picker, shared allowlisted session icons, localized host/plugin content, and the corresponding SDK and validation contracts.

  • Adds grounding steps, optional checklists, progress summaries, controls, and overlay styling.
  • Extends session descriptor validation and the public SDK with grounding and picker icons.
  • Adds an all-practice picker and wires practice selection through the session coordinator.
  • Expands Anxiety Aid Tools and its seven locale catalogs with grounding content and commands.
  • Two SDK contract inconsistencies remain: non-breathing Info updates fail only in production, and the test harness emits the wrong grounding pattern ID when practiceId is omitted.
  • The picker also needs keyboard behavior consistent with its declared ARIA menu semantics.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  P[Plugin grounding descriptor] --> V[Host descriptor validation]
  V --> C[Session overlay coordinator]
  C --> R[Pet-window renderer]
  R --> U[Grounding UI and practice picker]
  U --> E[Lifecycle and practice events]
  E --> P
  P --> T[SDK testing harness]
  T -. currently derives first step ID .-> E
  P --> H[Session handle update]
  H -. currently rejected for grounding .-> C
Loading

Reviews (1) · Last reviewed commit: "feat(aat): grounding 5-4-3-2-1 practice ..."

Comment thread packages/sdk/src/index.ts
/** 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;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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:

Fix in Claude Code

Comment thread packages/sdk/src/index.ts
/**
* 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`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Mock emits wrong pattern ID

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:

Fix in Claude Code

Comment on lines +475 to +478
for (const choice of descriptor.practices ?? []) {
const option = el("button", "session-practice-option");
option.type = "button";
option.setAttribute("role", "menuitemradio");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Picker lacks menu navigation

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!

Fix in Claude Code

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.
@alvinunreal

Copy link
Copy Markdown
Collaborator Author

Added b5da7e2: the session HUD card now sits on top of the pet for every practice (breathing, guided breathing, PMR, grounding). The orb wraps the pet near its resting spot below the card.

  • The pet rises about 50px instead of the whole card height.
  • The orb no longer moves when the card changes height.
  • The practice picker drops down under the header.
  • The carrier height total is unchanged.

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant