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,198 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* merge-subject.js — assemble the conventional-commit subject used by
|
|
3
|
-
* `runFinalizeMerge` and `runResumeMerge` and auto-truncate it on a
|
|
4
|
-
* word boundary when it would exceed commitlint's `header-max-length`.
|
|
5
|
-
*
|
|
6
|
-
* Story #2466 (Epic #2453) auto-generated a 102-char merge subject that
|
|
7
|
-
* commitlint rejected; `story-close.js`'s merge step silently rolled
|
|
8
|
-
* back to staged-only on each retry. This helper prevents the rejection
|
|
9
|
-
* by shaping the subject pre-commit:
|
|
10
|
-
*
|
|
11
|
-
* - The Conventional-Commits prefix (`<type>(<scope>): ` if scope is
|
|
12
|
-
* provided, otherwise `<type>: `) is preserved verbatim.
|
|
13
|
-
* - The ` (resolves #N)` suffix is preserved verbatim.
|
|
14
|
-
* - The title segment is truncated on a word boundary (whitespace),
|
|
15
|
-
* never mid-word, until the assembled subject's byte length fits
|
|
16
|
-
* within the cap.
|
|
17
|
-
* - On truncation, an operator-facing `Logger.warn` fires once and a
|
|
18
|
-
* `truncated-from: <original>` body trailer is returned so the
|
|
19
|
-
* caller can append it to the commit body.
|
|
20
|
-
*
|
|
21
|
-
* The cap is loaded from commitlint config via `@commitlint/load`,
|
|
22
|
-
* cached per-cwd, and falls back to 100 (the
|
|
23
|
-
* `@commitlint/config-conventional` default) when load fails.
|
|
24
|
-
*
|
|
25
|
-
* Pure (the shape function) + cached async loader. No I/O at shape time.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
import path from 'node:path';
|
|
29
|
-
import { Logger as DefaultLogger } from '../../Logger.js';
|
|
30
|
-
import { resolvesToken } from '../resolves-token.js';
|
|
31
|
-
|
|
32
|
-
const COMMITLINT_DEFAULT_HEADER_MAX_LENGTH = 100;
|
|
33
|
-
const headerCapCache = new Map();
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Load commitlint's `header-max-length` rule value for the given cwd.
|
|
37
|
-
* Caches the resolved cap per absolute cwd so repeated close-path calls
|
|
38
|
-
* inside a single process do not re-read commitlint config.
|
|
39
|
-
*
|
|
40
|
-
* Returns the default (100) when commitlint is not installed, the
|
|
41
|
-
* config is missing, or the rule is absent / disabled.
|
|
42
|
-
*
|
|
43
|
-
* @param {string} cwd
|
|
44
|
-
* @param {{ logger?: { warn?: Function } }} [opts]
|
|
45
|
-
* @returns {Promise<number>}
|
|
46
|
-
*/
|
|
47
|
-
export async function loadHeaderMaxLength(cwd, opts = {}) {
|
|
48
|
-
const logger = opts.logger ?? DefaultLogger;
|
|
49
|
-
const key = path.resolve(cwd);
|
|
50
|
-
if (headerCapCache.has(key)) return headerCapCache.get(key);
|
|
51
|
-
let cap = COMMITLINT_DEFAULT_HEADER_MAX_LENGTH;
|
|
52
|
-
try {
|
|
53
|
-
const mod = await import('@commitlint/load');
|
|
54
|
-
const load = mod.default ?? mod.load ?? mod;
|
|
55
|
-
const loaded = await load({}, { cwd: key });
|
|
56
|
-
const rule = loaded?.rules?.['header-max-length'];
|
|
57
|
-
if (Array.isArray(rule) && rule.length >= 3) {
|
|
58
|
-
const [level, _applicable, value] = rule;
|
|
59
|
-
if (level > 0 && Number.isFinite(value) && value > 0) {
|
|
60
|
-
cap = value;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
} catch (err) {
|
|
64
|
-
logger?.warn?.(
|
|
65
|
-
`[merge-subject] commitlint header-max-length load failed; ` +
|
|
66
|
-
`using default ${COMMITLINT_DEFAULT_HEADER_MAX_LENGTH}: ${err?.message ?? err}`,
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
headerCapCache.set(key, cap);
|
|
70
|
-
return cap;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Test-only: clear the per-cwd cap cache.
|
|
75
|
-
*/
|
|
76
|
-
export function _resetHeaderMaxLengthCache() {
|
|
77
|
-
headerCapCache.clear();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function buildPrefix(type, scope) {
|
|
81
|
-
return scope ? `${type}(${scope}): ` : `${type}: `;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Caps the `truncated-from: <subject>` trailer at `cap` bytes so it
|
|
85
|
-
// satisfies commitlint's `footer-max-line-length` rule. Without this
|
|
86
|
-
// cap, an original subject near the header cap (100) produces a
|
|
87
|
-
// ~116-char trailer line.
|
|
88
|
-
function buildTruncatedFromTrailer(originalSubject, cap) {
|
|
89
|
-
const prefix = 'truncated-from: ';
|
|
90
|
-
const budget = Math.max(0, cap - Buffer.byteLength(prefix, 'utf8'));
|
|
91
|
-
if (Buffer.byteLength(originalSubject, 'utf8') <= budget) {
|
|
92
|
-
return `${prefix}${originalSubject}`;
|
|
93
|
-
}
|
|
94
|
-
const ellipsisBytes = Buffer.byteLength('…', 'utf8');
|
|
95
|
-
let value = originalSubject;
|
|
96
|
-
while (Buffer.byteLength(value, 'utf8') + ellipsisBytes > budget) {
|
|
97
|
-
value = value.slice(0, -1);
|
|
98
|
-
}
|
|
99
|
-
return `${prefix}${value}…`;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function truncateTitleOnWordBoundary(title, budget) {
|
|
103
|
-
if (budget <= 0) return '';
|
|
104
|
-
if (Buffer.byteLength(title, 'utf8') <= budget) return title;
|
|
105
|
-
// Greedy: drop trailing tokens until the title fits the byte budget.
|
|
106
|
-
let truncated = title;
|
|
107
|
-
while (Buffer.byteLength(truncated, 'utf8') > budget) {
|
|
108
|
-
const lastWs = truncated.search(/\s+\S*$/u);
|
|
109
|
-
if (lastWs <= 0) {
|
|
110
|
-
// No earlier whitespace — fall back to byte-safe slice.
|
|
111
|
-
truncated = truncated.slice(0, Math.max(0, truncated.length - 1));
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
truncated = truncated.slice(0, lastWs);
|
|
115
|
-
}
|
|
116
|
-
return truncated.replace(/\s+$/u, '');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Shape a Conventional-Commits subject so it fits within `headerMaxLength`.
|
|
121
|
-
*
|
|
122
|
-
* Returns `{ subject, original, truncated, bodyTrailer }`:
|
|
123
|
-
* - `subject` — the (possibly truncated) one-line subject.
|
|
124
|
-
* - `original` — the un-truncated subject (always populated).
|
|
125
|
-
* - `truncated` — boolean, true iff truncation fired.
|
|
126
|
-
* - `bodyTrailer` — `truncated-from: <original>` when truncated, else null.
|
|
127
|
-
*
|
|
128
|
-
* Side effects: on truncation, emits a single `Logger.warn` line naming
|
|
129
|
-
* the original and truncated subjects.
|
|
130
|
-
*
|
|
131
|
-
* @param {{
|
|
132
|
-
* type: string,
|
|
133
|
-
* scope?: string|null,
|
|
134
|
-
* title: string,
|
|
135
|
-
* storyId: number|string,
|
|
136
|
-
* headerMaxLength?: number,
|
|
137
|
-
* logger?: { warn?: Function },
|
|
138
|
-
* }} args
|
|
139
|
-
* @returns {{ subject: string, original: string, truncated: boolean, bodyTrailer: string|null }}
|
|
140
|
-
*/
|
|
141
|
-
export function shapeMergeSubject({
|
|
142
|
-
type,
|
|
143
|
-
scope = null,
|
|
144
|
-
title,
|
|
145
|
-
storyId,
|
|
146
|
-
headerMaxLength = COMMITLINT_DEFAULT_HEADER_MAX_LENGTH,
|
|
147
|
-
logger = DefaultLogger,
|
|
148
|
-
}) {
|
|
149
|
-
const lcTitle = title.charAt(0).toLowerCase() + title.slice(1);
|
|
150
|
-
const prefix = buildPrefix(type, scope);
|
|
151
|
-
const suffix = resolvesToken(storyId);
|
|
152
|
-
const originalSubject = `${prefix}${lcTitle}${suffix}`;
|
|
153
|
-
if (Buffer.byteLength(originalSubject, 'utf8') <= headerMaxLength) {
|
|
154
|
-
return {
|
|
155
|
-
subject: originalSubject,
|
|
156
|
-
original: originalSubject,
|
|
157
|
-
truncated: false,
|
|
158
|
-
bodyTrailer: null,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
const fixedBytes =
|
|
162
|
-
Buffer.byteLength(prefix, 'utf8') + Buffer.byteLength(suffix, 'utf8');
|
|
163
|
-
const titleBudget = headerMaxLength - fixedBytes;
|
|
164
|
-
const truncatedTitle = truncateTitleOnWordBoundary(lcTitle, titleBudget);
|
|
165
|
-
const subject = `${prefix}${truncatedTitle}${suffix}`;
|
|
166
|
-
logger?.warn?.(
|
|
167
|
-
`[merge-subject] subject exceeded commitlint cap (${headerMaxLength}); ` +
|
|
168
|
-
`truncated on word boundary. original="${originalSubject}" ` +
|
|
169
|
-
`truncated="${subject}"`,
|
|
170
|
-
);
|
|
171
|
-
return {
|
|
172
|
-
subject,
|
|
173
|
-
original: originalSubject,
|
|
174
|
-
truncated: true,
|
|
175
|
-
bodyTrailer: buildTruncatedFromTrailer(originalSubject, headerMaxLength),
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Convenience: shape a subject and assemble the final commit message
|
|
181
|
-
* (subject plus optional trailer block). Returns a single string suitable
|
|
182
|
-
* for passing as the `-m` argument to `git commit` / `git merge`.
|
|
183
|
-
*
|
|
184
|
-
* @param {Parameters<typeof shapeMergeSubject>[0]} args
|
|
185
|
-
* @returns {{ message: string, subject: string, original: string, truncated: boolean }}
|
|
186
|
-
*/
|
|
187
|
-
export function buildMergeMessageWithCap(args) {
|
|
188
|
-
const shaped = shapeMergeSubject(args);
|
|
189
|
-
const message = shaped.bodyTrailer
|
|
190
|
-
? `${shaped.subject}\n\n${shaped.bodyTrailer}`
|
|
191
|
-
: shaped.subject;
|
|
192
|
-
return {
|
|
193
|
-
message,
|
|
194
|
-
subject: shaped.subject,
|
|
195
|
-
original: shaped.original,
|
|
196
|
-
truncated: shaped.truncated,
|
|
197
|
-
};
|
|
198
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* phases/branch-restore.js — capture + restore the main-repo's starting
|
|
3
|
-
* branch around the merge-lock-protected close (Story #2138 / #2141; moved
|
|
4
|
-
* into the phases pipeline by Story #2460, Epic #2453).
|
|
5
|
-
*
|
|
6
|
-
* The orchestrator captures the starting branch BEFORE entering the
|
|
7
|
-
* merge lock and runs `restoreStartingBranch` in a `finally` block, so
|
|
8
|
-
* any throw inside `runStoryCloseLocked` leaves the operator on the
|
|
9
|
-
* branch they came in on rather than stranded mid-rebase / mid-merge.
|
|
10
|
-
*
|
|
11
|
-
* Public surface:
|
|
12
|
-
* - captureStartingBranch(cwd, deps?) ← exported (story-close.js re-export)
|
|
13
|
-
* - restoreStartingBranch(opts, deps?) ← exported (story-close.js re-export)
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { gitSpawn as defaultGitSpawn } from '../../../git-utils.js';
|
|
17
|
-
import { Logger } from '../../../Logger.js';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Capture the main-repo's current branch name before `runStoryCloseLocked`
|
|
21
|
-
* runs. Returns `{ ok: true, branch }` on success, `{ ok: false, reason }`
|
|
22
|
-
* when HEAD is detached or `git rev-parse` fails.
|
|
23
|
-
*
|
|
24
|
-
* @param {string} cwd
|
|
25
|
-
* @param {{ gitSpawn?: typeof defaultGitSpawn }} [deps]
|
|
26
|
-
* @returns {{ ok: true, branch: string } | { ok: false, reason: string }}
|
|
27
|
-
*/
|
|
28
|
-
export function captureStartingBranch(cwd, deps = {}) {
|
|
29
|
-
const gitSpawn = deps.gitSpawn ?? defaultGitSpawn;
|
|
30
|
-
const res = gitSpawn(cwd, 'rev-parse', '--abbrev-ref', 'HEAD');
|
|
31
|
-
if (res.status !== 0) {
|
|
32
|
-
return {
|
|
33
|
-
ok: false,
|
|
34
|
-
reason: `rev-parse-failed: ${res.stderr || 'unknown'}`,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
const branch = (res.stdout || '').trim();
|
|
38
|
-
if (!branch || branch === 'HEAD') {
|
|
39
|
-
return { ok: false, reason: 'detached-head' };
|
|
40
|
-
}
|
|
41
|
-
return { ok: true, branch };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Restore the main-repo to `startingBranch` via `git switch`. Refuses the
|
|
46
|
-
* switch when the destination tree is dirty (`git status --porcelain` is
|
|
47
|
-
* non-empty). Never invokes `git reset --hard` or `git checkout --force`.
|
|
48
|
-
*
|
|
49
|
-
* Returns a structured envelope so callers (and tests) can assert which
|
|
50
|
-
* branch they end up on and why.
|
|
51
|
-
*
|
|
52
|
-
* @param {object} opts
|
|
53
|
-
* @param {string} opts.cwd
|
|
54
|
-
* @param {{ ok: boolean, branch?: string, reason?: string }} opts.captured
|
|
55
|
-
* @param {{ gitSpawn?: typeof defaultGitSpawn, logger?: object }} [deps]
|
|
56
|
-
* @returns {{ restored: boolean, branch?: string, reason?: string, skipped?: boolean }}
|
|
57
|
-
*/
|
|
58
|
-
export function restoreStartingBranch({ cwd, captured }, deps = {}) {
|
|
59
|
-
const gitSpawn = deps.gitSpawn ?? defaultGitSpawn;
|
|
60
|
-
const log = deps.logger ?? Logger;
|
|
61
|
-
if (!captured || captured.ok !== true) {
|
|
62
|
-
return {
|
|
63
|
-
restored: false,
|
|
64
|
-
skipped: true,
|
|
65
|
-
reason: captured?.reason
|
|
66
|
-
? `no-starting-branch: ${captured.reason}`
|
|
67
|
-
: 'no-starting-branch',
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
const { branch } = captured;
|
|
71
|
-
const currentRes = gitSpawn(cwd, 'rev-parse', '--abbrev-ref', 'HEAD');
|
|
72
|
-
if (currentRes.status === 0 && currentRes.stdout.trim() === branch) {
|
|
73
|
-
return { restored: true, branch, reason: 'already-on-branch' };
|
|
74
|
-
}
|
|
75
|
-
const statusRes = gitSpawn(cwd, 'status', '--porcelain');
|
|
76
|
-
if (statusRes.status !== 0) {
|
|
77
|
-
log.warn?.(
|
|
78
|
-
`[story-close] branch-restore: \`git status --porcelain\` failed in ${cwd}: ${statusRes.stderr || 'unknown'}`,
|
|
79
|
-
);
|
|
80
|
-
return {
|
|
81
|
-
restored: false,
|
|
82
|
-
branch,
|
|
83
|
-
reason: `status-failed: ${statusRes.stderr || 'unknown'}`,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
if (statusRes.stdout.length > 0) {
|
|
87
|
-
log.error?.(
|
|
88
|
-
`[story-close] branch-restore: refusing to switch to \`${branch}\` — working tree is dirty in ${cwd}. ` +
|
|
89
|
-
`Resolve the local changes manually, then \`git switch ${branch}\`.`,
|
|
90
|
-
);
|
|
91
|
-
return { restored: false, branch, reason: 'dirty-tree' };
|
|
92
|
-
}
|
|
93
|
-
const switchRes = gitSpawn(cwd, 'switch', branch);
|
|
94
|
-
if (switchRes.status !== 0) {
|
|
95
|
-
log.warn?.(
|
|
96
|
-
`[story-close] branch-restore: \`git switch ${branch}\` failed: ${switchRes.stderr || 'unknown'}`,
|
|
97
|
-
);
|
|
98
|
-
return {
|
|
99
|
-
restored: false,
|
|
100
|
-
branch,
|
|
101
|
-
reason: `switch-failed: ${switchRes.stderr || 'unknown'}`,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
return { restored: true, branch };
|
|
105
|
-
}
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* phases/close.js — merge + post-merge pipeline phase (Story #2460,
|
|
3
|
-
* Epic #2453 — CLI thinning pilot).
|
|
4
|
-
*
|
|
5
|
-
* Runs once the pre-merge gates have passed (or been skipped on a
|
|
6
|
-
* resume path). Owns:
|
|
7
|
-
* - the resume-aware merge runner dispatch (`runResumeMerge` vs
|
|
8
|
-
* `runFinalizeMerge`, skipped entirely on a `resumeFromPostMerge` path),
|
|
9
|
-
* - the post-merge close pipeline (ticket transitions, cascade, health,
|
|
10
|
-
* dashboard regen) via `runPostMergeClose`,
|
|
11
|
-
* - the success-path close-result envelope serialisation.
|
|
12
|
-
*
|
|
13
|
-
* Public surface:
|
|
14
|
-
* - runMergePhase(ctx)
|
|
15
|
-
* - runPostMergePhase(ctx)
|
|
16
|
-
* - runClosePhase(ctx) ← composite (merge → post-merge)
|
|
17
|
-
*
|
|
18
|
-
* The split between `runMergePhase` and `runPostMergePhase` keeps each
|
|
19
|
-
* function at one level of abstraction (and well under the < 200 LOC /
|
|
20
|
-
* CC < 12 phase-file budget).
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { Logger } from '../../../Logger.js';
|
|
24
|
-
import { PROJECT_ROOT } from '../../../project-root.js';
|
|
25
|
-
import { STATE_LABELS } from '../../ticketing.js';
|
|
26
|
-
import { runFinalizeMerge, runResumeMerge } from '../merge-runner.js';
|
|
27
|
-
import { runPostMergeClose } from '../post-merge-close.js';
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Story #2961 — final assertion that the Story ticket reached
|
|
31
|
-
* `agent::done` after the post-merge cascade. The cascade is the single
|
|
32
|
-
* writer of the `closing → done` label flip; without this readback,
|
|
33
|
-
* `runStoryClose` returns `success: true` even when the flip silently
|
|
34
|
-
* failed (the failure mode that Epic #2880 wave 0's friction note
|
|
35
|
-
* F-W0-2 surfaced via the runner's GitHub probe — see Story #2894).
|
|
36
|
-
*
|
|
37
|
-
* Outcomes:
|
|
38
|
-
* - `{ ok: true }` — ticket has `agent::done` (or is closed).
|
|
39
|
-
* - `{ ok: false, actualLabels }` — cascade returned but the label
|
|
40
|
-
* never reached `agent::done`. The caller must downgrade
|
|
41
|
-
* `success: true` → `success: false`.
|
|
42
|
-
* - `{ ok: 'skipped', warning }` — `provider.getTicket` threw. The
|
|
43
|
-
* verification could not run, but the close itself succeeded, so
|
|
44
|
-
* the caller returns the success envelope with a `warnings[]` entry.
|
|
45
|
-
*/
|
|
46
|
-
export async function verifyFinalStoryLabel({ provider, storyId }) {
|
|
47
|
-
if (!provider || typeof provider.getTicket !== 'function') {
|
|
48
|
-
return {
|
|
49
|
-
ok: 'skipped',
|
|
50
|
-
warning: `label-verification-skipped: provider.getTicket unavailable`,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
let ticket;
|
|
54
|
-
try {
|
|
55
|
-
ticket = await provider.getTicket(storyId, { fresh: true });
|
|
56
|
-
} catch (err) {
|
|
57
|
-
return {
|
|
58
|
-
ok: 'skipped',
|
|
59
|
-
warning: `label-verification-skipped: ${err?.message ?? err}`,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
const labels = Array.isArray(ticket?.labels) ? ticket.labels : [];
|
|
63
|
-
if (labels.includes(STATE_LABELS.DONE) || ticket?.state === 'closed') {
|
|
64
|
-
return { ok: true };
|
|
65
|
-
}
|
|
66
|
-
return { ok: false, actualLabels: labels };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Run the merge step. Skipped entirely on the already-merged resume path
|
|
71
|
-
* — the merge already landed on `origin/epic/<id>` during the prior close
|
|
72
|
-
* attempt; the only remaining work is the post-merge pipeline.
|
|
73
|
-
*/
|
|
74
|
-
export async function runMergePhase(ctx) {
|
|
75
|
-
const {
|
|
76
|
-
resumeFromConflict,
|
|
77
|
-
resumeFromPostMerge,
|
|
78
|
-
cwd,
|
|
79
|
-
epicBranch,
|
|
80
|
-
storyBranch,
|
|
81
|
-
story,
|
|
82
|
-
storyId,
|
|
83
|
-
epicId,
|
|
84
|
-
config,
|
|
85
|
-
bus,
|
|
86
|
-
progress,
|
|
87
|
-
progressLog,
|
|
88
|
-
} = ctx;
|
|
89
|
-
|
|
90
|
-
if (resumeFromPostMerge) {
|
|
91
|
-
progress(
|
|
92
|
-
'MERGE',
|
|
93
|
-
`Skipping rebase + merge — story tip already reachable from ${epicBranch}`,
|
|
94
|
-
);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const mergeArgs = {
|
|
99
|
-
cwd,
|
|
100
|
-
epicBranch,
|
|
101
|
-
storyBranch,
|
|
102
|
-
storyTitle: story.title,
|
|
103
|
-
storyId,
|
|
104
|
-
epicId,
|
|
105
|
-
config,
|
|
106
|
-
bus,
|
|
107
|
-
log: progressLog,
|
|
108
|
-
};
|
|
109
|
-
await (resumeFromConflict ? runResumeMerge : runFinalizeMerge)(mergeArgs);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Run the post-merge close pipeline — ticket transitions, cascade, health
|
|
114
|
-
* regen, dashboard regen. Returns the final close-result envelope.
|
|
115
|
-
*/
|
|
116
|
-
export async function runPostMergePhase(ctx) {
|
|
117
|
-
const {
|
|
118
|
-
config,
|
|
119
|
-
storyId,
|
|
120
|
-
epicId,
|
|
121
|
-
story,
|
|
122
|
-
storyBranch,
|
|
123
|
-
epicBranch,
|
|
124
|
-
cwd,
|
|
125
|
-
provider,
|
|
126
|
-
notifyFn,
|
|
127
|
-
tasks,
|
|
128
|
-
skipDashboard,
|
|
129
|
-
progress,
|
|
130
|
-
phaseTimer,
|
|
131
|
-
clearPhaseTimerState,
|
|
132
|
-
bus,
|
|
133
|
-
} = ctx;
|
|
134
|
-
|
|
135
|
-
return runPostMergeClose({
|
|
136
|
-
config,
|
|
137
|
-
storyId,
|
|
138
|
-
epicId,
|
|
139
|
-
story,
|
|
140
|
-
storyBranch,
|
|
141
|
-
epicBranch,
|
|
142
|
-
cwd,
|
|
143
|
-
projectRoot: PROJECT_ROOT,
|
|
144
|
-
provider,
|
|
145
|
-
notify: notifyFn,
|
|
146
|
-
tasks,
|
|
147
|
-
skipDashboard,
|
|
148
|
-
progress,
|
|
149
|
-
logger: Logger,
|
|
150
|
-
phaseTimer,
|
|
151
|
-
clearPhaseTimerState,
|
|
152
|
-
bus,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Pure envelope builder. Given the post-merge `result` and the
|
|
158
|
-
* `verifyFinalStoryLabel` verdict, returns the close-result envelope
|
|
159
|
-
* `runClosePhase` will surface back to `runStoryClose`. Exported so the
|
|
160
|
-
* contract test can drive the failure / skipped / success branches
|
|
161
|
-
* without spinning up the merge + cascade pipeline.
|
|
162
|
-
*/
|
|
163
|
-
export function buildCloseEnvelope({ result, verdict, storyId }) {
|
|
164
|
-
if (verdict.ok === false) {
|
|
165
|
-
const failedResult = {
|
|
166
|
-
...result,
|
|
167
|
-
status: 'failed',
|
|
168
|
-
phase: 'closing',
|
|
169
|
-
reason: 'label-transition-failed',
|
|
170
|
-
actualLabels: verdict.actualLabels,
|
|
171
|
-
};
|
|
172
|
-
Logger.warn?.(
|
|
173
|
-
`[story-close] ❌ Story #${storyId} cascade returned but label is not ` +
|
|
174
|
-
`${STATE_LABELS.DONE} (actual: ${JSON.stringify(verdict.actualLabels)}). ` +
|
|
175
|
-
`Returning failure envelope.`,
|
|
176
|
-
);
|
|
177
|
-
return { success: false, result: failedResult };
|
|
178
|
-
}
|
|
179
|
-
if (verdict.ok === 'skipped') {
|
|
180
|
-
return {
|
|
181
|
-
success: true,
|
|
182
|
-
result: { ...result, warnings: [verdict.warning] },
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
return { success: true, result };
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Composite phase: merge → post-merge close → final-label readback →
|
|
190
|
-
* envelope serialise. The caller (`runStoryCloseLocked` in
|
|
191
|
-
* story-close.js) marks the `close` phase on its phase timer before
|
|
192
|
-
* calling in.
|
|
193
|
-
*/
|
|
194
|
-
export async function runClosePhase(ctx) {
|
|
195
|
-
await runMergePhase(ctx);
|
|
196
|
-
const result = await runPostMergePhase(ctx);
|
|
197
|
-
|
|
198
|
-
// Story #2961 — final readback before declaring success. The
|
|
199
|
-
// post-merge cascade is the single writer for the `closing → done`
|
|
200
|
-
// label flip; if it silently failed, surface a failure envelope here
|
|
201
|
-
// rather than relying on the runner's downstream GitHub probe.
|
|
202
|
-
const verdict = await verifyFinalStoryLabel({
|
|
203
|
-
provider: ctx.provider,
|
|
204
|
-
storyId: ctx.storyId,
|
|
205
|
-
});
|
|
206
|
-
const envelope = buildCloseEnvelope({
|
|
207
|
-
result,
|
|
208
|
-
verdict,
|
|
209
|
-
storyId: ctx.storyId,
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
Logger.info(
|
|
213
|
-
`\n--- STORY CLOSE RESULT ---\n${JSON.stringify(envelope.result, null, 2)}\n--- END RESULT ---\n`,
|
|
214
|
-
);
|
|
215
|
-
if (envelope.success) {
|
|
216
|
-
ctx.progress(
|
|
217
|
-
'DONE',
|
|
218
|
-
`✅ Story #${ctx.storyId} merged into ${ctx.epicBranch}. ${envelope.result.ticketsClosed.length} ticket(s) closed.`,
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
return envelope;
|
|
222
|
-
}
|