mandrel 2.13.0 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/.agents/audit-checklists/navigability.md +1 -1
  2. package/.agents/docs/workflows.md +4 -5
  3. package/.agents/schemas/story-deliver-terminal.schema.json +60 -6
  4. package/.agents/scripts/acceptance-eval.js +18 -1
  5. package/.agents/scripts/agents-bootstrap-github.js +22 -1
  6. package/.agents/scripts/apply-quality-bootstrap.js +6 -0
  7. package/.agents/scripts/audit-labels-bootstrap.js +15 -1
  8. package/.agents/scripts/audit-to-stories.js +26 -1
  9. package/.agents/scripts/boot-sweep.js +4 -1
  10. package/.agents/scripts/bootstrap.js +1 -0
  11. package/.agents/scripts/check-arch-cycles.js +20 -0
  12. package/.agents/scripts/check-baselines.js +8 -2
  13. package/.agents/scripts/check-context-budget.js +40 -5
  14. package/.agents/scripts/check-dead-exports.js +21 -0
  15. package/.agents/scripts/check-doc-links.js +12 -1
  16. package/.agents/scripts/check-lifecycle-doc-drift.js +9 -0
  17. package/.agents/scripts/check-workflow-citations.js +332 -0
  18. package/.agents/scripts/deliver-light.js +71 -9
  19. package/.agents/scripts/deliver-recover.js +4 -1
  20. package/.agents/scripts/diagnose-friction.js +17 -1
  21. package/.agents/scripts/diagnose.js +20 -14
  22. package/.agents/scripts/drain-pending-cleanup.js +20 -1
  23. package/.agents/scripts/evidence-gate.js +20 -1
  24. package/.agents/scripts/generate-config-docs.js +14 -1
  25. package/.agents/scripts/generate-lifecycle-docs.js +14 -1
  26. package/.agents/scripts/generate-workflows-doc.js +14 -1
  27. package/.agents/scripts/git-cleanup.js +32 -1
  28. package/.agents/scripts/lib/cli-usage.js +174 -0
  29. package/.agents/scripts/lib/cli-utils.js +12 -0
  30. package/.agents/scripts/lib/doc-tiers.js +53 -10
  31. package/.agents/scripts/lib/orchestration/plan-context.js +16 -11
  32. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +122 -6
  33. package/.agents/scripts/lib/workflow-closure.js +431 -0
  34. package/.agents/scripts/mandrel-update-preflight.js +9 -0
  35. package/.agents/scripts/nav-registry-diff.js +13 -0
  36. package/.agents/scripts/plan-context.js +17 -1
  37. package/.agents/scripts/plan-critics.js +10 -0
  38. package/.agents/scripts/plan-persist.js +33 -1
  39. package/.agents/scripts/plan-run-epilogue.js +12 -1
  40. package/.agents/scripts/quality-preview.js +17 -1
  41. package/.agents/scripts/resolve-doc-tiers.js +13 -0
  42. package/.agents/scripts/resolve-stories.js +1 -0
  43. package/.agents/scripts/resync-status-column.js +4 -1
  44. package/.agents/scripts/signals-view.js +11 -0
  45. package/.agents/scripts/single-story-close.js +24 -0
  46. package/.agents/scripts/single-story-confirm-merge.js +16 -0
  47. package/.agents/scripts/single-story-init.js +21 -1
  48. package/.agents/scripts/stories-wave-tick.js +1 -0
  49. package/.agents/scripts/sync-agentrc.js +16 -4
  50. package/.agents/scripts/update-ticket-state.js +23 -2
  51. package/.agents/workflows/audit-navigability.md +2 -2
  52. package/.agents/workflows/audit-to-stories.md +1 -1
  53. package/.agents/workflows/deliver.md +80 -81
  54. package/.agents/workflows/git-cleanup.md +9 -14
  55. package/.agents/workflows/helpers/acceptance-self-eval.md +14 -13
  56. package/.agents/workflows/helpers/audit-lens-core.md +2 -2
  57. package/.agents/workflows/helpers/code-review.md +11 -11
  58. package/.agents/workflows/helpers/deliver-digest.md +7 -8
  59. package/.agents/workflows/helpers/deliver-light.md +196 -0
  60. package/.agents/workflows/helpers/deliver-reference.md +46 -14
  61. package/.agents/workflows/helpers/deliver-story-reference.md +55 -63
  62. package/.agents/workflows/helpers/deliver-story.md +22 -22
  63. package/.agents/workflows/helpers/mandrel-sync-config.md +2 -2
  64. package/.agents/workflows/helpers/parallel-tooling.md +1 -2
  65. package/.agents/workflows/helpers/plan-reference.md +72 -14
  66. package/.agents/workflows/helpers/worktree-lifecycle.md +1 -4
  67. package/.agents/workflows/mandrel-update.md +6 -6
  68. package/.agents/workflows/plan.md +86 -83
  69. package/docs/CHANGELOG.md +22 -0
  70. package/package.json +2 -1
  71. package/.agents/workflows/deliver-light.md +0 -117
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: >-
3
- The deliver path's one bundled framework read (Story #4736). Carries what
3
+ The deliver path's one bundled framework read. Carries what
4
4
  every Story delivery always needs — dispatch decision, engine invariants,
