diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1ab1d8..bfc0ac7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,10 @@ Please choose versions by [Semantic Versioning](http://semver.org/).
* MINOR version when you add functionality in a backwards-compatible manner, and
* PATCH version when you make backwards-compatible bug fixes.
+## Unreleased
+
+- feat: `vault-cli:plan-task`'s fix loop now applies a gap that carries a stated fix and no genuine alternative, and asks the operator only for a real fork. It previously put every auditor finding to the operator as an `AskUserQuestion`, so a gap whose only defensible outcome was the one already written down still cost an interrupt β two workers hit it on 2026-10-17, and in both the operator picked the recommended option every time while the goal's manager independently gave the same answers. (A third was reported by the manager but carries no `AskUserQuestion` in its transcript, so it is not counted.) The loop now classifies each gap by one question ("is there a second answer I would defend?"), applies one-fix gaps via `Edit` and reports them as `π§ Applied: β¦`, and reserves the question for two-or-more genuine outcomes or an operator-only decision. A gap whose options would read *"(Recommended) do X Β· 2. do nothing"* is named as a one-fix gap wearing a menu. Applied fixes still re-enter the same `Score: X β Y` cycle and the `β₯ 8` gate is unchanged; the record is kept β every applied fix is printed and any that changed a criterion's claim is recorded in the task's `# Progress`, so the classification removes the question and never the audit trail. Three gap classes still always ask: an unevidenced premise (the fix is a read only the operator can vouch for), a misread operator quote, and a scope change. `--non-interactive` is untouched β its short-circuit still edits nothing. Rationale: `agent-cmd/no-user-prompts`, applied to plan-task's own fix loop.
+
## v0.169.5
- fix: `vault-cli:work-on-task-assistant` no longer states conclusions from evidence it merely grepped, and its report block list is declared closed. Dispatched 2026-10-17 to find a task and its guides, the agent added an unsanctioned `π¬ Independent read-only corroboration` block asserting the router log held "exactly one request" in a window that held 16 (five PIDs across four builds), and that "the absence of any worker-attributable line means the request did not arrive" β the opposite of the truth, since that router sampler-gates successful requests out of the log while always logging failures. The owning session had to re-derive both claims, and taken at face value they would have inverted the diagnosis. A second rule requires any inference to be marked `(inference β unverified)`: a log the agent did not write may be sampled, truncated, or shared by concurrent writers, and its silence rarely means absence.
diff --git a/commands/execute-task.md b/commands/execute-task.md
index 408c8bb..95a5412 100644
--- a/commands/execute-task.md
+++ b/commands/execute-task.md
@@ -204,7 +204,7 @@ Task lifecycle:
1. `/vault-cli:create-task` β capture (lenient)
2. `/vault-cli:work-on-task` β orient (status + guides + daily note), then auto-chain plan β execute (interactive)
-3. `/vault-cli:plan-task` β sharpen (5 hard gates); never flips phase
+3. `/vault-cli:plan-task` β sharpen (9 hard gates); never flips phase
4. **`/vault-cli:execute-task`** β the sole gate; flips planning β execution + prints first subtask + DoD reminder β this command
5. Start work β while working, use any of:
- `/vault-cli:update-task` β log completed work, sync to daily note / parent goal
diff --git a/commands/plan-task.md b/commands/plan-task.md
index 84d091b..e4c4ee4 100644
--- a/commands/plan-task.md
+++ b/commands/plan-task.md
@@ -18,7 +18,7 @@ Under NO-ASK, every point that would ask instead **reports and stops**:
- **Step 6 gaps** β do not enter the fix loop, do not `Edit` the task from assumed answers. Skip to step 7 and exit on the `β ` branch, listing each unresolved gap as a bullet phrased as the question you would have asked, so the operator can answer it on resume.
- **Step 5 soft KISS warning** β print it as a note; it never blocks exit on its own.
-Everything else is unchanged: entry-contract flips (step 3), the auditor run (step 4), and the five gate checks (step 5) all behave identically. A task whose gates pass clean produces the same `β
Plan ready` in both modes β NO-ASK only changes what happens to a task that has real gaps.
+Everything else is unchanged: entry-contract flips (step 3), the auditor run (step 4), and the nine gate checks (step 5) all behave identically. A task whose gates pass clean produces the same `β
Plan ready` in both modes β NO-ASK only changes what happens to a task that has real gaps.
## When to use
@@ -82,7 +82,7 @@ Task tool with:
### 5. Check the non-negotiables
-Six checks beyond the auditor's general scoring β first five are hard (any failure β mandatory question in step 6, can't exit on auditor score alone), sixth is a soft warning.
+Ten checks beyond the auditor's general scoring β nine hard (any failure β a step 6 gap, classified there as apply-or-ask; can't exit on auditor score alone), plus the KISS ceiling as the one soft warning. This list is the source of truth for the count; if you add or remove a check, update every "nine" below in the same pass.
**Hard:**
@@ -145,20 +145,20 @@ Six checks beyond the auditor's general scoring β first five are hard (any fai
**Note the scope of this item.** It sits inside a block that is skipped for non-shipping-class tasks (next line), yet the defect it catches is not shipping-specific β the 2026-09-21 case was a diagnosis task, where this gate never ran. `agents/task-auditor.md` Β§ 15 carries the same check and runs on every task; this item is the shipping-class enforcement, not the universal home.
Skip this whole check for non-shipping-class tasks (pure research, decision, doc-only with no published artifact).
-- **Subtask-goal alignment** β every `# Tasks` checkbox must either (a) map by topic to β₯ 1 `# Success Criteria` outcome, or (b) be the e2e verify subtask. Flag any orphan as a scope-creep candidate; in step 6 the owner can link it to an SC, move it to `# Out of Scope`, or split it into a separate task.
-- **Blast radius named** β if any subtask pushes to a registry, deploys, mutates a cluster, or needs a credential/secret, the task must name the external system AND the account written to (e.g. *"pushes `docker.io/bborbe/
` under the bborbe Docker Hub account"*). A credential requirement with no named target is a scope gap: the owner discovers what was automated at the secrets request, after the work has shipped. Observed 2026-08-27 β a publish-on-tag CI was designed, merged and released; the owner objected (*"Is the agent trying to push a docker image? I don't think that I want this"*) only when its Docker Hub secrets were requested, costing two reversal PRs for a net deletion. Flag β mandatory question in step 6.
-- **Resolution steps are resolvable** β a subtask naming a *lookup, join or key* (*"resolve the gate to its store `item_id`"*, *"look up the record by X"*) must be checked against whether that key actually exists and is derivable **by the actor that will run it**. This is the one hard check that is about the plan's *premise* rather than its shape: a subtask can name a concrete verb, a concrete artifact and a concrete outcome and still be unsatisfiable by construction. Ask of each: *do the two records share a field, and does the caller hold it?* Observed 2026-09-21 β a subtask read *"the sweep resolves the gate it is about to publish to a store `item_id`"*. No such join existed: the store wrote `item_id` itself, the producer's dedup key was a hash of a value the manager never holds, and the third candidate field was documented as `` β two kinds of value in one field, so it could not anchor an identity either. The same session's e2e-verify subtask also named no procedure and no expected result. **Two unsatisfiable-by-construction subtasks in one task is the signal that this check is missing, not that the author was careless** β and the cost is paid at execution, where the premise has already collapsed and the task file needs revising mid-flight. Flag β mandatory question in step 6.
+- **Subtask-goal alignment** β every `# Tasks` checkbox must either (a) map by topic to β₯ 1 `# Success Criteria` outcome, or (b) be the e2e verify subtask. Flag any orphan as a scope-creep candidate; in step 6 the owner can link it to an SC, move it to `# Out of Scope`, or split it into a separate task β a step 6 fork, since those are three defensible outcomes.
+- **Blast radius named** β if any subtask pushes to a registry, deploys, mutates a cluster, or needs a credential/secret, the task must name the external system AND the account written to (e.g. *"pushes `docker.io/bborbe/
` under the bborbe Docker Hub account"*). A credential requirement with no named target is a scope gap: the owner discovers what was automated at the secrets request, after the work has shipped. Observed 2026-08-27 β a publish-on-tag CI was designed, merged and released; the owner objected (*"Is the agent trying to push a docker image? I don't think that I want this"*) only when its Docker Hub secrets were requested, costing two reversal PRs for a net deletion. Flag β a step 6 gap, applied or asked per its classification there.
+- **Resolution steps are resolvable** β a subtask naming a *lookup, join or key* (*"resolve the gate to its store `item_id`"*, *"look up the record by X"*) must be checked against whether that key actually exists and is derivable **by the actor that will run it**. This is the one hard check that is about the plan's *premise* rather than its shape: a subtask can name a concrete verb, a concrete artifact and a concrete outcome and still be unsatisfiable by construction. Ask of each: *do the two records share a field, and does the caller hold it?* Observed 2026-09-21 β a subtask read *"the sweep resolves the gate it is about to publish to a store `item_id`"*. No such join existed: the store wrote `item_id` itself, the producer's dedup key was a hash of a value the manager never holds, and the third candidate field was documented as `` β two kinds of value in one field, so it could not anchor an identity either. The same session's e2e-verify subtask also named no procedure and no expected result. **Two unsatisfiable-by-construction subtasks in one task is the signal that this check is missing, not that the author was careless** β and the cost is paid at execution, where the premise has already collapsed and the task file needs revising mid-flight. Flag β a step 6 gap, applied or asked per its classification there.
-- **Premise matches the ask** β when `# Impact` quotes the operator verbatim, re-read the quote against Summary + Success Criteria. Flag when the quote admits more than one reading, or when an SC/constraint excludes a plausible reading of it (e.g. *"must NOT be named X"* when the quote says X). A plan can score 9/10 on shape and still build the wrong thing β the task writer's interpretation is not the operator's words. Observed 2026-09-23: *"add a open skill"* was read as an open-items skill (name `open` banned); the operator meant moving `/open` β `/supervisor:open` β found only after release. Flag β mandatory question in step 6, quoting both readings.
-- **Empirical premises are evidenced** β a `# Impact` or Summary asserting a fact about the running system (*"nothing else reads this DB"*, *"the data is disposable"*, *"X is unused"*, *"the functional window is one minute"*) is a premise the plan rests on, and the shape checks never reach it. This is the *system* sibling of the premise check above: that one compares the operator's quote to the plan, this one asks whether the plan's own factual premise is evidenced in the file. Ask of each: *does the task name the read that establishes this β a query, a log line, a config?* Absent it, flag β mandatory question in step 6. Observed: a task claimed *"the data is disposableβ¦ nothing else reads this DB"* and was audited 9/10 three times; the claim was false, and the change was built, merged and deployed, then reverted.
-- **Steps are runnable by the actor that owns the task** β a criterion or subtask naming a command the executing session's **tier** may not run is unsatisfiable by construction, however concrete it reads. `claude-supervisor`'s tiers are the common case: `/supervisor:open` and the `manager-*` / `fleet-*` verbs are manager-only, and a worker session must not run them. This is the *authority* sibling of the premise check above β that one asks whether the actor holds the **key**, this one whether it holds the **right**. Ask of each named command: *may the session that owns this task run it β and if not, does the criterion name who does?* Observed 2026-09-30 β an SC required *"one live run shows both halves β¦ read from that session's own output"*. The command was `/supervisor:open --flagged`, the task was worker-anchored, and the criterion was satisfiable only after the run was routed to a manager session. The plan had passed every shape check. Flag β mandatory question in step 6.
+- **Premise matches the ask** β when `# Impact` quotes the operator verbatim, re-read the quote against Summary + Success Criteria. Flag when the quote admits more than one reading, or when an SC/constraint excludes a plausible reading of it (e.g. *"must NOT be named X"* when the quote says X). A plan can score 9/10 on shape and still build the wrong thing β the task writer's interpretation is not the operator's words. Observed 2026-09-23: *"add a open skill"* was read as an open-items skill (name `open` banned); the operator meant moving `/open` β `/supervisor:open` β found only after release. Flag β a step 6 fork, never a one-fix gap (the operator's own words are the decision), quoting both readings.
+- **Empirical premises are evidenced** β a `# Impact` or Summary asserting a fact about the running system (*"nothing else reads this DB"*, *"the data is disposable"*, *"X is unused"*, *"the functional window is one minute"*) is a premise the plan rests on, and the shape checks never reach it. This is the *system* sibling of the premise check above: that one compares the operator's quote to the plan, this one asks whether the plan's own factual premise is evidenced in the file. Ask of each: *does the task name the read that establishes this β a query, a log line, a config?* Absent it, flag β a step 6 fork (unevidenced premise β see Β§ 6 *Three gaps always ask*); apply only when the read is yours to run. Observed: a task claimed *"the data is disposableβ¦ nothing else reads this DB"* and was audited 9/10 three times; the claim was false, and the change was built, merged and deployed, then reverted.
+- **Steps are runnable by the actor that owns the task** β a criterion or subtask naming a command the executing session's **tier** may not run is unsatisfiable by construction, however concrete it reads. `claude-supervisor`'s tiers are the common case: `/supervisor:open` and the `manager-*` / `fleet-*` verbs are manager-only, and a worker session must not run them. This is the *authority* sibling of the premise check above β that one asks whether the actor holds the **key**, this one whether it holds the **right**. Ask of each named command: *may the session that owns this task run it β and if not, does the criterion name who does?* Observed 2026-09-30 β an SC required *"one live run shows both halves β¦ read from that session's own output"*. The command was `/supervisor:open --flagged`, the task was worker-anchored, and the criterion was satisfiable only after the run was routed to a manager session. The plan had passed every shape check. Flag β a step 6 gap, applied or asked per its classification there.
**Routing a step to another tier has the same test, in reverse.** A step re-assigned to a manager must be one the manager contract permits β a manager never performs a row's work (no verification, no investigation) and never spawns `role: manager`. A worker's own SC probe stays the worker's; when it cannot run it, route it to the operator, not up the tier. Observed 2026-10-10: SC probes routed to a topic manager were declined at execution, forcing a re-ask.
**Soft:**
- **KISS ceiling** β if `# Tasks` has > 8 checkboxes, warn: *"task may be too large for one session β consider splitting, moving items to `# Out of Scope`, or promoting to a goal."* Owner decides; task can still proceed to execution.
-Any hard check failing β mandatory question in step 6; can't exit on auditor score alone. Soft check failing β surfaced as a question in step 6 but doesn't block exit if owner says proceed.
+Any hard check failing β a step 6 gap, resolved there by its classification (one-fix gaps applied, forks asked); can't exit on auditor score alone. Soft check failing β surfaced in step 6 but doesn't block exit if owner says proceed.
### 6. Surface gaps + fix loop
@@ -193,7 +193,20 @@ Any hard check failing β mandatory question in step 6; can't exit on auditor s
Only findings the auditor labelled `[template-level]` are verdict-coverable. An `[instance-level]` finding always asks, verdict or not.
-Translate findings (auditor + non-negotiable checks) into questions. Rules:
+**Classify every gap before you put it to anyone β a one-fix gap is applied, not asked.** Read each gap (auditor finding or failed non-negotiable) and sort it by one question: *is there a second answer I would defend?* (Under `--non-interactive` none of this applies β the NO-ASK short-circuit above still governs, and nothing is `Edit`ed.)
+
+- **One-fix gap β apply it, then report it.** The gap carries a stated fix and no genuine alternative β a missing `# Definition of Done`, a baseline to rebase, a window to pin, a criterion whose evidence shape is wrong. Apply the stated fix via `Edit` (re-running the step 2 ownership gate first) and print `π§ Applied: β `. Do not open an `AskUserQuestion` for it.
+- **Real fork β ask.** Two or more genuinely defensible outcomes, or a decision only the operator can make β scope, a production-touching step, which of two homes a rule belongs in. These are what the rules below are for.
+
+**The distinguishing test: write the second answer down before you ask.** State the alternative you would have offered. Cannot name one you would defend β one-fix gap, apply it. Can name two β fork, ask. A gap whose options would read *"(Recommended) do X Β· 2. do nothing"* is a one-fix gap wearing a menu: "do nothing" is a refusal to decide, not an alternative, and an operator who picks option 1 every time is telling you the menu should not have been built. This is `agent-cmd/no-user-prompts` reaching a case its own trigger already names β it covers `commands/**/*.md`, and plan-task's own fix loop is the prompt.
+
+**Report; never silently rewrite.** The classification removes the *question*, never the *record*. Print every applied fix, and when one changed a criterion's claim, record it in the task's `# Progress` β the operator must be able to see what plan-task decided on their behalf and reverse it. A silent rewrite is the failure mode this trades against; do not reintroduce it for brevity.
+
+**Applied fixes re-enter the loop.** They take the same `Score: X β Y` cycle as an answered question β re-run the auditor after each batch, and keep looping until score β₯ 8 AND all nine hard non-negotiables pass. The gate does not relax because nobody was asked.
+
+**Three gaps always ask, whatever they look like.** An **unevidenced premise** the plan rests on β the fix is a *read*, and only the operator can say whether it was taken. A **misread operator quote**, where `# Impact` quotes the operator and the plan's reading is one of two plausible ones β those are the operator's own words, so only they can settle it. And a **scope** change, where "apply the obvious fix" and "this task should not do that at all" are both live. For a premise, do the read first when it is cheap and in-scope, then report the result rather than asking; ask only when the read is not yours to run.
+
+Translate the remaining findings (auditor + non-negotiable checks) into questions. Rules:
- Max 3 questions per turn
- Each question is short (one sentence) + tight options (single yes/no OR 2-4 numbered options)
@@ -201,7 +214,7 @@ Translate findings (auditor + non-negotiable checks) into questions. Rules:
- Quote the offending line/section so owner sees what triggered the question
- Use `AskUserQuestion` for the actual ask
-Apply each answer via `Edit` β re-running the step 2 ownership gate first (see there). Re-run auditor after each batch. Print delta `Score: X β Y`. Loop until score β₯ 8 AND all five hard non-negotiables pass OR owner says "good enough." A current template verdict (see the template-verdict check above) satisfies the score gate for the findings it covers.
+Apply each answer via `Edit` β re-running the step 2 ownership gate first (see there). Re-run auditor after each batch. Print delta `Score: X β Y`. Loop until score β₯ 8 AND all nine hard non-negotiables pass OR owner says "good enough." A current template verdict (see the template-verdict check above) satisfies the score gate for the findings it covers.
**Propagate, don't just patch.** A reworded criterion is usually restated verbatim in `# Tasks` and `# Definition of Done`, and sometimes in the Summary and `# Out of Scope`. Edit every section that restates it in the same pass β a fix applied to the criterion alone leaves the plan still carrying the claim you just removed, and the next audit reports it as a *fresh* defect rather than the same one. That reads as a new problem, so the loop repairs the restatement instead of noticing the half-application, and burns a round per section. When an answer changes a criterion's claim, grep the task file for the old wording before re-running the auditor.
@@ -225,11 +238,11 @@ Under NO-ASK the score is whatever the auditor returned (nothing was fixed, so t
## Notes
-- **Scope is focused on what blocks safe execution.** Plan-task enforces five hard planning-gate checks (SC defined, subtasks reach goal, e2e verify subtask, subtask-goal alignment, blast radius named) plus the KISS ceiling as a soft sixth, because each one prevents a specific failure mode: missing outcomes, missing path, dishonest-tick verification, scope creep, an unnamed blast radius, oversize task. Other heuristics (MVP framing, Out-of-Scope capture quality, evidence shape) stay in `task-auditor` and `task-writing.md` as canonical rules β surfaced via the auditor in step 4, not promoted to dedicated gates. Letting the auditor enforce general structure while plan-task enforces the five named gates keeps the command short and the gates legible.
+- **Scope is focused on what blocks safe execution.** Plan-task enforces nine hard planning-gate checks β SC defined, subtasks reach goal, e2e verify subtask, subtask-goal alignment, blast radius named, resolution steps resolvable, premise matches the ask, empirical premises evidenced, steps runnable by the owning actor β plus the KISS ceiling as a soft tenth, because each one prevents a specific failure mode: missing outcomes, missing path, dishonest-tick verification, scope creep, an unnamed blast radius, an unsatisfiable-by-construction premise, a misread operator quote, an unevidenced system claim, a step the owning tier may not run, and oversize task. Other heuristics (MVP framing, Out-of-Scope capture quality) stay in `task-auditor` and `task-writing.md` as canonical rules β surfaced via the auditor in step 4, not promoted to dedicated gates. Letting the auditor enforce general structure while plan-task enforces the nine named gates keeps the gates legible.
- **Questions stay tight, with consequence visible.** 2-3 lines of setup β short options. "Tight" doesn't mean stripping context β owner must see what each answer *changes*. Quote the offending line, name the trade-off, then options.
- **Subtask granularity = session-sized.** When proposing or sharpening `# Tasks` items, target *work-block size* (a session's worth of work), not CLI-step size. Aim for 3-6 items per task. Reject auditor-suggested over-decomposition like "run precommit / open PR / merge PR" as separate subtasks β those collapse into one "ship the change" block.
- **Reads `~/.claude/plugins/marketplaces/vault-cli/docs/task-writing.md` as the canonical rule source** β same rules `task-auditor` enforces.
-- **Conversational on purpose.** Owner is the judge of substance. Plan-task never silently rewrites; every change comes from an explicit answer. This is exactly why `--non-interactive` refuses to guess: with no owner to answer, the honest move is to stop and list the gaps, never to invent answers and edit the task.
+- **Conversational on purpose β about substance, not about ratification.** Owner is the judge of substance: a genuine fork always goes to them. What changed is that a gap carrying one stated fix and no alternative is *applied* and reported rather than put to them as a question β asking there was a request to ratify, not a question, and it cost an interrupt per gap. Plan-task still never *silently* rewrites: every applied fix is printed in the run's output, and any that changed a criterion's claim is recorded in `# Progress`. This is also why `--non-interactive` refuses to guess: with no owner to answer, the honest move is to stop and list the gaps, never to invent answers and edit the task.
- **Entry contract.** A row at `phase: todo` is not planned by plan-task: it refuses, tells the operator the row is waiting in their approval inbox, and asks whether to approve it β running `vault-cli task approve` itself on the operator's explicit yes, and never without it. `vault-cli task approve` performs the `todo β planning` flip and records `approved_by`/`approved_at` β plan-task itself never flips a phase. No `/work-on-task` prerequisite for the approval itself. An **empty** phase is a different state, not a stricter one: it is not the approval inbox, `task approve` cannot accept it, and the entry path (`vault-cli task work-on`) is what advances it β plan-task reports the row as unentered and stops, rather than approving it or advancing the phase itself.
- **No phase flip.** plan-task never transitions phase; it validates and hands off to `/vault-cli:execute-task`, which owns the `planning β execution` flip. The `todo β planning` entry flip happens only through `vault-cli task approve` β step 3 writes no phase, it refuses an unapproved row and at most promotes `next` β `in_progress`.
- **Mechanical fixes stay in `/audit-task`.** This command is for substance (SC, subtasks, goal alignment), not formatting.
@@ -240,7 +253,7 @@ Task lifecycle:
1. `/vault-cli:create-task` β capture (lenient)
2. `/vault-cli:work-on-task` β orient (status + guides + daily note), then auto-chain into this command (both modes; headless callers pass `--non-interactive` through)
-3. **`/vault-cli:plan-task`** β sharpen (5 hard gates); never flips `planning β execution` β this command
+3. **`/vault-cli:plan-task`** β sharpen (9 hard gates); never flips `planning β execution` β this command
4. `/vault-cli:execute-task` β gate planning β execution; flips phase + prints first subtask + DoD reminder
5. Start work β while working, use any of:
- `/vault-cli:update-task` β log completed work, sync to daily note / parent goal