Merge feature/ask-dont-guess into develop

This commit is contained in:
Bastien Chanot
2026-09-17 11:41:39 +02:00
16 changed files with 210 additions and 48 deletions
+27
View File
@@ -23,6 +23,33 @@ for this change, diff reviewed on the branch).
- [ ] A5 registries at capitalize: LRN (doc vs observed `ask` under auto, - [ ] A5 registries at capitalize: LRN (doc vs observed `ask` under auto,
2.1.273; `autoMode.allow` = exception tier; wildcarded-interpreter 2.1.273; `autoMode.allow` = exception tier; wildcarded-interpreter
allow suspended), BDR-090 addendum allow suspended), BDR-090 addendum
## 2026-09-16 — ask, don't guess: orchestrators ask about open choices (feature/ask-dont-guess)
User: the orchestrators (ship-feature, feat, hotfix, bugfix, init-project)
settle choices they should ask about ("cet icône, plutôt à gauche ou à
droite ?"), even mid-run. Diagnosis: contract-interview STEP 2 only fires on
gaps (outcome / scope / constraints), so a taste choice never triggers a
question; feat:153 and bugfix:165 tell the orchestrator to "make the
decision HERE" on NEED-DECISION. Decisions (user, 2026-09-15/16): global
rule changes for all work, hotfix included; classes VISIBLE / PUBLIC NAME /
SCOPE ask, internal technical choices never. Spec:
`docs/superpowers/specs/2026-09-16-ask-dont-guess-design.md`; plan:
`docs/superpowers/plans/2026-09-16-ask-dont-guess.md` (9 tasks, lock-first).
- [x] P1 `lib/contract-interview.md` — STEP 2 CLARIFY (pass A gaps, pass B
open choices), MID-RUN CLARIFICATION, HOW TO ASK; 9 locks in
`contract-verifier.test.sh`
- [x] P2 `CLAUDE.global.md:51-55` — "Ask rather than guess" replaces the
one-question rule; bug line reconciled
- [x] P3 `skills/feat/SKILL.md` — pass B at STEP 1, NEED-DECISION routed on class
- [x] P4 `skills/bugfix/SKILL.md` — pass B at STEP 3, NEED-DECISION routed on class
- [x] P5 `skills/hotfix/SKILL.md` — pass B at LOCATE, tagged BLOCKED relayed;
lock `loops-light.test.sh:84`
- [x] P6 `skills/ship-feature` STEP 2 + `skills/init-project` contract §/STEP 3
- [x] P7 `agents/interviewer.md` — visible/public/scope item never `(assumed)`
- [x] P8 `agents/{feater,bugfixer,hotfixer}.md` — CLASS tag; 3 locks in `gates.test.sh`
- [x] P9 `make test` green (2026-09-16), CHANGELOG, TODO tick; manual behavioral check still OPEN before merge
- [ ] P10 registries at capitalize: BDR (supersedes the one-question rule),
LRN (taste is invisible to a gap-only trigger; fresh re-dispatch cost
favors plan-time questions)
## 2026-09-15 — align config + deployment on the hand-edited settings.json (feature/automode-config-alignment) ## 2026-09-15 — align config + deployment on the hand-edited settings.json (feature/automode-config-alignment)
User edited global `settings.json` by hand: 4 destructive rules moved User edited global `settings.json` by hand: 4 destructive rules moved
+19
View File
@@ -43,6 +43,25 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).
and undeclared node packages (`npx`/`dlx` of a package absent from the and undeclared node packages (`npx`/`dlx` of a package absent from the
lockfile, `npm install <name>`). `SETTINGS.md` gains the `autoMode.allow` lockfile, `npm install <name>`). `SETTINGS.md` gains the `autoMode.allow`
tier and the reason a static `Bash(node *)` rule cannot do this job. tier and the reason a static `Bash(node *)` rule cannot do this job.
- **Ask, don't guess: the orchestrators ask about open choices instead of
settling them.** `CLAUDE.global.md` replaces "one question upfront, never
mid-task" with: a choice visible in the result, a name that becomes
public, or a scope the request does not settle → ask, even mid-task;
internal technical choices stay Claude's. `lib/contract-interview.md`
STEP 2 becomes CLARIFY: pass A (the three gap checks, at contract time)
and pass B (the open-choice sweep in three classes, run once at each
flow's PLAN step, no question cap, over-5 guard, "you decide" recorded as
delegated). New MID-RUN CLARIFICATION section: an executor's
`NEED-DECISION` carries a `CLASS:` tag; visible / public-name / scope go
to the user verbatim, internal is decided in the loop; answers land in
the contract `[gated]`. New HOW TO ASK section (LRN-102). `/feat`,
`/bugfix`, `/hotfix`, `/ship-feature`, `/init-project` wire pass B at
their plan step; `/feat` and `/bugfix` stop deciding `NEED-DECISION`
themselves; `/hotfix` drops "zero questions ever" and allows one
re-dispatch for a class-tagged BLOCKED; the interviewer never ships a
visible / public-name / scope item as `(assumed)`; feater, bugfixer and
hotfixer report the class. Locks updated in the `contract-verifier`,
`loops-light` and `gates` tests.
- **The classifier, not `permissions.ask`, now guards destructive shell - **The classifier, not `permissions.ask`, now guards destructive shell
work** (BDR-090). Ten rules left the static tiers: `rsync`, `kill -9`, work** (BDR-090). Ten rules left the static tiers: `rsync`, `kill -9`,
`killall`, `pkill` out of `deny`, and `python3 -c`, `python -c`, `killall`, `pkill` out of `deny`, and `python3 -c`, `python -c`,
+6 -2
View File
@@ -48,11 +48,15 @@ Apply unless repo-specific instructions override.
calls. Skill-mandated gates (fresh verifier/security/challenge) calls. Skill-mandated gates (fresh verifier/security/challenge)
always dispatch as written. Don't redo delegated work by hand — always dispatch as written. Don't redo delegated work by hand —
failed gates re-dispatch fresh executors instead. failed gates re-dispatch fresh executors instead.
- One question upfront if needed — don't interrupt mid-task. - Ask rather than guess. A choice visible in the result (placement,
wording, order, behavior), a name that becomes public (command, flag,
endpoint, file), or a scope the request does not settle → ask, even
mid-task. Batch what can be batched. Internal technical choices with
no observable effect stay yours.
*Exception: skill-mandated gates and checkpoints (orchestrator *Exception: skill-mandated gates and checkpoints (orchestrator
validation gates, approval gates, darwin checkpoints) always fire.* validation gates, approval gates, darwin checkpoints) always fire.*
- Bug received → fix directly: check logs, find root cause, resolve - Bug received → fix directly: check logs, find root cause, resolve
autonomously. autonomously; a visible choice in the fix still gets asked.
- Something goes wrong → STOP, re-plan. Never push through. - Something goes wrong → STOP, re-plan. Never push through.
- Deviations: minor or clearly justified → do, explain after. - Deviations: minor or clearly justified → do, explain after.
Significant or shaky justification → ask before deviating. Significant or shaky justification → ask before deviating.
+5 -3
View File
@@ -27,8 +27,9 @@ Every choice was made in the plan or is a NEED-DECISION to report.
- Apply the FIX PLAN to the letter — fix the ROOT CAUSE named in DIAGNOSIS, - Apply the FIX PLAN to the letter — fix the ROOT CAUSE named in DIAGNOSIS,
not the symptom. A plan hole or an open choice (naming, data shape, API not the symptom. A plan hole or an open choice (naming, data shape, API
surface, dependency) → STOP, report `NEED-DECISION` with the precise surface, dependency, a user-visible choice such as placement, wording or
question. Never re-investigate or improvise a different fix. behavior) → STOP, report `NEED-DECISION` with the precise question and
its `CLASS:`. Never re-investigate or improvise a different fix.
- Stay inside the contract FILE SCOPE. A needed file outside it → - Stay inside the contract FILE SCOPE. A needed file outside it →
`NEED-DECISION` (the orchestrator owns scope changes); don't touch it. `NEED-DECISION` (the orchestrator owns scope changes); don't touch it.
- Add or update the regression test the plan names — it must fail before the - Add or update the regression test the plan names — it must fail before the
@@ -73,5 +74,6 @@ FILE(S) : <created/modified paths>
TEST(S) : <regression test added/updated + final suite run result, verbatim line> TEST(S) : <regression test added/updated + final suite run result, verbatim line>
SMOKE : <build/typecheck result if run, or n/a> SMOKE : <build/typecheck result if run, or n/a>
NOTES : <DONE: deviations (must be none) | NEED-DECISION: the exact NOTES : <DONE: deviations (must be none) | NEED-DECISION: the exact
question + the options you see | BLOCKED: the blocker verbatim> question + the options you see + CLASS: visible | public-name |
scope | internal | BLOCKED: the blocker verbatim>
``` ```
+5 -3
View File
@@ -37,8 +37,9 @@ report below is optional on this path (the dispatcher needs the edit applied
## EXECUTION RULES ## EXECUTION RULES
- Follow the plan to the letter. A plan hole or an open choice (naming, - Follow the plan to the letter. A plan hole or an open choice (naming,
data shape, API surface, dependency) → STOP, report `NEED-DECISION` with data shape, API surface, dependency, a user-visible choice such as
the precise question. Never improvise a design decision. placement, wording or behavior) → STOP, report `NEED-DECISION` with the
precise question and its `CLASS:`. Never improvise a design decision.
- Stay inside the contract FILE SCOPE. A needed file outside it → - Stay inside the contract FILE SCOPE. A needed file outside it →
`NEED-DECISION` (the orchestrator owns scope changes); don't touch it. On `NEED-DECISION` (the orchestrator owns scope changes); don't touch it. On
the applier path the scope is the files named in the bundle item — apply the applier path the scope is the files named in the bundle item — apply
@@ -84,5 +85,6 @@ STATUS : DONE | NEED-DECISION | BLOCKED
FILES : <created/modified paths> FILES : <created/modified paths>
TESTS : <added/updated + final suite run result, verbatim line> TESTS : <added/updated + final suite run result, verbatim line>
NOTES : <DONE: deviations (must be none) | NEED-DECISION: the exact NOTES : <DONE: deviations (must be none) | NEED-DECISION: the exact
question + the options you see | BLOCKED: the blocker verbatim> question + the options you see + CLASS: visible | public-name |
scope | internal | BLOCKED: the blocker verbatim>
``` ```
+6 -1
View File
@@ -43,6 +43,10 @@ the edit applied + self-verified, not the report grammar).
BLOCKED`, report why (the orchestrator escalates to `/bugfix`), never BLOCKED`, report why (the orchestrator escalates to `/bugfix`), never
expand scope yourself. On the applier path it is the files named in the expand scope yourself. On the applier path it is the files named in the
bundle item — apply only those. bundle item — apply only those.
- An open user-visible choice the contract does not settle (placement,
wording, behavior) → `STATUS BLOCKED` with `CLASS: visible | public-name |
scope` in NOTES, BEFORE editing anything. The orchestrator asks the user
and re-dispatches once.
- If tests exist for the affected code, run them. Detection cascade: - If tests exist for the affected code, run them. Detection cascade:
```bash ```bash
# JS/TS # JS/TS
@@ -78,5 +82,6 @@ STATUS : DONE | BLOCKED
FILE(S) : <changed files — suffix files you CREATED with " (new)"> FILE(S) : <changed files — suffix files you CREATED with " (new)">
FIX : <one-line description> FIX : <one-line description>
SMOKE : <test/build result, verbatim line> SMOKE : <test/build result, verbatim line>
NOTES : <BLOCKED: the blocker; DONE: none> NOTES : <BLOCKED: the blocker, + CLASS: visible | public-name | scope when
you halted at an open choice before editing; DONE: none>
``` ```
+3 -3
View File
@@ -14,13 +14,13 @@ Gather context. Produce complete PROJECT BRIEF as single source of truth.
- If the initial prompt already provides name + purpose + stack + features + architecture → skip questions and generate the BRIEF directly. - If the initial prompt already provides name + purpose + stack + features + architecture → skip questions and generate the BRIEF directly.
- Otherwise ask only what's genuinely missing, in a single structured block. - Otherwise ask only what's genuinely missing, in a single structured block.
- After answers: produce BRIEF. One follow-up allowed if answer is ambiguous. - After answers: produce BRIEF. One follow-up allowed if answer is ambiguous.
- Hard budget: 2 question rounds total (initial block + one follow-up). The BRIEF ships after round 2 no matter what — gaps become OPEN DECISIONS, never a third round. - Hard budget: 2 question rounds total (initial block + one follow-up) for gaps. The BRIEF ships after round 2 — gaps become OPEN DECISIONS. Sole exception: a VISIBLE, PUBLIC NAME or SCOPE choice (a user-facing placement or wording, a public command/flag/endpoint name, whether X is in scope) still open after round 2 gets ONE more targeted question; it never ships as `(assumed)`.
## FAILURE MODES ## FAILURE MODES
| Trigger | First response | If still unresolved | | Trigger | First response | If still unresolved |
|---|---|---| |---|---|---|
| Answer vague/ambiguous | One targeted follow-up on that item only | Record item in OPEN DECISIONS with the safest reading, marked `(assumed)` — never invent a confident value | | Answer vague/ambiguous | One targeted follow-up on that item only | Gap: record it in OPEN DECISIONS with the safest reading, marked `(assumed)` — never invent a confident value. Visible / public-name / scope item: one more targeted question instead, never `(assumed)` |
| "I don't know / you decide" | Propose ONE concrete default + why, ask yes/no | Take the default, mark `(assumed)`, list in OPEN DECISIONS | | "I don't know / you decide" | Propose ONE concrete default + why, ask yes/no | Take the default, mark `(assumed)`, list in OPEN DECISIONS |
| Contradictory answers (e.g. embedded runtime + managed cloud DB) | Name the contradiction, ask which side wins | Put BOTH options in OPEN DECISIONS; do not silently pick one | | Contradictory answers (e.g. embedded runtime + managed cloud DB) | Name the contradiction, ask which side wins | Put BOTH options in OPEN DECISIONS; do not silently pick one |
| Partial answer to the block | Re-ask ONLY the missing items in the follow-up round | Missing fields → `none stated` + OPEN DECISIONS entry | | Partial answer to the block | Re-ask ONLY the missing items in the follow-up round | Missing fields → `none stated` + OPEN DECISIONS entry |
@@ -77,6 +77,6 @@ Stop after BRIEF. Orchestrator handles next step.
- Design, architect, or implement anything — the BRIEF is the entire deliverable. - Design, architect, or implement anything — the BRIEF is the entire deliverable.
- Recommend a stack/framework unless the user asks or a FAILURE MODES default applies. - Recommend a stack/framework unless the user asks or a FAILURE MODES default applies.
- Re-ask a question the initial prompt or a previous answer already covered. - Re-ask a question the initial prompt or a previous answer already covered.
- Exceed the 2-round budget, whatever is still missing. - Exceed the 2-round budget for gaps; the only extra question is the single targeted one a visible / public-name / scope item earns.
- Fill any BRIEF field with an invented value — `(assumed)` + OPEN DECISIONS is the only path for gaps. - Fill any BRIEF field with an invented value — `(assumed)` + OPEN DECISIONS is the only path for gaps.
- Editorialize on the user's choices (no "great choice", no unsolicited warnings — one factual flag in OPEN DECISIONS if a choice conflicts with a stated constraint). - Editorialize on the user's choices (no "great choice", no unsolicited warnings — one factual flag in OPEN DECISIONS if a choice conflicts with a stated constraint).
+72 -9
View File
@@ -7,8 +7,9 @@ subagents = execution + report only; gates and loop decisions live in the
main loop). main loop).
Run this in the ORCHESTRATOR MAIN LOOP, never in a subagent — STEP 2 may Run this in the ORCHESTRATOR MAIN LOOP, never in a subagent — STEP 2 may
talk to the human. Mandatory passage in every flow; questions are optional talk to the human, at contract time (pass A) and again at the flow's PLAN
and proportional — a complete request goes through silently. step (pass B). Questions follow the open choices, never a quota — a complete
request goes through silently.
## STEP 1 — CAPTURE (verbatim) ## STEP 1 — CAPTURE (verbatim)
@@ -17,16 +18,51 @@ message). No paraphrase, no cleanup, no translation, no summarizing. This
section is IMMUTABLE for the life of the run — every later consumer section is IMMUTABLE for the life of the run — every later consumer
(planner, dev, verifier) reads THESE words, never a restatement. (planner, dev, verifier) reads THESE words, never a restatement.
## STEP 2 — AMBIGUITY CHECK (questions optional, proportional) ## STEP 2 — CLARIFY (ask, never guess)
Ask ONLY if one of these is missing AND not derivable from the repo: Two passes, both in the main loop, both may talk to the human.
**Pass A — gaps.** Run here, against the request. Ask if one of these is
missing AND not derivable from the repo:
- a testable expected outcome - a testable expected outcome
- an unambiguous scope (what is allowed to change) - an unambiguous scope (what is allowed to change)
- non-contradictory constraints - non-contradictory constraints
Complete request → ZERO questions, stay silent. Otherwise: max 3 questions, **Pass B — open choices.** Defined here, run ONCE at the flow's PLAN step
one single batch (house rule: one question upfront, never mid-task). Never (see "Where pass B fires" below), against the plan just written — that is
ask what the repo can answer — verify paths/APIs/behavior yourself first. where choices become concrete. Enumerate every choice the run will settle
that the request leaves open; keep those in these classes:
1. VISIBLE — the user would see it in the result: placement, label, wording,
color, order, what a click does.
2. PUBLIC NAME — a name that outlives the run: command, flag, endpoint, env
var, a file the human will read.
3. SCOPE — "should X change too?", where the request does not name X.
NEVER ask class 4 — internal technical choices with no observable effect
(function decomposition, data shape, local naming, layout inside an
already-scoped zone). Those are delegated; asking them is the noise that
makes classes 1-3 ignorable. Never ask what the repo or the request already
answers — verify paths/APIs/behavior yourself first.
No question cap. Each pass asks what it finds, in ONE batch. A request that
leaves nothing open goes through silently. More than 5 open choices in pass B
= the request is under-specified: list them, say so, stop — do not fire a
questionnaire. "You decide" / "peu importe" is an answer: record it as
`A: delegated — <default taken>` and never re-ask it.
Pass B answers land in the contract's CLARIFICATIONS marked
`[gated <YYYY-MM-DD>]` — the contract is already on disk by then.
### Where pass B fires
| Flow | Pass B runs at | Against |
|------|----------------|---------|
| feat | STEP 1 PLAN, before 1b CHALLENGE | the PLAN checklist |
| bugfix | STEP 3 FIX PLAN, before 3b | the FIX PLAN |
| hotfix | STEP 1 LOCATE | the 1-2 target files' visible effect |
| ship-feature | STEP 2 PLAN, after the brainstorm | the plan, minus what the brainstorm settled |
| init-project | STEP 3 DESIGN, before VALIDATION GATE #1 | the DESIGN, minus what the interview and brainstorm settled |
| onboard | its STEP 3 interview, unchanged | scope, in one block |
## STEP 3 — DERIVE ## STEP 3 — DERIVE
@@ -85,7 +121,7 @@ Template:
<the user's exact words> <the user's exact words>
## CLARIFICATIONS ## CLARIFICATIONS
Q: <question> / A: <answer> Q: <question> / A: <answer> (pass B and mid-run entries: [gated <YYYY-MM-DD>])
(or: none — request complete) (or: none — request complete)
## ACCEPTANCE CRITERIA ## ACCEPTANCE CRITERIA
@@ -105,6 +141,33 @@ Q: <question> / A: <answer>
Print one line to the user, then continue the flow: Print one line to the user, then continue the flow:
`CONTRACT: <path> — <n> criteria, scope <files|repo-wide>, <q> questions asked` `CONTRACT: <path> — <n> criteria, scope <files|repo-wide>, <q> questions asked`
## MID-RUN CLARIFICATION (the channel executors halt into)
An executor cannot talk to the human. It halts with `NEED-DECISION`, the
exact question, the options it sees, and a `CLASS:` tag (visible |
public-name | scope | internal). `/hotfix`: the hotfixer keeps
`DONE | BLOCKED`; a BLOCKED carrying the tag follows the same routing instead
of escalating to `/bugfix`. The orchestrator re-reads the class — the tag is
a hint, not a verdict — then routes:
- visible / public-name / scope → ASK THE HUMAN, verbatim question and
options. Never decide these yourself, never spend a round-trip guessing.
- internal → decide here, note the decision, re-dispatch. The only case the
orchestrator settles alone; max 2 such round-trips → escalate.
Every answer, human or orchestrator, appends to the contract's
CLARIFICATIONS marked `[gated <YYYY-MM-DD>]` — the same micro-gate as scope
enrichment — and to the plan handed to the FRESH re-dispatched executor,
which reads the decision from disk, never from a transcript.
## HOW TO ASK (LRN-102)
The harness reliably renders only the turn's FINAL text; text printed before
a tool call may be swallowed. So:
- up to 4 questions → one `AskUserQuestion` call; option descriptions carry
the context; print nothing the user needs before the call.
- more than 4, or a list handed back for re-specification → plain text, end
the turn.
## Lifecycle ## Lifecycle
- **REQUEST**: immutable, for the life of the run. Never rewritten, never - **REQUEST**: immutable, for the life of the run. Never rewritten, never
@@ -134,7 +197,7 @@ Print one line to the user, then continue the flow:
| Flow | Weight | | Flow | Weight |
|------|--------| |------|--------|
| hotfix | Silent autofill — criteria: "symptom gone; build/tests green"; scope = the 1-2 target files. Zero questions ever. | | hotfix | Pass A silent autofill — criteria: "symptom gone; build/tests green"; scope = the 1-2 target files. Pass B runs at LOCATE against the 1-2 target files' visible effect; a typo fix asks nothing. |
| feat / bugfix | Proportional. bugfix: the DIAGNOSIS feeds the criteria (symptom reproduced-then-gone + regression test present). | | feat / bugfix | Proportional. bugfix: the DIAGNOSIS feeds the criteria (symptom reproduced-then-gone + regression test present). |
| ship-feature | Full. Design decisions approved at the validation gate append criteria `[gated <date>]` — the human validates the enriched contract, the verifier receives that version. | | ship-feature | Full. Design decisions approved at the validation gate append criteria `[gated <date>]` — the human validates the enriched contract, the verifier receives that version. |
| init-project | Full. The interviewer's PROJECT BRIEF pours into the contract (V1 features → criteria). | | init-project | Full. The interviewer's PROJECT BRIEF pours into the contract (V1 features → criteria). |
+9 -2
View File
@@ -48,8 +48,15 @@ fi
tf "verbatim request immutable" "$LIB" "REQUEST (verbatim — IMMUTABLE)" tf "verbatim request immutable" "$LIB" "REQUEST (verbatim — IMMUTABLE)"
tf "contracts dir committed path" "$LIB" ".claude/tasks/contracts/" tf "contracts dir committed path" "$LIB" ".claude/tasks/contracts/"
tf "unique per-run slug" "$LIB" "<YYYY-MM-DD>-<slug>-<HHMM>" tf "unique per-run slug" "$LIB" "<YYYY-MM-DD>-<slug>-<HHMM>"
tf "silent when complete" "$LIB" "ZERO questions" tf "silent when nothing open" "$LIB" "goes through silently"
tf "question budget" "$LIB" "max 3 questions" tf "no question cap" "$LIB" "No question cap"
tf "pass B classes" "$LIB" "PUBLIC NAME"
tf "class 4 excluded" "$LIB" "NEVER ask class 4"
tf "over-5 guard" "$LIB" "More than 5 open choices"
tf "delegated answer" "$LIB" "delegated —"
tf "mid-run channel" "$LIB" "## MID-RUN CLARIFICATION"
tf "class tag" "$LIB" "CLASS:"
tf "how to ask" "$LIB" "## HOW TO ASK"
tf "aborted status" "$LIB" "status: aborted" tf "aborted status" "$LIB" "status: aborted"
tf "never left dirty" "$LIB" "NEVER left dirty" tf "never left dirty" "$LIB" "NEVER left dirty"
tf "scope enrichment micro-gate" "$LIB" "micro-gate" tf "scope enrichment micro-gate" "$LIB" "micro-gate"
+3
View File
@@ -311,6 +311,9 @@ lock "bugfixer passes" "$BF" "## FOUR PASSES"
lock "bugfixer stays minimal" "$BF" "keep the fix minimal" lock "bugfixer stays minimal" "$BF" "keep the fix minimal"
lock "bugfixer neg control" "$BF" "**Negative control.**" lock "bugfixer neg control" "$BF" "**Negative control.**"
lock "bugfixer test must fail" "$BF" "A test that passes both ways" lock "bugfixer test must fail" "$BF" "A test that passes both ways"
lock "feater class tag" "$FE" "CLASS:"
lock "bugfixer class tag" "$BF" "CLASS:"
lock "hotfixer class tag" "$REPO/agents/hotfixer.md" "CLASS:"
echo "" echo ""
echo "gates: $PASS pass, $FAIL fail" echo "gates: $PASS pass, $FAIL fail"
+1 -1
View File
@@ -81,7 +81,7 @@ tf "hotfixer report grammar" "$HOT" "HOTFIX-EXEC REPORT"
echo "── skills/hotfix/SKILL.md (hotfix wiring — revert, not loop) ──" echo "── skills/hotfix/SKILL.md (hotfix wiring — revert, not loop) ──"
tf "hotfix silent contract" "$HSKL" "STEP 1.7 — CONTRACT (silent autofill)" tf "hotfix silent contract" "$HSKL" "STEP 1.7 — CONTRACT (silent autofill)"
tf "hotfix zero questions" "$HSKL" "questions ever" tf "hotfix pass B at locate" "$HSKL" "run pass B of"
tf "hotfix security gate" "$HSKL" "Security gate (fresh auditor)" tf "hotfix security gate" "$HSKL" "Security gate (fresh auditor)"
tf "hotfix block reverts" "$HSKL" "failure REVERTS, never loops" tf "hotfix block reverts" "$HSKL" "failure REVERTS, never loops"
tf "hotfix no verifier" "$HSKL" "No verifier is dispatched at hotfix weight" tf "hotfix no verifier" "$HSKL" "No verifier is dispatched at hotfix weight"
+11 -5
View File
@@ -116,6 +116,10 @@ RISK: <low/medium — what could go wrong>
obvious fix. obvious fix.
- If the fix is significant (>10 lines, multiple files, - If the fix is significant (>10 lines, multiple files,
behavior change): wait for user approval. behavior change): wait for user approval.
- Then run pass B of `$HOME/.claude/lib/contract-interview.md` against the
FIX PLAN: every VISIBLE / PUBLIC NAME / SCOPE choice it settles that the
bug report left open → one batch of questions, before STEP 3b. The trivial
fast-path is not exempt: a 1-line fix with a visible choice still asks.
## STEP 3b — CHALLENGE THE FIX PLAN (before the contract) ## STEP 3b — CHALLENGE THE FIX PLAN (before the contract)
Unless the fix is the trivial 1-2 line case STEP 3 already fast-paths, the Unless the fix is the trivial 1-2 line case STEP 3 already fast-paths, the
@@ -135,8 +139,8 @@ the STEP 3 approval gate.
Run `$HOME/.claude/lib/contract-interview.md` (main loop). The DIAGNOSIS Run `$HOME/.claude/lib/contract-interview.md` (main loop). The DIAGNOSIS
feeds it: REQUEST verbatim = the bug report as received; ACCEPTANCE CRITERIA feeds it: REQUEST verbatim = the bug report as received; ACCEPTANCE CRITERIA
= the symptom reproduced-then-gone + a regression test present and passing; = the symptom reproduced-then-gone + a regression test present and passing;
FILE SCOPE = the FIX PLAN files. Questions stay proportional (a clear, FILE SCOPE = the FIX PLAN files. Pass A only here (pass B ran at STEP 3); a
reproduced bug → zero). It writes the contract to clear, reproduced bug asks nothing. It writes the contract to
`.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`; keep the path — the `.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`; keep the path — the
executor reads it first and GATE 1 (STEP 6) hands it to a fresh verifier. executor reads it first and GATE 1 (STEP 6) hands it to a fresh verifier.
@@ -162,9 +166,11 @@ ops, no security dispatch. Finish with the BUGFIX-EXEC REPORT."
Parse the `BUGFIX-EXEC REPORT`: Parse the `BUGFIX-EXEC REPORT`:
- `STATUS : DONE` → STEP 6. - `STATUS : DONE` → STEP 6.
- `STATUS : NEED-DECISION` → make the decision HERE (that is reflection), - `STATUS : NEED-DECISION` → route on its `CLASS:` per MID-RUN CLARIFICATION
append it to the plan, re-dispatch a FRESH bugfixer with plan + decision. in `$HOME/.claude/lib/contract-interview.md`: visible / public-name / scope
Max 2 decision round-trips → escalate to the user. → ask the user, verbatim; internal → decide HERE (max 2 such round-trips
→ escalate). Append the answer to the contract `[gated]` and to the plan,
re-dispatch a FRESH bugfixer with plan + decision.
- `STATUS : BLOCKED` → surface the blocker to the user, stop. - `STATUS : BLOCKED` → surface the blocker to the user, stop.
## STEP 6 — VERIFY + SECURE + PRE-COMMIT GATE + COMMIT (main loop, LRN-083) ## STEP 6 — VERIFY + SECURE + PRE-COMMIT GATE + COMMIT (main loop, LRN-083)
+15 -10
View File
@@ -85,9 +85,9 @@ MEMORY; feed STEP 1 PLAN. Inline consumption — reader = planner, no injection.
## STEP 0.7 — CONTRACT ## STEP 0.7 — CONTRACT
Run `$HOME/.claude/lib/contract-interview.md` (main loop — you are it). It Run `$HOME/.claude/lib/contract-interview.md` (main loop — you are it). It
captures the request verbatim, asks 0-3 questions PROPORTIONAL to ambiguity captures the request verbatim, runs pass A (gaps: outcome, scope,
(a complete request → zero questions, silent), derives testable acceptance constraints — a complete request goes through silently), derives testable
criteria + file scope, and writes the contract to acceptance criteria + file scope, and writes the contract to
`.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`. Keep the path — the `.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`. Keep the path — the
executor reads it first and GATE 1 (STEP 4) hands it to a fresh verifier. executor reads it first and GATE 1 (STEP 4) hands it to a fresh verifier.
@@ -114,8 +114,11 @@ PLAN:
[ ] <test file> — <test to add> [ ] <test file> — <test to add>
``` ```
If the approach is ambiguous: ask the user ONE focused question BEFORE Then run pass B of `$HOME/.claude/lib/contract-interview.md` against this
dispatching — never after (the executor cannot relay questions). plan: every VISIBLE / PUBLIC NAME / SCOPE choice the plan settles that the
request left open → one batch of questions BEFORE dispatching; answers land
in the contract's CLARIFICATIONS `[gated]` and in the plan. A choice that
surfaces only during execution comes back as `NEED-DECISION` (STEP 3).
## STEP 1b — CHALLENGE THE PLAN (before branching) ## STEP 1b — CHALLENGE THE PLAN (before branching)
The STEP 1 plan is a reflection worth attacking before a branch is spent on it. The STEP 1 plan is a reflection worth attacking before a branch is spent on it.
@@ -125,8 +128,8 @@ Persist it to `.claude/tasks/plans/<date>-<slug>-<HHMM>.md`, then run
Three blind challengers attack it; RE-THINK every aspect a BLOCKER lands (a named Three blind challengers attack it; RE-THINK every aspect a BLOCKER lands (a named
plan change, or `[deferred]`), re-challenge once if the plan materially changed. The plan change, or `[deferred]`), re-challenge once if the plan materially changed. The
STEP 3 executor receives the REVISED plan. Before dispatch, print a CHALLENGE SUMMARY STEP 3 executor receives the REVISED plan. Before dispatch, print a CHALLENGE SUMMARY
(BLOCKERs addressed / deferred / lenses returned), surfacing any deferred BLOCKER via (BLOCKERs addressed / deferred / lenses returned), surfacing any deferred BLOCKER in
STEP 1's one-question gate. the STEP 1 pass B batch.
## STEP 2 — BRANCH ## STEP 2 — BRANCH
@@ -150,9 +153,11 @@ Finish with the FEAT-EXEC REPORT."
Parse the `FEAT-EXEC REPORT`: Parse the `FEAT-EXEC REPORT`:
- `STATUS : DONE` → STEP 4. - `STATUS : DONE` → STEP 4.
- `STATUS : NEED-DECISION` → make the decision HERE (that is reflection), - `STATUS : NEED-DECISION` → route on its `CLASS:` per MID-RUN CLARIFICATION
append it to the plan, re-dispatch a FRESH feater with plan + decision. in `$HOME/.claude/lib/contract-interview.md`: visible / public-name / scope
Max 2 decision round-trips → escalate to the user. → ask the user, verbatim; internal → decide HERE (max 2 such round-trips
→ escalate). Append the answer to the contract `[gated]` and to the plan,
re-dispatch a FRESH feater with plan + decision.
- `STATUS : BLOCKED` → surface the blocker to the user, stop. - `STATUS : BLOCKED` → surface the blocker to the user, stop.
## STEP 4 — VERIFY + SECURE (fresh gates, bounded loops) ## STEP 4 — VERIFY + SECURE (fresh gates, bounded loops)
+19 -7
View File
@@ -47,6 +47,10 @@ git log --oneline -3
as `/bugfix` (root-cause investigation, then a scoped fix)." as `/bugfix` (root-cause investigation, then a scoped fix)."
- Settle the proposed fix HERE — the executor cannot ask questions, so the - Settle the proposed fix HERE — the executor cannot ask questions, so the
exact edit (what changes, in which file(s)) must be closed before dispatch. exact edit (what changes, in which file(s)) must be closed before dispatch.
- Then run pass B of `$HOME/.claude/lib/contract-interview.md` against that
edit: a VISIBLE / PUBLIC NAME / SCOPE choice the bug description leaves
open (which way the icon aligns, the label's wording) → ask before
dispatch. A typo or a wrong value asks nothing.
OPTIONAL — memory check (exempt by default; hotfix = obvious fix, mirror of its capitalize OPTIONAL — memory check (exempt by default; hotfix = obvious fix, mirror of its capitalize
skip). For a RECURRING or urgent bug only, a quick blockers-only glance may save time: skip). For a RECURRING or urgent bug only, a quick blockers-only glance may save time:
@@ -66,8 +70,9 @@ Follow `$HOME/.claude/lib/design-gate.md`:
## STEP 1.7 — CONTRACT (silent autofill) ## STEP 1.7 — CONTRACT (silent autofill)
Run `$HOME/.claude/lib/contract-interview.md` at hotfix weight: **zero Run `$HOME/.claude/lib/contract-interview.md` at hotfix weight: pass A is a
questions ever** (a hotfix is an obvious fix by definition). Autofill the silent autofill (a hotfix is an obvious fix by definition); pass B already
ran at STEP 1, ask nothing more here. Autofill the
contract — REQUEST verbatim = the bug description as given; ACCEPTANCE contract — REQUEST verbatim = the bug description as given; ACCEPTANCE
CRITERIA = "symptom gone; build/tests green"; FILE SCOPE = the 1-2 target CRITERIA = "symptom gone; build/tests green"; FILE SCOPE = the 1-2 target
files from STEP 1. It writes `.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`. files from STEP 1. It writes `.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`.
@@ -135,8 +140,14 @@ security dispatch, no revert. Finish with the HOTFIX-EXEC REPORT."
Parse the `HOTFIX-EXEC REPORT`: Parse the `HOTFIX-EXEC REPORT`:
- `STATUS : DONE` → STEP 4 (the SMOKE line in the report decides pass/fail - `STATUS : DONE` → STEP 4 (the SMOKE line in the report decides pass/fail
there; DONE here means execution completed, not that it verified clean). there; DONE here means execution completed, not that it verified clean).
- `STATUS : BLOCKED` → if any edits were made, revert ONLY the executor's - `STATUS : BLOCKED` with `CLASS: visible | public-name | scope` in NOTES →
files: `git restore --source=$PRE -- <FILE(S) from the report>` and delete the executor halted at an open choice before editing (nothing to revert):
ask the user per MID-RUN CLARIFICATION in
`$HOME/.claude/lib/contract-interview.md`, append the answer to the
contract `[gated]`, re-dispatch ONCE with the closed choice. This is the
one re-dispatch hotfix allows; it is not a retry of a failed attempt.
- `STATUS : BLOCKED` otherwise → if any edits were made, revert ONLY the
executor's files: `git restore --source=$PRE -- <FILE(S) from the report>` and delete
any NEW file the report lists (untracked, absent from $PRE). Never any NEW file the report lists (untracked, absent from $PRE). Never
`git restore .` — it would wipe the tolerated pre-existing edits too. `git restore .` — it would wipe the tolerated pre-existing edits too.
Surface the blocker to the user; STOP. One attempt only — hotfix never Surface the blocker to the user; STOP. One attempt only — hotfix never
@@ -227,9 +238,10 @@ trivial hotfix still produces a `chore(memory): journal — …` commit (Frame 2
- Reflection (LOCATE, contract, gate decisions) NEVER leaves this main - Reflection (LOCATE, contract, gate decisions) NEVER leaves this main
loop; execution NEVER stays in it — the executor is the sonnet-pinned loop; execution NEVER stays in it — the executor is the sonnet-pinned
hotfixer subagent (BDR-066). hotfixer subagent (BDR-066).
- The executor is dispatched FRESH, once — hotfix never re-dispatches (no - The executor is dispatched FRESH, once — hotfix never re-dispatches after
decision round-trips; a blocked or failed attempt reverts and escalates a failed or blocked attempt (it reverts and escalates to `/bugfix`, it
to `/bugfix`, it does not retry). does not retry). Sole exception: a class-tagged BLOCKED answered by the
user (STEP 3), re-dispatched once with the closed choice.
- Design gate only if CSS/style signals detected. See STEP 1.5. - Design gate only if CSS/style signals detected. See STEP 1.5.
- **Revert-not-loop preserved**: smoke FAIL or security BLOCK → - **Revert-not-loop preserved**: smoke FAIL or security BLOCK →
file-scoped revert from `$PRE` (STEP 4's protocol — never `git file-scoped revert from `$PRE` (STEP 4's protocol — never `git
+5 -2
View File
@@ -58,8 +58,8 @@ In both cases: MANDATORY STOP until user answers remaining questions. Produce PR
**Then run `$HOME/.claude/lib/contract-interview.md`** seeded from the BRIEF: **Then run `$HOME/.claude/lib/contract-interview.md`** seeded from the BRIEF:
REQUEST verbatim = the user's project description; ACCEPTANCE CRITERIA = the REQUEST verbatim = the user's project description; ACCEPTANCE CRITERIA = the
V1 FEATURES (each testable); FILE SCOPE = the planned tree. No new questions V1 FEATURES (each testable); FILE SCOPE = the planned tree. Pass A is covered
(the interview already asked). It writes by the interview; pass B runs at STEP 3 against the DESIGN. It writes
`.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`; the DESIGN approved at STEP `.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`; the DESIGN approved at STEP
4 ENRICHES it, and STEP 9's verifier judges the MVP against the enriched 4 ENRICHES it, and STEP 9's verifier judges the MVP against the enriched
contract. contract.
@@ -70,6 +70,9 @@ Load `$HOME/.claude/agents/analyzer.md`. Analyze BRIEF: existing code, stack con
## STEP 3 — DESIGN ## STEP 3 — DESIGN
Invoke `superpowers:brainstorming` with BRIEF + ANALYSIS REPORT. Invoke `superpowers:brainstorming` with BRIEF + ANALYSIS REPORT.
Produce DESIGN: stack+versions, full folder tree, module responsibilities, data flow, interfaces (signatures only), config+tooling, test strategy, resolved decisions, prereqs list. Produce DESIGN: stack+versions, full folder tree, module responsibilities, data flow, interfaces (signatures only), config+tooling, test strategy, resolved decisions, prereqs list.
Then run pass B of `$HOME/.claude/lib/contract-interview.md` against the DESIGN
(minus what the BRIEF and the brainstorm settled): one batch before STEP 4;
answers append to the contract `[gated]`.
## STEP 4 — VALIDATION GATE #1 ★ MANDATORY STOP ## STEP 4 — VALIDATION GATE #1 ★ MANDATORY STOP
Present: Present:
+4
View File
@@ -116,6 +116,10 @@ Refine request into validated design via Socratic questioning. Don't proceed unt
Invoke `superpowers:writing-plans` with the validated design AND the 0d digest: every task Invoke `superpowers:writing-plans` with the validated design AND the 0d digest: every task
must be consistent with the in-force constraints; where a task implements or affects one, must be consistent with the in-force constraints; where a task implements or affects one,
note the ID inline. Break design into tasks (2-5 min each). Each task: exact file paths, full code, verification steps. note the ID inline. Break design into tasks (2-5 min each). Each task: exact file paths, full code, verification steps.
Then run pass B of `$HOME/.claude/lib/contract-interview.md` against the plan:
every VISIBLE / PUBLIC NAME / SCOPE choice the plan settles that neither the
request nor the STEP 1 brainstorm settled (check the contract's CLARIFICATIONS
first) → one batch before STEP 2b; answers append to the contract `[gated]`.
## STEP 2b — CHALLENGE THE PLAN (adversarial, before the gate) ## STEP 2b — CHALLENGE THE PLAN (adversarial, before the gate)
Before the human sees the plan, harden it. Run `$HOME/.claude/lib/challenge-plan.md`: Before the human sees the plan, harden it. Run `$HOME/.claude/lib/challenge-plan.md`: