Skip to content

Commit 63f3c30

Browse files
committed
Fifth pass: lift 5 figures off the 8.0 reuse floor; tighten workers s3
Five attached figures had been sharing a more general image, which scored 8.0 against the example-figure rubric's "match the running variables" criterion. Each now gets a slug-specific figure: typed-dicts union-types → typed-dict-shape (already existed for structured-data-shapes; fits typed-dicts identically) type-aliases annotation-ghost → type-alias-name (new: complex annotation collapses to a name) match-statements branch-fork → match-dispatch-ladder (new: value flows down patterns, first match wins) advanced-match-patterns branch-fork → match-pattern-variants (new: capture / alternative / guard / class rows) loop-else early-exit → loop-else-gate (new: fell through vs broke, two outcomes) The Workers journey section "Preserve the lesson while respecting the runtime" was the only journey-section figure scoring 7.5. Redesigned to depict the real mechanism: a lesson question forks two ways — a ghost process-API path (struck through) and a live captured-output path (emphasis). The lesson preserves its question by taking the live path. Should lift the score off the 7.5 floor toward 8.5. Figure registry: 103 → 107. Coverage unchanged at 109/109. 39 tests pass. https://claude.ai/code/session_01MazwoRWAihW6dwso3fMCHE
1 parent ecce666 commit 63f3c30

5 files changed

Lines changed: 70 additions & 14 deletions

File tree

public/prototyping/journey-figures-gestalt.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

