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
package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import nodeFs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
|
|
4
|
-
import { calculateForSource } from '../../../maintainability-engine.js';
|
|
5
|
-
import { formatNumber } from './_bullet-format.js';
|
|
6
|
-
import {
|
|
7
|
-
createDriftDetector,
|
|
8
|
-
walkComponentRegressions,
|
|
9
|
-
} from './component-drift.js';
|
|
10
|
-
|
|
11
|
-
const DEFAULT_THRESHOLD = 2.0;
|
|
12
|
-
// Distinct from the canonical ratchet baseline at `baselines/maintainability.json`
|
|
13
|
-
// (Epic #730 Story 5.5) โ this file is a per-wave drift SNAPSHOT, not the
|
|
14
|
-
// committed score baseline. Filename intentionally differs so a repo-wide
|
|
15
|
-
// grep for the canonical baseline no longer hits the snapshot.
|
|
16
|
-
const BASELINE_FILENAME = 'wave-mi-snapshot.json';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Detect per-component maintainability regressions from a baseline rollup
|
|
20
|
-
* against the gate's configured floors. Pure โ the caller loads the
|
|
21
|
-
* baseline via `lib/baselines/reader.js#load('maintainability')` and passes
|
|
22
|
-
* the resulting `{ rollup }` plus the gate config block.
|
|
23
|
-
*
|
|
24
|
-
* Bullet shape (Task #1919, Epic #1786):
|
|
25
|
-
*
|
|
26
|
-
* ๐ maintainability: <component> <axis> <value> < floor <floor>
|
|
27
|
-
*
|
|
28
|
-
* Maintainability is "higher is better" โ every axis breach reports when
|
|
29
|
-
* `value < floor`. Component-scoped breaches do NOT trigger a `*` bullet
|
|
30
|
-
* unless `*` itself breaches. The walk itself is the shared
|
|
31
|
-
* `component-drift.js` helper (Story #3984).
|
|
32
|
-
*
|
|
33
|
-
* @param {{
|
|
34
|
-
* rollup?: Record<string, Record<string, number>>,
|
|
35
|
-
* gateConfig?: { floors?: Record<string, Record<string, number>> } & object,
|
|
36
|
-
* }} params
|
|
37
|
-
* @returns {string[]}
|
|
38
|
-
*/
|
|
39
|
-
export function detectComponentRegressions(params = {}) {
|
|
40
|
-
return walkComponentRegressions(params, {
|
|
41
|
-
isBreach: (value, target) => value < target,
|
|
42
|
-
formatBullet: (name, axis, value, target) =>
|
|
43
|
-
`๐ maintainability: ${name} ${axis} ${formatNumber(value)} < floor ${formatNumber(target)}`,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Detects per-file maintainability drop versus a wave-start baseline.
|
|
49
|
-
*
|
|
50
|
-
* Usage:
|
|
51
|
-
* const detector = createMaintainabilityDriftDetector({ cwd, files });
|
|
52
|
-
* detector.captureBaseline(); // call once at wave-start
|
|
53
|
-
* await detector.detect(rows); // call each progress fire
|
|
54
|
-
*
|
|
55
|
-
* A baseline is a map of file -> score, persisted to
|
|
56
|
-
* `<cwd>/<baselineDir>/wave-mi-snapshot.json` so that a resumed epic
|
|
57
|
-
* run can re-read the snapshot from the previous wave rather than lose the
|
|
58
|
-
* anchor. Any file whose score has dropped by >= `threshold` since baseline
|
|
59
|
-
* is surfaced as a bullet:
|
|
60
|
-
*
|
|
61
|
-
* ๐ Maintainability drift: <file> -<n.nn> vs wave-start baseline
|
|
62
|
-
*
|
|
63
|
-
* Errors while reading/scoring individual files are swallowed โ a single
|
|
64
|
-
* bad file must not take the progress reporter down.
|
|
65
|
-
*
|
|
66
|
-
* @param {{
|
|
67
|
-
* cwd?: string,
|
|
68
|
-
* files?: string[], // files to watch; repo-relative paths
|
|
69
|
-
* fs?: { readFileSync: Function, writeFileSync?: Function, mkdirSync?: Function, existsSync?: Function },
|
|
70
|
-
* calculate?: (source: string) => number,
|
|
71
|
-
* threshold?: number, // drop (baseline - current) that trips a bullet
|
|
72
|
-
* baselineDir?: string, // directory (under cwd) to persist snapshot
|
|
73
|
-
* }} [opts]
|
|
74
|
-
*/
|
|
75
|
-
export function createMaintainabilityDriftDetector(opts = {}) {
|
|
76
|
-
const fs = opts.fs ?? nodeFs;
|
|
77
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
78
|
-
const calculate = opts.calculate ?? calculateForSource;
|
|
79
|
-
const threshold = Number.isFinite(opts.threshold)
|
|
80
|
-
? opts.threshold
|
|
81
|
-
: DEFAULT_THRESHOLD;
|
|
82
|
-
|
|
83
|
-
function scoreFile(relPath) {
|
|
84
|
-
try {
|
|
85
|
-
const abs = path.join(cwd, relPath);
|
|
86
|
-
const src = fs.readFileSync(abs, 'utf-8');
|
|
87
|
-
const score = calculate(src);
|
|
88
|
-
return Number.isFinite(score) ? score : null;
|
|
89
|
-
} catch {
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return createDriftDetector({
|
|
95
|
-
fs,
|
|
96
|
-
cwd,
|
|
97
|
-
files: opts.files,
|
|
98
|
-
baselineDir: opts.baselineDir,
|
|
99
|
-
baselineFilename: BASELINE_FILENAME,
|
|
100
|
-
scoreFile,
|
|
101
|
-
captureScore: (score) => score,
|
|
102
|
-
async detect({ baseline, scoreFile: score }) {
|
|
103
|
-
const bullets = [];
|
|
104
|
-
for (const [relPath, baseScore] of Object.entries(baseline)) {
|
|
105
|
-
const current = score(relPath);
|
|
106
|
-
if (current == null) continue;
|
|
107
|
-
const drop = baseScore - current;
|
|
108
|
-
if (drop >= threshold) {
|
|
109
|
-
bullets.push(
|
|
110
|
-
`๐ Maintainability drift: ${relPath} -${drop.toFixed(2)} vs wave-start baseline`,
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return bullets;
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import nodeFs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Detects "worktree residue" โ stories that the ticket graph reports as done,
|
|
6
|
-
* but whose `.worktrees/story-<id>/` directory is still on disk. This usually
|
|
7
|
-
* means story-close failed to reap the worktree (see the Windows
|
|
8
|
-
* partial-reap failure mode in friction memory), and a future run of the
|
|
9
|
-
* same story id would collide with the stale directory.
|
|
10
|
-
*
|
|
11
|
-
* The detector is pure (aside from fs reads) and accepts an fs adapter so the
|
|
12
|
-
* unit test can drive present/absent cases without touching disk.
|
|
13
|
-
*
|
|
14
|
-
* @param {{
|
|
15
|
-
* fs?: { existsSync: (p: string) => boolean },
|
|
16
|
-
* cwd?: string,
|
|
17
|
-
* }} [opts]
|
|
18
|
-
* @returns {(rows: Array<{id:number|string, state:string}>) => Promise<string[]>}
|
|
19
|
-
*/
|
|
20
|
-
export function createStalledWorktreeDetector(opts = {}) {
|
|
21
|
-
const fs = opts.fs ?? nodeFs;
|
|
22
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
23
|
-
return async function detect(rows = []) {
|
|
24
|
-
const bullets = [];
|
|
25
|
-
for (const row of rows) {
|
|
26
|
-
if (row?.state !== 'done') continue;
|
|
27
|
-
const relPath = `.worktrees/story-${row.id}`;
|
|
28
|
-
const absPath = path.join(cwd, relPath);
|
|
29
|
-
if (fs.existsSync(absPath)) {
|
|
30
|
-
bullets.push(
|
|
31
|
-
`โ ๏ธ Worktree residue: #${row.id} marked done but .worktrees/story-${row.id}/ still present`,
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return bullets;
|
|
36
|
-
};
|
|
37
|
-
}
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* StoryLauncher โ produces the per-wave dispatch plan and (optionally)
|
|
3
|
-
* delegates execution to an injected `dispatch` adapter.
|
|
4
|
-
*
|
|
5
|
-
* After Story #908, in-session Agent-tool fan-out replaces the subprocess
|
|
6
|
-
* spawn pipeline. The launcher's primary responsibility is `planWave(stories)`:
|
|
7
|
-
* given a wave's Story tickets it returns a stable list of
|
|
8
|
-
* `{ storyId, worktree }` entries. The `/deliver` skill consumes that
|
|
9
|
-
* list (one wave at a time) to format one assistant turn containing N
|
|
10
|
-
* parallel `Agent` tool calls (subagent_type `general-purpose`), each of
|
|
11
|
-
* which drives `/deliver <storyId>` for one Story.
|
|
12
|
-
*
|
|
13
|
-
* `launchWave(stories)` is a convenience for callers that already hold a
|
|
14
|
-
* concrete dispatch adapter (tests, future programmatic harnesses). It calls
|
|
15
|
-
* `planWave` and forwards the plan to `dispatch({ plan, concurrencyCap, signal })`,
|
|
16
|
-
* returning the adapter's result list. The CLI does not provide a default
|
|
17
|
-
* dispatch adapter โ invoking the engine without one is an explicit error.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
const DEFAULT_TIMEOUT_MS = 6 * 60 * 60 * 1000;
|
|
21
|
-
|
|
22
|
-
export class StoryLauncher {
|
|
23
|
-
/**
|
|
24
|
-
* @param {{
|
|
25
|
-
* ctx?: { dispatch?: Function, concurrencyCap?: number, worktreeResolver?: (storyId: number) => string, logger?: object },
|
|
26
|
-
* concurrencyCap?: number,
|
|
27
|
-
* dispatch?: (args: { plan: Array<{ storyId: number, worktree?: string }>, concurrencyCap: number, signal?: AbortSignal }) => Promise<Array<{ storyId: number, status: string, detail?: string }>>,
|
|
28
|
-
* worktreeResolver?: (storyId: number) => string,
|
|
29
|
-
* timeoutMs?: number,
|
|
30
|
-
* logger?: { info: Function, warn: Function, error: Function }
|
|
31
|
-
* }} opts
|
|
32
|
-
*/
|
|
33
|
-
constructor(opts = {}) {
|
|
34
|
-
const ctx = opts?.ctx;
|
|
35
|
-
const dispatch = opts?.dispatch ?? ctx?.dispatch ?? null;
|
|
36
|
-
const concurrencyCap = opts?.concurrencyCap ?? ctx?.concurrencyCap;
|
|
37
|
-
if (!Number.isInteger(concurrencyCap) || concurrencyCap < 1) {
|
|
38
|
-
throw new RangeError('concurrencyCap must be a positive integer');
|
|
39
|
-
}
|
|
40
|
-
this.concurrencyCap = concurrencyCap;
|
|
41
|
-
this.dispatch = dispatch;
|
|
42
|
-
this.worktreeResolver = opts?.worktreeResolver ?? ctx?.worktreeResolver;
|
|
43
|
-
this.timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
44
|
-
this.logger = opts?.logger ?? ctx?.logger ?? console;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Produce the dispatch plan for a wave. Pure: no side effects, no IO. The
|
|
49
|
-
* caller (the `/deliver` skill's wave loop, or `launchWave` below)
|
|
50
|
-
* decides what to do with the plan.
|
|
51
|
-
*
|
|
52
|
-
* @param {Array<number|{id?:number,storyId?:number,number?:number}>} stories
|
|
53
|
-
* @returns {Array<{ storyId: number, worktree?: string }>}
|
|
54
|
-
*/
|
|
55
|
-
planWave(stories) {
|
|
56
|
-
return (stories ?? []).map((s) => {
|
|
57
|
-
const storyId =
|
|
58
|
-
typeof s === 'object' && s !== null
|
|
59
|
-
? (s.id ?? s.storyId ?? s.number)
|
|
60
|
-
: s;
|
|
61
|
-
const id = Number(storyId);
|
|
62
|
-
return {
|
|
63
|
-
storyId: id,
|
|
64
|
-
worktree: this.worktreeResolver?.(id),
|
|
65
|
-
};
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Plan + dispatch the wave through the injected adapter. Returns one result
|
|
71
|
-
* entry per input Story preserving input order. Throws when no dispatch
|
|
72
|
-
* adapter was injected โ the engine is no longer callable without one.
|
|
73
|
-
*
|
|
74
|
-
* @param {object[]} stories
|
|
75
|
-
* @param {AbortSignal} [signal]
|
|
76
|
-
* @returns {Promise<Array<{ storyId: number, status: string, detail?: string }>>}
|
|
77
|
-
*/
|
|
78
|
-
async launchWave(stories, signal) {
|
|
79
|
-
if (typeof this.dispatch !== 'function') {
|
|
80
|
-
throw new TypeError(
|
|
81
|
-
'StoryLauncher.launchWave requires a dispatch adapter (in-session Agent-tool fan-out is the responsibility of the /deliver skill).',
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
const plan = this.planWave(stories);
|
|
85
|
-
if (plan.length === 0) return [];
|
|
86
|
-
|
|
87
|
-
const controller = new AbortController();
|
|
88
|
-
const timer = setTimeout(
|
|
89
|
-
() =>
|
|
90
|
-
controller.abort(new Error(`wave timed out after ${this.timeoutMs}ms`)),
|
|
91
|
-
this.timeoutMs,
|
|
92
|
-
);
|
|
93
|
-
const onParentAbort = () => controller.abort(signal?.reason);
|
|
94
|
-
signal?.addEventListener?.('abort', onParentAbort, { once: true });
|
|
95
|
-
try {
|
|
96
|
-
const results = await this.dispatch({
|
|
97
|
-
plan,
|
|
98
|
-
concurrencyCap: this.concurrencyCap,
|
|
99
|
-
signal: controller.signal,
|
|
100
|
-
});
|
|
101
|
-
return this.#alignResults(plan, results);
|
|
102
|
-
} catch (err) {
|
|
103
|
-
return plan.map((p) => ({
|
|
104
|
-
storyId: p.storyId,
|
|
105
|
-
status: 'failed',
|
|
106
|
-
detail: err?.message ?? String(err),
|
|
107
|
-
}));
|
|
108
|
-
} finally {
|
|
109
|
-
clearTimeout(timer);
|
|
110
|
-
signal?.removeEventListener?.('abort', onParentAbort);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
#alignResults(plan, results) {
|
|
115
|
-
const list = Array.isArray(results) ? results : [];
|
|
116
|
-
const byId = new Map(list.map((r) => [Number(r.storyId), r]));
|
|
117
|
-
return plan.map((p) => {
|
|
118
|
-
const r = byId.get(p.storyId);
|
|
119
|
-
if (r) return { storyId: p.storyId, ...r };
|
|
120
|
-
return {
|
|
121
|
-
storyId: p.storyId,
|
|
122
|
-
status: 'failed',
|
|
123
|
-
detail: 'dispatch returned no result for this story',
|
|
124
|
-
};
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
}
|
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* story-run-progress-writer โ render the per-story progress snapshot.
|
|
3
|
-
*
|
|
4
|
-
* Story #3909 โ this module no longer **posts** a `story-run-progress`
|
|
5
|
-
* structured comment. That per-Story comment was the redundant mid-flight
|
|
6
|
-
* progress surface: an Epic run already keeps the operator-facing
|
|
7
|
-
* `epic-run-progress` rollup (one comment on the Epic) plus the
|
|
8
|
-
* `epic-run-state` checkpoint and the lifecycle ledger, and the rollup is
|
|
9
|
-
* rendered from the checkpoint `waves[]` โ it never read the per-Story
|
|
10
|
-
* comment. The per-Story comment fired at five phase transitions each and
|
|
11
|
-
* duplicated state already on the labels + ledger, so the comment write was
|
|
12
|
-
* removed.
|
|
13
|
-
*
|
|
14
|
-
* The renderer survives because its `{ body, payload }` output still feeds
|
|
15
|
-
* two non-comment contracts: the `renderedBody` markdown the `/deliver`
|
|
16
|
-
* and `single-story-deliver` CLIs (`story-phase.js`, the inline `story-init.js` prepare step)
|
|
17
|
-
* relay to chat so the operator sees the phase table inline, and the snapshot
|
|
18
|
-
* payload returned in those CLIs' JSON envelopes. `upsertStoryRunProgress`
|
|
19
|
-
* therefore renders-only: it computes the body/payload and (optionally) mirrors
|
|
20
|
-
* a low-severity webhook event, but writes no GitHub comment.
|
|
21
|
-
*
|
|
22
|
-
* Payload shape โ per tech spec #902 (kept stable; the CLI envelopes carry it
|
|
23
|
-
* verbatim):
|
|
24
|
-
*
|
|
25
|
-
* {
|
|
26
|
-
* "kind": "story-run-progress",
|
|
27
|
-
* "storyId": <number>,
|
|
28
|
-
* "branch": "story-<id>",
|
|
29
|
-
* "phase": "init|implementing|closing|blocked|done",
|
|
30
|
-
* "tasks": [
|
|
31
|
-
* { "id": <n>, "title": "...", "state": "done", "commitSha": "abc1234" },
|
|
32
|
-
* { "id": <n>, "title": "...", "state": "executing" },
|
|
33
|
-
* { "id": <n>, "title": "...", "state": "pending" }
|
|
34
|
-
* ],
|
|
35
|
-
* "updatedAt": "<iso8601>"
|
|
36
|
-
* }
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
export const STORY_RUN_PROGRESS_TYPE = 'story-run-progress';
|
|
40
|
-
|
|
41
|
-
const VALID_TASK_STATES = new Set([
|
|
42
|
-
'pending',
|
|
43
|
-
'executing',
|
|
44
|
-
'done',
|
|
45
|
-
'blocked',
|
|
46
|
-
'failed',
|
|
47
|
-
]);
|
|
48
|
-
|
|
49
|
-
const VALID_PHASES = new Set([
|
|
50
|
-
'init',
|
|
51
|
-
'implementing',
|
|
52
|
-
'closing',
|
|
53
|
-
'blocked',
|
|
54
|
-
'done',
|
|
55
|
-
]);
|
|
56
|
-
|
|
57
|
-
const TASK_STATE_EMOJI = {
|
|
58
|
-
pending: 'โณ',
|
|
59
|
-
executing: '๐ง',
|
|
60
|
-
done: 'โ
',
|
|
61
|
-
blocked: '๐ง',
|
|
62
|
-
failed: 'โ',
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const PHASE_EMOJI = {
|
|
66
|
-
init: '๐ฑ',
|
|
67
|
-
implementing: '๐ง',
|
|
68
|
-
closing: '๐',
|
|
69
|
-
blocked: '๐ง',
|
|
70
|
-
done: 'โ
',
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Canonical 2-tier Story-phase order. The Story-phase snapshot replaces the
|
|
75
|
-
* 4-tier per-Task list when the Story carries inline acceptance (no child
|
|
76
|
-
* Tasks). Each entry tracks `status` + `startedAt` / `endedAt` so the parent
|
|
77
|
-
* `/deliver` aggregator can render a coarse progress bar without
|
|
78
|
-
* walking Task tickets.
|
|
79
|
-
*/
|
|
80
|
-
export const STORY_PHASE_ORDER = ['init', 'implement', 'validate', 'close'];
|
|
81
|
-
|
|
82
|
-
const VALID_STORY_PHASE_STATUS = new Set(['pending', 'in-progress', 'done']);
|
|
83
|
-
|
|
84
|
-
const STORY_PHASE_STATUS_EMOJI = {
|
|
85
|
-
pending: 'โณ',
|
|
86
|
-
'in-progress': '๐ง',
|
|
87
|
-
done: 'โ
',
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Build the canonical default `phases[]` array for a freshly-initialized
|
|
92
|
-
* 2-tier Story snapshot. All entries are `pending`; timestamps are null.
|
|
93
|
-
* Exported so call sites (the story-init prepare step, story-phase) and
|
|
94
|
-
* tests can build the same shape without re-implementing it.
|
|
95
|
-
*
|
|
96
|
-
* @returns {Array<{ name: string, status: 'pending', startedAt: null, endedAt: null }>}
|
|
97
|
-
*/
|
|
98
|
-
export function defaultStoryPhases() {
|
|
99
|
-
return STORY_PHASE_ORDER.map((name) => ({
|
|
100
|
-
name,
|
|
101
|
-
status: 'pending',
|
|
102
|
-
startedAt: null,
|
|
103
|
-
endedAt: null,
|
|
104
|
-
}));
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Normalize one Story-phase row into the canonical schema. Timestamps may be
|
|
109
|
-
* `null` (phase not yet started) or ISO-8601 strings; status is one of
|
|
110
|
-
* pending | in-progress | done.
|
|
111
|
-
*
|
|
112
|
-
* @param {object} phase
|
|
113
|
-
* @returns {object}
|
|
114
|
-
*/
|
|
115
|
-
function normalizeStoryPhase(phase) {
|
|
116
|
-
if (!phase || typeof phase !== 'object') {
|
|
117
|
-
throw new TypeError('story-run-progress phase rows must be objects');
|
|
118
|
-
}
|
|
119
|
-
const name = String(phase.name ?? '');
|
|
120
|
-
if (!STORY_PHASE_ORDER.includes(name)) {
|
|
121
|
-
throw new RangeError(
|
|
122
|
-
`story-run-progress invalid phase name "${name}"; ` +
|
|
123
|
-
`expected one of: ${STORY_PHASE_ORDER.join(', ')}`,
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
const status = String(phase.status ?? 'pending');
|
|
127
|
-
if (!VALID_STORY_PHASE_STATUS.has(status)) {
|
|
128
|
-
throw new RangeError(
|
|
129
|
-
`story-run-progress invalid phase status "${status}" for "${name}"; ` +
|
|
130
|
-
`expected one of: ${[...VALID_STORY_PHASE_STATUS].join(', ')}`,
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
return {
|
|
134
|
-
name,
|
|
135
|
-
status,
|
|
136
|
-
startedAt: phase.startedAt == null ? null : String(phase.startedAt),
|
|
137
|
-
endedAt: phase.endedAt == null ? null : String(phase.endedAt),
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Normalize one Task row into the canonical schema. `commitSha` is only
|
|
143
|
-
* carried on `done` rows (it has no meaning before the commit lands and is
|
|
144
|
-
* cleared on rollback).
|
|
145
|
-
*
|
|
146
|
-
* @param {object} task
|
|
147
|
-
* @returns {object}
|
|
148
|
-
*/
|
|
149
|
-
function normalizeTask(task) {
|
|
150
|
-
if (!task || typeof task !== 'object') {
|
|
151
|
-
throw new TypeError('story-run-progress task rows must be objects');
|
|
152
|
-
}
|
|
153
|
-
const id = Number(task.id ?? task.taskId);
|
|
154
|
-
if (!Number.isInteger(id) || id <= 0) {
|
|
155
|
-
throw new TypeError(
|
|
156
|
-
`story-run-progress task row missing valid id: ${JSON.stringify(task)}`,
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
const state = String(task.state ?? 'pending');
|
|
160
|
-
if (!VALID_TASK_STATES.has(state)) {
|
|
161
|
-
throw new RangeError(
|
|
162
|
-
`story-run-progress invalid task state "${state}" for task #${id}; ` +
|
|
163
|
-
`expected one of: ${[...VALID_TASK_STATES].join(', ')}`,
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
const row = { id, title: String(task.title ?? ''), state };
|
|
167
|
-
if (state === 'done' && task.commitSha != null) {
|
|
168
|
-
row.commitSha = String(task.commitSha);
|
|
169
|
-
}
|
|
170
|
-
return row;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Build the markdown body the writer upserts. Pure: no IO, no provider call.
|
|
175
|
-
* Exported so tests can pin the rendered shape without going through the
|
|
176
|
-
* upsert path.
|
|
177
|
-
*
|
|
178
|
-
* Two shapes are supported, selected by whether `input.phases` (2-tier
|
|
179
|
-
* Story-phase snapshot) or `input.tasks` (legacy 4-tier per-Task list) is
|
|
180
|
-
* provided. Callers MUST pass exactly one of the two โ passing both is
|
|
181
|
-
* rejected as a contract violation so a mistake at the call site fails
|
|
182
|
-
* loudly rather than silently dropping one shape.
|
|
183
|
-
*
|
|
184
|
-
* @param {{
|
|
185
|
-
* storyId: number,
|
|
186
|
-
* branch: string,
|
|
187
|
-
* phase: string,
|
|
188
|
-
* tasks?: object[],
|
|
189
|
-
* phases?: object[],
|
|
190
|
-
* updatedAt?: string,
|
|
191
|
-
* }} input
|
|
192
|
-
* @returns {{ body: string, payload: object }}
|
|
193
|
-
*/
|
|
194
|
-
export function renderStoryRunProgressBody(input) {
|
|
195
|
-
const storyId = Number(input?.storyId);
|
|
196
|
-
if (!Number.isInteger(storyId) || storyId <= 0) {
|
|
197
|
-
throw new TypeError(
|
|
198
|
-
'renderStoryRunProgressBody requires a numeric storyId',
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
const branch = String(input?.branch ?? '');
|
|
202
|
-
if (!branch) {
|
|
203
|
-
throw new TypeError(
|
|
204
|
-
'renderStoryRunProgressBody requires a non-empty branch',
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
const phase = String(input?.phase ?? '');
|
|
208
|
-
if (!VALID_PHASES.has(phase)) {
|
|
209
|
-
throw new RangeError(
|
|
210
|
-
`renderStoryRunProgressBody invalid phase "${phase}"; ` +
|
|
211
|
-
`expected one of: ${[...VALID_PHASES].join(', ')}`,
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const hasPhases = Array.isArray(input.phases);
|
|
216
|
-
const hasTasks = Array.isArray(input.tasks);
|
|
217
|
-
if (hasPhases && hasTasks) {
|
|
218
|
-
throw new TypeError(
|
|
219
|
-
'renderStoryRunProgressBody: pass either `phases` (2-tier) or `tasks` ' +
|
|
220
|
-
'(4-tier), not both โ the snapshot shape is mutually exclusive.',
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const updatedAt = input.updatedAt ?? new Date().toISOString();
|
|
225
|
-
|
|
226
|
-
if (hasPhases) {
|
|
227
|
-
return renderPhasesBody({
|
|
228
|
-
storyId,
|
|
229
|
-
branch,
|
|
230
|
-
phase,
|
|
231
|
-
phases: input.phases,
|
|
232
|
-
updatedAt,
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
return renderTasksBody({
|
|
236
|
-
storyId,
|
|
237
|
-
branch,
|
|
238
|
-
phase,
|
|
239
|
-
tasks: input.tasks ?? [],
|
|
240
|
-
updatedAt,
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Render the 4-tier per-Task body. Pure helper for `renderStoryRunProgressBody`.
|
|
246
|
-
*/
|
|
247
|
-
function renderTasksBody({
|
|
248
|
-
storyId,
|
|
249
|
-
branch,
|
|
250
|
-
phase,
|
|
251
|
-
tasks: rawTasks,
|
|
252
|
-
updatedAt,
|
|
253
|
-
}) {
|
|
254
|
-
const tasks = rawTasks.map(normalizeTask);
|
|
255
|
-
const payload = {
|
|
256
|
-
kind: STORY_RUN_PROGRESS_TYPE,
|
|
257
|
-
storyId,
|
|
258
|
-
branch,
|
|
259
|
-
phase,
|
|
260
|
-
tasks,
|
|
261
|
-
updatedAt,
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
const done = tasks.filter((t) => t.state === 'done').length;
|
|
265
|
-
const total = tasks.length;
|
|
266
|
-
const phaseEmoji = PHASE_EMOJI[phase] ?? '';
|
|
267
|
-
const header = `### ๐ Story #${storyId} โ ${phaseEmoji} ${phase} ยท ${done}/${total} tasks done`;
|
|
268
|
-
const tableRows = tasks.length
|
|
269
|
-
? [
|
|
270
|
-
'| ID | State | Title | Commit |',
|
|
271
|
-
'| --- | --- | --- | --- |',
|
|
272
|
-
...tasks.map((t) => {
|
|
273
|
-
const emoji = TASK_STATE_EMOJI[t.state] ?? '';
|
|
274
|
-
const commit = t.commitSha
|
|
275
|
-
? `\`${String(t.commitSha).slice(0, 7)}\``
|
|
276
|
-
: 'โ';
|
|
277
|
-
const title = String(t.title).replace(/\|/g, '\\|');
|
|
278
|
-
return `| #${t.id} | ${emoji} ${t.state} | ${title} | ${commit} |`;
|
|
279
|
-
}),
|
|
280
|
-
].join('\n')
|
|
281
|
-
: '_(no tasks recorded for this story)_';
|
|
282
|
-
|
|
283
|
-
const body = [
|
|
284
|
-
header,
|
|
285
|
-
'',
|
|
286
|
-
`Branch: \`${branch}\``,
|
|
287
|
-
'',
|
|
288
|
-
tableRows,
|
|
289
|
-
'',
|
|
290
|
-
'```json',
|
|
291
|
-
JSON.stringify(payload, null, 2),
|
|
292
|
-
'```',
|
|
293
|
-
].join('\n');
|
|
294
|
-
|
|
295
|
-
return { body, payload };
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Render the 2-tier Story-phase body. Pure helper for
|
|
300
|
-
* `renderStoryRunProgressBody`. Emits a `phases[]` payload whose entries
|
|
301
|
-
* carry `{ name, status, startedAt, endedAt }` for init/implement/validate/close.
|
|
302
|
-
*/
|
|
303
|
-
function renderPhasesBody({ storyId, branch, phase, phases: raw, updatedAt }) {
|
|
304
|
-
const phases = raw.map(normalizeStoryPhase);
|
|
305
|
-
const payload = {
|
|
306
|
-
kind: STORY_RUN_PROGRESS_TYPE,
|
|
307
|
-
storyId,
|
|
308
|
-
branch,
|
|
309
|
-
phase,
|
|
310
|
-
phases,
|
|
311
|
-
updatedAt,
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
const done = phases.filter((p) => p.status === 'done').length;
|
|
315
|
-
const total = phases.length;
|
|
316
|
-
const phaseEmoji = PHASE_EMOJI[phase] ?? '';
|
|
317
|
-
const header = `### ๐ Story #${storyId} โ ${phaseEmoji} ${phase} ยท ${done}/${total} phases done`;
|
|
318
|
-
const tableRows = phases.length
|
|
319
|
-
? [
|
|
320
|
-
'| Phase | Status | Started | Ended |',
|
|
321
|
-
'| --- | --- | --- | --- |',
|
|
322
|
-
...phases.map((p) => {
|
|
323
|
-
const emoji = STORY_PHASE_STATUS_EMOJI[p.status] ?? '';
|
|
324
|
-
const started = p.startedAt ?? 'โ';
|
|
325
|
-
const ended = p.endedAt ?? 'โ';
|
|
326
|
-
return `| ${p.name} | ${emoji} ${p.status} | ${started} | ${ended} |`;
|
|
327
|
-
}),
|
|
328
|
-
].join('\n')
|
|
329
|
-
: '_(no phases recorded for this story)_';
|
|
330
|
-
|
|
331
|
-
const body = [
|
|
332
|
-
header,
|
|
333
|
-
'',
|
|
334
|
-
`Branch: \`${branch}\``,
|
|
335
|
-
'',
|
|
336
|
-
tableRows,
|
|
337
|
-
'',
|
|
338
|
-
'```json',
|
|
339
|
-
JSON.stringify(payload, null, 2),
|
|
340
|
-
'```',
|
|
341
|
-
].join('\n');
|
|
342
|
-
|
|
343
|
-
return { body, payload };
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Render the story-run-progress snapshot for one phase transition and return
|
|
348
|
-
* `{ body, payload }` so callers can surface the markdown body to chat and
|
|
349
|
-
* carry the payload in their JSON envelope. Story #3909 โ this no longer posts
|
|
350
|
-
* a GitHub comment (the redundant mid-flight progress surface was deleted); it
|
|
351
|
-
* renders only and, when `notify` is supplied, mirrors a low-severity webhook
|
|
352
|
-
* event for operators who wire one up.
|
|
353
|
-
*
|
|
354
|
-
* Two shapes are supported, selected by whether `args.phases` (2-tier
|
|
355
|
-
* Story-phase snapshot) or `args.tasks` (legacy 4-tier per-Task list) is
|
|
356
|
-
* provided. The webhook mirror's `done/total` count is computed from whichever
|
|
357
|
-
* shape is active.
|
|
358
|
-
*
|
|
359
|
-
* @param {{
|
|
360
|
-
* provider?: import('../../ITicketingProvider.js').ITicketingProvider,
|
|
361
|
-
* storyId: number,
|
|
362
|
-
* branch: string,
|
|
363
|
-
* phase: string,
|
|
364
|
-
* tasks?: object[],
|
|
365
|
-
* phases?: object[],
|
|
366
|
-
* epicId?: number,
|
|
367
|
-
* updatedAt?: string,
|
|
368
|
-
* notify?: Function,
|
|
369
|
-
* }} args
|
|
370
|
-
* @returns {Promise<{ body: string, payload: object }>}
|
|
371
|
-
*/
|
|
372
|
-
export async function upsertStoryRunProgress(args) {
|
|
373
|
-
const { notify, epicId, provider: _provider, ...rest } = args ?? {};
|
|
374
|
-
const { body, payload } = renderStoryRunProgressBody(rest);
|
|
375
|
-
if (typeof notify === 'function') {
|
|
376
|
-
const isPhases = Array.isArray(payload.phases);
|
|
377
|
-
const items = isPhases ? payload.phases : payload.tasks;
|
|
378
|
-
const done = isPhases
|
|
379
|
-
? items.filter((p) => p.status === 'done').length
|
|
380
|
-
: items.filter((t) => t.state === 'done').length;
|
|
381
|
-
const total = items.length;
|
|
382
|
-
const unit = isPhases ? 'phases' : 'tasks';
|
|
383
|
-
const message = `Story #${payload.storyId} ยท ${payload.phase} ยท ${done}/${total} ${unit} done`;
|
|
384
|
-
await Promise.resolve(
|
|
385
|
-
notify(
|
|
386
|
-
payload.storyId,
|
|
387
|
-
{
|
|
388
|
-
severity: 'low',
|
|
389
|
-
message,
|
|
390
|
-
event: STORY_RUN_PROGRESS_TYPE,
|
|
391
|
-
level: 'story',
|
|
392
|
-
epicId,
|
|
393
|
-
phase: payload.phase,
|
|
394
|
-
},
|
|
395
|
-
{ skipComment: true },
|
|
396
|
-
),
|
|
397
|
-
).catch(() => {});
|
|
398
|
-
}
|
|
399
|
-
return { body, payload };
|
|
400
|
-
}
|