From 6a1218a5af1bde875167284f9e10bb1d84fbbfa3 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Fri, 7 Aug 2026 14:30:06 +0800 Subject: [PATCH 1/2] docs(design-system): add the 7 August handover MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A fresh session picking this work up cold currently has to re-derive state that was already measured, and several items in the inherited backlog are provably wrong — the previous session spent most of itself establishing that. Adds docs/design-system/HANDOVER-2026-08-07.md and links it from the document set README as the cold-start entry point. Carries: - measured state (53 registered / 29 adopted / 24 unadopted; 13 open defect rows; 7 blocking gates, 6 partial, 2 planned; 6 ungated prohibitions; 0 committed baselines), with the command to regenerate every figure - what landed 7 Aug (#1655, #1658, #1663, #1669) including the #207-vs-#227 clinical decision and why it went the way it did - six measured corrections to the older backlog, each of which would otherwise send the next session down a wrong path — notably that `--shadow-focus` is NOT dead (a *.tsx-only grep says it is; the live consumer is in globals.css), and that check:type-scale/check:icon-scale already ship as hard-zero gates - the ordered plan, split into finishing the kit and updating the live design - the baseline hold as the decision that unblocks the most, and why Linux provenance cannot be produced on Windows - scope discipline: do not build the 43 outlined P1/P2 components - the repo gotchas that cost the previous session (stale local main ref, the twelve superseded codex/v2-* branches that read as "ahead", lying background exit codes, verify:pr-local failing closed on lock parity, contended Chromium) - verification recipes and a ready-to-use prompt for the next session Ledger registration is deliberately left to `/issues capture` rather than hand-written rows: ids are allocated read-modify-write and hand-edits have collided before (`#156`). docs:check-links, docs:check-index, docs:check-inventory all exit 0. Co-Authored-By: Claude Opus 5 --- docs/design-system/HANDOVER-2026-08-07.md | 272 ++++++++++++++++++++++ docs/design-system/README.md | 5 + 2 files changed, 277 insertions(+) create mode 100644 docs/design-system/HANDOVER-2026-08-07.md diff --git a/docs/design-system/HANDOVER-2026-08-07.md b/docs/design-system/HANDOVER-2026-08-07.md new file mode 100644 index 0000000000..bf74a17dec --- /dev/null +++ b/docs/design-system/HANDOVER-2026-08-07.md @@ -0,0 +1,272 @@ +# Design system — handover, 7 August 2026 + +**Point a fresh session at this file.** It carries the measured state, the work that +landed, the places the previous backlog was **wrong**, and the ordered plan. It exists so +the next session does not re-derive any of it — several of the corrections below cost a +full session to establish. + +- **Companion documents:** [README.md](README.md) · [SPEC.md](SPEC.md) · + [TOKENS.md](TOKENS.md) · [COMPONENTS.md](COMPONENTS.md) · [GATES.md](GATES.md) · + [DECISIONS.md](DECISIONS.md) · [ADOPTION.md](ADOPTION.md) +- **Machine truth:** [`adoption-manifest.json`](adoption-manifest.json) (generated — never + hand-edit) · [`adoption-contract.json`](adoption-contract.json) +- **Adjacent contracts:** [`docs/search-chrome-behaviour.md`](../search-chrome-behaviour.md) · + [`docs/wiring-conventions.md`](../wiring-conventions.md) · + [`docs/outstanding-issues.md`](../outstanding-issues.md) + +--- + +## 1 · Measured state + +All figures measured on `origin/main` at handover, not recalled. + +| Metric | Value | +| ------------------------------------------ | ------------------------------------------------ | +| Registered visual components | 53 | +| Product-adopted | **29** | +| Unadopted (zero product imports) | **24** | +| Open rows in COMPONENTS §0.4 defect ledger | **13** open, 11 done | +| Gates | **7 implemented-blocking**, 6 partial, 2 planned | +| Prohibitions with no gate at all | **6** | +| Committed visual baselines | **0** (deliberate — see §5) | +| Specified but not built | 23 P1 + 20 P2, outline only | + +The 24 unadopted: `AnswerFooter` `Button` `Checkbox` `Citation` `CitationList` +`ConfirmDialog` `Disclosure` `DisclosureGroup` `DoseLine` `DownloadLink` `ErrorSummary` +`ExternalTextLink` `FieldError` `FieldHint` `LinkAction` `Pagination` `Progress` +`RadioGroup` `SearchField` `StageList` `Tabs` `TextLink` `ToastRegion` `Tooltip`. + +Regenerate any of this with: + +```bash +npm run design-system:adoption:update && npm run check:design-system-contract +``` + +--- + +## 2 · What landed on 7 August 2026 + +| PR | Commit | What | +| ------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | +| [#1655](https://github.com/BigSimmo/Database/pull/1655) | `cc349d130` | Gate 3's false `--focus` evidence, GATES §1's false "type-step unenforced" note, three stale §0.4 rows, ToggleSwitch knob onto `transform` | +| [#1658](https://github.com/BigSimmo/Database/pull/1658) | `d9221389c` | `AnswerCard` adopted on the live answer surface; `#207`-vs-`#227` resolved. Adoption 27 → 29 | +| [#1663](https://github.com/BigSimmo/Database/pull/1663) | `82b6f5a4c` | Five named tracking tokens + `arbitraryTracking` contract ratchet | +| [#1669](https://github.com/BigSimmo/Database/pull/1669) | open at handover | 68 tracking sites across 40 files migrated; ratchet baseline 68 → **0** | + +### The clinical decision recorded in #1658 + +`AnswerCard` and the live surface disagreed about degraded answers, and **both sides were +documented and measured**, neither referencing the other: + +- `#207` required a retrieval banner on **every** degraded state — "the adoption failure + this guards is a silent one … the caution the product shows today is simply gone." +- `#227` suppressed it for `ungrounded`/`source_only`, having measured the duplicate: + three renderings of one warning, eleven lines of caution around one line of answer, + 147px of scroll against a phone budget of 8. + +**Resolved in favour of `#227`, on the owner's decision.** `#207` protects that the caution +_survives_, not that a _banner_ carries it — `VerificationNotice` states it in words and the +card carries `data-state`. The banner now renders only for `stale_evidence` and +`partial_retrieval`, the two kinds that say something the notice cannot (_which_ sources are +overdue, _how much_ was missed). The `#207` test now pins the duplicate **out**, so a banner +reappearing for `ungrounded` fails as the `#227` regression it would be. + +Do not re-litigate this without the owner. + +--- + +## 3 · Corrections — the previous backlog is wrong in six measured places + +Verify before acting on any inherited design-system list. These were each established by +measurement and cost real time. + +1. **Letterspacing is not 371 sites / 31 values.** That counts `*-mockups.tsx`, which is + design scratch and gate-exempt. Production was **110 / 18**; the contract's AST pass saw + **68 across 40 files**. All three numbers are true of different things; only the last is + actionable. Now **0** (#1669). +2. **`--shadow-focus` is not dead.** Live consumer: `.chat-composer-shell-delta:focus-within` + in `globals.css`. It _is_ the forbidden companion focus ring Gate 3 prohibits, so removing + it is a **visible focus-state change on the search composer**, not a dead-code sweep. + A `--include=*.tsx` grep will tell you it has zero consumers. It does not. +3. **`check:type-scale` and `check:icon-scale` exist** and are hard-zero gates inside + `verify:cheap` since 30 July. Only the ESLint _rules_ are absent. Arbitrary sizes + (`text-[12px]`) are blocked; **step selection among named steps is not** — that is the + real gap (1 318 sites across 8 non-standard steps). Do not write a lint duplicating the + half that ships. +4. **Local duplicates already converge.** All three "duplicate" local `Chip`s and + therapy-compass `EmptyState`/`LoadingState` are already thin wrappers over the DS + components. +5. **Unbounded "log once" Sets are closed.** `verification-notice.tsx` is bounded at 32 with + FIFO eviction; four other modules use `createBoundedDiagnosticRecorder`. +6. **Roughly five of fourteen component-defect rows are stale.** Already resolved: + ToggleSwitch motion, TextField/SearchField/Select hint+`describedBy` (fixed via + `FormField`), Checkbox/RadioGroup ids (`useId`), Tabs `aria-controls`, Links `tone` leak. + +--- + +## 4 · The plan + +### Track A — finish the kit + +**A1 · `cn()` + tailwind-merge (`#218`).** The keystone. Blocks Chip/metadataPill +convergence and any reliable size override; `cn()` is plain concat today and two source +sites already carry workaround comments. **Its own PR** — it adds a dependency +(`operationalRisk: true`) and changes class resolution across ~200 importing files, so it +must not be bundled or landed alongside a visual change whose Chromium job you still need to +read. + +**A2 · `--shadow-focus`.** Replace the composer's companion ring with the sanctioned +`outline` / `--focus` treatment used everywhere else, then delete the token (both theme +declarations). Visible focus-state change on the search composer — read +[`docs/search-chrome-behaviour.md`](../search-chrome-behaviour.md) first and get a Chromium +look. + +**A3 · Remaining token debt.** `--shadow-tight`'s 155 consumers onto the `--eN` ladder; a +step-_selection_ lint for the eight non-standard type steps; extend the contract ratchet to +raw padding / radius / line-height literals (it covers colour, shadow, tap and tracking +today). + +**A4 · The 13 open §0.4 rows.** Button `forwardRef` · Progress/StageList (hardcoded `1.4s` +shimmer, `step 0 of N` reachable, whole-list live region) · StatusMark app-type coupling · +PageHeader title starve · Disclosure print · AccessibleTable dense headers and Button-based +expander · Tabs invalid-value tab order · Pagination focus/announce · Links `download` +overridable by spread and `gap` animation · Citation static-span labelling · +Checkbox/RadioGroup raw dimensions and group hint/error. + +**A5 · Close the six ungated prohibitions.** Highest value in Track A, because a prohibition +with no gate row is a suggestion — that is the failure mode GATES.md exists to prevent. +Colour-boundary lint (no numeral painted with a status colour) · PDF/diagram invert refusal · +layout-property animation lint · border+ring co-occurrence · `--shadow-tight` alias lint · +`dark:` override lint (3 live instances). + +**A6 · Gates 2/4/7/8 from partial to blocking.** Gate 4 needs a repo-wide status-indicator +enumeration — today a new colour-only indicator slips through. Gate 2 needs the fixed-height +`h-10` case and `test:e2e:style-contract` wired into `verify:cheap`. + +### Track B — update the live design + +**B1 · Adopt demand-driven, never as a race to 53/53.** Pick a surface and let it pull, the +way #1658 did. Forms are the largest single tranche: `FieldError` `FieldHint` `ErrorSummary` +`SearchField` `Checkbox` `RadioGroup` all land together on one form conversion. + +**B2 · `AnswerFooter` and `DoseLine`** need a provenance/dose payload the answer surface does +not yet produce. That is backend-shaped work, not a component swap. Do not stub one to make +the adoption count look better. + +**B3 · The 19 genuine bare-dash sites** onto `MissingValue` (therapy-compass getters, +specifier `sourceFamily`, favourites counts when untrusted). **Leave the ~5 calculator +`derived.started ? score : "—"` sites permanently** — "not started" is not a missing clinical +value, and `MissingValueReason` has no member for it; converting them would render "Not +recorded" for a score the clinician simply has not entered. + +**B4 · The visual state matrix** — hover / active / disabled / busy / invalid / 320px / dark / +forced-colours / print, per component. Currently proven for none. Blocked on §5. + +--- + +## 5 · The decision that unblocks the most + +**The visual baseline hold, issue `#118`.** Zero baselines committed, harness +`continue-on-error`. Until the design is declared final: + +- there is **no visual regression protection at all** — every change to the live look ships + unverified; +- Gate 2's per-surface geometry, the 320px proofs and the whole state matrix (B4) stay + unprovable; +- the adoption contract cannot demand real proof. + +Nothing in Track B is safe at scale until baselines exist. The first step is a CI run +producing `linux` / `ubuntu-24.04` baselines with approved provenance — +**they cannot be generated on Windows**: `snapshotPathTemplate` carries `{platform}`, so +win32 PNGs are invisible to the ubuntu CI job and only `linux/` gates anything. + +`--spacing-tap` is **48px** and pinned from both sides. Production tap targets are `min-h-12`. +Do **not** "fix" them to `min-h-11` to satisfy generic WCAG advice — that reintroduces a known +`ui-smoke` sub-pixel flake. + +--- + +## 6 · Scope discipline — what "perfected" should mean + +**Do not build the 43 outlined P1/P2 components.** That is the failure the audit named: +documentation describing a system roughly 2.8× the size of the one a designer can use. +`FilterBar` and `DataTable` are already retired _names_, not future contracts, for exactly +this reason. + +Freeze the outline as a catalogue. Build on demand. Treat "perfected" as: + +> 13 defect rows closed · 6 prohibitions gated · token debt finished · baselines committed + +On that definition it is roughly four or five focused PRs plus the baseline decision. On the +"build everything outlined" definition it is months, and it makes the kit worse. + +--- + +## 7 · Repo gotchas that cost the previous session + +- **The local `main` ref is stale.** Measured 111 commits behind `origin/main`. A first-turn + glob against the worktree reported "the design system is unmerged branch work"; it had + fully landed. Run `git rev-parse main origin/main` **first** and use `origin/main` for every + containment question. +- **The twelve `codex/v2-*` branches are superseded snapshots**, 14 000–28 000 lines _behind_ + main. `git rev-list --count` reads them as "ahead" because the content landed via + squash-merge. Use `git diff --shortstat origin/main..` — a large deletion count + means it would revert main. Merging one throws ~45 conflicts. Cherry-pick if anything is + wanted; never merge. +- **Background-task exit codes lie.** Append `; echo "X_EXIT=$?"`, log to a file, and grep the + "N passed" tally. Exit 0 alone is never proof. +- **`verify:pr-local` fails closed** at `check:installed-lock-parity` on playwright drift + (issue `#149`) before running anything. `npm run test` directly is the way to close the real + gap; do not `npm ci` on a box with dozens of node processes — concurrent installs corrupt + `node_modules` here. +- **Chromium runs are unreliable under contention** on the dev box; they produce false reds, + not signal. Let CI's job be the authority for UI verification. +- **Three test files fail on Windows on main itself**, unrelated to design-system work: + `installed-lock-parity` (`#149`), `pr-handoff-stop` (simulated `jq` absence, from #1649), + `mode-nav-addon-slot` (absolute Windows vs POSIX-relative paths, from #1647). + +--- + +## 8 · Verification recipes + +```bash +# smallest correct gate for design-system work +npm run check:design-system-contract # tokens + adoption + design-sync parity +npm run check:type-scale # hard zero: no arbitrary text-[12px] +npx vitest run tests/ckb-v2-token-contract.test.ts tests/design-system-adoption.test.ts + +# component behaviour +npx vitest run tests/ui-primitives.dom.test.tsx tests/ui-v2-components.dom.test.tsx tests/ui-v2-answer-safety.dom.test.tsx + +# before any push — format is in CI but NOT in verify:cheap +npm run format && git add -A && git commit +npm run typecheck && npm run lint && npm run test +``` + +Regenerate the adoption manifest after **any** change to component imports: +`npm run design-system:adoption:update`. It is generated; never hand-edit it. + +The contract ratchet is per-path. To re-baseline after clearing debt, set only the metric you +cleared and assert every other metric is unchanged first — the previous session scripted that +check so a rewrite could not silently move an unrelated number. + +--- + +## 9 · Prompt for the next session + +> Read `docs/design-system/HANDOVER-2026-08-07.md` first — it carries the measured state, the +> corrections to the old backlog, and the ordered plan. Confirm `git rev-parse main origin/main` +> agree before reasoning about what has landed. +> +> Start with **Track A1: give `cn()` tailwind-merge** (`#218`). Own PR, no bundling: it adds a +> dependency and changes class resolution across ~200 importing files. Verify with +> `npm run check:design-system-contract`, `npm run typecheck`, `npm run lint`, `npm run test`, +> and the component DOM suites in §8. Expect three pre-existing Windows test failures listed in +> §7 — confirm they are unchanged rather than treating them as yours. +> +> Do not commit visual baselines, do not merge any `codex/v2-*` branch, do not build the +> outlined P1/P2 components, and do not write a lint duplicating `check:type-scale`. + +Register the Track A and Track B items in the durable ledger with `/issues capture` rather +than hand-writing rows into [`docs/outstanding-issues.md`](../outstanding-issues.md) — ids are +allocated read-modify-write and hand-edits have collided before (`#156`). diff --git a/docs/design-system/README.md b/docs/design-system/README.md index 7908a3c725..05fa6b3bae 100644 --- a/docs/design-system/README.md +++ b/docs/design-system/README.md @@ -5,6 +5,11 @@ only in the token files.** Source-of-truth ranking: `AGENTS.md` → `ckb-v2-toke committed tests → `.design-sync/conventions.md` → this set. Where this set contradicts a higher source, the higher source wins and the contradiction is a defect here. +**Picking the work up cold?** Start at +[HANDOVER-2026-08-07.md](HANDOVER-2026-08-07.md) — measured state, the ordered plan, and the +six places the older design-system backlog is provably wrong. It exists so a fresh session +does not re-derive what a previous one already measured. + Reading order: 1. [SPEC.md](SPEC.md) — principles, foundations, patterns, degraded states, accessibility, From e7937860ff81ad487a2219e5930825d5f2c889e3 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 09:53:20 +0000 Subject: [PATCH 2/2] fix: apply CodeRabbit auto-fixes Fixed 1 file(s) based on 2 unresolved review comments. Co-authored-by: CodeRabbit --- docs/design-system/HANDOVER-2026-08-07.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/design-system/HANDOVER-2026-08-07.md b/docs/design-system/HANDOVER-2026-08-07.md index bf74a17dec..d8f1c35cc1 100644 --- a/docs/design-system/HANDOVER-2026-08-07.md +++ b/docs/design-system/HANDOVER-2026-08-07.md @@ -1,6 +1,7 @@ # Design system — handover, 7 August 2026 -**Point a fresh session at this file.** It carries the measured state, the work that +**Read `AGENTS.md` first — it is the highest-priority source of truth for rules and gates. +Then point a fresh session at this file.** It carries the measured state, the work that landed, the places the previous backlog was **wrong**, and the ordered plan. It exists so the next session does not re-derive any of it — several of the corrections below cost a full session to establish. @@ -239,7 +240,8 @@ npx vitest run tests/ckb-v2-token-contract.test.ts tests/design-system-adoption. npx vitest run tests/ui-primitives.dom.test.tsx tests/ui-v2-components.dom.test.tsx tests/ui-v2-answer-safety.dom.test.tsx # before any push — format is in CI but NOT in verify:cheap -npm run format && git add -A && git commit +npm run format +git status && git diff # review changes; stage only the reviewed paths, e.g. git add npm run typecheck && npm run lint && npm run test ``` @@ -254,7 +256,8 @@ check so a rewrite could not silently move an unrelated number. ## 9 · Prompt for the next session -> Read `docs/design-system/HANDOVER-2026-08-07.md` first — it carries the measured state, the +> Read `AGENTS.md` first — it is the highest-priority source of truth for rules and gates. +> Then read `docs/design-system/HANDOVER-2026-08-07.md` — it carries the measured state, the > corrections to the old backlog, and the ordered plan. Confirm `git rev-parse main origin/main` > agree before reasoning about what has landed. >