public/prototyping/journey-workers.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
<h1>Workers</h1>
3838
<p class="meta">This journey explains the examples that were adapted so they can teach operating-system boundaries while still running inside Cloudflare Dynamic Workers.</p>
3939
</section>
40-
<section class="journey-section"><div><h2>Replace unavailable process boundaries with portable evidence.</h2><p class="meta">Dynamic Workers run Python in a constrained runtime, so examples cannot assume child processes, shell commands, or project-local virtual environments are available.</p><ul class="journey-list"><li><a class="text-link journey-item-title" href="/examples/virtual-environments">Virtual Environments</a><p class="meta">report stable environment facts instead of creating or depending on a local virtual environment</p></li><li><a class="text-link journey-item-title" href="/examples/subprocesses">Subprocesses</a><p class="meta">show the command and `CompletedProcess` result shape</p></li><li><a class="text-link journey-item-title" href="/examples/threads-and-processes">Threads and Processes</a><p class="meta">compare thread and process executor boundaries</p></li></ul></div><figure class="journey-figure"><svg viewBox="0 0 222 84" width="222" height="84" xmlns="http://www.w3.org/2000/svg"><text x="0" y="4" font-family="-apple-system, 'Source Sans Pro', sans-serif" font-size="8" fill="rgba(82, 16, 0, 0.7)" text-anchor="start" letter-spacing="0.5">UNAVAILABLE</text><rect x="0" y="12" width="180" height="22" fill="none" stroke="#521000" stroke-width="0.5" opacity="0.4"/><text x="90.0" y="27.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">multiprocessing.Process()</text><line x1="0" y1="24" x2="180" y2="24" stroke="#521000" stroke-width="0.6" stroke-dasharray="2 2"/><text x="0" y="50" font-family="-apple-system, 'Source Sans Pro', sans-serif" font-size="8" fill="rgba(82, 16, 0, 0.7)" text-anchor="start" letter-spacing="0.5">PORTABLE EVIDENCE</text><rect x="0" y="58" width="60" height="22" fill="rgba(82, 16, 0, 0.05)" stroke="#521000" stroke-width="1.0"/><text x="30.0" y="73.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">value</text><line x1="60" y1="69" x2="93.0" y2="69.0" stroke="#FF4801" stroke-width="1.4"/><polygon points="100,69 93.0,71.8 93.0,66.2" fill="#FF4801"/><rect x="102" y="58" width="120" height="22" fill="none" stroke="#521000" stroke-width="1.0"/><text x="162.0" y="73.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">asserted in-process</text></svg><figcaption>Worker isolation breaks the usual cross-process pathways; the lesson preserves a captured value as portable evidence instead.</figcaption></figure></section><section class="journey-section"><div><h2>Keep network lessons local to the protocol boundary.</h2><p class="meta">Workers should not open arbitrary low-level sockets, so the networking example teaches addresses, protocol constants, and bytes without making an outbound connection.</p><ul class="journey-list"><li><a class="text-link journey-item-title" href="/examples/bytes-and-bytearray">Bytes and Bytearray</a><p class="meta">show the text-to-bytes boundary that networking and subprocess APIs usually require</p></li><li><a class="text-link journey-item-title" href="/examples/networking">Networking</a><p class="meta">make endpoint and byte-encoding boundaries visible without opening a socket</p></li><li><a class="text-link journey-item-title" href="/examples/async-await">Async Await</a><p class="meta">show the supported coroutine model for I/O-shaped work in this environment</p></li></ul></div><figure class="journey-figure"><svg viewBox="0 0 144 110" width="144" height="110" xmlns="http://www.w3.org/2000/svg"><text x="0" y="4" font-family="-apple-system, 'Source Sans Pro', sans-serif" font-size="8" fill="rgba(82, 16, 0, 0.7)" text-anchor="start" letter-spacing="0.5">REQUEST SHAPE</text><rect x="0" y="12" width="140" height="22" fill="none" stroke="#521000" stroke-width="1.0"/><text x="70.0" y="27.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">GET /resource</text><line x1="70" y1="38" x2="70.0" y2="49.0" stroke="#FF4801" stroke-width="1.4"/><polygon points="70,56 67.2,49.0 72.8,49.0" fill="#FF4801"/><text x="0" y="76" font-family="-apple-system, 'Source Sans Pro', sans-serif" font-size="8" fill="rgba(82, 16, 0, 0.7)" text-anchor="start" letter-spacing="0.5">RESPONSE SHAPE · ASSERTED LOCALLY</text><rect x="0" y="84" width="140" height="22" fill="none" stroke="#521000" stroke-width="1.0"/><text x="70.0" y="99.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">200 OK · { … }</text></svg><figcaption>Demonstrate the protocol shape (request and response) rather than calling out over the network.</figcaption></figure></section><section class="journey-section"><div><h2>Preserve the lesson while respecting the runtime.</h2><p class="meta">The changed examples favor deterministic, editable evidence over fake demonstrations of unavailable operating-system features.</p><ul class="journey-list"><li><a class="text-link journey-item-title" href="/examples/logging">Logging</a><p class="meta">show operational output through a configurable Python API rather than shell output</p></li><li><a class="text-link journey-item-title" href="/examples/testing">Testing</a><p class="meta">capture test-runner output so the page remains deterministic</p></li><li><a class="text-link journey-item-title" href="/examples/context-managers">Context Managers</a><p class="meta">show cleanup boundaries that still apply when resources are represented abstractly</p></li></ul></div><figure class="journey-figure"><svg viewBox="0 0 200 46" width="200" height="46" xmlns="http://www.w3.org/2000/svg"><rect x="0" y="4" width="80" height="36" fill="none" stroke="#521000" stroke-width="1.0"/><text x="6" y="1" font-family="-apple-system, 'Source Sans Pro', sans-serif" font-size="8" fill="rgba(82, 16, 0, 0.7)" text-anchor="start" letter-spacing="0.5">LESSON</text><text x="40" y="26" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">shape</text><rect x="120" y="4" width="80" height="36" fill="none" stroke="#521000" stroke-width="1.0"/><text x="126" y="1" font-family="-apple-system, 'Source Sans Pro', sans-serif" font-size="8" fill="rgba(82, 16, 0, 0.7)" text-anchor="start" letter-spacing="0.5">RUNTIME</text><text x="160" y="26" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">limits</text><line x1="80" y1="22" x2="113.0" y2="22.0" stroke="#FF4801" stroke-width="1.4"/><polygon points="120,22 113.0,24.8 113.0,19.2" fill="#FF4801"/><text x="100" y="22" font-family="-apple-system, 'Source Sans Pro', sans-serif" font-size="9" fill="rgba(82, 16, 0, 0.7)" text-anchor="middle">value</text></svg><figcaption>The lesson&#x27;s evidence survives across the boundary that the worker runtime enforces.</figcaption></figure></section>
40+
<section class="journey-section"><div><h2>Replace unavailable process boundaries with portable evidence.</h2><p class="meta">Dynamic Workers run Python in a constrained runtime, so examples cannot assume child processes, shell commands, or project-local virtual environments are available.</p><ul class="journey-list"><li><a class="text-link journey-item-title" href="/examples/virtual-environments">Virtual Environments</a><p class="meta">report stable environment facts instead of creating or depending on a local virtual environment</p></li><li><a class="text-link journey-item-title" href="/examples/subprocesses">Subprocesses</a><p class="meta">show the command and `CompletedProcess` result shape</p></li><li><a class="text-link journey-item-title" href="/examples/threads-and-processes">Threads and Processes</a><p class="meta">compare thread and process executor boundaries</p></li></ul></div><figure class="journey-figure"><svg viewBox="0 0 222 84" width="222" height="84" xmlns="http://www.w3.org/2000/svg"><text x="0" y="4" font-family="-apple-system, 'Source Sans Pro', sans-serif" font-size="8" fill="rgba(82, 16, 0, 0.7)" text-anchor="start" letter-spacing="0.5">UNAVAILABLE</text><rect x="0" y="12" width="180" height="22" fill="none" stroke="#521000" stroke-width="0.5" opacity="0.4"/><text x="90.0" y="27.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">multiprocessing.Process()</text><line x1="0" y1="24" x2="180" y2="24" stroke="#521000" stroke-width="0.6" stroke-dasharray="2 2"/><text x="0" y="50" font-family="-apple-system, 'Source Sans Pro', sans-serif" font-size="8" fill="rgba(82, 16, 0, 0.7)" text-anchor="start" letter-spacing="0.5">PORTABLE EVIDENCE</text><rect x="0" y="58" width="60" height="22" fill="rgba(82, 16, 0, 0.05)" stroke="#521000" stroke-width="1.0"/><text x="30.0" y="73.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">value</text><line x1="60" y1="69" x2="93.0" y2="69.0" stroke="#FF4801" stroke-width="1.4"/><polygon points="100,69 93.0,71.8 93.0,66.2" fill="#FF4801"/><rect x="102" y="58" width="120" height="22" fill="none" stroke="#521000" stroke-width="1.0"/><text x="162.0" y="73.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">asserted in-process</text></svg><figcaption>Worker isolation breaks the usual cross-process pathways; the lesson preserves a captured value as portable evidence instead.</figcaption></figure></section><section class="journey-section"><div><h2>Keep network lessons local to the protocol boundary.</h2><p class="meta">Workers should not open arbitrary low-level sockets, so the networking example teaches addresses, protocol constants, and bytes without making an outbound connection.</p><ul class="journey-list"><li><a class="text-link journey-item-title" href="/examples/bytes-and-bytearray">Bytes and Bytearray</a><p class="meta">show the text-to-bytes boundary that networking and subprocess APIs usually require</p></li><li><a class="text-link journey-item-title" href="/examples/networking">Networking</a><p class="meta">make endpoint and byte-encoding boundaries visible without opening a socket</p></li><li><a class="text-link journey-item-title" href="/examples/async-await">Async Await</a><p class="meta">show the supported coroutine model for I/O-shaped work in this environment</p></li></ul></div><figure class="journey-figure"><svg viewBox="0 0 144 110" width="144" height="110" xmlns="http://www.w3.org/2000/svg"><text x="0" y="4" font-family="-apple-system, 'Source Sans Pro', sans-serif" font-size="8" fill="rgba(82, 16, 0, 0.7)" text-anchor="start" letter-spacing="0.5">REQUEST SHAPE</text><rect x="0" y="12" width="140" height="22" fill="none" stroke="#521000" stroke-width="1.0"/><text x="70.0" y="27.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">GET /resource</text><line x1="70" y1="38" x2="70.0" y2="49.0" stroke="#FF4801" stroke-width="1.4"/><polygon points="70,56 67.2,49.0 72.8,49.0" fill="#FF4801"/><text x="0" y="76" font-family="-apple-system, 'Source Sans Pro', sans-serif" font-size="8" fill="rgba(82, 16, 0, 0.7)" text-anchor="start" letter-spacing="0.5">RESPONSE SHAPE · ASSERTED LOCALLY</text><rect x="0" y="84" width="140" height="22" fill="none" stroke="#521000" stroke-width="1.0"/><text x="70.0" y="99.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">200 OK · { … }</text></svg><figcaption>Demonstrate the protocol shape (request and response) rather than calling out over the network.</figcaption></figure></section><section class="journey-section"><div><h2>Preserve the lesson while respecting the runtime.</h2><p class="meta">The changed examples favor deterministic, editable evidence over fake demonstrations of unavailable operating-system features.</p><ul class="journey-list"><li><a class="text-link journey-item-title" href="/examples/logging">Logging</a><p class="meta">show operational output through a configurable Python API rather than shell output</p></li><li><a class="text-link journey-item-title" href="/examples/testing">Testing</a><p class="meta">capture test-runner output so the page remains deterministic</p></li><li><a class="text-link journey-item-title" href="/examples/context-managers">Context Managers</a><p class="meta">show cleanup boundaries that still apply when resources are represented abstractly</p></li></ul></div><figure class="journey-figure"><svg viewBox="0 0 200 46" width="200" height="46" xmlns="http://www.w3.org/2000/svg"><rect x="0" y="22" width="130" height="24" fill="none" stroke="#521000" stroke-width="1.0"/><text x="65.0" y="38.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">lesson question</text><line x1="130" y1="22" x2="154.35516502901007" y2="4.139545645392621" stroke="#521000" stroke-width="1.0"/><polygon points="160,0 156.0109832871671,6.397479633788596 152.69934677085303,1.881611656996646" fill="#521000"/><rect x="162" y="0" width="130" height="20" fill="none" stroke="#521000" stroke-width="0.5" opacity="0.4"/><text x="227.0" y="14.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">process API</text><line x1="162" y1="10" x2="292" y2="10" stroke="#521000" stroke-width="0.6" stroke-dasharray="2 2"/><line x1="130" y1="46" x2="153.3592169136464" y2="53.78640563788213" stroke="#FF4801" stroke-width="1.4"/><polygon points="160,56 152.47377916879927,56.44271887242357 154.24465465849354,51.1300924033407" fill="#FF4801"/><rect x="162" y="50" width="130" height="20" fill="rgba(82, 16, 0, 0.05)" stroke="#521000" stroke-width="1.0"/><text x="227.0" y="64.0" font-family="'JetBrains Mono', 'IBM Plex Mono', Menlo, monospace" font-size="10" fill="#521000" text-anchor="middle">captured output</text></svg><figcaption>The lesson&#x27;s evidence survives across the boundary that the worker runtime enforces.</figcaption></figure></section>
4141
</article>
4242

