Skip to content

Phase 1a.4: dark surfaces onto --surface-ink, --ruby-on-ink, and two live AA fixes - #540

Merged
pftg merged 10 commits into
masterfrom
phase-1a4-dark-surfaces
Aug 21, 2026
Merged

Phase 1a.4: dark surfaces onto --surface-ink, --ruby-on-ink, and two live AA fixes#540
pftg merged 10 commits into
masterfrom
phase-1a4-dark-surfaces

Conversation

@pftg

@pftg pftg commented Aug 21, 2026

Copy link
Copy Markdown
Member

Phase 1a.4 — the dark-surface work, unblocked and shipped. CSS only; no baselines (see Gates).

What changed

1. The token that was blocking the phase. --ruby-on-ink: #e85a52, measured on --surface-ink #14110f:

ratio AA-normal
--color-ruby #cc342d 3.67:1 fails (large-text only)
--ruby-on-ink #e85a52 5.39:1 passes, with headroom

For ruby text/icons on the dark band. Ruby backgrounds keep --color-ruby with white on top.

2. The dark band unified — all of it. It was three groups that had to move together:

  • footer.css background-color: black
  • 12 .fl-builder-bottom-edge-layer .fl-shape-content .fl-shape fills across 9 files
  • 5 section bands: .home-services, .about-achievements, .careers-testimonial, .service-overview, .use-case-details

Moving any subset leaves a seam. My first pass moved the first two and created the seam it was meant to remove — codex caught it, and the browser confirmed .home-proof's edge at rgb(20,17,15) meeting .home-services at rgb(0,0,0).

3. Three live WCAG AA failures fixed. Homepage SERVICES and CLIENTS + CASE STUDIES were at 4.1:1 on black — live today. Migrating the bands then dropped about-achievements-eyebrow and service-overview-eyebrow to 3.67:1, because the old ruby is worse on --surface-ink than on black. All four now use --ruby-on-ink.

That interaction is why the bands and the text are one change, not two.

Evidence — from the live render, not the suite

Measured in the browser on all five affected pages (homepage, about-us, careers, a single-service page, a single-use-case page), checking for both dark seams and AA failures, widened on two pages from eyebrows to every text element on the ink band:

seams: []          aaFailures: []

Live values: both dark painters compute rgb(20, 17, 15); --ruby-on-ink resolves to #e85a52; eyebrows 4.1 → 6.02:1.

Gates — and why there are no baselines here

bin/hugo-build clean.

I originally accepted 15 macOS baselines and reported "55 screenshots compared, no failures." That evidence was worthless. Running the suite on pristine master — master's CSS, master's baselines, nothing of mine:

Suite Failures on untouched master
bin/rake test:critical 13 of 55
bin/rake test:system 18 of 126

My run was green only because it had rewritten the baselines with this machine's output. That's replacement, not verification, and committing it would bake local render drift into the repo, mixed in with the intended recolour and indistinguishable from it.

The tell I should have followed sooner: a blog diff showed the article body vertically shifted — a background-color change cannot move layout. It nearly passed because it arrived batched with diffs that genuinely were the intended recolour.

All 15 baselines are reverted. They need recording where the canonical ones came from:

gh workflow run test.yml --ref phase-1a4-dark-surfaces \
  -f screenshots=true -f update-baselines=true

Same rule ci-gates.md already states for Linux, for the same reason.

Scope

31 hardcoded blacks remain, none adjacent to a migrated edge; several are code-block surfaces — a design decision, not a token rename. .fl-button has 720 occurrences, so "three button roles" is a multi-PR migration, not a unit.

Knowledge recorded

  • .okf/architecture/css-pipeline.md — reading color off the element your selector matched rather than the one that paints reported 1.12:1 for eyebrows on a page that renders fine; FL-Builder nests three levels deep.
  • .okf/build/test-gates.md — run the suite on pristine master before trusting a green run.

🤖 Generated with Claude Code


Handoff — 16 stale Linux baselines

This PR invalidates these Linux baselines (from CI run 32460674225 on the branch). Not recorded here — Linux rides the parallel PR, per Paul 2026-08-19:

