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,188 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* standalone-feedback-rollup.js — end-of-run feedback rollup for the
|
|
5
|
-
* `/deliver` standalone multi-Story path (Epic #4406 / Story #4416).
|
|
6
|
-
*
|
|
7
|
-
* The standalone delivery path (`helpers/deliver-stories`) drives one or
|
|
8
|
-
* more Epic-free Stories to green, and each per-Story sub-agent appends
|
|
9
|
-
* `friction` records to its **standalone** signals stream at
|
|
10
|
-
* `temp/standalone/stories/story-<sid>/signals.ndjson` (written via
|
|
11
|
-
* `appendSignal({ epicId: null, storyId })`). Before this rollup that
|
|
12
|
-
* tree was write-only — nothing ever read it back. This CLI closes the
|
|
13
|
-
* gap: it scans the standalone streams for the delivered Story set and
|
|
14
|
-
* emits a per-category friction summary that `deliver-stories.md`
|
|
15
|
-
* surfaces in its Phase 3 run summary.
|
|
16
|
-
*
|
|
17
|
-
* Usage:
|
|
18
|
-
* node standalone-feedback-rollup.js --stories <id,...>
|
|
19
|
-
*
|
|
20
|
-
* Contract:
|
|
21
|
-
* - Stream paths resolve **exclusively** through the `temp-paths`
|
|
22
|
-
* helpers via `forEachLine(null, storyId, cb, config)` — the `null`
|
|
23
|
-
* Epic sentinel routes to the standalone tree. No hand-built path
|
|
24
|
-
* strings.
|
|
25
|
-
* - Aggregates `friction` records by their **top-level** `category`
|
|
26
|
-
* (Epic #4406 canonical envelope shape); a record with no category
|
|
27
|
-
* buckets under `Unknown`.
|
|
28
|
-
* - **Never fails a run.** A missing or empty stream degrades to an
|
|
29
|
-
* empty contribution; the CLI always prints a JSON summary and
|
|
30
|
-
* exits 0. Observability MUST NOT take down the delivering flow.
|
|
31
|
-
*
|
|
32
|
-
* Output (stdout, one JSON object):
|
|
33
|
-
* {
|
|
34
|
-
* "kind": "standalone-feedback-rollup",
|
|
35
|
-
* "stories": [<id>, ...],
|
|
36
|
-
* "totalFriction": <int>,
|
|
37
|
-
* "byCategory": { "<category>": <count>, ... },
|
|
38
|
-
* "perStory": { "<id>": { "friction": <int>, "missing": <bool> }, ... }
|
|
39
|
-
* }
|
|
40
|
-
*
|
|
41
|
-
* @see .agents/scripts/lib/observability/signals-writer.js (forEachLine, appendSignal)
|
|
42
|
-
* @see .agents/scripts/lib/config/temp-paths.js (signalsFile — null Epic sentinel)
|
|
43
|
-
* @see .agents/workflows/helpers/deliver-stories.md (Phase 3 summary wiring)
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
import { runAsCli } from './lib/cli-utils.js';
|
|
47
|
-
import { resolveConfig } from './lib/config-resolver.js';
|
|
48
|
-
import { forEachLine } from './lib/observability/signals-writer.js';
|
|
49
|
-
|
|
50
|
-
const FRICTION_KIND = 'friction';
|
|
51
|
-
const UNKNOWN_CATEGORY = 'Unknown';
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Parse `--stories <id,...>` into an ordered, de-duplicated array of
|
|
55
|
-
* positive-integer Story IDs. Accepts a single comma-separated value or
|
|
56
|
-
* repeated `--stories` flags. Non-integer / non-positive tokens are
|
|
57
|
-
* rejected so a typo surfaces as an input error rather than a silently
|
|
58
|
-
* empty rollup.
|
|
59
|
-
*
|
|
60
|
-
* @param {string[]} args
|
|
61
|
-
* @returns {{ stories: number[] }}
|
|
62
|
-
*/
|
|
63
|
-
export function parseArguments(args) {
|
|
64
|
-
const raw = [];
|
|
65
|
-
for (let i = 0; i < args.length; i++) {
|
|
66
|
-
if (args[i] === '--stories') {
|
|
67
|
-
const value = args[++i];
|
|
68
|
-
if (typeof value === 'string') {
|
|
69
|
-
raw.push(...value.split(','));
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const seen = new Set();
|
|
75
|
-
const stories = [];
|
|
76
|
-
for (const token of raw) {
|
|
77
|
-
const trimmed = token.trim();
|
|
78
|
-
if (trimmed.length === 0) continue;
|
|
79
|
-
const id = Number(trimmed);
|
|
80
|
-
if (!Number.isInteger(id) || id <= 0) {
|
|
81
|
-
throw new Error(
|
|
82
|
-
`--stories expects comma-separated positive integers; got ${JSON.stringify(trimmed)}`,
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
if (seen.has(id)) continue;
|
|
86
|
-
seen.add(id);
|
|
87
|
-
stories.push(id);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (stories.length === 0) {
|
|
91
|
-
throw new Error(
|
|
92
|
-
'Usage: node standalone-feedback-rollup.js --stories <id,...>',
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return { stories };
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Read one standalone Story's signals stream and aggregate its `friction`
|
|
101
|
-
* records by top-level `category`, mutating the shared `byCategory` tally.
|
|
102
|
-
*
|
|
103
|
-
* Degrades to a zero contribution on a missing / empty / unreadable
|
|
104
|
-
* stream — `forEachLine` already swallows fs + JSON faults and reports a
|
|
105
|
-
* missing file via `{ missing: true }` rather than throwing.
|
|
106
|
-
*
|
|
107
|
-
* @param {number} storyId
|
|
108
|
-
* @param {Record<string, number>} byCategory Mutated in place.
|
|
109
|
-
* @param {object} config
|
|
110
|
-
* @returns {Promise<{ friction: number, missing: boolean }>}
|
|
111
|
-
*/
|
|
112
|
-
async function rollupStory(storyId, byCategory, config) {
|
|
113
|
-
let friction = 0;
|
|
114
|
-
// `epicId: null` routes forEachLine → signalsFile(null, storyId, config)
|
|
115
|
-
// → the standalone tree. Never a hand-built path string.
|
|
116
|
-
const result = await forEachLine(
|
|
117
|
-
null,
|
|
118
|
-
storyId,
|
|
119
|
-
(record) => {
|
|
120
|
-
if (
|
|
121
|
-
record === null ||
|
|
122
|
-
typeof record !== 'object' ||
|
|
123
|
-
record.kind !== FRICTION_KIND
|
|
124
|
-
) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
const category =
|
|
128
|
-
typeof record.category === 'string' && record.category.length > 0
|
|
129
|
-
? record.category
|
|
130
|
-
: UNKNOWN_CATEGORY;
|
|
131
|
-
byCategory[category] = (byCategory[category] ?? 0) + 1;
|
|
132
|
-
friction += 1;
|
|
133
|
-
},
|
|
134
|
-
config,
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
return { friction, missing: Boolean(result?.missing) };
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Aggregate friction across every named standalone Story stream.
|
|
142
|
-
*
|
|
143
|
-
* @param {number[]} stories
|
|
144
|
-
* @param {object} [config]
|
|
145
|
-
* @returns {Promise<{
|
|
146
|
-
* kind: string,
|
|
147
|
-
* stories: number[],
|
|
148
|
-
* totalFriction: number,
|
|
149
|
-
* byCategory: Record<string, number>,
|
|
150
|
-
* perStory: Record<string, { friction: number, missing: boolean }>,
|
|
151
|
-
* }>}
|
|
152
|
-
*/
|
|
153
|
-
export async function buildRollup(stories, config) {
|
|
154
|
-
const byCategory = {};
|
|
155
|
-
const perStory = {};
|
|
156
|
-
let totalFriction = 0;
|
|
157
|
-
|
|
158
|
-
for (const storyId of stories) {
|
|
159
|
-
const { friction, missing } = await rollupStory(
|
|
160
|
-
storyId,
|
|
161
|
-
byCategory,
|
|
162
|
-
config,
|
|
163
|
-
);
|
|
164
|
-
perStory[storyId] = { friction, missing };
|
|
165
|
-
totalFriction += friction;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return {
|
|
169
|
-
kind: 'standalone-feedback-rollup',
|
|
170
|
-
stories,
|
|
171
|
-
totalFriction,
|
|
172
|
-
byCategory,
|
|
173
|
-
perStory,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export async function main(args = process.argv.slice(2)) {
|
|
178
|
-
const { stories } = parseArguments(args);
|
|
179
|
-
const config = resolveConfig();
|
|
180
|
-
const summary = await buildRollup(stories, config);
|
|
181
|
-
process.stdout.write(`${JSON.stringify(summary, null, 2)}\n`);
|
|
182
|
-
return 0;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
runAsCli(import.meta.url, main, {
|
|
186
|
-
source: 'StandaloneFeedbackRollup',
|
|
187
|
-
propagateExitCode: true,
|
|
188
|
-
});
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/* node:coverage ignore file */
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* story-close.js — Story Execution Closure (CLI shell).
|
|
6
|
-
*
|
|
7
|
-
* Thin pipeline that wires the phase modules under
|
|
8
|
-
* `lib/orchestration/story-close/phases/`. Each phase runs as a discrete
|
|
9
|
-
* step and may short-circuit the pipeline with a `{ status: 'blocked' }`
|
|
10
|
-
* envelope. Pipeline shape:
|
|
11
|
-
*
|
|
12
|
-
* 1. parse + resolveCloseInputs (lib/orchestration/story-close/close-inputs.js)
|
|
13
|
-
* 1.5. already-done no-op guard (inline below) — a Story already at
|
|
14
|
-
* `agent::done` AND closed short-circuits here so no phase below it
|
|
15
|
-
* ever flips the label away from `agent::done` or reopens the issue.
|
|
16
|
-
* 2. preflight (phases/preflight.js)
|
|
17
|
-
* 3. state-flip → closing (inline helper below)
|
|
18
|
-
* 4. capture starting branch (phases/branch-restore.js)
|
|
19
|
-
* 5. acquire per-Epic merge lock + run the locked pipeline
|
|
20
|
-
* (phases/locked-pipeline.js — gates, refresh, close)
|
|
21
|
-
* 6. restore starting branch (finally; phases/branch-restore.js)
|
|
22
|
-
*
|
|
23
|
-
* Usage: `node story-close.js --story <ID> [--epic <ID>]`. Exit codes:
|
|
24
|
-
* 0 ok
|
|
25
|
-
* 1 error
|
|
26
|
-
* 2 prior-state (pass --resume / --restart) OR preflight refused
|
|
27
|
-
*
|
|
28
|
-
* @see .agents/workflows/helpers/deliver-stories.md
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
import { runAsCli } from './lib/cli-utils.js';
|
|
32
|
-
import { tempRootFrom } from './lib/config/temp-paths.js';
|
|
33
|
-
import { Logger } from './lib/Logger.js';
|
|
34
|
-
import { createBus } from './lib/orchestration/lifecycle/bus.js';
|
|
35
|
-
import { createLedgerWriter } from './lib/orchestration/lifecycle/ledger-writer.js';
|
|
36
|
-
import { checkCdOutGuard } from './lib/orchestration/story-close/cd-out-guard.js';
|
|
37
|
-
import { resolveCloseInputs } from './lib/orchestration/story-close/close-inputs.js';
|
|
38
|
-
import { withEpicMergeLock } from './lib/orchestration/story-close/merge-runner.js';
|
|
39
|
-
import {
|
|
40
|
-
captureStartingBranch,
|
|
41
|
-
restoreStartingBranch,
|
|
42
|
-
} from './lib/orchestration/story-close/phases/branch-restore.js';
|
|
43
|
-
import { runStoryCloseLocked } from './lib/orchestration/story-close/phases/locked-pipeline.js';
|
|
44
|
-
import {
|
|
45
|
-
emitPreflightBlockedResult,
|
|
46
|
-
runStoryClosePreflight,
|
|
47
|
-
} from './lib/orchestration/story-close/phases/preflight.js';
|
|
48
|
-
import { describeAutoRefreshOutcome } from './lib/orchestration/story-close/phases/refresh.js';
|
|
49
|
-
import {
|
|
50
|
-
renderCoverageTimeoutFrictionBody,
|
|
51
|
-
renderSpawnTimeoutFrictionBody,
|
|
52
|
-
resolveSpawnTimeoutReason,
|
|
53
|
-
} from './lib/orchestration/story-close/phases/timeout-blocked.js';
|
|
54
|
-
import {
|
|
55
|
-
STATE_LABELS,
|
|
56
|
-
transitionTicketState,
|
|
57
|
-
} from './lib/orchestration/ticketing.js';
|
|
58
|
-
import { PREFLIGHT_REFUSED_EXIT_CODE } from './lib/preflight-runner.js';
|
|
59
|
-
import { notify } from './notify.js';
|
|
60
|
-
|
|
61
|
-
// Re-exports preserved for historical test imports. Each underlying
|
|
62
|
-
// implementation now lives under `phases/`.
|
|
63
|
-
export {
|
|
64
|
-
captureStartingBranch,
|
|
65
|
-
checkCdOutGuard,
|
|
66
|
-
describeAutoRefreshOutcome,
|
|
67
|
-
renderCoverageTimeoutFrictionBody,
|
|
68
|
-
renderSpawnTimeoutFrictionBody,
|
|
69
|
-
resolveSpawnTimeoutReason,
|
|
70
|
-
restoreStartingBranch,
|
|
71
|
-
runStoryClosePreflight,
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const progress = Logger.createProgress('story-close', { stderr: true });
|
|
75
|
-
const progressLog = (tag, msg) => progress(tag, msg);
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Best-effort lifecycle-bus wiring. Story #2241 / Task #2247 — bus emits
|
|
79
|
-
* land in the Epic-scoped NDJSON ledger so a sub-agent's `story.merged` /
|
|
80
|
-
* `story.blocked` records sit alongside the parent runner's `wave.*`.
|
|
81
|
-
* A wiring failure logs and returns `null` — the close result must never
|
|
82
|
-
* depend on lifecycle observability.
|
|
83
|
-
*/
|
|
84
|
-
function wireLifecycleBus({ epicId, config }) {
|
|
85
|
-
try {
|
|
86
|
-
const lifecycleBus = createBus();
|
|
87
|
-
const tempRoot = tempRootFrom(config);
|
|
88
|
-
const ledger = createLedgerWriter({
|
|
89
|
-
epicId: Number(epicId),
|
|
90
|
-
tempRoot,
|
|
91
|
-
});
|
|
92
|
-
ledger.register(lifecycleBus);
|
|
93
|
-
return lifecycleBus;
|
|
94
|
-
} catch (err) {
|
|
95
|
-
Logger.warn?.(
|
|
96
|
-
`[story-close] ⚠️ lifecycle bus init failed (continuing without emits): ${err?.message ?? err}`,
|
|
97
|
-
);
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Phase 3 — flip the Story label to `agent::closing` once preflight has
|
|
104
|
-
* passed and before we acquire the per-Epic merge lock. Best-effort.
|
|
105
|
-
*/
|
|
106
|
-
async function transitionToClosing({ provider, storyId, notifyFn }) {
|
|
107
|
-
try {
|
|
108
|
-
await transitionTicketState(provider, storyId, STATE_LABELS.CLOSING, {
|
|
109
|
-
cascade: false,
|
|
110
|
-
notify: notifyFn,
|
|
111
|
-
});
|
|
112
|
-
progress('STATE', `Story #${storyId} → ${STATE_LABELS.CLOSING}`);
|
|
113
|
-
} catch (err) {
|
|
114
|
-
Logger.warn?.(
|
|
115
|
-
`[story-close] failed to flip Story #${storyId} → ${STATE_LABELS.CLOSING}: ${err?.message ?? err}`,
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** Orchestrate the Story closure. Exported for testing. */
|
|
121
|
-
export async function runStoryClose({
|
|
122
|
-
storyId: storyIdParam,
|
|
123
|
-
epicId: epicIdParam,
|
|
124
|
-
skipDashboard: skipDashboardParam,
|
|
125
|
-
skipValidation: skipValidationParam,
|
|
126
|
-
cwd: cwdParam,
|
|
127
|
-
resume: resumeParam,
|
|
128
|
-
restart: restartParam,
|
|
129
|
-
injectedProvider,
|
|
130
|
-
} = {}) {
|
|
131
|
-
const resolved = await resolveCloseInputs({
|
|
132
|
-
storyIdParam,
|
|
133
|
-
epicIdParam,
|
|
134
|
-
skipDashboardParam,
|
|
135
|
-
skipValidationParam,
|
|
136
|
-
cwdParam,
|
|
137
|
-
resumeParam,
|
|
138
|
-
restartParam,
|
|
139
|
-
injectedProvider,
|
|
140
|
-
});
|
|
141
|
-
const {
|
|
142
|
-
storyId,
|
|
143
|
-
epicId,
|
|
144
|
-
cwd,
|
|
145
|
-
worktreePath,
|
|
146
|
-
skipDashboard,
|
|
147
|
-
skipValidation: skipValidationResolved,
|
|
148
|
-
resumeFlag,
|
|
149
|
-
restartFlag,
|
|
150
|
-
noEvidenceFlag,
|
|
151
|
-
config,
|
|
152
|
-
provider,
|
|
153
|
-
story,
|
|
154
|
-
epicBranch,
|
|
155
|
-
storyBranch,
|
|
156
|
-
} = resolved;
|
|
157
|
-
|
|
158
|
-
// Phase 0 — idempotency guard. A re-run against a Story that is already
|
|
159
|
-
// fully closed must be a safe no-op. Without this guard, Phase 3 below
|
|
160
|
-
// (`transitionToClosing`) unconditionally flips the label to
|
|
161
|
-
// `agent::closing` — and `transitionTicketState`
|
|
162
|
-
// (lib/orchestration/ticketing/transition.js) unconditionally sends
|
|
163
|
-
// `state: 'open'` for any non-`agent::done` target — so re-running close
|
|
164
|
-
// against an already-closed Story reopens the GitHub issue and strips
|
|
165
|
-
// `agent::done` *before* the post-merge pipeline even starts. If the
|
|
166
|
-
// pipeline then throws or a phase silently no-ops (the merge is already
|
|
167
|
-
// fully reaped, so there is nothing left to redo), the Story is left
|
|
168
|
-
// regressed at `agent::closing`/OPEN instead of a safe no-op.
|
|
169
|
-
//
|
|
170
|
-
// The "already fully closed" test mirrors the deepest-level guard in the
|
|
171
|
-
// post-merge `ticketClosurePhase` (post-merge/phases/ticket-closure.js):
|
|
172
|
-
// label `agent::done` AND issue `state === 'closed'`, an AND — never a
|
|
173
|
-
// state-alone check. The `state === 'closed'` disjunct is deliberately
|
|
174
|
-
// excluded per the hard-won reasoning in
|
|
175
|
-
// `lib/single-story/confirm-merge.js`: a Story can arrive here closed at
|
|
176
|
-
// the GitHub layer (a `Closes #<id>` PR footer, or a prior close that set
|
|
177
|
-
// `state: closed` but was killed before the label flip landed) while its
|
|
178
|
-
// label is legitimately still `agent::closing`. Treating that as
|
|
179
|
-
// already-done would skip the very `closing → done` re-assertion the
|
|
180
|
-
// re-run exists to perform, stranding the label. Requiring BOTH signals
|
|
181
|
-
// no-ops only a genuinely finished Story.
|
|
182
|
-
const alreadyDone =
|
|
183
|
-
Array.isArray(story?.labels) &&
|
|
184
|
-
story.labels.includes(STATE_LABELS.DONE) &&
|
|
185
|
-
story?.state === 'closed';
|
|
186
|
-
if (alreadyDone) {
|
|
187
|
-
progress(
|
|
188
|
-
'SKIP',
|
|
189
|
-
`Story #${storyId} is already ${STATE_LABELS.DONE} and closed — no-op re-run.`,
|
|
190
|
-
);
|
|
191
|
-
return {
|
|
192
|
-
success: true,
|
|
193
|
-
result: {
|
|
194
|
-
storyId,
|
|
195
|
-
epicId,
|
|
196
|
-
action: 'noop',
|
|
197
|
-
reason: 'already-done',
|
|
198
|
-
merged: true,
|
|
199
|
-
},
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const notifyFn = (ticketId, payload, opts = {}) =>
|
|
204
|
-
notify(ticketId, payload, { config, provider, ...opts });
|
|
205
|
-
|
|
206
|
-
const bus = wireLifecycleBus({ epicId, config });
|
|
207
|
-
|
|
208
|
-
progress('INIT', `Closing Story #${storyId}...`);
|
|
209
|
-
|
|
210
|
-
// Phase 2 — preflight (exit-code 2 reservation when refused).
|
|
211
|
-
const preflightOutcome = await runStoryClosePreflight({ storyId, cwd });
|
|
212
|
-
if (!preflightOutcome.ok) {
|
|
213
|
-
const blockedResult = await emitPreflightBlockedResult({
|
|
214
|
-
storyId,
|
|
215
|
-
preflight: preflightOutcome,
|
|
216
|
-
progress,
|
|
217
|
-
});
|
|
218
|
-
return {
|
|
219
|
-
success: false,
|
|
220
|
-
result: blockedResult,
|
|
221
|
-
exitCode: PREFLIGHT_REFUSED_EXIT_CODE,
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Phase 3 — flip Story → `agent::closing`.
|
|
226
|
-
await transitionToClosing({ provider, storyId, notifyFn });
|
|
227
|
-
|
|
228
|
-
// Phase 4 — capture the starting branch so the `finally` block can
|
|
229
|
-
// restore it on any throw inside the merge-lock-protected region.
|
|
230
|
-
const startingBranch = captureStartingBranch(cwd);
|
|
231
|
-
if (!startingBranch.ok) {
|
|
232
|
-
Logger.warn?.(
|
|
233
|
-
`[story-close] branch-restore: could not capture starting branch (${startingBranch.reason}); finally-block restore will be skipped.`,
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Phase 5 — acquire per-Epic merge lock for the entire close flow.
|
|
238
|
-
try {
|
|
239
|
-
return await withEpicMergeLock(
|
|
240
|
-
epicId,
|
|
241
|
-
{ repoRoot: cwd, timeoutMs: 60_000, log: progressLog },
|
|
242
|
-
() =>
|
|
243
|
-
runStoryCloseLocked({
|
|
244
|
-
storyId,
|
|
245
|
-
epicId,
|
|
246
|
-
cwd,
|
|
247
|
-
worktreePath,
|
|
248
|
-
skipDashboard,
|
|
249
|
-
skipValidationParam: skipValidationResolved,
|
|
250
|
-
resumeFlag,
|
|
251
|
-
restartFlag,
|
|
252
|
-
noEvidenceFlag,
|
|
253
|
-
config,
|
|
254
|
-
provider,
|
|
255
|
-
story,
|
|
256
|
-
epicBranch,
|
|
257
|
-
storyBranch,
|
|
258
|
-
notifyFn,
|
|
259
|
-
bus,
|
|
260
|
-
progress,
|
|
261
|
-
progressLog,
|
|
262
|
-
}),
|
|
263
|
-
);
|
|
264
|
-
} finally {
|
|
265
|
-
restoreStartingBranch({ cwd, captured: startingBranch });
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
runAsCli(
|
|
270
|
-
import.meta.url,
|
|
271
|
-
async () => {
|
|
272
|
-
const envelope = await runStoryClose();
|
|
273
|
-
if (envelope?.exitCode === PREFLIGHT_REFUSED_EXIT_CODE) {
|
|
274
|
-
process.exit(PREFLIGHT_REFUSED_EXIT_CODE);
|
|
275
|
-
}
|
|
276
|
-
// Story #2840 — a blocked envelope (code-review-critical, etc.) carries
|
|
277
|
-
// its own exit code so the CLI fails non-zero without losing the
|
|
278
|
-
// envelope shape that callers serialise.
|
|
279
|
-
if (Number.isInteger(envelope?.exitCode) && envelope.exitCode !== 0) {
|
|
280
|
-
process.exit(envelope.exitCode);
|
|
281
|
-
}
|
|
282
|
-
return envelope;
|
|
283
|
-
},
|
|
284
|
-
{
|
|
285
|
-
source: 'story-close',
|
|
286
|
-
onError: (err) => {
|
|
287
|
-
// exitCode=2 covers two reservations: dispatchRecovery's
|
|
288
|
-
// prior-state refusal AND Story #1289's preflight refusal.
|
|
289
|
-
if (err?.exitCode === 2) process.exit(2);
|
|
290
|
-
Logger.error(`[phase=fatal] [story-close] ${err.stack || err.message}`);
|
|
291
|
-
process.exit(1);
|
|
292
|
-
},
|
|
293
|
-
},
|
|
294
|
-
);
|