4343
</body>

public/prototyping/production-figures-gestalt.html

Lines changed: 3 additions & 3 deletions
Large diffs are not rendered by default.

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.489bc3f7eb6d.css', 'SYNTAX_JS': '/syntax-highlight.3b6c7f730d46.js', 'EDITOR_JS': '/editor.dd81f5171b14.js'}
3-
HTML_CACHE_VERSION = '943aba25c847'
3+
HTML_CACHE_VERSION = '36c6cfd73183'

src/marginalia.py

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,57 @@ def object_lifecycle(c: Canvas) -> None:
11601160
c.cell(284, 22, "__del__", w=80, h=24)
11611161

11621162

1163+
# ─── Fifth pass: tightened figures for slugs that were on reuse-floors ─
1164+
1165+
1166+
def type_alias_name(c: Canvas) -> None:
1167+
"""Type aliases · complex annotation collapses to a single readable name."""
1168+
c.cell(0, 30, "dict[str, list[tuple[int, str]]]", w=240, h=24, ghost=True)
1169+
c.closed_arrow(120, 54, 120, 70, emphasis=True)
1170+
c.label(96, 62, "type Index = …", anchor="middle")
1171+
c.cell(80, 76, "Index", w=80, h=24, soft=True)
1172+
1173+
1174+
def match_dispatch_ladder(c: Canvas) -> None:
1175+
"""Match statements · the value flows down the patterns; the first match wins."""
1176+
c.cell(0, 0, "match value", w=170, h=22)
1177+
cases = ["case 0:", "case [x, y]:", "case Point(0, _):", "case _:"]
1178+
for i, txt in enumerate(cases):
1179+
c.cell(0, 30 + i * 22, txt, w=170, h=20)
1180+
c.dashed(186, 32, 186, 122)
1181+
c.dot(186, 74, emphasis=True)
1182+
c.closed_arrow(186, 110, 186, 124, emphasis=True)
1183+
c.label(196, 76, "first match", anchor="start")
1184+
1185+
1186+
def match_pattern_variants(c: Canvas) -> None:
1187+
"""Advanced match patterns · capture, alternative, guard, class — four pattern shapes."""
1188+
rows = [("capture", "[x, y]"), ("alternative", "P() | Q()"), ("guard", "[x] if x > 0"), ("class", "Point(x=0, y=_)")]
1189+
for i, (kind, shape) in enumerate(rows):
1190+
y = i * 22
1191+
c.cell(0, y, kind, w=90, h=20)
1192+
c.cell(92, y, shape, w=180, h=20, soft=(kind == "class"))
1193+
1194+
1195+
def loop_else_gate(c: Canvas) -> None:
1196+
"""Loop else · runs when the loop falls through naturally; break skips it."""
1197+
c.cell(0, 20, "loop body", w=110, h=24)
1198+
c.closed_arrow(110, 20, 150, 0, emphasis=True)
1199+
c.cell(152, 0, "fell through · else runs", w=160, h=20, soft=True)
1200+
c.closed_arrow(110, 44, 150, 56, emphasis=False)
1201+
c.cell(152, 50, "broke · else skipped", w=160, h=20)
1202+
1203+
1204+
def workers_lesson_runtime(c: Canvas) -> None:
1205+
"""Workers · lesson uses captured output as evidence when the runtime forbids the process API."""
1206+
c.cell(0, 22, "lesson question", w=130, h=24)
1207+
c.closed_arrow(130, 22, 160, 0, emphasis=False)
1208+
c.cell(162, 0, "process API", w=130, h=20, ghost=True)
1209+
c.dashed(162, 10, 292, 10)
1210+
c.closed_arrow(130, 46, 160, 56, emphasis=True)
1211+
c.cell(162, 50, "captured output", w=130, h=20, soft=True)
1212+
1213+
11631214
def lazy_stream(c: Canvas) -> None:
11641215
"""Iteration · Compose lazy value streams: filter and map flow values without materialising."""
11651216
c.object_box(0, 26, "source", "[a,b,c]", w=78, h=24)
@@ -1287,6 +1338,11 @@ def lazy_stream(c: Canvas) -> None:
12871338
"csv-records": (csv_records, 212, 96),
12881339
"warning-signal": (warning_signal, 292, 80),
12891340
"object-lifecycle": (object_lifecycle, 366, 60),
1341+
# Fifth pass: slug-specific figures lifting attached scores off the 8.0 floor
1342+
"type-alias-name": (type_alias_name, 240, 104),
1343+
"match-dispatch-ladder": (match_dispatch_ladder, 220, 130),
1344+
"match-pattern-variants": (match_pattern_variants, 272, 96),
1345+
"loop-else-gate": (loop_else_gate, 312, 76),
12901346
}
12911347