desktop/blog/index/_pagination             desktop/services/_cta-contact_us
desktop/blog/special/codeblocks/bare       desktop/services/_footer
desktop/blog/special/codeblocks/indented   desktop/services/_overview
desktop/contact_us                         desktop/services/_services
desktop/homepage/_clients                  mobile/blog/index/_pagination
desktop/homepage/_cta-contact_us           mobile/blog/special/codeblocks/indented
desktop/homepage/_footer                   mobile/services
desktop/homepage/_services
desktop/homepage/_technologies

All 16 are dark-band surfaces. The reds were checked against the run, not assumed.

A record was dispatched and then dropped: screening it by byte-size found desktop/blog/tag.png at 12.44%, whose diff showed different blog posts ("108 posts tagged rails" vs 106) — content drift from a blind whole-site record, not this change.

Merging is safe: test.yml triggers on pull_request and workflow_dispatch only — no push trigger — so this does not turn master red; and on PRs the job is continue-on-error.

pftg and others added 3 commits August 21, 2026 09:00
…by-on-ink

The dark band was two painters disagreeing: footer.css set `background-color:
black` while 12 `.fl-builder-bottom-edge-layer .fl-shape-content .fl-shape`
rules across 9 page files set `fill: #000000`. Moving either alone produces a
visible seam where the SVG edge meets the footer, which is why an earlier
attempt at this was reverted. Both move together here.

Also lands the token that was blocking the rest of 1a.4:

  --ruby-on-ink: #e85a52

Measured on --surface-ink #14110f:

  --color-ruby #cc342d   3.67:1   fails AA-normal, large-text only
  --ruby-on-ink #e85a52  5.39:1   passes AA-normal with headroom

That is for ruby TEXT/icons on the dark band. Ruby BACKGROUNDS keep
--color-ruby with white on top, which is unaffected. Footer text was checked
against the new band before shipping: links #969798 6.43:1, body #fff 18.80:1,
both AA.

Verified in the browser rather than from source: both painters now compute to
rgb(20, 17, 15), so the seam is closed, and --ruby-on-ink resolves to #e85a52.
Desktop 1920 and mobile 390 both read correctly - the warm ink is legibly
different from pure black and every footer element survives.

Gates: bin/hugo-build clean. bin/qtest --changed reported
[snap_diff] 55 screenshots compared, 10 failures - all 10 are surfaces
containing the dark band (both footers, both CTA bands, contact_us, the two
pagination frames, three codeblock frames). Baselines were reset to HEAD first,
because the tree carried 10 dirty PNGs from an earlier session that would have
made the comparison meaningless.

Accepted deliberately, with the pixel check rather than the diff metric:

  old baseline  srgba(0,0,0,1)
  new render    srgba(20,17,15,1)

The 0.06-0.81 difference_levels are pixel COUNTS, not perceptual magnitude - a
whole band shifting slightly moves most pixels in frame.

macOS baselines only; Linux rides the parallel PR.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Measured in the browser, not inferred: the SERVICES and CLIENTS + CASE STUDIES
eyebrows paint --color-ruby #cc342d on an #000000 section band at 4.1:1, which
fails WCAG AA for normal text. They are live on the homepage today.

Moved to --ruby-on-ink (the token added in the previous commit): 4.1 -> 6.02:1,
AA pass. Re-measured after rebuild rather than assumed. The light-surface
eyebrow on the same page (home-why-us-eyebrow, ruby on white) is untouched and
still reads 5.13:1 - this is the check the earlier blanket eyebrow sweep failed,
which is why that one was reverted.

This also had to happen alongside the band work rather than after it: on
--surface-ink #14110f the old ruby measures 3.67:1, so unifying the dark
surfaces without fixing the text would have made these two worse.

Scope deliberately stopped here. 18 eyebrow rules paint ruby and 36 hardcoded
black backgrounds remain, but only the failures I could MEASURE are fixed -
sweeping all of them blind is precisely what produced the reverted regression.
The remaining blacks include code-block surfaces, which are a separate design
decision, not a token rename.

An instrument note, since it nearly cost a wrong conclusion: the first
measurement read `color` off the `.fl-module` WRAPPER and reported 1.12:1 - near
black on black, which would be invisible - on a page that plainly renders fine.
The painted text lives deeper in the tree. Walking down to the element that
actually holds the text gave the real 4.1:1. A computed-style reading that
contradicts the render is the instrument being wrong, not the page.

