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
|
@@ -6,7 +6,7 @@ description: >-
|
|
|
6
6
|
`/plan`, after `epic-plan-decompose-author` writes
|
|
7
7
|
`temp/epic-<Epic_ID>/tickets.json` and before `epic-plan-decompose.js`
|
|
8
8
|
validates and persists it. Reconciles the draft against the Tech Spec
|
|
9
|
-
"Delivery Slicing"
|
|
9
|
+
"Delivery Slicing" ceiling via scope-preserving operations only.
|
|
10
10
|
allowed_tools:
|
|
11
11
|
- Read
|
|
12
12
|
- Write
|
|
@@ -17,22 +17,22 @@ allowed_tools:
|
|
|
17
17
|
|
|
18
18
|
## Policy Capsule
|
|
19
19
|
|
|
20
|
-
- Run only after `epic-plan-decompose-author` has written `temp/epic-<Epic_ID>/tickets.json`; fail loudly if the draft array is missing. Read the
|
|
20
|
+
- Run only after `epic-plan-decompose-author` has written `temp/epic-<Epic_ID>/tickets.json`; fail loudly if the draft array is missing. Read the sectioned Epic body (which carries the folded Tech Spec sections) from `temp/epic-<Epic_ID>/decomposer-context.json` (the same envelope the author skill consumed) — never re-fetch from GitHub, and never call the GitHub API from this Skill.
|
|
21
21
|
- Emit exactly two artifacts inside `temp/epic-<Epic_ID>/`: the **consolidated** `tickets.json` (overwriting the draft array in place) and a human-readable `consolidation-report.md` (the rationale + before/after diff the operator reviews at the HITL gate). Both MUST exist before returning.
|
|
22
22
|
- **Scope conservation is the load-bearing invariant.** You are a *critic*, not a second author: you MUST NOT add scope, invent tickets, or drop acceptance criteria. Every acceptance item and every `verify` entry present in the draft MUST survive into the consolidated array (possibly re-homed onto a merged Story). **This is your contract, not a machine guarantee:** there is **no runtime acceptance-union diff** on your output. The only deterministic runtime backstop the validator applies after you run is the standard ticket-structure validation — it does not re-derive the pre-consolidation acceptance/verify union, so a critic that silently dropped an acceptance item would **not** be caught downstream. (The repo's unit test exercises a *pure model* of the merge over an over-fragmented fixture to document the intended invariant; it does not inspect this Skill's actual output.) Conserve scope yourself, deliberately, on every merge.
|
|
23
23
|
- Your operations are constrained to exactly two shapes: **(1) merge two or more Stories** into one (union their `changes`/`acceptance`/`verify`/`references`, keep one coherent `goal`); **(2) rewire `depends_on`** so the edges still reference surviving sibling-Story slugs. No other mutation is permitted.
|
|
24
|
-
- Consume the Tech Spec **"Delivery Slicing"** section as
|
|
24
|
+
- Consume the Tech Spec **"Delivery Slicing"** section as a **ceiling, not a target**, when one is present: the Architect's proposed N shippable Stories is an *upper bound*, not a floor. Cluster the draft's Stories toward that grouping, and go **below** N when slices form dependent single-consumer chains — a slice whose "Independent? No" row carries no justification (parallelism, risk isolation, or delivery-envelope pressure) folds into its consumer. You **never** split above N. When the section is **absent**, degrade gracefully — apply only the cohesion rules below and leave the rest of the draft shape intact.
|
|
25
25
|
- Apply the same cohesion heuristic the author skill leads with: **one Story = one coherent change with one reason to exist**, and the **single-consumer merge rule** (a Story whose only consumer is one sibling Story is merged into that sibling). Lead every merge decision with the change's reason, not its file count.
|
|
26
26
|
- **Missing reason-to-exist check (cohesion gate).** Every draft Story body MUST carry a non-empty `reason_to_exist` meta field (the parseable form of "one Story = one coherent change with one reason to exist", encoded in the `<!-- meta: {"reason_to_exist": "..."} -->` comment and surfaced as `body.reason_to_exist` by `lib/story-body/story-body.js`). Flag any Story whose body carries **no** non-empty reason to exist: a Story that cannot state its single reason in one sentence is a cohesion smell — it is probably two Stories, or two Stories that should be merged into one. Name each flagged Story in the consolidation report so the operator sees the cohesion gap at the HITL diff gate.
|
|
27
27
|
- After every merge, **rewire `depends_on`**: drop self-edges, collapse edges that now point at the absorbing Story onto itself, and re-point any edge that named a now-deleted slug at its surviving successor. Never leave a `depends_on` referencing a slug absent from the consolidated array — the validator HARD-rejects unknown deps.
|
|
28
|
-
- The consolidation report MUST name each operation applied (merged slugs → surviving slug, rewired edges) with a one-line reason, plus a before/after Story-count line, so the operator can approve or reject at the HITL diff gate before the persist call.
|
|
28
|
+
- The consolidation report MUST name each operation applied (merged slugs → surviving slug, rewired edges) with a one-line reason, plus a before/after Story-count line, so the operator can approve or reject at the HITL diff gate before the persist call. When the consolidated count drops **below** the Delivery-Slicing count (a below-ceiling coarsening), the report MUST surface that fact explicitly — e.g. `Below ceiling: N (Delivery Slicing) → M (consolidated)` — and attach a one-line rationale to each below-ceiling merge (which dependent single-consumer slice folded into which consumer, and why it was unjustified), so the operator sees the coarsening at the Phase 8.3 advisory diff.
|
|
29
29
|
|
|
30
30
|
## Role
|
|
31
31
|
|
|
32
32
|
Senior Project Manager + Orchestrator, acting as a **holistic critic** with
|
|
33
33
|
fresh context. This Skill is deliberately *separate* from
|
|
34
34
|
`epic-plan-decompose-author` (the generator): a same-pass self-critique is the
|
|
35
|
-
weak mode this is built to escape. The generator maps
|
|
35
|
+
weak mode this is built to escape. The generator maps Epic capabilities to
|
|
36
36
|
Stories ~1:1; this critic steps back and looks at the *whole* decomposition
|
|
37
37
|
against the Tech Spec's intentional grouping before any GitHub write.
|
|
38
38
|
|
|
@@ -54,10 +54,13 @@ reads:
|
|
|
54
54
|
- `temp/epic-<Epic_ID>/tickets.json` — the **draft** Story array the
|
|
55
55
|
`epic-plan-decompose-author` Skill wrote. This is the consolidation input.
|
|
56
56
|
- `temp/epic-<Epic_ID>/decomposer-context.json` — the authoring envelope
|
|
57
|
-
emitted by `epic-plan-decompose.js --emit-context`. Read `
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
emitted by `epic-plan-decompose.js --emit-context`. Read `epicBody`
|
|
58
|
+
from it — the sectioned Epic body carrying the folded Tech Spec
|
|
59
|
+
sections (there is no separate `techSpec` key — Story #4324). The
|
|
60
|
+
**"Delivery Slicing"**
|
|
61
|
+
section (authored by `epic-plan-spec-author`) is the
|
|
62
|
+
grouping **ceiling** when present (you may merge below it, never split above
|
|
63
|
+
it); degrade gracefully when it is absent.
|
|
61
64
|
|
|
62
65
|
## Outputs
|
|
63
66
|
|
|
@@ -74,16 +77,21 @@ Both files MUST exist before the Skill returns.
|
|
|
74
77
|
|
|
75
78
|
## Procedure
|
|
76
79
|
|
|
77
|
-
### Step 1 — Load the draft and the
|
|
80
|
+
### Step 1 — Load the draft and the ceiling
|
|
78
81
|
|
|
79
82
|
Read `temp/epic-<Epic_ID>/tickets.json` (the draft array) and
|
|
80
|
-
`temp/epic-<Epic_ID>/decomposer-context.json` (for the
|
|
81
|
-
the Tech Spec
|
|
83
|
+
`temp/epic-<Epic_ID>/decomposer-context.json` (for the `epicBody`, which
|
|
84
|
+
carries the Tech Spec sections). Locate
|
|
85
|
+
the **"Delivery Slicing"** section. Pin two facts before mutating
|
|
82
86
|
anything:
|
|
83
87
|
|
|
84
|
-
1. The **
|
|
88
|
+
1. The **grouping ceiling** — the N shippable Stories the Architect proposed in
|
|
85
89
|
Delivery Slicing, or `null` when the section is absent (graceful-degrade
|
|
86
|
-
mode: cohesion rules only).
|
|
90
|
+
mode: cohesion rules only). Treat N as an upper bound you may go below, not a
|
|
91
|
+
floor you must hit. Note which slices are marked "Independent? No" and
|
|
92
|
+
whether each carries a justification (parallelism, risk isolation, or
|
|
93
|
+
delivery-envelope pressure) — an unjustified dependent slice is a
|
|
94
|
+
fold-into-consumer candidate.
|
|
87
95
|
2. The **draft Story count** — so you can spot over-fragmented capability
|
|
88
96
|
clusters.
|
|
89
97
|
|
|
@@ -92,17 +100,23 @@ anything:
|
|
|
92
100
|
Across the draft Story array, decide which Stories merge:
|
|
93
101
|
|
|
94
102
|
- **Over-fragmented capability** → when several draft Stories map to one
|
|
95
|
-
Delivery-Slicing
|
|
103
|
+
Delivery-Slicing slice (or one coherent reason to exist), merge them into a
|
|
96
104
|
single Story: union their `changes` / `acceptance` / `verify` / `references`,
|
|
97
105
|
write one coherent `goal`, and keep the union of labels.
|
|
98
|
-
- **Single-consumer Story** → merge into the one sibling that consumes it.
|
|
106
|
+
- **Single-consumer Story** → merge into the one sibling that consumes it. This
|
|
107
|
+
is the primary lever for going **below** the Delivery-Slicing ceiling: an
|
|
108
|
+
"Independent? No" slice whose only consumer is one sibling folds into that
|
|
109
|
+
sibling unless its row justifies staying separate (parallelism, risk
|
|
110
|
+
isolation, or delivery-envelope pressure). Coarsening below N here is
|
|
111
|
+
expected, not an over-reach — record it as a below-ceiling merge (see Step 4).
|
|
99
112
|
- **Missing reason to exist** → flag any Story whose body carries no non-empty
|
|
100
113
|
`reason_to_exist` meta field. A Story that cannot name its single coherent
|
|
101
114
|
reason is a cohesion smell; record it in the report so the operator can
|
|
102
115
|
re-scope it (merge, split, or have the author supply the reason) at the HITL
|
|
103
116
|
gate.
|
|
104
117
|
|
|
105
|
-
|
|
118
|
+
Never split a draft Story to *reach* N — N is a ceiling, and adding scope is
|
|
119
|
+
out of contract. Record each decision with its one-line reason for the report.
|
|
106
120
|
|
|
107
121
|
### Step 3 — Rewire dependencies and conserve scope
|
|
108
122
|
|
|
@@ -120,7 +134,12 @@ After applying the operations:
|
|
|
120
134
|
|
|
121
135
|
Write the consolidated array to `temp/epic-<Epic_ID>/tickets.json` (2-space
|
|
122
136
|
indent, machine-consumed) and the rationale + before/after diff to
|
|
123
|
-
`temp/epic-<Epic_ID>/consolidation-report.md`.
|
|
137
|
+
`temp/epic-<Epic_ID>/consolidation-report.md`. When the consolidated count
|
|
138
|
+
landed **below** the Delivery-Slicing ceiling, the report MUST call that out
|
|
139
|
+
explicitly — a `Below ceiling: N (Delivery Slicing) → M (consolidated)` line
|
|
140
|
+
plus a one-line rationale per below-ceiling merge (which dependent
|
|
141
|
+
single-consumer slice folded into which consumer, and why it was unjustified) —
|
|
142
|
+
so the operator sees the coarsening at the Phase 8.3 advisory diff.
|
|
124
143
|
|
|
125
144
|
### Step 5 — Hand back to `/plan`
|
|
126
145
|
|
|
@@ -32,9 +32,10 @@ allowed_tools:
|
|
|
32
32
|
|
|
33
33
|
## Role
|
|
34
34
|
|
|
35
|
-
Senior Project Manager + Orchestrator. The Skill's job is to take
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
Senior Project Manager + Orchestrator. The Skill's job is to take the
|
|
36
|
+
sectioned Epic body (whose managed sections carry the folded Tech Spec and
|
|
37
|
+
Acceptance Table — Story #4324) and emit a flat Story backlog the
|
|
38
|
+
orchestrator can execute autonomously.
|
|
38
39
|
|
|
39
40
|
## When to use
|
|
40
41
|
|
|
@@ -55,10 +56,12 @@ reads:
|
|
|
55
56
|
`node .agents/scripts/epic-plan-decompose.js --epic <Epic_ID> --emit-context`.
|
|
56
57
|
Fields:
|
|
57
58
|
- `epic.id`, `epic.title`
|
|
58
|
-
- `
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
boundary + dependency-DAG
|
|
59
|
+
- `epicBody` — the sectioned Epic body. It carries everything the
|
|
60
|
+
decomposer needs in one document: the `## User Stories` section
|
|
61
|
+
(User-Story extraction), the folded Tech Spec sections
|
|
62
|
+
(`## Delivery Slicing` onward — module boundary + dependency-DAG
|
|
63
|
+
extraction), and the `## Acceptance Table` AC-ID table. There is no
|
|
64
|
+
separate `techSpec` envelope key (Story #4324).
|
|
62
65
|
- `heuristics[]` — risk heuristics surfaced from
|
|
63
66
|
`agentSettings.planning.riskHeuristics`. Apply each one against the
|
|
64
67
|
Stories you are emitting; flag matches via `risk::high` labels.
|
|
@@ -117,7 +120,7 @@ Pin three values explicitly before writing any tickets:
|
|
|
117
120
|
Apply the fully-rendered decomposer system prompt — the `systemPrompt`
|
|
118
121
|
field of the loaded context envelope, produced by
|
|
119
122
|
[`decomposer-prompts.js`](../../../scripts/lib/templates/decomposer-prompts.js)
|
|
120
|
-
— to the
|
|
123
|
+
— to the sectioned Epic body (`epicBody`). That rendered string is the authoritative
|
|
121
124
|
prompt body (with `maxTickets`, `maxTokenBudget`, and the sizing thresholds
|
|
122
125
|
already interpolated); the authoring-guidance sections below complement it
|
|
123
126
|
without restating it. Emit JSON only (no prose, no Markdown fence). The
|
|
@@ -224,6 +227,8 @@ They are NOT top-level ticket fields.
|
|
|
224
227
|
|
|
225
228
|
The first question is **cohesion, not count**: *is this one coherent change with one reason to exist?* File count cannot tell a trivial 10-file mechanical rename from a hard 3-file parser+caller+config change — so lead with the change's reason, not its size. Size against the real one-pass delivery envelope (`maxTokenBudget`): a Story is correctly sized when a single agent can hold its full change, acceptance, and verification in one pass within that budget.
|
|
226
229
|
|
|
230
|
+
The envelope also has a **floor**, not just a ceiling: a Story that would plausibly use well under a third of `maxTokenBudget` and is neither parallel-deliverable nor orthogonal to its siblings is a **merge candidate** — modern frontier models one-shot capability-sized changes, so a chain of small dependent Stories needlessly pays a full per-Story delivery session (hydration, branch, PR, review, CI) per link. This is soft guidance, not a threshold or validator finding; the canonical phrasing lives in `DELIVERABLE_GRANULARITY_GUIDANCE.envelopeFloor` in `ticket-validator-sizing.js`, which the decomposer prompt interpolates — do not restate a divergent version here.
|
|
231
|
+
|
|
227
232
|
- **One Story = one coherent change with one reason to exist.** If you cannot state that reason in a sentence, the Story is probably two Stories.
|
|
228
233
|
- **Single-consumer merge rule.** A Story whose only consumer is one sibling Story should be **merged into that sibling** rather than emitted separately — a single-consumer downstream slice is not its own unit of work.
|
|
229
234
|
- **Split independent, parallelizable work** into sibling Stories — but only when the pieces genuinely have separate reasons to exist.
|
|
@@ -237,11 +242,11 @@ The first question is **cohesion, not count**: *is this one coherent change with
|
|
|
237
242
|
|
|
238
243
|
#### DELIVERY SLICING (consume the Tech Spec target grouping when present)
|
|
239
244
|
|
|
240
|
-
The Tech Spec may carry a `## Delivery Slicing` section authored by the
|
|
241
|
-
Architect, proposing how the
|
|
245
|
+
The Epic body's Tech Spec sections may carry a `## Delivery Slicing` section authored by the
|
|
246
|
+
Architect, proposing how the Epic's enumerated capabilities cluster into N
|
|
242
247
|
shippable Stories. When that section is **present**, treat it as the **target
|
|
243
248
|
grouping**: prefer emitting Stories that match the Architect's proposed
|
|
244
|
-
clusters rather than mapping
|
|
249
|
+
clusters rather than mapping Epic capabilities 1:1. When it is **absent**,
|
|
245
250
|
degrade gracefully — decompose at deliverable granularity using the cohesion
|
|
246
251
|
rules above, exactly as before. The Phase 8 holistic consolidation pass
|
|
247
252
|
(`epic-plan-consolidate`) reconciles your draft against this same Delivery
|
|
@@ -263,7 +268,7 @@ Declaring `wide` with a non-empty reason **lifts the `hardFiles` rejection** —
|
|
|
263
268
|
|
|
264
269
|
#### BRAND / COPY / STYLE WORK
|
|
265
270
|
|
|
266
|
-
- Stories that touch user-visible copy, brand assets, or visual style MUST cite the relevant section of `docs/style-guide.md` in `acceptance` (e.g. `"acceptance": ["Hero copy matches docs/style-guide.md §3 (voice & tone)"]`). If `docs/style-guide.md` does not exist or has no relevant section, state that explicitly: `"acceptance": ["docs/style-guide.md absent — copy reviewed against the inline brand brief in
|
|
271
|
+
- Stories that touch user-visible copy, brand assets, or visual style MUST cite the relevant section of `docs/style-guide.md` in `acceptance` (e.g. `"acceptance": ["Hero copy matches docs/style-guide.md §3 (voice & tone)"]`). If `docs/style-guide.md` does not exist or has no relevant section, state that explicitly: `"acceptance": ["docs/style-guide.md absent — copy reviewed against the inline brand brief in the Epic body"]`. Silence on style sourcing is a smell.
|
|
267
272
|
|
|
268
273
|
#### BINDING ACCEPTANCE vs ADVISORY CHANGES (authoring altitude)
|
|
269
274
|
|
|
@@ -281,11 +286,11 @@ When a Story's acceptance describes a **signed-in / authenticated** persona reac
|
|
|
281
286
|
- Phrase it as: `"From the signed-in home, the persona navigates to Reports → Export and sees the export button"` — not `"GET /reports/export returns the export view"`.
|
|
282
287
|
- This applies to signed-in journeys only; an unauthenticated landing page or a deliberately deep-linkable share URL is exempt — say so in the acceptance item when you take that exemption.
|
|
283
288
|
|
|
284
|
-
### WAVE-0 BDD SCAFFOLD STORY (features-first; emit when the Acceptance
|
|
289
|
+
### WAVE-0 BDD SCAFFOLD STORY (features-first; emit when the Acceptance Table has `new`-disposition rows)
|
|
285
290
|
|
|
286
|
-
The
|
|
291
|
+
The Epic body's `## Acceptance Table` section (columns `AC ID | Outcome | Feature File | Scenario | Disposition`) tags each row's `Disposition` with one of `new | updated | unchanged`. A `new` row names a `.feature` file + scenario that does NOT yet exist on `main`. The framework is features-first: implementation Stories reference those `.feature` paths in their `verify[]` lines, so the files MUST already exist when those Stories run — otherwise verification fails mid-delivery on a missing file (observed gap: Epic #18 in `dsj1984/athportal` had 9 `new` rows and no Story tasked with creating the feature files Stories #1457 / #1466 verified against).
|
|
287
292
|
|
|
288
|
-
When the Acceptance
|
|
293
|
+
When the Acceptance Table contains **one or more `Disposition: new` rows**, you MUST emit **exactly one** dedicated wave-0 scaffold Story whose sole job is to create those `.feature` files with `@skip`-tagged scenarios BEFORE any implementation Story runs:
|
|
289
294
|
|
|
290
295
|
- **goal** (in body string): contains the literal token `bdd-scaffold`.
|
|
291
296
|
- **depends_on**: EMPTY (`[]`) — the scaffold runs first, in wave 0.
|
|
@@ -295,9 +300,9 @@ When the Acceptance Spec contains **one or more `Disposition: new` rows**, you M
|
|
|
295
300
|
- **verify** (top-level array): a grep/validate command (tier `validate`), NOT an e2e runner — verifying that a file exists with the required tags needs no browser/playwright run. Include a check that each new AC ID's namespaced tag is present in the scaffolded files, alongside the `@skip` check.
|
|
296
301
|
- Each implementation Story whose `verify[]` references a scaffolded `.feature` path MUST add `depends_on: ["<scaffold-slug>"]` so the scaffold lands in an earlier wave. Omitting the link trips the soft `missing-bdd-scaffold` finding in `ticket-validator-conflicts.js` (advisory, not a hard block).
|
|
297
302
|
|
|
298
|
-
When the Acceptance
|
|
303
|
+
When the Acceptance Table contains **zero `new`-disposition rows** (every row is `updated` or `unchanged`), do NOT emit a scaffold Story — there is nothing to create.
|
|
299
304
|
|
|
300
|
-
**Worked example.** Epic #42, Acceptance
|
|
305
|
+
**Worked example.** Epic #42, Acceptance Table with two `new` rows (`AC-1` -> `tests/features/billing/invoice.feature`, `AC-2` -> `tests/features/billing/refund.feature`). The scaffold Story below uses a serialized string `body`, top-level `acceptance`/`verify` arrays, an empty `depends_on`, and tags each scenario with both `@skip` and its namespaced `@epic-42-ac-N` tag:
|
|
301
306
|
|
|
302
307
|
{
|
|
303
308
|
"slug": "scaffold-billing-feature-files",
|
|
@@ -407,7 +412,7 @@ any logical ordering requirement via Story-level `depends_on`.
|
|
|
407
412
|
- Do **not** call the GitHub API from this Skill. Persistence is the
|
|
408
413
|
script's job; the Skill is pure JSON authoring.
|
|
409
414
|
- Do **not** write outside `temp/epic-<Epic_ID>/`. Reads may cover the
|
|
410
|
-
|
|
415
|
+
Epic body plus any docs the context envelope cites.
|
|
411
416
|
- The decomposer prompt's `${maxTickets}` value is the **reviewability
|
|
412
417
|
budget** (Story #2798). Staying under is the default; exceeding it
|
|
413
418
|
requires both an `over_budget_rationale` in the JSON output and the
|
|
@@ -5,7 +5,7 @@ description: >-
|
|
|
5
5
|
ticket array an Epic's decompose phase produced. Use during Phase 8 of
|
|
6
6
|
`/plan`, after `epic-plan-decompose-author` / `epic-plan-consolidate` write
|
|
7
7
|
`temp/epic-<Epic_ID>/tickets.json` and before `epic-plan-decompose.js`
|
|
8
|
-
validates and persists it. Reads the
|
|
8
|
+
validates and persists it. Reads the sectioned Epic body AND the cited
|
|
9
9
|
code surfaces, then emits predicted-rework findings before any GitHub write.
|
|
10
10
|
allowed_tools:
|
|
11
11
|
- Read
|
|
@@ -18,7 +18,7 @@ allowed_tools:
|
|
|
18
18
|
|
|
19
19
|
## Policy Capsule
|
|
20
20
|
|
|
21
|
-
- Run only after a draft `temp/epic-<Epic_ID>/tickets.json` exists (authored by `epic-plan-decompose-author`, and consolidated by `epic-plan-consolidate` if that pass ran); fail loudly if the draft array is missing. Read the
|
|
21
|
+
- Run only after a draft `temp/epic-<Epic_ID>/tickets.json` exists (authored by `epic-plan-decompose-author`, and consolidated by `epic-plan-consolidate` if that pass ran); fail loudly if the draft array is missing. Read the sectioned Epic body from `temp/epic-<Epic_ID>/decomposer-context.json` (the same envelope the author skill consumed) — never re-fetch from GitHub, and never call the GitHub API from this Skill.
|
|
22
22
|
- **You MUST read the actual cited code surfaces.** For every Story, open the files named in its `changes[]` / `references[]` (resolve each path against the repo root; use `Read` / `Grep`) and read enough of each to judge whether the Story's `acceptance[]` is verifiable against the real code and whether its `changes[]` assumptions hold. This is the load-bearing difference between this critic and the structural file-assumption gate: that gate proves a path **exists** (or does not); this critic reads what the file actually **contains**. A pre-mortem that did not open the cited files has not run.
|
|
23
23
|
- Emit exactly one artifact: a human-readable `temp/epic-<Epic_ID>/premortem-report.md` — the predicted-rework findings the operator reviews at the Phase 8 HITL diff. It MUST exist before returning.
|
|
24
24
|
- **This critic never writes to GitHub and never persists `tickets.json`.** It is read-and-report only: it does NOT mutate the draft array, does NOT create issues, and does NOT flip any label. Re-authoring on its findings is the author skill's job (the workflow re-runs `epic-plan-decompose-author` on the report before the persist call).
|
|
@@ -32,7 +32,7 @@ Senior Engineer + Architect, acting as a **fresh-context pre-mortem critic**.
|
|
|
32
32
|
This Skill is deliberately *separate* from `epic-plan-decompose-author` (the
|
|
33
33
|
generator) and from `epic-plan-consolidate` (the scope-preserving merge critic):
|
|
34
34
|
a same-pass self-critique is the weak mode this is built to escape. The
|
|
35
|
-
generator maps
|
|
35
|
+
generator maps Epic capabilities to Stories against the spec text; this critic
|
|
36
36
|
opens the **actual cited code** and asks "if I tried to deliver this exact
|
|
37
37
|
backlog, where would it rework?" — before any GitHub write makes the rework
|
|
38
38
|
expensive.
|
|
@@ -56,8 +56,9 @@ The workflow passes the Epic ID as the Skill argument. The Skill itself reads:
|
|
|
56
56
|
- `temp/epic-<Epic_ID>/tickets.json` — the **draft** (or consolidated) Story
|
|
57
57
|
array. This is the pre-mortem subject.
|
|
58
58
|
- `temp/epic-<Epic_ID>/decomposer-context.json` — the authoring envelope emitted
|
|
59
|
-
by `epic-plan-decompose.js --emit-context`. Read `
|
|
60
|
-
|
|
59
|
+
by `epic-plan-decompose.js --emit-context`. Read `epicBody` from it —
|
|
60
|
+
the sectioned Epic body carrying the folded Tech Spec sections
|
|
61
|
+
(there is no separate `techSpec` key — Story #4324).
|
|
61
62
|
- **The repository working tree** — the actual files each Story's `changes[]` /
|
|
62
63
|
`references[]` name. Resolve each path against the repo root and read it.
|
|
63
64
|
|
|
@@ -78,7 +79,7 @@ artifact and mutates **no** GitHub state.
|
|
|
78
79
|
### Step 1 — Load the draft and the spec
|
|
79
80
|
|
|
80
81
|
Read `temp/epic-<Epic_ID>/tickets.json` (the Story array) and
|
|
81
|
-
`temp/epic-<Epic_ID>/decomposer-context.json` (for the
|
|
82
|
+
`temp/epic-<Epic_ID>/decomposer-context.json` (for the `epicBody`). If the
|
|
82
83
|
draft array is missing, fail loudly and instruct the caller to run the
|
|
83
84
|
`epic-plan-decompose-author` Skill first.
|
|
84
85
|
|