12921348

@@ -1472,11 +1528,11 @@ def lazy_stream(c: Canvas) -> None:
14721528
"An iterable knows how to produce an iterator (via iter()); the iterator knows how to produce values (via next()).",
14731529
)],
14741530
"type-aliases": [(
1475-
"cell-0", "annotation-ghost",
1476-
"A type alias names a complex annotation once so call sites read as their domain meaning, not their type composition.",
1531+
"cell-0", "type-alias-name",
1532+
"A type alias names a complex annotation once so call sites read as the domain meaning, not the type composition.",
14771533
)],
14781534
"typed-dicts": [(
1479-
"cell-0", "union-types",
1535+
"cell-0", "typed-dict-shape",
14801536
"TypedDict gives each key a typed value, so `obj['x']` is checked against the declared shape.",
14811537
)],
14821538
"union-and-optional-types": [(
@@ -1643,8 +1699,8 @@ def lazy_stream(c: Canvas) -> None:
16431699
"A predicate sorts a value into one of several branches; if/elif/else is the explicit spelling.",
16441700
)],
16451701
"match-statements": [(
1646-
"cell-0", "branch-fork",
1647-
"match dispatches on the shape of a value to one of several branches; richer than if-elif.",
1702+
"cell-0", "match-dispatch-ladder",
1703+
"match dispatches by pattern shape; the value flows down the patterns and the first match wins.",
16481704
)],
16491705
"assignment-expressions": [(
16501706
"cell-0", "naming-decisions",
@@ -1663,7 +1719,7 @@ def lazy_stream(c: Canvas) -> None:
16631719
"async iteration and async with both rest on the same loop-vs-coroutine handoff as await.",
16641720
)],
16651721
"loop-else": [(
1666-
"cell-0", "early-exit",
1722+
"cell-0", "loop-else-gate",
16671723
"The loop's else branch runs only when the loop falls through naturally; break skips it.",
16681724
)],
16691725
"break-and-continue": [(
@@ -1691,8 +1747,8 @@ def lazy_stream(c: Canvas) -> None:
16911747
"while repeats the body until the condition becomes false; the back-edge returns to the test each pass.",
16921748
)],
16931749
"advanced-match-patterns": [(
1694-
"cell-0", "branch-fork",
1695-
"Capture, guard, OR-pattern, and class patterns each refine how a value sorts into one of several branches.",
1750+
"cell-0", "match-pattern-variants",
1751+
"Capture, alternative, guard, and class patterns each name a different way a value can match a case.",
16961752
)],
16971753
"literals": [(
16981754
"cell-0", "value-types",

0 commit comments

Comments
 (0)