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,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/orchestration/wave-marker.js — Wave-marker regex + parser.
|
|
3
|
-
*
|
|
4
|
-
* Centralizes the regex used to recognize `wave-N-start` / `wave-N-end`
|
|
5
|
-
* structured-comment types so call sites (`ticketing.js`, tool-registry
|
|
6
|
-
* descriptors, tests) all agree on the same bounded pattern.
|
|
7
|
-
*
|
|
8
|
-
* The wave index is bounded to 1-3 digits (0-999) so a malformed or
|
|
9
|
-
* malicious marker cannot trigger pathological regex backtracking on
|
|
10
|
-
* unbounded `\d+`.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
export const WAVE_MARKER_RE = /^wave-([0-9]{1,3})-(start|end)$/;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Parse a wave-marker string into its components.
|
|
17
|
-
*
|
|
18
|
-
* @param {string} s
|
|
19
|
-
* @returns {{ index: number, phase: 'start' | 'end' } | null}
|
|
20
|
-
* `null` for any input that is not a string or does not match
|
|
21
|
-
* {@link WAVE_MARKER_RE}.
|
|
22
|
-
*/
|
|
23
|
-
export function parseWaveMarker(s) {
|
|
24
|
-
if (typeof s !== 'string') return null;
|
|
25
|
-
const m = WAVE_MARKER_RE.exec(s);
|
|
26
|
-
if (!m) return null;
|
|
27
|
-
return { index: Number(m[1]), phase: m[2] };
|
|
28
|
-
}
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* wave-record-io.js — impure helpers for the per-Story status recorder CLI
|
|
3
|
-
* (`epic-execute-record-wave.js`): ticket verification, manifest title
|
|
4
|
-
* lookup, and returns reconciliation.
|
|
5
|
-
*
|
|
6
|
-
* These functions all hit the provider and are intentionally kept out of
|
|
7
|
-
* `wave-record-projection.js`, which is the pure helper layer. The parent
|
|
8
|
-
* CLI imports both modules and threads the I/O results through the
|
|
9
|
-
* projection.
|
|
10
|
-
*
|
|
11
|
-
* Story #4155 (Epic #4151) — the wave-batch livelock-recovery path
|
|
12
|
-
* (`planStoryIdsForWave` + the empty-mode-B reconcile) was deleted along
|
|
13
|
-
* with the wave checkpoint it keyed off. Under the ready-set runtime a
|
|
14
|
-
* Story's terminal state is always re-derivable from its live label on the
|
|
15
|
-
* next `tick`, so there is no falsely-`complete` empty wave to recover from
|
|
16
|
-
* — the recorder records exactly the Stories it was handed.
|
|
17
|
-
*
|
|
18
|
-
* Story #3909 — the per-wave dispatch-manifest refresh hop was deleted; the
|
|
19
|
-
* manifest is written once at `epic-deliver-prepare` time and left frozen.
|
|
20
|
-
* `loadManifestTitleMap` reads it for rollup-row titles.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { Logger } from '../Logger.js';
|
|
24
|
-
import { concurrentMap } from '../util/concurrent-map.js';
|
|
25
|
-
import {
|
|
26
|
-
reconcileStoryFromGitHub,
|
|
27
|
-
renderMalformedReturnsFriction,
|
|
28
|
-
} from './epic-runner/sub-agent-return.js';
|
|
29
|
-
import { parseFencedJsonComment } from './structured-comment-parser.js';
|
|
30
|
-
import { findStructuredComment, postStructuredComment } from './ticketing.js';
|
|
31
|
-
import { normalizeReturnsPure } from './wave-record-projection.js';
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Default cap for {@link verifyWaveResults}. Mirrors the default for
|
|
35
|
-
* `delivery.deliverRunner.verifyConcurrencyCap` in `.agentrc.json`
|
|
36
|
-
* (Epic #3019 Tech Spec §1.4 / Story #3024).
|
|
37
|
-
*/
|
|
38
|
-
const DEFAULT_VERIFY_CONCURRENCY_CAP = 4;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Normalize raw `--returns` payload (per-Story sub-agent return texts) into
|
|
42
|
-
* the same shape `validateResults` produces. Entries that fail to parse are
|
|
43
|
-
* reconciled from GitHub and recorded as parse failures; the caller posts a
|
|
44
|
-
* single rolled-up friction comment listing every failure.
|
|
45
|
-
*
|
|
46
|
-
* @param {{ provider: object, returns: Array<{ storyId: number, returnText: string }> }} args
|
|
47
|
-
*/
|
|
48
|
-
export async function normalizeReturns({ provider, returns } = {}) {
|
|
49
|
-
return normalizeReturnsPure({
|
|
50
|
-
returns,
|
|
51
|
-
reconcile: ({ storyId }) => reconcileStoryFromGitHub({ provider, storyId }),
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Verify a single result row: pass-through when the row is not claiming
|
|
57
|
-
* `done`, otherwise re-fetch the ticket and emit either the verified row
|
|
58
|
-
* (label/state agrees) or a `{ verified, discrepancy }` pair when the
|
|
59
|
-
* claim disagrees with GitHub. Network failures surface as
|
|
60
|
-
* `verify-error` discrepancies — they cannot prove the claim either way
|
|
61
|
-
* so the row is downgraded to `failed`.
|
|
62
|
-
*
|
|
63
|
-
* Extracted as a per-row mapper so {@link verifyWaveResults} can run the
|
|
64
|
-
* verifications through {@link concurrentMap} under a bounded cap.
|
|
65
|
-
*
|
|
66
|
-
* @param {object} r
|
|
67
|
-
* @param {{ getTicket: Function }} provider
|
|
68
|
-
* @returns {Promise<{ verified: object, discrepancy: object|null }>}
|
|
69
|
-
*/
|
|
70
|
-
async function verifySingleResult(r, provider) {
|
|
71
|
-
if (r.status !== 'done') {
|
|
72
|
-
return { verified: r, discrepancy: null };
|
|
73
|
-
}
|
|
74
|
-
let ticket;
|
|
75
|
-
try {
|
|
76
|
-
ticket = await provider.getTicket(r.storyId, { fresh: true });
|
|
77
|
-
} catch (err) {
|
|
78
|
-
const message = err?.message ?? String(err);
|
|
79
|
-
return {
|
|
80
|
-
verified: { ...r, status: 'failed', verifyError: message },
|
|
81
|
-
discrepancy: {
|
|
82
|
-
storyId: r.storyId,
|
|
83
|
-
claimed: 'done',
|
|
84
|
-
actual: 'verify-error',
|
|
85
|
-
verifyError: message,
|
|
86
|
-
},
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
const labels = ticket?.labels ?? [];
|
|
90
|
-
const isDone = labels.includes('agent::done') || ticket?.state === 'closed';
|
|
91
|
-
if (isDone) {
|
|
92
|
-
return { verified: r, discrepancy: null };
|
|
93
|
-
}
|
|
94
|
-
const actualLabel =
|
|
95
|
-
labels.find((l) => typeof l === 'string' && l.startsWith('agent::')) ??
|
|
96
|
-
'unknown';
|
|
97
|
-
return {
|
|
98
|
-
verified: { ...r, status: 'failed' },
|
|
99
|
-
discrepancy: { storyId: r.storyId, claimed: 'done', actual: actualLabel },
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Re-fetch each Story's actual ticket state and downgrade any
|
|
105
|
-
* `status: 'done'` claim whose ticket has not actually reached
|
|
106
|
-
* `agent::done` (or `state: 'closed'`). Returns the verified rows plus
|
|
107
|
-
* a list of discrepancies for friction reporting.
|
|
108
|
-
*
|
|
109
|
-
* Verification reads each Story ticket fresh (`{ fresh: true }`) so a
|
|
110
|
-
* stale cache cannot mask the discrepancy. A network failure during
|
|
111
|
-
* verification cannot prove the claim either way, so the row is
|
|
112
|
-
* downgraded to `failed` and a `verify-error` discrepancy is recorded —
|
|
113
|
-
* an unverifiable `done` must not be recorded as `done`, which is what the
|
|
114
|
-
* auto-merge predicate reads as "GitHub agrees everything is done."
|
|
115
|
-
*
|
|
116
|
-
* Story #3024 — verification runs through {@link concurrentMap} under a
|
|
117
|
-
* bounded cap (default 4, override via
|
|
118
|
-
* `delivery.deliverRunner.verifyConcurrencyCap`). Per-row failures are
|
|
119
|
-
* captured inside the mapper so one Story's `getTicket` throw cannot
|
|
120
|
-
* abort the whole batch — the per-row try/catch lives in
|
|
121
|
-
* {@link verifySingleResult} and turns into a `verify-error`
|
|
122
|
-
* discrepancy rather than a rejected mapper. Input order is preserved
|
|
123
|
-
* (mapper-index → output-index), matching the previous serial behaviour.
|
|
124
|
-
*
|
|
125
|
-
* @param {{
|
|
126
|
-
* provider: { getTicket?: Function },
|
|
127
|
-
* results: Array<object>,
|
|
128
|
-
* concurrencyCap?: number,
|
|
129
|
-
* }} args
|
|
130
|
-
*/
|
|
131
|
-
export async function verifyWaveResults({
|
|
132
|
-
provider,
|
|
133
|
-
results,
|
|
134
|
-
concurrencyCap,
|
|
135
|
-
} = {}) {
|
|
136
|
-
if (!provider || typeof provider.getTicket !== 'function') {
|
|
137
|
-
return { verified: results ?? [], discrepancies: [] };
|
|
138
|
-
}
|
|
139
|
-
const cap =
|
|
140
|
-
Number.isInteger(concurrencyCap) && concurrencyCap >= 1
|
|
141
|
-
? concurrencyCap
|
|
142
|
-
: DEFAULT_VERIFY_CONCURRENCY_CAP;
|
|
143
|
-
const rows = results ?? [];
|
|
144
|
-
const outcomes = await concurrentMap(
|
|
145
|
-
rows,
|
|
146
|
-
(r) => verifySingleResult(r, provider),
|
|
147
|
-
{ concurrency: cap },
|
|
148
|
-
);
|
|
149
|
-
const verified = [];
|
|
150
|
-
const discrepancies = [];
|
|
151
|
-
for (const out of outcomes) {
|
|
152
|
-
verified.push(out.verified);
|
|
153
|
-
if (out.discrepancy) discrepancies.push(out.discrepancy);
|
|
154
|
-
}
|
|
155
|
-
return { verified, discrepancies };
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Best-effort cross-look of the dispatch-manifest titles. Failure to read
|
|
160
|
-
* or parse the manifest is non-fatal — empty title is acceptable.
|
|
161
|
-
*
|
|
162
|
-
* @param {{ provider: object, epicId: number }} args
|
|
163
|
-
*/
|
|
164
|
-
export async function loadManifestTitleMap({ provider, epicId }) {
|
|
165
|
-
try {
|
|
166
|
-
const comment = await findStructuredComment(
|
|
167
|
-
provider,
|
|
168
|
-
epicId,
|
|
169
|
-
'dispatch-manifest',
|
|
170
|
-
);
|
|
171
|
-
if (!comment) return new Map();
|
|
172
|
-
const payload = parseFencedJsonComment(comment);
|
|
173
|
-
if (!payload || !Array.isArray(payload.stories)) return new Map();
|
|
174
|
-
return new Map(
|
|
175
|
-
payload.stories
|
|
176
|
-
.map((s) => [Number(s.storyId ?? s.id), String(s.title ?? '')])
|
|
177
|
-
.filter(([id]) => Number.isFinite(id)),
|
|
178
|
-
);
|
|
179
|
-
} catch {
|
|
180
|
-
return new Map();
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Parse / reconcile the per-Story returns (or pass `results` through). Posts
|
|
186
|
-
* a single rolled-up friction comment listing every malformed return on
|
|
187
|
-
* failure — non-fatal if the post itself fails.
|
|
188
|
-
*
|
|
189
|
-
* @returns {Promise<{ resolvedResults: Array, parseFailures: Array }>}
|
|
190
|
-
*/
|
|
191
|
-
export async function resolveResolvedResults({
|
|
192
|
-
provider,
|
|
193
|
-
epicId,
|
|
194
|
-
results,
|
|
195
|
-
returns,
|
|
196
|
-
}) {
|
|
197
|
-
if (returns == null) {
|
|
198
|
-
return { resolvedResults: results, parseFailures: [] };
|
|
199
|
-
}
|
|
200
|
-
const normalized = await normalizeReturns({ provider, returns });
|
|
201
|
-
if (normalized.parseFailures.length > 0) {
|
|
202
|
-
try {
|
|
203
|
-
const body = renderMalformedReturnsFriction({
|
|
204
|
-
epicId,
|
|
205
|
-
failures: normalized.parseFailures,
|
|
206
|
-
});
|
|
207
|
-
await postStructuredComment(provider, epicId, 'friction', body);
|
|
208
|
-
} catch (err) {
|
|
209
|
-
Logger.error(
|
|
210
|
-
`[epic-execute-record-wave] Failed to post malformed-return friction on Epic #${epicId}: ${err?.message ?? err}`,
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return {
|
|
215
|
-
resolvedResults: normalized.results,
|
|
216
|
-
parseFailures: normalized.parseFailures,
|
|
217
|
-
};
|
|
218
|
-
}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* wave-record-notifications.js — webhook-emit helpers for the per-Story
|
|
3
|
-
* status recorder CLI (`epic-execute-record-wave.js`).
|
|
4
|
-
*
|
|
5
|
-
* Story #4155 (Epic #4151) — the Epic `/deliver` runtime cut over from the
|
|
6
|
-
* wave-batch scheduler to the continuous ready-set core, so these emits are
|
|
7
|
-
* no longer keyed to a wave boundary. The recorder fires curated webhook
|
|
8
|
-
* events per recorder beat: `epic-started` once (on the first recorded
|
|
9
|
-
* Story), `epic-progress` with the run's done/total counts (re-derived from
|
|
10
|
-
* the checkpoint's flat per-Story `stories` map), and `epic-blocked` when a
|
|
11
|
-
* Story in this beat blocked or failed. Each helper is fire-and-forget —
|
|
12
|
-
* webhook misconfig or a transient Slack outage must not block the loop.
|
|
13
|
-
*
|
|
14
|
-
* These helpers stay in their own module to keep the parent CLI a thin
|
|
15
|
-
* runner shell. They are not part of the pure projection layer; they
|
|
16
|
-
* intentionally call `notify` (or the test-injected stand-in) and Logger.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import { Logger } from '../Logger.js';
|
|
20
|
-
import {
|
|
21
|
-
emitEpicBlocked,
|
|
22
|
-
emitEpicProgress,
|
|
23
|
-
emitEpicStarted,
|
|
24
|
-
} from './epic-runner/progress-reporter/transport.js';
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Build the notify-bound closure used by the curated webhook emitters. When
|
|
28
|
-
* a test passes `injectedNotify`, we route through it verbatim; otherwise
|
|
29
|
-
* thread `orchestration` + `provider` into the default `notify` so the
|
|
30
|
-
* downstream hook layer has everything it needs.
|
|
31
|
-
*/
|
|
32
|
-
export function buildNotifyFn(injectedNotify, config, provider, defaultNotify) {
|
|
33
|
-
if (injectedNotify) return injectedNotify;
|
|
34
|
-
return (ticketId, payload, opts = {}) =>
|
|
35
|
-
defaultNotify(ticketId, payload, {
|
|
36
|
-
orchestration: config.orchestration,
|
|
37
|
-
provider,
|
|
38
|
-
...opts,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Count Stories in a terminal `done` state across the checkpoint's flat
|
|
44
|
-
* per-Story `stories` status map. Pure helper.
|
|
45
|
-
*
|
|
46
|
-
* @param {Record<string, { status?: string }>|undefined} stories
|
|
47
|
-
* @returns {number}
|
|
48
|
-
*/
|
|
49
|
-
export function countDoneStories(stories) {
|
|
50
|
-
const map = stories && typeof stories === 'object' ? stories : {};
|
|
51
|
-
let done = 0;
|
|
52
|
-
for (const rec of Object.values(map)) {
|
|
53
|
-
if (rec?.status === 'done') done += 1;
|
|
54
|
-
}
|
|
55
|
-
return done;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Fire the curated webhook events for a recorder beat. Each emit is
|
|
60
|
-
* fire-and-forget (the emit helpers swallow webhook misconfiguration), but
|
|
61
|
-
* we still serialise them so the order is deterministic.
|
|
62
|
-
*
|
|
63
|
-
* - `epic-started` fires exactly once: on the very first recorded Story
|
|
64
|
-
* (signalled by `firstRecord === true`), before any Story has been
|
|
65
|
-
* recorded on a prior beat.
|
|
66
|
-
* - `epic-progress` always fires with the run's done/total counts.
|
|
67
|
-
* - `epic-blocked` fires when this beat recorded at least one blocked or
|
|
68
|
-
* failed Story.
|
|
69
|
-
*
|
|
70
|
-
* @param {{
|
|
71
|
-
* injectedNotify?: Function,
|
|
72
|
-
* defaultNotify: Function,
|
|
73
|
-
* config: object,
|
|
74
|
-
* provider: object,
|
|
75
|
-
* epicId: number,
|
|
76
|
-
* firstRecord: boolean,
|
|
77
|
-
* stories: Record<string, { status?: string }>,
|
|
78
|
-
* verified: Array<{ storyId: number, status: string }>,
|
|
79
|
-
* blockedStoryIds: number[],
|
|
80
|
-
* }} args
|
|
81
|
-
*/
|
|
82
|
-
export async function emitRecordNotifications({
|
|
83
|
-
injectedNotify,
|
|
84
|
-
defaultNotify,
|
|
85
|
-
config,
|
|
86
|
-
provider,
|
|
87
|
-
epicId,
|
|
88
|
-
firstRecord,
|
|
89
|
-
stories,
|
|
90
|
-
verified,
|
|
91
|
-
blockedStoryIds,
|
|
92
|
-
}) {
|
|
93
|
-
const notifyFn = buildNotifyFn(
|
|
94
|
-
injectedNotify,
|
|
95
|
-
config,
|
|
96
|
-
provider,
|
|
97
|
-
defaultNotify,
|
|
98
|
-
);
|
|
99
|
-
const map = stories && typeof stories === 'object' ? stories : {};
|
|
100
|
-
const totalStories = Object.keys(map).length;
|
|
101
|
-
const doneStories = countDoneStories(map);
|
|
102
|
-
|
|
103
|
-
if (firstRecord) {
|
|
104
|
-
await emitEpicStarted({
|
|
105
|
-
notify: notifyFn,
|
|
106
|
-
epicId,
|
|
107
|
-
totalStories,
|
|
108
|
-
logger: Logger,
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const blockedIds = Array.isArray(blockedStoryIds) ? blockedStoryIds : [];
|
|
113
|
-
const failedStoryId = (verified ?? []).find(
|
|
114
|
-
(r) => r.status === 'failed',
|
|
115
|
-
)?.storyId;
|
|
116
|
-
const failingStoryId = blockedIds[0] ?? failedStoryId;
|
|
117
|
-
const hasFailure = blockedIds.length > 0 || failedStoryId != null;
|
|
118
|
-
|
|
119
|
-
if (hasFailure) {
|
|
120
|
-
await emitEpicBlocked({
|
|
121
|
-
notify: notifyFn,
|
|
122
|
-
epicId,
|
|
123
|
-
reason: blockedIds.length > 0 ? 'story_blocked' : 'story_failed',
|
|
124
|
-
storyId: failingStoryId,
|
|
125
|
-
logger: Logger,
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
await emitEpicProgress({
|
|
130
|
-
notify: notifyFn,
|
|
131
|
-
epicId,
|
|
132
|
-
done: doneStories,
|
|
133
|
-
total: totalStories,
|
|
134
|
-
phase: 'wave-loop',
|
|
135
|
-
openBlockers: hasFailure
|
|
136
|
-
? [
|
|
137
|
-
{
|
|
138
|
-
reason: blockedIds.length > 0 ? 'story_blocked' : 'story_failed',
|
|
139
|
-
storyId: failingStoryId,
|
|
140
|
-
},
|
|
141
|
-
]
|
|
142
|
-
: [],
|
|
143
|
-
logger: Logger,
|
|
144
|
-
});
|
|
145
|
-
}
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* wave-record-projection.js — pure helpers for the per-Story status
|
|
3
|
-
* recorder CLI (`epic-execute-record-wave.js`).
|
|
4
|
-
*
|
|
5
|
-
* Story #4155 (Epic #4151) — the Epic `/deliver` runtime cut over from the
|
|
6
|
-
* wave-batch scheduler to the continuous ready-set core. The post-dispatch
|
|
7
|
-
* persistence shrank with it: there is no longer a wave-level aggregation
|
|
8
|
-
* (`aggregateWaveStatus`), a `currentWave` advance (`nextCurrentWave`), a
|
|
9
|
-
* next-action classifier (`classifyWaveOutcome`), or a `projectWaveRecord`
|
|
10
|
-
* splice into a `waves[]` history. The recorder now writes each returned
|
|
11
|
-
* Story's **terminal status** into the checkpoint's flat per-Story `stories`
|
|
12
|
-
* map and re-renders the operator rollup from that map.
|
|
13
|
-
*
|
|
14
|
-
* Every export here is pure: no network I/O, no filesystem reads, no
|
|
15
|
-
* spawning. The parent CLI handles the impure work (provider calls,
|
|
16
|
-
* checkpoint reads/writes, webhook emits) and threads the resolved inputs
|
|
17
|
-
* through these helpers.
|
|
18
|
-
*
|
|
19
|
-
* Group the exports by responsibility:
|
|
20
|
-
*
|
|
21
|
-
* - Input validation: `validateResults`, `validateReturnsEntry`,
|
|
22
|
-
* `classifyParsedReturn`, `validateEpic`, `selectInputFlag`.
|
|
23
|
-
* - Normalization: `normalizeReturnsPure`.
|
|
24
|
-
* - Projection: `toRollupRow`.
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
import { parseStoryAgentReturn } from './epic-runner/sub-agent-return.js';
|
|
28
|
-
|
|
29
|
-
/** Per-Story return statuses we accept off `/deliver` sub-agents. */
|
|
30
|
-
export const VALID_STORY_STATUSES = new Set(['done', 'blocked', 'failed']);
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Story status → rollup-row state. Post-fan-out every Story is in a
|
|
34
|
-
* terminal state, so we only emit the three terminal forms here.
|
|
35
|
-
*/
|
|
36
|
-
export const STORY_STATUS_TO_ROW_STATE = {
|
|
37
|
-
done: 'done',
|
|
38
|
-
blocked: 'blocked',
|
|
39
|
-
failed: 'failed',
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Validate and normalize an inbound `--results` array into the per-Story
|
|
44
|
-
* shape the rest of the pipeline consumes.
|
|
45
|
-
*
|
|
46
|
-
* @param {unknown} raw
|
|
47
|
-
*/
|
|
48
|
-
export function validateResults(raw) {
|
|
49
|
-
if (!Array.isArray(raw)) {
|
|
50
|
-
throw new TypeError(
|
|
51
|
-
'epic-execute-record-wave: --results must be a JSON array of per-Story result objects',
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
return raw.map((entry, idx) => {
|
|
55
|
-
if (!entry || typeof entry !== 'object') {
|
|
56
|
-
throw new TypeError(
|
|
57
|
-
`epic-execute-record-wave: results[${idx}] must be an object; got ${typeof entry}`,
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
const storyId = Number(entry.storyId ?? entry.id);
|
|
61
|
-
if (!Number.isInteger(storyId) || storyId <= 0) {
|
|
62
|
-
throw new TypeError(
|
|
63
|
-
`epic-execute-record-wave: results[${idx}].storyId must be a positive integer; got ${JSON.stringify(entry.storyId)}`,
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
const status = String(entry.status ?? '');
|
|
67
|
-
if (!VALID_STORY_STATUSES.has(status)) {
|
|
68
|
-
throw new RangeError(
|
|
69
|
-
`epic-execute-record-wave: results[${idx}].status "${status}" must be one of: ${[...VALID_STORY_STATUSES].join(', ')}`,
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
const out = { storyId, status };
|
|
73
|
-
if (typeof entry.phase === 'string') out.phase = entry.phase;
|
|
74
|
-
if (entry.blockerCommentId != null) {
|
|
75
|
-
out.blockerCommentId = String(entry.blockerCommentId);
|
|
76
|
-
}
|
|
77
|
-
return out;
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Pure validator for a single `--returns[]` entry. Throws the same
|
|
83
|
-
* `TypeError`s the outer loop used to throw inline, returning a
|
|
84
|
-
* `{ storyId, returnText }` pair on success. Extracted so `normalizeReturns`
|
|
85
|
-
* can route each entry through the same validate → parse → reconcile path
|
|
86
|
-
* without nesting four conditionals deep.
|
|
87
|
-
*/
|
|
88
|
-
export function validateReturnsEntry(entry, idx) {
|
|
89
|
-
if (!entry || typeof entry !== 'object') {
|
|
90
|
-
throw new TypeError(
|
|
91
|
-
`epic-execute-record-wave: returns[${idx}] must be an object; got ${typeof entry}`,
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
const storyId = Number(entry.storyId ?? entry.id);
|
|
95
|
-
if (!Number.isInteger(storyId) || storyId <= 0) {
|
|
96
|
-
throw new TypeError(
|
|
97
|
-
`epic-execute-record-wave: returns[${idx}].storyId must be a positive integer; got ${JSON.stringify(entry.storyId)}`,
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
let returnText;
|
|
101
|
-
if (typeof entry.returnText === 'string') {
|
|
102
|
-
returnText = entry.returnText;
|
|
103
|
-
} else if (entry.returnText == null) {
|
|
104
|
-
returnText = '';
|
|
105
|
-
} else {
|
|
106
|
-
returnText = JSON.stringify(entry.returnText);
|
|
107
|
-
}
|
|
108
|
-
return { storyId, returnText };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Pure helper: classify a parsed sub-agent return for a known `storyId`.
|
|
113
|
-
* Returns either `{ ok: true, value }` (use the parsed envelope as-is) or
|
|
114
|
-
* `{ ok: false, error }` (caller must reconcile from GitHub and record a
|
|
115
|
-
* parse failure with the message).
|
|
116
|
-
*/
|
|
117
|
-
export function classifyParsedReturn(parsed, storyId) {
|
|
118
|
-
if (parsed.ok && Number(parsed.value.storyId) === storyId) {
|
|
119
|
-
return { ok: true, value: parsed.value };
|
|
120
|
-
}
|
|
121
|
-
const error = parsed.ok
|
|
122
|
-
? `parsed envelope storyId ${parsed.value.storyId} disagrees with expected ${storyId}`
|
|
123
|
-
: parsed.error;
|
|
124
|
-
return { ok: false, error };
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Build the rollup-row shape the unified `epic-run-progress` writer
|
|
129
|
-
* consumes. Returns `{ id, title, state, blockerCommentId? }`.
|
|
130
|
-
*/
|
|
131
|
-
export function toRollupRow(verified, titleById) {
|
|
132
|
-
const row = {
|
|
133
|
-
id: verified.storyId,
|
|
134
|
-
title: titleById.get(verified.storyId) ?? '',
|
|
135
|
-
state: STORY_STATUS_TO_ROW_STATE[verified.status] ?? 'unknown',
|
|
136
|
-
};
|
|
137
|
-
if (verified.status === 'blocked' && verified.blockerCommentId != null) {
|
|
138
|
-
row.blockerCommentId = String(verified.blockerCommentId);
|
|
139
|
-
}
|
|
140
|
-
return row;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/** Validate the core `{ epicId }` invariant. Throws on bad input. */
|
|
144
|
-
export function validateEpic(epicId) {
|
|
145
|
-
if (!Number.isInteger(epicId) || epicId <= 0) {
|
|
146
|
-
throw new TypeError(
|
|
147
|
-
'runEpicExecuteRecordWave: --epic must be a positive integer',
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Pure helper: enforce the XOR contract between `--results` and `--returns`.
|
|
154
|
-
* Throws on "neither" / "both"; otherwise returns the chosen flag name so
|
|
155
|
-
* the CLI can route to `parseInputArg` with a single branch.
|
|
156
|
-
*/
|
|
157
|
-
export function selectInputFlag(hasResults, hasReturns) {
|
|
158
|
-
if (hasResults && hasReturns) {
|
|
159
|
-
throw new TypeError(
|
|
160
|
-
'epic-execute-record-wave: pass --results OR --returns, not both',
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
if (!hasResults && !hasReturns) {
|
|
164
|
-
throw new TypeError(
|
|
165
|
-
'epic-execute-record-wave: --results or --returns is required',
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
return hasResults ? 'results' : 'returns';
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Normalize a return-text array into the parsed-results shape, returning the
|
|
173
|
-
* envelopes that parsed cleanly and a list of failures for entries that
|
|
174
|
-
* disagreed with their expected `storyId` or were not envelope-shaped. This
|
|
175
|
-
* is the pure half of `normalizeReturns` in the CLI; the impure half
|
|
176
|
-
* (`reconcileStoryFromGitHub` on each failure) is bound by the caller via
|
|
177
|
-
* the `reconcile` dependency.
|
|
178
|
-
*
|
|
179
|
-
* Tests pin the success path without binding `reconcile`; the CLI binds it
|
|
180
|
-
* to the network helper.
|
|
181
|
-
*
|
|
182
|
-
* @param {object} args
|
|
183
|
-
* @param {Array<{ storyId: number, returnText: string }>} args.returns
|
|
184
|
-
* @param {(args: { storyId: number }) => Promise<object> | object} [args.reconcile]
|
|
185
|
-
* Optional async hook used to fetch a fallback row when parsing fails. If
|
|
186
|
-
* omitted, parse failures push a placeholder `{ storyId, status: 'failed' }`
|
|
187
|
-
* row so the caller can still record without I/O.
|
|
188
|
-
*/
|
|
189
|
-
export async function normalizeReturnsPure({ returns, reconcile } = {}) {
|
|
190
|
-
if (!Array.isArray(returns)) {
|
|
191
|
-
throw new TypeError(
|
|
192
|
-
'epic-execute-record-wave: --returns must be a JSON array of { storyId, returnText } objects',
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
const results = [];
|
|
196
|
-
const parseFailures = [];
|
|
197
|
-
for (const [idx, entry] of returns.entries()) {
|
|
198
|
-
const { storyId, returnText } = validateReturnsEntry(entry, idx);
|
|
199
|
-
const parsed = parseStoryAgentReturn(returnText);
|
|
200
|
-
const classified = classifyParsedReturn(parsed, storyId);
|
|
201
|
-
if (classified.ok) {
|
|
202
|
-
results.push(classified.value);
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
const fallback = reconcile
|
|
206
|
-
? await reconcile({ storyId })
|
|
207
|
-
: { storyId, status: 'failed' };
|
|
208
|
-
results.push(fallback);
|
|
209
|
-
parseFailures.push({ storyId, error: classified.error, returnText });
|
|
210
|
-
}
|
|
211
|
-
return { results, parseFailures };
|
|
212
|
-
}
|