5
5
  the change-set/ceremony incantation, the acceptance-eval gate, and the
6
6
  terminal envelope contract — so the engine reads one file instead of
@@ -23,10 +23,10 @@ description: >-
23
23
  Read `stories[].dispatchMode` from the `resolve-stories.js` envelope. Two
24
24
  rules produce it, in order:
25
25
 
26
- 1. **Run topology (#4736).** A run resolving **one** Story is `inline`
26
+ 1. **Run topology.** A run resolving **one** Story is `inline`
27
27
  whatever its shape — sub-agent isolation is load-bearing only against a
28
28
  *concurrent* sibling racing the same checkout, and a one-Story run has none.
29
- 2. **Body shape (#4722).** In a multi-Story run, a lite-shaped body is
29
+ 2. **Body shape.** In a multi-Story run, a lite-shaped body is
30
30
  `inline`; a full-shaped body, an unparseable one, or a footprint touching a
31
31
  sensitive-path class is `subagent`. The `route::lite` label is a
32
32
  human-visible hint, never the control signal.
@@ -42,7 +42,6 @@ gates, same PR to `main`, same terminal envelope, byte for byte.
42
42
  | Ticket type | `type::story` only; an `Epic: #N` footer means **stop and re-plan** |
43
43
  | Branch | `story-<id>`, seeded from `project.baseBranch` (`main`) |
44
44
  | Merge target | `main` via PR (squash + required checks) — never a direct push |
45
- | Integration branch | **None** — no `epic/<id>`, no `--no-ff` wave merge |
46
45
  | Gates | Every close gate runs regardless of route; no route bypasses one |
47
46
  | State | Only via `update-ticket-state.js --ticket <id> --state <state>` |
48
47
  | Paths | Prefix every path-based tool with the absolute `workCwd` — `cd` does not scope them |
@@ -52,7 +51,7 @@ the only sanctioned landing. A silent local build is not a delivery.
52
51
 
53
52
  ## 3. Change set — computed once, handed to everyone
54
53
 
55
- One enumeration per Story (#4593). A critic that re-runs its own `git diff`
54
+ One enumeration per Story. A critic that re-runs its own `git diff`
56
55
  can score a different set than the one that routed it:
57
56
 
58
57
  ```bash
@@ -76,7 +75,7 @@ fresh. An `inline` dispatch mode overrides all of it to inline critics. Close's
76
75
 
77
76
  ## 4. Acceptance self-eval (Step 1a, required)
78
77
 
79
- **One verdict-owner per cluster** (#4723) — the fresh critic *or* the inline
78
+ **One verdict-owner per cluster** — the fresh critic *or* the inline
80
79
  self-eval, named by `verdictOwner`, never both and never a warm-up pass. It
81
80
  scores each `acceptance[]` item against the change set above, with `verify[]`
82
81
  output as evidence. Bounded by `delivery.acceptanceEval.maxRounds` (default 2).
@@ -96,7 +95,7 @@ Per-round mechanics: [`acceptance-self-eval.md`](acceptance-self-eval.md).
96
95
  `single-story-close.js` emits exactly one envelope on stdout between
97
96
  `--- STORY DELIVER TERMINAL ---` markers, schema-validated against
98
97
  [`story-deliver-terminal.schema.json`](../../schemas/story-deliver-terminal.schema.json)
99
- (#4543 — the SSOT; read the JSON only when you need a field this table omits).
98
+ — the SSOT; read the JSON only when you need a field this table omits.
100
99
  Relay it verbatim; never hand-compose one, never substitute prose.
101
100
 
102
101
  | `status` | Exit | Meaning | You do |
@@ -113,7 +112,7 @@ Required fields: `kind` (`story-deliver-terminal`), `storyId`, `status`,
113
112
  reports every gate as `passed` / `failed` / `skipped` — a skipped gate is
114
113
  reported, never omitted, so a missing gate is never read as a passing one.
115
114
 
116
- **Gate output is captured, not streamed (#4736).** Close writes gate lines to
115
+ **Gate output is captured, not streamed.** Close writes gate lines to
117
116
  `temp/orchestration/close-gates-<storyId>.log` and reports a one-line digest on
118
117
  success; a failed gate replays its tail inline. `AGENT_LOG_LEVEL=verbose`
119
118
  restores live streaming.
@@ -0,0 +1,196 @@
1
+ ---
2
+ description:
3
+ The unplanned prompt path shared by /deliver and /plan Gate #1. Judges a
4
+ prompt's predicted footprint, authors a receipt Story, then lands it through
5
+ the same single-story-init / single-story-close engine — every close gate
6
+ unchanged.
7
+ ---
8
+
9
+ # Unplanned delivery (the prompt path)
10
+
11
+ > **A path, not a command.** There is no `/deliver-light` to type. This file is
12
+ > reached two ways — `/deliver "<prompt>"` (an operator describing small work)
13
+ > and `/plan` Gate #1 (a seed the suggestion says fits the light ceilings, once
14
+ > the operator confirms). Read
15
+ > [`deliver-digest.md`](deliver-digest.md) once first — the engine invariants,
16
+ > gates, and terminal-envelope contract below are its.
17
+
18
+ ## Role
19
+
20
+ For a genuinely trivial change — a one-file fix, a small addition, a small
21
+ amendment — the multi-session plan→deliver ceremony buys nothing the bare model
22
+ lacks except **gates and landing**. This path keeps exactly those: one session
23
+ straight to execution from a prompt, landing through the unchanged close path.
24
+ It never relaxes a close gate, never bypasses the PR to `main`, and never lands
25
+ over-scope work silently.
26
+
27
+ Two callers, one gate: whichever door you arrived through, the suitability gate
28
+ below is the decision. A `/plan` Gate #1 suggestion is a *suggestion* — it is
29
+ read against seed-time signals (`DELIVER_LIGHT_SUGGESTION_CEILINGS`: artifacts,
30
+ risk hits, sensitive-path classes), while the gate here is read against a
31
+ predicted *shape* (`STORY_SHAPE_CEILINGS`: `maxChanges`, `maxAcceptance`). They
32
+ are deliberately two different checks, so the gate still runs after a confirm.
33
+
34
+ ## Four invariants (do not skip one)
35
+
36
+ 1. **Suitability gate.** The prompt's predicted footprint is judged by the
37
+ shared shape machinery (`deriveStoryShape` / `deriveChangeLevel`) **and** a
38
+ ledgered model verdict with a recorded reason. Both must agree on `lite`.
39
+ 2. **Over-scope stops — it never hard-fails.** An over-ceiling prompt STOPS and
40
+ asks the operator to escalate to `/plan` or proceed light. Under `--yes` it
41
+ fails closed to an **`escalated` terminal envelope** that ends the session
42
+ (§ Escalation is terminal).
43
+ 3. **Diff-derived backstop.** After implementation the ACTUAL change set is
44
+ re-checked — the diff is the real scope signal — and an over-ceiling diff is
45
+ blocked rather than landed.
46
+ 4. **Minimal receipt Story.** A `type::story` is authored inline so `refs #`,
47
+ history, telemetry, and the `agent::executing → agent::done` state machine
48
+ all survive.
49
+
50
+ ## Procedure
51
+
52
+ 1. **Predict + gate.** Form the predicted footprint (new files, edited files,
53
+ acceptance count) and your ledgered verdict (a recorded reason for `lite`),
54
+ then run the gate:
55
+
56
+ ```bash
57
+ node .agents/scripts/deliver-light.js --prompt "<prompt>" \
58
+ --creates <csv> --refactors <csv> --acceptance <n> \
59
+ --route lite --reason "<why this is trivial>" [--amends '#<id>'] [--yes]
60
+ ```
61
+
62
+ Branch on `action` in the JSON envelope:
63
+ - **`proceed-light`** — the receipt Story is authored; read `storyId` and
64
+ `nextCommands`. Continue to step 2.
65
+ - **`ask-operator`** — predicted scope exceeds the light ceilings. STOP and
66
+ ask the operator to escalate to `/plan` or proceed light. Do not proceed
67
+ on your own. This is a **question, not a terminal** — wait for the answer.
68
+ - **over-scope under `--yes`** — no `action` to branch on: the gate emits an
69
+ **`escalated` terminal envelope** instead (exit 2). § Escalation is
70
+ terminal governs; you are finished.
71
+
72
+ `--amends '#<id>'` is the canonical light case — shape-checked identically; a
73
+ heavy amendment escalates to `/plan` like any other over-scope prompt.
74
+
75
+ **Entered from `/plan` Gate #1?** Fill `--creates` / `--refactors` /
76
+ `--acceptance` / `--reason` from the plan-context envelope's codebase
77
+ snapshot and `complexitySignals` rather than re-deriving them from the seed
78
+ text — Gate #1 has already done that work, and re-deriving throws away the
79
+ better signal. An `ask-operator` verdict here means the two ceiling sets
80
+ disagreed: **return to [`../plan.md`](../plan.md) step 2 (Author) in the same
81
+ session**, carrying the interrogation you already paid for. That bounce-back
82
+ is not an escalation and does not need a fresh session (§ Why the two
83
+ directions differ).
84
+
85
+ 2. **Init (same engine).** From the main checkout, synchronously, with the
86
+ maximum Bash timeout:
87
+
88
+ ```bash
89
+ node .agents/scripts/single-story-init.js --story <storyId>
90
+ ```
91
+
92
+ Capture `workCwd`; `remoteVerified: false` → flip `agent::blocked` and stop.
93
+ This is [`/deliver`](../deliver.md)'s worktree/branch/lease/label engine,
94
+ invoked, not reimplemented.
95
+
96
+ 3. **Implement + self-eval.** `cd` into `workCwd`, implement the change, run
97
+ `npm test` once in the worktree, then run the bounded acceptance self-eval
98
+ loop ([`deliver-story.md`](deliver-story.md) Step 1a). Commit
99
+ on `story-<id>` with `(refs #<storyId>)`.
100
+
101
+ 4. **Diff backstop.** Before close, re-check the ACTUAL diff:
102
+
103
+ ```bash
104
+ node .agents/scripts/deliver-light.js --backstop --story <storyId>
105
+ ```
106
+
107
+ Exit `3` (`blocked: true`) means the landed diff exceeds the light ceilings
108
+ (file count or a sensitive-path class). STOP, flip `agent::blocked`, and
109
+ escalate to `/plan` — do not land.
110
+
111
+ 5. **Close and land (same engine).** Exactly [`/deliver`](../deliver.md)'s close:
112
+
113
+ ```bash
114
+ node .agents/scripts/single-story-close.js --story <storyId> --cwd <main-repo>
115
+ ```
116
+
117
+ Branch on the terminal envelope's `status` per
118
+ [`deliver-digest.md`](deliver-digest.md) § 5 — every close
119
+ gate runs byte-identical to the full path.
120
+
121
+ ## Escalation is terminal {#escalation-is-terminal}
122
+
123
+ Over-scope under `--yes` emits a schema-validated `story-deliver-terminal`
124
+ envelope with **`status: "escalated"`**, `storyId: null`, and a `nextCommand`
125
+ naming the `/plan` invocation that owns the work.
126
+
127
+ **That envelope IS this session's terminal output.** Relay it and stop. There is
128
+ no remaining step, no degraded fallback, and no smaller version of the work to
129
+ attempt.
130
+
131
+ **Invoking `/plan` in this same session is forbidden.** Hand the operator the
132
+ `nextCommand`; `/plan` runs in a **fresh** session.
133
+
134
+ This is not style — it is the empirical finding that motivated the envelope.
135
+ A mandrel-bench 2.13.0 light-arm run read the escalation and continued anyway:
136
+ it invoked `/plan` in-session and delivered. The in-session plan authored **one**
137
+ Story against the scenario's 3–5 contract, where a fresh `/plan` session on the
138
+ identical seed authored **four**. Planning inside a session already framed as
139
+ small work under-decomposes, so walking past the escalation silently produced
140
+ the very outcome the guard exists to prevent. The gate's decision was right both
141
+ times; only the outcome's finality was missing.
142
+
143
+ Nothing is left half-started: an escalated run creates **no receipt Story, no
144
+ `story-<id>` branch, and no worktree** — the escalation path returns before
145
+ every creation call site, and `escalation.created` records all three as `false`
146
+ in a shape the schema pins, so a later run finds nothing to trip over.
147
+
148
+ ## Why the two directions differ {#why-the-two-directions-differ}
149
+
150
+ Traffic runs both ways between this path and `/plan`, and the two directions
151
+ have **deliberately different session rules**. It reads like an inconsistency;
152
+ it is not. The rule:
153
+
154
+ > **The direction whose guard is model judgment must break the session. The
155
+ > direction whose guard is mechanical need not.**
156
+
157
+ **Light → `/plan` must be a fresh session.** What is being protected is
158
+ *authoring judgment*, and the empirical finding above is that a session already
159
+ framed as small work under-decomposes — one Story against a 3–5 contract where
160
+ a fresh session on the identical seed authored four. The frame is the hazard,
161
+ so only a new session removes it.
162
+
163
+ **`/plan` → light may stay in-session.** Gate #1 fires **before** authoring, so
164
+ there is no authoring to corrupt, and the frame at that point is "plan this
165
+ seed" — the neutral one, not the small one. Everything on the receiving side is
166
+ mechanical: `STORY_SHAPE_CEILINGS`, the ledgered verdict, the diff backstop.
167
+ None of them degrade because the context is large, so nothing is gained by
168
+ paying for a fresh session.
169
+
170
+ Do not "fix" this into symmetry in either direction. Making `/plan` → light
171
+ require a fresh session throws away a paid-for interrogation for no guard.
172
+ Letting light → `/plan` run in-session reintroduces the exact failure the
173
+ `escalated` envelope exists to prevent.
174
+
175
+ ## Constraints
176
+
177
+ - **Land, block, or escalate — never a silent local build.** The close push is
178
+ the only sanctioned landing; an `escalated` terminal is the only sanctioned
179
+ ending that delivers nothing, and it ends the session
180
+ (§ Escalation is terminal).
181
+ - **No parallel engine.** This path invokes `single-story-init.js` and
182
+ `single-story-close.js`; it never reimplements worktree, branch, PR, or merge
183
+ mechanics.
184
+ - **State only via `update-ticket-state.js`.** Drive every `agent::*`
185
+ transition through the script; report state, not process.
186
+
187
+ ## See also
188
+
189
+ - [`/deliver`](../deliver.md) — the delivery entry point; routes here on a
190
+ free-text prompt.
191
+ - [`/plan`](../plan.md) — routes here from Gate #1 on a confirmed suggestion,
192
+ and owns the work an over-scope prompt escalates to.
193
+ - [`deliver-story.md`](deliver-story.md) — the one Story delivery engine every
194
+ path shares.
195
+ - [`deliver-digest.md`](deliver-digest.md) — engine invariants, gates, and the
196
+ terminal-envelope contract.
@@ -9,7 +9,7 @@ description:
9
9
  # /deliver — reference appendix (on-demand)
10
10
 
11
11
  Reference-only detail split out of [`deliver.md`](../deliver.md) so the
12
- always-resident spine stays lean (Story #4708). Nothing here is a new MUST —
12
+ always-resident spine stays lean. Nothing here is a new MUST —
13
13
  it is the mechanics an operator consults when the matching lever is engaged.
14
14
 
15
15
  ## Sequencing edge cases (`stories-wave-tick.js`)
@@ -18,13 +18,13 @@ Each beat re-probes live state: it re-resolves the graph, classifies **done**
18
18
  (`agent::done` or a closed issue — including foreign blockers that landed in
19
19
  another run), and derives **in-flight** from live `agent::executing` /
20
20
  `agent::closing` labels. You never compute `done` or `in-flight` — that
21
- accounting is read from reality every beat (Story #4594).
21
+ accounting is read from reality every beat.
22
22
 
23
- **`--dispatched` is the one thing you must tell it (Story #4601).** List every
23
+ **`--dispatched` is the one thing you must tell it.** List every
24
24
  Story id you have spawned this run. Live state cannot instantly report a Story
25
25
  you dispatched moments ago: `single-story-init.js` publishes `agent::executing`
26
- before the worktree install (Story #4620 moved it ahead of the multi-minute
27
- install, so the window is now short rather than minutes-long), but it is not
26
+ before the worktree install (ahead of the multi-minute install, so the
27
+ window is short rather than minutes-long), but it is not
28
28
  zero — until the label lands the Story still reads `agent::ready` and, without
29
29
  `--dispatched`, the next beat would hand it back and a second sub-agent would
30
30
  join the first on the same branch and worktree, interleaving commits.
@@ -34,10 +34,10 @@ is additive, not authoritative — the probe unions it into the label-derived se
34
34
  and then filters it against live state, so an id that has since gone
35
35
  `agent::done` is dropped for you. Re-listing an id costs nothing and cannot
36
36
  double-count a slot; *omitting* one is the only way to get this wrong. This is
37
- why `--dispatched` is not the `--done` bookkeeping #4594 retired, and why
37
+ why `--dispatched` is not the retired `--done` bookkeeping, and why
38
38
  `--in-flight` remains rejected under `--probe-live`.
39
39
 
40
- **Cross-run de-confliction is automatic (Story #4620).** A Story another
40
+ **Cross-run de-confliction is automatic.** A Story another
41
41
  operator is delivering is withheld without any bookkeeping from you: the probe
42
42
  reads the Story's assignee lease and, when it belongs to a different operator,
43
43
  withholds the Story and reports it in the envelope's
@@ -51,7 +51,7 @@ probe logs a warning and leans on init's lease refusal alone.
51
51
 
52
52
  ## Dispatch mechanics (role-scoped by default)
53
53
 
54
- **A single-Story run executes inline (Story #4736).** Sub-agent isolation is
54
+ **A single-Story run executes inline.** Sub-agent isolation is
55
55
  load-bearing only for **concurrent** dispatch — two workers sharing a checkout
56
56
  would race on worktrees and branch refs — so a run resolving exactly one Story
57
57
  has no sibling to isolate from and pays the spawn premium for nothing (a boot is
@@ -61,7 +61,7 @@ a cache write at full rate; an inline continuation is a cache read at ~10%).
61
61
  retained in full for multi-Story waves, and the rule changes **where** the
62
62
  engine runs, never what runs — gates, PR, and terminal envelope are identical.
63
63
 
64
- **Lite-shaped Stories execute inline (Story #4722).** Before spawning anything,
64
+ **Lite-shaped Stories execute inline.** Before spawning anything,
65
65
  read the Story's `dispatchMode` from the resolver envelope
66
66
  (`stories[].dispatchMode`, derived by `resolveStoryDispatchMode` in
67
67
  `lib/orchestration/complexity-gate.js` **from the fetched Story body's own
@@ -91,9 +91,10 @@ prompt: `storyId`; `docsDigestPath` (the per-run docs digest, null when
91
91
  `project.docsContextFiles` is unset); `checklistPath` (the footprint-matched
92
92
  write-time audit checklist, produced at dispatch, below); and the
93
93
  **change-set discipline** — the worker computes the change set once with
94
- `computeChangeSet` and hands that one list to every acceptance critic (Story #4593); it never lets a critic re-derive the diff.
94
+ `computeChangeSet` and hands that one list to every acceptance critic; it
95
+ never lets a critic re-derive the diff.
95
96
 
96
- **Produce `checklistPath` before the spawn (Story #4627).** Compute the payload
97
+ **Produce `checklistPath` before the spawn.** Compute the payload
97
98
  from the Story's predicted footprint (its `changes[]` / `references[]` path
98
99
  entries) with `buildDispatchChecklist` and write it to the run temp dir, then
99
100
  thread the resulting path (empty when nothing matched):
@@ -124,6 +125,38 @@ execute it directly, in this turn, threading the same `docsDigestPath` /
124
125
  content, execute directly without a re-read turn. The engine, gates, and
125
126
  terminal envelope are identical either way — only the isolation differs.
126
127
 
128
+ ## Intent phrases (what replaced the flag table)
129
+
130
+ `/deliver` has no operator-facing flags. The scripts still take every flag they
131
+ always did — the workflow fills them in from what the operator said, the same
132
+ derive-then-announce contract `/git-deliver` uses for its terminal level.
133
+
134
+ | The operator says | You pass | Effect |
135
+ | --- | --- | --- |
136
+ | "I'll merge it myself", "don't wait", "just open the PR" | `--no-wait-merge` | Rest at `agent::closing` for a human land |
137
+ | "wait for the merge", "land it" | `--wait-merge` | Close-and-land — already the default (`delivery.routing.closeAndLand`) |
138
+ | "take the lease", "steal it", "it's mine, override" | `--steal` | Forwarded to `single-story-init.js` |
139
+ | "one at a time", "sequentially", "no parallelism" | `--concurrency 1` | Serialize a multi-Story run |
140
+ | "run <n> at once" | `--concurrency <n>` | One-run cap only |
141
+
142
+ Two rules keep this honest:
143
+
144
+ 1. **Announce before acting.** Name the intent you read and the flag it fills
145
+ in. A misread phrase is then visible in one line rather than discovered at
146
+ the terminal envelope.
147
+ 2. **Silence means config, not a literal.** With no intent phrase, omit the
148
+ flag entirely so `delivery.deliverRunner.concurrencyCap` (and any
149
+ `.agentrc.local.json` override) wins. Filling in the config default as a
150
+ literal silently defeats that override — the failure this table most easily
151
+ causes.
152
+
153
+ `--yes` is deliberately **absent** from the table. It is not an intent an
154
+ operator expresses; it is a runner asserting *nobody is at the keyboard*, and
155
+ it changes fail-closed behavior (it is what turns the unplanned path's
156
+ over-scope stop into an `escalated` terminal envelope, and what auto-proceeds
157
+ `/plan`'s gates). Cron, `/loop`, and headless dispatch set it. An attended run
158
+ never does, however the operator phrases their impatience.
159
+
127
160
  ## Operator-merge implies no-wait
128
161
 
129
162
  `--no-auto-merge` and `delivery.ci.autoMerge: "strict"` leave the PR
@@ -163,8 +196,7 @@ Ceremony depth is selected by `delivery.routing.ceremonyProfile`
163
196
  (`minimal` | `standard` | `strict`, default `standard`) and the **change level
164
197
  derived from the Story's own diff** — the changed files' intersection with the
165
198
  sensitive-path classes in `audit-rules.json`
166
- (`review-depth.js#deriveChangeLevel`), not a planner-authored verdict
167
- (Story #4542):
199
+ (`review-depth.js#deriveChangeLevel`), not a planner-authored verdict:
168
200
 
169
201
  | Profile | Acceptance critic | When to use |
170
202
  | --- | --- | --- |
@@ -179,7 +211,7 @@ sensitive-path classes in `audit-rules.json`
179
211
  | **Per-run (N>1)** | Audit roster · follow-up roll-up · sibling coherence | `plan-run-epilogue.js` once at run end |
180
212
  | **Per-Story land tail** | Follow-up capture · status resync · ref cleanup · base fast-forward | `single-story-close/phases/post-land.js` (in-process, per-step reported) |
181
213
 
182
- ## Async merge-confirm mode (`delivery.mergeWatch.mode: "async"`, Story #4698)
214
+ ## Async merge-confirm mode (`delivery.mergeWatch.mode: "async"`)
183
215
 
184
216
  A slow-CI consumer can opt the close into `"async"` mode so the merge wait
185
217
  probes once for ~60s (catching an instant merge or an instantly-red required