mandrel 1.94.0 → 2.0.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 +59 -73
- package/.agents/agents/story-worker.md +12 -13
- package/.agents/docs/SDLC.md +489 -1285
- package/.agents/docs/agentrc-reference.json +177 -67
- package/.agents/docs/configuration.md +104 -138
- package/.agents/docs/execution-reference.md +17 -20
- package/.agents/docs/quality-gates.md +13 -19
- package/.agents/docs/workflows.md +3 -3
- package/.agents/instructions.md +70 -81
- package/.agents/rules/ci-remediation.md +8 -12
- package/.agents/rules/git-conventions-reference.md +6 -7
- package/.agents/rules/git-conventions.md +16 -22
- package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
- package/.agents/schemas/agentrc.schema.json +54 -214
- package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
- package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
- package/.agents/schemas/risk-verdict.schema.json +0 -13
- package/.agents/scripts/analyze-execution.js +1 -1
- package/.agents/scripts/audit-to-stories.js +7 -7
- package/.agents/scripts/boot-sweep.js +1 -1
- package/.agents/scripts/check-lifecycle-lint.js +6 -9
- package/.agents/scripts/check-prepush-recovery.js +1 -1
- package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
- package/.agents/scripts/lib/Logger.js +6 -10
- package/.agents/scripts/lib/audit-suite/runner.js +2 -2
- package/.agents/scripts/lib/audit-suite/selector.js +5 -5
- package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
- package/.agents/scripts/lib/baselines/kernel.js +206 -18
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -4
- package/.agents/scripts/lib/baselines/reader.js +1 -6
- package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
- package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
- package/.agents/scripts/lib/checks/index.js +2 -1
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
- package/.agents/scripts/lib/cli/standard-args.js +13 -22
- package/.agents/scripts/lib/cli-args.js +16 -7
- package/.agents/scripts/lib/close-validation/gates.js +2 -2
- package/.agents/scripts/lib/config/ci.js +6 -31
- package/.agents/scripts/lib/config/delivery-routing.js +45 -29
- package/.agents/scripts/lib/config/explain.js +55 -36
- package/.agents/scripts/lib/config/limits.js +17 -58
- package/.agents/scripts/lib/config/paths.js +0 -2
- package/.agents/scripts/lib/config/quality.js +1 -1
- package/.agents/scripts/lib/config/runners.js +17 -50
- package/.agents/scripts/lib/config/temp-paths.js +19 -14
- package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
- package/.agents/scripts/lib/config-resolver.js +2 -7
- package/.agents/scripts/lib/config-settings-schema-delivery.js +24 -148
- package/.agents/scripts/lib/config-settings-schema-quality.js +8 -14
- package/.agents/scripts/lib/config-settings-schema.js +52 -38
- package/.agents/scripts/lib/dependency-parser.js +3 -2
- package/.agents/scripts/lib/doc-tiers.js +2 -2
- package/.agents/scripts/lib/duplicate-search.js +211 -41
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
- package/.agents/scripts/lib/findings/promote-finding.js +5 -5
- package/.agents/scripts/lib/framework-version.js +2 -3
- package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
- package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
- package/.agents/scripts/lib/git-utils.js +32 -6
- package/.agents/scripts/lib/github/framework-repo.js +6 -0
- package/.agents/scripts/lib/label-constants.js +10 -23
- package/.agents/scripts/lib/label-taxonomy.js +9 -43
- package/.agents/scripts/lib/observability/active-story-env.js +1 -1
- package/.agents/scripts/lib/observability/hook-heartbeat.js +20 -52
- package/.agents/scripts/lib/observability/source-classifier.js +3 -3
- package/.agents/scripts/lib/onboard/init-tail.js +1 -3
- package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
- package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +8 -5
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +83 -20
- package/.agents/scripts/lib/orchestration/code-review.js +20 -268
- package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
- package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
- package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
- package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
- package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +8 -8
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
- package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
- package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
- package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
- package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
- package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
- package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
- package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
- package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +13 -13
- package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
- package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
- package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
- package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
- package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
- package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
- package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
- package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
- package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
- package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
- package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
- package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
- package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
- package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
- package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
- package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
- package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -12
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
- package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
- package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
- package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
- package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
- package/.agents/scripts/lib/orchestration/ticket-validator.js +2 -7
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
- package/.agents/scripts/lib/planning-corpus.js +16 -11
- package/.agents/scripts/lib/preflight-runner.js +2 -2
- package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
- package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
- package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
- package/.agents/scripts/lib/story-adjacency.js +11 -14
- package/.agents/scripts/lib/story-body/story-body.js +124 -70
- package/.agents/scripts/lib/story-plan.js +2 -4
- package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
- package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
- package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
- package/.agents/scripts/lib/validation-evidence.js +1 -1
- package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
- package/.agents/scripts/lib/workspace-provisioner.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
- package/.agents/scripts/lint-issue-body.js +71 -40
- package/.agents/scripts/mandrel-update-preflight.js +1 -1
- package/.agents/scripts/notify.js +4 -3
- package/.agents/scripts/plan-context.js +64 -74
- package/.agents/scripts/plan-persist.js +121 -280
- package/.agents/scripts/plan-run-epilogue.js +97 -0
- package/.agents/scripts/providers/github/issues.js +17 -33
- package/.agents/scripts/providers/github/mappers.js +0 -12
- package/.agents/scripts/providers/github/tickets.js +2 -5
- package/.agents/scripts/resolve-plan-run.js +117 -0
- package/.agents/scripts/signals-view.js +24 -19
- package/.agents/scripts/single-story-close.js +11 -14
- package/.agents/scripts/single-story-confirm-merge.js +39 -23
- package/.agents/scripts/single-story-init.js +29 -20
- package/.agents/scripts/stories-wave-tick.js +6 -6
- package/.agents/scripts/story-plan.js +26 -47
- package/.agents/scripts/update-ticket-state.js +6 -15
- package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
- package/.agents/skills/core/idea-refinement/SKILL.md +6 -6
- package/.agents/skills/core/scope-triage/SKILL.md +28 -172
- package/.agents/skills/skills.index.json +3 -43
- package/.agents/starter-agentrc.json +0 -5
- package/.agents/templates/agent-protocol.md +9 -10
- package/.agents/workflows/audit-architecture.md +3 -3
- package/.agents/workflows/audit-clean-code.md +3 -3
- package/.agents/workflows/audit-dependencies.md +3 -3
- package/.agents/workflows/audit-devops.md +3 -3
- package/.agents/workflows/audit-documentation.md +5 -5
- package/.agents/workflows/audit-lighthouse.md +3 -3
- package/.agents/workflows/audit-navigability.md +3 -2
- package/.agents/workflows/audit-performance.md +3 -3
- package/.agents/workflows/audit-privacy.md +3 -3
- package/.agents/workflows/audit-quality.md +3 -3
- package/.agents/workflows/audit-security.md +3 -3
- package/.agents/workflows/audit-seo.md +3 -3
- package/.agents/workflows/audit-sre.md +3 -3
- package/.agents/workflows/audit-to-stories.md +20 -20
- package/.agents/workflows/audit-ux-ui.md +3 -3
- package/.agents/workflows/deliver.md +122 -174
- package/.agents/workflows/git-cleanup.md +3 -4
- package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
- package/.agents/workflows/helpers/acceptance-self-eval.md +16 -29
- package/.agents/workflows/helpers/code-review.md +70 -193
- package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
- package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
- package/.agents/workflows/helpers/diagnose.md +10 -10
- package/.agents/workflows/helpers/parallel-tooling.md +1 -1
- package/.agents/workflows/helpers/signals.md +16 -16
- package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
- package/.agents/workflows/mandrel-update.md +2 -1
- package/.agents/workflows/plan.md +112 -145
- package/.agents/workflows/qa-assist.md +24 -30
- package/.agents/workflows/qa-explore.md +29 -38
- package/.agents/workflows/qa-run.md +2 -2
- package/README.md +9 -8
- package/docs/CHANGELOG.md +30 -0
- package/lib/migrations/index.js +6 -5
- package/package.json +2 -2
- package/.agents/agents/retro.md +0 -42
- package/.agents/personas/architect.md +0 -113
- package/.agents/personas/devops-engineer.md +0 -38
- package/.agents/personas/engineer.md +0 -33
- package/.agents/personas/project-manager.md +0 -114
- package/.agents/personas/qa-engineer.md +0 -95
- package/.agents/personas/security-engineer.md +0 -111
- package/.agents/personas/technical-writer.md +0 -101
- package/.agents/schemas/dispatch-manifest.json +0 -232
- package/.agents/schemas/epic-spec.schema.json +0 -153
- package/.agents/schemas/lifecycle/slice.end.schema.json +0 -21
- package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +0 -20
- package/.agents/schemas/lifecycle/slice.start.schema.json +0 -17
- package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
- package/.agents/scripts/bookkeeping-reconcile.js +0 -117
- package/.agents/scripts/dispatcher.js +0 -295
- package/.agents/scripts/epic-audit-prepare.js +0 -497
- package/.agents/scripts/epic-audit-recheck.js +0 -274
- package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
- package/.agents/scripts/epic-deliver-preflight.js +0 -462
- package/.agents/scripts/epic-deliver-prepare.js +0 -852
- package/.agents/scripts/epic-execute-record-wave.js +0 -449
- package/.agents/scripts/epic-plan-clarity.js +0 -211
- package/.agents/scripts/epic-plan-healthcheck.js +0 -581
- package/.agents/scripts/epic-reconcile.js +0 -625
- package/.agents/scripts/lib/baseline-snapshot.js +0 -979
- package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
- package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
- package/.agents/scripts/lib/config/lifecycle.js +0 -40
- package/.agents/scripts/lib/config/preflight.js +0 -58
- package/.agents/scripts/lib/config/retro.js +0 -77
- package/.agents/scripts/lib/epic-merge-lock.js +0 -322
- package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
- package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -539
- package/.agents/scripts/lib/orchestration/deliver-route.js +0 -173
- package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
- package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
- package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
- package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -621
- package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
- package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
- package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
- package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
- package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
- package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
- package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
- package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
- package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
- package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +0 -270
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -465
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -284
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
- package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
- package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
- package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
- package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
- package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
- package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
- package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
- package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
- package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
- package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
- package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
- package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
- package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
- package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
- package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
- package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
- package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
- package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
- package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
- package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
- package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
- package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
- package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
- package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
- package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
- package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
- package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
- package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -302
- package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
- package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
- package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
- package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
- package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
- package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
- package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
- package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
- package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
- package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
- package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
- package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
- package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
- package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
- package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
- package/.agents/scripts/lib/push-epic-retry.js +0 -209
- package/.agents/scripts/lib/spec/index.js +0 -36
- package/.agents/scripts/lib/spec/loader.js +0 -425
- package/.agents/scripts/lib/spec/state.js +0 -208
- package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
- package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
- package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
- package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
- package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
- package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
- package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
- package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
- package/.agents/scripts/lib/wave-runner/tick.js +0 -754
- package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
- package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
- package/.agents/scripts/lifecycle-emit.js +0 -510
- package/.agents/scripts/retro-run.js +0 -218
- package/.agents/scripts/slice-phase.js +0 -361
- package/.agents/scripts/standalone-feedback-rollup.js +0 -188
- package/.agents/scripts/story-close.js +0 -294
- package/.agents/scripts/story-init.js +0 -599
- package/.agents/scripts/story-phase.js +0 -369
- package/.agents/scripts/wave-tick.js +0 -464
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
- package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
- package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
- package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
- package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -383
- package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
- package/.agents/workflows/helpers/deliver-epic-reference.md +0 -547
- package/.agents/workflows/helpers/deliver-epic-single.md +0 -331
- package/.agents/workflows/helpers/deliver-epic.md +0 -998
- package/.agents/workflows/helpers/deliver-stories.md +0 -450
- package/.agents/workflows/helpers/epic-audit.md +0 -189
- package/.agents/workflows/helpers/epic-deliver-story.md +0 -436
- package/.agents/workflows/helpers/epic-testing.md +0 -125
- package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
- package/.agents/workflows/helpers/plan-epic.md +0 -353
- package/.agents/workflows/helpers/plan-story.md +0 -251
- package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
- /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
|
@@ -1,441 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: epic-plan-decompose-author
|
|
3
|
-
description: >-
|
|
4
|
-
Author the Story ticket JSON for an Epic from the decomposer
|
|
5
|
-
authoring context emitted by `plan-context.js --epic <Epic_ID>`. Use
|
|
6
|
-
during Phase 8 of `/plan` when the host LLM needs to write the ticket
|
|
7
|
-
array before `plan-persist.js` validates and persists it.
|
|
8
|
-
allowed_tools:
|
|
9
|
-
- Read
|
|
10
|
-
- Write
|
|
11
|
-
- Bash
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# epic-plan-decompose-author
|
|
15
|
-
|
|
16
|
-
## Policy Capsule
|
|
17
|
-
|
|
18
|
-
- Run only after `plan-context.js --epic <Epic_ID>` has written `temp/epic-<Epic_ID>/decomposer-context.json`; fail loudly if the file is missing.
|
|
19
|
-
- Emit exactly one artifact: `temp/epic-<Epic_ID>/tickets.json` (a JSON array). Do not write anywhere else, and never call the GitHub API from this Skill — persistence belongs to the script.
|
|
20
|
-
- Output is JSON only — no prose, no Markdown fence. The downstream validator (`lib/orchestration/ticket-validator.js`) is the authoritative gate.
|
|
21
|
-
- **Re-emit rule (amend, don't regenerate — Story #4431).** On a re-emit — the validator rejecting the draft, or a Phase 8.3/8.4/8.5 critic flagging specific Stories — apply **targeted edits** to the existing `temp/epic-<Epic_ID>/tickets.json`, fixing only the rejected or flagged Stories, rather than re-authoring the whole array from scratch. `helpers/plan-epic.md` bounds each critic's feedback to **one refinement pass** — apply the edit and re-run the downstream step once; do not loop.
|
|
22
|
-
- Treat **`maxTickets`** from the context envelope as a **reviewability budget**, not a hard authoring cap (Story #2798). Merge narrow, single-module Stories into their capability first; if the plan genuinely needs more, emit the full plan and add a compact `over_budget_rationale` note inside the first Story's `## Goal` section explaining why the plan exceeds the budget. Operator persistence then requires the explicit `--allow-over-budget` override on `plan-persist.js`; without it the persist step rejects the over-budget array. Never truncate the JSON array to fit.
|
|
23
|
-
- Honour the 2-tier hierarchy: every ticket is a **Story** attached directly to the Epic. Stories carry the implementation scope inline; no Feature and no lower ticket tier exists. Thematic grouping is prose in the Epic body / Tech Spec, never a ticket.
|
|
24
|
-
- **Decompose at deliverable granularity, not module/task level.** A Story is a capability slice a frontier model delivers and self-verifies in one pass — a shippable slice a reviewer would accept as a single PR — not a single module or file. See the STORY SIZING section for the full guidance and the single-consumer merge rule.
|
|
25
|
-
- Every ticket carries `type::story` and `persona::*` labels. Every Story ticket object MUST carry top-level `acceptance: string[]` and `verify: string[]` arrays (read by `hasInlineAcceptanceAndVerify` in the validator) and `body` MUST be a **string** produced by `serialize()` from `lib/story-body/story-body.js` — an object body causes `createOp` in `epic-spec-reconciler-ops.js` to throw `StoryBodyParseError` (Story #3302), and is also silently discarded by `composeStoryBody` in the GitHub provider, producing an empty issue body.
|
|
26
|
-
- **New-File Contract**: any path referenced in `goal`, `acceptance`, or `verify` that does not exist on `main` MUST appear in the Story's `changes[]` with `assumption: "creates"`; otherwise the freshness validator rejects the decompose.
|
|
27
|
-
- Acceptance items MUST be **observable from outside the agent** (command exits 0, file exists, snapshot matches, testid resolves). Items like "verify by reading the diff" or "looks good" are forbidden — push them into `verify` commands instead.
|
|
28
|
-
- Acceptance MUST NOT prescribe a commit subject starting with a non-Conventional-Commits prefix; the literal `baseline-refresh:` leading token is forbidden (use a body trailer instead — see Epic #2501).
|
|
29
|
-
- A legitimately broad Story (files > `hardFiles`) MUST declare `wide` with a one-line reason (encoded in the serialized body string via the `<!-- meta -->` comment) to lift the `hardFiles` rejection; lead the sizing decision with cohesion, not count. UI-touching Stories MUST end `changes` with a `data-testid invariance:` or `data-testid changes: <old> -> <new>` declaration.
|
|
30
|
-
- A Story's `depends_on` references only **sibling Stories within the same Epic**. Apply the cross-cutting-config-file rule (sequential `depends_on` or a late-wave wiring Story) whenever multiple Stories edit a shared root config file.
|
|
31
|
-
- **Authoring-contract altitude (Epic #4131 F8).** `acceptance[]` and `verify[]` are the Story's **binding contract** — the executor MUST satisfy them exactly, and they are the only definition of "done." `changes[]` and `references[]` are an **advisory implementation sketch**: a best-effort prediction of which files the work touches that the executor MAY revise when the codebase tells a different story. Author `acceptance[]`/`verify[]` so they capture the outcome independently of any particular file layout — never bake an incidental implementation detail into them that the advisory sketch is free to change. This does **not** weaken the file-assumption gate: `changes[]` paths are still validated structurally against the base branch (a `creates` against an existing path still fails), the New-File Contract still holds, and the executor's revised approach stays bounded by the inviolable `acceptance[]`/`verify[]` contract and `rules/security-baseline.md`.
|
|
32
|
-
- **Navigate-don't-deep-link acceptance standard (Epic #4131 F5).** For any Story whose acceptance describes a **signed-in** (authenticated) scenario reaching a feature surface, author the acceptance so the persona starts from their authenticated home and **reaches the feature through navigation** (clicking a nav door, menu item, or link the UI exposes) — never by asserting against a hardcoded deep-link URL. A scenario that drops the user straight onto `/some/feature/path` proves the page renders but not that the feature is reachable, masking orphaned surfaces with no nav owner. Phrase signed-in acceptance as "from the signed-in home, the persona navigates to … and sees …", not "loading `/feature/path` shows the feature."
|
|
33
|
-
|
|
34
|
-
## Role
|
|
35
|
-
|
|
36
|
-
Senior Project Manager + Orchestrator. The Skill's job is to take the
|
|
37
|
-
sectioned Epic body (whose managed sections carry the folded Tech Spec and
|
|
38
|
-
Acceptance Table — Story #4324) and emit a flat Story backlog the
|
|
39
|
-
orchestrator can execute autonomously.
|
|
40
|
-
|
|
41
|
-
## When to use
|
|
42
|
-
|
|
43
|
-
`/plan` Phase 8, immediately after
|
|
44
|
-
`plan-context.js --epic <Epic_ID>` writes
|
|
45
|
-
`temp/epic-<Epic_ID>/decomposer-context.json`. The Skill replaces the
|
|
46
|
-
inline "Author the Ticket Array" step in the legacy workflow body —
|
|
47
|
-
the caller dispatches this Skill via the `Skill` tool, supplies the Epic
|
|
48
|
-
ID, and on completion has `temp/epic-<Epic_ID>/tickets.json` ready for
|
|
49
|
-
the persist + validate half of the script.
|
|
50
|
-
|
|
51
|
-
## Inputs
|
|
52
|
-
|
|
53
|
-
The dispatcher passes the Epic ID as the Skill argument. The Skill itself
|
|
54
|
-
reads:
|
|
55
|
-
|
|
56
|
-
- `temp/epic-<Epic_ID>/decomposer-context.json` — produced by
|
|
57
|
-
`node .agents/scripts/plan-context.js --epic <Epic_ID>`.
|
|
58
|
-
Fields:
|
|
59
|
-
- `epic.id`, `epic.title`
|
|
60
|
-
- `epicBody` — the sectioned Epic body. It carries everything the
|
|
61
|
-
decomposer needs in one document: the `## User Stories` section
|
|
62
|
-
(User-Story extraction), the folded Tech Spec sections
|
|
63
|
-
(`## Delivery Slicing` onward — module boundary + dependency-DAG
|
|
64
|
-
extraction), and the `## Acceptance Table` AC-ID table. There is no
|
|
65
|
-
separate `techSpec` envelope key (Story #4324).
|
|
66
|
-
- `heuristics[]` — risk heuristics surfaced from
|
|
67
|
-
`agentSettings.planning.riskHeuristics`. Apply each one against the
|
|
68
|
-
Stories you are emitting; flag matches via `risk::high` labels.
|
|
69
|
-
- `maxTickets` — reviewability budget; a framework constant
|
|
70
|
-
(`LIMITS_DEFAULTS.maxTickets` in `.agents/scripts/lib/config/limits.js`,
|
|
71
|
-
not operator-configurable — Story #2798, Story #4163). Default: stay
|
|
72
|
-
under. When the plan genuinely needs more, emit the full plan with
|
|
73
|
-
an `over_budget_rationale` and rely on the operator's
|
|
74
|
-
`--allow-over-budget` override at persist time. The script logs the
|
|
75
|
-
resolved value to stderr.
|
|
76
|
-
- `contextMode` — `"full"` or `"summary"`. When `"summary"`, work
|
|
77
|
-
from the `bodySummary` fields rather than re-fetching the bodies.
|
|
78
|
-
|
|
79
|
-
- `systemPrompt` — the **authoritative, fully-rendered decomposer system
|
|
80
|
-
prompt** (Story #4162). It is produced by `renderDecomposerSystemPrompt`
|
|
81
|
-
in
|
|
82
|
-
[`decomposer-prompts.js`](../../../scripts/lib/templates/decomposer-prompts.js),
|
|
83
|
-
the single source of the prompt body, with `maxTickets`,
|
|
84
|
-
`maxTokenBudget`, and the sizing thresholds already interpolated. Apply
|
|
85
|
-
**this** string as your system prompt — this SKILL deliberately does NOT
|
|
86
|
-
embed a second verbatim copy of the prompt body, so the two surfaces
|
|
87
|
-
cannot drift. The sections below are authoring guidance that complements
|
|
88
|
-
the rendered prompt; they are not a replacement copy of it.
|
|
89
|
-
|
|
90
|
-
## Outputs
|
|
91
|
-
|
|
92
|
-
- `temp/epic-<Epic_ID>/tickets.json` — JSON array of Story
|
|
93
|
-
objects conforming to the schema in this Skill's body.
|
|
94
|
-
|
|
95
|
-
The file MUST exist before the Skill returns. The caller will then run
|
|
96
|
-
`node .agents/scripts/plan-persist.js --epic <Epic_ID> --tickets
|
|
97
|
-
temp/epic-<Epic_ID>/tickets.json`, which validates the array, persists
|
|
98
|
-
the hierarchy as GitHub issues, and transitions the Epic to
|
|
99
|
-
`agent::ready`. The script's validator is the final gate — author for
|
|
100
|
-
its rules, not for "looks right."
|
|
101
|
-
|
|
102
|
-
## Procedure
|
|
103
|
-
|
|
104
|
-
### Step 1 — Load the context
|
|
105
|
-
|
|
106
|
-
Read `temp/epic-<Epic_ID>/decomposer-context.json` with the `Read` tool.
|
|
107
|
-
Pin three values explicitly before writing any tickets:
|
|
108
|
-
|
|
109
|
-
1. `maxTickets` — your reviewability budget. Merge narrow slices into
|
|
110
|
-
capability Stories rather than spilling over the budget; if the plan
|
|
111
|
-
genuinely needs more, emit the full plan with an
|
|
112
|
-
`over_budget_rationale` (Story #2798).
|
|
113
|
-
2. `contextMode` — if `"summary"`, the body strings are bounded; trust
|
|
114
|
-
them, but keep Tasks more conservative because the upstream context
|
|
115
|
-
is partial.
|
|
116
|
-
3. `heuristics[]` — render the active risk heuristics in front of you
|
|
117
|
-
so the planning persona can mention them as Stories are emitted.
|
|
118
|
-
|
|
119
|
-
### Step 2 — Decompose against the rendered system prompt
|
|
120
|
-
|
|
121
|
-
Apply the fully-rendered decomposer system prompt — the `systemPrompt`
|
|
122
|
-
field of the loaded context envelope, produced by
|
|
123
|
-
[`decomposer-prompts.js`](../../../scripts/lib/templates/decomposer-prompts.js)
|
|
124
|
-
— to the sectioned Epic body (`epicBody`). That rendered string is the authoritative
|
|
125
|
-
prompt body (with `maxTickets`, `maxTokenBudget`, and the sizing thresholds
|
|
126
|
-
already interpolated); the authoring-guidance sections below complement it
|
|
127
|
-
without restating it. Emit JSON only (no prose, no Markdown fence). The
|
|
128
|
-
downstream validator in
|
|
129
|
-
[`lib/orchestration/ticket-validator.js`](../../../scripts/lib/orchestration/ticket-validator.js)
|
|
130
|
-
will reject anything off-shape. Merge narrow, single-module slices into
|
|
131
|
-
their capability first; emit one Story per capability slice a frontier
|
|
132
|
-
model can deliver and self-verify in one pass.
|
|
133
|
-
|
|
134
|
-
### Step 3 — Write the file
|
|
135
|
-
|
|
136
|
-
Write the final JSON array to `temp/epic-<Epic_ID>/tickets.json` with
|
|
137
|
-
the `Write` tool. Do not pretty-print past 2-space indent — the file is
|
|
138
|
-
machine-consumed.
|
|
139
|
-
|
|
140
|
-
### Step 4 — Hand back to `/plan`
|
|
141
|
-
|
|
142
|
-
Return control. The caller invokes
|
|
143
|
-
`node .agents/scripts/plan-persist.js --epic <Epic_ID> --tickets
|
|
144
|
-
temp/epic-<Epic_ID>/tickets.json`, which validates, persists, and flips
|
|
145
|
-
the Epic to `agent::ready`.
|
|
146
|
-
|
|
147
|
-
## Decomposer system prompt — single-sourced (Story #4162)
|
|
148
|
-
|
|
149
|
-
The authoritative decomposer system-prompt **body** is single-sourced in
|
|
150
|
-
[`decomposer-prompts.js`](../../../scripts/lib/templates/decomposer-prompts.js)
|
|
151
|
-
(`renderDecomposerSystemPrompt`) and delivered to you fully rendered in the
|
|
152
|
-
`systemPrompt` field of `temp/epic-<Epic_ID>/decomposer-context.json` — with
|
|
153
|
-
`maxTickets`, `maxTokenBudget`, the `DEFAULT_TASK_SIZING` thresholds, and the
|
|
154
|
-
risk heuristics already interpolated. **Apply that rendered string as your
|
|
155
|
-
system prompt.** This SKILL deliberately does **not** embed a second verbatim
|
|
156
|
-
copy of the prompt body (the preamble, the JSON output schema, the hierarchy /
|
|
157
|
-
label / output-format rules); duplicating it here is exactly the drift the
|
|
158
|
-
single-source contract exists to prevent, and the guard test in
|
|
159
|
-
`tests/ticket-decomposer.test.js` fails if a second full copy reappears on
|
|
160
|
-
either surface.
|
|
161
|
-
|
|
162
|
-
The value `${maxTickets}` in the rendered prompt is substituted at runtime
|
|
163
|
-
from the `maxTickets` field of the loaded context. Treat it as the
|
|
164
|
-
**reviewability budget** (Story #2798) — stay under by default; over-budget
|
|
165
|
-
plans need an `over_budget_rationale` plus operator `--allow-over-budget` to
|
|
166
|
-
persist. It is **not** a hard authoring cap: the prompt no longer carries any
|
|
167
|
-
ticket-count limit directive, and you MUST never truncate the JSON array to fit
|
|
168
|
-
(Story #4162). The rendered prompt also names the delivery token
|
|
169
|
-
budget (`maxTokenBudget`) as the real one-pass sizing envelope — size each
|
|
170
|
-
Story so a single agent can deliver and self-verify it within that budget.
|
|
171
|
-
|
|
172
|
-
## Authoring guidance (complements the rendered prompt)
|
|
173
|
-
|
|
174
|
-
The sections below are the SKILL's authoring guidance. They do **not** restate
|
|
175
|
-
the rendered prompt body — they record the contract details and sizing
|
|
176
|
-
heuristics you apply when shaping the ticket array. Where a number appears it
|
|
177
|
-
is the `DEFAULT_TASK_SIZING` default; the rendered prompt interpolates the live
|
|
178
|
-
value, which always wins.
|
|
179
|
-
|
|
180
|
-
### STORY BODY SHAPE (string body, top-level acceptance/verify)
|
|
181
|
-
|
|
182
|
-
For Stories, `body` MUST be a **string** — the serialized markdown produced by
|
|
183
|
-
calling `serialize()` from `lib/story-body/story-body.js`. Do NOT emit `body`
|
|
184
|
-
as a JSON object: `createOp` in `epic-spec-reconciler-ops.js` will throw
|
|
185
|
-
`StoryBodyParseError` when it receives an object body (Story #3302
|
|
186
|
-
serialize-or-throw contract), and `composeStoryBody` in the GitHub provider
|
|
187
|
-
also discards non-string bodies producing an empty issue. The freshness gate
|
|
188
|
-
(`collectTaskChangesPaths`) and the assumption gate
|
|
189
|
-
(`collectStoryAssumptionEntries`) both parse the string body via
|
|
190
|
-
`story-body.js#parse` to recover `changes[]`/`references[]` — they operate
|
|
191
|
-
correctly only on the serialized string form.
|
|
192
|
-
|
|
193
|
-
The `acceptance[]` and `verify[]` arrays live at the **top level** of the
|
|
194
|
-
Story ticket object (not nested inside `body`). The validator's
|
|
195
|
-
`hasInlineAcceptanceAndVerify(story)` reads `story.acceptance` and
|
|
196
|
-
`story.verify` directly — nesting them inside a body object makes them
|
|
197
|
-
invisible to the validator, causing the backlog to be treated as the legacy
|
|
198
|
-
4-tier shape and producing a `Cross-Validation Failed: Backlog must contain at
|
|
199
|
-
least one Task.` error.
|
|
200
|
-
|
|
201
|
-
The serialized `body` string renders these markdown sections in order: `##
|
|
202
|
-
Goal` (one sentence), `## Changes` (object-form `{ "path", "assumption" }`
|
|
203
|
-
bullets), `## Acceptance` (checkbox items), `## Verify` (command + tier), and
|
|
204
|
-
`## References` (read-only `{ "path", "assumption": "exists" }` bullets).
|
|
205
|
-
Fields `wide` and `estimated_test_files` are encoded as a `<!-- meta: {...}
|
|
206
|
-
-->` comment appended to the serialized body string (handled by `serialize()`).
|
|
207
|
-
They are NOT top-level ticket fields.
|
|
208
|
-
|
|
209
|
-
#### STORY BODY RULES
|
|
210
|
-
|
|
211
|
-
- **slug**: MUST be hyphen-case (`^[a-z0-9][a-z0-9-]*$`). Do not use underscores.
|
|
212
|
-
- **goal** (in body string): One sentence stating WHY this Story exists within the Epic.
|
|
213
|
-
- **reason_to_exist** (REQUIRED, encoded in the body `<!-- meta: {...} -->` comment — NOT a top-level ticket field): One sentence stating the single coherent reason this Story exists, distinct from the broader `goal` prose. Every Story MUST carry a non-empty `reason_to_exist`; it is the machine-checkable form of the cohesion rule (**one Story = one coherent change with one reason to exist**). The `epic-plan-consolidate` critic flags any Story whose body carries no non-empty reason, and the sizing validator (`ticket-validator-sizing.js`) emits a deterministic **soft** `missing-reason-to-exist` finding as the runtime backstop. Encode it as `<!-- meta: {"reason_to_exist": "..."} -->`.
|
|
214
|
-
- **changes** (in body string): Each entry is an object `{ path, assumption }` where `assumption` is one of `creates | refactors-existing | deletes`. The Phase 8 validator probes the base branch for every declared path and rejects the decompose when the declared assumption contradicts reality: `creates` against an existing path is an error, `refactors-existing` / `deletes` against a missing path is an error. Use `refactors-existing` for in-place edits to a file already on `main`; `creates` for net-new files; `deletes` for removals. Acceptable path shapes include explicit files (`src/components/Foo.tsx`), glob patterns (`tests/e2e/*.spec.ts`, `**/*.astro`), and module identifiers that resolve to files.
|
|
215
|
-
- **references** (in body string, optional): Object-form entries `{ path, assumption: "exists" }` for paths the Story **reads** but does not modify (test fixtures it relies on, sibling modules it imports, feature files it scans). The validator probes these like `changes` and rejects the decompose when an `exists` path is absent on the base branch. Use this list to make read-dependencies explicit so a hallucinated or stale assumption surfaces at planning time rather than execution time.
|
|
216
|
-
- **NEW-FILE CONTRACT (must-follow)**: Any path the Story references in `goal`, `acceptance`, or `verify` that does **not** already exist on `main` MUST also appear in the same Story's `changes` array with `assumption: "creates"`. The freshness validator probes `main` for every referenced code path and rejects the decompose when a missing path is absent from `changes` — even when the Story is the one authoring the file. Example: a Story creating `tests/lib/foo.test.js` whose `verify` runs `node --test tests/lib/foo.test.js` MUST include `{ "path": "tests/lib/foo.test.js", "assumption": "creates" }` in `changes`, otherwise the validator emits a freshness miss and the decompose round trips for a re-emit.
|
|
217
|
-
- **acceptance** (top-level array on ticket object): Items MUST be observable from outside the agent. Acceptable shapes: a specific command exits 0, a file exists at a given path, a snapshot test matches, a `data-testid` resolves under a given selector, a row count in a fixture matches. UNACCEPTABLE: "verify by reading the diff", "looks good", "matches the spec" — push these down into a `verify` command instead.
|
|
218
|
-
- **verify** (top-level array on ticket object): Each entry MUST name a testing tier in parentheses, drawn from `unit` / `contract` / `e2e` / `validate`. Example: `npm run test -- src/x.test.ts (unit)`, `npm run validate (validate)`. Stories with zero verify entries SHOULD fail validation; if a Story is genuinely unverifiable in isolation (e.g., a copy edit auditor will eyeball), the literal entry `manual:<reason>` is allowed so the absence is intentional, not lazy. Manual entries without a reason are rejected.
|
|
219
|
-
- **estimated_test_files** (optional, encoded in body meta comment): Integer estimate of how many test files this Story creates or modifies. Omit when the number is not estimable. Informational only — it does not gate the decompose.
|
|
220
|
-
|
|
221
|
-
#### FORBIDDEN SUBJECT-PREFIX PRESCRIPTIONS (Conventional-Commits only)
|
|
222
|
-
|
|
223
|
-
- `acceptance` items MUST NOT prescribe a commit subject that begins with a non-Conventional-Commits prefix. The allowed leading types are `feat|fix|chore|refactor|perf|docs|style|test|build|ci|revert` (matching `commitlint.config.js` and `release-please-config.json`). Historic ad-hoc subject prefixes — such as the legacy `baseline-refresh` token used as a leading prefix — are FORBIDDEN as subject prescriptions, because they fail the local `commit-msg` hook and the close-time validator (`ticket-validator.js` → `validateAcceptanceSubjectPrefix`) will reject the decompose with `code: 'forbidden-subject-prefix'`. When a Story needs a baseline-refresh-style classification, prescribe a Conventional-Commits subject (e.g. `chore(baselines): refresh maintainability snapshot`) and, if a machine-readable marker is required, prescribe a body trailer such as `baseline-refresh: true` (note the trailing space and value, not a subject prefix). See Epic #2501 for the rationale.
|
|
224
|
-
|
|
225
|
-
#### STORY SIZING — DELIVERABLE GRANULARITY, COHESION FIRST (the numeric ceiling is only a backstop)
|
|
226
|
-
|
|
227
|
-
**Decompose at deliverable granularity, not module/task level.** A Story is a **capability slice a frontier model delivers and self-verifies in one pass** — a shippable slice a reviewer would accept as a single PR, a capability or user-visible surface, **not a single module or file**. Fold module-level slices into the capability they belong to rather than emitting one Story per module. (This definition is the single source of truth in `DELIVERABLE_GRANULARITY_GUIDANCE` in `ticket-validator-sizing.js`; the rendered decomposer prompt interpolates the same string — do not restate a divergent version here.)
|
|
228
|
-
|
|
229
|
-
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.
|
|
230
|
-
|
|
231
|
-
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.
|
|
232
|
-
|
|
233
|
-
- **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.
|
|
234
|
-
- **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.
|
|
235
|
-
- **Split independent, parallelizable work** into sibling Stories — but only when the pieces genuinely have separate reasons to exist.
|
|
236
|
-
- **Declare `wide` with a one-line reason when a change is legitimately broad** (a cohesive cutover that spans many files for one reason).
|
|
237
|
-
|
|
238
|
-
**Numeric backstop.** The thresholds are defined **once**, in the `DEFAULT_TASK_SIZING` constant in `ticket-validator-sizing.js` (operator-overridable via `agentSettings.planning.taskSizing`). They are a backstop, not the primary rule — do not restate divergent numbers anywhere else. The defaults:
|
|
239
|
-
|
|
240
|
-
- A Story touching more than **`softFiles` (15)** files emits an advisory width finding — a nudge to check cohesion or declare `wide`.
|
|
241
|
-
- A Story touching more than **`hardFiles` (30)** files is **rejected** unless it declares `wide` with a reason.
|
|
242
|
-
- Acceptance mass is **advisory only**: more than **`softAcceptanceCount` (10)** acceptance items emits an advisory warning. There is NO hard acceptance ceiling — a long binding contract is a signal to re-check cohesion, never a reason to fragment one coherent capability into dependent slices.
|
|
243
|
-
|
|
244
|
-
#### DELIVERY-SCHEDULE SIMULATION (the story count must earn itself)
|
|
245
|
-
|
|
246
|
-
Before emitting, simulate the delivery schedule the plan implies and judge the
|
|
247
|
-
plan by its schedule, not by how tidy the taxonomy looks. The canonical rules
|
|
248
|
-
live in the rendered decomposer prompt (`decomposer-prompts.js`) — in brief:
|
|
249
|
-
|
|
250
|
-
1. **Build the wave schedule.** A Story runs only after every `depends_on`
|
|
251
|
-
completes, and two Stories that name the same file in `changes[]` cannot
|
|
252
|
-
run in the same wave (the scheduler serializes file-overlapping Stories
|
|
253
|
-
even when no `depends_on` edge links them).
|
|
254
|
-
2. **Compute the parallelism yield** — story count ÷ critical-path length in
|
|
255
|
-
waves. A yield near 1.0 means the plan is a serial chain: N Stories that
|
|
256
|
-
deliver no faster than one Story while paying N delivery sessions.
|
|
257
|
-
3. **Every Story must earn its slot** by at least one of **(a) parallelism**
|
|
258
|
-
(it runs concurrently with a sibling in the schedule just built — not
|
|
259
|
-
merely "logically independent"), **(b) risk isolation** (it isolates a
|
|
260
|
-
consumer-facing behavior change or high-risk cutover into its own
|
|
261
|
-
reviewable, revertable unit), or **(c) envelope pressure** (merged into its
|
|
262
|
-
neighbor it would exceed the one-pass delivery envelope).
|
|
263
|
-
4. **A dependent link with none of those justifications merges into its
|
|
264
|
-
consumer** — the single-consumer merge rule generalized from pairs to
|
|
265
|
-
chains.
|
|
266
|
-
5. **Hot-file rule.** When one file appears in the `changes[]` of more than a
|
|
267
|
-
third of the Stories, the slicing axis cuts across a shared seam — merge
|
|
268
|
-
the Stories that co-edit it, or re-slice along the seam.
|
|
269
|
-
|
|
270
|
-
End each Story's `reason_to_exist` with its justification letter and one
|
|
271
|
-
clause, e.g. "… (a: runs in wave 1 alongside <slug>)" or "(b: isolates the
|
|
272
|
-
auto-merge default change)". A reason that names only a topic ("config work",
|
|
273
|
-
"docs") with no justification is a merge signal.
|
|
274
|
-
|
|
275
|
-
#### DELIVERY SLICING (consume the Tech Spec target grouping when present)
|
|
276
|
-
|
|
277
|
-
The Epic body's Tech Spec sections may carry a `## Delivery Slicing` section authored by the
|
|
278
|
-
Architect, proposing how the Epic's enumerated capabilities cluster into N
|
|
279
|
-
shippable Stories. When that section is **present**, treat it as the **target
|
|
280
|
-
grouping**: prefer emitting Stories that match the Architect's proposed
|
|
281
|
-
clusters rather than mapping Epic capabilities 1:1. When it is **absent**,
|
|
282
|
-
degrade gracefully — decompose at deliverable granularity using the cohesion
|
|
283
|
-
rules above, exactly as before. The Phase 8 holistic consolidation pass
|
|
284
|
-
(`epic-plan-consolidate`) reconciles your draft against this same Delivery
|
|
285
|
-
Slicing target before persist, so aligning to it here reduces the work the
|
|
286
|
-
consolidation critic has to do.
|
|
287
|
-
|
|
288
|
-
#### `wide` DECLARATION (optional — for legitimately broad changes)
|
|
289
|
-
|
|
290
|
-
A Story whose footprint is legitimately broad declares `wide` carrying a one-line human-readable reason. Encode it in the `<!-- meta: {"wide": {"reason": "..."}} -->` comment that `serialize()` appends to the body string — e.g. `"wide": { "reason": "hard contract cutover: migrate every <X> call site in one PR" }`.
|
|
291
|
-
|
|
292
|
-
Declaring `wide` with a non-empty reason **lifts the `hardFiles` rejection** — no Story is rejected for width when it states why it is broad. Omit `wide` for ordinary Stories; a wide footprint with no `wide` declaration emits only an advisory nudge (check cohesion or declare `wide`), never a rejection on its own. Glob entries in `changes[]` (bullets containing `*`) are `unknown-width`: the numeric ceiling is skipped, and a glob Story with no `wide` declaration emits the same advisory nudge.
|
|
293
|
-
|
|
294
|
-
#### UI / TESTID INVARIANCE (per CLAUDE.md safety rule)
|
|
295
|
-
|
|
296
|
-
- Stories that touch UI (`*.tsx`, `*.astro`, `*.svelte`, `*.vue`, components folders) MUST end `changes` with one of:
|
|
297
|
-
- `data-testid invariance: <list of testids that MUST be preserved>`, or
|
|
298
|
-
- `data-testid changes: <old> -> <new>` paired with a corresponding `tests/e2e/*.spec.ts` edit in the same Story or a depends_on Story.
|
|
299
|
-
- Renaming a testid without the matching e2e edit is FORBIDDEN.
|
|
300
|
-
|
|
301
|
-
#### BRAND / COPY / STYLE WORK
|
|
302
|
-
|
|
303
|
-
- 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.
|
|
304
|
-
|
|
305
|
-
#### BINDING ACCEPTANCE vs ADVISORY CHANGES (authoring altitude)
|
|
306
|
-
|
|
307
|
-
The canonical altitude + New-File Contract wording is single-sourced in `AUTHORING_ALTITUDE_GUIDANCE` in `ticket-validator-sizing.js` (Story #4272); the rendered decomposer prompt interpolates the same strings, so do not restate a divergent version here. The three canonical statements:
|
|
308
|
-
|
|
309
|
-
- **Binding contract vs advisory sketch.** `acceptance[]` and `verify[]` are the Story's **binding contract** — the executor MUST satisfy them exactly, and they are the only definition of "done." `changes[]` and `references[]` are an **advisory implementation sketch**: your best prediction of the file footprint, which the executor MAY revise when the real codebase diverges from the sketch. Author `acceptance[]` / `verify[]` to assert the **outcome** independent of any one file layout — never pin an incidental implementation detail (an internal helper name, a private file path) into an acceptance item that the advisory `changes[]` is free to reshape; assert the observable behaviour instead.
|
|
310
|
-
- **New-File Contract.** Any path named in a Story's `goal`, `acceptance`, or `verify` that does NOT already exist on `main` MUST also appear in that Story's `changes[]` with `assumption: "creates"`; otherwise the freshness validator rejects the decompose — even when the Story is the one authoring the file.
|
|
311
|
-
- **Advisory does not mean unvalidated.** `changes[]` paths still pass the base-branch file-assumption probes (a `creates` against an existing path still fails), the New-File Contract still holds, and the executor's latitude to revise the approach never licenses skipping `acceptance[]` / `verify[]` or relaxing any `rules/security-baseline.md` MUST.
|
|
312
|
-
|
|
313
|
-
#### NAVIGATE-DON'T-DEEP-LINK (signed-in acceptance scenarios)
|
|
314
|
-
|
|
315
|
-
When a Story's acceptance describes a **signed-in / authenticated** persona reaching a feature surface, author it so the persona starts from their authenticated home and **reaches the feature through navigation** — clicking a nav door, menu entry, or link the UI actually exposes — **never** via a hardcoded deep-link URL.
|
|
316
|
-
|
|
317
|
-
- A deep-link scenario (`load /reports/export and assert the export button`) proves the page renders but NOT that it is reachable; it masks an orphaned surface that no navigation door points to.
|
|
318
|
-
- 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"`.
|
|
319
|
-
- 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.
|
|
320
|
-
|
|
321
|
-
### WAVE-0 BDD SCAFFOLD STORY (features-first; emit when the Acceptance Table has `new`-disposition rows)
|
|
322
|
-
|
|
323
|
-
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).
|
|
324
|
-
|
|
325
|
-
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:
|
|
326
|
-
|
|
327
|
-
- **goal** (in body string): contains the literal token `bdd-scaffold`.
|
|
328
|
-
- **depends_on**: EMPTY (`[]`) — the scaffold runs first, in wave 0.
|
|
329
|
-
- **changes** (in body string): one `{ path, assumption: "creates" }` entry per distinct `.feature` file named in a `new` row.
|
|
330
|
-
- **acceptance** (top-level array): MUST assert (a) every new `.feature` file exists, (b) every new scenario within them carries an `@skip` tag, AND (c) every new scenario also carries its **namespaced per-Epic AC tag** `@epic-<id>-ac-N` (one tag per AC ID the scenario satisfies). Keep items observable (a command exits 0; a file exists at a path).
|
|
331
|
-
- **The namespaced AC tag is REQUIRED at scaffold time, not only at de-skip time.** Phase 7 finalize's `acceptance-spec-reconciler.js` matches AC IDs only against `@epic-<id>-ac-*` / `@pending` tags under `tests/features/**` — a bare `@ac-N` tag is deliberately ignored to prevent cross-Epic collision (Story #3362). A scaffolded scenario carrying `@skip` but no `@epic-<id>-ac-N` tag reads as `missing[]` at finalize and throws, aborting close, even after the implementation Story de-skips it — the tag was never added in either pass. Tag each scenario with both `@skip` AND `@epic-<id>-ac-N` (substituting the Epic's real ID and the scenario's own AC number) in this SAME wave-0 commit; do not defer the AC tag to the later de-skip edit.
|
|
332
|
-
- **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.
|
|
333
|
-
- 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).
|
|
334
|
-
|
|
335
|
-
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.
|
|
336
|
-
|
|
337
|
-
> **Read [`examples.md`](./examples.md) on demand** for a fully worked wave-0
|
|
338
|
-
> scaffold Story (Epic #42, two `new` rows) showing the serialized string
|
|
339
|
-
> `body`, the top-level `acceptance`/`verify` arrays, the empty `depends_on`,
|
|
340
|
-
> and the paired `@skip` + `@epic-<id>-ac-N` tagging.
|
|
341
|
-
|
|
342
|
-
### SCOPE-OVERLAP FLAGGING (docs/runbook downstream of config work)
|
|
343
|
-
|
|
344
|
-
When a "docs update" / "runbook" / "README" Story appears downstream of an earlier Story in the same Epic whose AC already covers updating the same document (e.g. a "config + runbook" Story followed by a "docs" Story touching the same runbook), the downstream Story's deliverable may be fully absorbed by the earlier Story. Flag the risk directly in the Story `body.acceptance` by appending an item of the form:
|
|
345
|
-
"Scope verification note: this Story's deliverable may already be satisfied by Story #<slug-or-id>'s AC — before implementing, `git diff main -- <path>` against the upstream Story branch and confirm whether a substantive edit is still required, or whether only a cross-reference remains."
|
|
346
|
-
This prevents the executing agent from redoing work the upstream Story already merged.
|
|
347
|
-
|
|
348
|
-
### CROSS-CUTTING CONFIG FILE EDITS (shared root files across Stories)
|
|
349
|
-
|
|
350
|
-
If two or more Stories in the same decomposition edit any of the shared
|
|
351
|
-
configuration files enumerated below, you MUST either:
|
|
352
|
-
|
|
353
|
-
1. Add explicit `depends_on` links chaining the affected Stories so they
|
|
354
|
-
merge sequentially (preferred when the Stories share thematic scope and
|
|
355
|
-
the second Story's edits build on the first), OR
|
|
356
|
-
2. Split the cross-cutting edits into a single dedicated late-wave "wiring"
|
|
357
|
-
Story that runs after the dependents land (preferred when the dependent
|
|
358
|
-
Stories are otherwise unrelated and would only collide at the wiring
|
|
359
|
-
point).
|
|
360
|
-
|
|
361
|
-
Trade-offs: option (1) keeps each Story end-to-end coherent but serializes
|
|
362
|
-
their delivery; option (2) keeps the dependents parallel but introduces a
|
|
363
|
-
narrow extra Story whose AC is purely integration. Pick (1) when the shared
|
|
364
|
-
file edit is small and thematically owned by one of the Stories; pick (2)
|
|
365
|
-
when several otherwise-independent Stories all need to register themselves
|
|
366
|
-
in the same manifest.
|
|
367
|
-
|
|
368
|
-
Shared configuration files (non-exhaustive):
|
|
369
|
-
|
|
370
|
-
- `.github/workflows/*.yml` — any single workflow file edited by multiple
|
|
371
|
-
Stories
|
|
372
|
-
- `package.json` at the repo root (dependency or script edits)
|
|
373
|
-
- `pnpm-workspace.yaml`, `turbo.json`, `nx.json`, `lerna.json` — monorepo
|
|
374
|
-
manifests
|
|
375
|
-
- `tsconfig.base.json`, `tsconfig.json` at the repo root
|
|
376
|
-
- `.gitignore`, `.npmrc`, `.nvmrc` at the repo root
|
|
377
|
-
- Any single file under a `schemas/` directory if it is the only producer
|
|
378
|
-
of a contract consumed by other Stories — those consumers MUST
|
|
379
|
-
`depends_on` the producer
|
|
380
|
-
- **Registry / barrel files** (Story #2962). Files whose primary purpose
|
|
381
|
-
is to wire siblings together (listener registries, handler maps,
|
|
382
|
-
manifest barrels) collide whenever two concurrent Stories *create new
|
|
383
|
-
files* that the registry must import. The validator recognises this
|
|
384
|
-
class via `planning.crossCuttingRegistries` (extender-shaped). The
|
|
385
|
-
framework default list is:
|
|
386
|
-
- `lib/orchestration/lifecycle/listeners/index.js`
|
|
387
|
-
- `**/listeners/index.js`
|
|
388
|
-
- `**/handlers/index.js`
|
|
389
|
-
|
|
390
|
-
Trigger: two or more concurrent Stories either edit a registry path
|
|
391
|
-
directly **or** declare `assumption: creates` for a file in the
|
|
392
|
-
registry's parent directory. Remediation is the same as the shared
|
|
393
|
-
configuration files above — sequential `depends_on` between the
|
|
394
|
-
Stories, or a dedicated late-wave wiring Story. Consumers extend the
|
|
395
|
-
list per-project via `planning.crossCuttingRegistries` in
|
|
396
|
-
`.agentrc.json` (accepts `["…"]` to replace or `{ append: [...] }` to
|
|
397
|
-
add to the framework default).
|
|
398
|
-
|
|
399
|
-
### WIDELY-USED SYMBOL DELETION (Story #2962)
|
|
400
|
-
|
|
401
|
-
When a Story's `body.changes` declares `{ path, assumption: "deletes" }`,
|
|
402
|
-
the decomposer probes the base branch at plan time via `git grep -l`
|
|
403
|
-
for files that reference the deleted module's basename. When the count
|
|
404
|
-
exceeds `planning.largeFanOutThreshold` (default `10`), the validator
|
|
405
|
-
emits a `fan-out-warning` finding and `epic-plan-decompose` refuses to
|
|
406
|
-
persist unless the operator passes `--allow-large-fan-out`.
|
|
407
|
-
|
|
408
|
-
This gate exists because re-prompting the planner cannot reduce a
|
|
409
|
-
deletion's call-site count — the only safe remediations are to split
|
|
410
|
-
the deletion into a subsystem-by-subsystem migration across multiple
|
|
411
|
-
Stories or to confirm the deletion is intentional and bypass the gate
|
|
412
|
-
with the flag. The threshold is configurable per-project via
|
|
413
|
-
`planning.largeFanOutThreshold` in `.agentrc.json`.
|
|
414
|
-
|
|
415
|
-
Do NOT silently allow two Stories to write the same root configuration
|
|
416
|
-
file in the same wave; parallel dispatch would produce a merge conflict
|
|
417
|
-
on every Story-to-Epic close after the first.
|
|
418
|
-
|
|
419
|
-
CRITICAL: Dependencies should follow execution blockers. Stories attach
|
|
420
|
-
directly to the Epic — never emit a `parent_slug` field. A Story's
|
|
421
|
-
`depends_on` MUST only reference other Stories within the SAME Epic; express
|
|
422
|
-
any logical ordering requirement via Story-level `depends_on`.
|
|
423
|
-
|
|
424
|
-
## Constraints
|
|
425
|
-
|
|
426
|
-
- Do **not** call the GitHub API from this Skill. Persistence is the
|
|
427
|
-
script's job; the Skill is pure JSON authoring.
|
|
428
|
-
- Do **not** write outside `temp/epic-<Epic_ID>/`. Reads may cover the
|
|
429
|
-
Epic body plus any docs the context envelope cites.
|
|
430
|
-
- The decomposer prompt's `${maxTickets}` value is the **reviewability
|
|
431
|
-
budget** (Story #2798). Staying under is the default; exceeding it
|
|
432
|
-
requires both an `over_budget_rationale` in the JSON output and the
|
|
433
|
-
operator's `--allow-over-budget` flag at persist time. Silently
|
|
434
|
-
exceeding the budget — or truncating the plan to fit — is forbidden.
|
|
435
|
-
- If `temp/epic-<Epic_ID>/decomposer-context.json` is missing, fail
|
|
436
|
-
loudly. Instruct the caller to run `--emit-context` first.
|
|
437
|
-
- The validator
|
|
438
|
-
([`lib/orchestration/ticket-validator.js`](../../../scripts/lib/orchestration/ticket-validator.js))
|
|
439
|
-
is the authoritative gate. On rejection, apply the re-emit rule above —
|
|
440
|
-
a targeted edit to the existing `tickets.json` fixing only what was
|
|
441
|
-
rejected — rather than re-authoring the array from scratch.
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# epic-plan-decompose-author — examples & extended rationale
|
|
2
|
-
|
|
3
|
-
Read this file on demand while authoring the ticket array. The SKILL.md carries
|
|
4
|
-
the operating contract (Policy Capsule, Inputs / Outputs, Procedure, the
|
|
5
|
-
authoring guidance that complements the rendered decomposer prompt, and
|
|
6
|
-
Constraints); this file carries the worked WAVE-0 BDD scaffold Story and the
|
|
7
|
-
extended reasoning behind it.
|
|
8
|
-
|
|
9
|
-
## WAVE-0 BDD scaffold Story — worked example
|
|
10
|
-
|
|
11
|
-
The contract lives in SKILL.md under **WAVE-0 BDD SCAFFOLD STORY**: when the
|
|
12
|
-
Epic body's `## Acceptance Table` carries one or more `Disposition: new` rows,
|
|
13
|
-
emit **exactly one** dedicated wave-0 scaffold Story whose sole job is to create
|
|
14
|
-
those `.feature` files with `@skip`-tagged scenarios (each also carrying its
|
|
15
|
-
namespaced `@epic-<id>-ac-N` tag) BEFORE any implementation Story runs.
|
|
16
|
-
|
|
17
|
-
**Worked example.** Epic #42, Acceptance Table with two `new` rows
|
|
18
|
-
(`AC-1` -> `tests/features/billing/invoice.feature`,
|
|
19
|
-
`AC-2` -> `tests/features/billing/refund.feature`). The scaffold Story below
|
|
20
|
-
uses a serialized string `body`, top-level `acceptance`/`verify` arrays, an
|
|
21
|
-
empty `depends_on`, and tags each scenario with both `@skip` and its namespaced
|
|
22
|
-
`@epic-42-ac-N` tag:
|
|
23
|
-
|
|
24
|
-
{
|
|
25
|
-
"slug": "scaffold-billing-feature-files",
|
|
26
|
-
"type": "story",
|
|
27
|
-
"title": "Scaffold @skip-tagged billing feature files",
|
|
28
|
-
"depends_on": [],
|
|
29
|
-
"labels": ["type::story", "persona::qa-engineer"],
|
|
30
|
-
"acceptance": [
|
|
31
|
-
"tests/features/billing/invoice.feature and tests/features/billing/refund.feature both exist on the branch",
|
|
32
|
-
"every Scenario in the two new feature files is preceded by an @skip tag (grep for un-skipped scenarios returns zero matches)",
|
|
33
|
-
"the invoice.feature scenario carries @epic-42-ac-1 and the refund.feature scenario carries @epic-42-ac-2"
|
|
34
|
-
],
|
|
35
|
-
"verify": [
|
|
36
|
-
"test -f tests/features/billing/invoice.feature && test -f tests/features/billing/refund.feature (validate)",
|
|
37
|
-
"test -z \"$(grep -rL '@skip' tests/features/billing/*.feature)\" (validate)",
|
|
38
|
-
"grep -q '@epic-42-ac-1' tests/features/billing/invoice.feature && grep -q '@epic-42-ac-2' tests/features/billing/refund.feature (validate)"
|
|
39
|
-
],
|
|
40
|
-
"body": "## Goal\nbdd-scaffold: create the @skip-tagged, @epic-42-ac-N-tagged feature files the billing-flows implementation Stories verify against, so wave-0 lands them before any implementation Story runs.\n\n## Changes\n- {\"path\": \"tests/features/billing/invoice.feature\", \"assumption\": \"creates\"}\n- {\"path\": \"tests/features/billing/refund.feature\", \"assumption\": \"creates\"}\n\n## Acceptance\n- [ ] tests/features/billing/invoice.feature and tests/features/billing/refund.feature both exist on the branch\n- [ ] every Scenario in the two new feature files is preceded by an @skip tag\n- [ ] the invoice.feature scenario carries @epic-42-ac-1 and the refund.feature scenario carries @epic-42-ac-2\n\n## Verify\n- test -f tests/features/billing/invoice.feature && test -f tests/features/billing/refund.feature (validate)\n- test -z \"$(grep -rL '@skip' tests/features/billing/*.feature)\" (validate)\n- grep -q '@epic-42-ac-1' tests/features/billing/invoice.feature && grep -q '@epic-42-ac-2' tests/features/billing/refund.feature (validate)\n"
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
The implementation Stories that later un-skip and flesh out these scenarios each
|
|
44
|
-
carry `depends_on: ["scaffold-billing-feature-files"]`, placing them in a later
|
|
45
|
-
wave than the scaffold. They MUST NOT add the `@epic-42-ac-N` tag themselves —
|
|
46
|
-
it is already present from the scaffold pass; their job is to remove `@skip`
|
|
47
|
-
once the scenario passes.
|