core/docs/handoff/wave-R-mastery-briefs-2026-06-12.md

346 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Wave R Mastery Revamp — Dispatch Briefs (R0aR0d, R1)
Date: 2026-06-12
Plan: `docs/workbench/wave-R-mastery-revamp.md` (read it first — it is the
governing spec; this pack is the per-operator cut).
## Dispatch order
```
Echelon 1 (parallel dispatch): R0a ∥ R0b ∥ R0c
Echelon 2: R0d (after R0c merges)
Echelon 3: R1 (after all R0 merges)
```
**Merge order is a strict train even though dispatch is parallel:**
R0a merges FIRST (smallest PR; carries the honesty fix; lands the CI lane
that then verifies R0b/R0c). R0b and R0c merge next, either order, each
rebased on merged main before push if R0a landed meanwhile. R0d after R0c.
Never combine R0 briefs into one PR.
Brief 5 (Trace route, `wave-1-evidence-spine-briefs-2026-06-12.md`) **stays
on hold** until R0 lands; it gets re-issued upgraded as the first R2 brief.
## Standing constraints (every brief)
- Worktree per operator, always off fresh `origin/main` — never share a
working dir.
- The merge pipeline is automated; **pre-push verification is the gate.**
Run your brief's verification block before pushing.
- Token-only styling (no raw hex/rgb outside `tokens.css`); no color-only
encoding; motion only via `--motion-*` tokens; `prefers-reduced-motion`
collapses to instant.
- ADR-0162 no-go list applies verbatim (no thinking animations, no
glassmorphism, no toasts that auto-dismiss audit events, no icon-only
buttons).
- Surfaces stay distinct everywhere: `surface``articulation_surface`
`walk_surface`.
- No mutation endpoints, no writes outside `workbench_data/` from workbench
code.
- Until R0a merges: full `pnpm test` may hang on teardown. Verify with
`pnpm build` + per-file `pnpm vitest run <file>`; `pkill -9 -f vitest`
afterwards if needed.
- Commit format `<type>(workbench): <description>`; push with `-u`; open a
PR titled as given in the brief.
---
## Brief R0a — Test-runner hardening + frontend CI lane
**Suggested operator:** Codex
**Scope:** `workbench-ui/` test config + timer hygiene; one new GitHub
workflow. No product code changes beyond timer cleanup.
### Worktree
```bash
cd /Users/kaizenpro/Projects/core
git fetch origin
git worktree add ../core-wb-r0a origin/main -b feat/wb-r0a-test-hardening
cd ../core-wb-r0a/workbench-ui && pnpm install
```
### Context
Full multi-file `pnpm test` hangs on worker teardown — tests pass, the
process never exits. Diagnosed 2026-06-12: live handles at teardown
(`Timestamp.tsx` `setInterval(..., 60_000)`, copy-feedback `setTimeout`s);
`vite.config.ts` has no `testTimeout`/`teardownTimeout`; switching pools does
not fix it; single files exit clean. Separately: **no CI workflow runs
workbench-ui at all** (`smoke.yml` / `full-pytest.yml` are Python-only).
### Deliverables
1. `vite.config.ts` test config: `testTimeout: 10_000`,
`hookTimeout: 10_000`, `teardownTimeout: 5_000`. Tune pool options only
if measurements justify it — caps first, knobs second.
2. Timer hygiene: audit every `setInterval`/`setTimeout`/`AbortController`
under `src/`; ensure each has a cleanup path on unmount. In tests that
mount timer-scheduling components (`Timestamp`, copy buttons), use
`vi.useFakeTimers()` with restoration in `afterEach`.
3. Prove it: full `pnpm test` runs to completion AND the process exits.
Record wall-clock in the PR body.
4. New `.github/workflows/workbench-ui.yml`:
- `on: pull_request` + `push: branches: [main]`, both with
`paths: ['workbench-ui/**', '.github/workflows/workbench-ui.yml']`
(the workflow validates changes to itself)
- single job, `timeout-minutes: 15`: pnpm setup (frozen lockfile) →
`pnpm build``pnpm test`
- Node 20, pnpm via `corepack` or `pnpm/action-setup`
5. Honesty fix, **unconditional**: remove the `j/k`, `/`, and
`Enter — Open selected item` rows from `KeyboardHelp.tsx` and its test
expectations — the overlay must not advertise shortcuts that do not
exist. (`Enter` is real only inside the palette, which carries its own
hint; as a global list affordance it is false until R0d.) R0d restores
these rows as real, registry-backed entries.
6. Minimal route conformance test (front-loaded from R1):
`src/app/routeConformance.test.tsx`, parametrized over the implemented
routes (Chat, Proposals, Evals, Replay). For each route, under mocked
query states, assert: empty state renders a one-line absence statement +
a next action; error state renders what-failed + mutation status +
reproducer + retry-safety; loading state renders a specific label (never
"Thinking…"). Per ADR-0162 §6. Fix routes that fail; no expected-fail
lists (a test that tolerates violations is decoration).
### Verification before push
```bash
cd workbench-ui && pnpm build && time pnpm test # must EXIT, all green
git -C .. diff --stat origin/main # only intended files
```
PR title: `fix(workbench): test-runner teardown hardening + frontend CI lane`
---
## Brief R0b — Playwright smoke lane
**Suggested operator:** GPT5.5-Thinking
**Scope:** `workbench-ui/` e2e only. Pays ADR-0162 acceptance-criteria debt
(§ acceptance 5, 6, 7). No product code changes except test hooks
(`data-testid` additions are allowed, sparingly).
### Worktree
```bash
cd /Users/kaizenpro/Projects/core
git fetch origin
git worktree add ../core-wb-r0b origin/main -b feat/wb-r0b-playwright
cd ../core-wb-r0b/workbench-ui && pnpm install
```
### Deliverables
1. `@playwright/test` devDependency (pinned), `playwright.config.ts` with
`webServer` serving the built app (`pnpm build && vite preview`),
chromium-only project (keep the lane lean).
2. `e2e/palette.spec.ts` — from each of the ten routes: `Meta+K` opens the
palette; selecting a navigation command reaches every route (URL
asserted). The app must be usable with the backend absent — routes render
their error/empty states, never a white screen (this doubles as an
offline-resilience assertion).
3. `e2e/reduced-motion.spec.ts` — with `reducedMotion: 'reduce'`, tokenized
motion collapses to instant (assert computed transition/animation
durations are `0s` on a drawer open and palette open).
4. `e2e/preview-offline.spec.ts``context.route('**', abort)` for
non-localhost requests; `/preview` still renders every primitive section
(fonts are self-hosted; nothing may fetch the network).
5. `pnpm test:e2e` script; add a **separate job** to
`.github/workflows/workbench-ui.yml` if R0a's workflow exists on your
base, else create the file with just your job (merge is trivial either
way) — `timeout-minutes: 15`, cache playwright browsers.
### Verification before push
```bash
cd workbench-ui && pnpm build && pnpm test:e2e # all green locally
```
PR title: `test(workbench): playwright smoke lane (ADR-0162 acceptance 5-7)`
---
## Brief R0c — Evidence addresses (URL = subject)
**Suggested operator:** Claude
**Scope:** React/TypeScript. The audit-native deep-linking substrate every
R2 route will consume.
### Worktree
```bash
cd /Users/kaizenpro/Projects/core
git fetch origin
git worktree add ../core-wb-r0c origin/main -b feat/wb-r0c-evidence-addresses
cd ../core-wb-r0c/workbench-ui && pnpm install
```
### Read first
- `docs/workbench/wave-R-mastery-revamp.md` § R0c
- `workbench-ui/src/app/evidenceContext.tsx` (the `EvidenceSubject` union)
- `workbench-ui/src/app/App.tsx`, `useGlobalKeyboard.ts`,
`commandRegistry.ts`
### Deliverables
1. `workbench-ui/src/app/evidenceAddress.ts`:
- `subjectToUrl(subject: EvidenceSubject): string` — canonical path
(`/trace/42`, `/proposals/<id>`, `/evals/<lane>`, `/replay/<artifact>`)
plus `?inspect=` when the inspector is open on a different subject
- `urlToSubject(params, searchParams): { route: EvidenceSubject | null,
inspect: EvidenceSubject | null }` — total inverse; malformed input
returns `null`, never throws
- The codec speaks ALL subject kinds now, including ones whose routes are
still placeholders — the grammar is fixed once.
2. `App.tsx` route params: `/trace/:turnId?`, `/proposals/:proposalId?`,
`/evals/:laneId?`, `/replay/:artifactId?`. Placeholder routes keep flat
paths.
3. `EvidenceProvider` ↔ URL sync: `?inspect=` carries inspector subject +
open state; deep link restores it; subject changes update the URL
(`replace`, not `push` — selection churn must not pollute history).
4. Existing routes restore selection from their param on load and write it
on selection change: `ProposalsRoute`, `EvalsRoute`, `ReplayRoute`.
5. `Cmd+Shift+C` in `useGlobalKeyboard`: copies
`window.location.origin + subjectToUrl(current subject)`; no-op with no
subject; input-focus guard applies. Visible copy-confirmation must not
auto-dismiss audit context (a transient inline "Copied" on the inspector
header is fine; no toast).
6. Tests: codec round-trip for every subject kind (including malformed
inputs); deep-link restores Proposals selection (MemoryRouter
`initialEntries`); `?inspect=` restores inspector; URL updates use
`replace`.
### Verification before push
```bash
cd workbench-ui && pnpm build
pnpm vitest run src/app/evidenceAddress.test.ts src/app/evidenceContext.test.tsx src/app/proposals/ProposalsRoute.test.tsx
# (per-file runs until R0a lands; then plain `pnpm test`)
```
PR title: `feat(workbench): evidence addresses — deep-linkable subjects + inspector URL state`
---
## Brief R0d — Interaction substrate (AFTER R0c merges)
**Suggested operator:** Codex or GPT5.5-Thinking
**Scope:** React/TypeScript. List navigation, virtualization, panel chrome,
inspector resize, palette action verbs.
### Worktree
```bash
cd /Users/kaizenpro/Projects/core
git fetch origin
git worktree add ../core-wb-r0d origin/main -b feat/wb-r0d-interaction-substrate
cd ../core-wb-r0d/workbench-ui && pnpm install
ls src/app/evidenceAddress.ts || echo "STOP: R0c not merged"
```
### Deliverables
1. `src/design/hooks/useListNavigation.ts`: `j`/`k`/`ArrowUp`/`ArrowDown`/
`Home`/`End` move focus, `Enter` activates, input-focus guard (reuse the
`isInputFocused` pattern from `useGlobalKeyboard.ts`). Roving tabindex or
`aria-activedescendant` — focused row visibly distinct, screen-reader
coherent. Unit tested.
2. `src/design/components/VirtualizedList/`: wraps `@tanstack/react-virtual`
(add dep, pinned), composes `useListNavigation`, deterministic item keys,
stable scroll restoration. Tested (virtualization kicks in above the
threshold; keyboard nav still works across virtualized boundaries).
3. `src/design/components/Panel/`: header (title + toolbar slot) + body
chrome, token-only. This is the standard panel every R2 route composes.
4. Inspector resize in `Shell.tsx`: wire the existing `SplitPane` for the
inspector column; width persisted to localStorage **with guarded access**
(see commit `af8d4f75` for the precedent — storage can throw).
5. Palette action commands: `commandRegistry.ts` gains an action kind
(discriminated union: `navigate` | `action`); routes register/unregister
their own commands on mount (the deferred Wave-1 call-site pattern).
First verbs: "Copy evidence link" (calls R0c's address copy), "Toggle
inspector", and Evals registers "Run eval lane <lane>" (executes the
existing read-only `POST /evals/run` — ADR-0160-allowed lane, not a
mutation).
6. Wire it for real: Proposals list and Replay artifact list adopt
`useListNavigation` + `SearchInput` (the `/` shortcut becomes real where
mounted).
7. `Kbd` primitive (front-loaded from R1): a small token-only component for
rendering key chords; `KeyboardHelp` and palette shortcut hints adopt it.
8. `KeyboardHelp.tsx` becomes **registry-driven**: the overlay renders its
rows from the shortcut/command registry instead of a hand-maintained
array, so advertising an unimplemented shortcut is structurally
impossible. The rows R0a removed (`j/k`, `/`, `Enter`) return here as
real registry entries. Test: every row in the rendered overlay
corresponds to a registered, handled shortcut.
### Verification before push
```bash
cd workbench-ui && pnpm build && pnpm test # R0a is merged by now: full run must exit green
```
PR title: `feat(workbench): interaction substrate — list nav, virtualization, panel chrome, inspector resize, palette verbs`
---
## Brief R1 — Design mastery pass (AFTER all R0 merges)
**Suggested operator:** Claude
**Scope:** one PR, visual + doctrine-as-tests. No new routes, no new
endpoints.
### Worktree
```bash
cd /Users/kaizenpro/Projects/core
git fetch origin
git worktree add ../core-wb-r1 origin/main -b feat/wb-r1-design-mastery
cd ../core-wb-r1/workbench-ui && pnpm install
ls src/design/components/Panel || echo "STOP: R0d not merged"
```
### Deliverables
1. Typography precision: `tabular-nums` on every metric cell
(`MetadataTable` values, eval metrics, `turn_cost_ms`); type-scale audit
against ADR-0162 §2; `text-wrap: balance` on headings.
2. Selection-state unification: one tokenized treatment for selected vs
focused rows, applied across Proposals / Evals / Replay lists.
3. Hash display standard: 12-char truncation + copy + mono everywhere;
consolidate `src/app/chat/CopyableHash.tsx` into `DigestBadge` and delete
the duplicate (cleanup-as-you-find: imports, tests, preview entries).
4. `EvidenceChainRail` in `RightInspector`: the seven spine stages (intent →
subject → provenance → admissibility → replay → authority → action), each
rendered lit (evidence present) / dim (not applicable) / hollow (not
recorded). Status derives ONLY from fields the subject carries — never
inferred, never faked. "Not recorded" is an honest, visible state.
5. Empty-state glyphs: small static deterministic monochrome SVGs (inline,
no asset fetches).
6. `Panel` adoption in Proposals + Evals routes (Chat/Replay opportunistic).
7. **Doctrine-as-tests** (route conformance shipped in R0a; extend it to any
surface this PR touches, then add):
- Raw-hex scan: vitest node test walking `src/**` asserting no
hex/rgb literals outside `tokens.css`.
- Schema-drift gate: `scripts/dump-schemas.py` (read-only AST walk over
`workbench/schemas.py`, exact `scripts/dump-enums.py` pattern) →
`schema-snapshot.json` → vitest asserts `src/types/api.ts` covers every
dataclass field. Engine schema drift fails loudly at test time.
### Verification before push
```bash
cd workbench-ui && pnpm build && pnpm test && pnpm test:e2e
cd .. && uv run python scripts/dump-schemas.py > /dev/null # script runs clean
```
PR title: `feat(workbench): design mastery pass — chain rail, typography, doctrine-as-tests`
---
## After this pack
R2 briefs (Trace upgraded, Runs, Audit, Packs, Vault, Settings — parallel)
and R3 briefs (Replay Moment, deterministic DAG viewer, Demo Theater,
wrong=0 ledger) are authored once R0/R1 are on main, against the real
substrate. Specs and exclusions: `docs/workbench/wave-R-mastery-revamp.md`.