mandrel 1.80.0 → 1.82.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.
- package/.agents/README.md +5 -5
- package/.agents/docs/SDLC.md +93 -80
- package/.agents/docs/configuration.md +11 -1
- package/.agents/docs/quality-gates.md +61 -0
- package/.agents/docs/workflows.md +1 -1
- package/.agents/instructions.md +9 -7
- package/.agents/personas/architect.md +8 -5
- package/.agents/personas/engineer-mobile.md +3 -2
- package/.agents/personas/engineer-web.md +3 -2
- package/.agents/personas/engineer.md +6 -5
- package/.agents/personas/product.md +19 -13
- package/.agents/personas/project-manager.md +9 -8
- package/.agents/personas/qa-engineer.md +10 -6
- package/.agents/personas/refactorer.md +3 -2
- package/.agents/personas/technical-writer.md +2 -1
- package/.agents/personas/ux-designer.md +2 -2
- package/.agents/schemas/agentrc.schema.json +10 -0
- package/.agents/scripts/acceptance-spec-reconciler.js +143 -59
- package/.agents/scripts/epic-deliver-prepare.js +0 -31
- package/.agents/scripts/epic-plan-decompose.js +2 -5
- package/.agents/scripts/epic-plan-spec.js +16 -19
- package/.agents/scripts/hierarchy-gate.js +11 -11
- package/.agents/scripts/lib/ITicketingProvider.js +4 -3
- package/.agents/scripts/lib/baselines/env-overrides.js +35 -0
- package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
- package/.agents/scripts/lib/bdd-scenario-scanner.js +1 -1
- package/.agents/scripts/lib/cli-args.js +1 -5
- package/.agents/scripts/lib/codebase-snapshot.js +1 -1
- package/.agents/scripts/lib/config/temp-paths.js +1 -4
- package/.agents/scripts/lib/config-settings-schema.js +5 -0
- package/.agents/scripts/lib/epic-body-sections.js +222 -0
- package/.agents/scripts/lib/epic-plan-clarity.js +38 -1
- package/.agents/scripts/lib/epic-plan-ideation.js +15 -3
- package/.agents/scripts/lib/label-constants.js +7 -17
- package/.agents/scripts/lib/label-taxonomy.js +4 -21
- package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +47 -1
- package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +7 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +1 -1
- package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +2 -1
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +19 -8
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +23 -22
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +7 -10
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +4 -38
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +8 -9
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +11 -5
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/cli-args.js +26 -5
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +102 -304
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +32 -29
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +19 -20
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-authoring-grounding.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +6 -9
- package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +3 -4
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +20 -27
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +11 -5
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +22 -59
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +1 -1
- package/.agents/scripts/lib/orchestration/planning-context-budget.js +1 -1
- package/.agents/scripts/lib/orchestration/preflight-cache.js +1 -1
- package/.agents/scripts/lib/orchestration/spec-freshness.js +3 -3
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +1 -1
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +122 -1
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +5 -8
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +2 -2
- package/.agents/scripts/lib/plan-phase-cleanup.js +1 -2
- package/.agents/scripts/lib/qa/qa-context-hydrator.js +6 -85
- package/.agents/scripts/lib/templates/decomposer-prompts.js +14 -8
- package/.agents/scripts/lifecycle-emit.js +1 -1
- package/.agents/scripts/lint-label-vocabulary.js +2 -3
- package/.agents/scripts/providers/github/mappers.js +0 -3
- package/.agents/scripts/providers/github/tickets.js +7 -18
- package/.agents/scripts/single-story-init.js +0 -1
- package/.agents/scripts/story-init.js +1 -29
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +37 -18
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +23 -18
- package/.agents/skills/core/epic-plan-premortem/SKILL.md +7 -6
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +161 -109
- package/.agents/skills/core/hydrate-context/SKILL.md +10 -5
- package/.agents/skills/core/knowledge-transfer/SKILL.md +3 -2
- package/.agents/skills/core/scope-triage/SKILL.md +2 -1
- package/.agents/skills/skills.index.json +6 -6
- package/.agents/templates/epic-from-idea.md +4 -0
- package/.agents/workflows/audit-to-stories.md +2 -2
- package/.agents/workflows/helpers/code-review.md +11 -9
- package/.agents/workflows/helpers/deliver-epic.md +32 -44
- package/.agents/workflows/helpers/epic-audit.md +11 -8
- package/.agents/workflows/helpers/epic-deliver-story.md +10 -16
- package/.agents/workflows/helpers/epic-plan-decompose.md +17 -12
- package/.agents/workflows/helpers/epic-plan-spec.md +68 -68
- package/.agents/workflows/helpers/parallel-tooling.md +2 -1
- package/.agents/workflows/helpers/plan-epic.md +114 -99
- package/.agents/workflows/helpers/single-story-deliver.md +1 -1
- package/.agents/workflows/helpers/worktree-lifecycle.md +1 -1
- package/.agents/workflows/plan.md +8 -8
- package/.agents/workflows/qa-assist.md +2 -1
- package/docs/CHANGELOG.md +28 -0
- package/package.json +1 -1
- package/.agents/scripts/lib/issue-link-parser.js +0 -74
- package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +0 -116
- package/.agents/scripts/lib/orchestration/planning-state-manager.js +0 -318
- package/.agents/scripts/lib/story-init/hierarchy-tracer.js +0 -57
|
@@ -79,13 +79,15 @@ review yourself, honor the `depth` semantics above directly.
|
|
|
79
79
|
|
|
80
80
|
1. Resolve `[TICKET_ID]` from `ticketId` (Story or Epic depending on `scope`).
|
|
81
81
|
2. Resolve `[BASE_REF]` from `baseRef` and `[HEAD_REF]` from `headRef`.
|
|
82
|
-
3. Fetch the `[TICKET_ID]` ticket and
|
|
82
|
+
3. Fetch the `[TICKET_ID]` ticket and resolve the planning context:
|
|
83
83
|
- **Story scope** — read the parent Epic from the Story body, then load
|
|
84
|
-
the Epic
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
the Epic body (including its `## User Stories` section and its folded
|
|
85
|
+
Tech Spec sections).
|
|
86
|
+
- **Epic scope** — read the Epic body directly; its managed sections
|
|
87
|
+
carry the Tech Spec.
|
|
88
|
+
4. Read the Epic body fully (including its Tech Spec sections) to
|
|
89
|
+
understand the intended
|
|
90
|
+
scope, architectural decisions, and acceptance criteria.
|
|
89
91
|
|
|
90
92
|
## Step 1 — Automated Audit (Pre-Review)
|
|
91
93
|
|
|
@@ -120,7 +122,7 @@ before finalizing findings.
|
|
|
120
122
|
|
|
121
123
|
### Pillar 1: Spec Adherence
|
|
122
124
|
|
|
123
|
-
Does the implementation match the
|
|
125
|
+
Does the implementation match the Epic's requirements and Tech Spec architecture?
|
|
124
126
|
|
|
125
127
|
- Compare each completed Story/Task against its stated acceptance criteria.
|
|
126
128
|
- Flag any undocumented deviations, missing features, or scope creep.
|
|
@@ -251,7 +253,7 @@ anything not fixed in-place.
|
|
|
251
253
|
structured comment for the operator to triage in Step 5.
|
|
252
254
|
2. **Leave the finding on the structured comment for Step 5.** Required
|
|
253
255
|
when the finding falls into any of the following classes:
|
|
254
|
-
- `spec-deviation` — the change diverges from the
|
|
256
|
+
- `spec-deviation` — the change diverges from the Epic/Tech Spec.
|
|
255
257
|
- `secrets` — credentials, tokens, or PII surfaced in the diff.
|
|
256
258
|
- `test-deletion` — coverage was removed without an explicit
|
|
257
259
|
decision in the spec.
|
|
@@ -359,7 +361,7 @@ to the next phase of the parent workflow.
|
|
|
359
361
|
the scope is set by the caller, and reviewing against the wrong base
|
|
360
362
|
produces either a hollow review (too small a diff) or noise (too large a
|
|
361
363
|
diff that includes unrelated history).
|
|
362
|
-
- **Always** read the
|
|
364
|
+
- **Always** read the Epic body and Tech Spec before reviewing code. Findings without
|
|
363
365
|
spec context are noise.
|
|
364
366
|
- **Never** implement fixes unless the operator explicitly requests it. The
|
|
365
367
|
default mode is read-only audit.
|
|
@@ -167,24 +167,17 @@ Validates `type::epic`, enumerates `type::story` descendants, parses
|
|
|
167
167
|
(to enumerate the open Story set), and upserts the `epic-run-state`
|
|
168
168
|
checkpoint in the per-Story-status shape (a flat `stories` map seeded at
|
|
169
169
|
`pending`, plus the global `concurrencyCap`). Treat the printed JSON as
|
|
170
|
-
`state`: `{ epicId, storyCount, concurrencyCap, stories,
|
|
170
|
+
`state`: `{ epicId, storyCount, concurrencyCap, stories, checkpointInitializedAt }`.
|
|
171
171
|
`stories` is the flat dispatch hint (`{ storyId, worktree, title }` per open
|
|
172
172
|
Story); the ready-set `tick` (Phase 2) decides which to dispatch on each
|
|
173
173
|
beat. Flip the Epic to `agent::executing` (idempotent) after the CLI returns.
|
|
174
174
|
|
|
175
|
-
**
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
per-Story `getEpic` round-trips (one per child, each in its own process
|
|
182
|
-
with its own provider cache) to this one parent-side resolution — the
|
|
183
|
-
immutable Epic issue is invariant for the lifetime of a delivery run.
|
|
184
|
-
When a linkage is `null` (the Epic links no PRD or Tech Spec), omit the
|
|
185
|
-
corresponding flag; the child's `story-init.js` then falls back to its
|
|
186
|
-
own `getEpic` resolution for the missing id, preserving graceful
|
|
187
|
-
degradation.
|
|
175
|
+
**No spec-ticket linkage to resolve (Story #4324).** The Tech Spec lives
|
|
176
|
+
as managed sections of the Epic body itself — there is no separate
|
|
177
|
+
Tech-Spec issue id in the envelope and no `--tech-spec` flag to thread
|
|
178
|
+
into the per-Story `story-init.js` invocations. Story agents receive the
|
|
179
|
+
Tech Spec via context hydration, which embeds the Epic body (with the
|
|
180
|
+
`## Acceptance Table` section stripped) directly into each Story prompt.
|
|
188
181
|
|
|
189
182
|
> **Preflight guards (Story #3482 / F-workflow-guards).** Before the
|
|
190
183
|
> snapshot phase runs — and before any worktree is created — prepare runs
|
|
@@ -218,19 +211,19 @@ degradation.
|
|
|
218
211
|
|
|
219
212
|
Once the preflight guards pass, the snapshot phase applies one more gate:
|
|
220
213
|
|
|
221
|
-
> **Acceptance-
|
|
214
|
+
> **Acceptance-table start gate.** Before the wave loop fans out, the
|
|
222
215
|
> snapshot phase
|
|
223
216
|
> ([`lib/orchestration/epic-runner/phases/snapshot.js`](../../scripts/lib/orchestration/epic-runner/phases/snapshot.js))
|
|
224
217
|
> asserts that the Epic either carries the `acceptance::n-a` waiver
|
|
225
|
-
> label **or** has a
|
|
226
|
-
>
|
|
227
|
-
> presence is sufficient, matching the PRD and Tech Spec contract.
|
|
218
|
+
> label **or** has a `## Acceptance Table` managed section in its
|
|
219
|
+
> body — section presence is sufficient.
|
|
228
220
|
> The reviewer's OK during `/plan` Phase 7 is the approval
|
|
229
|
-
> signal
|
|
221
|
+
> signal. Neither condition met →
|
|
230
222
|
> the snapshot throws a clear error
|
|
231
|
-
> (`[epic-deliver] Epic #<id> cannot launch: …`
|
|
223
|
+
> (`[epic-deliver] Epic #<id> cannot launch: …` — naming the missing
|
|
224
|
+
> `## Acceptance Table` section and the absent waiver) and `runAsCli`
|
|
232
225
|
> maps it to `process.exit(1)`. Operator remediation: either run
|
|
233
|
-
> `/plan` Phase 7 to author the
|
|
226
|
+
> `/plan` Phase 7 to author the acceptance table, or apply the
|
|
234
227
|
> `acceptance::n-a` label to opt out.
|
|
235
228
|
|
|
236
229
|
---
|
|
@@ -348,10 +341,7 @@ matching `story.dispatch.end` record is appended later by
|
|
|
348
341
|
`epic-execute-record-wave.js` (via `emit-story-dispatch-end.js`, Story #3900)
|
|
349
342
|
after the Agent return is recorded in § 2c.
|
|
350
343
|
|
|
351
|
-
Each Agent call's prompt must (1) name the Story + Epic ids
|
|
352
|
-
`prdId` / `techSpecId` from the Phase 1 prepare envelope** (Story #4253) so
|
|
353
|
-
the child can thread `--prd <prdId> --tech-spec <techSpecId>` into its
|
|
354
|
-
`story-init.js` Step 0 — omit whichever flag is `null`, (2)
|
|
344
|
+
Each Agent call's prompt must (1) name the Story + Epic ids, (2)
|
|
355
345
|
instruct the child to invoke `helpers/epic-deliver-story <storyId>`
|
|
356
346
|
(whose Step 4 defines the child's return shape), (3) remind the child
|
|
357
347
|
of the **non-interactive contract** (no clarifying questions;
|
|
@@ -765,19 +755,22 @@ bus-owned finalize) composes three helpers under
|
|
|
765
755
|
chain.** Treat this section as a runtime contract — `/deliver`
|
|
766
756
|
just fires the emit and reads the resulting ledger.
|
|
767
757
|
|
|
768
|
-
1. **Acceptance-
|
|
758
|
+
1. **Acceptance-table reconciliation — bus-driven.** The
|
|
769
759
|
`AcceptanceReconciler` listener invokes
|
|
770
760
|
[`acceptance-spec-reconciler.js`](../../scripts/acceptance-spec-reconciler.js)
|
|
771
|
-
to diff the AC IDs declared in the
|
|
772
|
-
|
|
761
|
+
to diff the AC IDs declared in the Epic body's `## Acceptance Table`
|
|
762
|
+
section against `@ac-*` / `@pending` tags in `tests/features/**`,
|
|
763
|
+
recording each row's verification outcome
|
|
764
|
+
(`satisfied` / `pending` / `missing`) into the table's Disposition
|
|
765
|
+
column via a section-scoped upsert of the Epic body. A
|
|
773
766
|
non-OK reconciliation throws (per
|
|
774
767
|
[`rules/orchestration-error-handling.md`](../../rules/orchestration-error-handling.md)),
|
|
775
|
-
aborting finalize **before** any PR is opened
|
|
776
|
-
|
|
777
|
-
until the AC coverage gap is fixed. The reconciler returns
|
|
768
|
+
aborting finalize **before** any PR is opened — so the Epic stays
|
|
769
|
+
unfinalized until the AC coverage gap is fixed. The reconciler returns
|
|
778
770
|
`status: 'waived'` without scanning features when the Epic carries
|
|
779
771
|
`acceptance::n-a`, and defends against direct CLI invocation by
|
|
780
|
-
refusing to run when
|
|
772
|
+
refusing to run when the body has no `## Acceptance Table` section
|
|
773
|
+
and no waiver is set (the
|
|
781
774
|
start gate in Phase 1 would normally catch that first).
|
|
782
775
|
2. **PR open — bus-driven (Story #2894).** On
|
|
783
776
|
`acceptance.reconcile.ok` the `Finalizer` listener invokes
|
|
@@ -800,21 +793,16 @@ just fires the emit and reads the resulting ledger.
|
|
|
800
793
|
in [`check-lifecycle-lint.js`](../../scripts/check-lifecycle-lint.js)
|
|
801
794
|
keeps `gh pr merge --auto --squash --delete-branch` confined to
|
|
802
795
|
`AutomergeArmer` — Phase 7 never shells the merge command.
|
|
803
|
-
3. **
|
|
804
|
-
|
|
805
|
-
[`closePlanningTickets`](../../scripts/lib/orchestration/finalize/close-planning-tickets.js)
|
|
806
|
-
to close the three planning context tickets
|
|
807
|
-
(`context::prd`, `context::tech-spec`, `context::acceptance-spec`)
|
|
808
|
-
so the Epic's `Closes #<id>` auto-close path is not blocked by
|
|
809
|
-
open sub-issues, then
|
|
796
|
+
3. **Hand-off — bus-driven (Story #2894).** After `openOrLocatePr`
|
|
797
|
+
returns, the `Finalizer` chains
|
|
810
798
|
[`postHandoffComment`](../../scripts/lib/orchestration/finalize/post-handoff-comment.js)
|
|
811
799
|
to upsert the canonical `epic-handoff` structured comment naming
|
|
812
|
-
the PR URL.
|
|
813
|
-
are counted under `alreadyClosed`, and the handoff comment is
|
|
800
|
+
the PR URL. The helper is idempotent — the handoff comment is
|
|
814
801
|
edited in place via `upsertStructuredComment` rather than
|
|
815
|
-
appending a duplicate.
|
|
816
|
-
|
|
817
|
-
|
|
802
|
+
appending a duplicate. There is **no planning-ticket close sweep**
|
|
803
|
+
(Story #4324): the planning artifacts live as sections of the Epic
|
|
804
|
+
body itself, so there are no context tickets to close and nothing
|
|
805
|
+
blocks the Epic's `Closes #<id>` auto-close path.
|
|
818
806
|
|
|
819
807
|
Branch cleanup is out-of-band (Phase 9 reaps local refs after merge; the
|
|
820
808
|
rare "scrap and reset" case for an unmerged Epic is handled manually).
|
|
@@ -44,12 +44,15 @@ change-set selection. Both lens sources fire through the **same**
|
|
|
44
44
|
2. Resolve `[EPIC_BRANCH]` — `epic/<epicId>`.
|
|
45
45
|
3. Resolve `[BASE_BRANCH]` from `baseBranch` in `.agentrc.json` (default:
|
|
46
46
|
`main`).
|
|
47
|
-
4. Fetch the Epic ticket
|
|
48
|
-
|
|
49
|
-
- **
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
4. Fetch the Epic ticket — the Epic body is the single planning
|
|
48
|
+
document:
|
|
49
|
+
- **Narrative sections** — Context / Goal / Scope / User Stories /
|
|
50
|
+
Acceptance Criteria.
|
|
51
|
+
- **Tech Spec** — the folded Tech Spec sections (opening with
|
|
52
|
+
`## Delivery Slicing`) inside the body's managed region.
|
|
53
|
+
5. Read the Epic body fully (including its Tech Spec sections) to
|
|
54
|
+
understand the intended
|
|
55
|
+
scope, selected lenses, and acceptance criteria.
|
|
53
56
|
|
|
54
57
|
## Step 1 — Prepare (`epic-audit-prepare.js`)
|
|
55
58
|
|
|
@@ -226,7 +229,7 @@ For each 🔴 / 🟠 finding, the host LLM MUST decide between two paths:
|
|
|
226
229
|
(path 2) and record the attempt context in Step 4.
|
|
227
230
|
2. **Escalate to the operator via Step 4.** Required when the finding
|
|
228
231
|
falls into any of the following classes:
|
|
229
|
-
- `spec-deviation` — the change diverges from the
|
|
232
|
+
- `spec-deviation` — the change diverges from the Epic/Tech Spec.
|
|
230
233
|
- `secrets` — credentials, tokens, or PII surfaced in the diff.
|
|
231
234
|
- `test-deletion` — coverage was removed without an explicit
|
|
232
235
|
decision in the spec.
|
|
@@ -282,7 +285,7 @@ The body MUST include:
|
|
|
282
285
|
|
|
283
286
|
- **Always** diff against `[BASE_BRANCH]`, not against individual Story
|
|
284
287
|
branches. The audit examines the cumulative effect of the entire Epic.
|
|
285
|
-
- **Always** read the
|
|
288
|
+
- **Always** read the Epic body and Tech Spec before walking lenses. Findings
|
|
286
289
|
without spec context are noise.
|
|
287
290
|
- **Always** cap focused fixes at one attempt per finding (Step 3). The
|
|
288
291
|
host LLM is the executor; there is no shared retry/anti-thrash module
|
|
@@ -77,21 +77,15 @@ the parent's permissions but have **no input channel** mid-run.
|
|
|
77
77
|
Run from the **main checkout** (the worktree does not exist yet):
|
|
78
78
|
|
|
79
79
|
```bash
|
|
80
|
-
node .agents/scripts/story-init.js --story <storyId>
|
|
81
|
-
--prd <prdId> --tech-spec <techSpecId>
|
|
80
|
+
node .agents/scripts/story-init.js --story <storyId>
|
|
82
81
|
```
|
|
83
82
|
|
|
84
|
-
**
|
|
85
|
-
the Epic
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
during wide fan-out). **Omit** whichever flag the prompt reported as `null`;
|
|
91
|
-
`story-init.js` then falls back to its own `getEpic` resolution for the
|
|
92
|
-
missing id (graceful degradation on a missing Epic linkage). When dispatched
|
|
93
|
-
interactively with neither flag, drop both — the legacy single-fetch path is
|
|
94
|
-
unchanged.
|
|
83
|
+
**No spec-ticket threading (Story #4324).** The Tech Spec lives as managed
|
|
84
|
+
sections of the Epic body — there is no separate Tech-Spec issue, no
|
|
85
|
+
`--tech-spec` flag, and no per-Story hierarchy trace to a spec ticket.
|
|
86
|
+
Your hydrated prompt already embeds the Epic body (with the
|
|
87
|
+
`## Acceptance Table` section stripped), which carries the folded Tech
|
|
88
|
+
Spec sections; do not fetch a Tech Spec issue.
|
|
95
89
|
|
|
96
90
|
> **Execution mode (sub-agents must read).** This command typically takes
|
|
97
91
|
> 3–6 minutes when the worktree's per-tree install runs. Invoke it
|
|
@@ -105,15 +99,15 @@ unchanged.
|
|
|
105
99
|
> partial state, so the recovery is to re-run it synchronously, but
|
|
106
100
|
> prevention is cheaper: just give Bash the 10-minute timeout and block.
|
|
107
101
|
|
|
108
|
-
The script validates `type::story`, checks blockers,
|
|
109
|
-
Epic
|
|
102
|
+
The script validates `type::story`, checks blockers, resolves the parent
|
|
103
|
+
Epic id, seeds `story-<id>` from the
|
|
110
104
|
Epic branch, and (when worktree isolation is on) runs `git worktree add`
|
|
111
105
|
at `.worktrees/story-<id>/`. The Story flips to `agent::executing`. A
|
|
112
106
|
`story-init` structured comment is upserted with the Story's inline
|
|
113
107
|
`acceptance[]` and `verify[]` arrays from the body.
|
|
114
108
|
|
|
115
109
|
Capture `workCwd`, `dependenciesInstalled` (tri-state), and
|
|
116
|
-
`context.
|
|
110
|
+
`context.parentId`. Add `--dry-run` to check
|
|
117
111
|
status without git or ticket changes.
|
|
118
112
|
|
|
119
113
|
### Step 0.5 — `cd` into the workCwd
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: >-
|
|
3
|
-
Phase 8 of sprint planning — decompose an Epic's
|
|
3
|
+
Phase 8 of sprint planning — decompose an Epic's sectioned body (which
|
|
4
|
+
carries the folded Tech Spec) into a
|
|
4
5
|
backlog of child Stories, persist the backlog, and flip the Epic to
|
|
5
6
|
`agent::ready`. Host-LLM authored; no external API calls.
|
|
6
7
|
---
|
|
@@ -18,8 +19,9 @@ Director / Architect
|
|
|
18
19
|
## Context
|
|
19
20
|
|
|
20
21
|
This helper is the **decompose phase** of the split planning pipeline. It
|
|
21
|
-
reads the
|
|
22
|
-
|
|
22
|
+
reads the Epic body — whose managed sections carry the Tech Spec previously
|
|
23
|
+
produced by the spec phase
|
|
24
|
+
helper ([`epic-plan-spec.md`](epic-plan-spec.md)) — generates the Epic's child
|
|
23
25
|
Story tickets, persists them to GitHub, and flips the Epic to
|
|
24
26
|
`agent::ready` (parking) so a human can run `/deliver` when
|
|
25
27
|
execution should begin.
|
|
@@ -38,9 +40,9 @@ skill.
|
|
|
38
40
|
|
|
39
41
|
## Constraint
|
|
40
42
|
|
|
41
|
-
- **Do not** run this skill until the spec phase is complete. The Epic
|
|
42
|
-
|
|
43
|
-
refuse to proceed otherwise.
|
|
43
|
+
- **Do not** run this skill until the spec phase is complete. The Epic body
|
|
44
|
+
must carry Tech Spec content (the managed section or a `## Delivery
|
|
45
|
+
Slicing` heading); the script will refuse to proceed otherwise.
|
|
44
46
|
- **Do not** restructure the Story set after the decomposition
|
|
45
47
|
writes — the `epic-plan-state` checkpoint records the structure as
|
|
46
48
|
committed. Use `--force` to rebuild from scratch.
|
|
@@ -52,7 +54,7 @@ skill.
|
|
|
52
54
|
## Prerequisites
|
|
53
55
|
|
|
54
56
|
1. **Epic is on `agent::review-spec`** — i.e. the spec phase has already run
|
|
55
|
-
and the
|
|
57
|
+
and the Epic body carries the Tech Spec sections.
|
|
56
58
|
2. **API keys** — `GITHUB_TOKEN` set in `.env`.
|
|
57
59
|
|
|
58
60
|
## Step 1 — Gather decomposition context
|
|
@@ -62,7 +64,8 @@ node .agents/scripts/epic-plan-decompose.js --epic [Epic_ID] --emit-context \
|
|
|
62
64
|
> temp/epic-[Epic_ID]/decomposer-context.json
|
|
63
65
|
```
|
|
64
66
|
|
|
65
|
-
The emitted JSON contains the
|
|
67
|
+
The emitted JSON contains the Epic body (`epicBody` — the spec sections and
|
|
68
|
+
acceptance table travel inside it), risk heuristics, the
|
|
66
69
|
decomposer system prompt, and the `maxTickets` **reviewability budget**
|
|
67
70
|
(Story #2798 — not a hard cap; over-budget plans require an explicit
|
|
68
71
|
`--allow-over-budget` override at persist time).
|
|
@@ -74,7 +77,7 @@ Story objects that conforms to the schema in the system prompt
|
|
|
74
77
|
and write it to `temp/epic-[Epic_ID]/tickets.json`.
|
|
75
78
|
|
|
76
79
|
When the Tech Spec carries a `## Delivery Slicing` section, author toward the
|
|
77
|
-
Architect's proposed shippable-Story clusters rather than mapping
|
|
80
|
+
Architect's proposed shippable-Story clusters rather than mapping Epic
|
|
78
81
|
capabilities 1:1; degrade gracefully (current behaviour) when it is absent.
|
|
79
82
|
|
|
80
83
|
## Step 2.5 — Phase 8.3: Holistic Consolidation (HITL diff gate)
|
|
@@ -87,7 +90,8 @@ deterministic validator and **before** the GitHub write.
|
|
|
87
90
|
Activate the
|
|
88
91
|
[`epic-plan-consolidate`](../../skills/core/epic-plan-consolidate/SKILL.md)
|
|
89
92
|
skill with `[Epic_ID]` as input. It reads the draft
|
|
90
|
-
`temp/epic-[Epic_ID]/tickets.json` plus the
|
|
93
|
+
`temp/epic-[Epic_ID]/tickets.json` plus the Epic body (with its folded
|
|
94
|
+
Tech Spec sections) from
|
|
91
95
|
`decomposer-context.json`, reconciles the draft against the Tech Spec
|
|
92
96
|
`## Delivery Slicing` target (degrading gracefully when absent), and emits:
|
|
93
97
|
|
|
@@ -187,8 +191,9 @@ is the single source of truth for which temp paths this phase owns.
|
|
|
187
191
|
|
|
188
192
|
## Troubleshooting
|
|
189
193
|
|
|
190
|
-
- "Epic #N
|
|
191
|
-
|
|
194
|
+
- "Epic #N body carries no Tech Spec sections (no ## Delivery Slicing)" —
|
|
195
|
+
run `/plan [Epic_ID]`
|
|
196
|
+
first (it will run the spec phase if the Tech Spec sections are missing).
|
|
192
197
|
- Validator rejects the tickets file — the most common causes are a
|
|
193
198
|
Story whose `parent_slug` does not point at a Feature, a missing
|
|
194
199
|
`acceptance[]` / `verify[]` array on a Story body, or a Story
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: >-
|
|
3
|
-
Phase 7 of sprint planning — generate the
|
|
4
|
-
persist them as
|
|
5
|
-
`agent::review-spec`. Host-LLM authored; no external API calls.
|
|
3
|
+
Phase 7 of sprint planning — generate the Tech Spec and Acceptance Table for
|
|
4
|
+
an Epic, persist them as managed sections of the Epic body, and flip the
|
|
5
|
+
Epic to `agent::review-spec`. Host-LLM authored; no external API calls.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Sprint Plan — Spec Phase (helper)
|
|
@@ -18,22 +18,28 @@ Director / Architect
|
|
|
18
18
|
## Context
|
|
19
19
|
|
|
20
20
|
This helper is the **spec phase** of the split planning pipeline. It produces
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
reviewer can read the
|
|
21
|
+
two planning artifacts for an Epic — a Technical Specification and an
|
|
22
|
+
Acceptance Table — persists them as **marker-delimited managed sections of
|
|
23
|
+
the Epic body** (`<!-- mandrel:tech-spec:start/end -->` and
|
|
24
|
+
`<!-- mandrel:acceptance-table:start/end -->`), and flips the Epic to
|
|
25
|
+
`agent::review-spec` (parking) so a human reviewer can read the updated Epic
|
|
26
|
+
body on GitHub before decomposition. A `/plan` Epic run creates exactly
|
|
27
|
+
**one** issue — the Epic. The PRD artifact class was retired (Story #4314);
|
|
28
|
+
its one novel section, **User Stories**, lives inline in the Epic body.
|
|
29
|
+
Story #4324 retired the `context::tech-spec` / `context::acceptance-spec`
|
|
30
|
+
ticket classes the same way — the content semantics are unchanged, only
|
|
31
|
+
where the output lives moved.
|
|
26
32
|
|
|
27
33
|
> **Single prose home.** The canonical, full-detail spec-phase contract
|
|
28
|
-
> (idempotent
|
|
34
|
+
> (idempotent managed sections, the fold rationale, the
|
|
29
35
|
> `acceptance::n-a` waiver, the Epic-lease preflight) lives in
|
|
30
36
|
> [`epic-plan.md` § Phase 7](plan-epic.md). This helper carries only the
|
|
31
37
|
> operational step list; when the two disagree, `epic-plan.md` wins.
|
|
32
38
|
|
|
33
|
-
The
|
|
34
|
-
`epic-plan-spec.js` is a deterministic wrapper that (a) emits the
|
|
35
|
-
context you need and (b) persists the
|
|
36
|
-
lifecycle state.
|
|
39
|
+
The Tech Spec and Acceptance Table are authored **directly by you, the host
|
|
40
|
+
LLM**. `epic-plan-spec.js` is a deterministic wrapper that (a) emits the
|
|
41
|
+
authoring context you need and (b) persists the sections and transitions the
|
|
42
|
+
Epic lifecycle state.
|
|
37
43
|
|
|
38
44
|
The complementary Phase 8 helper is
|
|
39
45
|
[`epic-plan-decompose.md`](epic-plan-decompose.md). The `/plan`
|
|
@@ -41,14 +47,14 @@ wrapper chains both helpers with a confirmation gate in between.
|
|
|
41
47
|
|
|
42
48
|
## Constraint
|
|
43
49
|
|
|
44
|
-
- **Do not** create
|
|
45
|
-
|
|
50
|
+
- **Do not** create any tickets from this phase — the only GitHub write is
|
|
51
|
+
the section-scoped Epic body update (plus structured comments);
|
|
46
52
|
decomposition belongs to
|
|
47
53
|
[`epic-plan-decompose.md`](epic-plan-decompose.md).
|
|
48
54
|
- **Do not** flip the Epic to `agent::ready` from this skill. The terminal
|
|
49
55
|
label for the spec phase is `agent::review-spec`.
|
|
50
56
|
- **Every** temp file must include the Epic ID in its name. Multiple Epics may
|
|
51
|
-
be planned concurrently; bare names like `temp/
|
|
57
|
+
be planned concurrently; bare names like `temp/techspec.md` will collide.
|
|
52
58
|
- **Stop and hand back to the operator** after Step 4 when
|
|
53
59
|
`planningRisk.requiresReview` is true or the operator passed
|
|
54
60
|
`--force-review` — do not chain into decomposition. Low-risk Epics
|
|
@@ -58,7 +64,8 @@ wrapper chains both helpers with a confirmation gate in between.
|
|
|
58
64
|
## Prerequisites
|
|
59
65
|
|
|
60
66
|
1. **GitHub Epic** — an open issue with the `type::epic` label. The Epic's
|
|
61
|
-
body should contain enough narrative context
|
|
67
|
+
body should contain enough narrative context (including its `## User
|
|
68
|
+
Stories` section) to seed the Tech Spec.
|
|
62
69
|
2. **API keys** — `GITHUB_TOKEN` set in `.env`.
|
|
63
70
|
|
|
64
71
|
## Step 1 — Gather authoring context
|
|
@@ -71,23 +78,18 @@ node .agents/scripts/epic-plan-spec.js --epic [Epic_ID] --emit-context \
|
|
|
71
78
|
> temp/epic-[Epic_ID]/planner-context.json
|
|
72
79
|
```
|
|
73
80
|
|
|
74
|
-
## Step 2 — Author the
|
|
81
|
+
## Step 2 — Author the Tech Spec
|
|
75
82
|
|
|
76
|
-
Read `temp/epic-[Epic_ID]/planner-context.json`. Using
|
|
77
|
-
|
|
78
|
-
`
|
|
79
|
-
|
|
80
|
-
`##
|
|
83
|
+
Read `temp/epic-[Epic_ID]/planner-context.json`. Using
|
|
84
|
+
`systemPrompts.techSpec`, the Epic body (its Context / Goal / Scope / User
|
|
85
|
+
Stories sections), and `docsContext`, write the Tech Spec to
|
|
86
|
+
`temp/epic-[Epic_ID]/techspec.md`. Open the document with the
|
|
87
|
+
`## Delivery Slicing` section (no `<h1>`); do not restate the Epic's
|
|
88
|
+
Context / Goal / Scope — the output lands as sections of the same Epic body.
|
|
81
89
|
|
|
82
|
-
## Step
|
|
90
|
+
## Step 2.5 — Author the risk verdict
|
|
83
91
|
|
|
84
|
-
|
|
85
|
-
write the Tech Spec to `temp/epic-[Epic_ID]/techspec.md`. Start with
|
|
86
|
-
`## Technical Overview` (no `<h1>`).
|
|
87
|
-
|
|
88
|
-
## Step 3.5 — Author the risk verdict
|
|
89
|
-
|
|
90
|
-
Judge the change described by the PRD and Tech Spec you just wrote and
|
|
92
|
+
Judge the change described by the Epic body and Tech Spec you just wrote and
|
|
91
93
|
write `temp/epic-[Epic_ID]/risk-verdict.json` conforming to
|
|
92
94
|
[`risk-verdict.schema.json`](../../schemas/risk-verdict.schema.json):
|
|
93
95
|
`{ axes: [{ axis, level, rationale }], summary }`. The authoritative
|
|
@@ -95,39 +97,36 @@ authoring rules (axis vocabulary, judgment-not-keywords, derivation
|
|
|
95
97
|
preview) live in the
|
|
96
98
|
[`epic-plan-spec-author` Skill, Step 4](../../skills/core/epic-plan-spec-author/SKILL.md).
|
|
97
99
|
|
|
98
|
-
## Step
|
|
100
|
+
## Step 2.6 — Author the Acceptance Table
|
|
99
101
|
|
|
100
|
-
Using `systemPrompts.acceptanceSpec`, the
|
|
101
|
-
Acceptance Spec to `temp/epic-[Epic_ID]/acceptance-spec.md`. It
|
|
102
|
-
stable-ID acceptance criteria
|
|
103
|
-
(`| AC ID | Outcome | Feature File | Scenario | Disposition |`) that
|
|
104
|
-
close-time reconciliation in `/deliver` Phase 6.
|
|
102
|
+
Using `systemPrompts.acceptanceSpec`, the Epic body, and the Tech Spec, write
|
|
103
|
+
the Acceptance Spec to `temp/epic-[Epic_ID]/acceptance-spec.md`. It opens
|
|
104
|
+
with `## Acceptance Table` and captures the stable-ID acceptance criteria
|
|
105
|
+
table (`| AC ID | Outcome | Feature File | Scenario | Disposition |`) that
|
|
106
|
+
drives close-time reconciliation in `/deliver` Phase 6.
|
|
105
107
|
|
|
106
108
|
**Skip this step only** when the Epic carries the `acceptance::n-a` waiver
|
|
107
|
-
label (refactor-only or docs-only Epics); in that case omit
|
|
108
|
-
from Step
|
|
109
|
+
label (refactor-only or docs-only Epics); in that case omit
|
|
110
|
+
`--acceptance-table` from Step 3.
|
|
109
111
|
|
|
110
|
-
## Step
|
|
112
|
+
## Step 3 — Persist and transition
|
|
111
113
|
|
|
112
114
|
```bash
|
|
113
|
-
# Normal flow (
|
|
115
|
+
# Normal flow (both managed sections)
|
|
114
116
|
node .agents/scripts/epic-plan-spec.js --epic [Epic_ID] \
|
|
115
|
-
--
|
|
116
|
-
--techspec temp/epic-[Epic_ID]/techspec.md \
|
|
117
|
+
--tech-spec temp/epic-[Epic_ID]/techspec.md \
|
|
117
118
|
--risk-verdict temp/epic-[Epic_ID]/risk-verdict.json \
|
|
118
|
-
--acceptance-
|
|
119
|
+
--acceptance-table temp/epic-[Epic_ID]/acceptance-spec.md
|
|
119
120
|
|
|
120
|
-
# Re-plan (--force overwrites the
|
|
121
|
+
# Re-plan (--force overwrites the managed sections in place)
|
|
121
122
|
node .agents/scripts/epic-plan-spec.js --epic [Epic_ID] \
|
|
122
|
-
--
|
|
123
|
-
--techspec temp/epic-[Epic_ID]/techspec.md \
|
|
123
|
+
--tech-spec temp/epic-[Epic_ID]/techspec.md \
|
|
124
124
|
--risk-verdict temp/epic-[Epic_ID]/risk-verdict.json \
|
|
125
|
-
--acceptance-
|
|
125
|
+
--acceptance-table temp/epic-[Epic_ID]/acceptance-spec.md --force
|
|
126
126
|
|
|
127
|
-
# Waived (acceptance::n-a label on Epic — no Acceptance
|
|
127
|
+
# Waived (acceptance::n-a label on Epic — no Acceptance Table authored)
|
|
128
128
|
node .agents/scripts/epic-plan-spec.js --epic [Epic_ID] \
|
|
129
|
-
--
|
|
130
|
-
--techspec temp/epic-[Epic_ID]/techspec.md \
|
|
129
|
+
--tech-spec temp/epic-[Epic_ID]/techspec.md \
|
|
131
130
|
--risk-verdict temp/epic-[Epic_ID]/risk-verdict.json
|
|
132
131
|
```
|
|
133
132
|
|
|
@@ -136,22 +135,21 @@ On success the script:
|
|
|
136
135
|
- Validates the risk verdict against `risk-verdict.schema.json` (a
|
|
137
136
|
malformed verdict fails closed before any GitHub mutation) and derives
|
|
138
137
|
the `planningRisk` envelope from it.
|
|
139
|
-
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
omitted under the `acceptance::n-a` waiver.
|
|
143
|
-
- Appends a `## Planning Artifacts` section to the Epic body.
|
|
138
|
+
- Upserts the Tech Spec content and (unless waived) the `## Acceptance
|
|
139
|
+
Table` as managed sections of the Epic body, stripping any legacy
|
|
140
|
+
`## Planning Artifacts` section. The Acceptance Table is skipped when
|
|
141
|
+
`--acceptance-table` is omitted under the `acceptance::n-a` waiver.
|
|
144
142
|
- Upserts the `risk-verdict` structured comment recording the verdict and
|
|
145
143
|
the derived envelope.
|
|
146
144
|
- Upserts the `epic-plan-state` structured comment with the current phase,
|
|
147
|
-
|
|
148
|
-
timestamps.
|
|
145
|
+
the persisted-section flags (`techSpecPersisted`, `acceptanceTable`),
|
|
146
|
+
the `riskVerdict` field, and timestamps.
|
|
149
147
|
- Flips the Epic to `agent::review-spec`.
|
|
150
148
|
|
|
151
|
-
## Step
|
|
149
|
+
## Step 4 — Cleanup
|
|
152
150
|
|
|
153
151
|
The wrapper script deletes the phase-scoped temp files automatically when
|
|
154
|
-
Step
|
|
152
|
+
Step 3 succeeds — no operator action required. The cleanup contract lives in
|
|
155
153
|
[`lib/plan-phase-cleanup.js`](../../scripts/lib/plan-phase-cleanup.js), which
|
|
156
154
|
is the single source of truth for which temp paths this phase owns. If you
|
|
157
155
|
need to inspect the temp artefacts after the fact, re-run
|
|
@@ -162,12 +160,13 @@ need to inspect the temp artefacts after the fact, re-run
|
|
|
162
160
|
Branch on the shared planning risk decision surfaced in the persist stdout
|
|
163
161
|
JSON (`planningRisk`, `reviewRouting`):
|
|
164
162
|
|
|
165
|
-
- **High risk or `--force-review` — STOP.** Surface the
|
|
166
|
-
|
|
163
|
+
- **High risk or `--force-review` — STOP.** Surface the Epic URL to the
|
|
164
|
+
operator:
|
|
167
165
|
|
|
168
|
-
> "Spec phase complete for Epic #[ID]. Review
|
|
169
|
-
> on GitHub. When you're
|
|
170
|
-
>
|
|
166
|
+
> "Spec phase complete for Epic #[ID]. Review the updated Epic body
|
|
167
|
+
> (Tech Spec sections + `## Acceptance Table`) on GitHub. When you're
|
|
168
|
+
> ready, re-run `/plan [Epic_ID]` — the wrapper will pick up where it
|
|
169
|
+
> left off and run the decompose phase."
|
|
171
170
|
|
|
172
171
|
- **Low risk — auto-proceed.** Relay `reviewRouting.operatorMessage` and
|
|
173
172
|
continue directly to Phase 8 decomposition without waiting for verbal
|
|
@@ -177,8 +176,9 @@ JSON (`planningRisk`, `reviewRouting`):
|
|
|
177
176
|
|
|
178
177
|
- If `--emit-context` fails with "Epic not found", confirm the ID matches the
|
|
179
178
|
GitHub issue number and the token has `issues:read`.
|
|
180
|
-
- If the persist call fails after
|
|
181
|
-
re-run with `--force` (the
|
|
179
|
+
- If the persist call fails after writing the Tech Spec section but before
|
|
180
|
+
the Acceptance Table, re-run with `--force` (the section upsert is
|
|
181
|
+
idempotent — it replaces the managed regions in place).
|
|
182
182
|
- If the Epic does not flip to `agent::review-spec` after the script claims
|
|
183
183
|
success, the label write likely races with a concurrent mutation — re-run the
|
|
184
|
-
persist step; it's idempotent against the
|
|
184
|
+
persist step; it's idempotent against the already-persisted sections.
|
|
@@ -20,7 +20,8 @@ them in one assistant turn rather than serially. The host runtime executes
|
|
|
20
20
|
the batch in parallel; serial calls cost N round-trips for no gain.
|
|
21
21
|
|
|
22
22
|
- **Tool primitives:** `Read`, `Grep`, `Glob`, MCP `list_*` / `get_*` calls.
|
|
23
|
-
- **When:** reading the
|
|
23
|
+
- **When:** reading the Epic body (with its folded Tech Spec sections)
|
|
24
|
+
and Story body up front; grepping
|
|
24
25
|
for multiple unrelated patterns; globbing several directory trees;
|
|
25
26
|
fetching independent GitHub tickets.
|
|
26
27
|
- **Anti-pattern:** sequential `Read` → wait → `Read` → wait → `Grep` chains
|