Repository navigation
Conversation
The browser check covered #19's figure design for --fig-ink only: its contrast, the SVG having no painted chip, and the ink changing between themes. Two unit tests still guarded the rest by reading site.css as text. scripts/figure_theme_contract.mjs now measures, in light and in dark, on the rendered page: - every token in the grammar's FIGURE_TOKENS_LIGHT/DARK resolves to a colour on the figures and equals the colour the grammar documents (compared as computed colours, not as spelled); - every stroke and fill painted through a token paints that token's colour; - every such stroke and fill changes colour between light and dark; - no figure SVG has a painted background, and the ink keeps 4.5:1. The existing ink, chip and recolour checks move into the module, so the browser check and a stand-alone probe can share one implementation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012eisRQmQvg4TphwztxhQGJ
The browser check now measures what both tests meant on the rendered page
(scripts/figure_theme_contract.mjs). Planting each bug they targeted in
site.css and its served copy fails the rendered check; two of those plants
passed one of the text tests:
- test_dark_mode_recolours_marginalia_figures_through_tokens asserted
"--fig-ink" appears after the dark media query. "--fig-ink-soft" also
matches, so deleting the dark --fig-ink passed it, while the page drew
1.26:1 ink on the dark background.
- A chip under another selector (.cell-banner svg { background: ... })
passed both tests; the rendered chip check fails it.
- test_site_css_defines_every_token_in_both_schemes failed when a token
was respelled as the same colour (#521000 to rgb(82 16 0)); the
rendered check compares computed colours and passes.
Neither test held a non-text assertion. FigureThemeTokenContract keeps
test_every_painted_colour_is_a_token_reference, and the docs that cited
Contract 15 as a site.css check now point at the rendered check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012eisRQmQvg4TphwztxhQGJ
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
#19 added two tests that read
public/site.cssas text, the kind #20 replaced with rendered-style checks. This PR moves what they meant into the browser check and deletes them.What changed
New
scripts/figure_theme_contract.mjs, called byscripts/check_browser_layout.mjsin light and dark. On the rendered values page it measures:FIGURE_TOKENS_LIGHT/FIGURE_TOKENS_DARK(imported fromsrc/marginalia_grammar.pythroughuv) resolves to a colour on the figures, and equals the documented colour. Colours are compared as the browser computes them, not as they are spelled;var(--fig-*)token paints that token's colour;Measure rendered styles in the browser, smoke-test deploys, warn before waivers expire #20's three figure checks (ink contrast, chip, ink recolour) moved into the module unchanged in meaning. The recolour check now covers all 13 painted strokes and fills, not only the first ink stroke.
Deleted
tests/test_app.py::DarkModeAndAccessibilityTests::test_dark_mode_recolours_marginalia_figures_through_tokensandtests/test_marginalia_geometry.py::FigureThemeTokenContract::test_site_css_defines_every_token_in_both_schemes. Neither held a non-text assertion.FigureThemeTokenContractkeepstest_every_painted_colour_is_a_token_reference.The rubric and the visual-explainer spec cited "Contract 15" as a
site.csscheck; they now point at the rendered check. The README's list of what the browser test measures gains figure colours.Where each assertion moved
--fig-ink,--fig-ink-soft,--fig-accent,--fig-softappears after@media (prefers-color-scheme: dark)--figure-paperappears nowhere.cell-banner figure svgrule in the dark blockname: value;text for every grammar token, in the light part and in the dark partThe values page never paints
--fig-accent. So the module reads every token the grammar documents, not only the painted ones, and plant 3 below shows that this is what catches it.Planted-bug proofs
Each bug was planted in
public/site.cssand in the served, byte-identical copypublic/site.32ce5906d3c1.css(what a rebuild would serve).curlagainst the local Worker confirmed the plant was being served. Both old tests (still present at commit f897746) and the rendered check were then run, the files were restored withgit checkout, andgit diff --quietand the served CSS confirmed the restore after every plant.--fig-ink--fig-inkisrgb(82, 16, 0), grammar documentsrgb(243, 231, 220); 9 of 13 strokes/fills kept their light colour--fig-soft--fig-softis the light value; 1 of 13 fills kept its light colour--fig-accent(not painted on this page)--fig-accentisrgb(255, 72, 1), grammar documentsrgb(255, 107, 46):rootloses--fig-ink--fig-inkdoes not resolve; 9 strokes/fills off-token (strokes paintnone, fillsrgb(0, 0, 0)); ink contrast undefined--fig-ink-softdrifts torgba(82, 16, 0, 0.55)--fig-ink-softisrgba(82, 16, 0, 0.55), not the documentedrgba(82, 16, 0, 0.7)--figure-paperplus the dark.cell-banner figure svg, .journey-section-figure svg { … background: var(--figure-paper) })rgb(245, 241, 235).cell-banner svg { background: #F5F1EB; }--fig-ink: #521000respelledrgb(82 16 0)Plant 1 is a real gap: old test A's
assertIn("--fig-ink", dark_block)also matches--fig-ink-soft, so it could never catch a missing dark ink. The clean page passes the rendered check: all four tokens match the grammar in both themes, ink contrast is 13.03:1 light and 15.18:1 dark, and no chip appears.How the proofs ran.
make browser-layout-testdid not become ready in this container. The values page never getswindow.pythonByExampleEditor/.cm-content, because CodeMirror loads from esm.sh, which this container's Chromium cannot reach; the same thing happened on 2026-10-10 and 2026-10-11. So the proofs used a throwaway probe, not committed. It loads/examples/valuesthrough the local Worker (pywrangler dev --port 9696) and waits up to 60 s for server-rendered content only. It then importsscripts/figure_theme_contract.mjsand runs the same measurement andfigureThemeFailures()thatcheck_browser_layout.mjsruns, in light and then emulated dark, at the same 390×1800 viewport. The full browser check is left to GitHub CI's Chrome.Local verification (CI=true)
Run with the local Worker up on port 9696, at head 85c2da1:
npm audit --audit-level=high: pass (0 vulnerabilities)git diff --exit-code -- pylock.toml: passmake -k verify: every target passes exceptbrowser-layout-test. That includes 231 unit tests, verify-examples (109), all quality checks,search-ranking-test, ruff andcheck-generated.browser-layout-testfails at the known readiness step (CDN editor never loads here). It got that far only after the new top-leveldocumentedFigureTokens()call had already runuvsuccessfully.scripts/format_examples.py --check: passmake verify-python-version VERSION=3.13: pass (109 verified)git diff --check: passGitHub CI's Chrome runs the full
browser-layout-test, new checks included.🤖 Generated with Claude Code
https://claude.ai/code/session_012eisRQmQvg4TphwztxhQGJ
Generated by Claude Code