Gates: bin/hugo-build clean. bin/qtest --changed reported
[snap_diff] 5 screenshots compared, 2 failures - both use-cases footer surfaces
carrying the previous commit's band change on a page that run had not covered.
Pixel-verified as the same intentional shift, srgba(0,0,0,1) ->
srgba(20,17,15,1), and accepted. macOS only; Linux rides the parallel PR.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
One entry, on the architecture/css-pipeline.md instrument ladder: reading
`color` off the element your selector matched rather than the one that paints
the text reported 1.12:1 for eyebrows on a page that renders fine. FL-Builder
nests .fl-module > .fl-module-content > .fl-rich-text, so the wrapper is almost
never the painter, and the bogus reading would have buried the real 4.1:1 AA
failure under an implausible one.

Gates: v0.2 okf_validate .okf exits 0. Stamped with measured UTC.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6dbe4c41-bb62-4a31-a873-9cc4d683667e


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

pftg and others added 5 commits August 21, 2026 09:20
…meet

Codex review caught a real defect in the previous commit: moving the 12
bottom-edge shape fills to --surface-ink while the section bands they abut
stayed #000 CREATED the seam this phase exists to remove. Verified in the
browser before fixing - .home-proof's edge computed rgb(20,17,15) meeting
.home-services at rgb(0,0,0).

Only 5 bands are involved, and they are exactly the ones adjacent to a migrated
edge:

  .home-services        homepage.css
  .about-achievements   about-us.css
  .careers-testimonial  careers.css
  .service-overview     single-service.css
  .use-case-details     single-use-cases.css

Moving them exposed two more AA failures, which is the interaction that makes
these inseparable: --color-ruby measures 3.67:1 on --surface-ink, so any ruby
text on a migrated band gets WORSE. about-achievements-eyebrow and
service-overview-eyebrow both dropped to 3.67:1 and are moved to --ruby-on-ink.

Re-measured every affected page in the browser afterwards - homepage, about-us,
careers, a single-service page and a single-use-case page - checking for BOTH
dark seams and AA failures, and on careers/about-us widening the sweep from
eyebrows to every text element sitting on the ink band. All five report zero
seams and zero failures.

This is why the previous commit's "scope stopped here" was wrong rather than
conservative: the bands were not optional follow-up work, they were the other
half of the same change. The 31 remaining hardcoded blacks genuinely are
separate - none of them abuts a migrated edge, and several are code-block
surfaces.

Gates: bin/hugo-build clean. bin/test reported
[snap_diff] 55 screenshots compared, 3 failures - homepage _services,
_technologies and _clients, all the migrated band. Pixel-verified
srgba(0,0,0,1) -> srgba(20,17,15,1) and accepted. macOS only; Linux rides the
parallel PR.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
I accepted 15 macOS baselines across the previous commits and presented
"55 screenshots compared, no failures" as evidence the change was clean. That
evidence was worthless, and worse than worthless because it looked strong.

The check I skipped: run the suite on PRISTINE master. Doing it now, with
master's CSS and master's baselines and no change of mine in the tree:

  bin/rake test:critical   13 of 55 screenshots fail
  bin/rake test:system     18 of 126 screenshots fail

So this worktree's macOS rendering does not match the committed macOS baselines
at all, independently of anything I did. My run was green only because I had
overwritten the baselines with this machine's output - I was not verifying
against the repo's baselines, I was replacing them. Accepting them would bake
this machine's drift into the repo, mixed in with the intended colour change and
indistinguishable from it.

The blog code_highlight diff is the tell I should have followed sooner: the
article body is VERTICALLY SHIFTED, and a background-color change cannot move
layout. I nearly accepted it as "the same intentional shift" because it arrived
in the same batch as changes that were.

So all 15 baselines are reverted to master's. The CSS commits stand - their
correctness is established independently of the screenshot suite, by browser
measurement and pixel sampling of the live render:

  both dark painters compute rgb(20, 17, 15), seam closed
  --ruby-on-ink resolves to #e85a52
  eyebrows 4.1 -> 6.02:1 on the homepage, 3.67 -> AA-pass on about-us
  zero dark seams and zero AA failures across all 5 affected pages

Baselines must be re-recorded where the canonical ones were produced, not here:

  gh workflow run test.yml --ref phase-1a4-dark-surfaces \
    -f screenshots=true -f update-baselines=true

