docs(workbench): add wave-1 brief pack for Phase 1 polish

Four parallel-safe briefs covering Chat/Proposals/Replay/Evals polish,
each with operator assignment, dispatch line, doctrine refs, owned-files
scope, acceptance criteria, and validation commands.

Operator assignment:
- 1a Chat polish     -> Opus 4.6 (surface contract sensitive)
- 1b Proposals polish-> Sonnet 4.6 (tight-scope lifecycle)
- 1c Replay polish   -> Gemini 3.1 Pro (cross-file presentation)
- 1d Evals polish    -> GPT-OSS-120B / Copilot (mechanical)

All four are dispatchable simultaneously. No order dependency.
This commit is contained in:
Shay 2026-05-28 07:58:44 -07:00
parent 685aaae40e
commit a4a24de836
5 changed files with 558 additions and 0 deletions

View file

@ -0,0 +1,112 @@
# Brief 1a — Chat route polish
> **Operator:** Opus 4.6 (foundations / surface-contract sensitive)
> **Branch:** `workbench/wave-1a-chat-polish`
> **Base:** `feat/workbench-ui-continuation` @ `685aaae`
> **Estimated diff:** ~150300 lines, UI only
> **Why this operator:** Chat is the one Phase 1 brief that touches the
> Runtime Surface Contract (`surface` / `walk_surface` / `articulation_surface`).
> Distinguishing those correctly under the addendum §2 is high-stakes.
---
## Dispatch line
```bash
git fetch origin && \
git worktree add /Users/kaizenpro/Projects/core-w1a-chat \
-b workbench/wave-1a-chat-polish origin/feat/workbench-ui-continuation && \
cd /Users/kaizenpro/Projects/core-w1a-chat/workbench-ui && \
pnpm install
```
Then open the worktree in your editor and start.
---
## Doctrine refs (read before touching code)
- `docs/plans/workbench-ui-continuation.md` §Phase 1a
- `docs/plans/workbench-ui-continuation-addendum.md` §1 (Chat trust class),
§2 (Trace surface contract — applies to Chat's trace drawer), §7 (PR checklist)
- `docs/runtime_contracts.md` — surface distinction and `trace_hash` stability
## Scope (owned files)
- `src/app/chat/**` — everything in this folder
- Test files colocated with the above
## May read (no edits)
- `src/types/api.ts` (append-only at the bottom of the chat section if
new types are needed)
- `src/api/queries.ts` (no edits; this brief does not add hooks)
## Off-limits
- `src/design/**`
- `src/app/Shell.tsx`, `App.tsx`, `LeftNav.tsx`, `TopBar.tsx`, `StatusFooter.tsx`
- Any backend Python file
- Any placeholder file in `src/routes/`
## Tasks
- [ ] **State audit.** Walk every async surface in `src/app/chat/` and confirm
it has loading, empty, and error states. Where missing, add them using
`EmptyState` from `src/design/`.
- [ ] **Surface distinction.** Inspect the trace drawer / evidence panel. The
three surfaces — `surface`, `walk_surface`, `articulation_surface`
must render as three distinct UI elements with labels the operator can
tell apart at a glance. If currently conflated, separate them.
- [ ] **Navigation hardening.** From a turn response:
- clicking `trace_hash` opens the trace drawer at that turn,
- any proposal candidate links to its detail in the Proposals route
(use the existing route path; do not invent a new one).
- [ ] **⌘K commands.** Confirm or add palette entries for `New chat session`
and `Jump to proposal <id>`. Entries belong to chat; do not edit other
features' entries.
- [ ] **Trace-hash stability test.** Add a test asserting that mounting the
trace drawer, navigating nodes, and unmounting does not mutate any
`trace_hash` value held in component state. This is the addendum §2
proof obligation.
- [ ] **Tests for new interaction paths.** Use the existing `Shell.test.tsx`
pattern: render under MemoryRouter + QueryClientProvider, drive
interactions through `@testing-library/react`.
## Acceptance criteria
- Every async surface in `src/app/chat/` has loading + empty + error states.
- Trace drawer labels `surface` / `walk_surface` / `articulation_surface`
distinctly. A reviewer should be able to point at each on screen.
- `trace_hash` stability test exists and passes.
- ⌘K entries for `New chat session` and `Jump to proposal` are present and
keyboard-activatable.
- No edits to off-limits files. `git diff --stat` shows only `src/app/chat/`
and (optionally) `src/types/api.ts` append-only.
- `pnpm test` and `pnpm test:enum-coverage` green.
## Validation
```bash
cd workbench-ui
pnpm install
pnpm test
pnpm test:enum-coverage
git diff --stat $(git merge-base HEAD origin/feat/workbench-ui-continuation)..HEAD
```
The diff-stat output must include only `src/app/chat/**` and optionally
appended lines in `src/types/api.ts`. Anything else is out of scope.
## PR
Title: `feat(workbench/chat): polish states, surface distinction, ⌘K (wave 1a)`
Body uses the template in `docs/handoff/workbench-ui/wave-1/README.md`.
## When done
- [ ] PR open against `feat/workbench-ui-continuation`
- [ ] CI green
- [ ] Mark this brief complete by checking the box in this file in a follow-up
commit on the same PR (single source of truth: this file)

View file

@ -0,0 +1,111 @@
# Brief 1b — Proposals route polish
> **Operator:** Sonnet 4.6 (tight-scope route work)
> **Branch:** `workbench/wave-1b-proposals-polish`
> **Base:** `feat/workbench-ui-continuation` @ `685aaae`
> **Estimated diff:** ~150250 lines, UI only
> **Why this operator:** Proposals has a well-defined lifecycle
> (pending / accepted / rejected / withdrawn) and clear color tokens
> already in `src/design/`. Tight contract, no surface-contract surprises.
---
## Dispatch line
```bash
git fetch origin && \
git worktree add /Users/kaizenpro/Projects/core-w1b-proposals \
-b workbench/wave-1b-proposals-polish origin/feat/workbench-ui-continuation && \
cd /Users/kaizenpro/Projects/core-w1b-proposals/workbench-ui && \
pnpm install
```
---
## Doctrine refs
- `docs/plans/workbench-ui-continuation.md` §Phase 1b
- `docs/plans/workbench-ui-continuation-addendum.md` §1 (Proposals is
proposal-only — no direct accept/reject endpoints introduced; UI only
calls existing API), §7 (PR checklist)
## Scope (owned files)
- `src/app/proposals/**`
- Test files colocated with the above
## May read (no edits)
- `src/api/queries.ts` — observe existing `useProposals` / `useProposal` shapes
- `src/design/tokens.css` — read review-lifecycle tokens; do not edit
- `src/types/api.ts` — append-only at the bottom of proposals section if needed
## Off-limits
- `src/design/**` (including tokens)
- Shell / TopBar / LeftNav / StatusFooter / App.tsx
- Any backend Python file
- Any placeholder file
- Any new proposal-mutation endpoint or hook (proposal-only discipline)
## Tasks
- [ ] **State audit.** Confirm queue list and proposal detail handle loading,
empty, and error consistently. Wire `EmptyState` from `src/design/`
where missing.
- [ ] **Lifecycle color consistency.** The four states (`pending`,
`accepted`, `rejected`, `withdrawn`) must render with the same color
tokens in both list and detail. Verify each token is referenced via
CSS custom property — no hex literals.
- [ ] **Cross-route links.** From proposal detail:
- link to the source artifact (use existing Runs/artifact route path
if present; otherwise the artifact route Phase 2 will introduce —
for now link to the Replay-comparison entry-point if that exists),
- link to the replay-comparison view for the proposal if applicable.
Document any link that cannot land because the target route is a
placeholder; leave a TODO with the route name.
- [ ] **Suggested-CLI block.** Make the suggested-CLI snippet block
`user-select: text` (or a copy button) so the operator can copy it.
- [ ] **⌘K command entries.** Add `Open proposal <id>` palette entry
driven by the existing `useProposals` query. Only proposals entries —
do not touch other features'.
- [ ] **Route tests.** Cover at least:
- queue renders with loading → success transition,
- empty state when zero proposals returned,
- error state when query errors,
- lifecycle color class applied per state.
## Acceptance criteria
- Loading / empty / error covered everywhere in `src/app/proposals/`.
- All four lifecycle states render with the documented tokens, no hex
literals anywhere in this brief's diff (`grep -E '#[0-9a-fA-F]{3,6}'`
returns nothing in the diff).
- Suggested-CLI block is selectable or has a copy button.
- ⌘K entries for proposals are present and keyboard-activatable.
- No backend changes. No off-limits files touched.
- `pnpm test` and `pnpm test:enum-coverage` green.
## Validation
```bash
cd workbench-ui
pnpm install
pnpm test
pnpm test:enum-coverage
git diff --stat $(git merge-base HEAD origin/feat/workbench-ui-continuation)..HEAD
# Verify no hex literals introduced
git diff $(git merge-base HEAD origin/feat/workbench-ui-continuation)..HEAD -- 'src/app/proposals/**' | grep -E '^\+.*#[0-9a-fA-F]{3,6}' && echo "FAIL: hex literal introduced" || echo "ok: no hex literals"
```
## PR
Title: `feat(workbench/proposals): polish states, lifecycle colors, links (wave 1b)`
Body uses the template in `docs/handoff/workbench-ui/wave-1/README.md`.
## When done
- [ ] PR open against `feat/workbench-ui-continuation`
- [ ] CI green
- [ ] This brief checked complete on the PR

