DUNIN7 · Loomworks · Completion Record
Plain-language summary
The Engine already knew "where you are" — say "open Goosey" and your unqualified commands land in Goosey — but the screen showed none of it. This wires the two together: a top-bar chip reads here: 7 · Goosey · E0007 (your number · name · E-label, never the UUID); clicking a project opens it and sets focus as one act; saying "open X" / "close" moves focus and the chip follows. Built template-clean — every colour a design token, every brand word in strings.ts — with a guard test that fails the build if a guarded file introduces a raw colour or hardcoded brand word. The shared top bar (TopBar) was tokenized too, because the chip lives in it and a template's top bar must be swappable.
Branch off main bafdb07. Not pushed. Frontend-only; no Engine change.
| Commit | Step | Change |
|---|---|---|
9b795ee | 0 | Archive CR as branch base (baseline bafdb07, Vitest 470/62). |
2b52d2d | 1 | me-current-engagement.ts adapter — GET/PUT focus; typed SetFocusResult (404→not_found, 409→ambiguous, 401→unauthorized); vocab-wall allowlisted. |
fdeb5a0 | 2 | CurrentEngagementProvider — GET-on-mount; setFocus/clearFocus refetch on ok (GET-on-change); mounted in layout inside AuthProvider. |
346ba75 | 3 | Tokenize TopBar — 4 alpha-modifier conversions + 2 new tokens (--color-vellum-soft, --color-gold) wired into @theme; both surfaces verified; Tailwind v4 compiles every class. |
263ee4f | 4 | FocusChip (here: N·Name·E####, hidden off-focus, never UUID) + unified open (focus-set beside router.push, non-blocking) + FOCUS strings. |
a7d659a | 5 | Spoken open/close wired (useRefreshFocusOnIntent on the converse surfaces) + template-cleanliness guard. |
Vitest: 470 → 479 → 484 → 489 → 494 → 498 passed / 69 files, 0 failed. next build compiles clean (TypeScript + Tailwind; all 18 routes prerender). No schema/Engine change.
Loomworks/Companion; no general JSX-text scanner (over-broad). Two off-palette TopBar shades got new tokens (no Step 3 halt).current_engagement_id in types.ts would trip the vocabulary-wall (engagement_id substring); the adapter projects to camelCase Operator-vocab types (the projects.ts pattern) and unwraps FastAPI's {detail} envelope. Wire fields stay in the allowlisted adapter.useCurrentEngagementOptional (mirrors useAuthOptional) — chip / list / converse surfaces degrade to a no-op outside the provider (139 isolation tests would otherwise throw); the chip is correctly a no-op without focus context.Loomworks → BRAND.productName; "Speak to Companion" → NAV.voiceSpeakLabel (from BRAND.defaultCompanionName). Guard scope is an includelist (this CR's files + TopBar); EngagementList's pre-existing hex and other brand strings are out of scope (CR-2026-126 is the repo-wide colour sweep).FOCUS.ambiguous/notFound serve the endpoint path; the converse path uses the Engine's message.| Walk step | Covered by |
|---|---|
| 1 — click → navigates AND chip shows here: N·Name·E#### | UnifiedOpen.test (push + focus PUT); FocusChip.test (labels) |
| 2 — "open Goosey" → chip updates | RefreshFocusOnIntent.test (open intent refetches focus) |
| 3 — unqualified command lands in focus | Engine-side (CR-2026-123/124, merged + DB-walked); frontend reflects via provider |
| 4 — "open <duplicate>" → candidates; focus unchanged | me-current-engagement.test (409→ambiguous); CurrentEngagementProvider.test (ambiguous leaves focus) |
| 5 — "open <nonexistent>" → not-found; focus unchanged | me-current-engagement.test (404→not_found) |
| 6 — "close" → chip clears; next unqualified → asks | FocusChip.test (close→clear); CurrentEngagementProvider.test; Engine asks (CR-2026-124) |
| 7 — guards green; TopBar unchanged both surfaces | template-clean + vocabulary-wall green; next build compiles; TopBar 0 hex/rgba; both surface suites green |
TopBar render-identical: the alpha conversions are mathematically exact and the two new tokens resolve to the exact original hex; Tailwind v4.3.1 compiles every class (verified by direct compile, not trusted). Manual pixel-diff on a running app is the one check not automatable in jsdom; the math + compile make it identical by construction.
Halt before push — Operator authorization required
The branch (6 commits, 9b795ee..a7d659a) is not pushed. On review and explicit authorization, merge to main and push.
NAV.voiceSpeakLabel is static for Phase 1; the per-Operator name is the ready-not-active extension.cr-2026-125-companion-surface-phase1 at a7d659a, 6 commits ahead of main bafdb07. Not pushed. Tree clean (.dev.vars + .next/ ignored).cfeebd0).4aa11f2); no-hardcoded-CSS standing note + CR-2026-126 (3e25fa5); this completion record. (Record commits unpushed pending authorization.)