That is the same rule ci-gates.md already states for Linux - record where the
renderer matches - and it applies to macOS from this worktree for the same
reason.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The rule I most needed today and did not have. A green screenshot run proves
nothing until you know the suite is green with NOTHING changed:

  bin/rake test:critical   13 of 55 fail on untouched master in this worktree
  bin/rake test:system     18 of 126

My phase-1a.4 run reported "55 screenshots compared, no failures" and I quoted it
as evidence. It was green only because the run had rewritten the baselines with
this machine's output - replacement, not verification.

Recorded with the tell I should have followed sooner: a blog diff showed the
article body vertically SHIFTED, and a background-color change cannot move
layout. It nearly passed because it arrived batched with diffs that genuinely
were the intended recolour, which is the general hazard - a batch of expected
changes is where an unexpected one hides.

Also recorded: correctness of the change itself is establishable without the
suite, by browser measurement and pixel-sampling the live render, and that
evidence is independent of baseline drift. That is what carries this PR.

Gates: v0.2 okf_validate .okf exits 0. Stamped with measured UTC.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two concepts corrected against what actually shipped on this branch.

1. design/site-palette.md carried `#e85a52` as a RECOMMENDATION and said "Not
   yet applied - Paul's call". Both false: it is in css-variables.css and
   applied. That staleness is not cosmetic - a cold session reading it would
   conclude the phase was still gated on a decision, which is precisely the
   false state that produced hours of adjacent work instead of CSS. Now recorded
   as decided and shipped, with WHERE it was applied: the four eyebrows that
   measured below AA, not a site-wide sweep, because sweeping is what the
   reverted 41-rule attempt got wrong.

   Re-stated because it survives the decision unchanged: neither automated gate
   catches a contrast regression on those bands.

2. architecture/css-pipeline.md documented how to HUNT the shape layer but never
   what the dark band is made of. It is three groups - 1 footer background, 12
   bottom-edge SVG fills across 9 page files, 5 section bands - and moving a
   subset ships a seam. Both failure directions are now on record: moving the
   footer alone (reverted earlier), and moving footer+fills while leaving the
   bands black (this branch, caught in review).

   With the coupling that makes them inseparable: --color-ruby is 4.10:1 on
   #000 but 3.67:1 on --surface-ink, so migrating a band makes ruby text on it
   worse. Two eyebrows that were fine before the bands moved failed after.

Gates: v0.2 okf_validate .okf exits 0. Both concepts stamped with measured UTC.
Verified with flatten + grep -o and a positive control, per the counting caveat
in build/test-gates.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Swept the bundle for claims that rot, after site-palette.md was found carrying a
closed blocker as open. Two outcomes.

1. workflows/site-redesign-rollout.md needs no fix, BY DESIGN - it states that
   phase status comes from git rather than any document, and records reasoning
   rather than a state snapshot. Adding current status would make it worse. Worth
   stating as the counter-example to site-palette: the difference between a
   concept that rots and one that does not is whether it stores STATE or
   REASONING.

2. The bundle's one remaining cross-link warning was not a broken link.
   design/course-landing-components.md referenced a repo doc with
   `../../docs/projects/...`, which resolves correctly on disk - verified by
   listing the target from the concept's own directory - but the validator cannot
   follow a link out of .okf/, so it warned on every run. A permanent warning is
   worse than noise: it invites someone to "fix" a link that was never broken.

   The canonical path was already in that concept's `resource:` frontmatter, so
   the body link duplicated it. Converted to inline code; the bundle's broken-link
   warnings are now zero. Convention recorded in index.md.

Postscript, recorded in the log: the control I used to confirm this
(`grep -ci 'cross-link'`) returned 1 and looked like a regression, because it
matched the words inside the new log entry's own heading. The real message form
is `cross-link target not found`, which returns 0. A search term general enough
to match your own prose about a thing does not measure the thing.

Gates: v0.2 okf_validate .okf exits 0, zero `cross-link target not found`.
Edited concept stamped with measured UTC.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@pftg
pftg force-pushed the phase-1a4-dark-surfaces branch from a253463 to 715ea1b Compare August 21, 2026 07:52
pftg and others added 2 commits August 21, 2026 09:53
Dispatched test.yml -f update-baselines=true on this branch, because this
worktree's macOS render is drifted and cannot produce trustworthy baselines. The
bot recorded 84 Linux baselines for a change that moves one colour.

