Why this exists

The 23 lessons were authored independently. They vary roughly 3–5× in prose length, ~12× in engine size, and ~20× in test depth. Some of that is the point: a survey should be longer than an essay, and a topic with fewer natural interactions earns fewer labs. Some of it is just whichever bar the author hit that day.

You cannot level a collection you cannot see side-by-side. So this is the mirror. It defines one shared bar, then measures every lesson against it. It ships no lesson changes. Its only job is to make one decision possible: what does "the same level" mean, and which differences are intentional identity versus uneven quality.

The bar — anatomy of a complete lesson

A lesson is complete when it has all of these. The first group is pedagogy — the part that varies today. The second is craft, now largely enforced by the MHE loops and uniform across the collection.

Pedagogy (varies today)

1. Signature hero — an eyebrow that is a credit, year, or promise (never "Interactive lesson"), a display title, a subtitle, and a lede that states the stakes. 2. A motivating opening — a concrete "what breaks without this" before any mechanism. The reader should want the answer before they get it. 3. A legible arc — problem → core idea → mechanism (stepped) → limits & trade-offs → synthesis. Not a rigid template; a recognizable shape. Unique per lesson, not structureless. 4. Real interactive labs — each makes one claim physical and is driven by the engine, not a static diagram. Count may vary by topic; "is it load-bearing" may not. 5. A closing — a coda naming the one idea to carry away, with pointers onward. This is the most common gap today.

Craft (now uniform — verified by the loops)

6. Pure engine + tests, ≥90% covered. 7. Family glue — JetBrains Mono, both themes, reduced-motion gating, AA contrast, scoped CSS, keyboard a11y. 8. A sane length band (≈8–16 reading-minutes), with declared exceptions.

Intentional uniqueness vs quality gap

This is the whole game. The same metric is identity or debt depending on intent. A long lesson is a survey or a sprawl; a short one is a tight essay or a stub; few labs means a quiet topic or a missed interaction.

Looks like a differenceIntentional identity (keep)Quality gap (close)
Per-lesson accent / font / worldalways — it's the point
Long (concurrency 34m, udp 48m)a survey or history, declaredsprawl no one edited
Short (memory 6m)a tight essay, declareda stub missing mechanism or labs
Few labs (paxos/saga/trie = 4)topic has fewer interactionsa topic that begs for them
Thin engine (cap 42, udp 53 LOC)genuinely little pure logicrich logic left un-extracted
No codanever intentionalthe gap
The same number, two readings — intent decides.

The scorecard

All 23 lessons, with the deterministic columns measured read-only from the source tree. Cluster and tier are a first-pass proposal to ratify. read is section-prose words ÷ 200 (a rough proxy the audit refines); coda? is detected by section filename, so it undercounts — some lessons close inline. udp keeps its labs in components/ (the *), itself a small inconsistency to normalize.

LessonClusterTiersecslabsreadengLOCtestscoda?
binary-treesdata-structuresFoundational109939456
b-treesdata-structuresIntermediate1081030232
triedata-structuresIntermediate1041111312
vp-treedata-structuresIntermediate851039439
bloom-filtersprobabilisticFoundational146138014
cuckoo-filterprobabilisticIntermediate961215918
hyperloglogprobabilisticIntermediate97912128
bloom-clockprobabilisticAdvanced11720889
memorystorageFoundational756439
lsm-treesstorageIntermediate1081218625
sstablesstorageAdvanced651039445
shahashing-integrityFoundational1061522914
merkle-treeshashing-integrityIntermediate127149310
concurrency-foundationsconcurrency-txnFoundational25134678
acid-labconcurrency-txnIntermediate52932110
sagaconcurrency-txnAdvanced1041337931
cap-pacelcconsensus-membershipAdvanced11619426
swimconsensus-membershipAdvanced1061318912
paxosconsensus-membershipAdvanced94825223
udpnetworking-rpcFoundational11*48533
tlsnetworking-rpcIntermediate97922837
grpcnetworking-rpcIntermediate761116332
torrentsnetworking-rpcAdvanced1191049559
Measured columns are real; cluster/tier are the proposal to ratify.

What the data already says

Before anyone reads a single lesson, the table points at four things.

- Closings are the cheapest, highest-signal fix. About nine lessons have no named closing section. A consistent "one idea, where next" coda raises the floor uniformly. - Engine depth, test depth, and topic richness are mismatched in places. cap-pacelc (42 LOC / 6 tests), udp (53 / 3), concurrency (67 / 8), and bloom-clock (88 / 9) are thin where the topic is rich — candidates for "is the interactive core under-built, or is the topic genuinely simple?" - Two declared outliers, not gaps. concurrency (survey, 34m) and udp (history, 48m) should stay long — but say so, in writing. - Structure varies but is not chaos. Most lessons are 9–12 sections and 5–7 labs; the outliers each look intentional. The audit confirms.

