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 difference | Intentional identity (keep) | Quality gap (close) |
|---|---|---|
| Per-lesson accent / font / world | always — it's the point | — |
| Long (concurrency 34m, udp 48m) | a survey or history, declared | sprawl no one edited |
| Short (memory 6m) | a tight essay, declared | a stub missing mechanism or labs |
| Few labs (paxos/saga/trie = 4) | topic has fewer interactions | a topic that begs for them |
| Thin engine (cap 42, udp 53 LOC) | genuinely little pure logic | rich logic left un-extracted |
| No coda | never intentional | the gap |
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.
| Lesson | Cluster | Tier | secs | labs | read | engLOC | tests | coda? |
|---|---|---|---|---|---|---|---|---|
| binary-trees | data-structures | Foundational | 10 | 9 | 9 | 394 | 56 | ✓ |
| b-trees | data-structures | Intermediate | 10 | 8 | 10 | 302 | 32 | ✓ |
| trie | data-structures | Intermediate | 10 | 4 | 11 | 113 | 12 | ✓ |
| vp-tree | data-structures | Intermediate | 8 | 5 | 10 | 394 | 39 | — |
| bloom-filters | probabilistic | Foundational | 14 | 6 | 13 | 80 | 14 | — |
| cuckoo-filter | probabilistic | Intermediate | 9 | 6 | 12 | 159 | 18 | — |
| hyperloglog | probabilistic | Intermediate | 9 | 7 | 9 | 121 | 28 | ✓ |
| bloom-clock | probabilistic | Advanced | 11 | 7 | 20 | 88 | 9 | — |
| memory | storage | Foundational | 7 | 5 | 6 | 43 | 9 | ✓ |
| lsm-trees | storage | Intermediate | 10 | 8 | 12 | 186 | 25 | ✓ |
| sstables | storage | Advanced | 6 | 5 | 10 | 394 | 45 | — |
| sha | hashing-integrity | Foundational | 10 | 6 | 15 | 229 | 14 | ✓ |
| merkle-trees | hashing-integrity | Intermediate | 12 | 7 | 14 | 93 | 10 | ✓ |
| concurrency-foundations | concurrency-txn | Foundational | 25 | 1 | 34 | 67 | 8 | — |
| acid-lab | concurrency-txn | Intermediate | 5 | 2 | 9 | 321 | 10 | ✓ |
| saga | concurrency-txn | Advanced | 10 | 4 | 13 | 379 | 31 | ✓ |
| cap-pacelc | consensus-membership | Advanced | 11 | 6 | 19 | 42 | 6 | — |
| swim | consensus-membership | Advanced | 10 | 6 | 13 | 189 | 12 | — |
| paxos | consensus-membership | Advanced | 9 | 4 | 8 | 252 | 23 | ✓ |
| udp | networking-rpc | Foundational | 11 | * | 48 | 53 | 3 | — |
| tls | networking-rpc | Intermediate | 9 | 7 | 9 | 228 | 37 | ✓ |
| grpc | networking-rpc | Intermediate | 7 | 6 | 11 | 163 | 32 | ✓ |
| torrents | networking-rpc | Advanced | 11 | 9 | 10 | 495 | 59 | ✓ |
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.