Screened them by the byte-size procedure ci-gates.md already documents:

  76 of 84   under the ~1.2% noise floor
   7 of 84   footers and CTA bands - genuinely this change
   1 of 84   desktop/blog/tag.png at 12.44%

Diffing that outlier showed DIFFERENT BLOG POSTS - "108 posts tagged rails"
against 106, different titles and dates. Content published since the previous
recording, folded into an unrelated PR by a record that snapshots the whole site
rather than the diff.

The record commit is dropped from the branch (rebase --onto, backup tag first).
The PR is CSS-only and 84 mostly-unrelated binaries make its visual evidence
unreadable; and the screenshot job is continue-on-error on pull_request
(test.yml:72), so a stale Linux baseline reports without blocking. Linux rides
its own PR per Paul 2026-08-19.

Recorded in ci-gates.md beside the existing "record mode has no accept/reject
gate" rule, which had the screening procedure but not this consequence: the
outliers you find are often somebody else's work, and there is no CI-side filter
- bin/record-baselines <glob> does it locally, a dispatch cannot, so the
filtering has to happen after the fact.

Gates: v0.2 okf_validate .okf exits 0. Stamped in this file's own block form;
verified rows diffed against the merge base, additions only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Making debt legible rather than silent, per the async-first rule. The 1a.4
recolour invalidates 16 Linux baselines - all dark-band surfaces - listed in the
log entry and mirrored into the PR body, which is where whoever picks up the
Linux work will actually look.

The reds were read from CI run 32460674225 and checked against the failing
surfaces rather than assumed, per ci-gates.md's "a slow failure and a fast
failure are different failures".

Not recorded on this PR deliberately: Linux rides a parallel PR (Paul
2026-08-19). A record was dispatched and dropped when screening found content
drift in it, and re-dispatching to curate it here would take that instruction the
other way.

Two facts that make merging safe rather than reckless, both verified in the
workflow file: test.yml triggers on pull_request and workflow_dispatch ONLY -
no push trigger - so merging cannot turn master red; and on PRs the job is
continue-on-error. Which is also precisely the silent-drift condition
ci-gates.md already documents, now with a concrete list attached instead of a
general warning.

Gates: v0.2 okf_validate .okf exits 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@pftg
pftg merged commit f6298d9 into master Aug 21, 2026
4 of 5 checks passed
@pftg
pftg deleted the phase-1a4-dark-surfaces branch August 21, 2026 08:07
pftg added a commit that referenced this pull request Aug 21, 2026
Codex pre-merge on #552 returned 4 findings. Three accepted, one declined.

ACCEPTED - all three are the same failure: records written before the opus
review changed the implementation, never swept after.

1. OKF log and 20.06 described a tag-first derivation; the shipped template is
   prefix-only (the tag branch was deleted as dead code in review). A future
   maintainer could have restored deleted code or debugged nonexistent
   behavior. Both records now state prefix-only + name dict.
2. 20.06's gate line said "verifiers on sonnet" blanket - written before Paul's
   routing table finalized. Now stage-specific: code review = opus, design
   critique = fable, mechanical = sonnet.
3. The cold-session ledger still scheduled the Linux dispatch and Direction 2,
   both complete. Rows updated; judging now correctly blocked on Paul's Claude
   Design pass alone.

