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,97 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* plan-persist.js —
|
|
5
|
-
*
|
|
4
|
+
* plan-persist.js — flat Story GitHub-write surface for v2 `/plan`
|
|
5
|
+
* (Stage 3 — `docs/roadmap.md`).
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* (Tech Spec, optional Acceptance Table, risk verdict, tickets JSON), this
|
|
11
|
-
* CLI performs every GitHub mutation of the plan flow in one ordered,
|
|
12
|
-
* fail-closed pass:
|
|
7
|
+
* Given the author-written planning artifacts (`stories.json` +
|
|
8
|
+
* `risk-verdict.json`, optional shared Tech Spec), this CLI validates and
|
|
9
|
+
* creates Story issue(s) directly:
|
|
13
10
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* story
|
|
18
|
-
*
|
|
19
|
-
* `agent::review-spec`) → checkpoint v2 + `plan-summary` comment with
|
|
20
|
-
* the dry-run wave table → temp cleanup at terminal success only.
|
|
11
|
+
* risk-verdict → ticket validator / DAG / capacity → reachability →
|
|
12
|
+
* split-policy partition → fold/spill Spec into each Story body →
|
|
13
|
+
* createIssue(s) with type::story + agent::ready → risk-verdict +
|
|
14
|
+
* story-plan-state on every Story; plan-summary on the primary → temp
|
|
15
|
+
* cleanup.
|
|
21
16
|
*
|
|
22
|
-
*
|
|
23
|
-
* --
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* --
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* explicit (there is no Epic id to derive them from).
|
|
32
|
-
*
|
|
33
|
-
* Modes (Epic #4474 PR4, design §2 mode matrix): the risk verdict's
|
|
34
|
-
* optional `deliveryShape` field selects between the full fan-out persist
|
|
35
|
-
* (default; requires tickets) and the spec-only single-delivery variant
|
|
36
|
-
* (`deliveryShape: "single"`; NO tickets — the ticket validator + DAG are
|
|
37
|
-
* skipped, fenced by construction, and the `delivery::single` routing
|
|
38
|
-
* marker is applied instead of a Story tree; inert until #4475 lands the
|
|
39
|
-
* deliver-side reader). `--amend` selects the change-request delta path:
|
|
40
|
-
* tickets carry `op: add|modify|keep|close` and the persist maps the ops
|
|
41
|
-
* onto the existing tree.
|
|
42
|
-
*
|
|
43
|
-
* Flags:
|
|
44
|
-
* --force Deliberate re-persist: overwrite managed sections,
|
|
45
|
-
* close + recreate the story tree (reconciler
|
|
46
|
-
* --explicit-delete). Reuses on-disk artifacts —
|
|
47
|
-
* cleanup is deferred to terminal success, so a
|
|
48
|
-
* failed run leaves them in place.
|
|
49
|
-
* --resume Continue a partial persist after a crash
|
|
50
|
-
* (rate-limit, network): sections short-circuit
|
|
51
|
-
* idempotently, the reconciler creates only the
|
|
52
|
-
* missing slugs from its per-slug state ledger.
|
|
53
|
-
* --amend Change-request delta persist: every ticket carries
|
|
54
|
-
* `op: add|modify|keep|close`; close-and-recreate is
|
|
55
|
-
* scoped to modify/close slugs only, keeps are
|
|
56
|
-
* untouched, and the DAG is validated over the
|
|
57
|
-
* merged set.
|
|
58
|
-
* --explicit-delete Confirm the close ops of an --amend plan (mirrors
|
|
59
|
-
* epic-reconcile.js). Without it, an amend carrying
|
|
60
|
-
* close ops prints the dry-run diff and exits 2.
|
|
61
|
-
* --steal Force-transfer a live foreign Epic-lease claim.
|
|
62
|
-
* --force-review Operator-forced review routing (recorded in the
|
|
63
|
-
* checkpoint's reviewRouting envelope).
|
|
17
|
+
* CLI:
|
|
18
|
+
* --stories <file> Required Story ticket array (default length 1)
|
|
19
|
+
* --risk-verdict <file> Required risk verdict (no deliveryShape)
|
|
20
|
+
* --tech-spec <file> Optional shared Tech Spec folded into each Story
|
|
21
|
+
* --plan-dir <dir> Optional temp dir deleted at terminal success
|
|
22
|
+
* --plan-acceptance <file> Optional JSON string[] for partition coverage
|
|
23
|
+
* --plan-run-id <id> Optional plan-run token when N>1
|
|
24
|
+
* --dry-run Assemble + validate without GitHub writes
|
|
25
|
+
* --force-review Record operator-forced review routing
|
|
64
26
|
* --allow-over-budget / --allow-large-fan-out
|
|
65
|
-
* Same overrides as the retired split persist.
|
|
66
27
|
*
|
|
67
|
-
* Exit codes: 0
|
|
68
|
-
* error (see stderr); 2 — amend close ops require --explicit-delete (the
|
|
69
|
-
* dry-run diff is printed; nothing was mutated); 3 — reachability orphans
|
|
70
|
-
* (Epic #4474 PR6 named soft failure: the deterministic route-glob vs
|
|
71
|
-
* `planning.navigation.navRegistry` scan found route-adding draft stories
|
|
72
|
-
* with no navigation owner — the orphan-surface list is printed, nothing
|
|
73
|
-
* was mutated; apply one targeted amend and re-run the persist once). The
|
|
74
|
-
* Epic lease is released on every exit path.
|
|
28
|
+
* Exit codes: 0 success; 1 fatal; 3 reachability orphans (nothing mutated).
|
|
75
29
|
*/
|
|
76
30
|
|
|
77
|
-
// Fail-fast if the framework's runtime deps are not installed — must be the
|
|
78
|
-
// first import so the check runs before any third-party-importing sibling
|
|
79
|
-
// module is evaluated (Story #3432).
|
|
80
31
|
import './lib/runtime-deps/ensure-installed.js';
|
|
81
32
|
import { readFile } from 'node:fs/promises';
|
|
82
33
|
import path from 'node:path';
|
|
83
34
|
import { parseArgs } from 'node:util';
|
|
84
35
|
|
|
85
36
|
import { runAsCli } from './lib/cli-utils.js';
|
|
86
|
-
import { epicArtifactPath } from './lib/config/temp-paths.js';
|
|
87
37
|
import {
|
|
88
|
-
PROJECT_ROOT,
|
|
89
38
|
resolveConfig,
|
|
90
39
|
validateOrchestrationConfig,
|
|
91
40
|
} from './lib/config-resolver.js';
|
|
92
41
|
import { Logger } from './lib/Logger.js';
|
|
93
|
-
import { drainPendingCleanupAtBoot } from './lib/orchestration/epic-plan-spec/phases/drain.js';
|
|
94
|
-
import { loadRiskVerdict } from './lib/orchestration/epic-plan-spec/phases/risk-verdict.js';
|
|
95
42
|
import {
|
|
96
43
|
readPlanMetrics,
|
|
97
44
|
recordPlanInvocation,
|
|
@@ -99,7 +46,6 @@ import {
|
|
|
99
46
|
summarizePlanMetrics,
|
|
100
47
|
} from './lib/orchestration/plan-metrics.js';
|
|
101
48
|
import {
|
|
102
|
-
resolveDeliveryMode,
|
|
103
49
|
runPlanPersist,
|
|
104
50
|
writeCheckpointV2,
|
|
105
51
|
} from './lib/orchestration/plan-persist/run-plan-persist.js';
|
|
@@ -108,128 +54,139 @@ import {
|
|
|
108
54
|
buildWaveTable,
|
|
109
55
|
PLAN_SUMMARY_COMMENT_TYPE,
|
|
110
56
|
} from './lib/orchestration/plan-persist/summary.js';
|
|
57
|
+
import { loadRiskVerdict } from './lib/orchestration/planning/risk-verdict.js';
|
|
111
58
|
import { createProvider } from './lib/provider-factory.js';
|
|
112
59
|
|
|
113
|
-
// Re-exports for the stable public API (tests import through the CLI
|
|
114
|
-
// module, mirroring the plan-context.js CLI-shell shape).
|
|
115
60
|
export {
|
|
116
61
|
buildPlanSummaryCommentBody,
|
|
117
62
|
buildWaveTable,
|
|
118
63
|
PLAN_SUMMARY_COMMENT_TYPE,
|
|
119
|
-
resolveDeliveryMode,
|
|
120
64
|
runPlanPersist,
|
|
121
65
|
writeCheckpointV2,
|
|
122
66
|
};
|
|
123
67
|
|
|
124
|
-
export const EPIC_FROM_IDEA_TEMPLATE_PATH = path.resolve(
|
|
125
|
-
PROJECT_ROOT,
|
|
126
|
-
'.agents',
|
|
127
|
-
'templates',
|
|
128
|
-
'epic-from-idea.md',
|
|
129
|
-
);
|
|
130
|
-
|
|
131
68
|
const CLI_OPTIONS = {
|
|
132
|
-
|
|
133
|
-
'one-pager': { type: 'string' },
|
|
134
|
-
'tech-spec': { type: 'string' },
|
|
135
|
-
'acceptance-table': { type: 'string' },
|
|
69
|
+
stories: { type: 'string' },
|
|
136
70
|
'risk-verdict': { type: 'string' },
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
71
|
+
'tech-spec': { type: 'string' },
|
|
72
|
+
'plan-dir': { type: 'string' },
|
|
73
|
+
'plan-acceptance': { type: 'string' },
|
|
74
|
+
'plan-run-id': { type: 'string' },
|
|
75
|
+
'dry-run': { type: 'boolean', default: false },
|
|
141
76
|
'force-review': { type: 'boolean', default: false },
|
|
142
77
|
'allow-over-budget': { type: 'boolean', default: false },
|
|
143
78
|
'allow-large-fan-out': { type: 'boolean', default: false },
|
|
144
|
-
amend: { type: 'boolean', default: false },
|
|
145
|
-
'explicit-delete': { type: 'boolean', default: false },
|
|
146
79
|
};
|
|
147
80
|
|
|
148
81
|
const USAGE =
|
|
149
|
-
'Usage: plan-persist.js
|
|
150
|
-
'[--tech-spec <file>] [--
|
|
151
|
-
'[--
|
|
152
|
-
'[--
|
|
82
|
+
'Usage: plan-persist.js --stories <file> --risk-verdict <file> ' +
|
|
83
|
+
'[--tech-spec <file>] [--plan-dir <dir>] [--plan-acceptance <file>] ' +
|
|
84
|
+
'[--plan-run-id <id>] [--dry-run] [--force-review] ' +
|
|
85
|
+
'[--allow-over-budget] [--allow-large-fan-out]';
|
|
153
86
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (Number.isNaN(epicId)) {
|
|
161
|
-
throw new Error(
|
|
162
|
-
`Invalid epic ID: "${rawEpic}" — must be a number.\n${USAGE}`,
|
|
163
|
-
);
|
|
87
|
+
async function readOptional(filePath, { required }) {
|
|
88
|
+
try {
|
|
89
|
+
return await readFile(filePath, 'utf8');
|
|
90
|
+
} catch (err) {
|
|
91
|
+
if (!required && err?.code === 'ENOENT') return null;
|
|
92
|
+
throw new Error(`Cannot read ${filePath}: ${err.message}`);
|
|
164
93
|
}
|
|
165
|
-
return epicId;
|
|
166
94
|
}
|
|
167
95
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
* deferred). Ideation mode has no Epic id to derive from, so the paths must
|
|
174
|
-
* be explicit.
|
|
175
|
-
*/
|
|
176
|
-
function resolveArtifactPaths({ epicId, values, config }) {
|
|
177
|
-
const fallback = (basename) =>
|
|
178
|
-
epicId === null ? undefined : epicArtifactPath(epicId, basename, config);
|
|
179
|
-
const techSpecPath = values['tech-spec'] ?? fallback('techspec.md');
|
|
180
|
-
const riskVerdictPath =
|
|
181
|
-
values['risk-verdict'] ?? fallback('risk-verdict.json');
|
|
182
|
-
const ticketsPath = values.tickets ?? fallback('tickets.json');
|
|
183
|
-
const acceptancePath =
|
|
184
|
-
values['acceptance-table'] ?? fallback('acceptance-spec.md');
|
|
185
|
-
if (!techSpecPath || !riskVerdictPath) {
|
|
96
|
+
async function readJsonFile(filePath, label) {
|
|
97
|
+
const raw = await readOptional(filePath, { required: true });
|
|
98
|
+
try {
|
|
99
|
+
return JSON.parse(raw);
|
|
100
|
+
} catch (err) {
|
|
186
101
|
throw new Error(
|
|
187
|
-
`
|
|
102
|
+
`Failed to parse ${label} file "${filePath}" as JSON: ${err.message}`,
|
|
188
103
|
);
|
|
189
104
|
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function resolveInputPaths(values) {
|
|
190
108
|
return {
|
|
191
|
-
|
|
192
|
-
riskVerdictPath,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
109
|
+
storiesPath: path.resolve(values.stories),
|
|
110
|
+
riskVerdictPath: path.resolve(values['risk-verdict']),
|
|
111
|
+
techSpecPath: values['tech-spec']
|
|
112
|
+
? path.resolve(values['tech-spec'])
|
|
113
|
+
: null,
|
|
114
|
+
planAcceptancePath: values['plan-acceptance']
|
|
115
|
+
? path.resolve(values['plan-acceptance'])
|
|
116
|
+
: null,
|
|
117
|
+
planDir: values['plan-dir'] ? path.resolve(values['plan-dir']) : null,
|
|
197
118
|
};
|
|
198
119
|
}
|
|
199
120
|
|
|
200
|
-
async function
|
|
121
|
+
async function loadArtifacts(paths) {
|
|
122
|
+
const riskVerdict = loadRiskVerdict(paths.riskVerdictPath);
|
|
123
|
+
const stories = await readJsonFile(paths.storiesPath, 'stories');
|
|
124
|
+
const techSpecContent = paths.techSpecPath
|
|
125
|
+
? await readOptional(paths.techSpecPath, { required: true })
|
|
126
|
+
: null;
|
|
127
|
+
const planAcceptance = paths.planAcceptancePath
|
|
128
|
+
? await readJsonFile(paths.planAcceptancePath, 'plan-acceptance')
|
|
129
|
+
: null;
|
|
130
|
+
|
|
131
|
+
return { stories, riskVerdict, techSpecContent, planAcceptance };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function buildPersistOptions(values, paths) {
|
|
135
|
+
return {
|
|
136
|
+
forceReview: values['force-review'],
|
|
137
|
+
allowOverBudget: values['allow-over-budget'],
|
|
138
|
+
allowLargeFanOut: values['allow-large-fan-out'],
|
|
139
|
+
dryRun: values['dry-run'],
|
|
140
|
+
planRunId: values['plan-run-id'],
|
|
141
|
+
planDir: paths.planDir,
|
|
142
|
+
skipCleanup: values['dry-run'],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function runPersistInvocation({ values, config, provider, artifacts }) {
|
|
147
|
+
const paths = resolveInputPaths(values);
|
|
148
|
+
const settings = {
|
|
149
|
+
baseBranch: config.project?.baseBranch,
|
|
150
|
+
paths: config.project?.paths,
|
|
151
|
+
planning: config.planning,
|
|
152
|
+
docsContextFiles: config.project?.docsContextFiles,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
return recordPlanInvocation(
|
|
156
|
+
{
|
|
157
|
+
cli: 'plan-persist',
|
|
158
|
+
mode: values['dry-run'] ? 'dry-run' : 'persist',
|
|
159
|
+
config,
|
|
160
|
+
},
|
|
161
|
+
() =>
|
|
162
|
+
runPlanPersist({
|
|
163
|
+
provider,
|
|
164
|
+
artifacts,
|
|
165
|
+
config,
|
|
166
|
+
settings,
|
|
167
|
+
opts: buildPersistOptions(values, paths),
|
|
168
|
+
}),
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function attachPlanMetrics(result, config) {
|
|
201
173
|
try {
|
|
202
|
-
|
|
174
|
+
const summary = summarizePlanMetrics(await readPlanMetrics(config));
|
|
175
|
+
if (summary) {
|
|
176
|
+
result.planMetrics = summary;
|
|
177
|
+
Logger.info(`[plan-persist] ${renderPlanMetricsSummaryLine(summary)}`);
|
|
178
|
+
}
|
|
203
179
|
} catch (err) {
|
|
204
|
-
|
|
205
|
-
throw new Error(`Cannot read ${filePath}: ${err.message}`);
|
|
180
|
+
Logger.warn(`[plan-persist] plan-metrics summary skipped: ${err.message}`);
|
|
206
181
|
}
|
|
207
182
|
}
|
|
208
183
|
|
|
209
184
|
async function main() {
|
|
210
185
|
const { values } = parseArgs({ options: CLI_OPTIONS });
|
|
211
186
|
|
|
212
|
-
if (values.
|
|
213
|
-
throw new Error('--force and --resume are mutually exclusive.');
|
|
214
|
-
}
|
|
215
|
-
if (values.amend && (values.force || values.resume)) {
|
|
216
|
-
throw new Error(
|
|
217
|
-
'--amend is mutually exclusive with --force/--resume — the amend ' +
|
|
218
|
-
'delta is already an incremental re-persist.',
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const epicId = parseEpicId(values.epic);
|
|
223
|
-
const onePagerPath = values['one-pager'];
|
|
224
|
-
if (epicId === null && !onePagerPath) {
|
|
187
|
+
if (!values.stories || !values['risk-verdict']) {
|
|
225
188
|
throw new Error(USAGE);
|
|
226
189
|
}
|
|
227
|
-
if (epicId !== null && onePagerPath) {
|
|
228
|
-
throw new Error(
|
|
229
|
-
'--epic and --one-pager are mutually exclusive (ideation mode opens ' +
|
|
230
|
-
`the Epic itself).\n${USAGE}`,
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
190
|
|
|
234
191
|
let config;
|
|
235
192
|
try {
|
|
@@ -238,123 +195,19 @@ async function main() {
|
|
|
238
195
|
} catch (err) {
|
|
239
196
|
throw new Error(`Config schema validation failed:\n${err.message}`);
|
|
240
197
|
}
|
|
241
|
-
const settings = {
|
|
242
|
-
baseBranch: config.project?.baseBranch,
|
|
243
|
-
paths: config.project?.paths,
|
|
244
|
-
planning: config.planning,
|
|
245
|
-
docsContextFiles: config.project?.docsContextFiles,
|
|
246
|
-
};
|
|
247
198
|
const provider = createProvider(config);
|
|
199
|
+
const paths = resolveInputPaths(values);
|
|
200
|
+
const artifacts = await loadArtifacts(paths);
|
|
248
201
|
|
|
202
|
+
let result;
|
|
249
203
|
try {
|
|
250
|
-
await
|
|
251
|
-
|
|
204
|
+
result = await runPersistInvocation({
|
|
205
|
+
values,
|
|
252
206
|
config,
|
|
253
207
|
provider,
|
|
208
|
+
artifacts,
|
|
254
209
|
});
|
|
255
210
|
} catch (err) {
|
|
256
|
-
Logger.warn(`[plan-persist] pending-cleanup drain skipped: ${err.message}`);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const {
|
|
260
|
-
techSpecPath,
|
|
261
|
-
riskVerdictPath,
|
|
262
|
-
ticketsPath,
|
|
263
|
-
acceptancePath,
|
|
264
|
-
acceptanceExplicit,
|
|
265
|
-
ticketsExplicit,
|
|
266
|
-
} = resolveArtifactPaths({ epicId, values, config });
|
|
267
|
-
|
|
268
|
-
// Deterministic local reads + validation before any GitHub call. A
|
|
269
|
-
// malformed risk verdict fails closed here (Epic #3865); the section
|
|
270
|
-
// gate itself runs first inside runPlanPersist.
|
|
271
|
-
const techSpecContent = await readOptional(techSpecPath, { required: true });
|
|
272
|
-
const riskVerdict = loadRiskVerdict(riskVerdictPath);
|
|
273
|
-
// Tickets are mode-dependent (#4474 PR4): required when explicitly
|
|
274
|
-
// passed or in --amend mode; otherwise best-effort — a single-delivery
|
|
275
|
-
// plan authors no tickets file at all, and the mode-coherence gate
|
|
276
|
-
// (`resolveDeliveryMode`) hard-errors on every contradictory combination
|
|
277
|
-
// (including a stale tickets.json next to a `deliveryShape: "single"`
|
|
278
|
-
// verdict).
|
|
279
|
-
const ticketsRequired = ticketsExplicit || values.amend;
|
|
280
|
-
const ticketsRaw = ticketsPath
|
|
281
|
-
? await readOptional(ticketsPath, { required: ticketsRequired })
|
|
282
|
-
: null;
|
|
283
|
-
let tickets = null;
|
|
284
|
-
if (ticketsRaw !== null) {
|
|
285
|
-
try {
|
|
286
|
-
tickets = JSON.parse(ticketsRaw);
|
|
287
|
-
} catch (err) {
|
|
288
|
-
throw new Error(
|
|
289
|
-
`Failed to parse tickets file "${ticketsPath}" as JSON: ${err.message}`,
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
// Acceptance table: explicit path is required to exist; the per-Epic
|
|
294
|
-
// default is best-effort (absent file → no acceptance section, matching
|
|
295
|
-
// the waived/none dispositions).
|
|
296
|
-
const acceptanceSpecContent = acceptancePath
|
|
297
|
-
? await readOptional(acceptancePath, { required: acceptanceExplicit })
|
|
298
|
-
: null;
|
|
299
|
-
const onePagerContent = onePagerPath
|
|
300
|
-
? await readOptional(onePagerPath, { required: true })
|
|
301
|
-
: null;
|
|
302
|
-
const templateContent = onePagerContent
|
|
303
|
-
? await readOptional(EPIC_FROM_IDEA_TEMPLATE_PATH, { required: true })
|
|
304
|
-
: null;
|
|
305
|
-
|
|
306
|
-
// Plan-metrics ledger (#4474 PR1): stamp entry/exit + mode. Ideation runs
|
|
307
|
-
// have no Epic id at entry, so they stamp on the standalone stream.
|
|
308
|
-
const mode = values.amend
|
|
309
|
-
? 'amend'
|
|
310
|
-
: values.resume
|
|
311
|
-
? 'resume'
|
|
312
|
-
: values.force
|
|
313
|
-
? 'force'
|
|
314
|
-
: 'persist';
|
|
315
|
-
let result;
|
|
316
|
-
try {
|
|
317
|
-
result = await recordPlanInvocation(
|
|
318
|
-
{ cli: 'plan-persist', mode, epicId, config },
|
|
319
|
-
() =>
|
|
320
|
-
runPlanPersist({
|
|
321
|
-
epicId,
|
|
322
|
-
provider,
|
|
323
|
-
artifacts: {
|
|
324
|
-
techSpecContent,
|
|
325
|
-
acceptanceSpecContent,
|
|
326
|
-
riskVerdict,
|
|
327
|
-
tickets,
|
|
328
|
-
onePagerContent,
|
|
329
|
-
templateContent,
|
|
330
|
-
},
|
|
331
|
-
config,
|
|
332
|
-
settings,
|
|
333
|
-
opts: {
|
|
334
|
-
force: values.force,
|
|
335
|
-
resume: values.resume,
|
|
336
|
-
amend: values.amend,
|
|
337
|
-
explicitDelete: values['explicit-delete'],
|
|
338
|
-
steal: values.steal,
|
|
339
|
-
forceReview: values['force-review'],
|
|
340
|
-
allowOverBudget: values['allow-over-budget'],
|
|
341
|
-
allowLargeFanOut: values['allow-large-fan-out'],
|
|
342
|
-
},
|
|
343
|
-
}),
|
|
344
|
-
);
|
|
345
|
-
} catch (err) {
|
|
346
|
-
// Amend close-op confirmation gate (exit 2, mirroring the
|
|
347
|
-
// epic-reconcile.js contract): print the dry-run diff so the operator
|
|
348
|
-
// reviews exactly what would close, mutate nothing, and exit 2 so
|
|
349
|
-
// non-interactive callers can branch on the code.
|
|
350
|
-
if (err?.code === 'PLAN_AMEND_EXPLICIT_DELETE_REQUIRED') {
|
|
351
|
-
process.stdout.write(`${err.diff}\n\n${err.message}\n`);
|
|
352
|
-
process.exitCode = 2;
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
// Reachability soft failure (#4474 PR6): the orphan-surface list is the
|
|
356
|
-
// message; nothing was mutated (the check runs before any provider
|
|
357
|
-
// call). Exit 3 so non-interactive callers can branch on the code.
|
|
358
211
|
if (err?.code === 'PLAN_REACHABILITY_ORPHANS') {
|
|
359
212
|
process.stdout.write(`${err.message}\n`);
|
|
360
213
|
process.exitCode = 3;
|
|
@@ -363,19 +216,7 @@ async function main() {
|
|
|
363
216
|
throw err;
|
|
364
217
|
}
|
|
365
218
|
|
|
366
|
-
|
|
367
|
-
// (#4474 PR1). Additive and best-effort.
|
|
368
|
-
try {
|
|
369
|
-
const summary = summarizePlanMetrics(
|
|
370
|
-
await readPlanMetrics(result.epicId, config),
|
|
371
|
-
);
|
|
372
|
-
if (summary) {
|
|
373
|
-
result.planMetrics = summary;
|
|
374
|
-
Logger.info(`[plan-persist] ${renderPlanMetricsSummaryLine(summary)}`);
|
|
375
|
-
}
|
|
376
|
-
} catch (err) {
|
|
377
|
-
Logger.warn(`[plan-persist] plan-metrics summary skipped: ${err.message}`);
|
|
378
|
-
}
|
|
219
|
+
await attachPlanMetrics(result, config);
|
|
379
220
|
|
|
380
221
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
381
222
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* plan-run-epilogue.js — execute the real per-run closeout for
|
|
4
|
+
* `/deliver --run <planRunId>` and positional multi-Story delivers.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node .agents/scripts/plan-run-epilogue.js --run <planRunId>
|
|
8
|
+
* node .agents/scripts/plan-run-epilogue.js --run <planRunId> --stories 1,2,3
|
|
9
|
+
* node .agents/scripts/plan-run-epilogue.js --stories 1,2,3
|
|
10
|
+
*
|
|
11
|
+
* When `--stories` is omitted, `--run` is required and the set is resolved
|
|
12
|
+
* via plan-run labels (`state=all` so landed Stories are included).
|
|
13
|
+
* When `--stories` is supplied without `--run`, an adhoc planRunId is
|
|
14
|
+
* synthesized from the sorted Story ids.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import './lib/runtime-deps/ensure-installed.js';
|
|
18
|
+
import { parseArgs } from 'node:util';
|
|
19
|
+
|
|
20
|
+
import { runAsCli } from './lib/cli-utils.js';
|
|
21
|
+
import { resolveConfig } from './lib/config-resolver.js';
|
|
22
|
+
import { Logger } from './lib/Logger.js';
|
|
23
|
+
import {
|
|
24
|
+
fetchPlanRunIssues,
|
|
25
|
+
normalizePlanRunLabel,
|
|
26
|
+
resolvePlanRunFromIssues,
|
|
27
|
+
} from './lib/orchestration/resolve-plan-run.js';
|
|
28
|
+
import { runPlanRunEpilogue } from './lib/orchestration/run-epilogue.js';
|
|
29
|
+
import { createProvider } from './lib/provider-factory.js';
|
|
30
|
+
|
|
31
|
+
const CLI_OPTIONS = {
|
|
32
|
+
run: { type: 'string' },
|
|
33
|
+
stories: { type: 'string' },
|
|
34
|
+
cwd: { type: 'string' },
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {string[]} [argv]
|
|
39
|
+
* @returns {Promise<object>}
|
|
40
|
+
*/
|
|
41
|
+
export async function main(argv = process.argv.slice(2)) {
|
|
42
|
+
const { values } = parseArgs({
|
|
43
|
+
args: argv,
|
|
44
|
+
options: CLI_OPTIONS,
|
|
45
|
+
strict: false,
|
|
46
|
+
});
|
|
47
|
+
const runFlag = typeof values.run === 'string' ? values.run.trim() : '';
|
|
48
|
+
const hasStoriesFlag =
|
|
49
|
+
typeof values.stories === 'string' && values.stories.trim().length > 0;
|
|
50
|
+
if (!runFlag && !hasStoriesFlag) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
'Usage: node plan-run-epilogue.js (--run <planRunId> | --stories 1,2,3) [--stories 1,2,3]',
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
const cwd =
|
|
56
|
+
typeof values.cwd === 'string' && values.cwd.trim()
|
|
57
|
+
? values.cwd.trim()
|
|
58
|
+
: process.cwd();
|
|
59
|
+
const config = resolveConfig({ cwd });
|
|
60
|
+
const provider = createProvider(config);
|
|
61
|
+
|
|
62
|
+
let stories = [];
|
|
63
|
+
if (hasStoriesFlag) {
|
|
64
|
+
stories = values.stories
|
|
65
|
+
.split(',')
|
|
66
|
+
.map((s) => Number(s.trim()))
|
|
67
|
+
.filter((n) => Number.isInteger(n) && n > 0);
|
|
68
|
+
} else {
|
|
69
|
+
const planRunLabel = normalizePlanRunLabel(runFlag);
|
|
70
|
+
const issues = await fetchPlanRunIssues(provider, {
|
|
71
|
+
planRunLabel,
|
|
72
|
+
state: 'all',
|
|
73
|
+
});
|
|
74
|
+
const envelope = resolvePlanRunFromIssues({ run: runFlag, issues });
|
|
75
|
+
stories = (envelope.stories ?? [])
|
|
76
|
+
.map((s) => Number(s?.id ?? s))
|
|
77
|
+
.filter((n) => Number.isInteger(n) && n > 0);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const planRunId =
|
|
81
|
+
runFlag || `adhoc-${[...stories].sort((a, b) => a - b).join('-')}`;
|
|
82
|
+
|
|
83
|
+
const result = await runPlanRunEpilogue({
|
|
84
|
+
planRunId,
|
|
85
|
+
stories,
|
|
86
|
+
provider,
|
|
87
|
+
config,
|
|
88
|
+
cwd,
|
|
89
|
+
});
|
|
90
|
+
Logger.info(JSON.stringify(result, null, 2));
|
|
91
|
+
if (result.errors?.length) {
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
await runAsCli(import.meta.url, main);
|
|
@@ -22,6 +22,10 @@ import fs from 'node:fs/promises';
|
|
|
22
22
|
import { parseArgs } from 'node:util';
|
|
23
23
|
import { runAsCli } from './lib/cli-utils.js';
|
|
24
24
|
import { resolveConfig } from './lib/config-resolver.js';
|
|
25
|
+
import {
|
|
26
|
+
outboxPathFor,
|
|
27
|
+
postCommentOrBuffer,
|
|
28
|
+
} from './lib/orchestration/bookkeeping-outbox.js';
|
|
25
29
|
import {
|
|
26
30
|
assertValidStructuredCommentType,
|
|
27
31
|
upsertStructuredComment,
|
|
@@ -37,6 +41,11 @@ Flags:
|
|
|
37
41
|
retro, epic-run-state, wave-0-start) (required).
|
|
38
42
|
--body-file Path to a file containing the markdown body (required).
|
|
39
43
|
--provider Provider name (default: inferred from .agentrc.json github block).
|
|
44
|
+
--buffer Headless mode: buffer this upsert to the per-Epic bookkeeping
|
|
45
|
+
outbox instead of posting live. Requires --epic. Drained to
|
|
46
|
+
GitHub once at finalize by bookkeeping-reconcile.js (Epic
|
|
47
|
+
#4476). Omit for attended runs (posts live, unchanged).
|
|
48
|
+
--epic <id> Epic id owning the outbox (required with --buffer).
|
|
40
49
|
--help Show this message.
|
|
41
50
|
`;
|
|
42
51
|
|
|
@@ -64,6 +73,8 @@ export function parseArgv(argv) {
|
|
|
64
73
|
marker: { type: 'string' },
|
|
65
74
|
'body-file': { type: 'string' },
|
|
66
75
|
provider: { type: 'string' },
|
|
76
|
+
buffer: { type: 'boolean' },
|
|
77
|
+
epic: { type: 'string' },
|
|
67
78
|
help: { type: 'boolean' },
|
|
68
79
|
},
|
|
69
80
|
strict: false,
|
|
@@ -115,6 +126,33 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
115
126
|
: config;
|
|
116
127
|
const provider = createProvider(effectiveConfig);
|
|
117
128
|
|
|
129
|
+
// Headless buffering (Epic #4476 M5): route the upsert to the per-Epic
|
|
130
|
+
// outbox instead of a live GitHub round-trip. Requires --epic to locate the
|
|
131
|
+
// outbox; finalize's bookkeeping-reconcile.js drains it once. Attended runs
|
|
132
|
+
// (no --buffer) are unchanged.
|
|
133
|
+
if (values.buffer) {
|
|
134
|
+
const epicId = Number.parseInt(values.epic ?? '', 10);
|
|
135
|
+
if (!Number.isInteger(epicId) || epicId <= 0) {
|
|
136
|
+
process.stderr.write(
|
|
137
|
+
'[post-structured-comment] --buffer requires --epic <id>.\n',
|
|
138
|
+
);
|
|
139
|
+
process.exit(2);
|
|
140
|
+
}
|
|
141
|
+
assertValidStructuredCommentType(values.marker);
|
|
142
|
+
const { buffered } = await postCommentOrBuffer({
|
|
143
|
+
provider,
|
|
144
|
+
ticketId,
|
|
145
|
+
marker: values.marker,
|
|
146
|
+
body,
|
|
147
|
+
headless: true,
|
|
148
|
+
outboxPath: outboxPathFor(epicId, config),
|
|
149
|
+
});
|
|
150
|
+
process.stdout.write(
|
|
151
|
+
`${JSON.stringify({ success: true, ticketId, type: values.marker, buffered })}\n`,
|
|
152
|
+
);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
118
156
|
const envelope = await runPostStructuredComment({
|
|
119
157
|
ticketId,
|
|
120
158
|
type: values.marker,
|