Repository navigation
Conversation
…contracts Figures paint with --fig-* CSS tokens instead of literal colours, so one paint function renders in light mode, dark mode, the gestalt pages and the social cards; the dark-mode paper chip is gone. Figure fonts follow the page's own stacks and mono runs are pinned to MONO_ADVANCE with textLength. Paired figures share a baseline through a two-row subgrid. Redraw five figures as mechanisms carrying the lesson's own values: closures as an environment diagram, generators as three next() ribbons on countdown(3), the format spec as a real railroad, bytes as integer slots with the in-place write, and the regex figure as capture groups landing on "Ada: 10". Binding figures come from one parametrised factory so variables and constants show their own names. Fix nine arrows shorter than the new 20-unit minimum, drop the accent from five selector figures where it marked an arbitrary row, and demote four table-shaped figures (values, literals, logging, collections-module) with recorded rationales. Three new contracts: figure text must match the example source (no doubled backslashes; escape sequences must appear in the source), every arrow is at least ARROW_MIN, and site.css defines every figure token in both schemes. The bytes figure had shipped doubled backslashes and bytes the example never used, and the regex figure a pattern it never used; no geometry contract could see either. Rubrics gain a table gate, a zero-accent rule and a placement-honesty note; the synthesis and queue live in docs/diagram-upgrade-plan.md. Fixes #18 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
scripts/build_figure_contact_sheet.py renders every attached figure from a base revision and the working tree, keeps the rows whose drawing changed once colour, font and text-length attributes are ignored, and captures the sheet in both colour schemes through the existing headless-Chrome script. docs/pr-evidence gains the light and dark sheets for the diagram upgrade. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…re the redraws Restore figures on the four pages the previous commit left with a rationale instead of a drawing: values and logging are redrawn as mechanisms (the cell's text → str binding with the type() hop; the cell's three records crossing the handler's INFO gate), and literals and collections-module keep their tables at 8.5 until a mechanism replaces them. The no_figure_rationales registry is empty again and the rubric now says a weak figure is redrawn, not removed. Lighten the format-spec railroad from 53 elements to 35 by drawing bypass rails only over the stations the cell's 05.1f skips. Drop the "text" tag from the regex figure. Anchor the bytes figure to the cell that mutates packet. Score every changed figure criterion by criterion against the v2 rubric, record the totals and the losing criteria in the registry, and add a fresh rubric audit snapshot with the per-criterion table. Group the contact sheet into redrawn and adjusted rows with a note under each, so the eight drawings that need judgement are separated from the eleven that need a glance. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…estly Values lists only upper(), the method the example calls; generators shows the two next() calls the cell makes, not three; the railroad names its station precision, as the format-spec mini-language does. Three more figures drew values their example never computes and are redrawn from the cell: recursion shows the example's tree at the deepest frame of total(tree) with each frame's return value (it drew factorial(3)); dicts shows the cell's keys hashed to slots with the insert of "year" (it drew keys a to d and a collision); sentinel iteration shows read_chunk yielding "py" and "thon" and stopping on "" (it drew iter(read, '')). Format-spec and regex move from 9.5 to 9.0: the review called them the densest redraws, and the scores now say the same. The audit snapshot's per-criterion table covers all fourteen changed figures. The contact sheet classes a row as redrawn when its labels change, not only when its element count does; the spec's CSS sample uses max-width as its own invariant requires; the prototypes docstring describes the banner layout that ships. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
What
Every figure paints with the page's colour tokens and fonts, ten figures are redrawn as mechanisms built from their own cell's values, and three new contracts check figure content, arrow length and theme tokens.
Why
Fixes #18. The
bytes-and-bytearrayfigure renderedb'\\x63\\x61\\x66'with doubled backslashes, and those bytes never appear in the example. It shipped because every figure contract measures geometry and none reads a label. A review of the whole library (docs/diagram-upgrade-plan.md) found the same pattern elsewhere: theregular-expressionsfigure drew a pattern the example never uses,recursiondrewfactorial(3)on a page that sums a tree,dictsdrew keysatodand a collision on a page whose dict holdsnameandlanguage, andsentinel-iterationdrew placeholder chunks. Beyond content: figures hard-coded the light palette and sat on cream chips in dark mode; the SVG asked for JetBrains Mono and Source Sans while the page loads no web fonts; nine arrows were mostly arrowhead; and five selector figures put the accent on whichever row a loop reached last.How
Grammar.
INK,INK_SOFT,EMPHASISandSOFT_FILLarevar(--fig-*)references, andpublic/site.cssdefines the four tokens for light and dark, so one paint function renders in both schemes and the dark-mode chip goes away. Mono and sans faces follow the page's stacks, and each mono run carriestextLengthso divider maths holds on any platform.ARROW_MINis 20 units. A newenvphrase draws an environment frame with bindings.Figures, each from its cell's own values. Closures: an environment diagram, the returned frame ghosted, one live
__closure__reference. Generators: the cell's twonext()calls oncountdown(3), one ribbon each, the survivingnbeside each. Format spec: a railroad tracing the cell's05.1f, skipped stations ghosted under bypass rails. Bytes: the example's two bytes as integer slots withpacket[0] = ord("P"), anchored to the cell that performs it. Regex: the cell's two capture groups dropped ontoAda: 10. Values:textbound to astrobject and thetype()hop to whereupper()lives. Logging: the cell's three records crossing the handler's INFO gate. Recursion: the example's tree at the deepest frame oftotal(tree), with each frame's return value. Dicts: the cell's keys hashed to slots, the insert of"year"accented. Sentinel iteration:read_chunkyielding"py"and"thon"and stopping on"". The binding figure is a factory, sovariablesandconstantsshow their own names. Nine arrows were lengthened and five arbitrary accents removed.Alternatives considered. An earlier commit removed the four table-shaped figures (
values,literals,logging,collections-module) and recorded a rationale for each. Review of the branch showed that a page with a paragraph about a better picture has less than a page with the old picture, sovaluesandloggingwere redrawn andliteralsandcollections-modulekeep their tables at 8.5. The railroad was first drawn with a bypass rail over all seven stations (53 elements); it now traces one path with bypass rails only over the three stations05.1fskips. A library-wide check found 54 of 115 attachments carrying a code-like label absent from their example; most are formatting drift or placeholders the rubric allows, and the three that drew values the example never computes are redrawn here. The rest are queued.Contracts. 13: no rendered text carries a doubled backslash, and an escape sequence in an attached figure must appear in that example's source. 14: every arrow is at least
ARROW_MIN. 15:site.cssdefines all four tokens in both schemes with the grammar's values, and every grammar colour is a token reference.Docs. Both rubrics say a weak figure is redrawn rather than removed, a figure whose caption names no single element carries no accent, and how cell-0 anchors are scored.
docs/rubric-audit-2026-09-27.mdscores every changed figure criterion by criterion.Testing
FigureContentContract,FigureArrowLengthContractandFigureThemeTokenContractintests/test_marginalia_geometry.py.main: withmain'ssrc/marginalia.pyandpublic/site.cssswapped in, Contract 13 reports the two doubled-backslash labels (its escape-sequence check errors instead, because the branch registry names figuresmaindoes not define), Contract 14 reports the short arrows, and Contract 15 reports the missing tokens. With the branch files restored all three pass.make lint,make quality-checksandmake check-generatedpass; 120 social cards regenerated with provenance checked.src.app.routeon a local HTTP wrapper and captured withscripts/capture_browser_screenshot.mjsin dark mode; one social card was inspected for token colours.make devneeds Node 22, which the authoring machine lacks, so the Worker runtime and the POST runner were not exercised; neither is touched by this change.check-pr-readiness.pyfrom the good-pr skill warns about diff size (most of it regenerated gestalt pages and the social-card manifest) and about print statements; the only new prints are progress lines inscripts/build_figure_contact_sheet.py.Visual evidence
Claim: every changed figure is a drawing of the mechanism the cell describes, using the cell's own values, and renders in both colour schemes without a paper chip.
Input/fixture: every
[[figure_attachments]]and[[journey_section_figures]]entry indocs/quality-registries.toml, rendered bysrc/marginalia.pyat both revisions; rows whose drawing is unchanged once colour, font andtextLengthattributes are ignored are omitted.Baseline SHA:
3f300af0562bc6c0b0a0f41ead7ed02a0b147e7bCurrent SHA:
fb7c0b390d7b5c0804cf2182be3795aededcf3b7Regenerate:
uv run --python 3.13 scripts/build_figure_contact_sheet.py --base main --output docs/pr-evidence/diagram-upgrade-contact-sheet --notes docs/pr-evidence/diagram-upgrade-contact-sheet-notes.jsonIndependent check:
tests/test_marginalia_geometry.pyasserts no clipping, no collisions, palette and font discipline, at most one accent, content fidelity, arrow length and token presence for every figure at the head SHA. Hashes for both sheets are indocs/pr-evidence/README.md.Limitation: the sheets are rendered at one width with macOS fonts and do not show phone-width banners, the subgrid caption alignment on a paired banner, or the About page token list. Whether a redrawn figure is clearer than the one it replaces is a judgement; the per-criterion scores below are mine and the reviewer should form their own.
Legibility review
Scored against
docs/example-figure-rubric.mdv2; full per-criterion rows indocs/rubric-audit-2026-09-27.md.type(text).__name__debugmissingEach redraw is one paint function in
src/marginalia.pyplus one caption row in the registry, so any one of them reverts alone without touching the tokens, fonts or contracts.Risk
textLength), so every social card was regenerated. An HTML shell that embeds a figure without defining the tokens would render it in the browser's default black; Contract 15 coverssite.css, and the gestalt and social-card shells embed the tokens throughfigure_token_css().grid-template-rows: subgridon.cell-banner figureneeds Chrome 117, Safari 16 or Firefox 71. Older browsers ignore it and render the banner as before, without caption alignment.textLengthwithlengthAdjust="spacing"adds up to 0.05em of letter-spacing on monospace faces narrower than 0.6em, such as Consolas. Wider faces are compressed by the same mechanism; none in the stack is wider.Not in this PR
The queue in
docs/diagram-upgrade-plan.md: state-over-time drawings for context managers and decorators,envfor scope and recursion, mechanisms for the two remaining table figures, parametrising the other reused figures, moving anchors to the cell where the move happens, the wider content check across the 51 remaining attachments with labels absent from their example, and a pairwise ranking to replace the saturated score.🤖 Generated with Claude Code