DECLINED - recording macOS course/chapter baselines from this machine. The
merge-base run measured 13 failures on UNTOUCHED master here, so a local macOS
record poisons the repo with machine drift (the exact mechanism #540 reverted).
Cost acknowledged: those two keys stay red on macOS runs (diff 3.2%/11.4% vs
0.03 tolerance) until recorded on a healthy Mac - now tracked as an OUTSTANDING
item in the 20.06 ledger, not just the PR body.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pftg added a commit that referenced this pull request Aug 21, 2026
Codex pre-merge on #552 returned 4 findings. Three accepted, one declined.

ACCEPTED - all three are the same failure: records written before the opus
review changed the implementation, never swept after.

1. OKF log and 20.06 described a tag-first derivation; the shipped template is
   prefix-only (the tag branch was deleted as dead code in review). A future
   maintainer could have restored deleted code or debugged nonexistent
   behavior. Both records now state prefix-only + name dict.
2. 20.06's gate line said "verifiers on sonnet" blanket - written before Paul's
   routing table finalized. Now stage-specific: code review = opus, design
   critique = fable, mechanical = sonnet.
3. The cold-session ledger still scheduled the Linux dispatch and Direction 2,
   both complete. Rows updated; judging now correctly blocked on Paul's Claude
   Design pass alone.

DECLINED - recording macOS course/chapter baselines from this machine. The
merge-base run measured 13 failures on UNTOUCHED master here, so a local macOS
record poisons the repo with machine drift (the exact mechanism #540 reverted).
Cost acknowledged: those two keys stay red on macOS runs (diff 3.2%/11.4% vs
0.03 tolerance) until recorded on a healthy Mac - now tracked as an OUTSTANDING
item in the 20.06 ledger, not just the PR body.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pftg added a commit that referenced this pull request Aug 21, 2026
* Persist the clean-slate v2 pivot so any session can resume it

Paul approved the revised strategy (plan mode) and asked that all project
artifacts let a separate session finish the work when interrupted. The approved
plan lived only in a session-local plans file - invisible to a cold session -
so this commit moves the whole state into the repo.

New plan of record: docs/projects/2608-site-design-system/20-29-strategy/
20.06-clean-slate-v2-plan.md - the dual-run v2 rail (root layouts/next/, clean
bundles, functional partials reused verbatim), /next/ non-indexed production
staging, page-by-page cutover, legacy frozen with the 780 button sites and 39
blacks dropped as work-done-twice. Carries a COLD-SESSION STATE LEDGER with
per-item status and exact next actions, updated in the same commit as the work
it describes.

Decisions of record captured: 2-direction design competition, FULLY OPEN
(rebrand allowed - ruby/LIGHT hold on the live site only until Paul picks);
Claude Design and stitch COLLABORATE (the old "Rescue Room" project renders
extraction, which is why previews looked like course reuse); sub-agent model
routing - code review on opus, docs/panels on sonnet, mechanical on haiku,
Fable never inherited by spawns (CLAUDE.md updated).

Supersession markers placed where a cold session would otherwise read stale
direction as current: 2608 README pivot banner + inline markers on the
"no authority" paragraph and the phase table; 20.01 Phase-2 banner; OKF
site-redesign-rollout.md pivoted (old lane model kept under a superseded
heading) + log entry.

Author != verifier: a sonnet reviewer attacked the staged diff against its own
acceptance bar and returned 3 findings, all fixed before this commit - two
unmarked stale assertions in the README (the file a cold session reads FIRST)
and a ledger status claiming IN PROGRESS for work not yet started. Its
spot-checks verified bin/qtest:69-78 hole, enhanced-meta-tags noindex,
sitemap private-filter, and all three fl-line counts as written.

Gates: bin/hugo-build clean; v0.2 okf_validate exits 0; concept stamped with
measured UTC.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Phase 2.3: course module eyebrow - Module N + canonical name

Course lessons carry the canonical eyebrow (12px/700/0.14em/uppercase/ruby)
above the H1: "Module 2 · Validate the Problem". Derived from the "N.N ·"
title prefix; names mirror the canonical module map in how-this-course-works.
25 lessons render (census 5/6/2/5/7 across Modules 1-5); quickstart, faq,
walkthroughs, reference pages correctly get none. Browser-measured: computed
spec exact (letter-spacing 1.68px = 0.14em @ 12px), 5.13:1 on white - AA pass.
Desktop 1920 + mobile 390 inspected.

Opus diff review (author != verifier) returned 4 findings; all addressed
before this commit:

- F2/F3: the module-N tag branch was DEAD CODE - the 6 tagged lessons are a
  strict subset of the 25 prefixed ones, and hasPrefix "module-" without a
  digit check would render "Module card" from an unrelated tag. Tag branch
  deleted; derivation is the anchored prefix regex alone (11 lines -> 6).
- F4 (design): the digit-only eyebrow duplicated the number already visible in
  the H1 one line below - decorative, not helpful, failing CLAUDE.md's own
  gate language. Fixed by adding the module NAME, which the H1 does not carry.
- F1 (baselines): course/chapter desktop+mobile baselines are invalidated by
  design. Handling per the recorded procedure - see the attribution run in the
  next commit / PR body; local macOS records are untrustworthy on this
  machine, Linux records ride a CI dispatch on the branch, screened.

The reviewer also verified: regex safe against every real title (rendered
census, zero false positives on digit-leading titles), findRESubmatch empty
slice guarded by `with`, eyebrow rule survives production PurgeCSS verbatim,
no competing cascade (the one other header-p rule is @media print).

Also rides: model routing final form in CLAUDE.md (critical decisions +
editing/outlining = fable; coding, code review, content writing = opus;
mechanical = sonnet), 20.06 ledger status, OKF log entry.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Track A: shared design-competition brief (20.07) + routing refinements

One brief, two tools: the identical fully-open contract runs in stitch (agent-
driven; direction 2 generating now) and in a NEW Claude Design project (Paul-
driven) - identical wording keeps outputs comparable, and the doc warns off the
old "Rescue Room" project, which renders the extracted system this competition
steps back from. Carries its own status ledger per the cold-session rule.

Constraints are only the hard ones: no stock people, no logo walls/carousels/
repeated CTAs, claims-canon on any company fact, no extraction from the
current site. Everything else - palette, typography, identity - open, per
Paul's fully-open decision.

Routing refinements from Paul recorded in CLAUDE.md: design critique joins
fable (with critical decisions and editing/outlining); the /impeccable judging
panel therefore runs on fable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Track A ledger: Direction 2 landed - Institutional Authority

Dark midnight-navy/charcoal, IBM Plex Sans, forensic-artifact narrative.
Canon flags recorded for judging: invents a 90-day guarantee (not in canon);
dark chrome contradicts the peer-set evidence ADR-0003 cited - panel weighs
both, since the brief was fully open.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Linux baselines for course/chapter, screened from the CI record

The branch dispatch recorded 72 baselines for a change that adds one line to
one template. Screened per the recorded procedure (ci-gates.md): kept exactly
the 2 course keys this PR invalidates - desktop +0.84%, mobile +1.71%, both
consistent with an added eyebrow line - and dropped the other 70, which are
whole-site record noise and would fold unrelated drift into this PR (the
blog/tag.png content-drift incident, 2026-08-21).

The bot's whole-record commit is replaced by this screened one via
force-with-lease; backup of the bot ref is the run itself (32479029380).

macOS course/chapter keys remain UNRECORDED deliberately - the merge-base run
proved this machine's macOS render is drifted (13 failures on untouched
master), so local records would poison the repo. Listed in the PR handoff.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Apply codex findings: sync three records to the shipped implementation

Codex pre-merge on #552 returned 4 findings. Three accepted, one declined.

ACCEPTED - all three are the same failure: records written before the opus
review changed the implementation, never swept after.

1. OKF log and 20.06 described a tag-first derivation; the shipped template is
   prefix-only (the tag branch was deleted as dead code in review). A future
   maintainer could have restored deleted code or debugged nonexistent
   behavior. Both records now state prefix-only + name dict.
2. 20.06's gate line said "verifiers on sonnet" blanket - written before Paul's
   routing table finalized. Now stage-specific: code review = opus, design
   critique = fable, mechanical = sonnet.
3. The cold-session ledger still scheduled the Linux dispatch and Direction 2,
   both complete. Rows updated; judging now correctly blocked on Paul's Claude
   Design pass alone.

DECLINED - recording macOS course/chapter baselines from this machine. The
merge-base run measured 13 failures on UNTOUCHED master here, so a local macOS
record poisons the repo with machine drift (the exact mechanism #540 reverted).
Cost acknowledged: those two keys stay red on macOS runs (diff 3.2%/11.4% vs
0.03 tolerance) until recorded on a healthy Mac - now tracked as an OUTSTANDING
item in the 20.06 ledger, not just the PR body.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Track A: Claude Design project created and seeded from the session

Paul pointed out DesignSync reaches claude.ai/design from here - no copy-paste
handoff needed. Created "JetThoughts - From-Scratch Competition (2608)"
(a5f25203-6dd9-45c6-a978-5842152d1389) and seeded 8 files: the fully-open
BRIEF.md, both directions' DESIGN.md summaries (with the ruby-locked disclosure
on D1 and the canon flags on D2), and both full-page renders (2560px) as
preview cards. The old "Rescue Room" project stays untouched - it renders the
extracted system.

Paul's move shrinks to: open the project, run/iterate the brief, or critique
the two seeded directions. Everything cross-pollinates before the fable critic
and the judging board.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
pftg added a commit that referenced this pull request Aug 21, 2026
…0x) (#560)

* Screenshot tolerance 0.02 -> 0.0001: the visual gate was blind by 50x

DEFAULT_SCREENSHOT_CONFIG demanded that ~41,472 pixels of a 1920x1080 frame
differ before an assertion failed, so real changes passed green.
services/_testimonials-header sat at difference_level 0.005923 through an entire
dark-surface recolour and reported no change. Measured on
DesktopSiteTest#test_services at clean HEAD, 7 screenshots compared per run:
0.02 gives 2 failures, this commit gives 3. Run-to-run noise is 0.0 - repeat
runs return difference_levels identical to 16 decimal places, and 2 of the 7
stay green at the new floor - so 0.0001 (~207 px) clears jitter without
tripping on it. The ~30 calls that pin their own tolerance are untouched; only
the floor for calls pinning nothing moved.

Passing quietly is worse than failing, because it fossilizes the baseline: the
gem writes the fresh capture over the baseline PNG, then a PASS restores the
git-HEAD image back over it. A green run therefore never refreshes anything,
and every sub-tolerance change leaves the committed PNG showing the old render
until something large enough to fail arrives and the accumulated drift gets
accepted in one lump nobody can attribute. Corollary now documented: only a RED
run leaves a committable candidate, and deleting the PNG first does nothing
since the base is read from git HEAD.

SECTION_CONFIGS is KEPT at 0.02 on purpose. Its 7 keys equalled the old
default, making it a silent no-op; lowering the default inverts that into a
load-bearing shield holding ~22 section screenshots at the old tolerance until
their drift is measured. Deleting it here would drop those to 0.0001 unmeasured
and would also corrupt the headline number: with the shield removed the same
test fails 5 instead of 3, which is +3 rather than the +1 this change actually
costs. The two extra are exactly the screenshots whose names hit a
SECTION_CONFIGS key (services/_use-cases 0.017498, services/_technologies
0.013838), since keys match the tail after "/_" - /_technologies matches
technologies, /_testimonials-header does not match testimonials.

That mapping went from inert to safety-critical with no coverage, so it moves
to test/support/screenshot_section_config.rb and is pinned by
test/unit/screenshot_section_config_test.rb. It had to move: requiring
application_system_test_case.rb from a unit test boots Hugo, Capybara and that
file's dirty-fixtures abort. The guard was verified by mutation - splitting the
key on "-" so _testimonials-header matches the testimonials shield turns the
suite red, reverting turns it green - and the system path re-measured identical
(same 3 failures, same difference_levels) after the extraction.

test-gates.md also documents two blind spots tolerance cannot fix. Captures are
viewport-only at scroll top (1920x1080 desktop, 360x800 mobile,
test/support/setup_capybara.rb:85-86), so below-fold content is invisible at
ANY tolerance - a table-cell edit measures difference_level exactly 0 on mobile
even at tolerance 0, and every failure region here caps at the viewport height.
And perceptual_threshold = 2.0 (test/support/setup_snap_diff.rb:25) means vips
only counts a pixel as differing above CIE dE00 2.0, so a sub-threshold
recolour contributes zero differing pixels at any tolerance. Coverage fixes are
out of scope. Live doctrine swept truthful: the tutorial documented a
SCREENSHOT_TOLERANCE env var that exists nowhere in the codebase (and claimed a
1% default the code never had), a helper named
assert_stable_problematic_screenshot with its own section and three call sites,
and a per-OS tolerance-multiplier table - none of which exist in test/, bin/ or
lib/; visual-qa-criteria pinned 0.02. A doctrine file names its own mechanisms,
so its fiction looks executable and gets copied.

Gates: bin/rake test:unit 289 runs, 6090 assertions, 0 failures. bin/hugo-build
clean. okf_validate: 0 errors, 111 -> 112 warnings (exactly the one section-7
date heading this log entry adds). Screenshot suites are red on the stale #540
baselines by design - that is the gate biting:

  Screenshot does not match for 'desktop/services/_testimonials-header':
  ({"difference_level":0.005922550154320988})

which passed silently before this commit. Those baselines are NOT re-recorded
here; that is the follow-up's job.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Docs: 20.10 §4 gate-blindness marked FIXED (verifier residual P3)

The list taught the 2% blindness in present tense with 'left as-is
deliberately' - three claims made false by the previous commit. Edit
prescribed verbatim by the delta re-clear.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011SP5gaqXEgUie8pdFrmbeJ

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant