- Notifications
You must be signed in to change notification settings - Fork 0
docs(design-system): add the 7 August handover#1671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Uh oh!
There was an error while loading. Please reload this page.
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,275 @@ | ||
| # Design system — handover, 7 August 2026 | ||
| **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. | ||
| - **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..<branch>` — 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 status && git diff # review changes; stage only the reviewed paths, e.g. git add <path> | ||
| 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 `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. | ||
| > | ||
| > 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`). | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.