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,292 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* phases/gates.js — pre-merge gates phase (Story #2460, Epic #2453 —
|
|
3
|
-
* CLI thinning pilot).
|
|
4
|
-
*
|
|
5
|
-
* Runs the close-validation chain (format-autofix → attribution-aware
|
|
6
|
-
* baseline gates → maintainability projection) against the Story
|
|
7
|
-
* worktree before the merge. Outcomes:
|
|
8
|
-
*
|
|
9
|
-
* - `{ status: 'ok' }` — gates passed; caller continues.
|
|
10
|
-
* - `{ status: 'blocked' }` — baseline drift not attributable
|
|
11
|
-
* to the Story; caller emits `emitBaselineBlockedResult`.
|
|
12
|
-
* - `{ status: 'blocked-timeout' }` — one of the bounded-timeout
|
|
13
|
-
* spawns tripped its watchdog; caller routes through
|
|
14
|
-
* `emitSpawnTimeoutBlockedResult`.
|
|
15
|
-
*
|
|
16
|
-
* Story #2995 split the pre-merge body into a pure summarizer
|
|
17
|
-
* (`summarizeGateResults`) plus a side-effecting emitter
|
|
18
|
-
* (`emitGateOutcome`). `runPreMergeValidation` is now a thin sequencer:
|
|
19
|
-
* it runs the format-autofix and attribution gate side effects, hands
|
|
20
|
-
* the raw outcomes to the summarizer, and then routes through the
|
|
21
|
-
* emitter. Output is byte-identical to the pre-refactor function.
|
|
22
|
-
*
|
|
23
|
-
* Public surface:
|
|
24
|
-
* - shouldSkipValidation(input)
|
|
25
|
-
* - summarizeGateResults(results)
|
|
26
|
-
* - emitGateOutcome(summary, ctx)
|
|
27
|
-
* - runPreMergeValidation(input)
|
|
28
|
-
* - emitBaselineBlockedResult(input)
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
import { Logger } from '../../../Logger.js';
|
|
32
|
-
import { runPreMergeGatesWithAttribution } from '../baseline-attribution-wiring.js';
|
|
33
|
-
import { runFormatAutofix, runScopedFormatAutofix } from '../format-autofix.js';
|
|
34
|
-
import { emitBlockedCloseResult } from '../merge-runner.js';
|
|
35
|
-
import { emitMaintainabilityProjection } from '../pre-merge-validation.js';
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Format the `{ status: 'blocked' }` result returned by
|
|
39
|
-
* `runPreMergeGatesWithAttribution` into the canonical close-result
|
|
40
|
-
* envelope + console marker (Story #1124 — non-attributable baseline
|
|
41
|
-
* drift).
|
|
42
|
-
*/
|
|
43
|
-
export async function emitBaselineBlockedResult({
|
|
44
|
-
storyId,
|
|
45
|
-
gateOutcome,
|
|
46
|
-
progress: log,
|
|
47
|
-
bus = null,
|
|
48
|
-
}) {
|
|
49
|
-
const nonAttributable = gateOutcome.nonAttributable ?? [];
|
|
50
|
-
return emitBlockedCloseResult({
|
|
51
|
-
storyId,
|
|
52
|
-
phase: 'closing',
|
|
53
|
-
reason: 'baseline-drift-not-attributable',
|
|
54
|
-
extra: {
|
|
55
|
-
nonAttributable,
|
|
56
|
-
commentId: gateOutcome.commentId ?? null,
|
|
57
|
-
},
|
|
58
|
-
bus,
|
|
59
|
-
progress: log,
|
|
60
|
-
blockedMessage: `Story #${storyId} blocked: baseline drift on ${nonAttributable.length} path(s) not attributable to this Story.`,
|
|
61
|
-
logger: Logger,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Compute whether the pre-merge gate chain should be skipped on this
|
|
67
|
-
* close. Resume-from-anywhere paths skip; an explicit `--skip-validation`
|
|
68
|
-
* also skips.
|
|
69
|
-
*/
|
|
70
|
-
export function shouldSkipValidation({
|
|
71
|
-
skipValidationParam,
|
|
72
|
-
resumeFromConflict,
|
|
73
|
-
resumeFromMerge,
|
|
74
|
-
resumeFromPostMerge,
|
|
75
|
-
}) {
|
|
76
|
-
return (
|
|
77
|
-
!!skipValidationParam ||
|
|
78
|
-
resumeFromConflict ||
|
|
79
|
-
resumeFromMerge ||
|
|
80
|
-
resumeFromPostMerge
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Pure aggregator over the raw outcomes produced by the close-validation
|
|
86
|
-
* side effects (Story #2995 split). Consumes the format-autofix outcome
|
|
87
|
-
* and the attribution-aware gate outcome, then classifies the combined
|
|
88
|
-
* result into a verdict + blocker/advisory lists.
|
|
89
|
-
*
|
|
90
|
-
* Verdicts:
|
|
91
|
-
* - `'blocked-timeout'` — format-autofix spawn watchdog tripped, or the
|
|
92
|
-
* attribution gate chain itself returned `blocked-timeout`. The
|
|
93
|
-
* originating outcome is carried on the blocker entry so the emitter
|
|
94
|
-
* can return the canonical envelope verbatim.
|
|
95
|
-
* - `'blocked'` — attribution gate chain reported baseline
|
|
96
|
-
* drift not attributable to the Story.
|
|
97
|
-
* - `'ok'` — gates passed; the maintainability projection
|
|
98
|
-
* should be emitted and the gate envelope returned to the caller.
|
|
99
|
-
*
|
|
100
|
-
* Inputs are tolerated as `null`/`undefined` so callers that only ran a
|
|
101
|
-
* subset of the chain (resume paths, partial mocks) get a deterministic
|
|
102
|
-
* `'ok'` verdict instead of a thrown error.
|
|
103
|
-
*
|
|
104
|
-
* NO I/O. NO logger calls. NO label transitions. This function is the
|
|
105
|
-
* unit-testable shape of the pre-merge decision.
|
|
106
|
-
*/
|
|
107
|
-
export function summarizeGateResults({
|
|
108
|
-
formatAutofixOutcome = null,
|
|
109
|
-
gateOutcome = null,
|
|
110
|
-
} = {}) {
|
|
111
|
-
if (formatAutofixOutcome?.timedOut) {
|
|
112
|
-
return {
|
|
113
|
-
verdict: 'blocked-timeout',
|
|
114
|
-
blockers: [
|
|
115
|
-
{
|
|
116
|
-
kind: 'format-autofix-timeout',
|
|
117
|
-
formatAutofixOutcome,
|
|
118
|
-
},
|
|
119
|
-
],
|
|
120
|
-
advisories: [],
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
if (gateOutcome?.status === 'blocked') {
|
|
124
|
-
return {
|
|
125
|
-
verdict: 'blocked',
|
|
126
|
-
blockers: [
|
|
127
|
-
{
|
|
128
|
-
kind: 'baseline-drift',
|
|
129
|
-
gateOutcome,
|
|
130
|
-
},
|
|
131
|
-
],
|
|
132
|
-
advisories: [],
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
if (gateOutcome?.status === 'blocked-timeout') {
|
|
136
|
-
return {
|
|
137
|
-
verdict: 'blocked-timeout',
|
|
138
|
-
blockers: [
|
|
139
|
-
{
|
|
140
|
-
kind: 'gate-timeout',
|
|
141
|
-
gateOutcome,
|
|
142
|
-
},
|
|
143
|
-
],
|
|
144
|
-
advisories: [],
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
return {
|
|
148
|
-
verdict: 'ok',
|
|
149
|
-
blockers: [],
|
|
150
|
-
advisories: [],
|
|
151
|
-
gateOutcome,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Side-effecting emitter: consumes a `summarizeGateResults` summary plus
|
|
157
|
-
* the orchestration context and performs the actions implied by the
|
|
158
|
-
* verdict (Story #2995 split).
|
|
159
|
-
*
|
|
160
|
-
* - `blocked-timeout` from format-autofix → return the canonical
|
|
161
|
-
* timeout envelope built from `formatAutofixOutcome`.
|
|
162
|
-
* - `blocked` / `blocked-timeout` from the attribution gate chain →
|
|
163
|
-
* return the gate outcome verbatim (caller routes through
|
|
164
|
-
* `emitBaselineBlockedResult` / spawn-timeout handler).
|
|
165
|
-
* - `ok` → emit the maintainability projection (Logger side effect) and
|
|
166
|
-
* return the gate outcome verbatim.
|
|
167
|
-
*
|
|
168
|
-
* Maintaining output byte-equivalence with the pre-refactor function is
|
|
169
|
-
* the contract: the gate-outcome objects flow through unchanged.
|
|
170
|
-
*/
|
|
171
|
-
export function emitGateOutcome(summary, ctx) {
|
|
172
|
-
if (summary.verdict === 'blocked-timeout') {
|
|
173
|
-
const blocker = summary.blockers[0];
|
|
174
|
-
if (blocker?.kind === 'format-autofix-timeout') {
|
|
175
|
-
const fao = blocker.formatAutofixOutcome;
|
|
176
|
-
return {
|
|
177
|
-
status: 'blocked-timeout',
|
|
178
|
-
gateName: 'format-autofix',
|
|
179
|
-
exitCode: fao.exitCode ?? 124,
|
|
180
|
-
spawnCmd: fao.writeCmdString ?? null,
|
|
181
|
-
timeoutMs: fao.timeoutMs ?? null,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
return blocker?.gateOutcome ?? null;
|
|
185
|
-
}
|
|
186
|
-
if (summary.verdict === 'blocked') {
|
|
187
|
-
return summary.blockers[0]?.gateOutcome ?? null;
|
|
188
|
-
}
|
|
189
|
-
// verdict === 'ok'
|
|
190
|
-
emitMaintainabilityProjection({
|
|
191
|
-
cwd: ctx.cwd,
|
|
192
|
-
epicBranch: ctx.epicBranch,
|
|
193
|
-
storyBranch: ctx.storyBranch,
|
|
194
|
-
config: ctx.config,
|
|
195
|
-
logger: Logger,
|
|
196
|
-
});
|
|
197
|
-
return summary.gateOutcome;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Run the close-validation gate chain against the Story worktree. The
|
|
202
|
-
* format-autofix self-heal step runs first (Story #2165 — bounded
|
|
203
|
-
* timeout) and short-circuits the chain when the formatter spawn is
|
|
204
|
-
* SIGKILLed. Otherwise the attribution-aware gate chain runs.
|
|
205
|
-
*
|
|
206
|
-
* Story #2995 split this body into a pure summarizer
|
|
207
|
-
* (`summarizeGateResults`) + a side-effecting emitter
|
|
208
|
-
* (`emitGateOutcome`). This function is now a thin sequencer.
|
|
209
|
-
*
|
|
210
|
-
* Returns the gate envelope verbatim so the caller can route by
|
|
211
|
-
* `status` (`blocked` vs `blocked-timeout` vs `ok`).
|
|
212
|
-
*/
|
|
213
|
-
export async function runPreMergeValidation({
|
|
214
|
-
cwd,
|
|
215
|
-
worktreePath,
|
|
216
|
-
epicBranch,
|
|
217
|
-
storyBranch,
|
|
218
|
-
config,
|
|
219
|
-
storyId,
|
|
220
|
-
epicId,
|
|
221
|
-
noEvidenceFlag,
|
|
222
|
-
phaseTimer,
|
|
223
|
-
provider,
|
|
224
|
-
bus = null,
|
|
225
|
-
cycleState = null,
|
|
226
|
-
}) {
|
|
227
|
-
// Story #2533: scope-narrowed biome-format auto-apply on the Epic→Story
|
|
228
|
-
// diff. The scoped step folds format drift introduced by Story commits
|
|
229
|
-
// into a dedicated `fix(story-close):` commit on the Story branch and
|
|
230
|
-
// emits Logger.warn naming the auto-fixed files.
|
|
231
|
-
//
|
|
232
|
-
// Story #3407: when branch refs are available, this scoped step is the
|
|
233
|
-
// formatter autofix path. Falling through to the whole-tree `.` formatter
|
|
234
|
-
// from inside `.worktrees/story-*` is fragile against consumer ignore
|
|
235
|
-
// globs that exclude `.worktrees`, so the broad autofix is retained only
|
|
236
|
-
// for resume/legacy callers that cannot supply a diff anchor.
|
|
237
|
-
let formatAutofixOutcome = null;
|
|
238
|
-
if (epicBranch && storyBranch) {
|
|
239
|
-
// Story #3907 — pass `worktreePath` so the formatter writes + the scoped
|
|
240
|
-
// `fix(story-close):` commit land in the Story worktree (where
|
|
241
|
-
// `story-<id>` is checked out), never the main checkout's current branch.
|
|
242
|
-
formatAutofixOutcome = runScopedFormatAutofix({
|
|
243
|
-
cwd,
|
|
244
|
-
worktreePath,
|
|
245
|
-
storyId,
|
|
246
|
-
epicBranch,
|
|
247
|
-
storyBranch,
|
|
248
|
-
config,
|
|
249
|
-
logger: Logger,
|
|
250
|
-
});
|
|
251
|
-
} else {
|
|
252
|
-
formatAutofixOutcome = runFormatAutofix({
|
|
253
|
-
cwd,
|
|
254
|
-
storyId,
|
|
255
|
-
config,
|
|
256
|
-
logger: Logger,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
if (formatAutofixOutcome?.timedOut) {
|
|
260
|
-
const summary = summarizeGateResults({ formatAutofixOutcome });
|
|
261
|
-
return emitGateOutcome(summary, {
|
|
262
|
-
cwd,
|
|
263
|
-
epicBranch,
|
|
264
|
-
storyBranch,
|
|
265
|
-
config,
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
const gateOutcome = await runPreMergeGatesWithAttribution({
|
|
269
|
-
cwd,
|
|
270
|
-
worktreePath,
|
|
271
|
-
epicBranch,
|
|
272
|
-
storyBranch,
|
|
273
|
-
config,
|
|
274
|
-
storyId,
|
|
275
|
-
epicId,
|
|
276
|
-
cycleState,
|
|
277
|
-
useEvidence: !noEvidenceFlag,
|
|
278
|
-
phaseTimer,
|
|
279
|
-
provider,
|
|
280
|
-
bus,
|
|
281
|
-
});
|
|
282
|
-
const summary = summarizeGateResults({
|
|
283
|
-
formatAutofixOutcome,
|
|
284
|
-
gateOutcome,
|
|
285
|
-
});
|
|
286
|
-
return emitGateOutcome(summary, {
|
|
287
|
-
cwd,
|
|
288
|
-
epicBranch,
|
|
289
|
-
storyBranch,
|
|
290
|
-
config,
|
|
291
|
-
});
|
|
292
|
-
}
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* phases/locked-pipeline.js — the per-Epic-merge-lock-protected body of
|
|
3
|
-
* `runStoryClose` (Story #2460, Epic #2453 — CLI thinning pilot).
|
|
4
|
-
*
|
|
5
|
-
* Sits behind `withEpicMergeLock` in story-close.js. Owns:
|
|
6
|
-
*
|
|
7
|
-
* 1. dispatchRecovery — prior-state detection + --resume / --restart
|
|
8
|
-
* dispatch
|
|
9
|
-
* 2. fetchChildTickets — hydrate the cascade target set
|
|
10
|
-
* 3. phase-timer restore — pick up the snapshot story-init wrote
|
|
11
|
-
* 4. gates — pre-merge validation (skipped on resume)
|
|
12
|
-
* 5. refresh — bounded baseline auto-refresh (gates ok path)
|
|
13
|
-
* 6. close — merge + post-merge close pipeline
|
|
14
|
-
*
|
|
15
|
-
* The split out of story-close.js keeps the CLI shell at ≤ 300 LOC and
|
|
16
|
-
* means a future test can drive the locked pipeline with the lock
|
|
17
|
-
* mocked out — without re-acquiring the per-Epic lock or re-entering
|
|
18
|
-
* the preflight gate.
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
import { Logger } from '../../../Logger.js';
|
|
22
|
-
import { hasInlineAcceptance } from '../../../story-init/task-graph-builder.js';
|
|
23
|
-
import { fetchChildTickets } from '../../../story-lifecycle.js';
|
|
24
|
-
import { createPhaseTimer } from '../../../util/phase-timer.js';
|
|
25
|
-
import {
|
|
26
|
-
clearPhaseTimerState,
|
|
27
|
-
loadPhaseTimerState,
|
|
28
|
-
} from '../../../util/phase-timer-state.js';
|
|
29
|
-
import { read as readPlanState } from '../../epic-plan-state-store.js';
|
|
30
|
-
import { dispatchRecovery } from '../../story-close-recovery.js';
|
|
31
|
-
import { runClosePhase } from './close.js';
|
|
32
|
-
import { runStoryCodeReview } from './code-review.js';
|
|
33
|
-
import {
|
|
34
|
-
emitBaselineBlockedResult,
|
|
35
|
-
runPreMergeValidation,
|
|
36
|
-
shouldSkipValidation,
|
|
37
|
-
} from './gates.js';
|
|
38
|
-
import { runAutoRefreshSafely } from './refresh.js';
|
|
39
|
-
import { emitSpawnTimeoutBlockedResult } from './timeout-blocked-emitter.js';
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Run pre-merge gates and, on a clean outcome, the bounded baseline
|
|
43
|
-
* auto-refresh. Returns `{ blocked }` so the locked pipeline can
|
|
44
|
-
* short-circuit on a `blocked` / `blocked-timeout` gate outcome.
|
|
45
|
-
*
|
|
46
|
-
* `runPreMergeValidation` is an injectable seam (Story #3973): the
|
|
47
|
-
* forwarding of `config: ctx.config` into the gate builder is load-bearing
|
|
48
|
-
* — without it the typecheck gate ignores `project.commands.typecheck` and
|
|
49
|
-
* falls back to the hardcoded `npm run typecheck`, blocking every close for
|
|
50
|
-
* any consumer with a non-default typecheck command. The default is the
|
|
51
|
-
* module-level `runPreMergeValidation`; tests inject a spy to pin that
|
|
52
|
-
* `config` reaches the gate builder through this call site.
|
|
53
|
-
*
|
|
54
|
-
* @param {object} ctx - The locked-pipeline context bundle.
|
|
55
|
-
* @param {object} [deps] - Injectable collaborators.
|
|
56
|
-
* @param {typeof runPreMergeValidation} [deps.runPreMergeValidationFn]
|
|
57
|
-
* @param {typeof runAutoRefreshSafely} [deps.runAutoRefreshSafelyFn]
|
|
58
|
-
*/
|
|
59
|
-
export async function runGatesAndRefresh(
|
|
60
|
-
ctx,
|
|
61
|
-
{
|
|
62
|
-
runPreMergeValidationFn = runPreMergeValidation,
|
|
63
|
-
runAutoRefreshSafelyFn = runAutoRefreshSafely,
|
|
64
|
-
} = {},
|
|
65
|
-
) {
|
|
66
|
-
// Story #4017 — one shared cycle-state object per close cycle. The
|
|
67
|
-
// gate-failure attribution retry and the post-gates auto-refresh both
|
|
68
|
-
// funnel through `runRefreshCommit`, which keys its idempotency token
|
|
69
|
-
// off this object so each baseline kind is refreshed (scored +
|
|
70
|
-
// committed) at most once per close.
|
|
71
|
-
const cycleState = { refreshedKinds: new Set(), lastRefreshSha: null };
|
|
72
|
-
const gateOutcome = await runPreMergeValidationFn({
|
|
73
|
-
cwd: ctx.cwd,
|
|
74
|
-
worktreePath: ctx.worktreePath,
|
|
75
|
-
epicBranch: ctx.epicBranch,
|
|
76
|
-
storyBranch: ctx.storyBranch,
|
|
77
|
-
config: ctx.config,
|
|
78
|
-
storyId: ctx.storyId,
|
|
79
|
-
epicId: ctx.epicId,
|
|
80
|
-
noEvidenceFlag: ctx.noEvidenceFlag,
|
|
81
|
-
phaseTimer: ctx.phaseTimer,
|
|
82
|
-
provider: ctx.provider,
|
|
83
|
-
bus: ctx.bus,
|
|
84
|
-
cycleState,
|
|
85
|
-
});
|
|
86
|
-
if (gateOutcome?.status === 'blocked') {
|
|
87
|
-
return {
|
|
88
|
-
blocked: await emitBaselineBlockedResult({
|
|
89
|
-
storyId: ctx.storyId,
|
|
90
|
-
gateOutcome,
|
|
91
|
-
progress: ctx.progress,
|
|
92
|
-
bus: ctx.bus,
|
|
93
|
-
}),
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
if (gateOutcome?.status === 'blocked-timeout') {
|
|
97
|
-
return {
|
|
98
|
-
blocked: await emitSpawnTimeoutBlockedResult({
|
|
99
|
-
storyId: ctx.storyId,
|
|
100
|
-
epicId: ctx.epicId,
|
|
101
|
-
spawnName: gateOutcome.gateName ?? 'coverage-capture',
|
|
102
|
-
spawnCmd: gateOutcome.spawnCmd ?? null,
|
|
103
|
-
timeoutMs: gateOutcome.timeoutMs ?? null,
|
|
104
|
-
exitCode: gateOutcome.exitCode ?? 124,
|
|
105
|
-
config: ctx.config,
|
|
106
|
-
provider: ctx.provider,
|
|
107
|
-
progress: ctx.progress,
|
|
108
|
-
bus: ctx.bus,
|
|
109
|
-
}),
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
await runAutoRefreshSafelyFn(
|
|
113
|
-
{
|
|
114
|
-
storyId: ctx.storyId,
|
|
115
|
-
epicId: ctx.epicId,
|
|
116
|
-
cwd: ctx.worktreePath || ctx.cwd,
|
|
117
|
-
epicBranch: ctx.epicBranch,
|
|
118
|
-
storyBranch: ctx.storyBranch,
|
|
119
|
-
config: ctx.config,
|
|
120
|
-
cycleState,
|
|
121
|
-
},
|
|
122
|
-
{ progress: ctx.progress },
|
|
123
|
-
);
|
|
124
|
-
return { blocked: null };
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Read the parent Epic's judged `planningRisk` envelope off its
|
|
129
|
-
* `epic-plan-state` checkpoint so the Story-scope review can inherit the
|
|
130
|
-
* Epic's review depth (Story #3940). Best-effort and total — it reuses the
|
|
131
|
-
* shared `read` from `epic-plan-state-store.js` (the same reader `/plan
|
|
132
|
-
* --resume` and `epic-audit-prepare.js`'s `resolveRiskRoutedLenses` use, no
|
|
133
|
-
* third bespoke reader) and never fails the close:
|
|
134
|
-
*
|
|
135
|
-
* - absent/non-integer `epicId` (a Story that is not Epic-attached) → `null`
|
|
136
|
-
* - missing/unparseable checkpoint, no `planningRisk` field → `null`
|
|
137
|
-
* - any read throw (provider error, malformed comment) → `null`
|
|
138
|
-
*
|
|
139
|
-
* A `null` result threads through `runStoryCodeReview` → `runCodeReview`
|
|
140
|
-
* unchanged, so depth resolves from diff width alone (`standard`), preserving
|
|
141
|
-
* today's behaviour for an Epic that skipped `/plan`.
|
|
142
|
-
*
|
|
143
|
-
* @param {{ provider: object, epicId: number|null|undefined, readPlanStateFn?: typeof readPlanState }} args
|
|
144
|
-
* @returns {Promise<{ overallLevel?: string, axes?: Array<object> }|null>}
|
|
145
|
-
*/
|
|
146
|
-
export async function resolveParentEpicPlanningRisk({
|
|
147
|
-
provider,
|
|
148
|
-
epicId,
|
|
149
|
-
readPlanStateFn = readPlanState,
|
|
150
|
-
}) {
|
|
151
|
-
if (!Number.isInteger(epicId) || epicId <= 0) return null;
|
|
152
|
-
try {
|
|
153
|
-
const state = await readPlanStateFn({ provider, epicId });
|
|
154
|
-
return state?.planningRisk ?? null;
|
|
155
|
-
} catch {
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Body of `withEpicMergeLock(epicId, ..., () => …)` from story-close.js.
|
|
162
|
-
*
|
|
163
|
-
* @param {object} args - resolved-close-input bundle from
|
|
164
|
-
* `resolveCloseInputs` plus the orchestrator-injected `progress` /
|
|
165
|
-
* `progressLog` callbacks and the lifecycle bus.
|
|
166
|
-
* @returns {Promise<{ success: boolean, result?: object } | object>}
|
|
167
|
-
*/
|
|
168
|
-
export async function runStoryCloseLocked(args) {
|
|
169
|
-
const {
|
|
170
|
-
cwd,
|
|
171
|
-
storyId,
|
|
172
|
-
epicId,
|
|
173
|
-
epicBranch,
|
|
174
|
-
storyBranch,
|
|
175
|
-
config,
|
|
176
|
-
skipValidationParam,
|
|
177
|
-
resumeFlag,
|
|
178
|
-
restartFlag,
|
|
179
|
-
provider,
|
|
180
|
-
story,
|
|
181
|
-
progress,
|
|
182
|
-
} = args;
|
|
183
|
-
|
|
184
|
-
// Prior-state detection + --resume / --restart dispatch.
|
|
185
|
-
// `dispatchRecovery` only reads `orchestration.worktreeIsolation`; surface
|
|
186
|
-
// it from the canonical `delivery.worktreeIsolation` view directly.
|
|
187
|
-
const { resumeFromConflict, resumeFromMerge, resumeFromPostMerge } =
|
|
188
|
-
dispatchRecovery({
|
|
189
|
-
cwd,
|
|
190
|
-
storyId,
|
|
191
|
-
epicId,
|
|
192
|
-
epicBranch,
|
|
193
|
-
storyBranch,
|
|
194
|
-
orchestration: { worktreeIsolation: config.delivery?.worktreeIsolation },
|
|
195
|
-
resume: resumeFlag,
|
|
196
|
-
restart: restartFlag,
|
|
197
|
-
progress,
|
|
198
|
-
logger: Logger,
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
// Story #4251 — mirror the init-side short-circuit: a 2-tier Story (inline
|
|
202
|
-
// acceptance on its body) has no children, so skip the `fetchChildTickets`
|
|
203
|
-
// probe (empty sub-issues GraphQL query + never-matching `/search/issues`
|
|
204
|
-
// scan) entirely. The cascade target is just the Story itself. A body
|
|
205
|
-
// lacking inline acceptance still enumerates children for legacy / Epic
|
|
206
|
-
// callers.
|
|
207
|
-
const tasks = hasInlineAcceptance(story?.body)
|
|
208
|
-
? []
|
|
209
|
-
: await fetchChildTickets(provider, storyId);
|
|
210
|
-
provider.primeTicketCache([story, ...tasks]);
|
|
211
|
-
progress('TICKETS', `Found ${tasks.length} child ticket(s)`);
|
|
212
|
-
|
|
213
|
-
const prior = loadPhaseTimerState({ mainCwd: cwd, storyId });
|
|
214
|
-
const phaseTimer = createPhaseTimer(storyId, prior ? { restore: prior } : {});
|
|
215
|
-
|
|
216
|
-
const skipValidation = shouldSkipValidation({
|
|
217
|
-
skipValidationParam,
|
|
218
|
-
resumeFromConflict,
|
|
219
|
-
resumeFromMerge,
|
|
220
|
-
resumeFromPostMerge,
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
const ctx = {
|
|
224
|
-
...args,
|
|
225
|
-
tasks,
|
|
226
|
-
phaseTimer,
|
|
227
|
-
resumeFromConflict,
|
|
228
|
-
resumeFromMerge,
|
|
229
|
-
resumeFromPostMerge,
|
|
230
|
-
clearPhaseTimerState,
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
if (!skipValidation) {
|
|
234
|
-
const { blocked } = await runGatesAndRefresh(ctx);
|
|
235
|
-
if (blocked) return blocked;
|
|
236
|
-
|
|
237
|
-
// Story #2840 — Story-scope code review runs after the gate chain
|
|
238
|
-
// passes (so we know the diff is build-clean) but before the merge
|
|
239
|
-
// into `epic/<id>`. Critical findings short-circuit the close and
|
|
240
|
-
// exit non-zero; non-critical findings post a structured comment
|
|
241
|
-
// and let close proceed.
|
|
242
|
-
//
|
|
243
|
-
// Story #3940 — the review inherits the parent Epic's judged review
|
|
244
|
-
// depth: read the Epic's `planningRisk` envelope best-effort off its
|
|
245
|
-
// `epic-plan-state` checkpoint and forward it so `runCodeReview`
|
|
246
|
-
// resolves depth from BOTH that risk and the Story-scope
|
|
247
|
-
// (`epic/<id>...story-<id>`) changed-file count. A missing/unreadable
|
|
248
|
-
// checkpoint degrades to `null` (→ `standard`) without failing close.
|
|
249
|
-
const planningRisk = await resolveParentEpicPlanningRisk({
|
|
250
|
-
provider: ctx.provider,
|
|
251
|
-
epicId: ctx.epicId,
|
|
252
|
-
});
|
|
253
|
-
const review = await runStoryCodeReview({
|
|
254
|
-
storyId: ctx.storyId,
|
|
255
|
-
epicBranch: ctx.epicBranch,
|
|
256
|
-
storyBranch: ctx.storyBranch,
|
|
257
|
-
provider: ctx.provider,
|
|
258
|
-
bus: ctx.bus,
|
|
259
|
-
progress: ctx.progress,
|
|
260
|
-
planningRisk,
|
|
261
|
-
});
|
|
262
|
-
if (review.blocked) return review.blocked;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// Everything past validation is the `close` phase; the post-merge
|
|
266
|
-
// pipeline marks `api-sync` once the merge lands.
|
|
267
|
-
phaseTimer.mark('close');
|
|
268
|
-
|
|
269
|
-
return runClosePhase(ctx);
|
|
270
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* phases/preflight.js — story-close preflight phase (Story #2460, Epic
|
|
3
|
-
* #2453 — CLI thinning pilot).
|
|
4
|
-
*
|
|
5
|
-
* Wraps the registry-driven preflight scan + the canonical "preflight
|
|
6
|
-
* refused" close-result envelope. Runs BEFORE `withEpicMergeLock` so the
|
|
7
|
-
* per-Epic lock is not acquired just to release it on a refused
|
|
8
|
-
* preflight (the project-wide exit-code 2 reservation).
|
|
9
|
-
*
|
|
10
|
-
* Public surface:
|
|
11
|
-
* - runStoryClosePreflight(opts) ← exported (story-close.js re-export)
|
|
12
|
-
* - emitPreflightBlockedResult(opts)
|
|
13
|
-
* - runPreflightPhase(ctx) ← pipeline entry
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { Logger } from '../../../Logger.js';
|
|
17
|
-
import {
|
|
18
|
-
PREFLIGHT_REFUSED_EXIT_CODE,
|
|
19
|
-
runPreflight,
|
|
20
|
-
} from '../../../preflight-runner.js';
|
|
21
|
-
import { emitBlockedCloseResult } from '../merge-runner.js';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Run the story-close preflight gate. Exported so tests can drive it
|
|
25
|
-
* with an inline registry / probe spies without re-entering the full
|
|
26
|
-
* close orchestrator.
|
|
27
|
-
*
|
|
28
|
-
* @param {object} opts
|
|
29
|
-
* @param {string|number} opts.storyId
|
|
30
|
-
* @param {string} [opts.cwd=process.cwd()]
|
|
31
|
-
* @param {object} [opts.probes]
|
|
32
|
-
* @param {object} [opts.registry]
|
|
33
|
-
* @param {string} [opts.dir]
|
|
34
|
-
* @param {object} [opts.logger]
|
|
35
|
-
* @returns {Promise<{ ok: boolean, findings: Array, fixed: Array }>}
|
|
36
|
-
*/
|
|
37
|
-
export async function runStoryClosePreflight({
|
|
38
|
-
storyId,
|
|
39
|
-
cwd = process.cwd(),
|
|
40
|
-
probes,
|
|
41
|
-
registry,
|
|
42
|
-
dir,
|
|
43
|
-
logger,
|
|
44
|
-
} = {}) {
|
|
45
|
-
Logger.info(
|
|
46
|
-
`[story-close] Running preflight checks (scope=story-close) for Story #${storyId ?? '?'}...`,
|
|
47
|
-
);
|
|
48
|
-
const preflight = await runPreflight({
|
|
49
|
-
scope: 'story-close',
|
|
50
|
-
autoFix: true,
|
|
51
|
-
cwd,
|
|
52
|
-
probes,
|
|
53
|
-
registry,
|
|
54
|
-
dir,
|
|
55
|
-
logger,
|
|
56
|
-
});
|
|
57
|
-
return {
|
|
58
|
-
ok: !preflight.blocked,
|
|
59
|
-
findings: preflight.findings,
|
|
60
|
-
fixed: preflight.fixed,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Emit the canonical close-result envelope for the "preflight refused"
|
|
66
|
-
* exit. Shape mirrors `emitBaselineBlockedResult` so the wave aggregator's
|
|
67
|
-
* label-derivation fallback sees a consistent envelope.
|
|
68
|
-
*/
|
|
69
|
-
export async function emitPreflightBlockedResult({
|
|
70
|
-
storyId,
|
|
71
|
-
preflight,
|
|
72
|
-
progress,
|
|
73
|
-
}) {
|
|
74
|
-
return emitBlockedCloseResult({
|
|
75
|
-
storyId,
|
|
76
|
-
phase: 'preflight',
|
|
77
|
-
reason: 'preflight-refused',
|
|
78
|
-
extra: { findings: preflight.findings },
|
|
79
|
-
progress,
|
|
80
|
-
blockedMessage: `Story #${storyId} blocked: preflight refused — ${preflight.findings.length} blocker finding(s).`,
|
|
81
|
-
logger: Logger,
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Phase pipeline entry. Returns one of:
|
|
87
|
-
* - { ok: true } when preflight passed (caller continues)
|
|
88
|
-
* - { ok: false, exitEnvelope } when preflight refused (caller short-circuits
|
|
89
|
-
* with `{ success: false, result: exitEnvelope, exitCode: PREFLIGHT_REFUSED_EXIT_CODE }`)
|
|
90
|
-
*/
|
|
91
|
-
export async function runPreflightPhase({ ctx }) {
|
|
92
|
-
const outcome = await runStoryClosePreflight({
|
|
93
|
-
storyId: ctx.storyId,
|
|
94
|
-
cwd: ctx.cwd,
|
|
95
|
-
});
|
|
96
|
-
if (outcome.ok) return { ok: true };
|
|
97
|
-
const exitEnvelope = await emitPreflightBlockedResult({
|
|
98
|
-
storyId: ctx.storyId,
|
|
99
|
-
preflight: outcome,
|
|
100
|
-
progress: ctx.progress,
|
|
101
|
-
});
|
|
102
|
-
return {
|
|
103
|
-
ok: false,
|
|
104
|
-
exitEnvelope: {
|
|
105
|
-
success: false,
|
|
106
|
-
result: exitEnvelope,
|
|
107
|
-
exitCode: PREFLIGHT_REFUSED_EXIT_CODE,
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
}
|