The progression question — defer it

Do not commit to a tree yet; the dependency data does not exist. The scorecard's tier + cluster, plus a future prerequisites column, is that data. Two cheap, reversible steps, in order:

1. Add tier + tags to lesson-catalog.js (pure metadata, no UI). The index can then group and filter, surfacing a suggested order without committing to a tree. About 30 minutes, fully reversible. 2. Only if clean prerequisite chains emerge (merkle → torrents, acid → saga, concurrency → cap → paxos) graduate to a real graph.

The path, and a loop to fill the rest

Smallest steps first: (1) ratify the bar and the intentional-vs-gap test; (2) normalize closings — a coda per lesson, uniform shape, native voice; (3) stand up a read-only collection-coherence MHE loop to fill the judgment columns; (4) close gaps lesson-by-lesson, worst-first off the loop's map; (5) add tier + tags and revisit tree-vs-paths with real data.

Step 3 is the engine for the rest. It is the same shape as the existing read-only loops — content-accuracy, theme-parity: a deterministic signal, one locked-down opus agent per lesson, a strict cite-or-omit map. Per lesson it scores the §1 checklist (present / thin / missing, with a quote), names the arc it actually follows and where it breaks, rates each lab (load-bearing / decorative / static-that-should-be-live), proposes a tier + cluster + prerequisites, and makes the key call: each shortfall bucketed intentional identity (keep, with the one-sentence why) or quality gap (close, with the smallest fix). The output is this scorecard with the judgment columns filled — "they feel uneven" turned into a worst-first punch-list.

The proposal in full

The complete document, verbatim. Everything above is a reading of it; this is the source of record. It is a draft to argue with, and it changed no lesson or code to produce.

The full proposal, unedited.

COLLECTION.md · 185 lines
COLLECTION.md185 lines · Markdown
1# The Collection — coherence rubric & scorecard (PROPOSAL)
2 
3> **Status: draft for discussion. No lesson or code changes were made to produce
4> this.** It exists to make one decision possible: _what does "the same level"
5> mean_, and which differences between lessons are **intentional identity** vs
6> **uneven quality**. Everything below is a starting point to argue with, not a
7> verdict.
8 
9The 23 lessons were authored independently and vary ~3–5× in prose length, ~12×
10in engine size, and ~20× in test depth. Some of that is the point (a survey
11_should_ be longer than an essay); some is just whichever bar the author hit that
12day. You can't level a collection you can't see side-by-side, so this doc is the
13mirror: a shared bar, then every lesson measured against it.
14 
15---
16 
17## 1. The bar — anatomy of a complete Glassbox lesson
18 
19A lesson is **complete** when it has all of these. (The first group is the
20_pedagogy_; the second is the _craft_, now largely enforced by the MHE loops.)
21 
22**Pedagogy — the part that varies today**
23 
241. **Signature hero** — eyebrow that is a credit / year / promise (never
25 "Interactive lesson"), a display title, a one-line subtitle, a lede that
26 states the stakes. _(AGENTS.md already mandates this.)_
272. **A motivating opening** — a concrete "what breaks without this / why should I
28 care" _before_ any mechanism. The reader should want the answer before they
29 get it.
303. **A legible arc** — problem → core idea → mechanism (stepped) → limits &
31 trade-offs → synthesis. Not a rigid template; a recognizable _shape_. The
32 collection is meant to be unique per lesson, **not** structureless.
334. **Real interactive labs** — each lab makes _one_ claim physical and is driven
34 by the lesson's engine (not a static diagram). Count is allowed to vary by
35 topic; "is it actually interactive and load-bearing" is not.
365. **A closing** — a coda that names _the one idea to carry away_ and points
37 where to go next. **This is the single most common gap today (≈9 lessons).**
38 
39**Craft — now mostly uniform (verified by the loops)**
40 
416. **Pure engine + tests**`engine/index.js`, ≥90% covered. (Uniform; _depth_
42 still varies — see the scorecard.)
437. **Family glue** — JetBrains Mono for numerics/credits/eyebrows, both light &
44 dark themes, reduced-motion gating, AA contrast, scoped CSS, keyboard a11y.
45 _(All green as of the latest loop sweep.)_
468. **A sane length band** — target ≈ 8–16 reading-minutes, with **declared**
47 exceptions (a survey or an essay can opt out, on purpose, in writing).
48 
49---
50 
51## 2. Intentional uniqueness vs quality gap — how to tell them apart
52 
53This is the whole game. The same metric can be either, depending on intent:
54 
55| Looks like a difference | **Intentional identity** (keep) | **Quality gap** (close) |
56| --- | --- | --- |
57| Per-lesson accent / font / world | always — it's the point | — |
58| Long (concurrency 34 min, udp 48 min) | a _survey_ or _history_, declared as such | a lesson that sprawled because no one edited it |
59| Short (memory 6 min) | a tight _essay_, declared as such | a stub that never got its mechanism or labs |
60| Few labs (paxos/saga/trie = 4) | topic has fewer natural interactions | a topic that _begs_ for interaction and got prose |
61| Thin engine (cap 42, udp 53 LOC) | genuinely little pure logic to extract | rich logic left un-extracted / untestable |
62| No coda | **never intentional** — every lesson earns a close | the gap |
63 
64**Rule of thumb:** a difference is _intentional_ only if someone can say, in one
65sentence, _why_ — and that sentence belongs in the lesson's own notes. If the
66only answer is "that's just how it came out," it's a gap.
67 
68---
69 
70## 3. Scorecard (deterministic columns measured; judgment columns are the audit's job)
71 
72Clusters and tiers below are a **first-pass proposal** to ratify. `words` is
73section-prose only (a rough proxy; the audit refines it); `read` ≈ words ÷ 200;
74`coda?` is by section filename (so it _undercounts_ — some lessons close inline).
75 
76| Lesson | Cluster | Tier | secs | labs | ~words | read | engLOC | tests | coda? |
77| --- | --- | --- | ---: | ---: | ---: | ---: | ---: | ---: | :---: |
78| binary-trees | data-structures | Foundational | 10 | 9 | 1789 | 9 | 394 | 56 | ✓ |
79| b-trees | data-structures | Intermediate | 10 | 8 | 1913 | 10 | 302 | 32 | ✓ |
80| trie | data-structures | Intermediate | 10 | 4 | 2278 | 11 | 113 | 12 | ✓ |
81| vp-tree | data-structures | Intermediate | 8 | 5 | 1992 | 10 | 394 | 39 | — |
82| bloom-filters | probabilistic | Foundational | 14 | 6 | 2537 | 13 | 80 | 14 | — |
83| cuckoo-filter | probabilistic | Intermediate | 9 | 6 | 2408 | 12 | 159 | 18 | — |
84| hyperloglog | probabilistic | Intermediate | 9 | 7 | 1857 | 9 | 121 | 28 | ✓ |
85| bloom-clock | probabilistic | Advanced | 11 | 7 | 3950 | 20 | 88 | 9 | — |
86| memory | storage | Foundational | 7 | 5 | 1275 | 6 | 43 | 9 | ✓ |
87| lsm-trees | storage | Intermediate | 10 | 8 | 2498 | 12 | 186 | 25 | ✓ |
88| sstables | storage | Advanced | 6 | 5 | 1995 | 10 | 394 | 45 | — |
89| sha | hashing-integrity | Foundational | 10 | 6 | 3013 | 15 | 229 | 14 | ✓ |
90| merkle-trees | hashing-integrity | Intermediate | 12 | 7 | 2856 | 14 | 93 | 10 | ✓ |
91| concurrency-foundations | concurrency-txn | Foundational | 25 | 1 | 6885 | 34 | 67 | 8 | — |
92| acid-lab | concurrency-txn | Intermediate | 5 | 2 | 1818 | 9 | 321 | 10 | ✓ |
93| saga | concurrency-txn | Advanced | 10 | 4 | 2571 | 13 | 379 | 31 | ✓ |
94| cap-pacelc | consensus-membership | Advanced | 11 | 6 | 3871 | 19 | 42 | 6 | — |
95| swim | consensus-membership | Advanced | 10 | 6 | 2530 | 13 | 189 | 12 | — |
96| paxos | consensus-membership | Advanced | 9 | 4 | 1614 | 8 | 252 | 23 | ✓ |
97| udp | networking-rpc | Foundational | 11 | * | 9623 | 48 | 53 | 3 | — |
98| tls | networking-rpc | Intermediate | 9 | 7 | 1753 | 9 | 228 | 37 | ✓ |
99| grpc | networking-rpc | Intermediate | 7 | 6 | 2212 | 11 | 163 | 32 | ✓ |
100| torrents | networking-rpc | Advanced | 11 | 9 | 2002 | 10 | 495 | 59 | ✓ |
101 
102`*` udp keeps its labs in `components/`, not `labs/` — itself a small structural
103inconsistency worth normalizing.
104 
105---
106 
107## 4. What the data already says (before any reading)
108 
109- **Closings are the cheapest, highest-signal fix.** ≈9 lessons have no named
110 closing section (bloom-filters, cuckoo, bloom-clock, sstables, cap-pacelc,
111 swim, vp-tree, concurrency, udp). A consistent "the one idea + where next"
112 coda is a small, uniform win that immediately raises the floor.
113- **Engine depth ↔ test depth ↔ topic richness are mismatched in places.**
114 cap-pacelc (42 LOC / 6 tests) and udp (53 / 3) and concurrency (67 / 8) and
115 bloom-clock (88 / 9) are thin where the topic is rich — candidates for "is the
116 interactive core under-built, or genuinely simple?" swim is rich in prose but
117 light in tests (189 / 12).
118- **Two declared outliers, not gaps:** concurrency (survey, 34 min) and udp
119 (history/console, 48 min). These should _stay_ long — but say so in writing.
120- **Structure varies but isn't chaos.** Most lessons are 9–12 sections / 5–7
121 labs. The outliers (acid 5/2, sstables 6/5, concurrency 25/1) are each
122 arguably intentional — the audit confirms.
123 
124---
125 
126## 5. The progression question — defer it, let the data decide
127 
128Don't commit to a tree yet; you don't have the dependency data. The scorecard's
129**tier** + **cluster** + a future **prerequisites** column produce exactly that
130data. Two cheap, reversible steps toward an answer, in order:
131 
1321. **Add `tier` + `tags` to `lesson-catalog.js`** (pure metadata, no UI). Lets
133 the index _group_ and _filter_ — surfaces a suggested reading order without
134 committing to a tree. ~30 min, fully reversible.
1352. **Only if clean prerequisite chains emerge** (e.g. merkle → torrents,
136 acid → saga, concurrency → cap → paxos), graduate to a real progression
137 graph. If instead it's 7 loosely-coupled clusters (likely), **tags + a
138 "start here" path beats a tree** and costs far less.
139 
140My read: this is a _clustered collection_, not a strict curriculum, so tags +
141one or two suggested paths will feel better than a dependency tree. But that's a
142hypothesis the prerequisites data should confirm.
143 
144---
145 
146## 6. Proposed path — smallest steps first
147 
1481. **Ratify this bar** (§1) and the intentional-vs-gap test (§2). One
149 conversation. Nothing ships until the bar is agreed.
1502. **Normalize the one universal gap: closings.** Give every lesson a coda in
151 its own voice (the one idea + where next). Uniform shape, per-lesson texture —
152 the exact "coherent but separate" target, at the lowest risk.
1533. **Stand up a `collection-coherence` MHE loop** (sketch in §7) to fill the
154 judgment columns — arc completeness, lab load-bearingness, motivation, and an
155 _intentional-vs-gap_ verdict per lesson, cite-or-omit. Read-only; it maps, you
156 fix.
1574. **Close gaps lesson-by-lesson**, worst-first off the loop's map, each as its
158 own small reviewable change.
1595. **Add `tier` + `tags` metadata**; revisit tree-vs-paths with real prerequisite
160 data.
161 
162---
163 
164## 7. Sketch — a `collection-coherence` MHE loop
165 
166Same shape as the existing read-only loops (`content-accuracy`, `theme-parity`):
167deterministic signal → one locked-down `opus` agent per lesson → strict
168cite-or-omit map. Per lesson it would emit:
169 
170- the §1 checklist, each item **present / thin / missing** with a quoted cite;
171- the arc shape it actually follows, and where it breaks;
172- each lab rated **load-bearing / decorative / static-that-should-be-live**;
173- a proposed **tier**, **cluster**, and **prerequisites**;
174- and the key call: each shortfall bucketed **intentional identity** (keep, with
175 the one-sentence why) vs **quality gap** (close, with the smallest fix).
176 
177Output is one collection-wide table — this scorecard, with the judgment columns
178filled — that turns "they feel uneven" into a worst-first punch-list.
179 
180---
181 
182_Appendix — method: metrics gathered read-only from the source tree (section /
183lab file counts, section-prose word counts, `engine/index.js` LOC, `it()`/`test()`
184counts in each engine suite, closing-section filename detection). Clusters &
185tiers are the author's first-pass proposal. No lesson or code was modified._