mandrel 1.86.0 → 1.87.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 (30) hide show
  1. package/.agents/instructions.md +7 -0
  2. package/.agents/rules/git-conventions.md +13 -1
  3. package/.agents/scripts/boot-sweep.js +36 -4
  4. package/.agents/scripts/git-cleanup.js +8 -0
  5. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +107 -30
  6. package/.agents/scripts/lib/epic-plan-ideation.js +24 -3
  7. package/.agents/scripts/lib/framework-version.js +210 -0
  8. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +7 -22
  9. package/.agents/scripts/lib/orchestration/epic-cleanup.js +41 -5
  10. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +34 -3
  11. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +102 -7
  12. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +85 -1
  13. package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +34 -3
  14. package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +71 -4
  15. package/.agents/scripts/lib/single-story-sweep.js +60 -5
  16. package/.agents/scripts/lib/story-body/story-body.js +81 -4
  17. package/.agents/scripts/providers/github/tickets.js +18 -1
  18. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +7 -2
  19. package/.agents/skills/core/epic-plan-premortem/SKILL.md +8 -2
  20. package/.agents/skills/skills.index.json +3 -3
  21. package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +36 -8
  22. package/.agents/workflows/git-cleanup.md +72 -18
  23. package/.agents/workflows/helpers/acceptance-self-eval.md +23 -1
  24. package/.agents/workflows/helpers/deliver-epic.md +22 -3
  25. package/.agents/workflows/helpers/epic-audit.md +60 -2
  26. package/.agents/workflows/helpers/parallel-tooling.md +9 -2
  27. package/.agents/workflows/helpers/plan-epic.md +32 -14
  28. package/.agents/workflows/loops/nightly-audit.md +9 -1
  29. package/docs/CHANGELOG.md +15 -0
  30. package/package.json +1 -1
@@ -35,7 +35,29 @@ per-criterion, mid-delivery, and evaluates the actual work product.
35
35
  1. **Eval pass (fresh context, independent of the author).** Run a **separate
36
36
  critic pass** — a fresh-context sub-agent (`Agent` tool,
37
37
  `subagent_type: general-purpose`), *not* a continuation of your implementing