View file

@ -0,0 +1,111 @@
# Brief 1c — Replay route polish
> **Operator:** Gemini 3.1 Pro (survey + cross-file presentation work)
> **Branch:** `workbench/wave-1c-replay-polish`
> **Base:** `feat/workbench-ui-continuation` @ `685aaae`
> **Estimated diff:** ~150250 lines, UI only
> **Why this operator:** Replay polish requires reading divergence
> rendering across multiple files and improving clarity of metadata
> presentation. Gemini's strength is cross-file survey + presentation
> reasoning over a moderate diff surface.
---
## Dispatch line
```bash
git fetch origin && \
git worktree add /Users/kaizenpro/Projects/core-w1c-replay \
-b workbench/wave-1c-replay-polish origin/feat/workbench-ui-continuation && \
cd /Users/kaizenpro/Projects/core-w1c-replay/workbench-ui && \
pnpm install
```
---
## Doctrine refs
- `docs/plans/workbench-ui-continuation.md` §Phase 1c
- `docs/plans/workbench-ui-continuation-addendum.md` §1 (Replay = read-only;
no "fix" buttons, no artifact writes), §7 (PR checklist)
- The Replay route should never present an affordance to mutate an
artifact. Read + render + link out only.
## Scope (owned files)
- `src/app/replay/**`
- Test files colocated with the above
## May read (no edits)
- `src/api/queries.ts` — observe `useReplayComparison`, `useArtifacts`, `useArtifact`
- `src/design/tokens.css` — divergence-severity tokens
- `src/types/api.ts` — append-only at the bottom of replay section if needed
## Off-limits
- `src/design/**`
- Shell / TopBar / LeftNav / StatusFooter / App.tsx
- Any backend Python file
- Any placeholder file
- **No mutating affordances of any kind** — no "rerun", "save", "fix",
"accept divergence" buttons. Read-only doctrine.
## Tasks
- [ ] **Survey current state.** Read every file in `src/app/replay/` and
produce a short comment block at the top of the route (or in this
brief's PR description) summarizing what each component does. This
forces a complete read before edits.
- [ ] **State audit.** Artifact-selector and comparison view: loading,
empty (no artifacts available; selection invalid), error states.
- [ ] **Divergence-severity clarity.** Currently the divergence severity
may be coded via color alone. Add a textual severity label next to
the color band (e.g. `low`, `material`, `breaking`) so the meaning
is unambiguous without the color legend.
- [ ] **Metadata presentation.** Artifact metadata (timestamp, trace_hash,
run id, lane) should be presented in a key-value table or definition
list with consistent alignment. No "wall of text" rendering.
- [ ] **Back-link to proposal.** When the comparison view is reached from
a proposal, show a "Back to proposal #N" link. When reached directly,
do not show the link. Drive this from URL state, not props.
- [ ] **Route tests.** Cover:
- artifact selection populating comparison view,
- empty state when no artifacts,
- error state when comparison query fails,
- severity label rendering for each severity bucket.
## Acceptance criteria
- Every async surface in `src/app/replay/` has loading + empty + error.
- Divergence severity is conveyed by **both** color **and** text label.
- Artifact metadata renders as a structured key-value layout.
- Back-link to proposal appears only when route was entered from a proposal.
- No mutating affordances anywhere in the diff.
- No backend changes. No off-limits files touched.
- `pnpm test` and `pnpm test:enum-coverage` green.
## Validation
```bash
cd workbench-ui
pnpm install
pnpm test
pnpm test:enum-coverage
git diff --stat $(git merge-base HEAD origin/feat/workbench-ui-continuation)..HEAD
# Confirm no write paths introduced (no new mutation hooks)
git diff $(git merge-base HEAD origin/feat/workbench-ui-continuation)..HEAD -- 'src/app/replay/**' | grep -E '^\+.*(useMutation|fetch\(|axios\.(post|put|patch|delete))' && echo "FAIL: mutation introduced" || echo "ok: read-only preserved"
```
## PR
Title: `feat(workbench/replay): polish states, severity labels, metadata layout (wave 1c)`
Body uses the template in `docs/handoff/workbench-ui/wave-1/README.md`.
## When done
- [ ] PR open against `feat/workbench-ui-continuation`
- [ ] CI green
- [ ] This brief checked complete on the PR

View file

@ -0,0 +1,114 @@
# Brief 1d — Evals route polish
> **Operator:** GPT-OSS-120B or GitHub Copilot cloud agent (mechanical)
> **Branch:** `workbench/wave-1d-evals-polish`
> **Base:** `feat/workbench-ui-continuation` @ `685aaae`
> **Estimated diff:** ~120200 lines, UI only
> **Why this operator:** Evals polish is mostly mechanical: state audits,
> numeric column alignment, route tests. Clear acceptance criteria, narrow
> file scope, no surface-contract subtlety. Ideal for a local or
> cloud-mechanical operator.
---
## Dispatch line
```bash
git fetch origin && \
git worktree add /Users/kaizenpro/Projects/core-w1d-evals \
-b workbench/wave-1d-evals-polish origin/feat/workbench-ui-continuation && \
cd /Users/kaizenpro/Projects/core-w1d-evals/workbench-ui && \
pnpm install
```
---
## Doctrine refs
- `docs/plans/workbench-ui-continuation.md` §Phase 1d
- `docs/plans/workbench-ui-continuation-addendum.md` §1 (Evals = read-only;
no lane mutation, no "suppress failing case" affordance), §7 (PR checklist)
- Evals UI must not hide or suppress failing cases. Filters that change
view are fine; filters that remove failing cases from the underlying
count are not.
## Scope (owned files)
- `src/app/evals/**`
- Test files colocated with the above
## May read (no edits)
- `src/api/queries.ts``useEvalLanes`, `useEvalLane`, `useEvalExecution`
- `src/design/tokens.css` — read; do not edit
- `src/types/api.ts` — append-only at the bottom of evals section if needed
## Off-limits
- `src/design/**`
- Shell / TopBar / LeftNav / StatusFooter / App.tsx
- Any backend Python file
- Any placeholder file
- Any affordance that mutates a lane definition or hides a failing case
## Tasks
- [ ] **State audit.** Lane list and eval-run view: loading, empty
(no lanes; no runs for selected lane), error states.
- [ ] **Numeric column alignment.** Wherever numeric metrics render in a
list or table, they must be right-aligned, monospace-numeric, and
use tabular-nums for consistent digit width. Use existing tokens.
- [ ] **Metric readability.** Where a metric is shown alongside a target,
render `actual / target` with the actual value emphasized. If a
metric is failing (actual < target where higher-is-better, or
actual > target where lower-is-better), apply the existing
failure color token. No new tokens.
- [ ] **Lane selection persistence.** Selected lane should be reflected in
the URL (query string is fine). Reloading the page should restore the
selection.
- [ ] **⌘K command entry.** Add `Open eval lane <name>` palette entries
driven by the existing `useEvalLanes` query. Only evals entries.
- [ ] **Route tests.** Cover:
- lane list loading → success,
- empty state when no lanes,
- run view rendering metrics with correct alignment,
- failure color applied when metric does not meet target.
## Acceptance criteria
- Every async surface in `src/app/evals/` has loading + empty + error.
- All numeric metric columns are right-aligned with `tabular-nums`.
- Failing metrics use the existing failure token, no hex literals.
- Lane selection survives reload via URL state.
- ⌘K `Open eval lane` entries present and keyboard-activatable.
- No backend changes. No off-limits files touched. No affordance that
suppresses or hides failing cases.
- `pnpm test` and `pnpm test:enum-coverage` green.
## Validation
```bash
cd workbench-ui
pnpm install
pnpm test
pnpm test:enum-coverage
git diff --stat $(git merge-base HEAD origin/feat/workbench-ui-continuation)..HEAD
# No hex literals in the diff
git diff $(git merge-base HEAD origin/feat/workbench-ui-continuation)..HEAD -- 'src/app/evals/**' | grep -E '^\+.*#[0-9a-fA-F]{3,6}' && echo "FAIL: hex literal introduced" || echo "ok: no hex literals"
# No mutation hooks introduced
git diff $(git merge-base HEAD origin/feat/workbench-ui-continuation)..HEAD -- 'src/app/evals/**' | grep -E '^\+.*useMutation' && echo "FAIL: mutation introduced" || echo "ok: read-only preserved"
```
## PR
Title: `feat(workbench/evals): polish states, numeric alignment, lane URL state (wave 1d)`
Body uses the template in `docs/handoff/workbench-ui/wave-1/README.md`.
## When done
- [ ] PR open against `feat/workbench-ui-continuation`
- [ ] CI green
- [ ] This brief checked complete on the PR

View file

@ -0,0 +1,110 @@
# Workbench UI — Wave 1 Brief Pack
> **Parent plan:** `docs/plans/workbench-ui-continuation.md`
> **Binding addendum:** `docs/plans/workbench-ui-continuation-addendum.md`
> **Base branch:** `feat/workbench-ui-continuation` @ `685aaae`
> **Scope:** Phase 1 only — polish the four implemented routes
## What this wave does
Polish Chat, Proposals, Replay, and Evals so they are cohesive,
cross-linked, and handle loading/empty/error states consistently —
before any new route lands. All four routes are already implemented;
this is hardening, not feature work.
## Parallel safety
| Operator brief | Owns | Read-only touches |
|-----------------------|-----------------------------------|----------------------------------|
| 1a — Chat polish | `src/app/chat/**` | `src/types/api.ts` (append only) |
| 1b — Proposals polish | `src/app/proposals/**` | `src/types/api.ts` (append only) |
| 1c — Replay polish | `src/app/replay/**` | `src/types/api.ts` (append only) |
| 1d — Evals polish | `src/app/evals/**` | `src/types/api.ts` (append only) |
**Off-limits to every brief:**
- `src/design/**` (protected substrate — plan constraint)
- `src/app/Shell.tsx`, `LeftNav.tsx`, `TopBar.tsx`, `StatusFooter.tsx`
- `src/app/App.tsx` route table (no swaps in Wave 1)
- Any placeholder file in `src/routes/` (those belong to Phase 2+)
- `workbench-ui/src/design/tokens.css` and friends
- Backend Python (this is a UI-only wave)
**Coordinated surface:**
- CommandPalette entries: each brief adds **only** entries for its
own feature; no brief edits another's entries. If a conflict appears
at merge, the second-merging brief rebases additively.
- `src/types/api.ts`: append-only additions to the bottom of the
matching section. No edits to existing types.
## Dispatch DAG
```
┌── 1a Chat polish (Opus 4.6) ───────┐
main ──>│ │── merge any order
│── 1b Proposals polish (Sonnet 4.6)─│ (all four parallel-safe)
│ │
│── 1c Replay polish (Gemini 3.1) ───│
│ │
└── 1d Evals polish (GPT-OSS/Copilot)┘
```
All four briefs are dispatchable simultaneously. No order dependency.
## Doctrine that applies to every brief
From `docs/plans/workbench-ui-continuation-addendum.md`:
- **§1 trust classification.** Chat = read + turn-submit; Proposals = proposal-only;
Replay = read-only; Evals = read-only. No brief introduces a write path.
- **§2 surface contract (Chat brief only).** `surface`, `walk_surface`, and
`articulation_surface` rendered distinctly; `trace_hash` stability test required.
- **§7 per-PR checklist.** Every PR answers the four CLAUDE.md §PR Checklist
questions in its description.
- **§8 proof obligations.** New TS unions must have a test that fails under
their named violation, or the type is decoration.
## Validation each brief must run
```bash
cd workbench-ui
pnpm install # if first time on this worktree
pnpm test # all green
pnpm test:enum-coverage
```
Backend-touching changes are **out of scope** for Wave 1 and must be
rejected at review. Any "while I'm here" backend edit means the PR
fails the trust-classification check.
## PR template (every brief uses this)
```markdown
## Wave 1 brief: <1a|1b|1c|1d><feature> polish
### Trust classification
<read-only | read + turn-submit | proposal-only>
### CLAUDE.md §PR Checklist
- Capability/property/boundary added: <one line>
- Invariant preserved: <one line, e.g. trace_hash stability, no design-substrate edit>
- CLI/test lane that proves it: pnpm test + pnpm test:enum-coverage (UI-only)
- Trust boundary enforced: <one line; "no write paths introduced">
### Diff scope
- Owned: <files>
- Read-only touched: <files>
- Off-limits respected: yes
### Tests
- Added: <tests>
- Passing: pnpm test green; pnpm test:enum-coverage green
```
## Done criteria for the wave
- [ ] All four PRs merged to `feat/workbench-ui-continuation`
- [ ] No off-limits files modified across the merged set
- [ ] No backend changes across the merged set
- [ ] `pnpm test` and `pnpm test:enum-coverage` green on the merged tip
- [ ] CommandPalette has entries for the new interactions added by each brief
- [ ] All four briefs in this folder marked done in their respective files