mandrel 1.94.0 → 2.1.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 +116 -99
- package/.agents/agents/acceptance-critic.md +9 -7
- package/.agents/agents/story-worker.md +45 -51
- package/.agents/audit-checklists/performance.md +1 -1
- package/.agents/docs/SDLC.md +498 -1287
- package/.agents/docs/agentrc-reference.json +185 -80
- package/.agents/docs/configuration.md +132 -190
- package/.agents/docs/execution-reference.md +51 -25
- package/.agents/docs/quality-gates.md +25 -33
- package/.agents/docs/workflows.md +8 -8
- package/.agents/instructions.md +113 -139
- package/.agents/rules/ci-remediation.md +11 -15
- package/.agents/rules/git-conventions-reference.md +48 -58
- package/.agents/rules/git-conventions.md +16 -22
- package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
- package/.agents/schemas/agentrc.schema.json +83 -254
- package/.agents/schemas/audit-rules.json +59 -1
- package/.agents/schemas/audit-rules.schema.json +33 -1
- package/.agents/schemas/lifecycle/README.md +1 -2
- package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
- package/.agents/schemas/lifecycle/merge.flip-failed.schema.json +33 -0
- package/.agents/schemas/lifecycle/merge.unlanded.schema.json +1 -0
- package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
- package/.agents/schemas/lifecycle/story.merged.schema.json +1 -1
- package/.agents/schemas/signal-event.schema.json +3 -3
- package/.agents/schemas/story-deliver-terminal.schema.json +152 -0
- package/.agents/schemas/validation-evidence.schema.json +1 -1
- package/.agents/scripts/acceptance-eval.js +22 -66
- package/.agents/scripts/agents-bootstrap-github.js +1 -1
- package/.agents/scripts/audit-to-stories.js +7 -7
- package/.agents/scripts/boot-sweep.js +1 -1
- package/.agents/scripts/bootstrap.js +3 -3
- package/.agents/scripts/check-dead-exports.js +43 -104
- package/.agents/scripts/check-doc-links.js +2 -2
- package/.agents/scripts/check-lifecycle-lint.js +7 -10
- package/.agents/scripts/check-workflow-cli-lint.js +91 -0
- package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
- package/.agents/scripts/deliver-recover.js +122 -0
- package/.agents/scripts/drain-pending-cleanup.js +1 -1
- package/.agents/scripts/evidence-gate.js +20 -50
- package/.agents/scripts/generate-skills-index.js +17 -1
- package/.agents/scripts/generate-workflows-doc.js +4 -4
- package/.agents/scripts/lib/ITicketingProvider.js +1 -19
- 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 +328 -28
- 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 -15
- package/.agents/scripts/lib/baselines/reader.js +1 -6
- package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
- package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +28 -33
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
- package/.agents/scripts/lib/bootstrap/manifest.js +8 -11
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +30 -53
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +0 -2
- package/.agents/scripts/lib/checks/core-bare-clean.js +6 -3
- package/.agents/scripts/lib/checks/index.js +3 -2
- package/.agents/scripts/lib/checks/loop-health.js +12 -11
- package/.agents/scripts/lib/checks/state.js +17 -248
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +26 -24
- package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +3 -4
- package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +2 -2
- package/.agents/scripts/lib/checks/worktree-residue-biome.js +3 -3
- package/.agents/scripts/lib/cli/standard-args.js +13 -22
- package/.agents/scripts/lib/cli-args.js +39 -9
- package/.agents/scripts/lib/close-validation/gates.js +15 -15
- package/.agents/scripts/lib/close-validation/projections/inputs.js +7 -7
- package/.agents/scripts/lib/close-validation/projections/maintainability.js +12 -12
- package/.agents/scripts/lib/close-validation/runner.js +13 -21
- package/.agents/scripts/lib/close-validation/telemetry.js +17 -8
- package/.agents/scripts/lib/config/ci.js +6 -31
- package/.agents/scripts/lib/config/delivery-routing.js +52 -35
- package/.agents/scripts/lib/config/explain.js +61 -48
- package/.agents/scripts/lib/config/github.js +7 -5
- package/.agents/scripts/lib/config/limits.js +29 -80
- package/.agents/scripts/lib/config/paths.js +0 -2
- package/.agents/scripts/lib/config/quality.js +12 -15
- package/.agents/scripts/lib/config/runners.js +20 -66
- package/.agents/scripts/lib/config/temp-paths.js +30 -63
- package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
- package/.agents/scripts/lib/config-resolver.js +2 -7
- package/.agents/scripts/lib/config-settings-schema-delivery.js +55 -161
- package/.agents/scripts/lib/config-settings-schema-quality.js +17 -16
- package/.agents/scripts/lib/config-settings-schema.js +100 -60
- package/.agents/scripts/lib/dead-exports-knip.js +105 -0
- package/.agents/scripts/lib/dead-exports-mode.js +51 -0
- package/.agents/scripts/lib/dependency-parser.js +3 -2
- package/.agents/scripts/lib/doc-tiers.js +2 -2
- package/.agents/scripts/lib/duplicate-search.js +242 -41
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
- package/.agents/scripts/lib/findings/promote-finding.js +23 -14
- package/.agents/scripts/lib/format-generated-json.js +97 -0
- package/.agents/scripts/lib/framework-version.js +19 -190
- package/.agents/scripts/lib/gh-exec.js +8 -0
- package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
- package/.agents/scripts/lib/git-branch-lifecycle.js +17 -180
- package/.agents/scripts/lib/git-utils.js +32 -20
- package/.agents/scripts/lib/github/framework-repo.js +6 -0
- package/.agents/scripts/lib/json-utils.js +1 -2
- package/.agents/scripts/lib/label-constants.js +10 -38
- package/.agents/scripts/lib/label-taxonomy.js +10 -55
- package/.agents/scripts/lib/observability/active-story-env.js +44 -165
- package/.agents/scripts/lib/observability/runtime-friction.js +243 -0
- package/.agents/scripts/lib/observability/signal-validator.js +4 -4
- package/.agents/scripts/lib/observability/signals-writer.js +6 -82
- package/.agents/scripts/lib/observability/source-classifier.js +5 -5
- package/.agents/scripts/lib/observability/tool-trace-hook.js +2 -12
- package/.agents/scripts/lib/onboard/init-tail.js +1 -3
- package/.agents/scripts/lib/orchestration/acceptance-clusters.js +1 -1
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +2 -2
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +105 -44
- package/.agents/scripts/lib/orchestration/code-review.js +78 -436
- package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
- package/.agents/scripts/lib/orchestration/consolidation-precondition.js +4 -4
- package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
- package/.agents/scripts/lib/orchestration/deliver-recover.js +328 -0
- package/.agents/scripts/lib/orchestration/detectors-phase.js +12 -6
- 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/git-cleanup/phases/fast-forward.js +34 -0
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -2
- package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +142 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +17 -19
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +86 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +37 -103
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +21 -43
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +50 -85
- package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +3 -14
- package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
- package/.agents/scripts/lib/orchestration/merge-block-class.js +77 -21
- package/.agents/scripts/lib/orchestration/merge-poll.js +104 -0
- package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-context.js +354 -282
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +11 -22
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +4 -8
- package/.agents/scripts/lib/orchestration/plan-metrics.js +38 -6
- package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
- package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +71 -0
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +245 -0
- package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +116 -0
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +432 -858
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +778 -0
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +47 -115
- package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +509 -0
- 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 +52 -51
- package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
- package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +1 -1
- package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
- package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
- package/.agents/scripts/lib/orchestration/resolve-stories.js +344 -0
- package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
- package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
- package/.agents/scripts/lib/orchestration/review-depth.js +126 -47
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
- package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +3 -13
- package/.agents/scripts/lib/orchestration/review-providers/native.js +1 -154
- package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +3 -2
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +1 -1
- package/.agents/scripts/lib/orchestration/review-providers/types.js +5 -4
- package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +1 -1
- package/.agents/scripts/lib/orchestration/run-epilogue.js +784 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +25 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +11 -9
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +4 -4
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +86 -41
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +608 -152
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +77 -32
- package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +305 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +44 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +37 -4
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +2 -2
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +275 -46
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
- 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/format-autofix.js +10 -10
- package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +28 -42
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +360 -0
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +298 -0
- package/.agents/scripts/lib/orchestration/story-init-remote.js +51 -0
- package/.agents/scripts/lib/orchestration/story-plan-state.js +33 -0
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
- package/.agents/scripts/lib/orchestration/task-body-validator.js +60 -25
- package/.agents/scripts/lib/orchestration/ticket-lease.js +27 -74
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +130 -75
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +192 -377
- package/.agents/scripts/lib/orchestration/ticket-validator.js +123 -25
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +14 -72
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +45 -55
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +66 -6
- package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
- package/.agents/scripts/lib/plan-phase-cleanup.js +12 -14
- package/.agents/scripts/lib/planning-corpus.js +12 -281
- package/.agents/scripts/lib/preflight-runner.js +4 -4
- package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
- package/.agents/scripts/lib/qa/qa-context-hydrator.js +5 -5
- package/.agents/scripts/lib/signals/index.js +4 -17
- package/.agents/scripts/lib/signals/read.js +35 -35
- package/.agents/scripts/lib/signals/schema.js +8 -11
- package/.agents/scripts/lib/signals/span-tree.js +7 -7
- package/.agents/scripts/lib/signals/write.js +0 -1
- package/.agents/scripts/lib/single-story/story-merged-notify.js +13 -2
- package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
- package/.agents/scripts/lib/skills/parse-skill.js +16 -3
- package/.agents/scripts/lib/story-adjacency.js +17 -19
- package/.agents/scripts/lib/story-body/story-body.js +130 -75
- package/.agents/scripts/lib/story-plan.js +2 -4
- package/.agents/scripts/lib/templates/decomposer-prompts.js +51 -46
- package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
- package/.agents/scripts/lib/test-env.js +14 -1
- package/.agents/scripts/lib/test-tiers.js +0 -3
- package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +25 -39
- package/.agents/scripts/lib/validation-evidence.js +32 -60
- package/.agents/scripts/lib/wave-runner/ready-set.js +38 -12
- package/.agents/scripts/lib/workspace-provisioner.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +72 -25
- package/.agents/scripts/lib/worktree/lifecycle-manager.js +1 -2
- 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 +102 -80
- package/.agents/scripts/plan-persist.js +230 -279
- package/.agents/scripts/plan-run-epilogue.js +142 -0
- package/.agents/scripts/post-structured-comment.js +0 -38
- package/.agents/scripts/pr-watch-with-update.js +43 -22
- package/.agents/scripts/providers/github/compose.js +0 -1
- package/.agents/scripts/providers/github/errors.js +0 -19
- package/.agents/scripts/providers/github/issues.js +13 -39
- package/.agents/scripts/providers/github/mappers.js +5 -12
- package/.agents/scripts/providers/github/sub-issues.js +0 -47
- package/.agents/scripts/providers/github/tickets.js +33 -156
- package/.agents/scripts/providers/github.js +17 -6
- package/.agents/scripts/resolve-stories.js +236 -0
- package/.agents/scripts/run-coverage.js +4 -1
- package/.agents/scripts/run-lint.js +2 -2
- package/.agents/scripts/run-verify.js +31 -2
- package/.agents/scripts/signals-view.js +25 -21
- package/.agents/scripts/single-story-close.js +178 -26
- package/.agents/scripts/single-story-confirm-merge.js +313 -24
- package/.agents/scripts/single-story-init.js +35 -30
- package/.agents/scripts/stories-wave-tick.js +85 -10
- package/.agents/scripts/story-plan.js +28 -49
- package/.agents/scripts/update-ticket-state.js +14 -65
- package/.agents/skills/core/code-review-and-quality/SKILL.md +28 -450
- package/.agents/skills/core/code-review-and-quality/reference.md +458 -0
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +22 -315
- package/.agents/skills/core/debugging-and-error-recovery/reference.md +323 -0
- package/.agents/skills/core/diagnose-friction/SKILL.md +14 -18
- package/.agents/skills/core/documentation-and-adrs/SKILL.md +25 -397
- package/.agents/skills/core/documentation-and-adrs/reference.md +403 -0
- package/.agents/skills/core/gates-and-baselines/SKILL.md +12 -12
- package/.agents/skills/core/idea-refinement/SKILL.md +9 -9
- package/.agents/skills/core/scope-triage/SKILL.md +31 -172
- package/.agents/skills/core/security-and-hardening/SKILL.md +22 -367
- package/.agents/skills/core/security-and-hardening/reference.md +375 -0
- package/.agents/skills/skills.index.json +3 -53
- package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +2 -4
- package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +1 -1
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -3
- package/.agents/starter-agentrc.json +0 -5
- package/.agents/templates/agent-protocol.md +9 -10
- package/.agents/workflows/audit-architecture.md +6 -7
- package/.agents/workflows/audit-clean-code.md +7 -7
- package/.agents/workflows/audit-dependencies.md +3 -3
- package/.agents/workflows/audit-devops.md +3 -3
- package/.agents/workflows/audit-documentation.md +9 -10
- package/.agents/workflows/audit-lighthouse.md +11 -3
- package/.agents/workflows/audit-navigability.md +13 -2
- package/.agents/workflows/audit-performance.md +5 -6
- package/.agents/workflows/audit-privacy.md +3 -3
- package/.agents/workflows/audit-quality.md +11 -12
- package/.agents/workflows/audit-security.md +4 -5
- package/.agents/workflows/audit-seo.md +13 -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 +10 -3
- package/.agents/workflows/deliver.md +177 -176
- package/.agents/workflows/git-cleanup.md +5 -6
- package/.agents/workflows/git-deliver.md +1 -1
- package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
- package/.agents/workflows/helpers/acceptance-self-eval.md +35 -40
- package/.agents/workflows/helpers/code-quality-guardrails.md +7 -7
- package/.agents/workflows/helpers/code-review.md +75 -196
- package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +83 -44
- package/.agents/workflows/helpers/deliver-story.md +606 -0
- package/.agents/workflows/helpers/diagnose.md +10 -10
- package/.agents/workflows/helpers/parallel-tooling.md +3 -3
- package/.agents/workflows/helpers/signals.md +16 -16
- package/.agents/workflows/helpers/worktree-lifecycle.md +66 -86
- package/.agents/workflows/mandrel-update.md +2 -1
- package/.agents/workflows/plan.md +277 -145
- package/.agents/workflows/qa-assist.md +27 -33
- package/.agents/workflows/qa-explore.md +29 -38
- package/.agents/workflows/qa-run.md +2 -6
- package/README.md +9 -8
- package/bin/mandrel.js +12 -1
- package/docs/CHANGELOG.md +70 -0
- package/lib/cli/registry.js +262 -19
- package/lib/cli/sync-agents.js +157 -0
- package/lib/cli/sync-commands.js +115 -6
- package/lib/cli/sync.js +168 -6
- package/lib/cli/update.js +105 -8
- package/lib/cli/version-helpers.js +131 -0
- package/lib/migrations/README.md +7 -5
- package/lib/migrations/index.js +12 -8
- package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +100 -0
- package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +101 -0
- package/package.json +2 -2
- package/.agents/agents/retro.md +0 -42
- package/.agents/personas/architect.md +0 -113
- package/.agents/personas/devops-engineer.md +0 -38
- package/.agents/personas/engineer.md +0 -33
- package/.agents/personas/project-manager.md +0 -114
- package/.agents/personas/qa-engineer.md +0 -95
- package/.agents/personas/security-engineer.md +0 -111
- package/.agents/personas/technical-writer.md +0 -101
- package/.agents/schemas/dispatch-manifest.json +0 -232
- package/.agents/schemas/epic-perf-report.schema.json +0 -89
- package/.agents/schemas/epic-spec.schema.json +0 -153
- package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +0 -13
- package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +0 -13
- package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +0 -13
- package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +0 -15
- package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.blocked.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.close.end.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.complete.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +0 -14
- package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +0 -17
- package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +0 -15
- package/.agents/schemas/lifecycle/epic.plan.end.schema.json +0 -18
- package/.agents/schemas/lifecycle/epic.plan.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +0 -16
- package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.watch.end.schema.json +0 -29
- package/.agents/schemas/lifecycle/epic.watch.start.schema.json +0 -16
- package/.agents/schemas/lifecycle/slice.end.schema.json +0 -21
- package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +0 -20
- package/.agents/schemas/lifecycle/slice.start.schema.json +0 -17
- package/.agents/schemas/lifecycle/story.heartbeat.schema.json +0 -20
- package/.agents/schemas/risk-verdict.schema.json +0 -66
- package/.agents/schemas/story-perf-summary.schema.json +0 -73
- package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
- package/.agents/scripts/analyze-execution.js +0 -444
- package/.agents/scripts/bookkeeping-reconcile.js +0 -117
- package/.agents/scripts/check-prepush-recovery.js +0 -90
- package/.agents/scripts/dispatcher.js +0 -295
- package/.agents/scripts/epic-audit-prepare.js +0 -497
- package/.agents/scripts/epic-audit-recheck.js +0 -274
- package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
- package/.agents/scripts/epic-deliver-preflight.js +0 -462
- package/.agents/scripts/epic-deliver-prepare.js +0 -852
- package/.agents/scripts/epic-execute-record-wave.js +0 -449
- package/.agents/scripts/epic-plan-clarity.js +0 -211
- package/.agents/scripts/epic-plan-healthcheck.js +0 -581
- package/.agents/scripts/epic-reconcile.js +0 -625
- package/.agents/scripts/lib/baseline-snapshot.js +0 -979
- package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
- package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
- package/.agents/scripts/lib/config/lifecycle.js +0 -40
- package/.agents/scripts/lib/config/preflight.js +0 -58
- package/.agents/scripts/lib/config/retro.js +0 -77
- package/.agents/scripts/lib/epic-merge-lock.js +0 -322
- package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
- package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
- package/.agents/scripts/lib/git-merge-orchestrator.js +0 -261
- package/.agents/scripts/lib/observability/baseline-refresh-rate.js +0 -221
- package/.agents/scripts/lib/observability/hook-heartbeat.js +0 -219
- package/.agents/scripts/lib/observability/perf-aggregator.js +0 -813
- package/.agents/scripts/lib/observability/perf-report-readers.js +0 -328
- package/.agents/scripts/lib/observability/perf-report-render.js +0 -182
- package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +0 -270
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -539
- package/.agents/scripts/lib/orchestration/deliver-route.js +0 -173
- package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
- package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
- package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
- package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/risk-verdict.js +0 -105
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -621
- package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
- package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
- package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
- package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
- package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +0 -400
- 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/error-journal.js +0 -139
- package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
- package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
- package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
- package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +0 -270
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +0 -155
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-diff.js +0 -140
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -465
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -284
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +0 -665
- 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/plan-review-routing.js +0 -63
- package/.agents/scripts/lib/orchestration/planning-context-budget.js +0 -213
- package/.agents/scripts/lib/orchestration/planning-risk.js +0 -194
- package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +0 -56
- package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +0 -33
- package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +0 -78
- package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +0 -68
- package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +0 -118
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +0 -396
- package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
- package/.agents/scripts/lib/orchestration/preflight-cache.js +0 -187
- 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-perf-heuristics.js +0 -275
- package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
- package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
- package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
- package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
- package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
- package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
- package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
- package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
- package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
- package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
- package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
- package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
- package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
- package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
- package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
- package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
- package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
- package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -302
- package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
- package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
- package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
- package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
- package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
- package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
- package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
- package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
- package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
- package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
- package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
- package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
- package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
- package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
- package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
- package/.agents/scripts/lib/push-epic-retry.js +0 -209
- package/.agents/scripts/lib/spec/index.js +0 -36
- package/.agents/scripts/lib/spec/loader.js +0 -425
- package/.agents/scripts/lib/spec/state.js +0 -208
- package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
- package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
- package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
- package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
- package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
- package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
- package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
- package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
- package/.agents/scripts/lib/wave-runner/tick.js +0 -754
- package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
- package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
- package/.agents/scripts/lifecycle-emit.js +0 -510
- package/.agents/scripts/retro-run.js +0 -218
- package/.agents/scripts/slice-phase.js +0 -361
- package/.agents/scripts/standalone-feedback-rollup.js +0 -188
- package/.agents/scripts/story-close.js +0 -294
- package/.agents/scripts/story-init.js +0 -599
- package/.agents/scripts/story-phase.js +0 -369
- package/.agents/scripts/wave-tick.js +0 -464
- package/.agents/skills/core/analyze-execution/SKILL.md +0 -98
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
- package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
- package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
- package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
- package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -383
- package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
- package/.agents/workflows/helpers/deliver-epic-reference.md +0 -547
- package/.agents/workflows/helpers/deliver-epic-single.md +0 -331
- package/.agents/workflows/helpers/deliver-epic.md +0 -998
- package/.agents/workflows/helpers/deliver-stories.md +0 -450
- package/.agents/workflows/helpers/epic-audit.md +0 -189
- package/.agents/workflows/helpers/epic-deliver-story.md +0 -436
- package/.agents/workflows/helpers/epic-testing.md +0 -125
- package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
- package/.agents/workflows/helpers/plan-epic.md +0 -353
- package/.agents/workflows/helpers/plan-story.md +0 -251
- package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
- package/.agents/workflows/helpers/single-story-deliver.md +0 -557
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/orchestration/deliver-route.js — the deliver-side reader for the
|
|
3
|
-
* plan-time single-delivery seam (Epic #4475, M4-A).
|
|
4
|
-
*
|
|
5
|
-
* The plan path already ships the seam inert (Epic #4474): the risk verdict's
|
|
6
|
-
* `deliveryShape`, the `delivery::single` label, and the
|
|
7
|
-
* `epic-plan-state.decompose = { ticketCount: 0, shape: "single" }`
|
|
8
|
-
* checkpoint. Nothing on the deliver side read them — until this module. It
|
|
9
|
-
* folds those two markers (plus the global kill-switch) into a single
|
|
10
|
-
* delivery-route verdict for `/deliver`.
|
|
11
|
-
*
|
|
12
|
-
* Pure and total — inputs in, verdict out. No GitHub calls, no I/O, no
|
|
13
|
-
* throws. It mirrors how `review-depth.js#resolveDepth` and
|
|
14
|
-
* `epic-audit-prepare.js` read `planningRisk` / `decompose` off the
|
|
15
|
-
* `epic-plan-state` checkpoint: the caller fetches the Epic labels + the
|
|
16
|
-
* checkpoint, then hands both here.
|
|
17
|
-
*
|
|
18
|
-
* ── Routing precedence (highest wins) ──────────────────────────────────
|
|
19
|
-
* 1. Kill-switch. `delivery.routing.singleDelivery === false` forces
|
|
20
|
-
* `fan-out` for EVERY Epic, even a single-labelled one — the instant
|
|
21
|
-
* global revert (`lib/config/delivery-routing.js`). Overrides all.
|
|
22
|
-
* 2. Single marker. The `delivery::single` label (primary) OR
|
|
23
|
-
* `checkpoint.decompose.shape === "single"` (secondary) → `single`.
|
|
24
|
-
* 3. Wide-DAG advisory. A fan-out-shaped Epic whose ready-width > 1 is
|
|
25
|
-
* genuine parallelism → `fan-out`. Deliver-time width only ADVISES —
|
|
26
|
-
* it never reroutes a single-marked Epic (that would orphan a Story
|
|
27
|
-
* tree that does not exist; re-route = re-plan).
|
|
28
|
-
* 4. Legacy / no marker → `fan-out` (safe backward-compat: a legacy Epic
|
|
29
|
-
* has an authored Story tree the fan-out engine consumes).
|
|
30
|
-
*
|
|
31
|
-
* BEHAVIOR-PRESERVING in M4-A: the router consumes a `single` verdict via a
|
|
32
|
-
* stub that continues at `deliver-epic.md` (fan-out), so no `/deliver`
|
|
33
|
-
* observably changes until M4-B lands `deliver-epic-single.md`.
|
|
34
|
-
*
|
|
35
|
-
* @typedef {'single'|'fan-out'} DeliveryRoute
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
import { getDeliveryRouting } from '../config/delivery-routing.js';
|
|
39
|
-
|
|
40
|
-
/** The canonical single-delivery routing marker label. */
|
|
41
|
-
export const DELIVERY_SINGLE_LABEL = 'delivery::single';
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* True when the Epic carries the `delivery::single` routing label. Tolerant
|
|
45
|
-
* of the two label shapes callers hold: an array of label-name strings, or an
|
|
46
|
-
* array of `{ name }` objects (the GitHub REST label shape).
|
|
47
|
-
*
|
|
48
|
-
* @param {{ labels?: Array<string | { name?: string }> } | null | undefined} epic
|
|
49
|
-
* @returns {boolean}
|
|
50
|
-
*/
|
|
51
|
-
function hasSingleLabel(epic) {
|
|
52
|
-
const labels = Array.isArray(epic?.labels) ? epic.labels : [];
|
|
53
|
-
return labels.some((l) => {
|
|
54
|
-
const name = typeof l === 'string' ? l : l?.name;
|
|
55
|
-
return name === DELIVERY_SINGLE_LABEL;
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* True when the plan-state checkpoint's `decompose.shape` is the deliberate
|
|
61
|
-
* single shape. `plan-persist.js` writes `decompose = { ticketCount: 0,
|
|
62
|
-
* shape: "single" }` for a spec-only plan; every other value (including a
|
|
63
|
-
* legacy checkpoint with no `shape` field) is not-single.
|
|
64
|
-
*
|
|
65
|
-
* @param {{ decompose?: { shape?: string } } | null | undefined} checkpoint
|
|
66
|
-
* @returns {boolean}
|
|
67
|
-
*/
|
|
68
|
-
function hasSingleDecomposeShape(checkpoint) {
|
|
69
|
-
return checkpoint?.decompose?.shape === 'single';
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Resolve the delivery route for one Epic from its labels, its plan-state
|
|
74
|
-
* checkpoint, and the resolved config. See the module header for the full
|
|
75
|
-
* precedence. Pure — never throws; malformed / absent inputs degrade to the
|
|
76
|
-
* safe `fan-out` default.
|
|
77
|
-
*
|
|
78
|
-
* @param {{ labels?: Array<string | { name?: string }> } | null | undefined} epic
|
|
79
|
-
* The Epic ticket snapshot (only `labels` is read here).
|
|
80
|
-
* @param {{ decompose?: { shape?: string } } | null | undefined} checkpoint
|
|
81
|
-
* The `epic-plan-state` structured comment, parsed (or `null` on a legacy
|
|
82
|
-
* Epic that predates the checkpoint — treated as no marker).
|
|
83
|
-
* @param {object | null | undefined} config
|
|
84
|
-
* The resolved config; `delivery.routing.singleDelivery` is the kill-switch.
|
|
85
|
-
* @returns {{ route: DeliveryRoute, reason: string, singleDeliveryEnabled: boolean }}
|
|
86
|
-
*/
|
|
87
|
-
export function resolveEpicDeliveryRoute(epic, checkpoint, config) {
|
|
88
|
-
const { singleDelivery } = getDeliveryRouting(config);
|
|
89
|
-
|
|
90
|
-
// 1. Kill-switch — overrides all. A `false` value forces fan-out even for
|
|
91
|
-
// an Epic the planner marked single (the instant global revert).
|
|
92
|
-
if (singleDelivery === false) {
|
|
93
|
-
return {
|
|
94
|
-
route: 'fan-out',
|
|
95
|
-
reason:
|
|
96
|
-
'kill-switch: delivery.routing.singleDelivery=false forces fan-out for every Epic',
|
|
97
|
-
singleDeliveryEnabled: false,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// 2. Single marker — label (primary) OR checkpoint decompose shape
|
|
102
|
-
// (secondary). Either alone routes single.
|
|
103
|
-
const labelled = hasSingleLabel(epic);
|
|
104
|
-
const shaped = hasSingleDecomposeShape(checkpoint);
|
|
105
|
-
if (labelled || shaped) {
|
|
106
|
-
const via =
|
|
107
|
-
labelled && shaped
|
|
108
|
-
? `${DELIVERY_SINGLE_LABEL} label + decompose.shape="single"`
|
|
109
|
-
: labelled
|
|
110
|
-
? `${DELIVERY_SINGLE_LABEL} label`
|
|
111
|
-
: 'decompose.shape="single"';
|
|
112
|
-
return {
|
|
113
|
-
route: 'single',
|
|
114
|
-
reason: `single marker present (${via})`,
|
|
115
|
-
singleDeliveryEnabled: true,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// 3/4. No single marker → fan-out (a wide DAG or a legacy Story tree; the
|
|
120
|
-
// deliver-time width only advises and never reroutes here).
|
|
121
|
-
return {
|
|
122
|
-
route: 'fan-out',
|
|
123
|
-
reason: 'no single marker — fan-out (legacy Story tree or wide DAG)',
|
|
124
|
-
singleDeliveryEnabled: true,
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Compute the ready-width of a delivery plan — the count of work units that
|
|
130
|
-
* could dispatch on the first beat. It is the mechanical parallelism signal
|
|
131
|
-
* the planner uses at plan time to mark a genuinely-wide Epic `fan-out`, and
|
|
132
|
-
* that `/deliver` may surface as an advisory at deliver time (it never
|
|
133
|
-
* reroutes — see the module header).
|
|
134
|
-
*
|
|
135
|
-
* Accepts either input shape the framework already produces:
|
|
136
|
-
* - Delivery-Slicing rows — `[{ independent: boolean }, …]` from
|
|
137
|
-
* `parseDeliverySlicingTable`. A serial chain (every row
|
|
138
|
-
* `Independent: No`, or a lone independent slice) has width 1; two or
|
|
139
|
-
* more independent slices yield a width equal to that independent count
|
|
140
|
-
* (> 1) — genuine parallelism.
|
|
141
|
-
* - A wave DAG — `[[…], […], …]` (the array-of-waves `state.waves` shape
|
|
142
|
-
* `runBuildWaveDagPhase` produces). The width is the largest wave — the
|
|
143
|
-
* most Stories ready to dispatch on a single beat.
|
|
144
|
-
*
|
|
145
|
-
* Pure and total: an empty / malformed / unrecognized input degrades to
|
|
146
|
-
* width 1 (the safe "not wide" signal). Never throws.
|
|
147
|
-
*
|
|
148
|
-
* @param {Array<{ independent?: boolean }> | Array<Array<unknown>> | null | undefined} deliverySlicingRowsOrDag
|
|
149
|
-
* @returns {number} an integer ≥ 1.
|
|
150
|
-
*/
|
|
151
|
-
export function computeReadyWidth(deliverySlicingRowsOrDag) {
|
|
152
|
-
const input = deliverySlicingRowsOrDag;
|
|
153
|
-
if (!Array.isArray(input) || input.length === 0) return 1;
|
|
154
|
-
|
|
155
|
-
// Wave-DAG shape: an array whose entries are themselves arrays.
|
|
156
|
-
if (input.every((entry) => Array.isArray(entry))) {
|
|
157
|
-
let widest = 1;
|
|
158
|
-
for (const wave of input) {
|
|
159
|
-
if (wave.length > widest) widest = wave.length;
|
|
160
|
-
}
|
|
161
|
-
return widest;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Delivery-Slicing rows: entries are `{ independent }` records.
|
|
165
|
-
const independentCount = input.reduce(
|
|
166
|
-
(acc, row) =>
|
|
167
|
-
row && typeof row === 'object' && row.independent === true
|
|
168
|
-
? acc + 1
|
|
169
|
-
: acc,
|
|
170
|
-
0,
|
|
171
|
-
);
|
|
172
|
-
return independentCount >= 2 ? independentCount : 1;
|
|
173
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/orchestration/dispatch-engine.js — Core Dispatch Engine (SDK coordinator)
|
|
3
|
-
*
|
|
4
|
-
* Thin facade composing:
|
|
5
|
-
* - `dispatch-pipeline.js` — internal resolve/fetch/reconcile/graph helpers
|
|
6
|
-
*
|
|
7
|
-
* Every Epic is 2-tier (Epic → Story); `dispatch()` computes a
|
|
8
|
-
* Story-level wave plan and emits a 2-tier manifest. The legacy Task-tier
|
|
9
|
-
* dispatch runtime (Task fetcher, single-Story executor, the per-Task
|
|
10
|
-
* wave fan-out, and the Epic-completion detector) was removed in Epic
|
|
11
|
-
* #3163.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { PROJECT_ROOT, resolveConfig } from '../config-resolver.js';
|
|
15
|
-
import { ConflictingTypeLabelsError } from '../errors/index.js';
|
|
16
|
-
import { ensureLocalBranch } from '../git-branch-lifecycle.js';
|
|
17
|
-
import { Logger } from '../Logger.js';
|
|
18
|
-
import { TYPE_LABELS } from '../label-constants.js';
|
|
19
|
-
import { createProvider } from '../provider-factory.js';
|
|
20
|
-
import {
|
|
21
|
-
buildStoryDispatchGraph,
|
|
22
|
-
fetchEpicContext,
|
|
23
|
-
isTwoTierDispatch,
|
|
24
|
-
resolveDispatchContext,
|
|
25
|
-
} from './dispatch-pipeline.js';
|
|
26
|
-
import { buildManifest } from './manifest-builder.js';
|
|
27
|
-
import { STATE_LABELS } from './ticketing.js';
|
|
28
|
-
|
|
29
|
-
export const AGENT_DONE_LABEL = STATE_LABELS.DONE;
|
|
30
|
-
|
|
31
|
-
/* node:coverage ignore next */
|
|
32
|
-
export function ensureBranch(branchName, baseBranch) {
|
|
33
|
-
ensureLocalBranch(branchName, baseBranch, PROJECT_ROOT, {
|
|
34
|
-
log: (msg) => Logger.info(msg),
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Resolve a single ticket ID, detect its type, and delegate to the
|
|
40
|
-
* appropriate execution pipeline. Single entry point shared by the CLI
|
|
41
|
-
* wrapper and the MCP `dispatch_wave` tool.
|
|
42
|
-
*/
|
|
43
|
-
export async function resolveAndDispatch(options) {
|
|
44
|
-
const { ticketId, dryRun = false } = options;
|
|
45
|
-
const config = resolveConfig();
|
|
46
|
-
const provider = options.provider ?? createProvider(config);
|
|
47
|
-
|
|
48
|
-
const ticket = await provider.getTicket(ticketId);
|
|
49
|
-
const labels = ticket.labels || [];
|
|
50
|
-
|
|
51
|
-
const typeLabels = labels.filter((l) => l.startsWith('type::'));
|
|
52
|
-
if (typeLabels.length > 1) {
|
|
53
|
-
throw new ConflictingTypeLabelsError(
|
|
54
|
-
`Ticket #${ticketId} has conflicting type labels: ${typeLabels.join(', ')}. Exactly one type::* label is required.`,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const isStory = labels.includes(TYPE_LABELS.STORY);
|
|
59
|
-
const isEpic = labels.includes(TYPE_LABELS.EPIC);
|
|
60
|
-
|
|
61
|
-
if (isStory) {
|
|
62
|
-
throw new Error(
|
|
63
|
-
`[Dispatcher] Ticket #${ticketId} is a **Story**. Stories are dispatched ` +
|
|
64
|
-
'through the Story delivery path, not directly via the dispatcher. ' +
|
|
65
|
-
`Run \`/deliver ${ticketId}\` to execute this Story, ` +
|
|
66
|
-
`or dispatch its parent Epic with \`/deliver #<epicId>\`.`,
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (isEpic) {
|
|
71
|
-
return dispatch({ epicId: ticketId, dryRun, provider });
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const typeLabel = labels.find((l) => l.startsWith('type::')) || 'unknown';
|
|
75
|
-
throw new Error(
|
|
76
|
-
`[Dispatcher] Ticket #${ticketId} has type "${typeLabel.replace('type::', '')}". ` +
|
|
77
|
-
`Only "epic" or "story" tickets can be dispatched. ` +
|
|
78
|
-
`Please ensure the ticket is correctly categorized before execution.`,
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Main dispatcher. Orchestrates one dispatch cycle for an Epic.
|
|
84
|
-
* Primary public export of the orchestration SDK.
|
|
85
|
-
*/
|
|
86
|
-
export async function dispatch(options) {
|
|
87
|
-
const ctx = resolveDispatchContext(options, ensureBranch);
|
|
88
|
-
const { epicId, dryRun } = ctx;
|
|
89
|
-
|
|
90
|
-
const fetched = await fetchEpicContext(ctx);
|
|
91
|
-
|
|
92
|
-
// Every Epic is 2-tier (Epic → Story). Compute Story-level
|
|
93
|
-
// waves directly from the Story tickets and emit a 2-tier-shaped
|
|
94
|
-
// manifest with `waves[].stories[]` so downstream consumers (manifest
|
|
95
|
-
// renderer, /deliver wave planner) see the correct execution plan.
|
|
96
|
-
// Per-Story execution is owned by `/deliver` (story-init →
|
|
97
|
-
// story-close), not by this dispatcher.
|
|
98
|
-
if (isTwoTierDispatch(fetched.allTickets)) {
|
|
99
|
-
Logger.info(
|
|
100
|
-
'Detected 2-tier hierarchy — computing Story-level execution waves.',
|
|
101
|
-
);
|
|
102
|
-
const { allWaves: storyWaves } = buildStoryDispatchGraph(
|
|
103
|
-
fetched.allTickets,
|
|
104
|
-
);
|
|
105
|
-
return buildManifest({
|
|
106
|
-
epicId,
|
|
107
|
-
epic: fetched.epic,
|
|
108
|
-
tasks: [],
|
|
109
|
-
allTickets: fetched.allTickets,
|
|
110
|
-
waves: storyWaves,
|
|
111
|
-
dispatched: [],
|
|
112
|
-
dryRun,
|
|
113
|
-
hierarchy: '2-tier',
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// No Story tickets under the Epic — throw loudly rather than emit an
|
|
118
|
-
// empty manifest, matching the wave-loop's behavior (build-wave-dag.js
|
|
119
|
-
// throws the same message shape on this input). A silently-empty
|
|
120
|
-
// manifest masks a pre-cutover Epic whose children are legacy Features.
|
|
121
|
-
const typedChildren = (fetched.allTickets ?? [])
|
|
122
|
-
.map((t) => (t.labels ?? []).find((l) => l.startsWith('type::')))
|
|
123
|
-
.filter(Boolean);
|
|
124
|
-
const legacyHint =
|
|
125
|
-
typedChildren.length > 0
|
|
126
|
-
? ` Found ${typedChildren.length} non-Story child ticket(s) ` +
|
|
127
|
-
`(${[...new Set(typedChildren)].join(', ')}) — this Epic looks ` +
|
|
128
|
-
`pre-cutover (legacy Feature children) and needs migration to the ` +
|
|
129
|
-
`2-tier (Epic → Story) hierarchy before dispatch.`
|
|
130
|
-
: '';
|
|
131
|
-
throw new Error(
|
|
132
|
-
`Epic #${epicId} has no child stories to dispatch.${legacyHint}`,
|
|
133
|
-
);
|
|
134
|
-
}
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* dispatch-pipeline.js
|
|
3
|
-
*
|
|
4
|
-
* Internal pipeline helpers composed by `dispatch-engine.js::dispatch()`.
|
|
5
|
-
* Keeping these out of the coordinator keeps the public entry point compact
|
|
6
|
-
* and focused on the 2-tier flow: resolve → fetch → Story-graph.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { PROJECT_ROOT, resolveConfig } from '../config-resolver.js';
|
|
10
|
-
import { getEpicBranch } from '../git-utils.js';
|
|
11
|
-
import { Logger } from '../Logger.js';
|
|
12
|
-
import { TYPE_LABELS } from '../label-constants.js';
|
|
13
|
-
import { createProvider } from '../provider-factory.js';
|
|
14
|
-
import { buildStoryAdjacency } from '../story-adjacency.js';
|
|
15
|
-
import { WorktreeManager } from '../worktree-manager.js';
|
|
16
|
-
import { computeStoryWaves } from './dependency-analyzer.js';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Runtime context for a single dispatch cycle.
|
|
20
|
-
*
|
|
21
|
-
* Produced by {@link resolveDispatchContext} and consumed by every pipeline
|
|
22
|
-
* stage (fetch → graph → scaffold → GC → dispatch). All fields
|
|
23
|
-
* are resolved once up-front so downstream helpers can stay free of
|
|
24
|
-
* configuration look-ups.
|
|
25
|
-
*
|
|
26
|
-
* @typedef {object} DispatchContext
|
|
27
|
-
* @property {number} epicId Epic ticket number under dispatch.
|
|
28
|
-
* @property {boolean} dryRun When true, mutating side-effects are skipped.
|
|
29
|
-
* @property {object} config Resolved canonical `.agentrc.json` (with `project`, `github`, `planning`, `delivery` blocks).
|
|
30
|
-
* @property {import('../ITicketingProvider.js').ITicketingProvider} provider Ticketing provider (may come from cache).
|
|
31
|
-
* @property {import('../worktree-manager.js').WorktreeManager | undefined} worktreeManager Optional worktree manager (only when isolation is enabled and not dry-run).
|
|
32
|
-
* @property {string} baseBranch Trunk branch the Epic branches from (default `main`).
|
|
33
|
-
* @property {string} epicBranch Epic branch name (`epic/<epicId>`).
|
|
34
|
-
* @property {(branchName: string, baseBranch: string) => void} ensureBranch Caller-supplied branch-creation helper.
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The output of {@link fetchEpicContext}.
|
|
39
|
-
*
|
|
40
|
-
* @typedef {object} FetchedEpic
|
|
41
|
-
* @property {object} epic The Epic ticket record.
|
|
42
|
-
* @property {object[]} allTickets Every ticket under the Epic (stories + health).
|
|
43
|
-
* @property {Map<number, object>} allTicketsById Index of `allTickets` by ticket id.
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Resolve the runtime context for a dispatch: canonical config, provider, adapter,
|
|
48
|
-
* worktree manager, base/epic branch names, and the `ensureBranch` bound
|
|
49
|
-
* helper supplied by the caller.
|
|
50
|
-
*
|
|
51
|
-
* @param {object} options Dispatch entry options.
|
|
52
|
-
* @param {number} options.epicId Epic ticket number.
|
|
53
|
-
* @param {boolean} [options.dryRun=false] When true, skip branch creation and worktree setup.
|
|
54
|
-
* @param {import('../ITicketingProvider.js').ITicketingProvider} [options.provider] Pre-constructed provider (overrides factory).
|
|
55
|
-
* @param {import('../worktree-manager.js').WorktreeManager} [options.worktreeManager] Pre-constructed worktree manager.
|
|
56
|
-
* @param {(branchName: string, baseBranch: string) => void} ensureBranch Branch-creation helper bound by caller (keeps engine ↔ git-lifecycle coupling at the edge).
|
|
57
|
-
* @returns {DispatchContext} Fully resolved dispatch context.
|
|
58
|
-
*/
|
|
59
|
-
export function resolveDispatchContext(options, ensureBranch) {
|
|
60
|
-
const { epicId, dryRun = false } = options;
|
|
61
|
-
|
|
62
|
-
const config = resolveConfig();
|
|
63
|
-
const provider = options.provider ?? createProvider(config);
|
|
64
|
-
|
|
65
|
-
const wtConfig = config?.delivery?.worktreeIsolation;
|
|
66
|
-
let worktreeManager = options.worktreeManager;
|
|
67
|
-
if (!worktreeManager && wtConfig?.enabled && !dryRun) {
|
|
68
|
-
worktreeManager = new WorktreeManager({
|
|
69
|
-
repoRoot: PROJECT_ROOT,
|
|
70
|
-
config: wtConfig,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
epicId,
|
|
76
|
-
dryRun,
|
|
77
|
-
config,
|
|
78
|
-
provider,
|
|
79
|
-
worktreeManager,
|
|
80
|
-
baseBranch: config?.project?.baseBranch ?? 'main',
|
|
81
|
-
epicBranch: getEpicBranch(epicId),
|
|
82
|
-
ensureBranch,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Fetch Epic + all tickets and prime the provider cache.
|
|
88
|
-
*
|
|
89
|
-
* @param {DispatchContext} ctx Dispatch context.
|
|
90
|
-
* @returns {Promise<FetchedEpic>} Epic + ticket graph.
|
|
91
|
-
*/
|
|
92
|
-
export async function fetchEpicContext(ctx) {
|
|
93
|
-
const { provider, epicId } = ctx;
|
|
94
|
-
|
|
95
|
-
Logger.info(`\nFetching Epic #${epicId}...`);
|
|
96
|
-
const epic = await provider.getEpic(epicId);
|
|
97
|
-
|
|
98
|
-
Logger.info(`Fetching all tickets under Epic #${epicId}...`);
|
|
99
|
-
const allTickets = await provider.getTickets(epicId);
|
|
100
|
-
const allTicketsById = new Map(allTickets.map((t) => [t.id, t]));
|
|
101
|
-
|
|
102
|
-
provider.primeTicketCache(allTickets);
|
|
103
|
-
|
|
104
|
-
return { epic, allTickets, allTicketsById };
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Detect 2-tier hierarchy from the fetched ticket graph. After Epic #3163's
|
|
109
|
-
* hard cutover deleted the `type::task` ticket layer, shape selection is
|
|
110
|
-
* purely structural: any Epic carrying at least one `type::story` ticket
|
|
111
|
-
* resolves to 2-tier.
|
|
112
|
-
*
|
|
113
|
-
* @param {object[]} allTickets
|
|
114
|
-
* @returns {boolean}
|
|
115
|
-
*/
|
|
116
|
-
export function isTwoTierDispatch(allTickets) {
|
|
117
|
-
if (!Array.isArray(allTickets) || allTickets.length === 0) return false;
|
|
118
|
-
return allTickets.some((t) =>
|
|
119
|
-
(t.labelSet ?? new Set(t.labels ?? [])).has(TYPE_LABELS.STORY),
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Build the Story-level dispatch graph for a 2-tier Epic. Reads story
|
|
125
|
-
* tickets from `allTickets`, parses cross-Story `blocked by` references
|
|
126
|
-
* from each Story body (also honoring an optional `dependencies[]`
|
|
127
|
-
* field set by fixture providers), and computes wave indices via
|
|
128
|
-
* {@link computeStoryWaves}.
|
|
129
|
-
*
|
|
130
|
-
* The returned `allWaves` is an array of Story-ticket arrays, ordered by
|
|
131
|
-
* wave index. `storyMap` indexes the same Story tickets by id for downstream
|
|
132
|
-
* lookups (mirrors the `taskMap` returned by {@link buildDispatchGraph}).
|
|
133
|
-
*
|
|
134
|
-
* Stories with no resolvable wave (cycle pre-filter, missing in groups)
|
|
135
|
-
* are placed in their own trailing wave so they remain visible in the
|
|
136
|
-
* manifest output.
|
|
137
|
-
*
|
|
138
|
-
* @param {object[]} allTickets Fetched ticket graph (Epic + Stories).
|
|
139
|
-
* @returns {{ allWaves: object[][], storyMap: Map<number, object> }}
|
|
140
|
-
* @throws {Error} When the Story dependency graph contains a cycle.
|
|
141
|
-
*/
|
|
142
|
-
export function buildStoryDispatchGraph(allTickets) {
|
|
143
|
-
const stories = (allTickets ?? []).filter((t) =>
|
|
144
|
-
(t.labelSet ?? new Set(t.labels ?? [])).has(TYPE_LABELS.STORY),
|
|
145
|
-
);
|
|
146
|
-
const storyMap = new Map(stories.map((s) => [s.id, s]));
|
|
147
|
-
|
|
148
|
-
// Shared story-level adjacency builder (lib/story-adjacency.js) owns the
|
|
149
|
-
// dependency-source ordering contract: body `blocked by` references via
|
|
150
|
-
// `parseBlockedBy`, then explicit `dependencies[]`, foreign edges dropped.
|
|
151
|
-
const explicitDeps = buildStoryAdjacency(stories);
|
|
152
|
-
|
|
153
|
-
// computeStoryWaves expects a Map<storyId, { tasks: [] }>; with no Tasks
|
|
154
|
-
// present, only explicitDeps + focus-area rollup (no-op for empty
|
|
155
|
-
// task lists) drive wave assignment.
|
|
156
|
-
const storyGroups = new Map(
|
|
157
|
-
stories.map((s) => [s.id, { storyId: s.id, tasks: [] }]),
|
|
158
|
-
);
|
|
159
|
-
const waveAssignment = computeStoryWaves(storyGroups, explicitDeps);
|
|
160
|
-
|
|
161
|
-
// Bucket stories by wave index. `computeStoryWaves` returns -1 for any
|
|
162
|
-
// story it could not place; route those into a trailing bucket so they
|
|
163
|
-
// still surface in the manifest.
|
|
164
|
-
const byWave = new Map();
|
|
165
|
-
let maxWave = -1;
|
|
166
|
-
for (const story of stories) {
|
|
167
|
-
const wave = waveAssignment.get(story.id) ?? -1;
|
|
168
|
-
if (wave > maxWave) maxWave = wave;
|
|
169
|
-
if (!byWave.has(wave)) byWave.set(wave, []);
|
|
170
|
-
byWave.get(wave).push(story);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const allWaves = [];
|
|
174
|
-
for (let i = 0; i <= maxWave; i++) {
|
|
175
|
-
if (byWave.has(i)) allWaves.push(byWave.get(i));
|
|
176
|
-
}
|
|
177
|
-
if (byWave.has(-1)) allWaves.push(byWave.get(-1));
|
|
178
|
-
|
|
179
|
-
Logger.info(
|
|
180
|
-
`Computed ${allWaves.length} Story-level execution wave(s) (2-tier).`,
|
|
181
|
-
);
|
|
182
|
-
return { allWaves, storyMap };
|
|
183
|
-
}
|