38
- turn — so the evaluator does not grade its own homework. The critic:
38
+ turn — so the evaluator does not grade its own homework.
39
+
40
+ > **Inline-critic fallback (nesting-absent harness).** Dispatching the
41
+ > critic as a nested `Agent` is the preferred shape — it gives genuine
42
+ > fresh-context isolation — and works on any harness that carries `Agent`
43
+ > into sub-agents (Claude Code ≥ 2.1.202; see
44
+ > [#2870](https://github.com/dsj1984/mandrel/issues/2870)). This eval loop
45
+ > itself runs inside a Story delivery sub-agent, so the nested critic sits
46
+ > at nesting depth 2. If the host does **not** support nested `Agent`
47
+ > dispatch at that depth — the tool is absent, or a spawn attempt returns
48
+ > an unsupported-capability error — do **not** stall the Story. Fall back
49
+ > to authoring the verdict **inline**: in a deliberately scoped,
50
+ > self-critical pass (re-read only the diff, the `acceptance[]` /
51
+ > `verify[]` arrays, and the `verify[]` command output — treat the
52
+ > implementation reasoning as untrusted and score against the criteria
53
+ > afresh), write the same verdict file described below and hand it to the
54
+ > same `acceptance-eval.js` gate. The fresh-context isolation is weaker in
55
+ > the inline path, but the gate, the schema, the round cap, and the
56
+ > proceed / redraft / block decision are identical — a Story is **never**
57
+ > stranded on a nesting-absent harness. Note in the blocked/friction
58
+ > comment (if you block) that the inline fallback was used.
59
+
60
+ The critic:
39
61
  - Inspects the working diff (`git diff origin/<baseBranch>...HEAD`) and the
40
62
  Story's inline `acceptance[]` / `verify[]` arrays.
41
63
  - **Runs the `verify[]` commands** and consumes their output as **required
@@ -89,9 +89,17 @@ Every other runtime modifier is sourced from the Epic's labels or from
89
89
  - **Single pause point.** Only `agent::blocked` halts execution. No
90
90
  clarifying questions — if stuck, flip to `agent::blocked`, post a
91
91
  friction comment, park.
92
- - **Two-level dispatch.** Host LLM fans out per-Story Agent calls
93
- directly with `subagent_type: general-purpose`. Sub-agents do not
94
- carry the `Agent` tool, so this stays flat.
92
+ - **Flat Story dispatch by design.** Host LLM fans out per-Story Agent
93
+ calls directly with `subagent_type: general-purpose`. Keeping Story
94
+ dispatch flat — the host owns the single fan-out level — is a
95
+ **design choice**, not a harness constraint: the wave aggregator, idle
96
+ watchdog, and merge-lock all assume one host-owned dispatch level. As of
97
+ Claude Code 2.1.202 a level-1 sub-agent **does** carry the `Agent` tool
98
+ and can nest further (verified depth 2, announced max depth 5; see
99
+ [#2870](https://github.com/dsj1984/mandrel/issues/2870)), so a Story
100
+ worker may itself fan out for its own sub-work within that depth budget —
101
+ the Epic wave loop nonetheless stays flat by choice, not because nesting
102
+ is unavailable.
95
103
  - **Operator-merges-PR exit.** Phase 7 opens the PR; the workflow
96
104
  never merges to `main` itself. Phase 8.5 may fire auto-merge when
97
105
  every signal is clean.
@@ -481,6 +489,17 @@ therefore auto-runs its mapped lenses (e.g. a `security`-axis Epic runs
481
489
  low-risk Epic adds nothing. Findings are persisted as an `audit-results`
482
490
  structured comment on the Epic.
483
491
 
492
+ The helper walks the selected roster **serially in-context by default**; when
493
+ the roster carries more than one lens it **may delegate the walk to a single
494
+ audit-orchestrator sub-agent** that fans the already-selected lenses out as
495
+ parallel level-2 agents and returns only the aggregated `audit-results` (see
496
+ [`epic-audit.md` § "Optional: delegate the roster walk to an audit-orchestrator
497
+ sub-agent"](epic-audit.md), within the sub-agent depth budget noted under
498
+ "Flat Story dispatch by design" above). The roster stays fixed upstream, every
499
+ per-lens cost gate is preserved, and the seven sequential-only lenses are **not**
500
+ batch-converted — the fan-out parallelizes across lenses only and never changes
501
+ how any single lens runs internally.
502
+
484
503
  - **Any 🔴 Critical Blocker** — STOP. Relay to the operator.
485
504
  - **Only 🟠/🟡/🟢** — log as non-blocking and continue.
486
505
  - **Selector reports `degraded: true`** — STOP. Propagate the
@@ -1,8 +1,10 @@
1
1
  ---
2
2
  description: >-
3
3
  Run smart change-set audits at Epic finalize. Consumes the epic-audit-prepare
4
- envelope, dispatches each selected lens inline via runAuditSuite, and posts
5
- an audit-results structured comment back onto the Epic ticket.
4
+ envelope, dispatches each selected lens (inline, or via a single
5
+ audit-orchestrator sub-agent that fans the lenses out as parallel level-2
6
+ agents) through runAuditSuite, and posts an audit-results structured comment
7
+ back onto the Epic ticket.
6
8
  ---
7
9
 
8
10
  # Epic Audit (helper)
@@ -197,6 +199,62 @@ After the runner returns:
197
199
  🟡 Medium / 🟢 Suggestion). Hold the aggregate for Step 3
198
200
  (auto-fix) and Step 4 (the `audit-results` structured comment).
199
201
 
202
+ ### Optional: delegate the roster walk to an audit-orchestrator sub-agent
203
+
204
+ The Step 2 loop above walks the `selectedAudits` roster **serially in the
205
+ host's own context**. When the roster carries more than one lens, `/deliver`
206
+ Phase 4 MAY instead delegate the whole walk to a **single audit-orchestrator
207
+ sub-agent** — one level-1 `Agent` call (`subagent_type: general-purpose`) — that:
208
+
209
+ 1. Receives the **already-selected** `selectedAudits` roster, the run's
210
+ `depth`, and the prepare envelope's substitution payload. It does **not**
211
+ re-run `selectAudits` and does **not** widen the roster — the roster is
212
+ fixed upstream by Step 1 (see the Constraints below).
213
+ 2. Fans the roster out as **parallel level-2 agents, one per lens** (nested
214
+ `Agent` dispatch — verified depth 2, announced max depth 5, per
215
+ [#2870](https://github.com/dsj1984/mandrel/issues/2870) and the
216
+ "Flat Story dispatch by design" note in
217
+ [`deliver-epic.md`](deliver-epic.md)). Each level-2 agent executes exactly
218
+ one lens's workflow procedure at the run's `depth`, isolated from the main
219
+ context.
220
+ 3. Collects the per-lens findings, **aggregates them by severity** (🔴 / 🟠 /
221
+ 🟡 / 🟢), and returns **only the aggregated audit-results** to the host —
222
+ the per-lens reasoning transcripts stay in the level-2 leaves and never
223
+ enter the main context. The host resumes at Step 3 (remediation routing)
224
+ with the aggregate exactly as if it had walked the roster itself, and Step 4
225
+ posts the identical `audit-results` comment.
226
+
227
+ This delegation is a **cross-lens parallelization of the roster walk only**. It
228
+ is orthogonal to — and MUST NOT be conflated with — the *per-lens execution
229
+ strategy*:
230
+
231
+ - **The per-lens cost/precision gate is preserved.** Each level-2 lens agent
232
+ still runs its own lens at whatever strategy that lens's cost/precision gate
233
+ dictates (`docs/roadmap.md` § "The per-lens cost / precision gate"): an
234
+ orchestrated lens fans its own analysis dimensions out under
235
+ `runAuditOrchestration`, a sequential-only lens runs turn-by-turn. Fanning
236
+ the *roster* out in parallel changes **which context** runs a lens, never
237
+ **how** that lens runs internally, so no per-lens cost gate is bypassed or
238
+ altered.
239
+ - **The "do not batch-convert the sequential-only lenses" rule is preserved.**
240
+ The seven sequential-only lenses (`audit-dependencies`, `audit-devops`,
241
+ `audit-sre`, `audit-privacy`, `audit-seo`, `audit-ux-ui`,
242
+ `audit-lighthouse`) stay sequential **inside** their level-2 agent.
243
+ Dispatching them as parallel level-2 agents is **not** a batch-conversion of
244
+ their internal execution — a sequential-only lens remains sequential-only
245
+ (`docs/roadmap.md` § "Remaining orchestration surface"). Generalizing any of
246
+ those lenses to orchestrated is still a separate, gated, lens-by-lens
247
+ decision that this roster fan-out neither performs nor pre-empts.
248
+
249
+ Weigh the whole subtree's token cost before delegating
250
+ ([`.agents/instructions.md` § 4](../../instructions.md) — cost compounds with
251
+ nesting depth): the level-1 orchestrator plus one level-2 agent per lens
252
+ re-pays the always-loaded context at each level. For a single-lens roster the
253
+ serial host walk is cheaper; the delegation pays off when several lenses fan
254
+ out at once. Either path produces the identical Step 4 `audit-results` comment,
255
+ so the delegation is a performance/context-isolation choice, never a change to
256
+ what gets audited or reported.
257
+
200
258
  If a future Story lifts per-lens execution out of the host-LLM walk
201
259
  into the CLI itself, the runner will populate `findings[]` and this
202
260
  section will collapse to a "read the structured findings off the
@@ -76,8 +76,15 @@ If a unit of work is both long (Rule 2) and independent (Rule 1 or 3),
76
76
  prefer the higher-numbered rule — the parallelism gain compounds the
77
77
  background-shell gain. Concretely: dispatch the `Agent` calls in one turn
78
78
  (Rule 3), and **inside** each sub-agent let it apply Rule 2 to its own
79
- long-running shells. The host does not need to micromanage the child's
80
- shell strategy.
79
+ long-running shells and, within the supported nesting depth budget
80
+ (verified depth 2, announced max depth 5; see
81
+ [#2870](https://github.com/dsj1984/mandrel/issues/2870)), let it apply
82
+ **Rule 3** to its own independent sub-units as well, not only Rule 2
83
+ background shells. A sub-agent is a full orchestrator at its own level:
84
+ recursive `Agent` fan-out is available to it, so the host does not need to
85
+ micromanage the child's shell **or** dispatch strategy. Mind the depth
86
+ budget and the compounding cost — every nesting level re-pays the
87
+ always-loaded context (see [`instructions.md` § 4](../../instructions.md)).
81
88
 
82
89
  ## Constraints
83
90
 
@@ -683,26 +683,36 @@ node .agents/scripts/epic-plan-spec-validate.js \
683
683
 
684
684
  3. **Phase 8.3 — Holistic Consolidation (HITL diff gate)**: After the
685
685
  draft `temp/epic-[Epic_ID]/tickets.json` exists and **before** the persist
686
- call below, activate the
686
+ call below, **dispatch a genuine fresh-context sub-agent** (`Agent` tool,
687
+ `subagent_type: general-purpose`) whose task is to read the
687
688
  [`epic-plan-consolidate`](../../skills/core/epic-plan-consolidate/SKILL.md)
688
- skill with `[Epic_ID]` as input. This is a **separate critic pass with
689
- fresh context** (not a self-review appended to the author skill): it reads
690
- the draft array plus the Epic body (which carries the Tech Spec
691
- sections), reconciles the draft against
689
+ skill and execute its procedure with `[Epic_ID]` as input. Dispatching the critic
690
+ as a sub-agent **not** activating the skill inline in your authoring
691
+ turn is what makes it a **separate critic pass with fresh context**: the
692
+ sub-agent does not inherit the conversation that authored the draft, so it
693
+ cannot grade its own homework (the same nested-dispatch mechanic the
694
+ acceptance self-eval loop uses, now that the sub-agent depth limit is
695
+ lifted — see [`.agents/instructions.md` § 4](../../instructions.md)). The
696
+ sub-agent reads the draft array plus the Epic body (which carries the Tech
697
+ Spec sections), reconciles the draft against
692
698
  the Tech Spec `## Delivery Slicing` target, and emits a **consolidated**
693
699
  `tickets.json` plus a human-readable
694
700
  `temp/epic-[Epic_ID]/consolidation-report.md`. Its operations are
695
701
  scope-preserving only — **merge sibling Stories and rewire
696
702
  `depends_on`** — and it MUST NOT add scope or invent tickets; it
697
703
  consolidates fragmented slices by merging them into a cohesive Story,
698
- never by splitting one. It runs **before** the deterministic
704
+ never by splitting one. The sub-agent **never writes to GitHub**: it emits
705
+ only the two temp artifacts and returns control to this operator session.
706
+ It runs **before** the deterministic
699
707
  validator (step 7), so the validator re-checks its output and the critic
700
708
  cannot emit an invalid plan.
701
709
 
702
710
  **Show the operator the consolidation report (the before/after diff +
703
- rationale) before persisting.** Consolidation is never auto-applied without
704
- review: on operator approval, persist the consolidated `tickets.json`; on
705
- rejection, persist the draft instead. This is a sub-step of Phase 8 it
711
+ rationale) before persisting.** The HITL diff-confirm and the persist call
712
+ both run here in the **operator session**, never inside the sub-agent
713
+ consolidation is never auto-applied without review: on operator approval,
714
+ persist the consolidated `tickets.json`; on rejection, persist the draft
715
+ instead. This is a sub-step of Phase 8 — it
706
716
  does **not** renumber the top-level lifecycle phases (9–12).
707
717
 
708
718
  4. **Phase 8.4 — Reachability Completeness Critic (HITL diff gate, F6)**:
@@ -742,11 +752,17 @@ node .agents/scripts/epic-plan-spec-validate.js \
742
752
  invalid addition cannot reach GitHub.
743
753
 
744
754
  5. **Phase 8.5 — Planning Pre-Mortem Critic (code-reading, F9)**: After the
745
- reachability critic (8.4) and **before** the persist call below, activate the
755
+ reachability critic (8.4) and **before** the persist call below, **dispatch a
756
+ genuine fresh-context sub-agent** (`Agent` tool,
757
+ `subagent_type: general-purpose`) whose task is to read the
746
758
  [`epic-plan-premortem`](../../skills/core/epic-plan-premortem/SKILL.md)
747
- skill with `[Epic_ID]` as input. This is a **fresh-context critic** sibling
748
- to `epic-plan-consolidate`: it reads the drafted `tickets.json`, the Epic
749
- body (with its folded Tech Spec sections), **and the actual cited code
759
+ skill and execute its procedure with `[Epic_ID]` as input. Like the 8.3
760
+ consolidate pass, dispatching the critic as a sub-agent — **not** activating
761
+ the skill inline in your authoring turn is what makes it a genuine
762
+ **fresh-context critic** sibling to `epic-plan-consolidate`: the sub-agent
763
+ does not inherit the authoring conversation, so its code-reading review is
764
+ independent of the draft it grades. It reads the drafted `tickets.json`, the
765
+ Epic body (with its folded Tech Spec sections), **and the actual cited code
750
766
  surfaces** (the files each Story's
751
767
  `changes[]` / `references[]` name), then emits predicted-rework findings —
752
768
  unverifiable acceptance criteria, over- or under-specified Stories, and
@@ -756,7 +772,9 @@ node .agents/scripts/epic-plan-spec-validate.js \
756
772
  Unlike the consolidate critic it is **not** scope-preserving-only: it may
757
773
  recommend splitting an under-specified Story or tightening an AC. But it
758
774
  **never writes to GitHub** and never persists `tickets.json` — it only emits
759
- the report. Its findings are shown in the **same Phase 8 HITL diff**, and on
775
+ the report and returns control to this operator session. Its findings are
776
+ shown in the **same Phase 8 HITL diff** (which stays in the operator
777
+ session), and on
760
778
  operator approval the author re-runs (Step 2) on the findings **before** the
761
779
  persist call. The critic runs **before** the deterministic validator (step
762
780
  7), so the persist below is the single GitHub write for the whole phase.
@@ -32,7 +32,15 @@ Each scheduled run:
32
32
  (`/audit-security`, `/audit-clean-code`, `/audit-dependencies`,
33
33
  `/audit-quality`, and any others the project relies on). Each audit writes a
34
34
  structured `temp/audits/audit-*-results.md` report — that is the canonical
35
- artifact this loop consumes, not free-form prose.
35
+ artifact this loop consumes, not free-form prose. Because these audits are
36
+ **independent** of one another, a scheduled run **may fan them out to
37
+ parallel sub-agents** (one per audit) rather than walking them serially —
38
+ the same cross-lens parallelization `/deliver` Phase 4 uses (see
39
+ [`../helpers/epic-audit.md` § "Optional: delegate the roster walk to an
40
+ audit-orchestrator sub-agent"](../helpers/epic-audit.md)). Each sub-agent
41
+ returns only its structured report; the scheduler/host owns the fan-out just
42
+ as it owns the cadence, and each per-audit strategy (sequential or
43
+ orchestrated) is unchanged by running under its own sub-agent.
36
44
  2. **Diff against the prior night.** Compare the fresh findings against the last
37
45
  sweep's reports and against already-open Issues. A finding seen before is
38
46
  not new signal; only genuinely fresh or regressed findings warrant a record.
package/docs/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.87.0](https://github.com/dsj1984/mandrel/compare/mandrel-v1.86.0...mandrel-v1.87.0) (2026-07-08)
6
+
7
+
8
+ ### Added
9
+
10
+ * **boot-sweep:** report content-merged branches and align sweep docs ([#4396](https://github.com/dsj1984/mandrel/issues/4396)) ([#4398](https://github.com/dsj1984/mandrel/issues/4398)) ([8c9c938](https://github.com/dsj1984/mandrel/commit/8c9c938d34c0bcbdaeb607f5a148261925a58622))
11
+ * Epic [#4385](https://github.com/dsj1984/mandrel/issues/4385) ([#4392](https://github.com/dsj1984/mandrel/issues/4392)) ([0999dca](https://github.com/dsj1984/mandrel/commit/0999dcac00a708bca0d1a9664f46d8f79c9ffe11))
12
+ * **git-cleanup:** detect content-merged branches and surface silent skips (refs [#4395](https://github.com/dsj1984/mandrel/issues/4395)) ([#4397](https://github.com/dsj1984/mandrel/issues/4397)) ([a5ddabf](https://github.com/dsj1984/mandrel/commit/a5ddabf41f25a75cb5b63e0f51ed05e8dcfcf81d))
13
+ * **planning:** stamp authoring Mandrel version onto Epic and Story bodies (refs [#4382](https://github.com/dsj1984/mandrel/issues/4382)) ([#4383](https://github.com/dsj1984/mandrel/issues/4383)) ([db3de0a](https://github.com/dsj1984/mandrel/commit/db3de0a9302a8f3aa97b06ad74af04879aaba53a))
14
+
15
+
16
+ ### Fixed
17
+
18
+ * branchCleaner false-blocks a successfully-merged Epic when local branches are already reaped ([#4393](https://github.com/dsj1984/mandrel/issues/4393)) ([#4394](https://github.com/dsj1984/mandrel/issues/4394)) ([83a5604](https://github.com/dsj1984/mandrel/commit/83a5604b55aab470d9c4c08ee9d66b4b181af81a))
19
+
5
20
  ## [1.86.0](https://github.com/dsj1984/mandrel/compare/mandrel-v1.85.0...mandrel-v1.86.0) (2026-07-07)
6
21
 
7
22
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mandrel",
3
- "version": "1.86.0",
3
+ "version": "1.87.0",
4
4
  "description": "Claude Code-first opinionated workflow framework: instructions, personas, skills, and SDLC workflows that govern AI coding assistants.",
5
5
  "files": [
6
6
  ".agents/",