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,213 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* planning-context-budget.js
|
|
3
|
-
*
|
|
4
|
-
* Bounded planning-context budget for the `--emit-context` planning scripts
|
|
5
|
-
* (Epic #817 Story 9). Provides a summary representation of large markdown
|
|
6
|
-
* payloads (project docs, Epic body, Tech Spec body) so the host LLM is not
|
|
7
|
-
* handed multi-100KB envelopes when the underlying material exceeds the
|
|
8
|
-
* configured `maxBytes` budget.
|
|
9
|
-
*
|
|
10
|
-
* Two pure helpers:
|
|
11
|
-
* - `summarizeDoc(filePath, content, maxBytes)` extracts headings + bounded
|
|
12
|
-
* excerpts for one document.
|
|
13
|
-
* - `applyBudget(items, limits, opts)` decides full vs summary for a
|
|
14
|
-
* collection of `{ path, content }` items based on `summaryMode` and the
|
|
15
|
-
* total payload size.
|
|
16
|
-
*
|
|
17
|
-
* Both functions are deterministic and have no I/O.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
const HEADING_RE = /^(#{2,3})\s+(.+?)\s*$/;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Default per-excerpt cap so a single section heading does not consume the
|
|
24
|
-
* entire per-doc byte budget. The bounded sum across excerpts is enforced
|
|
25
|
-
* separately by {@link summarizeDoc}.
|
|
26
|
-
*/
|
|
27
|
-
const DEFAULT_PER_EXCERPT_BYTES = 800;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Default planning-context limits when callers do not pass through
|
|
31
|
-
* `getLimits(config).planningContext`. Mirrors `LIMITS_DEFAULTS` in
|
|
32
|
-
* `lib/config/limits.js` so this module is usable in standalone tests.
|
|
33
|
-
*/
|
|
34
|
-
export const PLANNING_CONTEXT_DEFAULTS = Object.freeze({
|
|
35
|
-
maxBytes: 50000,
|
|
36
|
-
summaryMode: 'auto',
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
function byteLen(s) {
|
|
40
|
-
if (s == null) return 0;
|
|
41
|
-
return Buffer.byteLength(String(s), 'utf-8');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function extractHeadings(content) {
|
|
45
|
-
if (!content) return [];
|
|
46
|
-
const lines = String(content).split(/\r?\n/);
|
|
47
|
-
const out = [];
|
|
48
|
-
for (const line of lines) {
|
|
49
|
-
const m = HEADING_RE.exec(line);
|
|
50
|
-
if (m) out.push({ level: m[1].length, text: m[2] });
|
|
51
|
-
}
|
|
52
|
-
return out;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Split a markdown body into preamble + per-heading sections so excerpts can
|
|
57
|
-
* be emitted with the heading they belong to. Lines preceding the first
|
|
58
|
-
* `## ` / `### ` heading become the `preamble` section (heading: null).
|
|
59
|
-
*/
|
|
60
|
-
function splitSections(content) {
|
|
61
|
-
if (!content) return [];
|
|
62
|
-
const lines = String(content).split(/\r?\n/);
|
|
63
|
-
const sections = [{ heading: null, body: [] }];
|
|
64
|
-
for (const line of lines) {
|
|
65
|
-
const m = HEADING_RE.exec(line);
|
|
66
|
-
if (m) {
|
|
67
|
-
sections.push({ heading: m[2], body: [] });
|
|
68
|
-
} else {
|
|
69
|
-
sections[sections.length - 1].body.push(line);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return sections;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Trim a multi-line section to the first non-empty paragraph, capped at
|
|
77
|
-
* `maxBytes` of utf-8. Preserves whitespace inside the kept paragraph but
|
|
78
|
-
* collapses leading/trailing blank lines so excerpts stay compact.
|
|
79
|
-
*/
|
|
80
|
-
function firstParagraph(lines, maxBytes) {
|
|
81
|
-
const text = lines.join('\n').replace(/^\s+|\s+$/g, '');
|
|
82
|
-
if (!text) return '';
|
|
83
|
-
// Take up to the first blank-line break (paragraph boundary).
|
|
84
|
-
const para = text.split(/\n\s*\n/)[0] ?? '';
|
|
85
|
-
const trimmed = para.trim();
|
|
86
|
-
if (byteLen(trimmed) <= maxBytes) return trimmed;
|
|
87
|
-
// Hard truncate at maxBytes utf-8 with an ellipsis marker so callers can
|
|
88
|
-
// tell the excerpt is bounded rather than corrupt.
|
|
89
|
-
const buf = Buffer.from(trimmed, 'utf-8').subarray(0, maxBytes);
|
|
90
|
-
// Avoid splitting a multi-byte codepoint at the boundary.
|
|
91
|
-
let safe = buf.toString('utf-8');
|
|
92
|
-
if (safe.length > 1 && safe.charCodeAt(safe.length - 1) === 0xfffd) {
|
|
93
|
-
safe = safe.slice(0, -1);
|
|
94
|
-
}
|
|
95
|
-
return `${safe.replace(/\s+$/, '')}…`;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Summarise a single markdown doc. Emits headings + per-section excerpts
|
|
100
|
-
* (preamble first), each bounded so a runaway section never blows the budget.
|
|
101
|
-
*
|
|
102
|
-
* @param {string} filePath repo-relative path used as the `path` field
|
|
103
|
-
* @param {string} content full markdown body
|
|
104
|
-
* @param {number} [maxBytes=50000] total per-doc byte budget for excerpts
|
|
105
|
-
* @returns {{ path: string, headings: string[], excerpts: Array<{heading: string|null, snippet: string}>, byteSize: number }}
|
|
106
|
-
*/
|
|
107
|
-
export function summarizeDoc(filePath, content, maxBytes = 50000) {
|
|
108
|
-
const safeContent = typeof content === 'string' ? content : '';
|
|
109
|
-
const byteSize = byteLen(safeContent);
|
|
110
|
-
const headingObjs = extractHeadings(safeContent);
|
|
111
|
-
const headings = headingObjs.map((h) => h.text);
|
|
112
|
-
|
|
113
|
-
const sections = splitSections(safeContent);
|
|
114
|
-
const perExcerptCap = Math.min(
|
|
115
|
-
DEFAULT_PER_EXCERPT_BYTES,
|
|
116
|
-
Math.max(120, Math.floor(maxBytes / Math.max(1, sections.length))),
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
const excerpts = [];
|
|
120
|
-
let used = 0;
|
|
121
|
-
for (const sec of sections) {
|
|
122
|
-
if (used >= maxBytes) break;
|
|
123
|
-
const remaining = Math.max(0, maxBytes - used);
|
|
124
|
-
const cap = Math.min(perExcerptCap, remaining);
|
|
125
|
-
const snippet = firstParagraph(sec.body, cap);
|
|
126
|
-
if (!snippet) continue;
|
|
127
|
-
excerpts.push({ heading: sec.heading, snippet });
|
|
128
|
-
used += byteLen(snippet);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
path: filePath,
|
|
133
|
-
headings,
|
|
134
|
-
excerpts,
|
|
135
|
-
byteSize,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function normalizeItems(items) {
|
|
140
|
-
if (!Array.isArray(items)) return [];
|
|
141
|
-
return items
|
|
142
|
-
.filter((it) => it && typeof it === 'object')
|
|
143
|
-
.map((it) => ({
|
|
144
|
-
path: it.path ?? it.name ?? '',
|
|
145
|
-
content: typeof it.content === 'string' ? it.content : '',
|
|
146
|
-
}));
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function totalBytes(items) {
|
|
150
|
-
let n = 0;
|
|
151
|
-
for (const it of items) n += byteLen(it.content);
|
|
152
|
-
return n;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function buildFullItems(items) {
|
|
156
|
-
return items.map((it) => ({
|
|
157
|
-
path: it.path,
|
|
158
|
-
content: it.content,
|
|
159
|
-
byteSize: byteLen(it.content),
|
|
160
|
-
}));
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function buildSummaryItems(items, maxBytes) {
|
|
164
|
-
// Distribute the byte budget across docs proportional to their size, with
|
|
165
|
-
// a per-doc floor so even tiny docs get a heading + tiny excerpt.
|
|
166
|
-
const total = totalBytes(items) || 1;
|
|
167
|
-
const floor = Math.max(512, Math.floor(maxBytes / Math.max(1, items.length)));
|
|
168
|
-
return items.map((it) => {
|
|
169
|
-
const share = Math.max(
|
|
170
|
-
floor,
|
|
171
|
-
Math.floor((byteLen(it.content) / total) * maxBytes),
|
|
172
|
-
);
|
|
173
|
-
return summarizeDoc(it.path, it.content, share);
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Apply the planning-context budget to a collection of doc-shaped items.
|
|
179
|
-
*
|
|
180
|
-
* @param {Array<{path?: string, name?: string, content: string}>} items
|
|
181
|
-
* @param {{ maxBytes?: number, summaryMode?: 'auto'|'always'|'never' }} [limits]
|
|
182
|
-
* @param {{ fullContext?: boolean }} [opts] — `fullContext: true` forces full
|
|
183
|
-
* mode regardless of `summaryMode` (mirrors the `--full-context` CLI flag).
|
|
184
|
-
* @returns {{ mode: 'full'|'summary', items: Array<object>, totalBytes: number }}
|
|
185
|
-
*/
|
|
186
|
-
export function applyBudget(items, limits = {}, opts = {}) {
|
|
187
|
-
const merged = { ...PLANNING_CONTEXT_DEFAULTS, ...(limits || {}) };
|
|
188
|
-
const { maxBytes, summaryMode } = merged;
|
|
189
|
-
const { fullContext = false } = opts;
|
|
190
|
-
|
|
191
|
-
const norm = normalizeItems(items);
|
|
192
|
-
const total = totalBytes(norm);
|
|
193
|
-
|
|
194
|
-
if (fullContext || summaryMode === 'never') {
|
|
195
|
-
return { mode: 'full', items: buildFullItems(norm), totalBytes: total };
|
|
196
|
-
}
|
|
197
|
-
if (summaryMode === 'always') {
|
|
198
|
-
return {
|
|
199
|
-
mode: 'summary',
|
|
200
|
-
items: buildSummaryItems(norm, maxBytes),
|
|
201
|
-
totalBytes: total,
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
// auto — summarise iff payload exceeds the budget.
|
|
205
|
-
if (total > maxBytes) {
|
|
206
|
-
return {
|
|
207
|
-
mode: 'summary',
|
|
208
|
-
items: buildSummaryItems(norm, maxBytes),
|
|
209
|
-
totalBytes: total,
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
return { mode: 'full', items: buildFullItems(norm), totalBytes: total };
|
|
213
|
-
}
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* planning-risk.js — derive the Epic planning-risk envelope from a
|
|
3
|
-
* planner-authored risk verdict.
|
|
4
|
-
*
|
|
5
|
-
* Pure ESM, no I/O. The planner (the `epic-plan-spec-author` Skill) judges
|
|
6
|
-
* the Epic it just specced and supplies a verdict of shape
|
|
7
|
-
* `{ axes: [{ axis, level, rationale }], summary }`, validated against
|
|
8
|
-
* `.agents/schemas/risk-verdict.schema.json` before it reaches this module.
|
|
9
|
-
* This module owns the deterministic control-flow outputs — overall level,
|
|
10
|
-
* review requirement, acceptance disposition, and gate decision — so the
|
|
11
|
-
* model supplies the *judgment input* while the harness owns the *gate
|
|
12
|
-
* decision* (Epic #3865 hard cutover from the retired keyword-regex
|
|
13
|
-
* classifier; see `docs/roadmap.md` Part 1).
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/** @typedef {'low' | 'medium' | 'high'} RiskLevel */
|
|
17
|
-
/** @typedef {'required' | 'recommended' | 'not-applicable'} AcceptanceDisposition */
|
|
18
|
-
/** @typedef {'review-required' | 'auto-proceed'} GateDecision */
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @typedef {Object} PlanningRiskAxis
|
|
22
|
-
* @property {string} axis
|
|
23
|
-
* @property {RiskLevel} level
|
|
24
|
-
* @property {string} rationale
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @typedef {Object} RiskVerdict
|
|
29
|
-
* @property {PlanningRiskAxis[]} axes
|
|
30
|
-
* @property {string} summary
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @typedef {Object} PlanningRiskEnvelope
|
|
35
|
-
* @property {PlanningRiskAxis[]} axes
|
|
36
|
-
* @property {RiskLevel} overallLevel
|
|
37
|
-
* @property {boolean} requiresReview
|
|
38
|
-
* @property {AcceptanceDisposition} acceptanceDisposition
|
|
39
|
-
* @property {GateDecision} gateDecision
|
|
40
|
-
* @property {string} [acceptanceWaivedReason] Present only when the
|
|
41
|
-
* acceptance disposition was forced to `not-applicable` by a non-axis
|
|
42
|
-
* signal (currently: no BDD runner detected). An operator-visible
|
|
43
|
-
* rationale so the override is never silent (Story #4145).
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* @typedef {Object} BddRunnerProbe
|
|
48
|
-
* @property {string|null} runner
|
|
49
|
-
* @property {boolean} fallback `true` when no supported BDD runner was
|
|
50
|
-
* detected in the project (`verifyBddRunnerPendingTag`).
|
|
51
|
-
* @property {string} [reason]
|
|
52
|
-
*/
|
|
53
|
-
|
|
54
|
-
const LEVEL_RANK = Object.freeze({ low: 0, medium: 1, high: 2 });
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Axes whose presence forces a `required` acceptance disposition. Mirrored
|
|
58
|
-
* by the `axis` enum in `.agents/schemas/risk-verdict.schema.json` — keep
|
|
59
|
-
* the two lists in sync.
|
|
60
|
-
*/
|
|
61
|
-
export const REQUIRED_AXES = new Set([
|
|
62
|
-
'visible-behavior',
|
|
63
|
-
'public-api',
|
|
64
|
-
'security',
|
|
65
|
-
'data-migration',
|
|
66
|
-
'billing',
|
|
67
|
-
'destructive-mutation',
|
|
68
|
-
'critical-workflow',
|
|
69
|
-
]);
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Axes that, when they are the only signals present, waive the acceptance
|
|
73
|
-
* spec (`not-applicable`). Mirrored by the `axis` enum in
|
|
74
|
-
* `.agents/schemas/risk-verdict.schema.json` — keep the two lists in sync.
|
|
75
|
-
*/
|
|
76
|
-
export const NOT_APPLICABLE_AXES = new Set([
|
|
77
|
-
'docs-only',
|
|
78
|
-
'test-harness',
|
|
79
|
-
'internal-refactor',
|
|
80
|
-
]);
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* @param {PlanningRiskAxis[]} axes
|
|
84
|
-
* @returns {RiskLevel}
|
|
85
|
-
*/
|
|
86
|
-
function resolveOverallLevel(axes) {
|
|
87
|
-
if (axes.length === 0) return 'low';
|
|
88
|
-
return axes.reduce(
|
|
89
|
-
(highest, entry) =>
|
|
90
|
-
LEVEL_RANK[entry.level] > LEVEL_RANK[highest] ? entry.level : highest,
|
|
91
|
-
'low',
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* @param {PlanningRiskAxis[]} axes
|
|
97
|
-
* @param {RiskLevel} overallLevel
|
|
98
|
-
* @returns {AcceptanceDisposition}
|
|
99
|
-
*/
|
|
100
|
-
function resolveAcceptanceDisposition(axes, overallLevel) {
|
|
101
|
-
const requiredAxes = axes.filter((entry) => REQUIRED_AXES.has(entry.axis));
|
|
102
|
-
if (requiredAxes.length > 0) {
|
|
103
|
-
return 'required';
|
|
104
|
-
}
|
|
105
|
-
if (
|
|
106
|
-
overallLevel === 'medium' ||
|
|
107
|
-
axes.some((entry) => entry.level === 'medium')
|
|
108
|
-
) {
|
|
109
|
-
return 'recommended';
|
|
110
|
-
}
|
|
111
|
-
if (
|
|
112
|
-
axes.length > 0 &&
|
|
113
|
-
axes.every((entry) => NOT_APPLICABLE_AXES.has(entry.axis))
|
|
114
|
-
) {
|
|
115
|
-
return 'not-applicable';
|
|
116
|
-
}
|
|
117
|
-
if (overallLevel === 'low') return 'not-applicable';
|
|
118
|
-
return 'recommended';
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* @param {RiskLevel} overallLevel
|
|
123
|
-
* @param {PlanningRiskAxis[]} axes
|
|
124
|
-
* @returns {boolean}
|
|
125
|
-
*/
|
|
126
|
-
function resolveRequiresReview(overallLevel, axes) {
|
|
127
|
-
if (overallLevel === 'high') return true;
|
|
128
|
-
if (overallLevel === 'medium') {
|
|
129
|
-
return axes.some(
|
|
130
|
-
(entry) =>
|
|
131
|
-
entry.level === 'medium' &&
|
|
132
|
-
(REQUIRED_AXES.has(entry.axis) || entry.axis === 'visible-behavior'),
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Derive the stable planningRisk envelope from a schema-validated planner
|
|
140
|
-
* verdict. Pure derivation — schema validation happens at the read boundary
|
|
141
|
-
* (`plan-persist.js` via `loadRiskVerdict`), never here, so a malformed verdict fails closed
|
|
142
|
-
* before this function runs.
|
|
143
|
-
*
|
|
144
|
-
* **No-BDD-runner waiver (Story #4145).** The acceptance disposition the risk
|
|
145
|
-
* axes derive presumes a BDD runner exists to satisfy an authored AC table.
|
|
146
|
-
* When `opts.bddRunner.fallback === true` (no supported runner detected — e.g.
|
|
147
|
-
* a `node:test` repo with no `tests/features/**`), an authored AC table can
|
|
148
|
-
* never be reconciled by `@epic-<id>-ac-*` feature tags, so `/deliver`
|
|
149
|
-
* finalize would abort. In that case the disposition is **forced** to
|
|
150
|
-
* `not-applicable` regardless of the risk axes, and `acceptanceWaivedReason`
|
|
151
|
-
* records the override so it is operator-visible, not silent. The
|
|
152
|
-
* `requiresReview` / `gateDecision` outputs are unaffected — a high-risk
|
|
153
|
-
* Epic still routes to review; only the acceptance-spec requirement is
|
|
154
|
-
* waived. Repos that ship a BDD runner (`fallback !== true`) are unaffected.
|
|
155
|
-
*
|
|
156
|
-
* @param {RiskVerdict} [verdict]
|
|
157
|
-
* @param {{ bddRunner?: BddRunnerProbe|null }} [opts]
|
|
158
|
-
* @returns {PlanningRiskEnvelope}
|
|
159
|
-
*/
|
|
160
|
-
export function deriveRiskEnvelope(verdict = {}, { bddRunner = null } = {}) {
|
|
161
|
-
const axes = (Array.isArray(verdict.axes) ? verdict.axes : []).map(
|
|
162
|
-
({ axis, level, rationale }) => ({ axis, level, rationale }),
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
const overallLevel = resolveOverallLevel(axes);
|
|
166
|
-
const axisDisposition = resolveAcceptanceDisposition(axes, overallLevel);
|
|
167
|
-
const requiresReview = resolveRequiresReview(overallLevel, axes);
|
|
168
|
-
const gateDecision = requiresReview ? 'review-required' : 'auto-proceed';
|
|
169
|
-
|
|
170
|
-
const noBddRunner = bddRunner?.fallback === true;
|
|
171
|
-
// Force the waiver only when the axes would otherwise have required (or
|
|
172
|
-
// recommended) an AC table; if the disposition is already not-applicable
|
|
173
|
-
// there is nothing to override and no waiver rationale to surface.
|
|
174
|
-
const forceWaiver = noBddRunner && axisDisposition !== 'not-applicable';
|
|
175
|
-
const acceptanceDisposition = forceWaiver
|
|
176
|
-
? 'not-applicable'
|
|
177
|
-
: axisDisposition;
|
|
178
|
-
|
|
179
|
-
/** @type {PlanningRiskEnvelope} */
|
|
180
|
-
const envelope = {
|
|
181
|
-
axes,
|
|
182
|
-
overallLevel,
|
|
183
|
-
requiresReview,
|
|
184
|
-
acceptanceDisposition,
|
|
185
|
-
gateDecision,
|
|
186
|
-
};
|
|
187
|
-
if (forceWaiver) {
|
|
188
|
-
envelope.acceptanceWaivedReason =
|
|
189
|
-
`no BDD runner detected (${bddRunner?.reason ?? 'no-bdd-runner-detected'}) — ` +
|
|
190
|
-
`an authored acceptance-spec AC table cannot be reconciled by feature tags, ` +
|
|
191
|
-
`so the acceptance disposition is waived to not-applicable (was ${axisDisposition}).`;
|
|
192
|
-
}
|
|
193
|
-
return envelope;
|
|
194
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* phases/branch-cleanup.js — post-merge Story branch deletion phase.
|
|
3
|
-
*
|
|
4
|
-
* Delegates the "delete this branch from local + remote, treat not-found
|
|
5
|
-
* as success" idempotency contract to `lib/git-branch-cleanup.js` so the
|
|
6
|
-
* deletion rules live in one place. A local delete failure is logged
|
|
7
|
-
* loudly (operators usually need to investigate a stale worktree),
|
|
8
|
-
* while a remote not-found is treated as a no-op.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { deleteBranchBoth } from '../../../git-branch-cleanup.js';
|
|
12
|
-
|
|
13
|
-
function reapPhaseLogger(progress) {
|
|
14
|
-
return progress ?? (() => {});
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function branchCleanupPhase(ctx, state = {}) {
|
|
18
|
-
const {
|
|
19
|
-
storyBranch,
|
|
20
|
-
repoRoot,
|
|
21
|
-
progress,
|
|
22
|
-
logger,
|
|
23
|
-
branchCleanup = deleteBranchBoth,
|
|
24
|
-
} = ctx;
|
|
25
|
-
const log = reapPhaseLogger(progress);
|
|
26
|
-
log('CLEANUP', `Deleting story branch: ${storyBranch}`);
|
|
27
|
-
|
|
28
|
-
const result = branchCleanup(storyBranch, {
|
|
29
|
-
cwd: repoRoot,
|
|
30
|
-
noVerify: true,
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
if (!result.local.deleted) {
|
|
34
|
-
const stderr = (result.local.stderr || '').trim();
|
|
35
|
-
const reapStatus = state.worktreeReap?.status;
|
|
36
|
-
logger.error(
|
|
37
|
-
` Local branch ${storyBranch} delete failed: ${stderr || 'unknown'}. ` +
|
|
38
|
-
`Check for stale worktrees (git worktree list).` +
|
|
39
|
-
(reapStatus ? ` worktreeReap=${reapStatus}.` : ''),
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
if (result.remote.deleted) {
|
|
43
|
-
if (result.remote.reason === 'not-found') {
|
|
44
|
-
log('CLEANUP', `Remote branch ${storyBranch} not found — skipped`);
|
|
45
|
-
} else {
|
|
46
|
-
log('CLEANUP', `✅ Remote branch ${storyBranch} deleted`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
localDeleted: result.local.deleted,
|
|
52
|
-
remoteDeleted: result.remote.deleted,
|
|
53
|
-
localReason: result.local.reason,
|
|
54
|
-
remoteReason: result.remote.reason,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* phases/dashboard-refresh.js — regenerate the dispatch manifest after
|
|
3
|
-
* a Story merges into its Epic branch. Honors `--skip-dashboard` so
|
|
4
|
-
* operators running an out-of-band close can suppress the I/O.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { generateAndSaveManifest } from '../../../../dispatcher.js';
|
|
8
|
-
|
|
9
|
-
function reapPhaseLogger(progress) {
|
|
10
|
-
return progress ?? (() => {});
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export async function dashboardRefreshPhase(ctx) {
|
|
14
|
-
const {
|
|
15
|
-
epicId,
|
|
16
|
-
provider,
|
|
17
|
-
skipDashboard,
|
|
18
|
-
progress,
|
|
19
|
-
generateManifestFn = generateAndSaveManifest,
|
|
20
|
-
} = ctx;
|
|
21
|
-
const log = reapPhaseLogger(progress);
|
|
22
|
-
if (skipDashboard) {
|
|
23
|
-
log(
|
|
24
|
-
'DASHBOARD',
|
|
25
|
-
'⏭️ Skipping dashboard refresh (--skip-dashboard flag set)',
|
|
26
|
-
);
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
log('DASHBOARD', 'Regenerating dispatch manifest...');
|
|
30
|
-
await generateManifestFn(epicId, true, { provider });
|
|
31
|
-
log('DASHBOARD', '✅ Dashboard manifest updated (temp/)');
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* phases/notification.js — post-merge story-complete notification phase.
|
|
3
|
-
*
|
|
4
|
-
* Fires a single consolidated story-merged webhook, then a rolled-up
|
|
5
|
-
* `epic-progress` webhook (comment-suppressed) so operators see the
|
|
6
|
-
* Epic's stories-done count tick up at each story-close without
|
|
7
|
-
* subscribing to the per-story `story-merged` channel. The rolled-up
|
|
8
|
-
* dispatch is best-effort — a flaky webhook MUST NOT block story-close.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { notify } from '../../../../notify.js';
|
|
12
|
-
import { Logger } from '../../../Logger.js';
|
|
13
|
-
|
|
14
|
-
function reapPhaseLogger(progress) {
|
|
15
|
-
return progress ?? (() => {});
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function notificationPhase(ctx, state) {
|
|
19
|
-
const {
|
|
20
|
-
epicId,
|
|
21
|
-
storyId,
|
|
22
|
-
story,
|
|
23
|
-
epicBranch,
|
|
24
|
-
config,
|
|
25
|
-
progress,
|
|
26
|
-
provider,
|
|
27
|
-
notifyFn = notify,
|
|
28
|
-
logger = Logger,
|
|
29
|
-
} = ctx;
|
|
30
|
-
const closedTickets = state.ticketClosure?.closedTickets ?? [];
|
|
31
|
-
const log = reapPhaseLogger(progress);
|
|
32
|
-
log('NOTIFY', `Sending story-complete notification for Story #${storyId}...`);
|
|
33
|
-
await notifyFn(
|
|
34
|
-
epicId,
|
|
35
|
-
{
|
|
36
|
-
severity: 'medium',
|
|
37
|
-
message: `✅ Story #${storyId} — *${story.title}* — has been completed and merged into \`${epicBranch}\`. ${closedTickets.length} ticket(s) closed.`,
|
|
38
|
-
event: 'story-merged',
|
|
39
|
-
level: 'story',
|
|
40
|
-
epicId,
|
|
41
|
-
},
|
|
42
|
-
{ config },
|
|
43
|
-
);
|
|
44
|
-
// Fire a rolled-up `epic-progress` webhook so operators see the Epic's
|
|
45
|
-
// overall stories-done count tick up at each story-close, without
|
|
46
|
-
// subscribing to the per-story `story-merged` channel. Comment is
|
|
47
|
-
// suppressed (skipComment: true) — the operator-facing GitHub
|
|
48
|
-
// comment is owned by the wave-record path; this fire is webhook-only.
|
|
49
|
-
// Failures are swallowed by design (warn-then-continue) so a flaky
|
|
50
|
-
// webhook never blocks story-close.
|
|
51
|
-
if (provider && epicId) {
|
|
52
|
-
try {
|
|
53
|
-
const subs = (await provider.getSubTickets?.(epicId)) ?? [];
|
|
54
|
-
const stories = subs.filter(
|
|
55
|
-
(t) => Array.isArray(t.labels) && t.labels.includes('type::story'),
|
|
56
|
-
);
|
|
57
|
-
const total = stories.length;
|
|
58
|
-
const done = stories.filter((s) => s.state === 'closed').length;
|
|
59
|
-
const pct = total === 0 ? 0 : Math.round((done / total) * 100);
|
|
60
|
-
await notifyFn(
|
|
61
|
-
epicId,
|
|
62
|
-
{
|
|
63
|
-
severity: 'medium',
|
|
64
|
-
message: `Epic #${epicId} progress · ${done}/${total} stories done (${pct}%) · Story #${storyId} merged`,
|
|
65
|
-
event: 'epic-progress',
|
|
66
|
-
level: 'epic',
|
|
67
|
-
epicId,
|
|
68
|
-
},
|
|
69
|
-
{ config, skipComment: true },
|
|
70
|
-
);
|
|
71
|
-
} catch (err) {
|
|
72
|
-
logger?.warn?.(
|
|
73
|
-
`[notificationPhase] rolled-up epic-progress dispatch failed (swallowed): ${err?.message ?? err}`,
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
log('NOTIFY', '✅ Notification sent');
|
|
78
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* phases/temp-cleanup.js — remove the per-Story manifest pair under
|
|
3
|
-
* `temp/epic-<eid>/stories/story-<sid>/manifest.{md,json}` (Epic #1030
|
|
4
|
-
* Story #1040). Falls back to the legacy flat
|
|
5
|
-
* `temp/story-manifest-<id>.{md,json}` layout when `epicId` is unknown
|
|
6
|
-
* — both paths are tried so partial migrations don't leak files in
|
|
7
|
-
* either layout. All deletes are idempotent; ENOENT is silently
|
|
8
|
-
* absorbed.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import path from 'node:path';
|
|
12
|
-
import { storyArtifactPath } from '../../../config/temp-paths.js';
|
|
13
|
-
|
|
14
|
-
function reapPhaseLogger(progress) {
|
|
15
|
-
return progress ?? (() => {});
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function tempCleanupPhase(ctx) {
|
|
19
|
-
const { storyId, epicId, projectRoot, progress, unlinkFn, config } = ctx;
|
|
20
|
-
const log = reapPhaseLogger(progress);
|
|
21
|
-
const unlink = unlinkFn ?? (await import('node:fs/promises')).unlink;
|
|
22
|
-
|
|
23
|
-
// Per-Epic layout (Epic #1030 Story #1040): `temp/epic-<eid>/stories/story-<sid>/manifest.{md,json}`.
|
|
24
|
-
// Legacy flat layout: `temp/story-manifest-<sid>.{md,json}`. The migration
|
|
25
|
-
// tolerates both — try the per-Epic path first when `epicId` is known,
|
|
26
|
-
// and always sweep the legacy path so a half-migrated cohort doesn't
|
|
27
|
-
// leave residue.
|
|
28
|
-
const targets = [];
|
|
29
|
-
if (epicId) {
|
|
30
|
-
const eid = Number(epicId);
|
|
31
|
-
const sid = Number(storyId);
|
|
32
|
-
targets.push(
|
|
33
|
-
{
|
|
34
|
-
path: storyArtifactPath(eid, sid, 'manifest.md', config),
|
|
35
|
-
label: `temp/epic-${epicId}/stories/story-${storyId}/manifest.md`,
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
path: storyArtifactPath(eid, sid, 'manifest.json', config),
|
|
39
|
-
label: `temp/epic-${epicId}/stories/story-${storyId}/manifest.json`,
|
|
40
|
-
},
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
// Legacy flat layout is rooted at the framework's projectRoot — this is
|
|
44
|
-
// a half-migrated-cohort sweep, not a configured-tempRoot target. Once
|
|
45
|
-
// the legacy paths can no longer exist on any live install, this block
|
|
46
|
-
// can be deleted entirely.
|
|
47
|
-
const legacyBase = path.join(
|
|
48
|
-
projectRoot,
|
|
49
|
-
'temp',
|
|
50
|
-
`story-manifest-${storyId}`,
|
|
51
|
-
);
|
|
52
|
-
targets.push(
|
|
53
|
-
{ path: `${legacyBase}.md`, label: `temp/story-manifest-${storyId}.md` },
|
|
54
|
-
{
|
|
55
|
-
path: `${legacyBase}.json`,
|
|
56
|
-
label: `temp/story-manifest-${storyId}.json`,
|
|
57
|
-
},
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
for (const target of targets) {
|
|
61
|
-
try {
|
|
62
|
-
await unlink(target.path);
|
|
63
|
-
log('CLEANUP', `🗑️ Deleted ${target.label}`);
|
|
64
|
-
} catch {
|
|
65
|
-
// File may not exist — deletion is idempotent.
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|