From bbe71899499145c5ab6ca99e1100176899cbb524 Mon Sep 17 00:00:00 2001 From: Carr1005 Date: Tue, 8 Sep 2026 07:41:12 -0700 Subject: [PATCH 1/7] =?UTF-8?q?Guide:=20gate-semantics=20reform=20(F12)=20?= =?UTF-8?q?=E2=80=94=20recommended-baseline=20rename,=20label=20timing=20f?= =?UTF-8?q?rames,=20deviation=20marks,=20bare-(default)=20ban?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The §6.0 express lane is named 'recommended baseline build' with a required one-line explanation (course choices where light, substitutions where heavy); never presented as the course's own configuration. - Two-label timing frames: Default column = generator's zero-setup call at generation time; '(Recommended)' = build agent's contextual call at gate time. - Resolved-decision checklist carries per-row deviation marks; baseline path walks through departing rows. - Bare '(default)' banned as an option label everywhere (gate + Options cells); the two sanctioned labels and their merged form are the only option labels. - §14 audit lines updated by reference. Co-Authored-By: Claude Fable 5 --- .../references/spec-generation-guide.md | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/.claude/skills/generate-spec/references/spec-generation-guide.md b/.claude/skills/generate-spec/references/spec-generation-guide.md index cb43ba4..436bb63 100644 --- a/.claude/skills/generate-spec/references/spec-generation-guide.md +++ b/.claude/skills/generate-spec/references/spec-generation-guide.md @@ -129,7 +129,7 @@ The **Decision Ledger** is the spec's second section (§6, right after the §0 p - **Category** — the §5.5 entry route that admitted the row (`design-argued | design-structural | realization | contradicted | learner`). Exactly one label, chosen by the precedence in the surfacing bar below; it determines the row's position in the fixed row order. - **Decision** — short name (e.g. "persistent store", "memory-core topology", "project"). - **Invariant** — what MUST hold to preserve the taught pattern. For learner-context rows it carries only the pattern's capability requirements on that dimension (§3) — typically empty for project/data/goal/scope-boundary, never invented. 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 — and when it is not the default (a §3 branch-1 substitution), tag that entry **"(course default)"** in the cell text, so the §6.0 gate's labeling duty is deterministic: the build agent must never have to infer which option the course actually used. +- **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 — and when it is not the default (a §3 branch-1 substitution), tag that entry **"(course default)"** in the cell text, so the §6.0 gate's labeling duty is deterministic: the build agent must never have to infer which option the course actually used. Never tag an Options entry with a bare "(default)": the Default column carries default-ness, and §6.0's two labels (provenance and recommendation) are the only sanctioned option labels. - **Default (course-derived)** — **exactly one** buildable target (§3). For heavy-dependency rows, resolved by the §3 dependency precedence, with the branch stated. When the default is the course's *example realization* — a domain-specific instantiation (its demo data, its example tools) rather than the pattern itself — the Decision or Default cell must say so and mark it as expected to be swapped when the learner's project (the project row) differs: the invariant, not the example, is what must survive. - **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. @@ -285,11 +285,11 @@ A Decision Ledger that no one is shown is worthless. A build agent's default beh - **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. -- **An express lane for the as-is builder, asked first.** The gate's FIRST question offers exactly two paths: build the course-default takeaway **as-is** (every Ledger row resolves to its Default), or **customize** the decisions row by row. Choosing as-is skips the per-row questions entirely — the agent prints the full resolved-decision checklist (every row = its Ledger default) and begins building; choosing customize enters the one-question-per-row loop. This is NOT an escape clause (§12.10): the user gave an explicit answer that covers every row — the same "defaults are fine" reply the determinism argument already sanctions — and the printed checklist still makes completeness visible. What stays forbidden is proceeding on *silence*. +- **An express lane for the baseline builder, asked first — and named honestly.** The gate's FIRST question offers exactly two paths: the **recommended baseline build** (every Ledger row resolves to its Default), or **customize** the decisions row by row. The express path is named "recommended baseline build" — never "build as-is with the course's setup" or any phrasing presenting it as the course's own configuration — because on substitution rows (§3 branch 1) the Default deliberately departs from what the course ran, so a course-default framing misattributes those rows: the same provenance error the labeling rule below prevents at option level, recurring at path level. The baseline option's text must carry a one-line explanation stating both halves: most rows resolve to the course's own choices, and wherever the course's choice needs setup the learner may not have (a paid key, an admin-provisioned service), a lighter equivalent stands in — with the step-5 checklist marking exactly where. Choosing the baseline skips the per-row questions entirely — the agent prints the full resolved-decision checklist and begins building; choosing customize enters the one-question-per-row loop. This is NOT an escape clause (§12.10): the user gave an explicit answer that covers every row — the same "defaults are fine" reply the determinism argument already sanctions — and the printed checklist still makes completeness visible. What stays forbidden is proceeding on *silence*. - **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.) - **One question per row — do not depend on a channel's item cap.** Interactive question tools cap how many questions fit in one call (Claude Code's `AskUserQuestion` allows at most a few), and a Ledger can have many rows. If the gate says "present every row" without saying *how*, the agent improvises — batching inconsistently, or (worse) presenting a first batch, getting a reply, and treating the build as unblocked while the rest are never asked (§12.11). Fix the mechanism deterministically: **one row = one question**, looped until every row is asked. One-per-row has no batch boundary to mis-track and its completeness is a plain count (N rows ⇒ N questions). **Never hardcode a numeric cap** ("4") into the gate — that is one environment's limit; state the capacity-relative rule instead so it holds for an uncapped or plain-text channel too. -- **Checklist-echo gates the build, not "a reply happened".** Keying resumption on "the user replied" fails the moment many rows exist: a reply to *some* rows satisfies it, and the rest are buried. Require a **visible artifact** instead — before any code, the agent prints a checklist of every row with its resolved value. A completion-driven agent cannot produce that checklist without having resolved every row, and the user/reviewer can *see* completeness. A printed artifact beats an internal "did I ask N times?" count precisely because the same agent that skips rows is the one that would judge the count. -- **Labels the course's actual choice "(course default)"; the build agent's own "(Recommended)" flag may coexist.** "(course default)" is factual provenance — what the course actually did — and must always mark the option the course actually used. On a **substitution row** (§3 dependency-precedence branch 1) that is the course-faithful **Options** entry, NOT the substituted Ledger Default: labeling the substitute "(course default)" misattributes it (observed in real learner feedback — a SQLite+Chroma default presented as the course's choice when the course ran Oracle). Separately, the build agent may mark an option "(Recommended)" per its own judgment or its question tool's convention (Claude Code's `AskUserQuestion` suggests exactly this) — that is advice about *this* learner's project, a different claim from provenance, and it is allowed. The two labels compose: when the agent's recommended option differs from the course's choice, both labels appear, each on its own option; when the recommended option IS the course's choice, use the single combined label **"(Recommended - course default)"**. A recommendation never removes or moves the "(course default)" label. +- **Checklist-echo gates the build, not "a reply happened".** Keying resumption on "the user replied" fails the moment many rows exist: a reply to *some* rows satisfies it, and the rest are buried. Require a **visible artifact** instead — before any code, the agent prints a checklist of every row with its resolved value. A completion-driven agent cannot produce that checklist without having resolved every row, and the user/reviewer can *see* completeness. A printed artifact beats an internal "did I ask N times?" count precisely because the same agent that skips rows is the one that would judge the count. The checklist also carries **deviation marks**: each row's line states whether its resolved value is the course's actual choice or departs from it — a substitution row resolved to its Default departs by construction; a customize answer may too — naming the course's choice on every departing row. And on the baseline path, the agent walks the learner through the departing rows alongside the checklist (each row's course choice, and the reason its Default substitutes — the row's own branch note carries it), so the express lane never hides where the baseline differs from the course. +- **Labels the course's actual choice "(course default)"; the build agent's own "(Recommended)" flag may coexist.** "(course default)" is factual provenance — what the course actually did — and must always mark the option the course actually used. On a **substitution row** (§3 dependency-precedence branch 1) that is the course-faithful **Options** entry, NOT the substituted Ledger Default: labeling the substitute "(course default)" misattributes it (observed in real learner feedback — a SQLite+Chroma default presented as the course's choice when the course ran Oracle). Separately, the build agent may mark an option "(Recommended)" per its own judgment or its question tool's convention (Claude Code's `AskUserQuestion` suggests exactly this) — that is advice about *this* learner's project, a different claim from provenance, and it is allowed. The two labels compose: when the agent's recommended option differs from the course's choice, both labels appear, each on its own option; when the recommended option IS the course's choice, use the single combined label **"(Recommended - course default)"**. A recommendation never removes or moves the "(course default)" label. The two labels also differ in **when their claims are made**: the Ledger's Default column is the *generator's* recommendation, fixed at generation time on zero-setup grounds (buildable as-is with nothing the learner must provision — the same grounds §3's precedence uses); "(Recommended)" is the *build agent's* judgment at gate time, made with the learner's context (their earlier gate answers; keys or services they actually hold). With no gate-time reason to depart, the agent recommends the row's Default; with one (say, the learner holds the key a keyed-tool row's course option needs), "(Recommended)" may land on any option — the label that never moves is "(course default)". These two labels, plus their merged form, are the **only sanctioned option labels** anywhere the spec presents choices — gate questions and Ledger Options cells alike. Never label an option with a bare "(default)" or "(Default)": default-ness is carried by the Ledger's Default column, not by a label, and a third label re-opens the provenance-vs-advice confusion the two-label design exists to close (observed as direct owner confusion in review). - **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.) - **Structured tool required when available; still portable.** If the environment has an interactive structured-question tool (Claude Code's `AskUserQuestion` or an equivalent), the gate MUST require using it — it is the reliability lever, not a mere suggestion. Name specific tools only as *examples* of the class, never as a hard dependency: a non-Claude agent (Codex, Cursor, plain chat) with no such tool must still comply by listing the rows in its reply and asking. So the rule is "use a structured question tool **if you have one**, else ask in plain text" — mechanism-*required* where possible, mechanism-*agnostic* in fallback. @@ -308,18 +308,23 @@ not because they are the right choice for this person's project. in yours), you MUST use it for the questions below — do not paraphrase them into a prose paragraph. Only if no such tool exists, list the rows in your reply and ask the user to respond to each. -2. **First question — build as-is, or customize?** Ask exactly one question with two options: - build the course-default takeaway **as-is** (every Ledger row resolves to its Default), or - **customize** the decisions row by row. If the user chooses as-is, skip step 3 — go straight - to the step-5 checklist and build. If the user chooses customize, continue with step 3. +2. **First question — recommended baseline build, or customize?** Ask exactly one question with + two options: the **recommended baseline build** — every Ledger row resolves to its Default: + mostly the course's own choices, with a lighter stand-in wherever the course's choice needs + setup you may not have (a paid API key, an admin-provisioned service); the step-5 checklist + marks exactly where the baseline differs from the course — or **customize** the decisions row + by row. If the user chooses the baseline, skip step 3 — go straight to the step-5 checklist + and build. If the user chooses customize, continue with step 3. 3. **Present the Ledger ONE ROW AT A TIME — one question per row.** For each row ask a single question: the **Decision** as the prompt, its **Options** as the choices. Append "(course default)" to the option the course actually used — on a substitution row that is the course-faithful Options entry, not the Ledger Default. You may also mark an option - "(Recommended)" per your own judgment or your question tool's convention; when your - recommended option IS the course's actual choice, merge the labels into - "(Recommended - course default)". A recommendation never removes or moves the - "(course default)" label. Use the answers already given (project, data, goal, …) to frame + "(Recommended)" — your judgment for THIS person's context, made now, at gate time; with no + contextual reason to depart, recommend the row's Default. When your recommended option IS + the course's actual choice, merge the labels into "(Recommended - course default)". A + recommendation never removes or moves the "(course default)" label, and no option is ever + labeled with a bare "(default)" — these two labels and their merged form are the only + option labels. Use the answers already given (project, data, goal, …) to frame later questions and describe options in the person's own terms — but never skip a row, drop or alter an Option, or move the "(course default)" label because of an earlier answer. Put any realizations beyond the tool's option slots (or the free-form case) under the tool's @@ -331,9 +336,13 @@ not because they are the right choice for this person's project. which resolves every row at once). Answers to *some* rows do NOT release the build; "no reply yet" is not an answer — wait for the user. 5. **Before the first line of code, print a resolved-decision checklist** — every Ledger row - with its final value (the user's choice, or its Ledger default). Begin implementation ONLY - after this complete checklist is shown; if any row is unresolved you are not done — return to - step 3. Build on the checklist's values. + with its final value (the user's choice, or its Ledger default), each line carrying a + deviation mark: `= course choice`, or `≠ course choice (course used: