mandrel 1.93.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/acceptance-critic.md +129 -0
- package/.agents/agents/story-worker.md +161 -0
- package/.agents/docs/SDLC.md +489 -1285
- package/.agents/docs/agentrc-reference.json +177 -67
- package/.agents/docs/configuration.md +108 -136
- package/.agents/docs/execution-reference.md +44 -22
- package/.agents/docs/quality-gates.md +13 -19
- package/.agents/docs/workflows.md +3 -3
- package/.agents/instructions.md +107 -108
- package/.agents/rules/ci-remediation.md +8 -12
- package/.agents/rules/git-conventions-reference.md +224 -0
- package/.agents/rules/git-conventions.md +42 -223
- package/.agents/rules/security-baseline.md +5 -0
- package/.agents/rules/testing-standards.md +106 -13
- package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
- package/.agents/schemas/agentrc.schema.json +71 -201
- 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/acceptance-eval.js +62 -18
- package/.agents/scripts/agents-bootstrap-github.js +1 -1
- 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-context-budget.js +62 -5
- 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/diagnose-friction.js +0 -6
- 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/bootstrap/project-bootstrap.js +56 -18
- 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 +160 -22
- package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
- package/.agents/scripts/lib/config/ci.js +6 -31
- package/.agents/scripts/lib/config/delivery-routing.js +103 -0
- package/.agents/scripts/lib/config/explain.js +57 -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 +3 -8
- package/.agents/scripts/lib/config-settings-schema-delivery.js +46 -136
- package/.agents/scripts/lib/config-settings-schema-quality.js +17 -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 +39 -4
- 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 +112 -3
- package/.agents/scripts/lib/observability/hook-heartbeat.js +187 -0
- package/.agents/scripts/lib/observability/source-classifier.js +3 -3
- package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
- package/.agents/scripts/lib/onboard/init-tail.js +1 -3
- package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
- package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
- package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +273 -0
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +204 -0
- 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-critic-conditions.js +3 -2
- 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 +14 -14
- 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/close-validation.js +1 -0
- 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 +3 -8
- 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/provider-factory.js +1 -1
- 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/post-structured-comment.js +38 -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/sync-claude-agents.js +165 -0
- package/.agents/scripts/update-ticket-state.js +37 -15
- package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
- package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
- package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
- package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
- package/.agents/skills/core/idea-refinement/SKILL.md +8 -14
- package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
- package/.agents/skills/core/scope-triage/SKILL.md +28 -172
- package/.agents/skills/skills.index.json +8 -418
- 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 -131
- 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 +52 -40
- 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/mandrel-sync-config.md +1 -1
- 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 +3 -2
- 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 +46 -0
- package/lib/cli/registry.js +95 -0
- package/lib/migrations/index.js +6 -5
- package/package.json +5 -3
- package/.agents/personas/architect.md +0 -113
- package/.agents/personas/devops-engineer.md +0 -38
- package/.agents/personas/engineer-mobile.md +0 -120
- package/.agents/personas/engineer-web.md +0 -111
- package/.agents/personas/engineer.md +0 -119
- package/.agents/personas/product.md +0 -94
- package/.agents/personas/project-manager.md +0 -114
- package/.agents/personas/qa-engineer.md +0 -95
- package/.agents/personas/refactorer.md +0 -113
- package/.agents/personas/security-engineer.md +0 -112
- package/.agents/personas/sre.md +0 -86
- package/.agents/personas/technical-writer.md +0 -101
- package/.agents/personas/ux-designer.md +0 -95
- package/.agents/schemas/dispatch-manifest.json +0 -232
- package/.agents/schemas/epic-spec.schema.json +0 -153
- package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
- 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 -590
- package/.agents/scripts/epic-execute-record-wave.js +0 -449
- package/.agents/scripts/epic-plan-clarity.js +0 -211
- package/.agents/scripts/epic-plan-decompose.js +0 -54
- package/.agents/scripts/epic-plan-healthcheck.js +0 -581
- package/.agents/scripts/epic-plan-spec.js +0 -64
- 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 -660
- 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 -388
- 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-story-dispatch-end.js +0 -147
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -384
- 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 -278
- 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/skill-capsule-loader.js +0 -109
- 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 -301
- 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/plan-critics.js +0 -199
- package/.agents/scripts/retro-run.js +0 -218
- 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 -335
- package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
- package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
- package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
- package/.agents/skills/core/code-simplification/SKILL.md +0 -389
- package/.agents/skills/core/context-engineering/SKILL.md +0 -309
- package/.agents/skills/core/context-engineering/examples.md +0 -58
- package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
- 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 -413
- package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
- package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
- package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
- package/.agents/skills/core/idea-refinement/examples.md +0 -437
- package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
- package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
- package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
- package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
- package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
- package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
- package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
- package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
- package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
- package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
- package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
- package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
- package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
- package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
- package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
- package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
- package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
- package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
- package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
- package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
- package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
- package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
- package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
- package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
- package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
- package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
- package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
- package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
- package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
- package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
- package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
- package/.agents/workflows/helpers/deliver-epic-reference.md +0 -534
- package/.agents/workflows/helpers/deliver-epic.md +0 -955
- package/.agents/workflows/helpers/deliver-stories.md +0 -440
- package/.agents/workflows/helpers/epic-audit.md +0 -189
- package/.agents/workflows/helpers/epic-deliver-story.md +0 -427
- 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 -351
- 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,590 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/* node:coverage ignore file */
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* epic-deliver-prepare.js — Step 0/1 of the operator-driven `/deliver`.
|
|
6
|
-
*
|
|
7
|
-
* Composes the existing engine phases that the in-process epic-runner used to
|
|
8
|
-
* call sequentially, but does NOT dispatch any Stories. The CLI is the single
|
|
9
|
-
* point at which the slash-command captures:
|
|
10
|
-
*
|
|
11
|
-
* 1. The Epic ticket snapshot (`runSnapshotPhase`).
|
|
12
|
-
* 2. The story DAG (`runBuildWaveDagPhase`) computed from every child Story —
|
|
13
|
-
* used here only to enumerate the open Story set and run the
|
|
14
|
-
* concurrency-hazard gate; the ready-set runtime re-derives readiness
|
|
15
|
-
* from live labels on every `tick`, so the prepare no longer persists a
|
|
16
|
-
* wave grouping.
|
|
17
|
-
* 3. The seeded `epic-run-state` checkpoint (`epic-run-state-store.initialize`)
|
|
18
|
-
* in the per-Story-status shape (Story #4155): a flat
|
|
19
|
-
* `stories: { [storyId]: { status: 'pending' } }` map plus the GLOBAL
|
|
20
|
-
* in-flight `concurrencyCap`. Idempotent — re-running prepare against a
|
|
21
|
-
* partially-driven Epic preserves the original `startedAt` and every
|
|
22
|
-
* already-recorded Story status (it never resets recorded progress).
|
|
23
|
-
* 4. The dispatch hint (`StoryLauncher.planWave`) — a deterministic list of
|
|
24
|
-
* `{ storyId, worktree }` entries the slash command uses to resolve
|
|
25
|
-
* per-Story worktree paths. The ready-set `tick` selects which of these
|
|
26
|
-
* to dispatch on each beat; the prepare only enumerates the set.
|
|
27
|
-
*
|
|
28
|
-
* Stdout is a single JSON envelope so the slash command can parse without
|
|
29
|
-
* re-reading any tickets.
|
|
30
|
-
*
|
|
31
|
-
* Usage:
|
|
32
|
-
* node .agents/scripts/epic-deliver-prepare.js --epic <epicId>
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
import fs from 'node:fs';
|
|
36
|
-
import path from 'node:path';
|
|
37
|
-
import { parseArgs } from 'node:util';
|
|
38
|
-
|
|
39
|
-
import { runBootSweep } from './boot-sweep.js';
|
|
40
|
-
import { buildChecklistPayload } from './lib/audit-suite/index.js';
|
|
41
|
-
import { runAsCli } from './lib/cli-utils.js';
|
|
42
|
-
import { getPaths, getRunners, resolveConfig } from './lib/config-resolver.js';
|
|
43
|
-
import { currentBranch as gitCurrentBranch } from './lib/git-branch-lifecycle.js';
|
|
44
|
-
import { getEpicBranch, gitSpawn } from './lib/git-utils.js';
|
|
45
|
-
import { Logger } from './lib/Logger.js';
|
|
46
|
-
import { ensureDocsDigest } from './lib/orchestration/docs-digest.js';
|
|
47
|
-
import {
|
|
48
|
-
resolveOperator,
|
|
49
|
-
runPrepareGuards,
|
|
50
|
-
} from './lib/orchestration/epic-deliver-lease-guard.js';
|
|
51
|
-
import {
|
|
52
|
-
initialize as initializeEpicRunState,
|
|
53
|
-
write as writeEpicRunState,
|
|
54
|
-
} from './lib/orchestration/epic-run-state-store.js';
|
|
55
|
-
import {
|
|
56
|
-
collectPendingStoryKeys,
|
|
57
|
-
evaluateConcurrencyGate,
|
|
58
|
-
filterFindingsToPending,
|
|
59
|
-
renderGateErrorMessage,
|
|
60
|
-
} from './lib/orchestration/epic-runner/concurrency-gate.js';
|
|
61
|
-
import { runBuildWaveDagPhase } from './lib/orchestration/epic-runner/phases/build-wave-dag.js';
|
|
62
|
-
import { runSnapshotPhase } from './lib/orchestration/epic-runner/phases/snapshot.js';
|
|
63
|
-
import { StoryLauncher } from './lib/orchestration/epic-runner/story-launcher.js';
|
|
64
|
-
import { collectStoryAssumptionEntries } from './lib/orchestration/file-assumptions.js';
|
|
65
|
-
import {
|
|
66
|
-
computeBaseSha,
|
|
67
|
-
readPreflightCache,
|
|
68
|
-
} from './lib/orchestration/preflight-cache.js';
|
|
69
|
-
import {
|
|
70
|
-
latestHeartbeatForOwner,
|
|
71
|
-
currentOwner as leaseCurrentOwner,
|
|
72
|
-
} from './lib/orchestration/ticket-lease.js';
|
|
73
|
-
import { createProvider } from './lib/provider-factory.js';
|
|
74
|
-
|
|
75
|
-
const HELP = `Usage: node .agents/scripts/epic-deliver-prepare.js --epic <epicId> [--ignore-concurrency-hazards] [--steal] [--as <handle>]
|
|
76
|
-
|
|
77
|
-
Snapshots Epic #<id>, builds the wave DAG, initializes the epic-run-state
|
|
78
|
-
checkpoint, and prints the per-wave dispatch plan as JSON. Before any of that,
|
|
79
|
-
runs two fail-closed preflight guards (Story #3482): a checkout-safety check
|
|
80
|
-
(refuse on a dirty tree or an unexpected branch) and an Epic-lease acquisition
|
|
81
|
-
(refuse on a live foreign claim).
|
|
82
|
-
|
|
83
|
-
Options:
|
|
84
|
-
--ignore-concurrency-hazards Bypass the cross-Story concurrency-hazard
|
|
85
|
-
gate (Story #2297). The flag's use is
|
|
86
|
-
recorded on the Epic checkpoint so retro
|
|
87
|
-
tooling can flag a run that shipped
|
|
88
|
-
despite an outstanding hazard.
|
|
89
|
-
--steal Forcibly transfer a live foreign Epic lease
|
|
90
|
-
to this operator instead of refusing. The
|
|
91
|
-
takeover is logged for auditability.
|
|
92
|
-
--as <handle> Operator identity to claim the Epic lease as.
|
|
93
|
-
Defaults to github.operatorHandle, then the
|
|
94
|
-
local git config user.email.
|
|
95
|
-
`;
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Build the production git shim the checkout-safety guard reads through. Pure
|
|
99
|
-
* `git` subprocess wrappers over `cwd`; injected as a seam so the unit suite
|
|
100
|
-
* can substitute an in-memory shim.
|
|
101
|
-
*
|
|
102
|
-
* @param {string} cwd
|
|
103
|
-
* @returns {{ statusPorcelain: () => { dirty: boolean, entries: string }, currentBranch: () => string|null }}
|
|
104
|
-
*/
|
|
105
|
-
function createGitShim(cwd) {
|
|
106
|
-
return {
|
|
107
|
-
statusPorcelain() {
|
|
108
|
-
const res = gitSpawn(cwd, 'status', '--porcelain');
|
|
109
|
-
if (res.status !== 0) {
|
|
110
|
-
throw new Error(
|
|
111
|
-
`[epic-deliver] Failed to read git status: ${res.stderr || '(no stderr)'}`,
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
const entries = res.stdout ?? '';
|
|
115
|
-
return { dirty: entries.length > 0, entries };
|
|
116
|
-
},
|
|
117
|
-
currentBranch() {
|
|
118
|
-
return gitCurrentBranch(cwd);
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Resolve the local `git config user.email` as the last-resort operator
|
|
125
|
-
* identity. Returns null when git is unavailable or the value is unset.
|
|
126
|
-
*
|
|
127
|
-
* @param {string} cwd
|
|
128
|
-
* @returns {string|null}
|
|
129
|
-
*/
|
|
130
|
-
function resolveGitUserEmail(cwd) {
|
|
131
|
-
const res = gitSpawn(cwd, 'config', 'user.email');
|
|
132
|
-
if (res.status !== 0) return null;
|
|
133
|
-
const value = (res.stdout ?? '').trim();
|
|
134
|
-
return value.length > 0 ? value : null;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* End-to-end prepare. DI-friendly: tests pass `injectedProvider` and skip the
|
|
139
|
-
* real GitHub round-trips.
|
|
140
|
-
*
|
|
141
|
-
* @param {{
|
|
142
|
-
* epicId: number,
|
|
143
|
-
* cwd?: string,
|
|
144
|
-
* injectedProvider?: object,
|
|
145
|
-
* injectedConfig?: object,
|
|
146
|
-
* }} args
|
|
147
|
-
* @returns {Promise<{
|
|
148
|
-
* epicId: number,
|
|
149
|
-
* storyCount: number,
|
|
150
|
-
* concurrencyCap: number,
|
|
151
|
-
* stories: Array<{ storyId: number, title: string, worktree?: string }>,
|
|
152
|
-
* checkpointInitializedAt: string,
|
|
153
|
-
* }>}
|
|
154
|
-
*/
|
|
155
|
-
/**
|
|
156
|
-
* Run the fail-closed preflight guards (Story #3482): refuse on a
|
|
157
|
-
* dirty/foreign-branch checkout and on a live foreign Epic lease, BEFORE any
|
|
158
|
-
* snapshot or git mutation. No-op when guards are suppressed. The guards are
|
|
159
|
-
* skipped when `skipPreflightGuards` is set, OR — implicitly — when a caller
|
|
160
|
-
* injects a provider but no git seam (the signature of the prepare-runner
|
|
161
|
-
* unit tests that drive an in-memory provider and never stand up a tree). The
|
|
162
|
-
* real CLI path injects neither, so the guards always run for an
|
|
163
|
-
* operator-driven invocation. Story #4075 — extracted from
|
|
164
|
-
* `runEpicDeliverPrepare`.
|
|
165
|
-
*/
|
|
166
|
-
async function runPreflightGuardsForPrepare({
|
|
167
|
-
epicId,
|
|
168
|
-
cwd,
|
|
169
|
-
config,
|
|
170
|
-
provider,
|
|
171
|
-
injectedProvider,
|
|
172
|
-
injectedGit,
|
|
173
|
-
asOperator,
|
|
174
|
-
steal,
|
|
175
|
-
leaseHeartbeatAt,
|
|
176
|
-
leaseNow,
|
|
177
|
-
skipPreflightGuards,
|
|
178
|
-
}) {
|
|
179
|
-
const guardsSuppressed =
|
|
180
|
-
skipPreflightGuards || (Boolean(injectedProvider) && !injectedGit);
|
|
181
|
-
if (guardsSuppressed) return;
|
|
182
|
-
|
|
183
|
-
const guardCwd = cwd ?? process.cwd();
|
|
184
|
-
const git = injectedGit ?? createGitShim(guardCwd);
|
|
185
|
-
const baseBranch = config.project?.baseBranch ?? 'main';
|
|
186
|
-
const expectedBranch = [getEpicBranch(epicId), baseBranch];
|
|
187
|
-
const operator =
|
|
188
|
-
resolveOperator({
|
|
189
|
-
asFlag: asOperator,
|
|
190
|
-
config,
|
|
191
|
-
gitUserEmail: injectedGit ? undefined : resolveGitUserEmail(guardCwd),
|
|
192
|
-
}) ?? null;
|
|
193
|
-
|
|
194
|
-
// Liveness seam: a foreign claim is only "live" (and so refuses) when the
|
|
195
|
-
// claim *owner* has a recent `story.heartbeat`. Without this the lease
|
|
196
|
-
// guard is inert — every foreign claim looks stale and gets silently
|
|
197
|
-
// reclaimed (audit #3513). Read the Epic's current assignee (the claim
|
|
198
|
-
// owner) and resolve that owner's latest heartbeat from the Epic lifecycle
|
|
199
|
-
// ledger via the shared resolver. Tests may inject `leaseHeartbeatAt`
|
|
200
|
-
// directly (any value, including null) to bypass the ledger read.
|
|
201
|
-
let heartbeatAt = leaseHeartbeatAt;
|
|
202
|
-
if (heartbeatAt === undefined) {
|
|
203
|
-
const epicTicket = await provider.getTicket(epicId);
|
|
204
|
-
const claimOwner = leaseCurrentOwner(epicTicket?.assignees);
|
|
205
|
-
heartbeatAt = claimOwner
|
|
206
|
-
? latestHeartbeatForOwner({ epicId, owner: claimOwner, config })
|
|
207
|
-
: null;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
await runPrepareGuards({
|
|
211
|
-
epicId,
|
|
212
|
-
expectedBranch,
|
|
213
|
-
git,
|
|
214
|
-
provider,
|
|
215
|
-
operator,
|
|
216
|
-
heartbeatAt,
|
|
217
|
-
steal,
|
|
218
|
-
config,
|
|
219
|
-
now: leaseNow,
|
|
220
|
-
logger: Logger,
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Route the Epic boot cleanup through the shared protected boot-sweep
|
|
226
|
-
* engine (Story #4373). Reaps merged, done `story-*` branches left over
|
|
227
|
-
* from prior runs — the protection partition skips any branch with
|
|
228
|
-
* unpushed work, a dirty worktree, or a still-open parent Story, so an
|
|
229
|
-
* in-flight Story is never touched. Fast-forward is off: the prepare may
|
|
230
|
-
* run on the Epic branch, and the fast-forward phase would otherwise
|
|
231
|
-
* check out the base branch.
|
|
232
|
-
*
|
|
233
|
-
* Best-effort — a sweep failure (lock contention, git/gh error) is
|
|
234
|
-
* swallowed and never blocks or fails the prepare. Skipped in the same
|
|
235
|
-
* injected-test shape the preflight guards use (a provider injected with
|
|
236
|
-
* no git seam) so unit tests never spawn real git/gh.
|
|
237
|
-
*/
|
|
238
|
-
async function runBootSweepForPrepare({
|
|
239
|
-
cwd,
|
|
240
|
-
config,
|
|
241
|
-
provider,
|
|
242
|
-
injectedProvider,
|
|
243
|
-
injectedGit,
|
|
244
|
-
injectedSweep,
|
|
245
|
-
skipPreflightGuards,
|
|
246
|
-
}) {
|
|
247
|
-
const suppressed =
|
|
248
|
-
skipPreflightGuards || (Boolean(injectedProvider) && !injectedGit);
|
|
249
|
-
if (suppressed) return;
|
|
250
|
-
try {
|
|
251
|
-
await runBootSweep({
|
|
252
|
-
cwd,
|
|
253
|
-
include: ['story-*'],
|
|
254
|
-
fastForward: false,
|
|
255
|
-
injectedConfig: config,
|
|
256
|
-
injectedProvider: provider,
|
|
257
|
-
injectedSweep,
|
|
258
|
-
logger: Logger,
|
|
259
|
-
});
|
|
260
|
-
} catch (err) {
|
|
261
|
-
Logger.warn(
|
|
262
|
-
`[epic-deliver-prepare] ⚠️ boot sweep threw (prepare continues): ${err?.message ?? err}`,
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Resolve the Epic state, preferring the preflight cache (Story #3027) and
|
|
269
|
-
* falling back to a fresh snapshot + wave-DAG pass on miss or baseSha
|
|
270
|
-
* mismatch. Returns `{ state, cacheStatus }`. Story #4075 — extracted from
|
|
271
|
-
* `runEpicDeliverPrepare`.
|
|
272
|
-
*/
|
|
273
|
-
async function resolvePrepareState({ epicId, cwd, provider }) {
|
|
274
|
-
const cached = await readPreflightCache({ epicId, cwd });
|
|
275
|
-
if (cached) {
|
|
276
|
-
const freshEpic = await provider.getTicket(epicId);
|
|
277
|
-
const cachedStoryIds = cached.stories
|
|
278
|
-
.map((s) => Number(s?.id ?? s?.number))
|
|
279
|
-
.filter((id) => Number.isInteger(id) && id > 0);
|
|
280
|
-
const freshStories = await Promise.all(
|
|
281
|
-
cachedStoryIds.map((id) => provider.getTicket(id)),
|
|
282
|
-
);
|
|
283
|
-
const freshBaseSha = computeBaseSha(freshEpic, freshStories);
|
|
284
|
-
if (freshBaseSha === cached.baseSha) {
|
|
285
|
-
return {
|
|
286
|
-
state: {
|
|
287
|
-
epic: cached.epic,
|
|
288
|
-
stories: cached.stories,
|
|
289
|
-
waves: cached.waves,
|
|
290
|
-
},
|
|
291
|
-
cacheStatus: 'hit',
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
const ctx = { epicId, provider };
|
|
296
|
-
let state = await runSnapshotPhase(ctx, {}, {});
|
|
297
|
-
state = await runBuildWaveDagPhase(ctx, {}, state);
|
|
298
|
-
return { state, cacheStatus: cached ? 'stale' : 'miss' };
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Evaluate the cross-Story concurrency-hazard gate (Story #2297). Throws on a
|
|
303
|
-
* tripped, non-bypassed gate; warns (and returns `gate`) on a bypassed trip.
|
|
304
|
-
* Story #4075 — extracted from `runEpicDeliverPrepare`.
|
|
305
|
-
*/
|
|
306
|
-
function evaluatePrepareConcurrencyGate({
|
|
307
|
-
config,
|
|
308
|
-
waves,
|
|
309
|
-
injectedFindings,
|
|
310
|
-
ignoreConcurrencyHazards,
|
|
311
|
-
}) {
|
|
312
|
-
const findings = Array.isArray(injectedFindings) ? injectedFindings : [];
|
|
313
|
-
const pendingKeys = collectPendingStoryKeys(waves);
|
|
314
|
-
const pendingFindings = filterFindingsToPending(findings, pendingKeys);
|
|
315
|
-
const gate = evaluateConcurrencyGate({
|
|
316
|
-
findings: pendingFindings,
|
|
317
|
-
policy: {
|
|
318
|
-
failOnConcurrencyHazards:
|
|
319
|
-
config?.delivery?.failOnConcurrencyHazards === true,
|
|
320
|
-
},
|
|
321
|
-
ignore: ignoreConcurrencyHazards === true,
|
|
322
|
-
});
|
|
323
|
-
if (gate.tripped && !gate.bypassed) {
|
|
324
|
-
const ownerRepo =
|
|
325
|
-
config?.github?.owner && config?.github?.repo
|
|
326
|
-
? `${config.github.owner}/${config.github.repo}`
|
|
327
|
-
: undefined;
|
|
328
|
-
throw new Error(renderGateErrorMessage(gate.findings, ownerRepo));
|
|
329
|
-
}
|
|
330
|
-
if (gate.tripped && gate.bypassed) {
|
|
331
|
-
Logger.warn(
|
|
332
|
-
`[epic-deliver-prepare] ⚠️ Concurrency-hazard gate bypassed via --ignore-concurrency-hazards (reason=${gate.reason}, count=${gate.findings.length}).`,
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
return gate;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Build the per-Epic docs digest and write it to
|
|
340
|
-
* `<tempRoot>/epic-<id>/docs-digest.md`, returning its repo-relative path.
|
|
341
|
-
* Story #4338 — the parent threads this path into every child prompt so
|
|
342
|
-
* delivery sub-agents read one compact outline instead of re-ingesting the
|
|
343
|
-
* full `project.docsContextFiles` set per Story.
|
|
344
|
-
*
|
|
345
|
-
* Keyed off the **un-defaulted** config (`config.raw`): when the operator has
|
|
346
|
-
* not configured `project.docsContextFiles`, this returns `null` (no file
|
|
347
|
-
* written) rather than digesting the resolver's built-in default set — the
|
|
348
|
-
* digest is an opt-in surface for projects that curate their docs context.
|
|
349
|
-
*
|
|
350
|
-
* @param {{ epicId: number, cwd?: string, config: object }} args
|
|
351
|
-
* @returns {Promise<string|null>} repo-relative digest path, or null when
|
|
352
|
-
* `project.docsContextFiles` is empty/unset (or every file is missing).
|
|
353
|
-
*/
|
|
354
|
-
async function writeDocsDigest({ epicId, cwd, config }) {
|
|
355
|
-
const rawFiles = config?.raw?.project?.docsContextFiles;
|
|
356
|
-
const docsContextFiles = Array.isArray(rawFiles) ? rawFiles : [];
|
|
357
|
-
if (docsContextFiles.length === 0) return null;
|
|
358
|
-
|
|
359
|
-
const paths = getPaths(config);
|
|
360
|
-
const root = path.resolve(cwd ?? process.cwd());
|
|
361
|
-
const docsRoot = path.resolve(root, paths.docsRoot);
|
|
362
|
-
const relPath = path.join(paths.tempRoot, `epic-${epicId}`, 'docs-digest.md');
|
|
363
|
-
const absPath = path.resolve(root, relPath);
|
|
364
|
-
const result = await ensureDocsDigest({
|
|
365
|
-
docsContextFiles,
|
|
366
|
-
docsRoot,
|
|
367
|
-
outputPath: absPath,
|
|
368
|
-
});
|
|
369
|
-
return result ? relPath : null;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Thread footprint-matched **local**-lens authoring checklists into the
|
|
374
|
-
* per-Story dispatch entries (Epic #4405, Story #4410). For each planned Story,
|
|
375
|
-
* derive its predicted footprint from the full ticket body's `changes[]` /
|
|
376
|
-
* `references[]` entries, build the budget-capped checklist payload (matched by
|
|
377
|
-
* `resolveLensTier(lens) === 'local'` + `matchesAnyFilePattern` — NOT
|
|
378
|
-
* `selectAudits`, so no provider or git diff runs here), and write it to
|
|
379
|
-
* `<tempRoot>/epic-<id>/checklists/story-<sid>.md`. The parent threads the
|
|
380
|
-
* returned repo-relative `checklistPath` into that child's maker prompt, next
|
|
381
|
-
* to `docsDigestPath`; a Story that matches no local lens gets a `null` path
|
|
382
|
-
* and no file.
|
|
383
|
-
*
|
|
384
|
-
* @param {{
|
|
385
|
-
* epicId: number,
|
|
386
|
-
* cwd?: string,
|
|
387
|
-
* config: object,
|
|
388
|
-
* stories: Array<{ storyId: number, worktree?: string, title?: string }>,
|
|
389
|
-
* storyById: Map<number, object>,
|
|
390
|
-
* }} args
|
|
391
|
-
* @returns {Promise<Array<{ storyId: number, worktree?: string, title?: string, checklistPath: string|null }>>}
|
|
392
|
-
*/
|
|
393
|
-
export async function writeStoryChecklists({
|
|
394
|
-
epicId,
|
|
395
|
-
cwd,
|
|
396
|
-
config,
|
|
397
|
-
stories,
|
|
398
|
-
storyById,
|
|
399
|
-
buildPayload = buildChecklistPayload,
|
|
400
|
-
}) {
|
|
401
|
-
const paths = getPaths(config);
|
|
402
|
-
const root = path.resolve(cwd ?? process.cwd());
|
|
403
|
-
|
|
404
|
-
return Promise.all(
|
|
405
|
-
stories.map(async (entry) => {
|
|
406
|
-
const ticket = storyById.get(Number(entry.storyId));
|
|
407
|
-
const footprint = ticket
|
|
408
|
-
? collectStoryAssumptionEntries(ticket).map((e) => e.path)
|
|
409
|
-
: [];
|
|
410
|
-
const { payload } = buildPayload({ footprint, logger: Logger });
|
|
411
|
-
if (!payload) return { ...entry, checklistPath: null };
|
|
412
|
-
|
|
413
|
-
const relPath = path.join(
|
|
414
|
-
paths.tempRoot,
|
|
415
|
-
`epic-${epicId}`,
|
|
416
|
-
'checklists',
|
|
417
|
-
`story-${entry.storyId}.md`,
|
|
418
|
-
);
|
|
419
|
-
const absPath = path.resolve(root, relPath);
|
|
420
|
-
await fs.promises.mkdir(path.dirname(absPath), { recursive: true });
|
|
421
|
-
await fs.promises.writeFile(absPath, payload, 'utf-8');
|
|
422
|
-
return { ...entry, checklistPath: relPath };
|
|
423
|
-
}),
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
export async function runEpicDeliverPrepare({
|
|
428
|
-
epicId,
|
|
429
|
-
cwd,
|
|
430
|
-
injectedProvider,
|
|
431
|
-
injectedConfig,
|
|
432
|
-
injectedFindings,
|
|
433
|
-
ignoreConcurrencyHazards = false,
|
|
434
|
-
steal = false,
|
|
435
|
-
asOperator,
|
|
436
|
-
injectedGit,
|
|
437
|
-
injectedSweep,
|
|
438
|
-
leaseHeartbeatAt,
|
|
439
|
-
leaseNow,
|
|
440
|
-
skipPreflightGuards = false,
|
|
441
|
-
} = {}) {
|
|
442
|
-
if (!Number.isInteger(epicId) || epicId <= 0) {
|
|
443
|
-
throw new TypeError(
|
|
444
|
-
'runEpicDeliverPrepare: --epic must be a positive integer',
|
|
445
|
-
);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
const config = injectedConfig ?? resolveConfig({ cwd });
|
|
449
|
-
if (!config.github) {
|
|
450
|
-
throw new Error('runEpicDeliverPrepare: no github block in .agentrc.json');
|
|
451
|
-
}
|
|
452
|
-
const provider = injectedProvider ?? createProvider(config);
|
|
453
|
-
const { deliverRunner } = getRunners(config);
|
|
454
|
-
const concurrencyCap = deliverRunner.concurrencyCap;
|
|
455
|
-
|
|
456
|
-
await runPreflightGuardsForPrepare({
|
|
457
|
-
epicId,
|
|
458
|
-
cwd,
|
|
459
|
-
config,
|
|
460
|
-
provider,
|
|
461
|
-
injectedProvider,
|
|
462
|
-
injectedGit,
|
|
463
|
-
asOperator,
|
|
464
|
-
steal,
|
|
465
|
-
leaseHeartbeatAt,
|
|
466
|
-
leaseNow,
|
|
467
|
-
skipPreflightGuards,
|
|
468
|
-
});
|
|
469
|
-
|
|
470
|
-
await runBootSweepForPrepare({
|
|
471
|
-
cwd,
|
|
472
|
-
config,
|
|
473
|
-
provider,
|
|
474
|
-
injectedProvider,
|
|
475
|
-
injectedGit,
|
|
476
|
-
injectedSweep,
|
|
477
|
-
skipPreflightGuards,
|
|
478
|
-
});
|
|
479
|
-
|
|
480
|
-
const { state, cacheStatus } = await resolvePrepareState({
|
|
481
|
-
epicId,
|
|
482
|
-
cwd,
|
|
483
|
-
provider,
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
const gate = evaluatePrepareConcurrencyGate({
|
|
487
|
-
config,
|
|
488
|
-
waves: state.waves,
|
|
489
|
-
injectedFindings,
|
|
490
|
-
ignoreConcurrencyHazards,
|
|
491
|
-
});
|
|
492
|
-
|
|
493
|
-
// Flatten the wave-DAG into the open Story set. The ready-set runtime
|
|
494
|
-
// re-derives readiness from live labels on every tick, so the checkpoint
|
|
495
|
-
// stores only the Story set in scope (seeded at `pending`) and the global
|
|
496
|
-
// in-flight cap — no wave grouping, no `currentWave`, no `totalWaves`.
|
|
497
|
-
const openStories = state.waves.flat();
|
|
498
|
-
const checkpointState = await initializeEpicRunState({
|
|
499
|
-
provider,
|
|
500
|
-
epicId,
|
|
501
|
-
storyIds: openStories,
|
|
502
|
-
concurrencyCap,
|
|
503
|
-
});
|
|
504
|
-
|
|
505
|
-
// Resolve per-Story worktree paths via the launcher so the slash command
|
|
506
|
-
// has a deterministic `{ storyId, worktree, title }` list to seed Agent
|
|
507
|
-
// dispatch from. This is a dispatch *hint* — the ready-set tick decides
|
|
508
|
-
// which Stories to dispatch on each beat; the prepare only enumerates them.
|
|
509
|
-
const launcher = new StoryLauncher({ concurrencyCap });
|
|
510
|
-
const plannedStories = launcher.planWave(openStories).map((entry, i) => ({
|
|
511
|
-
...entry,
|
|
512
|
-
title: openStories[i]?.title ?? '',
|
|
513
|
-
}));
|
|
514
|
-
|
|
515
|
-
// Thread footprint-matched local-lens authoring checklists into each Story's
|
|
516
|
-
// dispatch entry (Story #4410). Keyed off the full discovered tickets (which
|
|
517
|
-
// carry the `changes[]`/`references[]` bodies the footprint is derived from);
|
|
518
|
-
// a Story that matches no local lens gets a `null` checklistPath.
|
|
519
|
-
const storyById = new Map(
|
|
520
|
-
(state.stories ?? []).map((t) => [Number(t.id ?? t.number), t]),
|
|
521
|
-
);
|
|
522
|
-
const stories = await writeStoryChecklists({
|
|
523
|
-
epicId,
|
|
524
|
-
cwd,
|
|
525
|
-
config,
|
|
526
|
-
stories: plannedStories,
|
|
527
|
-
storyById,
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
// Persist the `--ignore-concurrency-hazards` flag on the checkpoint so
|
|
531
|
-
// retro tooling can flag a run that shipped despite an outstanding hazard
|
|
532
|
-
// (the warning above is one-shot; the checkpoint is durable).
|
|
533
|
-
if (gate.bypassed) {
|
|
534
|
-
await writeEpicRunState({
|
|
535
|
-
provider,
|
|
536
|
-
epicId,
|
|
537
|
-
state: { ...checkpointState, ignoreConcurrencyHazards: true },
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
const docsDigestPath = await writeDocsDigest({ epicId, cwd, config });
|
|
542
|
-
|
|
543
|
-
return {
|
|
544
|
-
epicId,
|
|
545
|
-
storyCount: openStories.length,
|
|
546
|
-
concurrencyCap,
|
|
547
|
-
stories,
|
|
548
|
-
checkpointInitializedAt:
|
|
549
|
-
checkpointState.startedAt ??
|
|
550
|
-
checkpointState.lastUpdatedAt ??
|
|
551
|
-
new Date().toISOString(),
|
|
552
|
-
concurrencyHazardsBypassed: gate.bypassed,
|
|
553
|
-
preflightCache: cacheStatus,
|
|
554
|
-
docsDigestPath,
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
async function main() {
|
|
559
|
-
const { values } = parseArgs({
|
|
560
|
-
options: {
|
|
561
|
-
epic: { type: 'string' },
|
|
562
|
-
help: { type: 'boolean', short: 'h' },
|
|
563
|
-
'ignore-concurrency-hazards': { type: 'boolean', default: false },
|
|
564
|
-
steal: { type: 'boolean', default: false },
|
|
565
|
-
as: { type: 'string' },
|
|
566
|
-
},
|
|
567
|
-
strict: false,
|
|
568
|
-
});
|
|
569
|
-
|
|
570
|
-
if (values.help) {
|
|
571
|
-
Logger.info(HELP);
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
const epicId = Number.parseInt(values.epic ?? '', 10);
|
|
575
|
-
if (Number.isNaN(epicId) || epicId <= 0) {
|
|
576
|
-
Logger.error('[epic-deliver-prepare] ERROR: --epic <epicId> is required.');
|
|
577
|
-
Logger.error(HELP);
|
|
578
|
-
process.exit(2);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
const result = await runEpicDeliverPrepare({
|
|
582
|
-
epicId,
|
|
583
|
-
ignoreConcurrencyHazards: values['ignore-concurrency-hazards'] === true,
|
|
584
|
-
steal: values.steal === true,
|
|
585
|
-
asOperator: typeof values.as === 'string' ? values.as : undefined,
|
|
586
|
-
});
|
|
587
|
-
Logger.info(JSON.stringify(result, null, 2));
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
runAsCli(import.meta.url, main, { source: 'epic-deliver-prepare' });
|