mandrel 2.11.0 → 2.13.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.
@@ -51,6 +51,16 @@ 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
55
+ load-bearing only for **concurrent** dispatch — two workers sharing a checkout
56
+ would race on worktrees and branch refs — so a run resolving exactly one Story
57
+ has no sibling to isolate from and pays the spawn premium for nothing (a boot is
58
+ a cache write at full rate; an inline continuation is a cache read at ~10%).
59
+ `resolve-stories.js` already reports it: a one-id run comes back with
60
+ `dispatchMode: "inline"` whatever the Story's shape. Role-scoped spawning is
61
+ retained in full for multi-Story waves, and the rule changes **where** the
62
+ engine runs, never what runs — gates, PR, and terminal envelope are identical.
63
+
54
64
  **Lite-shaped Stories execute inline (Story #4722).** Before spawning anything,
55
65
  read the Story's `dispatchMode` from the resolver envelope
56
66
  (`stories[].dispatchMode`, derived by `resolveStoryDispatchMode` in
@@ -114,6 +124,17 @@ execute it directly, in this turn, threading the same `docsDigestPath` /
114
124
  content, execute directly without a re-read turn. The engine, gates, and
115
125
  terminal envelope are identical either way — only the isolation differs.
116
126
 
127
+ ## Operator-merge implies no-wait
128
+
129
+ `--no-auto-merge` and `delivery.ci.autoMerge: "strict"` leave the PR
130
+ deliberately un-armed: there is nothing for close to land, so the Story rests
131
+ at `agent::closing` for the human merge and is **not** flipped to
132
+ `agent::blocked` — `--wait-merge` does not override this, because the operator
133
+ owning the merge is a decision to respect, not a fault to report. A genuine
134
+ *arm failure* is the opposite case: nobody chose it, so close still waits and
135
+ still blocks. That asymmetry is what keeps the must-land contract intact
136
+ without misfiling deliberate human merges as blocks.
137
+
117
138
  ## Per-run epilogue (N>1)
118
139
 
119
140
  Once the sequence reports `epilogueDue: true` (every Story done), keyed on the
@@ -341,6 +341,12 @@ The `single-story-close.js` script, in order:
341
341
 
342
342
  1. Runs the close-validation gates against `baseBranch` as the baseline.
343
343
  On any gate failure it throws — the operator fixes and re-runs close.
344
+ **Gate output is captured, not streamed (Story #4736).** Every gate line
345
+ goes to `temp/orchestration/close-gates-<storyId>.log`; a clean run reports
346
+ one digest line naming that artifact, and a **failed** gate replays its
347
+ captured tail inline so the evidence is in front of you without opening a
348
+ file. Read the artifact when you need the full text — or re-run under
349
+ `AGENT_LOG_LEVEL=verbose` for live streaming.
344
350
  1a. **Syncs the Story branch from `origin/<baseBranch>`** before push
345
351
  (Story #2580). Runs `git fetch origin <baseBranch>` followed by
346
352
  `git merge --no-edit origin/<baseBranch>` inside the worktree. This
@@ -11,6 +11,13 @@ description:
11
11
  > reference detail lives in
12
12
  > [`deliver-story-reference.md`](deliver-story-reference.md) ("reference"
13
13
  > below); consult on demand. Invoked by [`/deliver`](../deliver.md).
14
+ >
15
+ > **Read [`deliver-digest.md`](deliver-digest.md) once, first.** It is the
16
+ > one bundled read of what every delivery needs — dispatch decision, engine
17
+ > invariants, the change-set/ceremony incantation, the acceptance-eval gate,
18
+ > and the terminal-envelope contract — replacing the per-session re-reads of
19
+ > the helper set and `story-deliver-terminal.schema.json` (Story #4736). The
20
+ > steps below cite it as "digest § N" rather than restating it.
14
21
 
15
22
  ## Overview
16
23
 
@@ -74,15 +81,10 @@ One branch, one PR to `main`, commits against the inline `acceptance[]` /
74
81
 
75
82
  ### Step 1a — Bounded acceptance self-eval loop (**required**)
76
83
 
77
- Follow the single-homed include
78
- [`acceptance-self-eval.md`](acceptance-self-eval.md) (single verdict-owner,
79
- `verify[]`-as-evidence, proceed / redraft / block). Gate invocation (omit
80
- `--epic`):
81
-
82
- ```bash
83
- node <main-repo>/.agents/scripts/acceptance-eval.js \
84
- --story <storyId> --verdict <verdict-path>
85
- ```
84
+ Run the loop and score it with `acceptance-eval.js` — **digest § 4** carries
85
+ the invocation and the proceed / redraft / block contract; per-round critic
86
+ mechanics live in the single-homed include
87
+ [`acceptance-self-eval.md`](acceptance-self-eval.md).
86
88
 
87
89
  **`proceed`** → Step 2 then Step 3. **`block`** → **do not close**: post a
88
90
  `friction` comment and flip `agent::blocked` — commands and the
@@ -92,16 +94,12 @@ node <main-repo>/.agents/scripts/acceptance-eval.js \
92
94
  ## Step 2 — Ceremony (profile + derived level)
93
95
 
94
96
  Ceremony is `delivery.routing.ceremonyProfile` × the **derived change
95
- level** — never a planner-authored verdict (Story #4542).
96
- **Compute the change set once** (Story #4593) with the shared enumerator
97
- [`computeChangeSet`](../../scripts/lib/orchestration/change-set.js) the
98
- same module close uses and hand that one list to every critic. Derive the
99
- level with `deriveChangeLevel`, resolve fresh-vs-inline critics with
100
- `resolveCeremonyForRisk` (`ceremony-routing.js`); a lite Story runs inline
101
- regardless (exact incantation and routing rules: reference § Step 2).
102
- Hard gates (lint / test / format / coverage / CRAP / maintainability)
103
- always run in Step 3 — the derived level never disables them; do **not**
104
- pre-run the full close chain here.
97
+ level** — never a planner-authored verdict (Story #4542). **Digest § 3** is
98
+ the incantation: compute the change set once (Story #4593), derive the level,
99
+ resolve fresh-vs-inline critics with `ceremony-routing.js`; a lite Story runs
100
+ inline regardless (routing edge cases: reference § Step 2). Hard gates always
101
+ run in Step 3 — the derived level never disables them; do **not** pre-run the
102
+ close chain here.
105
103
 
106
104
  ## Step 3 — Close and land (`single-story-close.js`)
107
105
 
@@ -110,15 +108,12 @@ node <main-repo>/.agents/scripts/single-story-close.js --story <storyId> --cwd <
110
108
  ```
111
109
 
112
110
  **The whole delivery tail** — gates, PR, merge wait, `agent::done` flip,
113
- post-land tail in one process. Run it and **branch on the terminal
114
- envelope's `status`** (Story #4543):
115
-
116
- | `status` | Exit | Meaning | You do |
117
- | --- | --- | --- | --- |
118
- | `landed` | 0 | PR merged, `agent::done`, tail ran (`tail.*: false` degrades the report, not the land). | Relay the envelope (Step 7). |
119
- | `pending` | 3 | **Resumable, not a failure** — wait expired healthy, or a human owns the merge. | Run `nextCommand` until resolved. |
120
- | `blocked` | 1 | Hard block; `blocked.blockClass` names it. | `checks-failed` → Step 4; else relay. |
121
- | `failed` | 1 | A phase crashed; `phase` names which. | Diagnose, fix, re-run close. |
111
+ post-land tail in one process. Run it and **branch on the terminal envelope's
112
+ `status`** per the table in **digest § 5** (`landed` → Step 7; `pending` → run
113
+ `nextCommand`; `blocked`/`checks-failed` → Step 4; `failed` → diagnose and
114
+ re-run). Gate output is captured to
115
+ `temp/orchestration/close-gates-<storyId>.log` a clean run prints a digest
116
+ line, a red gate replays its tail inline (Story #4736).
122
117
 
123
118
  Internals (gate order, base-sync, auto-merge arming), the merge-wait
124
119
  budgets, the slow-CI **async** confirm mode (Story #4698 — launch the
@@ -143,13 +138,13 @@ recovery path **only** when the envelope routes you there:
143
138
 
144
139
  ## Step 7 — Return contract (**required as a sub-agent**) {#return-contract}
145
140
 
146
- The contract is the shipped schema
147
- [`story-deliver-terminal.schema.json`](../../schemas/story-deliver-terminal.schema.json)
148
- the SSOT for every field (Story #4543). End your turn by relaying the
149
- validated envelope close emits between its `--- STORY DELIVER TERMINAL ---`
150
- markers — never free-form prose, never a hand-composed object. `pending` is
151
- the only sanctioned no-merge ending, returned only when your own budget is
152
- exhausted (Story #1553). Reference § Step 7.
141
+ End your turn by relaying the validated envelope close emits between its
142
+ `--- STORY DELIVER TERMINAL ---` markers — never free-form prose, never a
143
+ hand-composed object. Statuses, exits, and required fields: **digest § 5**
144
+ (whose SSOT is the shipped
145
+ [schema](../../schemas/story-deliver-terminal.schema.json), Story #4543).
146
+ `pending` is the only sanctioned no-merge ending, returned only when your own
147
+ budget is exhausted (Story #1553). Reference § Step 7.
153
148
 
154
149
  ## Recovering a stranded Story {#recover}
155
150
 
@@ -175,6 +170,7 @@ reuses an open PR).
175
170
 
176
171
  ## See also
177
172
 
173
+ - [`deliver-digest.md`](deliver-digest.md) — the one bundled framework read.
178
174
  - [`/deliver`](../deliver.md) — unified entry point.
179
175
  - [`deliver-story-reference.md`](deliver-story-reference.md) — all on-demand
180
176
  detail.
@@ -7,8 +7,7 @@ description:
7
7
 
8
8
  # /plan --seed "<text>" | --seed-file <path> | --tickets <ids>
9
9
 
10
- > **Lean spine.** Happy path + gate list; edge-case and reference detail
11
- > lives in the on-demand
10
+ > **Lean spine.** Happy path + gate list; edge-case detail lives in on-demand
12
11
  > [`helpers/plan-reference.md`](helpers/plan-reference.md).
13
12
 
14
13
  ## Inputs
@@ -20,9 +19,9 @@ Epic/Story router, no scope-triage `epic|story` verdict:
20
19
  | --- | --- |
21
20
  | `/plan --seed "<text>"` / `--seed-file <path>` | Ideation from chat text or on-disk notes: interrogate → author **one Story by default** → persist. |
22
21
  | `/plan --tickets 123[,456…]` | Fetch issue(s), analyze into proper Stories (prefer N=1 rewrite). |
22
+ | `/plan --amends #<id>` | Amend a shipped Story from a **delta envelope** (prior body + acceptance + delivered file map), not a from-scratch re-interrogation (#4741). |
23
23
 
24
- `--body` is **not** a `/plan` entry; persist always goes through
25
- `plan-persist.js`.
24
+ `--body` is **not** a `/plan` entry; persist always goes through `plan-persist.js`.
26
25
 
27
26
  ## Flags
28
27
 
@@ -30,23 +29,24 @@ Epic/Story router, no scope-triage `epic|story` verdict:
30
29
  | --- | --- |
31
30
  | `--seed "<text>"` / `--seed-file <path>` | Seed text / pre-authored notes path. |
32
31
  | `--tickets <ids>` | Issue ids to analyze; closed as superseded at persist. |
32
+ | `--amends #<id>` | Prior Story to amend; emits a delta envelope, not a full re-interrogation (#4741). |
33
+ | `--chain-on-clean` | Persist: chain a clean lite dry-run into the real persist in one round-trip; full-route plans keep the review round-trip (#4741). |
33
34
  | `--no-close-superseded` | Keep the source issues open — no supersede comment, no close. |
34
- | `--force-review` | STOP at gate #2 for operator review — the only review gate (Story #4542). |
35
- | `--route-downgrade-reason "<text>"` | Authored `lite` verdict + reason (Story #4722), ledgered per Story; shape-validated, fails closed to `full`. |
35
+ | `--force-review` | STOP at gate #2 for operator review — the only review gate (#4542). |
36
+ | `--route-downgrade-reason "<text>"` | Authored `lite` verdict + reason (#4722); shape-validated, fails closed to `full`. |
36
37
  | `--allow-over-budget` | Permit a plan exceeding `maxTickets`. |
37
38
  | `--yes` | Non-interactive: auto-proceed gate #1 and gate #2 HITL waits. |
38
39
  | `--dry-run` | Author + validate without GitHub writes; run as a pre-pass. |
39
40
 
40
41
  ## Default-single split policy
41
42
 
42
- Author **one Story** unless (1) the pieces have **near-zero overlap**
43
- (genuinely independent capabilities), or (2) there is an **architectural
44
- seam** (different deployables, migration vs consumer). Coupled work stays
45
- one Story — decompose it inside `## Slicing` as intra-session checkpoints,
46
- not sibling tickets. When N>1, every acceptance criterion belongs to exactly
47
- one Story (`assertAcceptancePartition` refuses coupled splits). **N=1 is the
48
- lean path:** one authoring prompt, folded `## Spec`, light risk/critic
49
- profile — no Epic-scale ceremony.
43
+ Author **one Story** unless the pieces have **near-zero overlap** (genuinely
44
+ independent capabilities) or sit across an **architectural seam** (different
45
+ deployables, migration vs consumer). Coupled work stays one Story —
46
+ `## Slicing` intra-session checkpoints, not sibling tickets; when N>1 every
47
+ acceptance criterion belongs to exactly one Story
48
+ (`assertAcceptancePartition` refuses coupled splits). **N=1 is the lean
49
+ path:** one authoring prompt, folded `## Spec`, no Epic-scale ceremony.
50
50
 
51
51
  ## Procedure
52
52
 
@@ -55,69 +55,52 @@ profile — no Epic-scale ceremony.
55
55
  ```bash
56
56
  node .agents/scripts/plan-context.js --seed "<seed>" \
57
57
  --out temp/plan-<slug>/plan-context.json
58
- # or: --seed-file <path>
59
- # or: --tickets 123,456
58
+ # or: --seed-file <path> | --tickets 123,456 | --amends #<id>
60
59
  ```
61
60
 
62
- **Always pass `--out`.** Persist auto-discovers that envelope from
63
- `--plan-dir` and derives source-ticket ids from its `sourceTickets[]`
64
- (Story #4554); the CLI also writes **`stories.template.json`** — the
65
- authoring skeleton step 2 starts from.
66
-
67
- The envelope carries docs context, codebase snapshot, the story-author
68
- prompt, `sourceTickets[]`, `duplicates[]` (open **Stories** overlapping the
69
- seed never Epics), and advisory `complexitySignals` (**no routing
70
- authority**, Story #4722). A genuinely trivial scope earns
71
- `--route-downgrade-reason "<why>"` at persist — shape-validated, failing
72
- closed to `full`. Detail:
73
- [`helpers/plan-reference.md` § Shape-derived routing](helpers/plan-reference.md).
74
- Under `--yes`, do not ask free-form operator questions — unresolved
75
- unknowns land in Key Assumptions.
61
+ **Always pass `--out`.** Persist auto-discovers that envelope from `--plan-dir`
62
+ and derives source-ticket ids from its `sourceTickets[]` (#4554); the CLI also
63
+ writes **`stories.template.json`** — the authoring skeleton step 2 starts from.
64
+
65
+ The envelope carries docs context, the codebase snapshot, the story-author
66
+ prompt, `sourceTickets[]`, `duplicates[]` (open **Stories**, never Epics), and
67
+ advisory `complexitySignals` (**no routing authority**, #4722). A trivial scope
68
+ earns `--route-downgrade-reason "<why>"` at persist shape-validated, failing
69
+ closed to `full`
70
+ ([detail](helpers/plan-reference.md)).
71
+ Under `--yes`, do not ask free-form operator questions — unresolved unknowns
72
+ land in Key Assumptions.
76
73
 
77
74
  **Gate #1** — STOP to confirm the sharpened plan intent and any
78
- duplicate-candidate review. Under `--yes`, auto-proceed.
75
+ duplicate-candidate review. Under `--yes`, auto-proceed. When
76
+ `complexitySignals.deliverLightSuggestion.suggested` is `true`, surface an
77
+ **advisory** `/deliver-light` suggestion — the operator decides; under `--yes`
78
+ it is recorded and planning proceeds, **never an automatic reroute** (#4741).
79
79
 
80
80
  ### 2. Author
81
81
 
82
82
  **One-shot authoring (Story #4707).** Start from `stories.template.json`;
83
83
  author `stories.json` in one pass. Entries are pre-resolved (#4723); keep
84
- tiers/assumptions valid. `body` is a
85
- markdown string **or** a structured object; persist parses either,
86
- serializes the canonical markdown, and syncs the top-level `acceptance[]` /
87
- `verify[]` into the body — never dual-author those lists.
88
-
89
- ```jsonc
90
- // temp/plan-<slug>/stories.json
91
- [
92
- {
93
- "slug": "hyphen-case-slug", // ^[a-z0-9][a-z0-9-]*$
94
- "type": "story",
95
- "title": "Short descriptive title",
96
- "body": {
97
- "goal": "One sentence: why this Story exists.",
98
- "spec": "Optional — contract and invariants.",
99
- "changes": [{ "path": "path/to/file.ext", "assumption": "refactors-existing" }], // creates | refactors-existing | deletes
100
- "non_goals": [],
101
- "reason_to_exist": "One coherent reason this Story exists."
102
- },
103
- "acceptance": ["A testable, observable criterion"],
104
- "verify": ["exact command (unit|contract|e2e|validate)"],
105
- "depends_on": [] // sibling Story slugs, N>1 only
106
- }
107
- ]
108
- ```
84
+ tiers/assumptions valid. `body` is a markdown string **or** a structured
85
+ object; persist parses either, serializes the canonical markdown, and syncs the
86
+ top-level `acceptance[]` / `verify[]` into it — never dual-author those lists.
87
+
88
+ Each entry (the `stories.template.json` shape): `slug`
89
+ (`^[a-z0-9][a-z0-9-]*$`), `type: "story"`, `title`, `body` (`goal`, optional
90
+ `spec`, `changes[{path, assumption}]` — `creates|refactors-existing|deletes`,
91
+ `non_goals`, `reason_to_exist`), top-level `acceptance[]`, `verify[]`
92
+ (`… (unit|contract|e2e|validate)`), `depends_on[]` (N>1 only).
109
93
 
110
94
  Artifacts under `temp/plan-<slug>/`: `stories.json`
111
95
  (**length 1 by default**; over-budget Specs fail closed — split or tighten,
112
- never write Specs under `docs/`); optional `techspec.md` (**N===1 only** —
113
- folded into `## Spec`); optional `acceptance-manifest.json` (N>1 partition
114
- list — pass as `--plan-acceptance` or it is not read). For N=1,
115
- use the envelope `systemPrompts.story` and emit one cohesive Story.
116
- Split only under the policy above.
96
+ never under `docs/`); optional `techspec.md` (**N===1 only** — folded into
97
+ `## Spec`); optional `acceptance-manifest.json` (N>1 partition list — pass as
98
+ `--plan-acceptance`). For N=1, use the envelope `systemPrompts.story` and emit
99
+ one cohesive Story. Split only under the policy above.
117
100
 
118
- **Tickets mode:** every Story authors a top-level `supersedes[]` claiming
119
- the source issues it replaces; persist refuses a partial map (shape:
120
- [`helpers/plan-reference.md` § Tickets mode](helpers/plan-reference.md)).
101
+ **Tickets mode:** every Story authors a top-level `supersedes[]` claiming the
102
+ source issues it replaces; persist refuses a partial map
103
+ ([shape](helpers/plan-reference.md)).
121
104
 
122
105
  ### 2.5 Critics
123
106
 
@@ -147,9 +130,9 @@ ledgered: **do not proceed to Persist**; fix and re-run.
147
130
  **only** trigger). Under `--yes`, auto-proceed.
148
131
 
149
132
  Run persist with `--dry-run` **first** — same command, GitHub writes
150
- suppressed; every gate (ticket validator, body parse, DAG, capacity,
151
- budget, reachability, split-policy and supersede partitions, Spec fold)
152
- runs before the first `createIssue`. Then:
133
+ suppressed; every gate (validator, body parse, DAG, capacity, budget,
134
+ reachability, split/supersede partitions, Spec fold) runs before the first
135
+ `createIssue`. Then:
153
136
 
154
137
  ```bash
155
138
  node .agents/scripts/plan-persist.js \
@@ -160,30 +143,29 @@ node .agents/scripts/plan-persist.js \
160
143
  [--source-tickets 123,456] [...flags from the table above]
161
144
  ```
162
145
 
163
- Persist creates Story issue(s) with `type::story` plus a `plan-run::<id>`
164
- grouping label (**metadata only** never a delivery-resolution input, Story #4692); N>1 `depends_on` edges become `blocked by #<id>` body footers.
165
- `agent::ready` is the **terminal** flip, after all receipts are upserted — a
166
- ready Story is always fully persisted (Story #4541). stdout is pure JSON
167
- (logs on stderr).
146
+ At lite shape, `--chain-on-clean` chains that dry-run into the real persist in
147
+ one round-trip **only** when it is clean and `lite`; a full-route plan keeps
148
+ its review round-trip (#4741).
149
+
150
+ Persist creates `type::story` issue(s) plus a `plan-run::<id>` grouping label
151
+ (**metadata only**, #4692); N>1 `depends_on` edges become `blocked by #<id>`
152
+ footers. `agent::ready` is the **terminal** flip after all receipts land — a
153
+ ready Story is fully persisted (#4541). stdout is pure JSON.
168
154
 
169
- In `--tickets` mode persist resolves source ids **envelope-first** and
170
- closes each superseded source as `not_planned` with a comment (default on).
171
- Detail (channels, close contract, resume, temp hygiene):
172
- [`helpers/plan-reference.md`](helpers/plan-reference.md)on a stranded
173
- persist, re-run the same command; never hand-delete issues.
155
+ In `--tickets` mode persist resolves source ids **envelope-first** and closes
156
+ each as `not_planned` with a comment (default on;
157
+ [detail](helpers/plan-reference.md)). On a stranded persist, re-run the same
158
+ commandnever hand-delete issues.
174
159
 
175
160
  ## Constraints
176
161
 
177
- - `/plan` never starts delivery. No Epic ticket, no reconciler, no
178
- `delivery::single` marker.
179
- - Duplicate search targets open Stories (`type::story`), not Epics.
162
+ - `/plan` never starts delivery no Epic ticket, no reconciler. Duplicate
163
+ search targets open Stories (`type::story`), not Epics.
180
164
  - Deterministic gates still fail closed under `--yes`.
181
165
 
182
166
  ## See also
183
167
 
184
- - [`/deliver`](deliver.md) — delivery entry point.
185
- - [`/audit-to-stories`](audit-to-stories.md) — audit findings → plan seed.
186
- - [`helpers/plan-reference.md`](helpers/plan-reference.md) — on-demand
187
- detail.
168
+ - [`/deliver`](deliver.md), [`/audit-to-stories`](audit-to-stories.md),
169
+ [`helpers/plan-reference.md`](helpers/plan-reference.md) — on-demand detail.
188
170
  - [`core/scope-triage`](../skills/core/scope-triage/SKILL.md) — optional
189
171
  split-advisory notes only (no routing verdict).
package/docs/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [2.13.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.12.0...mandrel-v2.13.0) (2026-07-24)
6
+
7
+
8
+ ### Added
9
+
10
+ * **orchestration:** add /deliver-light — validated single-session delivery with full gates (refs [#4740](https://github.com/dsj1984/mandrel/issues/4740)) ([#4742](https://github.com/dsj1984/mandrel/issues/4742)) ([605c20b](https://github.com/dsj1984/mandrel/commit/605c20b5ce9c17c6dc7c40356a2e496bb2f25a44))
11
+ * plan-phase turn diet: same artifacts, fewer round-trips, amendment-aware envelope ([#4741](https://github.com/dsj1984/mandrel/issues/4741)) ([#4744](https://github.com/dsj1984/mandrel/issues/4744)) ([65b6790](https://github.com/dsj1984/mandrel/commit/65b67900ae58aea8a15e8a96e28895b1283df079))
12
+
13
+ ## [2.12.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.11.0...mandrel-v2.12.0) (2026-07-24)
14
+
15
+
16
+ ### Performance
17
+
18
+ * **orchestration:** cut deliver-path cost — inline single-Story dispatch, bounded close output, bundled reads (refs [#4736](https://github.com/dsj1984/mandrel/issues/4736)) ([#4737](https://github.com/dsj1984/mandrel/issues/4737)) ([81e62a8](https://github.com/dsj1984/mandrel/commit/81e62a87ca49add2aeb5b5a6b9ac11014edc3374))
19
+
20
+
21
+ ### Changed
22
+
23
+ * **orchestration:** thread injectedRules seam through route composition layers ([#4734](https://github.com/dsj1984/mandrel/issues/4734)) ([6e1daad](https://github.com/dsj1984/mandrel/commit/6e1daadbc24210fdb34e4892c0077256f2ccd051))
24
+
5
25
  ## [2.11.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.10.0...mandrel-v2.11.0) (2026-07-23)
6
26
 
7
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mandrel",
3
- "version": "2.11.0",
3
+ "version": "2.13.0",
4
4
  "description": "Claude Code-first opinionated workflow framework: instructions, skills, rules, and SDLC workflows that govern AI coding assistants.",
5
5
  "files": [
6
6
  ".agents/",