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,328 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* perf-report-readers.js — I/O readers + git-scrape helpers for the
|
|
3
|
-
* structured perf-summary comments (Epic #1030 / Story #1123, split out
|
|
4
|
-
* under Story #3350).
|
|
5
|
-
*
|
|
6
|
-
* Every export here touches the filesystem, the ticketing provider, or
|
|
7
|
-
* `git log`. The pure renderers that format the report bodies live in the
|
|
8
|
-
* sibling `perf-report-render.js`; the Story-/Epic-mode orchestrators in
|
|
9
|
-
* `analyze-execution.js` wire these readers to those renderers.
|
|
10
|
-
*
|
|
11
|
-
* @see docs/data-dictionary.md §StoryPerfSummary, §EpicPerfReport
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import fs from 'node:fs/promises';
|
|
15
|
-
import { storyArtifactPath } from '../config/temp-paths.js';
|
|
16
|
-
import { gitSpawn } from '../git-utils.js';
|
|
17
|
-
import { Logger } from '../Logger.js';
|
|
18
|
-
import { read as readSignals } from '../signals/read.js';
|
|
19
|
-
import { concurrentMap } from '../util/concurrent-map.js';
|
|
20
|
-
import { extractStoryPerfSummaryFromComment } from './perf-report-render.js';
|
|
21
|
-
import { forEachLine } from './signals-writer.js';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Stream every lifecycle event under the Epic into an in-memory array
|
|
25
|
-
* (Story #3025 / Task #3030). The perf-aggregator's wave-parallelism
|
|
26
|
-
* reducer needs a single chronological iterable spanning wave-start /
|
|
27
|
-
* wave-complete / state-transition events; the canonical reader walks
|
|
28
|
-
* the epic-level signals.ndjson first, then each per-Story stream in
|
|
29
|
-
* ascending Story-ID order, so that ordering matches the wave-tick
|
|
30
|
-
* emit order at runtime.
|
|
31
|
-
*
|
|
32
|
-
* Returns `[]` on any reader failure so the analyzer keeps composing
|
|
33
|
-
* its other report sections.
|
|
34
|
-
*/
|
|
35
|
-
export async function readEpicLifecycleEvents(epicId, config, logger) {
|
|
36
|
-
const events = [];
|
|
37
|
-
try {
|
|
38
|
-
for await (const evt of readSignals({ epic: epicId, config })) {
|
|
39
|
-
if (evt && typeof evt === 'object') events.push(evt);
|
|
40
|
-
}
|
|
41
|
-
} catch (err) {
|
|
42
|
-
logger?.warn?.(
|
|
43
|
-
`[analyze-execution] readEpicLifecycleEvents(${epicId}) failed (non-fatal): ${
|
|
44
|
-
err instanceof Error ? err.message : String(err)
|
|
45
|
-
}`,
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
return events;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Read every NDJSON line from a Story's signals stream into an array.
|
|
53
|
-
* Missing files resolve to `[]` so callers can treat absence as
|
|
54
|
-
* "no signals yet" without a try/catch.
|
|
55
|
-
*/
|
|
56
|
-
export async function readStorySignals(epicId, storyId, config) {
|
|
57
|
-
const events = [];
|
|
58
|
-
await forEachLine(
|
|
59
|
-
epicId,
|
|
60
|
-
storyId,
|
|
61
|
-
(parsed) => {
|
|
62
|
-
if (parsed && typeof parsed === 'object') events.push(parsed);
|
|
63
|
-
},
|
|
64
|
-
config,
|
|
65
|
-
);
|
|
66
|
-
return events;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Best-effort read of the per-Story phase-timings JSON written by
|
|
71
|
-
* `post-merge-close.js`. Returns `null` when the file is missing or
|
|
72
|
-
* malformed — phaseTimingsMs in the StoryPerfSummary degrades to `{}`
|
|
73
|
-
* rather than throwing.
|
|
74
|
-
*/
|
|
75
|
-
export async function readPhaseTimings(epicId, storyId, config, overridePath) {
|
|
76
|
-
const target =
|
|
77
|
-
overridePath ??
|
|
78
|
-
storyArtifactPath(epicId, storyId, 'phase-timings.json', config);
|
|
79
|
-
try {
|
|
80
|
-
const buf = await fs.readFile(target, 'utf8');
|
|
81
|
-
const parsed = JSON.parse(buf);
|
|
82
|
-
if (parsed && typeof parsed === 'object') return parsed;
|
|
83
|
-
return null;
|
|
84
|
-
} catch (err) {
|
|
85
|
-
if (err && err.code === 'ENOENT') return null;
|
|
86
|
-
Logger.warn(
|
|
87
|
-
`[analyze-execution] could not parse phase-timings at ${target}: ${
|
|
88
|
-
err instanceof Error ? err.message : String(err)
|
|
89
|
-
}`,
|
|
90
|
-
);
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Throw-away ghSpawnCount reader (Story #1795 / Epic #1788). Looks for
|
|
97
|
-
* the `temp/epic-<eid>/stories/story-<sid>/gh-spawn-count.json` file written by
|
|
98
|
-
* `close-validation.emitGhSpawnCount` immediately before the perf-summary
|
|
99
|
-
* phase spawns this analyzer. Returns the integer count when present and
|
|
100
|
-
* well-formed; `null` when absent or unparseable. Callers treat `null` as
|
|
101
|
-
* "no signal" — the structured comment simply omits `ghSpawnCount`.
|
|
102
|
-
*/
|
|
103
|
-
export async function readGhSpawnCount(epicId, storyId, config) {
|
|
104
|
-
const target = storyArtifactPath(
|
|
105
|
-
epicId,
|
|
106
|
-
storyId,
|
|
107
|
-
'gh-spawn-count.json',
|
|
108
|
-
config,
|
|
109
|
-
);
|
|
110
|
-
try {
|
|
111
|
-
const buf = await fs.readFile(target, 'utf8');
|
|
112
|
-
const parsed = JSON.parse(buf);
|
|
113
|
-
const count = parsed?.ghSpawnCount;
|
|
114
|
-
if (Number.isInteger(count) && count >= 0) return count;
|
|
115
|
-
return null;
|
|
116
|
-
} catch (err) {
|
|
117
|
-
if (err && err.code === 'ENOENT') return null;
|
|
118
|
-
Logger.warn(
|
|
119
|
-
`[analyze-execution] could not parse gh-spawn-count at ${target}: ${
|
|
120
|
-
err instanceof Error ? err.message : String(err)
|
|
121
|
-
}`,
|
|
122
|
-
);
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Fetch every `story-perf-summary` structured comment from the Stories
|
|
129
|
-
* under an Epic. We rely on `provider.getSubTickets(epicId)` for child
|
|
130
|
-
* enumeration (Stories carry `parent: #<epicId>` either via the native
|
|
131
|
-
* sub-issue link or the body marker — `getSubTickets` reconciles both).
|
|
132
|
-
* Missing comments are skipped (the Story may have been recut and not
|
|
133
|
-
* closed yet).
|
|
134
|
-
*/
|
|
135
|
-
export async function collectStorySummaries(provider, epicId, logger) {
|
|
136
|
-
let stories;
|
|
137
|
-
try {
|
|
138
|
-
const children = await provider.getSubTickets(epicId);
|
|
139
|
-
stories = Array.isArray(children) ? children : [];
|
|
140
|
-
} catch (err) {
|
|
141
|
-
logger.warn?.(
|
|
142
|
-
`[analyze-execution] getSubTickets(${epicId}) failed: ${
|
|
143
|
-
err instanceof Error ? err.message : String(err)
|
|
144
|
-
}`,
|
|
145
|
-
);
|
|
146
|
-
return [];
|
|
147
|
-
}
|
|
148
|
-
// Filter to Story tickets — descendants include Tasks too. We only
|
|
149
|
-
// want the per-Story summaries, so guard on `type::story`.
|
|
150
|
-
const storyTickets = stories.filter(
|
|
151
|
-
(t) =>
|
|
152
|
-
Array.isArray(t?.labels) &&
|
|
153
|
-
t.labels.some(
|
|
154
|
-
(l) => (typeof l === 'string' ? l : l?.name) === 'type::story',
|
|
155
|
-
),
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
// Bounded-parallel comment fetch (Story #3990). Each Story's comment
|
|
159
|
-
// thread is an independent paginated REST read through a fresh `gh`
|
|
160
|
-
// spawn, so a serial loop pays N sequential round-trips. concurrentMap
|
|
161
|
-
// preserves input→output index, keeping summaries in Story order; the
|
|
162
|
-
// per-Story try/catch stays inside the mapper so one failed fetch
|
|
163
|
-
// degrades to warn-and-skip without aborting the batch (mirrors
|
|
164
|
-
// verifySingleResult in lib/orchestration/wave-record-io.js, #3024).
|
|
165
|
-
const perStory = await concurrentMap(
|
|
166
|
-
storyTickets,
|
|
167
|
-
async (ticket) => {
|
|
168
|
-
const id = Number(ticket.id ?? ticket.number);
|
|
169
|
-
if (!Number.isInteger(id) || id < 1) return null;
|
|
170
|
-
let comments;
|
|
171
|
-
try {
|
|
172
|
-
comments = (await provider.getTicketComments(id)) ?? [];
|
|
173
|
-
} catch (err) {
|
|
174
|
-
logger.warn?.(
|
|
175
|
-
`[analyze-execution] getTicketComments(${id}) failed: ${
|
|
176
|
-
err instanceof Error ? err.message : String(err)
|
|
177
|
-
}`,
|
|
178
|
-
);
|
|
179
|
-
return null;
|
|
180
|
-
}
|
|
181
|
-
for (const c of comments) {
|
|
182
|
-
const parsed = extractStoryPerfSummaryFromComment(c?.body);
|
|
183
|
-
if (parsed) return parsed;
|
|
184
|
-
}
|
|
185
|
-
return null;
|
|
186
|
-
},
|
|
187
|
-
{ concurrency: 4 },
|
|
188
|
-
);
|
|
189
|
-
return perStory.filter((s) => s !== null);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Default git-log gatherer for the baseline-refresh-rate reporter
|
|
194
|
-
* (Story #1400 / Task #1427). Reads commits on `epic/<id>` over the
|
|
195
|
-
* trailing window and shapes them into the record format the pure
|
|
196
|
-
* reporter expects. Returns `[]` on any spawn failure so the retro
|
|
197
|
-
* comment keeps composing — the reporter then prints "no Story merges
|
|
198
|
-
* in window" and the operator can investigate offline.
|
|
199
|
-
*
|
|
200
|
-
* Injectable via `runEpicMode({ gatherEpicCommitsFn })` so the unit test
|
|
201
|
-
* can pin behavior without a temp git repo.
|
|
202
|
-
*/
|
|
203
|
-
export function gatherEpicCommitsFromGit({ epicId, windowDays, cwd, logger }) {
|
|
204
|
-
const ref = `epic/${epicId}`;
|
|
205
|
-
const since = `${windowDays} days ago`;
|
|
206
|
-
// Subject (%s) carries the Story-merge `(resolves #N)` and the
|
|
207
|
-
// `baseline-refresh:` prefix; ISO commit date (%cI) drives the window
|
|
208
|
-
// filter inside the reporter. Tab separator avoids subjects that
|
|
209
|
-
// contain pipes.
|
|
210
|
-
const res = gitSpawn(
|
|
211
|
-
cwd,
|
|
212
|
-
'log',
|
|
213
|
-
ref,
|
|
214
|
-
`--since=${since}`,
|
|
215
|
-
'--pretty=format:%H%x09%cI%x09%s',
|
|
216
|
-
);
|
|
217
|
-
if (res.status !== 0) {
|
|
218
|
-
logger.warn?.(
|
|
219
|
-
`[analyze-execution] git log ${ref} failed (non-fatal): ${res.stderr || res.stdout}`,
|
|
220
|
-
);
|
|
221
|
-
return [];
|
|
222
|
-
}
|
|
223
|
-
const lines = (res.stdout || '').split('\n').filter(Boolean);
|
|
224
|
-
return lines.map((line) => {
|
|
225
|
-
const [sha, isoDate, ...rest] = line.split('\t');
|
|
226
|
-
return {
|
|
227
|
-
sha,
|
|
228
|
-
isoDate,
|
|
229
|
-
subject: rest.join('\t'),
|
|
230
|
-
epicId,
|
|
231
|
-
};
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Default friction aggregator for the Quality-gate friction block
|
|
237
|
-
* (Story #1400 / Task #1429). Walks each child Story's signals.ndjson
|
|
238
|
-
* stream and returns counts of `baseline-refresh-regression` records
|
|
239
|
-
* plus the top offenders by file (and method, when present in the
|
|
240
|
-
* `regressedFiles` / `crapOverCap` payloads).
|
|
241
|
-
*
|
|
242
|
-
* Aggregation runs against the existing `signals.ndjson` stream — no new
|
|
243
|
-
* file format. Two upstream record shapes are walked:
|
|
244
|
-
* - check-maintainability emits a flat `regressedFiles[]` of `{ file, current, baseline, drop }`.
|
|
245
|
-
* - auto-refresh-runner emits `miOverCap[]` / `crapOverCap[]` rows
|
|
246
|
-
* carrying `path`/`file` and (for crap) `method`.
|
|
247
|
-
*
|
|
248
|
-
* Injectable via `runEpicMode({ aggregateFrictionFn })` so the unit test
|
|
249
|
-
* can pin behavior without seeding NDJSON files.
|
|
250
|
-
*/
|
|
251
|
-
export async function aggregateBaselineFrictionFromSignals({
|
|
252
|
-
epicId,
|
|
253
|
-
storyIds,
|
|
254
|
-
config,
|
|
255
|
-
windowDays,
|
|
256
|
-
now,
|
|
257
|
-
}) {
|
|
258
|
-
const cutoffMs = now().getTime() - windowDays * 24 * 60 * 60 * 1000;
|
|
259
|
-
const offenders = new Map(); // key → { file, method, occurrences }
|
|
260
|
-
const storiesAffected = new Set();
|
|
261
|
-
let totalRecords = 0;
|
|
262
|
-
|
|
263
|
-
for (const sid of storyIds) {
|
|
264
|
-
let touched = false;
|
|
265
|
-
await forEachLine(
|
|
266
|
-
epicId,
|
|
267
|
-
sid,
|
|
268
|
-
(record) => {
|
|
269
|
-
if (
|
|
270
|
-
!record ||
|
|
271
|
-
typeof record !== 'object' ||
|
|
272
|
-
record.kind !== 'friction' ||
|
|
273
|
-
record.category !== 'baseline-refresh-regression'
|
|
274
|
-
) {
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
const ts = Date.parse(record.ts);
|
|
278
|
-
if (Number.isFinite(ts) && ts < cutoffMs) return;
|
|
279
|
-
|
|
280
|
-
totalRecords += 1;
|
|
281
|
-
touched = true;
|
|
282
|
-
|
|
283
|
-
const flatFiles = Array.isArray(record.regressedFiles)
|
|
284
|
-
? record.regressedFiles.map((r) => ({ file: r.file }))
|
|
285
|
-
: [];
|
|
286
|
-
const miFiles = Array.isArray(record.miOverCap)
|
|
287
|
-
? record.miOverCap.map((r) => ({ file: r.path ?? r.file }))
|
|
288
|
-
: [];
|
|
289
|
-
const crapMethods = Array.isArray(record.crapOverCap)
|
|
290
|
-
? record.crapOverCap.map((r) => ({
|
|
291
|
-
file: r.file,
|
|
292
|
-
method: r.method,
|
|
293
|
-
}))
|
|
294
|
-
: [];
|
|
295
|
-
|
|
296
|
-
for (const off of [...flatFiles, ...miFiles, ...crapMethods]) {
|
|
297
|
-
if (!off || typeof off.file !== 'string' || off.file.length === 0) {
|
|
298
|
-
continue;
|
|
299
|
-
}
|
|
300
|
-
const key = off.method ? `${off.file}::${off.method}` : off.file;
|
|
301
|
-
const prev = offenders.get(key);
|
|
302
|
-
if (prev) {
|
|
303
|
-
prev.occurrences += 1;
|
|
304
|
-
} else {
|
|
305
|
-
offenders.set(key, {
|
|
306
|
-
file: off.file,
|
|
307
|
-
method: off.method ?? null,
|
|
308
|
-
occurrences: 1,
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
},
|
|
313
|
-
config,
|
|
314
|
-
);
|
|
315
|
-
if (touched) storiesAffected.add(sid);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const topOffenders = [...offenders.values()]
|
|
319
|
-
.sort((a, b) => b.occurrences - a.occurrences)
|
|
320
|
-
.slice(0, 10);
|
|
321
|
-
|
|
322
|
-
return {
|
|
323
|
-
totalRecords,
|
|
324
|
-
storiesAffected: storiesAffected.size,
|
|
325
|
-
topOffenders,
|
|
326
|
-
windowDays,
|
|
327
|
-
};
|
|
328
|
-
}
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* perf-report-render.js — pure renderers + summary extraction for the
|
|
3
|
-
* structured perf-summary comments (Epic #1030 / Story #1123, split out
|
|
4
|
-
* under Story #3350).
|
|
5
|
-
*
|
|
6
|
-
* Every export here is a pure function: it depends only on its inputs and
|
|
7
|
-
* performs no I/O. The Story-/Epic-mode orchestrators in
|
|
8
|
-
* `analyze-execution.js` read NDJSON, phase-timings, and git-log records
|
|
9
|
-
* via the sibling `perf-report-readers.js`, then hand the resulting plain
|
|
10
|
-
* objects to these renderers. Keeping the render surface free of I/O makes
|
|
11
|
-
* the report formatting unit-testable without fixtures.
|
|
12
|
-
*
|
|
13
|
-
* `extractStoryPerfSummaryFromComment` is the one mixed read/parse helper —
|
|
14
|
-
* it parses a comment body that originated from `renderStoryBody`, so it
|
|
15
|
-
* lives next to the renderer it mirrors. It delegates the fenced-JSON
|
|
16
|
-
* extraction to `parseFencedJsonComment` (the shared structured-comment
|
|
17
|
-
* parser) rather than open-coding the fence regex.
|
|
18
|
-
*
|
|
19
|
-
* @see docs/data-dictionary.md §StoryPerfSummary, §EpicPerfReport
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import { parseFencedJsonComment } from '../orchestration/structured-comment-parser.js';
|
|
23
|
-
|
|
24
|
-
export const STORY_PERF_TYPE = 'story-perf-summary';
|
|
25
|
-
export const EPIC_PERF_TYPE = 'epic-perf-report';
|
|
26
|
-
// Marker emitted by `upsertStructuredComment` for the story-perf-summary
|
|
27
|
-
// type. Mirrors `structuredCommentMarker(STORY_PERF_TYPE)` so the Epic
|
|
28
|
-
// rollup can detect summary comments without importing the renderer.
|
|
29
|
-
export const STORY_PERF_MARKER = `<!-- ap:structured-comment type="${STORY_PERF_TYPE}" -->`;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Render a small operator-facing summary block that doubles as the
|
|
33
|
-
* comment body. The fenced JSON payload is the canonical machine-
|
|
34
|
-
* readable surface; the prose lines above it give a human a reason to
|
|
35
|
-
* skim. The retro composer reads the fenced JSON, not the prose.
|
|
36
|
-
*/
|
|
37
|
-
export function renderStoryBody(payload) {
|
|
38
|
-
const friction = Object.entries(payload.frictionByCategory ?? {})
|
|
39
|
-
.map(([k, v]) => `${k}=${v}`)
|
|
40
|
-
.join(', ');
|
|
41
|
-
const phaseRows = Object.entries(payload.phaseTimingsMs ?? {})
|
|
42
|
-
.map(([k, v]) => `- \`${k}\`: ${v}ms`)
|
|
43
|
-
.join('\n');
|
|
44
|
-
const lines = [
|
|
45
|
-
`### Story Perf Summary — Story #${payload.storyId} (Epic #${payload.epicId})`,
|
|
46
|
-
'',
|
|
47
|
-
`Closed at: \`${payload.closedAt}\``,
|
|
48
|
-
'',
|
|
49
|
-
friction.length > 0
|
|
50
|
-
? `**Friction:** ${friction}`
|
|
51
|
-
: '**Friction:** none recorded',
|
|
52
|
-
'',
|
|
53
|
-
phaseRows.length > 0
|
|
54
|
-
? `**Phase timings:**\n${phaseRows}`
|
|
55
|
-
: '**Phase timings:** none recorded',
|
|
56
|
-
'',
|
|
57
|
-
`**Rework:** ${payload.reworkScore.filesEditedBeyondThreshold} files beyond threshold`,
|
|
58
|
-
`**Retries:** ${payload.retryDensity.retries} across ${payload.retryDensity.uniqueCommands} unique command(s)`,
|
|
59
|
-
'',
|
|
60
|
-
'```json',
|
|
61
|
-
JSON.stringify(payload, null, 2),
|
|
62
|
-
'```',
|
|
63
|
-
];
|
|
64
|
-
return lines.join('\n');
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Render the optional Quality-gate friction summary block (Story #1400 /
|
|
69
|
-
* Task #1429). Aggregates `baseline-refresh-regression` friction records
|
|
70
|
-
* from the Stories' signals.ndjson streams over the trailing window,
|
|
71
|
-
* counts them, and lists the top offenders by file/method.
|
|
72
|
-
*
|
|
73
|
-
* Output contract:
|
|
74
|
-
* - `friction == null` → empty string (caller injected nothing).
|
|
75
|
-
* - `friction.totalRecords === 0` → `**Quality gate friction:** none`
|
|
76
|
-
* - otherwise → count line + bulleted top-offenders list
|
|
77
|
-
*
|
|
78
|
-
* The block reads the existing `signals.ndjson` stream — no new file
|
|
79
|
-
* format. Aggregation is provided by `aggregateBaselineFrictionFromSignals`
|
|
80
|
-
* which the unit test can stub via `runEpicMode({ aggregateFrictionFn })`.
|
|
81
|
-
*/
|
|
82
|
-
export function renderQualityGateFrictionBlock(friction) {
|
|
83
|
-
if (!friction) return '';
|
|
84
|
-
const total = friction.totalRecords ?? 0;
|
|
85
|
-
if (total === 0) {
|
|
86
|
-
return ['', '**Quality gate friction:** none', ''].join('\n');
|
|
87
|
-
}
|
|
88
|
-
const offenders = (friction.topOffenders ?? [])
|
|
89
|
-
.map((o) => {
|
|
90
|
-
const where = o.method ? `${o.file} → ${o.method}` : o.file;
|
|
91
|
-
return `- \`${where}\` — ${o.occurrences} occurrence(s)`;
|
|
92
|
-
})
|
|
93
|
-
.join('\n');
|
|
94
|
-
return [
|
|
95
|
-
'',
|
|
96
|
-
`**Quality gate friction:** ${total} \`baseline-refresh-regression\` record(s) across ${friction.storiesAffected ?? 0} Story/Stories`,
|
|
97
|
-
offenders.length > 0 ? `\nTop offenders:\n${offenders}` : '',
|
|
98
|
-
'',
|
|
99
|
-
].join('\n');
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Render the per-Epic baseline-refresh-rate row (Story #1400 / Task #1427).
|
|
104
|
-
* Returns an empty string when `refresh` is null so the caller can
|
|
105
|
-
* concatenate unconditionally.
|
|
106
|
-
*/
|
|
107
|
-
export function renderBaselineRefreshRateRow(refresh) {
|
|
108
|
-
if (!refresh) return '';
|
|
109
|
-
const row = (refresh.perEpic ?? [])[0];
|
|
110
|
-
if (!row) {
|
|
111
|
-
return [
|
|
112
|
-
'',
|
|
113
|
-
`**Baseline refresh discipline (trailing ${refresh.windowDays}d):** no Story merges in window`,
|
|
114
|
-
'',
|
|
115
|
-
].join('\n');
|
|
116
|
-
}
|
|
117
|
-
const pct = (row.cleanMergeRate * 100).toFixed(1);
|
|
118
|
-
const target = row.cleanMergeRate >= 0.9 ? '✅' : '⚠️';
|
|
119
|
-
return [
|
|
120
|
-
'',
|
|
121
|
-
`**Baseline refresh discipline (trailing ${refresh.windowDays}d):** ${target} ${pct}% clean-merge rate (${row.storyMerges - row.baselineRefreshes}/${row.storyMerges} Stories landed without follow-up refresh; ${row.baselineRefreshes} \`baseline-refresh:\` commit(s))`,
|
|
122
|
-
'',
|
|
123
|
-
].join('\n');
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export function renderEpicBody(payload, extras = {}) {
|
|
127
|
-
const counts = payload.signalCounts ?? {};
|
|
128
|
-
const countLine = Object.entries(counts)
|
|
129
|
-
.map(([k, v]) => `${k}=${v}`)
|
|
130
|
-
.join(', ');
|
|
131
|
-
const hotspots = (payload.topHotspots ?? [])
|
|
132
|
-
.map(
|
|
133
|
-
(h) =>
|
|
134
|
-
`- \`${h.phase}\` — ${h.occurrences} occurrence(s), avg ratio ${h.avgRatio.toFixed(2)}`,
|
|
135
|
-
)
|
|
136
|
-
.join('\n');
|
|
137
|
-
const friction = (payload.mostFrictionStories ?? [])
|
|
138
|
-
.map((s) => `- Story #${s.storyId}: ${s.frictionCount} friction signal(s)`)
|
|
139
|
-
.join('\n');
|
|
140
|
-
const lines = [
|
|
141
|
-
`### Epic Perf Report — Epic #${payload.epicId}`,
|
|
142
|
-
'',
|
|
143
|
-
`Generated at: \`${payload.generatedAt}\``,
|
|
144
|
-
'',
|
|
145
|
-
`**Signal counts:** ${countLine.length > 0 ? countLine : 'none'}`,
|
|
146
|
-
'',
|
|
147
|
-
hotspots.length > 0
|
|
148
|
-
? `**Top hotspots:**\n${hotspots}`
|
|
149
|
-
: '**Top hotspots:** none recorded',
|
|
150
|
-
'',
|
|
151
|
-
friction.length > 0
|
|
152
|
-
? `**Most-friction Stories:**\n${friction}`
|
|
153
|
-
: '**Most-friction Stories:** none recorded',
|
|
154
|
-
renderBaselineRefreshRateRow(extras.baselineRefreshRate),
|
|
155
|
-
renderQualityGateFrictionBlock(extras.qualityGateFriction),
|
|
156
|
-
'',
|
|
157
|
-
'```json',
|
|
158
|
-
JSON.stringify(payload, null, 2),
|
|
159
|
-
'```',
|
|
160
|
-
];
|
|
161
|
-
return lines.join('\n');
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Extract a story-perf-summary payload from a comment body. The body
|
|
166
|
-
* begins with the structured marker line, followed by markdown prose,
|
|
167
|
-
* followed by a fenced ```json``` block carrying the canonical payload.
|
|
168
|
-
* We delegate the fence extraction to `parseFencedJsonComment` so the
|
|
169
|
-
* fenced-JSON regex lives in exactly one place.
|
|
170
|
-
*
|
|
171
|
-
* Returns `null` when the marker is missing, no fence is found, or the
|
|
172
|
-
* fence does not parse — the caller treats absence as "no signal" and
|
|
173
|
-
* keeps walking.
|
|
174
|
-
*/
|
|
175
|
-
export function extractStoryPerfSummaryFromComment(body) {
|
|
176
|
-
if (typeof body !== 'string' || !body.includes(STORY_PERF_MARKER)) {
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
const parsed = parseFencedJsonComment({ body });
|
|
180
|
-
if (parsed && parsed.kind === 'story-perf-summary') return parsed;
|
|
181
|
-
return null;
|
|
182
|
-
}
|