From eae1cbca6068444b04c3ebbc2bbfa5f09255a037 Mon Sep 17 00:00:00 2001 From: Robert Blust Date: Mon, 31 Aug 2026 23:31:05 +0200 Subject: [PATCH 1/2] Final review fix wave: correct false brand-mark claim, close the fences loophole MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CLAUDE.md: header contract fence is byte-identical on sixteen pages (6+6+4 across the three repositories), not fifteen — the count Task 6 fixed in one of four places while leaving this one wrong. - verify/check.mjs: add the missing third meta-assertion. seo and tokenVersion each had one; fences did not, so deleting `fences: [...]` from a page's spec (or adding a page to PAGES without it) turned the fence contract off for that page with no output change. Proved it fails by deleting `/model/`'s fences and watching verify name it before restoring. PR #40's body and the untracked plan document are corrected separately: the `.brand svg{color:var(--c-mid)}` edit never fixed a rendering defect on blust.ch — this site's mark fills `.plate`/`.rb` directly and never reads `currentColor`, so the rule is inert here and only load-bearing on companygraph.io/guestgraph.io's stroke-based marks. --- CLAUDE.md | 2 +- verify/check.mjs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index f7b1159..2dd4e9d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -364,7 +364,7 @@ fence is not a way around it. The row across the top — wordmark, links, language control — is one design on three sites, and like the tokens it is a copy, because a deck opens from `file://` and there is no stylesheet to share. It is fenced in every page as `header contract · vN` and is -**byte-identical on all fifteen pages** in the three repositories. Check it the way you +**byte-identical on all sixteen pages** in the three repositories. Check it the way you check the tokens: change it here, run this repo's suite, and bump `vN` in all three. What the contract says: diff --git a/verify/check.mjs b/verify/check.mjs index fd7f359..54cac2c 100644 --- a/verify/check.mjs +++ b/verify/check.mjs @@ -677,6 +677,15 @@ let failures = 0; const off = PAGES.filter(p => !p.tokenVersion).map(p => p.path); if (off.length) { console.log("✗ PAGES tokenVersion is not enabled on: " + off.join(", ")); failures++; } } +// And every page must opt into `fences`, for the same reason. Task 2 added the check that +// fails a page whose fences no longer include `prose reset` — but not this line, so deleting +// `fences: [...]` from a page's spec (or adding a page to PAGES without it) turns that check +// off for that page and design:check only finds fences that exist, so the whole suite stays +// green while the page silently loses every fence it should have been checked against. +{ + const off = PAGES.filter(p => !p.fences).map(p => p.path); + if (off.length) { console.log("✗ PAGES fences is not enabled on: " + off.join(", ")); failures++; } +} // And the suite must be talking to this site. A sibling repository left serving on :8000 is // not hypothetical — it happened during review, and the run reported six failures belonging // to a site nobody was testing. From d707b55f857d250a32d4f8519e66bbe8eb88b0ea Mon Sep 17 00:00:00 2001 From: Robert Blust Date: Tue, 1 Sep 2026 00:53:18 +0200 Subject: [PATCH 2/2] The conventions file described a discipline four fences no longer follow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CLAUDE.md overrides default behaviour by construction, so it is the first thing read and the last thing checked. Since the design package landed it has told anyone who read it to edit a fenced block in place, run the suite, and bump the version marker in all three repositories. That instruction now does nothing. The block is generated; the next `npm run design` overwrites the edit, and nothing warns you. It is the worst shape a note can take here — not missing, but confidently wrong, in the file whose whole job is to be trusted. Rewritten to say what is true: which blocks the package owns, that editing one in place is silently discarded, the three steps that actually change one (edit in the package, tag a release, sync here), and that `design:check` runs in CI so drift goes red without anyone going looking — the guarantee the old habit-with-a-tripwire never was. Two things stay hand-maintained and say so: the deck footer, which is still a versioned copy bumped in all three repositories, and the head contract, which has no fence at all. Also written down: the two escape hatches. Removing a fence from a page's `fences` array, or a group from design.config.json, each clears a red `design:check` with a one-line diff. Both are a decision to own a block and diverge, not a build fix. --- CLAUDE.md | 53 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 2dd4e9d..3c710c3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -284,11 +284,15 @@ fix by hand; do not link the two. ## The design system, and why it is a copy -Type and colour are shared across `blust.ch`, `guestgraph.io` and the talks repository. +Type and colour are shared across `blust.ch`, `guestgraph.io` and `companygraph.io`. They share no stylesheet and cannot: a deck has to open from `file://`, so there is nothing to import. Every page therefore carries its own copy of the token block, fenced by `design tokens · vN` markers. +**The copies have a source now.** They are generated from `@robertblust/design`, which this +repository pins by tag, and `npm run design` writes them. What that changes about editing them is +in *Changing a token* below, and it is the opposite of what this file said for most of its life. + - **Brightness is confidence, and each stop has exactly one job.** `--c-weak` a candidate considered and not accepted; `--c-mid` anything interactive — links, controls, the brand accent; `--c-firm` the resolved thing — the thesis, the current page; `--c-flag` a @@ -330,12 +334,44 @@ by `design tokens · vN` markers. type can utter. Weight says the same thing and never needs explaining. Do not reintroduce a degraded display face to make this point. -### Changing a token +### Changing a token, or anything else the package owns + +**Do not edit a fenced block in place. The next `npm run design` overwrites it and nothing warns +you.** This section used to say "edit the block, run `npm run verify`, bump `vN` in all three +repositories". That was true while the blocks were maintained by hand. It is now the one +instruction in this file that silently does nothing. + +Six blocks are generated, and the fence markers name them: `design tokens`, `header contract`, +`stage contract`, `language`, `prose reset` and `prose footer`. Everything between and including a +pair of markers belongs to the package. + +```bash +npm run design # rewrite every fenced block from the pinned release +npm run design:check # report drift without writing — runs in CI, before the browser suite +``` + +To change one of them: + +1. Edit it in `robertblust/design` under `blocks/`, and bump both its entry in `versions.json` and + the version typed into the block's own first line. A test there fails if the two disagree — it + exists because nothing else reconciled them. +2. Tag a release. The sites pin an exact **tag**, never a commit SHA: Dependabot's version detection + rejects a SHA, and this site would then never be told a release happened. +3. Here: take the Dependabot pull request, run `npm run design && npm run og`, commit what changed. + The design package has its own Dependabot group so a design bump never arrives beside a + Playwright one — it is the pull request that has to be read rather than merged on sight. + +`design:check` runs in CI, so a page that drifts from the pinned release goes red without anyone +remembering to look. That is the guarantee the old habit-with-a-tripwire never was. + +**Two escape hatches that are decisions, not build fixes.** Removing a fence's name from a page's +`fences` array in `PAGES`, or a group from `design.config.json`, each clears a red `design:check` +with a one-line diff. Either one means this site has decided to own that block and diverge. That is +a real choice; make it deliberately, in a commit that says so. -Edit the block, run `npm run verify`, and it will name any page in **this** repository that -is behind. Nothing can tell you that a sibling repository is behind — that is why the block -carries a version. Bumping `vN` means bumping it in all three repositories and running all -three suites. The check is a habit with a tripwire, not a guarantee. +**Not everything is generated.** The deck footer is still a hand-maintained copy carrying its own +version marker — see below, where the old discipline applies in full — and the `` contract is +a copy with no fence at all. Both decks under `talks/` carry the system too, and all four pages load their faces from the **one `fonts/` directory at the root** — `../../fonts/` from a deck, as on both sibling sites. @@ -364,8 +400,9 @@ fence is not a way around it. The row across the top — wordmark, links, language control — is one design on three sites, and like the tokens it is a copy, because a deck opens from `file://` and there is no stylesheet to share. It is fenced in every page as `header contract · vN` and is -**byte-identical on all sixteen pages** in the three repositories. Check it the way you -check the tokens: change it here, run this repo's suite, and bump `vN` in all three. +**byte-identical on all sixteen pages** in the three repositories. It is generated, like the +tokens: change it in `robertblust/design`, tag a release, then run `npm run design` here. Editing +it in this file does nothing — the next sync overwrites it. What the contract says: