Skip to content

Commit b259e84

Browse files
committed
Align diagrams with examples and journeys
1 parent ce4a598 commit b259e84

5 files changed

Lines changed: 152 additions & 117 deletions

File tree

docs/lessons-learned.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,20 @@ git diff --check
9393
- **Emphasis is scarce.** With site `--accent` saturated for UI use, a coral arrow on every line reads as no emphasis at all. `closed_arrow` defaults to `emphasis=False`; figures opt in only for the single element the prose names. Same rule for accent dots, gates, and ring highlights.
9494
- **Soft fills should be neutral, not accent-tinted.** A 5% warm-brown tint reads as a quiet container. An accent-tinted soft fill makes every object box look highlighted, which breaks the scarcity rule a second way.
9595
- **Two rubrics, one craft section.** Journey-section figures depict a *conceptual shift* across multiple lessons; example-cell figures depict the *single move* the surrounding cell discusses. `docs/journey-visualisation-rubric.md` and `docs/example-figure-rubric.md` score each on 10 points: content fidelity, craft, context. Topic gates per kind of section / cell shape.
96-
- **Constraint-shaped sections resist mechanism figures.** Workers' "Preserve the lesson while respecting the runtime" is a principle, not a mechanism. Forcing figures on such sections scores below the 8.5 gate. Either reframe the section around a mechanism or accept the gap deliberately.
96+
- **Constraint-shaped sections can improve when the constraint is drawn as a boundary, not a caveat.** Workers' runtime sections originally scored below target when the figure merely said an API was unavailable. They became rubric-complete once the diagrams showed the standard Python contract, the Worker boundary, and the portable evidence that preserves the lesson. If a constraint-shaped section cannot be reframed this way, then use the no-figure rationale registry instead of shipping a weak mechanism picture.
9797
- **Authoring stays on the contributor; figures stay on the curator.** Example markdown does not include figure references. `src/marginalia.py` holds `FIGURES` (paint functions) and `ATTACHMENTS` (slug → cell → figure → caption). Curating figures is a single-file edit that contributors never see.
9898
- **Inline between prose and code is the production layout; banners between cells is the prototyped richer grammar.** Cells with figures drop to single-column stacking (prose, figure, code) via `.lp-cell.has-figure { grid-template-columns: 1fr }`. Cells without figures keep today's `prose | code` 2-column grid bit-for-bit. The banner-between approach (`/prototyping/layout-banner-*`) supports multi-figure small-multiples between cells when one inline figure isn't enough.
9999
- **Centralised gestalt pages catch drift that page-by-page review misses.** `/prototyping/marginalia-gestalt`, `/prototyping/journey-figures-gestalt`, and `/prototyping/production-figures-gestalt` show every figure in three different framings. Seeing all section figures of a journey in one 3-up row exposes inconsistencies invisible across six tabs.
100100
- **Mapping reuses existing figures; promoting moves design to production.** Half of example coverage came from attaching existing FIGURES to new examples (no paint code). The other half from new paint code copied or designed from gestalt cards. Both paths must pass the rubric.
101101
- **Tests against the cell layout must allow the `has-figure` class.** When the renderer adds `has-figure` to cells with attached figures, assertions on the literal string `class="lesson-step lp-cell"` fail. Change those tests to check the substring `lesson-step lp-cell` so both variants match.
102102
- **Score what's shipping, not what was designed.** A scoring dict on the gestalt is design-time review. Production figures live in `src/marginalia.py` `FIGURES` and may have been redesigned during promotion. Scoring should track the production version with the gestalt as separate history.
103+
- **Semantic diagram review has four objects: page, cell, paint function, caption.** Geometry contracts can prove that a figure renders, but not that it still teaches the adjacent cell. On every diagram pass, read the current example cell, the attached paint function, the caption, and the score rationale together. The same audit caught `container-protocols` still showing `iter()/next()` after the page had shifted to `__setitem__`/`__contains__`/`__getitem__`, `structured-data-shapes` over-focusing on `TypedDict` while anchored to a dataclass cell, and `object-lifecycle` mentioning `__del__` after the lesson had been reframed around references.
103104
- **Some examples should never have figures.** Constraint-shaped, infrastructure-shaped, and aggregator-shaped slugs lack a single mechanism to depict. Force-fitting figures on them scores below the gate. Leave them figure-less and document why rather than ship weak figures.
104105
- **Audits without contracts rot; bug classes need automated gates.** When you find a bug class — clipping, collision, off-palette colour, drifting twin coordinates, duplicate caption — write a unit test that asserts the invariant across every figure. The geometry contracts in `tests/test_marginalia_geometry.py` started as ad-hoc scripts and were promoted to CI gates after the same bug class recurred. 54 tests today cover 9 contract families; new figures pass them automatically because each test iterates `FIGURES`.
105106
- **Clipping ≠ collision; padding the viewBox fixes one but not the other.** The `value-types` bug had two components: the first `INT` tag was clipped above the viewBox (geometry escapes its frame), and the `STR`/`LIST`/`DICT` tags overlapped the boxes above them (geometry collides internally). Padding the viewBox solved (1) and disguised (2). Element-element collision needs its own audit that walks every text-rect, text-text, and (for label-on-edge cases) text-line bounding-box pair.
106107
- **Heuristic audits over-flag; trust the design, not the regex.** Probes for "prose duplication" (SVG text matching caption substring), "text crossing a line" (label bbox bisected by a hairline), and "text overlapping a circle" each surfaced ~3-10 hits — all false positives. Diagrammatic labels naturally appear in captions (`__getattr__`, `yield from inner`); dashed strikes through `.append` are deliberate; text inside node circles is the design. Don't promote heuristic findings to contracts without confirming each is a real bug.
107108
- **Structural twins must share coordinates exactly.** When two figures depict parallel concepts — `kw-only-separator` and `positional-only-separator`, `class-triangle` and `metaclass-triangle` — they read as a pair. A single-pixel drift in one breaks the visual rhyme. Treat a coordinate change in one as a forced change in both, in the same commit. The audit caught `kw-only-separator` at the old `x=82` after `positional-only-separator` had moved to the corrected `x=75`.
108-
- **Reused figure → bespoke caption per slug.** The 8 library figures (`iter-protocol` across 4 iteration slugs, `aliasing-mutation` across mutability + copying-collections, etc.) shouldn't all carry the same caption. Each slug is a separate lesson; the figure stays, the framing changes. `FigureCaptionContract` enforces uniqueness across slugs after one verbatim duplicate slipped through.
109+
- **Reused figure → bespoke caption per slug, and revalidate reuse after page rewrites.** The 8 library figures (`iter-protocol` across iteration slugs, `aliasing-mutation` across mutability + copying-collections, etc.) shouldn't all carry the same caption. Each slug is a separate lesson; the figure stays, the framing changes. But reuse also has an expiry date: if the page's teaching cell changes topic, the old reusable figure may become semantically wrong even while tests pass. `FigureCaptionContract` enforces uniqueness; semantic review enforces fit.
109110
- **One paint registry, not two.** The marginalia-gestalt review page once rendered its own `e_*` paint functions parallel to `src/marginalia.py FIGURES`. Reviewers saw a different picture than readers, and the gestalt's bugs (overlapping labels, misaligned dashed lines) didn't ship. The gestalt is now a thin view over production: same paint, same drift surface, same audit coverage. 862 lines of duplicated paint code went away.
110111
- **Tag-above vs tag-inside is a layout decision driven by stacking.** `object_box(tag_position="above")` is natural for an isolated box; `tag_position="inside"` is required when boxes stack vertically with less than ~13px of gap (the tag's footprint). Defaults to `"above"` for the common isolated case; stacked callers opt in. The grammar carries the choice, not the caller's hand-positioned `tag()` call.
111112
- **Mono character alignment uses the font's advance, not eyeballed pixels.** JetBrains Mono advances ~6px per char at fs=10. A dashed line marking the `/` at index 12 of `def f(a, b, /, c, d): …` lives at `x=12*6+3=75`, not `x=82`. Hand-tuned positions drift; computed positions match the rendered glyph.

docs/quality-registries.toml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -597,18 +597,6 @@ outcomes = [
597597
"show cleanup boundaries that still apply when resources are represented abstractly",
598598
]
599599

600-
[journey_section_improvement_backlog."Replace unavailable process boundaries with portable evidence."]
601-
cause = "Workers section is constraint-shaped; the figure scores 8.0 because the section names an unavailable OS boundary more than a positive mechanism."
602-
next_action = "Reframe around portable evidence: captured output and in-process assertions preserve the subprocess/thread lesson when OS processes cannot run."
603-
604-
[journey_section_improvement_backlog."Keep network lessons local to the protocol boundary."]
605-
cause = "Workers section is constraint-shaped; the figure must carry protocol evidence rather than merely saying sockets are unavailable."
606-
next_action = "Reframe around request/response bytes and local protocol parsing, with standard socket usage shown once as the external boundary."
607-
608-
[journey_section_improvement_backlog."Preserve the lesson while respecting the runtime."]
609-
cause = "This is a principle rather than a mechanism, which lessons-learned identifies as resistant to strong figures."
610-
next_action = "Either split into concrete mechanisms or explicitly mark the section as principle-shaped with a no-strong-figure rationale."
611-
612600
[score_model]
613601
# Criterion weights mirror docs/example-quality-rubric.md. The registry
614602
# makes the scoring model inspectable even before every example is broken

scripts/check_quality_scores.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ def main() -> int:
9797
if title not in SECTION_FIGURE_SCORES:
9898
errors.append(f"journey section backlog for unknown section: {title}")
9999
continue
100+
score = SECTION_FIGURE_SCORES[title][0]
101+
if score >= section_min:
102+
errors.append(f"journey section backlog {title} is stale because score is now {score:.1f}")
100103
if not _entry_has_text(section_backlog[title], "cause", "next_action"):
101104
errors.append(f"journey section backlog {title} must include cause and next_action")
102105

src/asset_manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Generated by scripts/fingerprint_assets.py. Do not edit by hand.
22
ASSET_PATHS = {'SITE_CSS': '/site.57a55415849b.css', 'SYNTAX_JS': '/syntax-highlight.3b6c7f730d46.js', 'EDITOR_JS': '/editor.a4a7766e1b9b.js'}
3-
HTML_CACHE_VERSION = '2e6da1f2a673'
3+
HTML_CACHE_VERSION = '06dc2d833a37'

0 commit comments

Comments
 (0)