From a45e73874574ac6946045009cc43552a82c6a48c Mon Sep 17 00:00:00 2001 From: Carr1005 Date: Mon, 13 Jul 2026 00:52:55 +0800 Subject: [PATCH 1/2] =?UTF-8?q?Add=20Decision=20Ledger=20+=20=C2=A70=20pre?= =?UTF-8?q?-build=20gate=20to=20the=20spec-generation=20guide?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure how the generated spec surfaces design decisions, fixing three failure modes found while running the agent-memory course through the loop: - Replace the fixed six-slot "learner-intake" table with a course-derived **Decision Ledger** (§5.5, §6): one reviewable table holding every point where a build could diverge — learner-context AND pattern-critical / course-contradicted technique & dependency decisions — each pinned to one buildable course-derived default. Adds the invariant/options/default/ trade-off/owner row anatomy and a surfacing bar (§5.5). - Add a §3 dependency-precedence rule so a heavy course dependency (e.g. a cloud DB) resolves to one baked default — substitute-local unless the tech IS the taught subject — never a menu or contract (new traps §12.8/§12.9). - Add the **§0 "Before you build — REQUIRED" gate** (§6.0): an imperative, build-agent-addressed, mechanism-agnostic instruction to present every Ledger row (labeled "course default") and HARD STOP — end the turn and wait for the user's reply before writing code, with no "proceed on no response" escape (new trap §12.10). - Demote CTX-C to reference-only; add the owner provenance label (§9); add the matching §14 pre-handoff checks. Co-Authored-By: Claude Fable 5 --- .../references/spec-generation-guide.md | 162 ++++++++++++++---- 1 file changed, 133 insertions(+), 29 deletions(-) diff --git a/.claude/skills/generate-spec/references/spec-generation-guide.md b/.claude/skills/generate-spec/references/spec-generation-guide.md index e3d1027..e126d35 100644 --- a/.claude/skills/generate-spec/references/spec-generation-guide.md +++ b/.claude/skills/generate-spec/references/spec-generation-guide.md @@ -9,8 +9,8 @@ This guide stands in for three things at once: the **product framing** for the t 2. The spec-quality bar — right altitude 3. Inputs & the ground-truth rule 4. Procedure A — mine the materials (two passes) -5. Procedure B — derive the build -6. Required section template (§1–§7 + Course Context Pack) +5. Procedure B — derive the build (incl. §5.5 Derive the Decision Ledger) +6. Required section template (Decision Ledger + §1–§7 + Course Context Pack) 7. The Course Context Pack (CTX-A…CTX-E) 8. Contracts & acceptance-criteria format 9. Provenance labels @@ -61,19 +61,26 @@ Generation is gated on **two inputs**. Verify each is actually present before ge 1. **Notebook dump** (required) — notebooks concatenated to Markdown, cell by cell. Source of truth for **parameters, API surface, prompts, configs**. 2. **Transcripts** (required) — lesson transcripts. Source of truth for **lesson numbering and titles, rationale, spoken trade-offs, failure narration**. -**Learner intake is a build-time input, not a generation input.** One `spec.md` is generated and delivered to many learners; the learner supplies their own project when they build. So the generator **never has intake, must not ask for it, and must not block on it**. Instead: -- Emit each learner-specific value as a `[slot]` (§9 labels it *learner intake*). The intake dimensions a learner may later fill are: *Project* (what they're building); *Data/inputs* (what it operates on, where that lives); *Goal* (what "working" means — what retrieval should find, what the output must guarantee); *Model/provider* preference; *Environment* (where it runs, constraints); *Out of scope* (anything explicitly unwanted). -- **Every `[slot]` MUST carry a course-derived default** so the spec is buildable and evaluatable *as-is*, with zero intake. +**Learner intake is a build-time input, not a generation input.** One `spec.md` is generated and delivered to many learners; the learner supplies their own project when they build. So the generator **never has intake, must not ask for it, and must not block on it**. Instead, every point where a build could diverge — including the learner-context dimensions — becomes a **Decision Ledger** row (§5.5), each carrying a course-derived default. Specifically: +- The learner-context dimensions are Ledger rows with an *empty invariant* (the course has no opinion on them): *Project* (what they're building); *Data/inputs* (what it operates on, where that lives); *Goal* (what "working" means — what retrieval should find, what the output must guarantee); *Model/provider* preference; *Environment* (where it runs, constraints); *Out of scope* (anything explicitly unwanted). These are marked `[bracketed]` in the spec body (§9 labels them *learner intake*). +- **Every Ledger row — learner-context or otherwise — MUST carry a course-derived default** so the spec is buildable and evaluatable *as-is*, with zero intake. - The default MUST be **self-contained inside `spec.md`** — resolvable at build time without reading anything else. During a build, course `materials/` are off-limits (hook-enforced), so a default that points back at the course cannot be resolved. Bake it in. -### The deterministic course-default (the fallback that fixes inconsistent builds) +### The deterministic default (the fallback that fixes inconsistent builds) -A build-from-spec run with **no intake MUST resolve to exactly one target, every time** — the generator decides it, not the building agent. Never leave the default ambiguous between "the course's own example" and "some agnostic project"; that ambiguity is precisely what makes builds diverge run to run. Resolve the default with this precedence: +A build-from-spec run with **no intake MUST resolve to exactly one target, every time** — the generator decides it, not the building agent. This applies to **every Decision Ledger row** (§5.5), not just the project: each row names exactly one buildable default. Never leave a default ambiguous between "the course's own example" and "some agnostic project", and **never emit a contract or a menu in place of a default** — "any store meeting the invariant" or "e.g. X / Y / Z" is not a default; it is the ambiguity that makes builds diverge run to run (§12.8). + +**For the *project* row**, resolve the default with this precedence: 1. **Prefer the course's example scenario shape** — when the materials clearly afford a concrete example, re-express *its shape* on the self-contained synthetic fixture corpus (§5). Recognizably the course's example, but with facts *you* author (no course data copied — §11, §12.6). 2. **Else, a generic minimal instantiation** — when the course has no clean toy example, default to the smallest domain-neutral instantiation of the central pattern (§5), still on the synthetic fixture corpus. -Either way, name **one** buildable target. State which precedence branch you used in the slot's default note. +**For a *technique* or *dependency* row whose course realization is a heavy dependency** (a cloud DB, a hosted service, a keyed API, a GPU-class model — anything that cannot be baked into `spec.md` and run without external setup), resolve with this precedence: + +1. **Substitute the lightest self-contained realization that preserves the row's invariant** — e.g. an embedded local store standing in for a cloud vector DB, when the course teaches a *pattern* that the dependency merely happens to realize. The course's actual technology is still listed among the row's **Options**, never erased. +2. **UNLESS the specific technology *is* the taught subject** — a course *about* that exact product (e.g. "Building on Oracle Vector Search") — in which case reproduce it as the default, with baked-in setup instructions, and note the setup cost. + +Either way — project, technique, or dependency — name **one** buildable target and **state which precedence branch you took, and why, in the row's default note.** (This is the branch that, left unstated, made two generations of the same course diverge: one substituted a local store, the other emitted a menu.) **Ground-truth rule (hard gate).** Only the supplied materials count as course evidence. If you recognize the course from training, that memory is **not** a citable source — courses get refreshed, and recalled lesson numbers, parameters, and library versions are confidently wrong in exactly the ways that matter here. Anything you cannot point to in the supplied files is dropped or relabeled as your own addition (§9). **No files, no generation.** @@ -102,11 +109,33 @@ Keep a scratch **provenance ledger**: each extracted fact → where it came from ## 5. Procedure B — derive the build 1. **Name the course's central buildable pattern** as one pipeline (e.g. `load → split → embed+store → retrieve → generate → converse`), with a one-line reason each stage exists. -2. **Instantiate the pattern on the course-default** (§3), and mark the intake seams as `[slots]`. Because the generator has no learner intake, build the spec's skeleton on the deterministic default — the pattern instantiated with the default's data, goal, and model choices (on the synthetic fixture corpus), the course's pitfalls to avoid, and the course's API assumptions. Then mark exactly where a learner substitutes their own at build time: `[project]`, `[data]`, `[goal]`, `[model/provider]`, `[environment]`, `[out of scope]` — each with its course-derived default. That mapping is the spec's skeleton. (This is the difference between "here are some course snippets" and "use pattern A; data is B (default: fixture corpus); retrieval goal C; embedding D; chunking must consider E; avoid mistakes F/G/H; here are the course's API assumptions" — buildable as-is, with `[slots]` a learner can swap.) +2. **Derive the Decision Ledger from the pattern** (§5.5), and instantiate the pattern on each row's default (§3). Because the generator has no learner intake, build the spec's skeleton on the deterministic defaults — the pattern instantiated with the default project, data, goal, and model choices (on the synthetic fixture corpus), the course's pitfalls to avoid, and the course's API assumptions. The Ledger *is* the spec's skeleton: it names every point where the build could diverge, each pinned to one default a learner may swap. (This is the difference between "here are some course snippets" and "use pattern A; data is B (default: fixture corpus); retrieval goal C; embedding D; chunking must consider E; avoid mistakes F/G/H; here are the course's API assumptions" — buildable as-is, with the Ledger's rows a learner can swap.) 3. **Convert every demonstrated failure mode into a numbered business rule, and every rule into ≥1 acceptance criterion.** A failure mode without a rule is wasted curriculum; a rule without an AC is unverifiable. 4. **Design a fixture corpus**: small synthetic inputs whose facts *you* author, including one deliberate instance of *each* demonstrated failure mode, so the acceptance criteria run on day one before the learner wires in real data. 5. **Decide the stack**: pin modern versions as *this build's* choice; record course-era API names separately as perishable search keywords (CTX-D). Carry the pattern forward, not the era's call signatures. +### 5.5 Derive the Decision Ledger + +The **Decision Ledger** is the spec's second section (§6, right after the §0 pre-build gate) and its skeleton: every point where a build could legitimately diverge, each pinned to exactly one default. It replaces the old fixed "learner-intake slots" list — those six dimensions are still present, but as *rows*, not as the whole structure. The Ledger's shape is course-independent; its rows are course-specific, derived from the pattern (step 1). + +**A decision is not "learner" *or* "course".** Every design-critical decision has two roles at once: the **course** owns the *invariant* (what must stay true for the build to still embody the taught pattern) and a *course-derived default* (factual provenance — what the course did — not advice about the learner's project); the **learner** owns the *selection* among realizations that satisfy the invariant. "Should the store be online (a cloud DB) or offline (a local equivalent)?" is the canonical example — the course fixes the invariant ("a semantic-similarity store AND an exact-key store must both exist") and defaults to one; the learner picks the realization. So the Ledger does not sort decisions into "learner" vs "course" buckets; it records **who owns the answer** as a label (§9), which never changes how the row behaves. + +**Each row carries six fields:** +- **Decision** — short name (e.g. "persistent store", "distance metric", "project"). +- **Invariant** — what MUST hold to preserve the taught pattern. Empty for pure learner-context rows (project/data/goal/out-of-scope), where the course has no opinion. Write it precisely: this field doubles as the contract a future integration must satisfy. +- **Options** — realizations that satisfy the invariant, from course-faithful to tech-agnostic. The course's own technology always appears here even when it is not the default. +- **Default (course-derived)** — **exactly one** buildable target (§3). For heavy-dependency rows, resolved by the §3 dependency precedence, with the branch stated. +- **Trade-off** — what switching costs (carries the course's *spoken* trade-offs: re-embedding, re-tuning, lateral-or-worse results). +- **Owner** — a label only: `learner`, `course`, or `course+learner` (§9). Metadata; never gates behavior. + +**Procedure:** (a) walk each stage of the pattern (step 1); (b) list its decision points; (c) for each surfaced decision (see the bar below) write the six fields; (d) apply the §3 dependency precedence for any heavy-dependency row; (e) add the learner-context rows (project/data/goal/out-of-scope) with empty invariants. Pure learner rows still get a course-derived default (e.g. project defaults to the §3 example-shape target). + +**Surfacing bar — which decisions become Ledger rows.** Promote a decision to the Ledger iff **either**: +- **Pattern-critical** — changing the value would bend or break the taught pattern (store type, distance metric, retrieval strategy, offload/compaction trigger, deterministic-vs-agent-triggered operation split), **or** +- **Course-contradicted** — the course itself set it inconsistently across lessons or between signature/docstring/call site (e.g. cosine in one lesson, euclidean in another; `k=3` in a signature but `5` in the call). Self-contradiction is the strongest signal a human should see the choice, even if the stakes look low. + +Everything else — a single-valued parameter the course sets once and never varies (a chunk size, a token-estimate heuristic, a max-iteration cap) — stays a **defaulted value in the spec body**, not a Ledger row. It still carries its value and provenance; it is simply not promoted. Do not drown the Ledger in low-stakes rows; do not bury a pattern-critical or contradicted decision in prose (that is the failure §12.9 and the old CTX-C mis-home caused). + --- ## 6. Required section template (§1–§7 + Course Context Pack) @@ -121,17 +150,33 @@ The spec MUST contain these core sections, in this order (this is the seven-sect - -## Complete before handoff (optional — the spec builds as-is) - + course-derived knowledge; the Decision Ledger below holds every point where the + build could diverge, each pinned to one course-derived default so the spec builds + as-is with no intake; (c) provenance line: generated from notebooks + + transcripts on . --> + +## 0. Before you build — REQUIRED (do this first) + + +## Decision Ledger (§0 above requires the build agent to present these before building) + ## 1. Objective (pattern: CTX-A) @@ -140,9 +185,11 @@ The spec MUST contain these core sections, in this order (this is the seven-sect Without this, the agent adds plausible features nobody asked for.> ## 2. Tech Stack & Versions - + ## 3. Input/Output Contracts ★ ### CTX-A. The pattern ### CTX-B. Failure-mode catalog -### CTX-C. Decision guides +### CTX-C. Decision background ### CTX-D. Perishable assumptions ### CTX-E. Provenance map ``` @@ -186,6 +233,42 @@ End the spec with a status footer: version · course · learner project · the l **Optional sections** — add only when the feature demands it, placed between §7 and the Course Context Pack: performance targets (measurable thresholds), migration notes (before/after + rollback), UI state definitions (loading/error/empty/partial), error-handling taxonomy, compliance constraints (PII/payments/regulated data). Because the Context Pack is referenced by name (CTX-*) not by number, adding these never breaks a cross-reference. +### 6.0 The pre-build gate (spec §0 — REQUIRED) + +A Decision Ledger that no one is shown is worthless. A build agent's default behavior is *"build as-is; only stop for what blocks"* — and because every Ledger row carries a complete default, **nothing blocks, so nothing gets surfaced** and the learner never sees the decisions (the failure in §12.10). The fix is a **gate**: the generated spec's very first section (`## 0`) is an instruction to the *build* agent to present the Ledger before writing any code. + +**This gate is the only portable surfacing mechanism.** The spec is delivered as a single file to an unknown environment — the learner may build with Claude Code, claude.ai, OpenAI Codex, Cursor, or a custom harness. A hook could *enforce* the gate but is not portable (Claude Code CLI only). Prose in the spec cannot *guarantee* the step, but a maximally-structured prose gate is the strongest lever that travels everywhere. Write it for that job: + +- **Imperative and build-agent-addressed.** "You are the build agent. Before writing ANY code, you MUST…" — not a passive "review before build" header (which reads as a note to a human skimming and gets skipped). +- **First.** It is spec section `## 0`, ahead of everything including the Decision Ledger, visually isolated. +- **Presents EVERY Ledger row.** Do not have the gate re-filter or tier rows — the §5.5 surfacing bar already decided what became a row, so every row is by construction worth showing. (Never key the gate on row numbers; row identities are course-specific.) +- **Labels each row's value "course default", never "recommended".** The default is factual provenance (what the course did / the §3 precedence branch), not advice about *this* learner's project — the generator has no learner context and must not imply the default is best for them. +- **A hard stop, with no escape clause.** Presenting the decisions must end the agent's turn: it stops and waits for the user's reply before writing any code or touching any file. Do **not** give it a "proceed if there's no response" release valve — that is the loophole that re-opens §12.10: the agent *always* trivially has "no response" the instant it finishes presenting, so it reads the valve as immediate permission and the ask becomes theater. A narrower "proceed if launched non-interactively" escape is the same hole, smaller — drop it too; a completion-driven agent steers into whatever escape exists. Determinism is **not** at risk from waiting: it comes from every row having one course-derived default (§3, Known-Trap #7), so a user who replies "defaults are fine" lands on the identical target. Waiting changes *when* the agent proceeds, never *what* it builds. (If a genuinely headless harness cannot answer, the absent reply stalls that build — the harness's constraint to resolve by pre-answering, not a hole the spec should pre-drill.) +- **Mechanism-agnostic.** Describe the *behavior* (present the choices, pause for input); name a specific interactive tool only as an *example* ("e.g. Claude Code's `AskUserQuestion`, or the equivalent in your environment"), never as the load-bearing instruction — a non-Claude agent must still be able to comply by asking in plain text. + +Emit it using this course-independent template (fill the bracketed bits; the Ledger row list is whatever this course produced): + +```markdown +## 0. Before you build — REQUIRED (do this first) + +You are the build agent. Before writing ANY code, you MUST surface the design decisions +in the Decision Ledger (next section) to the person you are building for. Do **not** skip +this because the defaults look complete — the defaults exist so the build is *reproducible*, +not because they are the right choice for this person's project. + +1. Present **every** row of the Decision Ledger: its Decision, its Options, and which value + is the **course default**. +2. Let the user override any row. If your environment has an interactive question mechanism + (e.g. Claude Code's `AskUserQuestion`, or the equivalent in your tool), use it; otherwise + list the rows in your reply and ask the user to respond. +3. **Presenting the decisions ENDS YOUR TURN — that is, stop here and do not write code, + create or edit any file, or take any other build action until the user has replied.** + Presenting is not permission to proceed, and "no reply yet" is not an answer: wait for the + user. +4. Resume only after the user replies: build on their choices, and use the course default for + any row they leave unchanged. +``` + --- ## 7. The Course Context Pack (CTX-A…CTX-E) @@ -194,12 +277,18 @@ This section is the embedded eighth section of the generated spec — the part t - **CTX-A. The pattern** — the course's central pipeline with a one-line reason each stage exists. - **CTX-B. Failure-mode catalog** — one entry per demonstrated failure, each as: *symptom → cause → fix → "enforced by R#/AC#"*. Prose, no code. -- **CTX-C. Decision guides** — numbered trade-offs: parameters **with provenance** (which config, which lesson); technique selection ("use X when…"); composition/strategy choices stated with the course's *observed* results, not generic advice. +- **CTX-C. Decision background** — **reference only, not where decisions are made.** Every design-critical decision (pattern-critical or course-contradicted) is surfaced as a **Decision Ledger** row (§5.5); the Ledger is where a decision is presented, defaulted, and chosen. CTX-C holds the *durable background* a builder needs to understand those rows: the mechanism behind a trade-off, why the course observed what it did, and the provenance (which config, which lesson) behind a Ledger row's default. Each CTX-C entry that backs a Ledger row cross-references it (e.g. "→ Ledger D"). Do **not** park a live decision here as prose — if a builder must *choose*, it belongs in the Ledger. (This mis-home is the failure §12.9 records: contradicted decisions like cosine/euclidean and `k` buried in CTX-C where no one is asked to decide.) - **CTX-D. Perishable assumptions** — era-specific class/model/library names as a list, with the instruction: *treat these as search keywords against current docs, not guaranteed imports.* State plainly that the concepts in CTX-A…CTX-C are durable; only these names are perishable. - **CTX-E. Provenance map** — lesson titles in **transcript numbering** → which CTX-A/B/C items came from each. State explicitly: nothing in the spec requires platform access. > **Note on the name.** The Context Pack is the eighth section, extending the standard seven-section spec anatomy. It is referenced by the position-independent prefix **CTX-** rather than a section number, so the cross-references survive any reordering or insertion of optional sections. +### Integration mode (deferred — but write the invariants ready for it) + +A learner may eventually use the spec not to build a standalone takeaway but to **graft the taught pattern onto their own existing project** ("does my codebase still embody this pattern? what must I preserve?"). That second build mode is **not designed yet** — the current deliverable is the standalone takeaway (default) only. **Do not add an integration section or a second template.** + +But author each Decision Ledger row's **Invariant** field so it can *become* that mode's contract later: state what must hold in terms of the pattern's behavior, not the fixture's implementation ("a semantic-similarity store AND an exact-key store must both exist", not "use SQLite"). Written that way, the invariants already answer "what must my integration preserve?" when the mode is built. This costs nothing now and avoids a rewrite later. + --- ## 8. Contracts & acceptance-criteria format @@ -215,7 +304,8 @@ This section is the embedded eighth section of the generated spec — the part t Apply throughout the spec so course-derived content is never confused with your additions: - **Course-demonstrated** — traceable to the supplied materials; carries a `(CTX-X)` anchor whose entry traces to the ledger. - **Project hardening** — a constraint you added that the course did *not* demonstrate (e.g. idempotent re-ingest when the course wipes and rebuilds). Say so explicitly. The takeaway's credibility depends on never putting words in the course's mouth. -- **Learner intake** — `[bracketed]`. Never left empty at generation: every slot carries a course-derived default (§3) so the spec builds as-is; the brackets mark where a learner *may* substitute, not a gap that blocks handoff. +- **Learner intake** — `[bracketed]`. Never left empty at generation: every value carries a course-derived default (§3) so the spec builds as-is; the brackets mark where a learner *may* substitute, not a gap that blocks handoff. +- **Owner** (the Decision Ledger's owner column, §5.5) — `learner` (the course has no opinion; pure context, e.g. project/data), `course` (the course fixes it; a technique the learner rarely overrides), or `course+learner` (the course sets the invariant + default; the learner selects a realization, e.g. online-vs-offline store). This is **metadata about who owns the answer, not a behavior switch**: every row carries a default and is surfaced the same way regardless of owner. Owner never decides whether a row gets a default or whether it is shown. --- @@ -259,7 +349,10 @@ Each occurred in a real run; check for them explicitly. 4. **Over-attribution.** A hardening choice (e.g. idempotent re-ingest) read as course-taught when the course did the opposite. Label hardening as hardening (§9). 5. **Memory leakage.** Recognizing the course from training and generating "from it" without the files present produces plausible, wrong, unverifiable output. Enforce the ground-truth gate (§3). 6. **Snippet reassembly.** The failure this guide exists to prevent: the Context Pack carries concepts, mechanisms, decisions. If a fenced code block from the notebooks appears anywhere in the spec, delete it and write the behavior it implemented. -7. **Ambiguous default → inconsistent builds.** A spec that leaves the no-intake target unresolved — readable as either "build the course's own carried-in example" or "build some agnostic project" — makes the coding agent pick differently run to run. Fix: resolve **one** deterministic course-default per slot (§3) and bake it in, so every build-from-spec run with no intake lands on the same target. +7. **Ambiguous default → inconsistent builds.** A spec that leaves the no-intake target unresolved — readable as either "build the course's own carried-in example" or "build some agnostic project" — makes the coding agent pick differently run to run. Fix: resolve **one** deterministic default per Decision Ledger row (§3, §5.5) and bake it in, so every build-from-spec run with no intake lands on the same target. +8. **Contract-instead-of-default.** A Ledger row whose "default" is actually a *contract* ("any store that supports vector similarity and exact lookup") or a *menu* ("e.g. SQLite / pgvector / Oracle") names no single target — so the build agent picks, and two builds diverge. This is the exact failure observed when one generation baked a concrete local store and another wrote a menu. Fix: a default is **one buildable target**; the alternatives live in the **Options** column, not the Default. For a heavy-dependency row, apply the §3 dependency precedence and state the branch. +9. **Live decision buried as prose.** A pattern-critical or course-contradicted decision (distance metric, retrieval `k`, store type) written only as a CTX-C paragraph is never *surfaced* — no one is asked to decide, and the generator silently resolves it (often inconsistently run to run). Fix: promote it to a Decision Ledger row (§5.5 surfacing bar); leave only the durable background in CTX-C, cross-referenced to the row. +10. **Silent-default build.** Even a perfect Decision Ledger is never shown to the learner if nothing tells the *build* agent to present it. Because every row carries a complete default, the build never *blocks*, so a build agent proceeds silently on defaults and the learner sees no decision at all — the worst failure, since the decisions are on the page and still invisible. Fix: the spec MUST open with the §0 pre-build gate (§6.0) — an imperative, build-agent-addressed instruction to present every Ledger row and then **hard stop** (end the turn; write no code and touch no file until the user replies). **The gate MUST NOT carry a "proceed if there's no response" escape** — that re-opens this very trap: the agent *always* trivially has "no response" the moment it finishes presenting, so it reads the escape as immediate permission and the ask becomes theater. A narrower "proceed if launched non-interactively" escape is the same hole, smaller; omit it. A visible Ledger without the §0 hard-stop gate — or a gate with an escape clause — is a defect. --- @@ -269,7 +362,8 @@ Before delivering, ask: *could an agent rebuild behaviorally-equivalent output f - output shape changes between runs → the §3 contract is too vague; - scope grows with unrequested features → the §1 "Not Included" boundary is incomplete; - an edge case handled once but not next time → the §5 acceptance criteria don't cover it; -- the built *project* changes between no-intake runs (course example one run, agnostic the next) → the §3 course-default is ambiguous; resolve it to one target. +- the built *project* changes between no-intake runs (course example one run, agnostic the next) → the §3 default is ambiguous; resolve it to one target. +- the build's *stack or store* changes between no-intake runs (local one run, cloud the next) → a Decision Ledger row's Default is a menu or contract, not one target; fix per §12.8. There is no oracle for spec *correctness* except the user; executable acceptance criteria are the practical proxy. Without them, this is prompt-driven development with extra steps. @@ -285,6 +379,16 @@ Fix, don't annotate. - [ ] Parameter values cite the exact config they came from; no "course defaults" hand-waving. - [ ] Version claims match the notebooks' actual install lines; era stated honestly if unpinned. +**Decision Ledger** +- [ ] The spec opens with the `## 0. Before you build — REQUIRED` gate (§6.0), positioned **before** the Decision Ledger. +- [ ] The gate is imperative and addressed to the build agent, and instructs it to present **every** Ledger row with its value labeled **"course default"** (not "recommended"). +- [ ] The gate is a **hard stop**: it tells the build agent that presenting the decisions ends its turn — write no code and touch no file until the user replies — with **no "proceed if there's no response" (or "proceed if non-interactive") escape clause** (§12.10). And it is **mechanism-agnostic** (names an interactive tool only as an example; a non-Claude agent — Codex, Cursor, a custom harness — could comply by asking in plain text and then stopping). +- [ ] Every Decision Ledger row names **exactly one** buildable default — no menu, no "any X meeting the invariant" masquerading as a default (§12.8). +- [ ] Every pattern-critical or course-contradicted decision (§5.5 bar) is a Ledger row; none is left buried as CTX-C prose (§12.9). Conversely, single-valued low-stakes params are body defaults, not rows. +- [ ] Each heavy-dependency row records which §3 dependency-precedence branch was taken and why; the course's own technology appears in that row's Options. +- [ ] Each row's Invariant is written precisely enough to serve as an integration contract (§ Integration note); learner-context rows may have an empty invariant. +- [ ] Owner labels are present and used only as metadata — no row's default or surfacing depends on its owner. + **Anatomy** - [ ] Single clear objective; "Not Included" present (learner exclusions + past-course-scope). - [ ] §3 contracts are schemas; schema invariants are internally consistent with the ACs. @@ -301,4 +405,4 @@ Fix, don't annotate. ## Output -Deliver exactly one file named `spec.md` — the learner's only download. The "Complete before handoff" slots-and-defaults table is always the first section; because every slot carries a course-derived default, the spec is buildable as-is and unfilled slots never block handoff. Do **not** deliver the provenance ledger, mining notes, or any companion file: the single self-contained spec is the product. +Deliver exactly one file named `spec.md` — the learner's only download. It opens with the `## 0. Before you build — REQUIRED` gate (§6.0), immediately followed by the **Decision Ledger** (§5.5, §6); because every row carries a course-derived default, the spec is buildable as-is and unfilled rows never block handoff, while the §0 gate ensures the decisions are surfaced to a human who is present. Do **not** deliver the provenance ledger, mining notes, or any companion file: the single self-contained spec is the product. From e934873889235d24a79c0f0eea63f2c44d3cab19 Mon Sep 17 00:00:00 2001 From: Carr1005 Date: Mon, 13 Jul 2026 15:29:20 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=C2=A70=20gate:=20present=20one=20question?= =?UTF-8?q?=20per=20Ledger=20row,=20gate=20build=20on=20a=20printed=20chec?= =?UTF-8?q?klist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes a failure that surfaced on the 14-row agent-memory Ledger: the gate said "present every row" and released the build once "the user replied", but an interactive question tool caps items per call (Claude Code's AskUserQuestion takes only a few). So the agent presented a first batch, got a reply, treated the build as unblocked, and buried the remaining rows — and different agents improvised different batchings (inconsistency). Deterministic mechanism (§6.0), no hardcoded cap: - Require a structured question tool when the environment has one (else plain text) — it is the reliability lever, not a mere example. - Present ONE QUESTION PER ROW, looped until every row is asked. No batch seam to mis-track; completeness is a plain count (N rows ⇒ N questions). - Gate the build on a printed resolved-decision checklist covering EVERY row, not on a single reply — answers to some rows never release the build. Adds trap §12.11 (Partial-present build) and matching §14 checklist items. Portable: an agent without a structured tool lists rows in its reply and still echoes the checklist before code. Co-Authored-By: Claude Fable 5 --- .../references/spec-generation-guide.md | 61 +++++++++++++------ 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/.claude/skills/generate-spec/references/spec-generation-guide.md b/.claude/skills/generate-spec/references/spec-generation-guide.md index e126d35..8c84bde 100644 --- a/.claude/skills/generate-spec/references/spec-generation-guide.md +++ b/.claude/skills/generate-spec/references/spec-generation-guide.md @@ -157,12 +157,13 @@ The spec MUST contain these core sections, in this order (this is the seven-sect ## 0. Before you build — REQUIRED (do this first) + an imperative, build-agent-addressed instruction that presents every Ledger row ONE + QUESTION PER ROW via a structured question tool (required if the environment has one, e.g. + AskUserQuestion; else plain-text list) — never depending on a per-call item cap — then + HARD STOPS: write no code until every row is answered AND a resolved-decision checklist is + printed. No "proceed if no response" escape (§12.10); no partial-present build (§12.11). + Portable across Claude Code / claude.ai / OpenAI Codex / Cursor / a custom harness. Emit + the §6.0 template verbatim (fill in this course's specifics). --> ## Decision Ledger (§0 above requires the build agent to present these before building)