{
  "title": "AI Vibe Coding Mastery: the overlap matrix",
  "version": "0.3.0",
  "stage": "Stage 1. The scaffold: two repo skeletons, five failing gates, thirty empty units and a book that already builds.",
  "generatedAt": "2026-08-21",
  "path": "/research/data/vibe-coding-curriculum.json",
  "thesis": "The five tiers are marketing. The thirty terms are eight ideas seen from five altitudes, and the tier a term lands in is an accident of when you happen to hit it rather than a statement about its difficulty. A reader who finishes this matrix should stop counting to thirty and start counting to eight.",
  "method": "Every term is mapped to a primary throughline and one or more secondary throughlines. A term with only two marks is a term that genuinely does one and a half things, and the verdict field says so rather than inflating it. Verdicts are opinionated on purpose: a curriculum that treats all thirty terms as equally load-bearing is a curriculum that has not been used.",
  "throughlines": [
    {
      "key": "A",
      "name": "Context economics",
      "question": "What enters the window, what it costs, what gets evicted.",
      "ladder": [
        "3 Tokens",
        "2 Context Window",
        "12 Prompt Caching",
        "20 Progressive Disclosure",
        "24 Memory Consolidation"
      ],
      "passage": "Tokens are the unit of account, and for about a week that is all they are: a number at the bottom of the run. The context window turns the number into a constraint, because now there is a container and things fall out of it. Prompt caching is the first move that treats the container as an economic object rather than a physical one: the same prefix costs full price once and a fraction thereafter, so where you put a thing in the prompt starts to matter more than whether you put it there at all. Progressive disclosure inverts the default, loading a tool description or a skill body at the moment of use instead of at the top of the session. Memory consolidation is the terminal question the other four are all avoiding: when the session ends, what deserves to survive it, and who decides. Same idea, five altitudes: count, contain, amortise, defer, retain."
    },
    {
      "key": "B",
      "name": "Instruction packaging",
      "question": "Where standing instructions live, and at what scope they bind.",
      "ladder": [
        "1 Prompting",
        "4 Projects",
        "8 CLAUDE.md",
        "9 /commands",
        "14 Skills",
        "15 Hooks"
      ],
      "passage": "Every term on this line answers one question: how long does this instruction live, and what happens if it is ignored. A prompt binds for one turn and is forgotten. A project binds for a set of sessions because someone put a file in a folder. CLAUDE.md binds for a repository and is read every time, which makes it powerful and makes it a permanent tax on the window. A slash command binds only when called, which is the first time an instruction gets a trigger condition instead of a residency. A skill adds a description the model matches against, so the trigger becomes semantic rather than typed. Hooks are the discontinuity: everything above them is a suggestion the model may decline, and a hook is a process the harness runs whether the model likes it or not. That is the escalation, and it is not about verbosity. It is about bindingness."
    },
    {
      "key": "C",
      "name": "Delegation topology",
      "question": "How many agents, who reports to whom, who merges the result.",
      "ladder": [
        "11 Sub-Agents",
        "19 Parallel Agents",
        "22 Orchestrator-Workers",
        "29 Agents Managing Agents",
        "30 Multi-Repo Orchestration"
      ],
      "passage": "Delegation starts as a context trick and becomes an organisational chart. A sub-agent exists because the parent's window is finite: you send the search into a fresh context and get back a conclusion instead of four hundred lines of file dumps. Parallel agents are the same move widened, and the moment you widen it you inherit every problem a build system has ever had with concurrency. Orchestrator-workers names the shape that actually survives contact: one planner holding the scarce context, N workers holding none of it, and a merge step that is code rather than judgement. Agents managing agents is that shape with the planner's decisions themselves delegated, which mostly means you have handed away the budget. Multi-repo orchestration is the topology crossing an ownership boundary, where the question stops being how work is split and starts being who is allowed to push."
    },
    {
      "key": "D",
      "name": "Execution surface",
      "question": "Attended or unattended, interactive or headless, human in the loop or not.",
      "ladder": [
        "6 CLI",
        "17 Background Agents",
        "18 Headless Runs",
        "28 Agent CI/CD"
      ],
      "passage": "The CLI is a conversation you are present for, and almost every intuition people build in tier one is an intuition about being present: you will see the mistake, you will hit escape, you will notice the loop. Background agents remove your attention while keeping your machine. Headless runs remove the terminal altogether, and this is the real discontinuity, because a run with no human means every affordance you relied on has to become an exit code, a log line, or a machine-readable artifact. Agent CI/CD is the end state: a machine starts the run, a machine judges the output, and the only human in the loop is whoever reads the failure. Each step up removes a form of supervision, and every removal has to be paid for with something deterministic. That is why this line and line F are the same line viewed from different sides."
    },
    {
      "key": "E",
      "name": "Tool surface and trust boundary",
      "question": "What the agent can reach, and who wrote the thing it is reaching.",
      "ladder": [
        "5 API Keys",
        "6 CLI",
        "7 MCP Servers",
        "14 Skills",
        "26 Tool Poisoning"
      ],
      "passage": "An API key is the first trust boundary anyone meets and almost nobody recognises as one: the credential is the perimeter, and its scope is the blast radius. The CLI widens the surface to whatever the shell can run. MCP servers widen it again and change its character, because now the tools are written by someone else and their descriptions are loaded into your model's context as instructions it will read. Skills bundle scripts alongside prose, so the same package that tells the model what to do can also hand it something to run. Tool poisoning is where the line stops being architecture and becomes an adversary: a tool description is untrusted input that arrives pre-approved. Note the interaction with line A, because it is the ugly one. Loading tool descriptions lazily saves tokens and means the string nobody read arrives after the human stopped watching."
    },
    {
      "key": "F",
      "name": "Determinism wrapping stochasticity",
      "question": "The non-negotiable checks bolted around a probabilistic core.",
      "ladder": [
        "15 Hooks",
        "16 Harness Engineering",
        "18 Headless Runs",
        "21 Eval-Driven Loops",
        "27 Self-Healing Tests",
        "28 Agent CI/CD"
      ],
      "passage": "This is the line that makes the rest safe, and it is the line most curricula treat as plumbing. A hook is one deterministic check at one lifecycle point, and it is the smallest possible unit of the idea: the model proposed something, and a program decided. Harness engineering is that generalised into a shell, which is less a technique than a stance. Headless runs force determinism because there is nobody to interpret ambiguity. Eval-driven loops turn the binary gate into a score, which is what lets you compare two versions of a system rather than only rejecting one. Self-healing tests are where the line eats itself, and they need saying plainly: a test that rewrites its own assertion to pass has stopped being a check and become a very expensive way of printing PASS. Agent CI/CD is the whole line finally placed where it belongs, in front of the merge."
    },
    {
      "key": "G",
      "name": "Feedback loops",
      "question": "Measure, then feed the measurement back in.",
      "ladder": [
        "3 Tokens",
        "12 Prompt Caching",
        "21 Eval-Driven Loops",
        "24 Memory Consolidation",
        "25 Self-Improving Loops"
      ],
      "passage": "Count, rate, score, retain, rewrite. Token count is a measurement nobody acts on. Cache hit rate is the first measurement with an obvious action attached, and the action changes your prompt architecture rather than your prompt. Eval-driven loops are the point where measurement becomes a number you can regress against, and everything above tier four is unbuildable without one. Memory consolidation is a feedback loop pointed at the context itself: what proved useful is what gets kept. Self-improving loops close the circuit by letting the measured score select the next instruction set. The failure mode is at the top and it is Goodhart's, not a bug: an optimiser pointed at an eval will improve the eval, and whether it improved the system is a separate claim requiring separate evidence. Anyone who has watched a scored system get worse while its score went up already knows this line's real lesson."
    },
    {
      "key": "H",
      "name": "Isolation and parallel safety",
      "question": "Worktrees, sandboxes, branch topology, blast radius.",
      "ladder": [
        "13 Git Worktrees",
        "17 Background Agents",
        "19 Parallel Agents",
        "22 Orchestrator-Workers",
        "30 Multi-Repo Orchestration"
      ],
      "passage": "The thinnest line in the list by term count and the one that causes the most damage when skipped. A worktree is a second checkout of the same repository on a different branch, and it is the enabling primitive for every parallel thing that follows: two agents editing one directory is not a coordination problem, it is a corruption problem. Background agents need isolation for a different reason, which is that they run while you are also working and your uncommitted state is not their business. Parallel agents multiply the requirement. Orchestrator-workers formalises it, because a merge step only makes sense if the things being merged were separate. Multi-repo orchestration moves the boundary from directories to credentials and permissions, where the question is no longer whether two agents collide but whether one of them should have been able to push there at all."
    }
  ],
  "terms": [
    {
      "n": 1,
      "name": "Prompting",
      "tier": 1,
      "primary": "B",
      "secondary": [
        "A",
        "G"
      ],
      "dependsOn": [],
      "verdict": "known",
      "note": "You do this. The curriculum's job here is not to teach prompting, it is to establish the vocabulary the other 29 terms escalate from.",
      "buildPos": 1
    },
    {
      "n": 2,
      "name": "Context Window",
      "tier": 1,
      "primary": "A",
      "secondary": [
        "B",
        "C"
      ],
      "dependsOn": [
        1,
        3
      ],
      "verdict": "load-bearing",
      "note": "The constraint every later term is a workaround for. Delegation exists because windows are finite; caching exists because refilling them costs money. Teach the limit and half the curriculum becomes obvious.",
      "buildPos": 5
    },
    {
      "n": 3,
      "name": "Tokens",
      "tier": 1,
      "primary": "A",
      "secondary": [
        "G",
        "F"
      ],
      "dependsOn": [],
      "verdict": "known",
      "note": "The unit. Worth exactly one commit that prints them on every run, because a number nobody sees is a number nobody optimises.",
      "buildPos": 2
    },
    {
      "n": 4,
      "name": "Projects",
      "tier": 1,
      "primary": "B",
      "secondary": [
        "A"
      ],
      "dependsOn": [
        1
      ],
      "verdict": "thin",
      "note": "A product feature, not a technique: a folder with files and a standing instruction. It earns its slot only as the first time an instruction outlives a single turn. Two throughlines, honestly.",
      "buildPos": 6
    },
    {
      "n": 5,
      "name": "API Keys",
      "tier": 1,
      "primary": "E",
      "secondary": [
        "D",
        "F"
      ],
      "dependsOn": [],
      "verdict": "known",
      "note": "You have secrets management. The one genuinely new idea is that key scope is blast radius, which matters much later at term 30.",
      "buildPos": 3
    },
    {
      "n": 6,
      "name": "CLI",
      "tier": 1,
      "primary": "D",
      "secondary": [
        "E",
        "B"
      ],
      "dependsOn": [
        5
      ],
      "verdict": "known",
      "note": "You use a terminal. Its real role is to be the attended baseline that terms 17 and 18 take supervision away from.",
      "buildPos": 4
    },
    {
      "n": 7,
      "name": "MCP Servers",
      "tier": 2,
      "primary": "E",
      "secondary": [
        "A",
        "B"
      ],
      "dependsOn": [
        5,
        6
      ],
      "verdict": "load-bearing",
      "note": "A real protocol with a real trust boundary, and the moment you add a third-party server you have accepted the risk that term 26 describes nineteen terms later.",
      "buildPos": 9
    },
    {
      "n": 8,
      "name": "CLAUDE.md",
      "tier": 2,
      "primary": "B",
      "secondary": [
        "A",
        "F"
      ],
      "dependsOn": [
        1,
        2
      ],
      "verdict": "known",
      "note": "A README the harness reads on every turn. Useful, permanently priced into your context, and unable to enforce anything, which is the gap term 15 exists to close.",
      "buildPos": 7
    },
    {
      "n": 9,
      "name": "/commands",
      "tier": 2,
      "primary": "B",
      "secondary": [
        "A",
        "D"
      ],
      "dependsOn": [
        8
      ],
      "verdict": "known",
      "note": "A shell alias with a prompt in it. The idea that matters is the trigger condition: an instruction that is not resident until called.",
      "buildPos": 8
    },
    {
      "n": 10,
      "name": "Model Routing",
      "tier": 2,
      "primary": "A",
      "secondary": [
        "C",
        "G"
      ],
      "dependsOn": [
        3,
        6
      ],
      "verdict": "load-bearing",
      "note": "The cheapest large win in the list, and the first delegation decision anyone makes without noticing it is one. Route by measured task cost, not by vibes about which model is smarter.",
      "buildPos": 11
    },
    {
      "n": 11,
      "name": "Sub-Agents",
      "tier": 2,
      "primary": "C",
      "secondary": [
        "A",
        "H"
      ],
      "dependsOn": [
        2
      ],
      "verdict": "known",
      "note": "You have spawned one. The under-taught part is why: not to parallelise, but to keep four hundred lines of grep output out of the parent's window.",
      "buildPos": 12
    },
    {
      "n": 12,
      "name": "Prompt Caching",
      "tier": 2,
      "primary": "A",
      "secondary": [
        "B",
        "G"
      ],
      "dependsOn": [
        2,
        3
      ],
      "verdict": "load-bearing",
      "note": "Misplaced in tier 2. It forces a stable-prefix architecture, which you cannot have before you have a prompt architecture at all. Genuinely a tier 4 concern that pays tier 2 money.",
      "buildPos": 14
    },
    {
      "n": 13,
      "name": "Git Worktrees",
      "tier": 3,
      "primary": "H",
      "secondary": [
        "C",
        "D"
      ],
      "dependsOn": [
        6
      ],
      "verdict": "load-bearing",
      "note": "The enabling primitive for everything parallel. Nothing in tiers 4 and 5 is safe without it, and it is plain git that predates all of this by a decade.",
      "buildPos": 15
    },
    {
      "n": 14,
      "name": "Skills",
      "tier": 3,
      "primary": "B",
      "secondary": [
        "A",
        "E"
      ],
      "dependsOn": [
        8,
        9
      ],
      "verdict": "load-bearing",
      "note": "The first instruction package that is both semantically triggered and progressively disclosed. It is term 20 wearing a different hat, which is exactly the kind of overlap this matrix exists to surface.",
      "buildPos": 13
    },
    {
      "n": 15,
      "name": "Hooks",
      "tier": 3,
      "primary": "F",
      "secondary": [
        "B",
        "E"
      ],
      "dependsOn": [
        8
      ],
      "verdict": "load-bearing",
      "note": "The only term on the list that converts a suggestion into an enforcement. Everything in CLAUDE.md is advisory; a hook is a program. If a reader takes one thing from tier 3, this is it.",
      "buildPos": 16
    },
    {
      "n": 16,
      "name": "Harness Engineering",
      "tier": 3,
      "primary": "F",
      "secondary": [
        "B",
        "D",
        "E"
      ],
      "dependsOn": [
        15
      ],
      "verdict": "umbrella",
      "note": "Not a technique, a name for the union of 15, 18, 21 and 28. The unit should say so and spend its words on the stance rather than pretending there is a separate skill here.",
      "buildPos": 29
    },
    {
      "n": 17,
      "name": "Background Agents",
      "tier": 3,
      "primary": "D",
      "secondary": [
        "H",
        "C"
      ],
      "dependsOn": [
        13,
        18
      ],
      "verdict": "known",
      "note": "A scheduled job with a model in it. The new content is failure handling: nobody is watching, so the interesting design is what it does when it is wrong.",
      "buildPos": 18
    },
    {
      "n": 18,
      "name": "Headless Runs",
      "tier": 3,
      "primary": "D",
      "secondary": [
        "F",
        "G",
        "E"
      ],
      "dependsOn": [
        6,
        5
      ],
      "verdict": "load-bearing",
      "note": "The boundary between a tool you use and a system that runs. Everything at tier 4 and 5 assumes it, and it is where ambiguity has to become an exit code.",
      "recountNote": "Headless removes the human who approves tool calls, so permission mode becomes a design decision and the reachable tool surface widens. That is an E teaching point the unit cannot skip.",
      "buildPos": 17
    },
    {
      "n": 19,
      "name": "Parallel Agents",
      "tier": 4,
      "primary": "C",
      "secondary": [
        "H",
        "A"
      ],
      "dependsOn": [
        11,
        13
      ],
      "verdict": "known",
      "note": "Fan-out. The technique is ordinary; the hazards are not, and they all live in throughline H.",
      "buildPos": 19
    },
    {
      "n": 20,
      "name": "Progressive Disclosure",
      "tier": 4,
      "primary": "A",
      "secondary": [
        "B",
        "E"
      ],
      "dependsOn": [
        2,
        12,
        14
      ],
      "verdict": "load-bearing",
      "note": "The actual scaling technique for context, and in direct tension with term 12. Learning either alone leaves you worse off than learning neither, which is why it is collision one.",
      "buildPos": 20
    },
    {
      "n": 21,
      "name": "Eval-Driven Loops",
      "tier": 4,
      "primary": "G",
      "secondary": [
        "F",
        "D"
      ],
      "dependsOn": [
        18
      ],
      "verdict": "load-bearing",
      "note": "Without this, tier 5 is vibes with a build step. An eval suite with a scored baseline is the single highest-value artifact in the whole repo.",
      "buildPos": 21
    },
    {
      "n": 22,
      "name": "Orchestrator-Workers",
      "tier": 4,
      "primary": "C",
      "secondary": [
        "A",
        "H",
        "F"
      ],
      "dependsOn": [
        11,
        19,
        13
      ],
      "verdict": "load-bearing",
      "note": "The topology that survives contact. One planner holding scarce context, N workers holding none, and a merge that is code rather than judgement.",
      "recountNote": "The merge step. Deterministic reconciliation of N stochastic worker outputs is why the pattern works, and the line C passage already described it without the mark being made.",
      "buildPos": 22
    },
    {
      "n": 23,
      "name": "Ultrathink",
      "tier": 4,
      "primary": "A",
      "secondary": [
        "G"
      ],
      "dependsOn": [
        3,
        21
      ],
      "verdict": "thin",
      "note": "A knob, not an architecture: a token budget for reasoning. The real practice is spending more reasoning tokens where the branching factor is high, then checking whether the spend moved the eval score. Usually you cannot tell, and saying so is more useful than a chapter.",
      "buildPos": 23
    },
    {
      "n": 24,
      "name": "Memory Consolidation",
      "tier": 4,
      "primary": "A",
      "secondary": [
        "B",
        "G"
      ],
      "dependsOn": [
        2,
        21
      ],
      "verdict": "thin",
      "note": "In practice this means writing a summary file. The real technique is a retention policy decided before the session and a rule for what earns a place, so retention is a scored decision rather than a vibe.",
      "buildPos": 24
    },
    {
      "n": 25,
      "name": "Self-Improving Loops",
      "tier": 5,
      "primary": "G",
      "secondary": [
        "B",
        "F"
      ],
      "dependsOn": [
        21,
        24
      ],
      "verdict": "load-bearing-conditional",
      "note": "Real, and worthless without term 21. An optimiser without an eval is a random walk with a larger bill. With one, it is collision three and its central hazard is Goodhart.",
      "buildPos": 27
    },
    {
      "n": 26,
      "name": "Tool Poisoning",
      "tier": 5,
      "primary": "E",
      "secondary": [
        "F",
        "A",
        "B"
      ],
      "dependsOn": [
        7
      ],
      "verdict": "load-bearing",
      "note": "Badly placed at tier 5. The exposure begins at term 7, the moment a third-party server is added, so the curriculum teaches the attack nineteen terms after the reader took the risk. This should be taught in tier 2.",
      "recountNote": "A tool description is an instruction that binds, authored by an adversary. Framing poisoning as hostile instruction packaging is the sharpest available reading of the attack.",
      "buildPos": 10
    },
    {
      "n": 27,
      "name": "Self-Healing Tests",
      "tier": 5,
      "primary": "F",
      "secondary": [
        "G",
        "C"
      ],
      "dependsOn": [
        21,
        28
      ],
      "verdict": "dangerous",
      "note": "The most dangerous name on the list. A test that rewrites its assertion to pass has stopped being a test. The defensible practice is auto-triage: classify the failure, propose a diff, open a PR, require a human merge. Never auto-repair the assertion side.",
      "buildPos": 26
    },
    {
      "n": 28,
      "name": "Agent CI/CD",
      "tier": 5,
      "primary": "F",
      "secondary": [
        "D",
        "H",
        "G"
      ],
      "dependsOn": [
        18,
        21
      ],
      "verdict": "load-bearing",
      "note": "Gate agent output the way you gate human output, which mostly means refusing to make an exception. The technique is ordinary CI; the discipline is not treating a model's PR as pre-reviewed.",
      "recountNote": "CI gates on an eval score, so the measurement from line G is what the gate reads. Without it the pipeline can only check that the run exited zero.",
      "buildPos": 25
    },
    {
      "n": 29,
      "name": "Agents Managing Agents",
      "tier": 5,
      "primary": "C",
      "secondary": [
        "G",
        "D"
      ],
      "dependsOn": [
        22
      ],
      "verdict": "thin",
      "note": "Orchestrator-workers with a longer leash and worse observability. The only genuinely new content is the budget and the kill switch, so the unit should be about those two things and be short.",
      "buildPos": 28
    },
    {
      "n": 30,
      "name": "Multi-Repo Orchestration",
      "tier": 5,
      "primary": "H",
      "secondary": [
        "C",
        "E"
      ],
      "dependsOn": [
        22,
        13,
        5
      ],
      "verdict": "known",
      "note": "Mostly credential scoping and a dependency graph. The agent part is the easy part; the hard part is deciding which repository a given token may push to, which is term 5 grown up.",
      "buildPos": 30
    }
  ],
  "collisions": [
    {
      "key": "cache-vs-disclosure",
      "terms": [
        12,
        20
      ],
      "title": "Prompt caching against progressive disclosure",
      "claim": "The two most-recommended context optimisations are in direct tension, and applying both naively raises your bill while shrinking your context.",
      "failure": "You adopt progressive disclosure to stop paying for tool schemas and skill bodies you are not using, and load them at the moment of need instead. Your average context length falls, which is what you were measuring, so you call it a win. Your spend rises. Caching prices a stable prefix once and a fraction thereafter, and it is a prefix, not a set: inserting anything mid-conversation invalidates the cache from the insertion point forward. Every efficient late load re-bills everything before it. Nobody catches this from either unit alone, because the caching unit says structure your stable content first and the disclosure unit says load late, and the reader hears two pieces of good advice rather than one contradiction.",
      "resolution": "Disclose late at the tail, cache hard at the head, and never let a late-loaded artifact land upstream of the cache breakpoint. Measure spend and context length together or you will optimise one into the other."
    },
    {
      "key": "hooks-vs-parallel",
      "terms": [
        15,
        19
      ],
      "title": "Hooks against parallel agents and worktrees",
      "claim": "A hook written for one agent becomes a source of nondeterminism the moment there are four.",
      "failure": "The hook works perfectly for months. Then you fan out to four workers in four worktrees and gates start failing at random, passing on rerun, and never failing the same way twice. The cause is that hooks written under an implicit single-agent assumption reach for shared state: a lockfile, a package cache, a formatter run against the repository root rather than the worktree, a validation that reads the index instead of the tree it was invoked for. Worker two now passes or fails based on worker three's uncommitted work. Neither unit surfaces it, because the hooks unit assumes one agent and the worktrees unit assumes hooks are inert.",
      "resolution": "Every hook takes its working directory from the invocation rather than from the repository root, touches no shared mutable path, and is tested by running the same hook concurrently in N worktrees before you trust it in a fan-out."
    },
    {
      "key": "eval-vs-optimiser",
      "terms": [
        21,
        25
      ],
      "title": "Eval-driven loops against self-improving loops",
      "claim": "Pointing an optimiser at a score makes the score go up. Whether the system improved is a separate claim requiring separate evidence, and the loop cannot produce it.",
      "failure": "Three generations in, the eval score is up eleven points and the system is worse. The loop found the cheap edges of your rubric: prompts that hit the graded keywords, answers shaped to the length the scorer rewards, cases the suite happens not to cover getting quietly worse because nothing measured them. This is Goodhart, and it is not a bug in either term. An eval alone is fine because nothing is optimising against it. An optimiser without an eval cannot run at all. Only combined do you get the specific failure of measurable improvement that is not improvement, and the thing that makes it dangerous is that every artifact the loop produces looks like evidence.",
      "resolution": "Hold out a set the optimiser never sees and score against it every generation. Report the gap between seen and held-out score as a first-class number, and treat a widening gap as the finding rather than as noise. This is the same discipline as an audit sample the auditee did not select."
    }
  ],
  "tierCritique": [
    "Prompt caching sits at term 12 in tier 2 and belongs at tier 4. Tuning a hit rate requires a stable prompt architecture, and a tier 2 reader does not have one yet. It stays where the numbering puts it, and the unit says plainly that the reader is being handed a tier 4 lever early because it pays for itself immediately.",
    "Tool poisoning sits at term 26 in tier 5 and belongs at tier 2. Exposure starts at term 7, when the first third-party MCP server is added. Teaching the attack nineteen terms after the reader accepted the risk is teaching the fire drill after the fire. The curriculum keeps the numbering and adds a forward reference from term 7 with the minimum defensive practice attached.",
    "Harness engineering at term 16 is an umbrella over 15, 18, 21 and 28. It gets a commit because the repo needs the scaffold, and a short unit that says what it is a name for rather than pretending it is a separate skill."
  ],
  "verdictLegend": {
    "load-bearing": "Learning it changes what you build. Worth the full unit.",
    "load-bearing-conditional": "Load-bearing only when paired with a named prerequisite. Alone it is a hazard.",
    "known": "A name for something a working engineer is already doing. Build the commit, keep the unit short.",
    "thin": "More vibes than technique. The unit states the real underlying practice and stops.",
    "umbrella": "A label for the union of other terms rather than a technique of its own.",
    "dangerous": "The common reading of the term is a bad idea. The unit says so and gives the defensible narrower practice."
  },
  "recount": {
    "published": 89,
    "corrected": 93,
    "occasion": "The published summary claimed 89 marks and was challenged on the grounds that the implied average forced almost every term to exactly three, which is tighter than terms like 22 and 28 deserve. The challenge was right about the shape and wrong about the size.",
    "method": "Every term was re-examined against one test: would the unit have to teach something on that line. Four marks were added. One candidate was considered and rejected, and it is recorded below so the discipline is visible rather than only its result.",
    "added": [
      {
        "term": 18,
        "line": "E",
        "why": "Headless removes the human who approves tool calls, so permission mode becomes a design decision and the reachable tool surface widens. That is an E teaching point the unit cannot skip."
      },
      {
        "term": 22,
        "line": "F",
        "why": "The merge step. Deterministic reconciliation of N stochastic worker outputs is why the pattern works, and the line C passage already described it without the mark being made."
      },
      {
        "term": 26,
        "line": "B",
        "why": "A tool description is an instruction that binds, authored by an adversary. Framing poisoning as hostile instruction packaging is the sharpest available reading of the attack."
      },
      {
        "term": 28,
        "line": "G",
        "why": "CI gates on an eval score, so the measurement from line G is what the gate reads. Without it the pipeline can only check that the run exited zero."
      }
    ],
    "rejected": [
      {
        "term": 7,
        "line": "D",
        "why": "MCP transport, stdio against a remote service, was proposed as an execution-surface mark. Line D is about attendance, whether a human is in the loop, not about where a process runs. Transport belongs to E, which is already the primary. No mark added."
      }
    ],
    "statement": "93, not the 89 published and not the 94 guessed. Five terms carry four marks: 16, 18, 22, 26 and 28. Two carry two: 4 and 23, the two the verdict column calls thin. The remaining 23 carry three."
  },
  "buildOrder": {
    "order": [
      1,
      3,
      5,
      6,
      2,
      4,
      8,
      9,
      7,
      26,
      10,
      11,
      14,
      12,
      13,
      15,
      18,
      17,
      19,
      20,
      21,
      22,
      23,
      24,
      28,
      27,
      25,
      29,
      16,
      30
    ],
    "rule": "Teach order is the meme's 1 to 30 and does not move; those are the term IDs and they are the spine. Build order is a topological sort of the dependency edges, validated on every generation. Where the two diverge the unit carries a forward or backward pointer.",
    "divergences": [
      {
        "term": 2,
        "teachPos": 2,
        "buildPos": 5,
        "delta": 3,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      },
      {
        "term": 3,
        "teachPos": 3,
        "buildPos": 2,
        "delta": -1,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      },
      {
        "term": 4,
        "teachPos": 4,
        "buildPos": 6,
        "delta": 2,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      },
      {
        "term": 5,
        "teachPos": 5,
        "buildPos": 3,
        "delta": -2,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      },
      {
        "term": 6,
        "teachPos": 6,
        "buildPos": 4,
        "delta": -2,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      },
      {
        "term": 7,
        "teachPos": 7,
        "buildPos": 9,
        "delta": 2,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      },
      {
        "term": 8,
        "teachPos": 8,
        "buildPos": 7,
        "delta": -1,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      },
      {
        "term": 9,
        "teachPos": 9,
        "buildPos": 8,
        "delta": -1,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      },
      {
        "term": 10,
        "teachPos": 10,
        "buildPos": 11,
        "delta": 1,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      },
      {
        "term": 11,
        "teachPos": 11,
        "buildPos": 12,
        "delta": 1,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      },
      {
        "term": 12,
        "teachPos": 12,
        "buildPos": 14,
        "delta": 2,
        "why": "Needs a stable prefix to have a hit rate at all, so it builds after 8, 9 and 14.",
        "material": true
      },
      {
        "term": 13,
        "teachPos": 13,
        "buildPos": 15,
        "delta": 2,
        "why": "Worktrees are the isolation primitive every parallel term later depends on. Earlier is cheaper.",
        "material": true
      },
      {
        "term": 14,
        "teachPos": 14,
        "buildPos": 13,
        "delta": -1,
        "why": "Skills are prompt architecture, and 12 cannot be tuned until that architecture exists.",
        "material": true
      },
      {
        "term": 15,
        "teachPos": 15,
        "buildPos": 16,
        "delta": 1,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      },
      {
        "term": 16,
        "teachPos": 16,
        "buildPos": 29,
        "delta": 13,
        "why": "The synthesis chapter names 15, 18, 21 and 28 as its parts, and its commit is the Makefile wiring them. You cannot wire together things that do not exist yet, so it builds last but reads in Tier 3.",
        "material": true
      },
      {
        "term": 17,
        "teachPos": 17,
        "buildPos": 18,
        "delta": 1,
        "why": "Needs both a worktree to run in and a headless runner to be.",
        "material": true
      },
      {
        "term": 18,
        "teachPos": 18,
        "buildPos": 17,
        "delta": -1,
        "why": "Headless is the substrate for 17, 21 and 28, so it builds before all three rather than after 17.",
        "material": true
      },
      {
        "term": 25,
        "teachPos": 25,
        "buildPos": 27,
        "delta": 2,
        "why": "Enforced by ruling 3: conditional on 21, and it consumes 24's retention policy.",
        "material": true
      },
      {
        "term": 26,
        "teachPos": 26,
        "buildPos": 10,
        "delta": -16,
        "why": "Built with 7 because exposure begins the moment a third-party server is added. Ships the basic defence; the lazy-loading interaction forward-points to 20.",
        "material": true
      },
      {
        "term": 27,
        "teachPos": 27,
        "buildPos": 26,
        "delta": -1,
        "why": "Auto-triage opens a PR, which needs the pipeline from 28.",
        "material": true
      },
      {
        "term": 28,
        "teachPos": 28,
        "buildPos": 25,
        "delta": -3,
        "why": "CI gates on an eval score, so 21 must exist first.",
        "material": true
      },
      {
        "term": 29,
        "teachPos": 29,
        "buildPos": 28,
        "delta": -1,
        "why": "Incidental. Position shifted by packing the DAG around a material move, not a design decision.",
        "material": false
      }
    ],
    "materialCount": 10
  },
  "schedule": {
    "budgetHoursPerWeek": 8,
    "deliveredHoursPerWeek": 7,
    "deliveredRateNote": "8 hours booked, 7 assumed delivered. A 3-4 AM block is a good block for writing and a fragile one for attendance, and a schedule that assumes every booked hour lands is a schedule that slips without ever admitting it.",
    "perUnitHours": {
      "load-bearing": 4.5,
      "load-bearing-conditional": 5,
      "dangerous": 4.5,
      "umbrella": 2.5,
      "known": 2,
      "thin": 1.25
    },
    "perUnitNote": "A load-bearing unit is 2 to 3 hours building the commit against real issuer documents, 45 minutes making the failure reproduce on demand, an hour writing, and half an hour verifying sharp edges against actual version numbers. A thin unit still ships its commit; only the writing shrinks.",
    "slippage": 0.15,
    "holidayWeeks": 3,
    "holidayNote": "Thanksgiving week and the two weeks around the new year, taken as lost rather than optimistically halved.",
    "start": "2026-08-21",
    "finish": "2027-03-12",
    "workingWeeks": 25.2,
    "calendarWeeks": 29,
    "totalHours": 177,
    "tiers": [
      {
        "tier": 1,
        "terms": "1-6",
        "hours": 30,
        "weeks": 4.3,
        "ends": "2026-09-25",
        "carries": "Most of the domain substrate lands here: DefiLlama discovery, PDF fetch, storage. The tier looks cheap by verdict and is not.",
        "cumulativeWorkingWeeks": 4.3
      },
      {
        "tier": 2,
        "terms": "7-12",
        "hours": 36,
        "weeks": 5.1,
        "ends": "2026-10-30",
        "carries": "Three load-bearing terms plus the first interstitial, which needs a real token bill showing the spend going up.",
        "cumulativeWorkingWeeks": 9.4
      },
      {
        "tier": 3,
        "terms": "13-18",
        "hours": 37,
        "weeks": 5.3,
        "ends": "2026-12-11",
        "carries": "The heaviest tier. Four load-bearing terms, the synthesis chapter, and the hooks-against-worktrees reproduction that has to be flaky by construction.",
        "cumulativeWorkingWeeks": 14.7
      },
      {
        "tier": 4,
        "terms": "19-24",
        "hours": 32,
        "weeks": 4.5,
        "ends": "2027-01-29",
        "carries": "Evals and the held-out discipline, which every later gate reads. Two thin units keep the hours down.",
        "cumulativeWorkingWeeks": 19.2
      },
      {
        "tier": 5,
        "terms": "25-30",
        "hours": 35,
        "weeks": 5,
        "ends": "2027-03-05",
        "carries": "The optimiser, auto-triage, CI, and the two-repo boundary. Gate 5 has to pass on a negative delta before this tier is done.",
        "cumulativeWorkingWeeks": 24.2
      },
      {
        "tier": 0,
        "terms": "book",
        "hours": 7,
        "weeks": 1,
        "ends": "2027-03-12",
        "carries": "Preface, final ordering pass, and the full read-through against the built repo.",
        "cumulativeWorkingWeeks": 25.2
      }
    ],
    "risks": [
      "The estimate assumes issuer attestation PDFs stay reachable and roughly as inconsistent as they are now. A format change at a major issuer is a week.",
      "Harness behaviour moves. Any unit citing a flag may need re-verification at publication, which is why every unit carries the version it was checked against.",
      "Gate 4 is the schedule's real hinge. If the eval suite is not honest by mid-January, terms 25, 27 and 28 have nothing to measure against and Tier 5 stalls."
    ],
    "finishNote": "Derived from the hours, not chosen and then justified. If a tier runs long the date moves; the honest version of this line is that it is a forecast with a stated method, not a commitment."
  }
}
