mandrel 1.93.0 → 2.0.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 +59 -73
- package/.agents/agents/acceptance-critic.md +129 -0
- package/.agents/agents/story-worker.md +161 -0
- package/.agents/docs/SDLC.md +489 -1285
- package/.agents/docs/agentrc-reference.json +177 -67
- package/.agents/docs/configuration.md +108 -136
- package/.agents/docs/execution-reference.md +44 -22
- package/.agents/docs/quality-gates.md +13 -19
- package/.agents/docs/workflows.md +3 -3
- package/.agents/instructions.md +107 -108
- package/.agents/rules/ci-remediation.md +8 -12
- package/.agents/rules/git-conventions-reference.md +224 -0
- package/.agents/rules/git-conventions.md +42 -223
- package/.agents/rules/security-baseline.md +5 -0
- package/.agents/rules/testing-standards.md +106 -13
- package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
- package/.agents/schemas/agentrc.schema.json +71 -201
- package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
- package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
- package/.agents/schemas/risk-verdict.schema.json +0 -13
- package/.agents/scripts/acceptance-eval.js +62 -18
- package/.agents/scripts/agents-bootstrap-github.js +1 -1
- package/.agents/scripts/analyze-execution.js +1 -1
- package/.agents/scripts/audit-to-stories.js +7 -7
- package/.agents/scripts/boot-sweep.js +1 -1
- package/.agents/scripts/check-context-budget.js +62 -5
- package/.agents/scripts/check-lifecycle-lint.js +6 -9
- package/.agents/scripts/check-prepush-recovery.js +1 -1
- package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
- package/.agents/scripts/diagnose-friction.js +0 -6
- 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 +5 -5
- 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 -4
- package/.agents/scripts/lib/baselines/reader.js +1 -6
- package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +56 -18
- package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
- package/.agents/scripts/lib/checks/index.js +2 -1
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
- package/.agents/scripts/lib/cli/standard-args.js +13 -22
- package/.agents/scripts/lib/cli-args.js +16 -7
- package/.agents/scripts/lib/close-validation/gates.js +160 -22
- package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
- package/.agents/scripts/lib/config/ci.js +6 -31
- package/.agents/scripts/lib/config/delivery-routing.js +103 -0
- package/.agents/scripts/lib/config/explain.js +57 -36
- package/.agents/scripts/lib/config/limits.js +17 -58
- package/.agents/scripts/lib/config/paths.js +0 -2
- package/.agents/scripts/lib/config/quality.js +1 -1
- package/.agents/scripts/lib/config/runners.js +17 -50
- package/.agents/scripts/lib/config/temp-paths.js +19 -14
- package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
- package/.agents/scripts/lib/config-resolver.js +3 -8
- package/.agents/scripts/lib/config-settings-schema-delivery.js +46 -136
- package/.agents/scripts/lib/config-settings-schema-quality.js +17 -14
- package/.agents/scripts/lib/config-settings-schema.js +52 -38
- package/.agents/scripts/lib/dependency-parser.js +3 -2
- package/.agents/scripts/lib/doc-tiers.js +39 -4
- package/.agents/scripts/lib/duplicate-search.js +211 -41
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
- package/.agents/scripts/lib/findings/promote-finding.js +5 -5
- package/.agents/scripts/lib/framework-version.js +2 -3
- package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
- package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
- package/.agents/scripts/lib/git-utils.js +32 -6
- package/.agents/scripts/lib/github/framework-repo.js +6 -0
- package/.agents/scripts/lib/label-constants.js +10 -23
- package/.agents/scripts/lib/label-taxonomy.js +9 -43
- package/.agents/scripts/lib/observability/active-story-env.js +112 -3
- package/.agents/scripts/lib/observability/hook-heartbeat.js +187 -0
- package/.agents/scripts/lib/observability/source-classifier.js +3 -3
- package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
- package/.agents/scripts/lib/onboard/init-tail.js +1 -3
- package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
- package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
- package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +273 -0
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +204 -0
- package/.agents/scripts/lib/orchestration/code-review.js +20 -268
- package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
- package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
- package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
- 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/lifecycle/emit-loop-tick.js +8 -8
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
- package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
- package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
- package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
- package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
- package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
- 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 +14 -14
- package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
- package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
- package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
- package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
- package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
- package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
- package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
- package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
- package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
- package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
- package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
- package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
- package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +1 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
- 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/phases/code-review.js +15 -12
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
- package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
- package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
- package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
- package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
- package/.agents/scripts/lib/orchestration/ticket-validator.js +3 -8
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
- package/.agents/scripts/lib/planning-corpus.js +16 -11
- package/.agents/scripts/lib/preflight-runner.js +2 -2
- package/.agents/scripts/lib/provider-factory.js +1 -1
- package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
- package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
- package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
- package/.agents/scripts/lib/story-adjacency.js +11 -14
- package/.agents/scripts/lib/story-body/story-body.js +124 -70
- package/.agents/scripts/lib/story-plan.js +2 -4
- package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
- package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
- package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
- package/.agents/scripts/lib/validation-evidence.js +1 -1
- package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
- package/.agents/scripts/lib/workspace-provisioner.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
- 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 +64 -74
- package/.agents/scripts/plan-persist.js +121 -280
- package/.agents/scripts/plan-run-epilogue.js +97 -0
- package/.agents/scripts/post-structured-comment.js +38 -0
- package/.agents/scripts/providers/github/issues.js +17 -33
- package/.agents/scripts/providers/github/mappers.js +0 -12
- package/.agents/scripts/providers/github/tickets.js +2 -5
- package/.agents/scripts/resolve-plan-run.js +117 -0
- package/.agents/scripts/signals-view.js +24 -19
- package/.agents/scripts/single-story-close.js +11 -14
- package/.agents/scripts/single-story-confirm-merge.js +39 -23
- package/.agents/scripts/single-story-init.js +29 -20
- package/.agents/scripts/stories-wave-tick.js +6 -6
- package/.agents/scripts/story-plan.js +26 -47
- package/.agents/scripts/sync-claude-agents.js +165 -0
- package/.agents/scripts/update-ticket-state.js +37 -15
- package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
- package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
- package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
- package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
- package/.agents/skills/core/idea-refinement/SKILL.md +8 -14
- package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
- package/.agents/skills/core/scope-triage/SKILL.md +28 -172
- package/.agents/skills/skills.index.json +8 -418
- package/.agents/starter-agentrc.json +0 -5
- package/.agents/templates/agent-protocol.md +9 -10
- package/.agents/workflows/audit-architecture.md +3 -3
- package/.agents/workflows/audit-clean-code.md +3 -3
- package/.agents/workflows/audit-dependencies.md +3 -3
- package/.agents/workflows/audit-devops.md +3 -3
- package/.agents/workflows/audit-documentation.md +5 -5
- package/.agents/workflows/audit-lighthouse.md +3 -3
- package/.agents/workflows/audit-navigability.md +3 -2
- package/.agents/workflows/audit-performance.md +3 -3
- package/.agents/workflows/audit-privacy.md +3 -3
- package/.agents/workflows/audit-quality.md +3 -3
- package/.agents/workflows/audit-security.md +3 -3
- package/.agents/workflows/audit-seo.md +3 -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 +3 -3
- package/.agents/workflows/deliver.md +122 -131
- package/.agents/workflows/git-cleanup.md +3 -4
- package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
- package/.agents/workflows/helpers/acceptance-self-eval.md +52 -40
- package/.agents/workflows/helpers/code-review.md +70 -193
- package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
- package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
- package/.agents/workflows/helpers/diagnose.md +10 -10
- package/.agents/workflows/helpers/mandrel-sync-config.md +1 -1
- package/.agents/workflows/helpers/parallel-tooling.md +1 -1
- package/.agents/workflows/helpers/signals.md +16 -16
- package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
- package/.agents/workflows/mandrel-update.md +3 -2
- package/.agents/workflows/plan.md +112 -145
- package/.agents/workflows/qa-assist.md +24 -30
- package/.agents/workflows/qa-explore.md +29 -38
- package/.agents/workflows/qa-run.md +2 -2
- package/README.md +9 -8
- package/docs/CHANGELOG.md +46 -0
- package/lib/cli/registry.js +95 -0
- package/lib/migrations/index.js +6 -5
- package/package.json +5 -3
- package/.agents/personas/architect.md +0 -113
- package/.agents/personas/devops-engineer.md +0 -38
- package/.agents/personas/engineer-mobile.md +0 -120
- package/.agents/personas/engineer-web.md +0 -111
- package/.agents/personas/engineer.md +0 -119
- package/.agents/personas/product.md +0 -94
- package/.agents/personas/project-manager.md +0 -114
- package/.agents/personas/qa-engineer.md +0 -95
- package/.agents/personas/refactorer.md +0 -113
- package/.agents/personas/security-engineer.md +0 -112
- package/.agents/personas/sre.md +0 -86
- package/.agents/personas/technical-writer.md +0 -101
- package/.agents/personas/ux-designer.md +0 -95
- package/.agents/schemas/dispatch-manifest.json +0 -232
- package/.agents/schemas/epic-spec.schema.json +0 -153
- package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
- 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 -590
- package/.agents/scripts/epic-execute-record-wave.js +0 -449
- package/.agents/scripts/epic-plan-clarity.js +0 -211
- package/.agents/scripts/epic-plan-decompose.js +0 -54
- package/.agents/scripts/epic-plan-healthcheck.js +0 -581
- package/.agents/scripts/epic-plan-spec.js +0 -64
- 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/orchestration/context-hydration-engine.js +0 -660
- 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/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 -388
- 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/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/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-story-dispatch-end.js +0 -147
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -384
- 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 -278
- 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/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/post-merge-pipeline.js +0 -205
- 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-runner.js +0 -197
- package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +0 -109
- 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 -301
- 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/plan-critics.js +0 -199
- package/.agents/scripts/retro-run.js +0 -218
- 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 -335
- package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
- package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
- package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
- package/.agents/skills/core/code-simplification/SKILL.md +0 -389
- package/.agents/skills/core/context-engineering/SKILL.md +0 -309
- package/.agents/skills/core/context-engineering/examples.md +0 -58
- package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
- 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 -413
- package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
- package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
- package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
- package/.agents/skills/core/idea-refinement/examples.md +0 -437
- package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
- package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
- package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
- package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
- package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
- package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
- package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
- package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
- package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
- package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
- package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
- package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
- package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
- package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
- package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
- package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
- package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
- package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
- package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
- package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
- package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
- package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
- package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
- package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
- package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
- package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
- package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
- package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
- package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
- package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
- package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
- package/.agents/workflows/helpers/deliver-epic-reference.md +0 -534
- package/.agents/workflows/helpers/deliver-epic.md +0 -955
- package/.agents/workflows/helpers/deliver-stories.md +0 -440
- package/.agents/workflows/helpers/epic-audit.md +0 -189
- package/.agents/workflows/helpers/epic-deliver-story.md +0 -427
- 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 -351
- package/.agents/workflows/helpers/plan-story.md +0 -251
- package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
- /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pre-merge-validation.js — shift-left close-validation gate runner +
|
|
3
|
-
* maintainability projection advisory.
|
|
4
|
-
*
|
|
5
|
-
* Extracted from story-close.js (Story #956, Theme A finishing touch) so the
|
|
6
|
-
* close orchestrator becomes a thin CLI shell. Two responsibilities:
|
|
7
|
-
*
|
|
8
|
-
* - runPreMergeGates — drives `runCloseValidation` over the
|
|
9
|
-
* canonical gate list (typecheck, lint, test,
|
|
10
|
-
* format, maintainability, crap), routes
|
|
11
|
-
* `lint`/`test` start events into the supplied
|
|
12
|
-
* phase-timer, and throws on the first failed
|
|
13
|
-
* gate with the gate-specific hint embedded in
|
|
14
|
-
* the error message.
|
|
15
|
-
* - emitMaintainabilityProjection — runs the per-file MI ceiling projection
|
|
16
|
-
* and emits the `baseline-refresh:` advisory
|
|
17
|
-
* before the merge so the operator can ship the
|
|
18
|
-
* refresh atomically with the Story PR.
|
|
19
|
-
*
|
|
20
|
-
* Both helpers take their dependencies as injectable seams so unit tests
|
|
21
|
-
* pin behaviour without spawning the close script.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
// Story #1973 / Task #1985 — direct import from the maintainability per-kind
|
|
25
|
-
// module under `.agents/scripts/lib/baselines/kinds/`. Replaces the historical
|
|
26
|
-
// `child_process.spawn(node check-maintainability.js)` arm of this helper:
|
|
27
|
-
// the kernel-version label that used to come from the CLI's stdout is now
|
|
28
|
-
// resolved in-process from the per-kind module, and the test suite's
|
|
29
|
-
// no-spawn spy proves the projection path never reaches a per-kind CLI
|
|
30
|
-
// subprocess.
|
|
31
|
-
import * as maintainabilityKind from '../../baselines/kinds/maintainability.js';
|
|
32
|
-
import { buildDefaultGates as defaultBuildDefaultGates } from '../../close-validation/gates.js';
|
|
33
|
-
import {
|
|
34
|
-
formatMaintainabilityProjection as defaultFormatMaintainabilityProjection,
|
|
35
|
-
projectMaintainabilityRegressions as defaultProjectMaintainabilityRegressions,
|
|
36
|
-
} from '../../close-validation/projections/maintainability.js';
|
|
37
|
-
import { runCloseValidation as defaultRunCloseValidation } from '../../close-validation/runner.js';
|
|
38
|
-
import { getBaselines as defaultGetBaselines } from '../../config-resolver.js';
|
|
39
|
-
import { Logger as DefaultLogger } from '../../Logger.js';
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Story #2250 — lifecycle emits fire only when both a positive epicId and a
|
|
43
|
-
* positive storyId are present (the schema requires both) and a bus exists.
|
|
44
|
-
* Legacy resume fixtures pass `storyId: null` and must run without emits.
|
|
45
|
-
* Story #4075 — extracted from `runPreMergeGates`.
|
|
46
|
-
*/
|
|
47
|
-
export function lifecycleEmitsActive({ epicId, storyId, bus }) {
|
|
48
|
-
return (
|
|
49
|
-
Number.isInteger(epicId) &&
|
|
50
|
-
epicId > 0 &&
|
|
51
|
-
Number.isInteger(storyId) &&
|
|
52
|
-
storyId > 0 &&
|
|
53
|
-
!!bus
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Build the typed `PRE_MERGE_GATE_FAILED` Error from the first failed gate.
|
|
59
|
-
* Story #2136 / Task #2143 — failure metadata is surfaced as typed Error
|
|
60
|
-
* properties so callers (notably `runPreMergeGatesWithAttribution`)
|
|
61
|
-
* pattern-match exit codes without parsing the human message; the message
|
|
62
|
-
* format is preserved byte-for-byte so existing regex consumers keep
|
|
63
|
-
* matching. Story #4075 — extracted from `runPreMergeGates`.
|
|
64
|
-
*/
|
|
65
|
-
export function buildGateFailureError({ gate, status, gateCwd }) {
|
|
66
|
-
const err = new Error(
|
|
67
|
-
`Pre-merge validation failed at "${gate.name}" (exit ${status})${gateCwd ? ` in ${gateCwd}` : ''}.` +
|
|
68
|
-
(gate.hint ? ` ${gate.hint}` : ''),
|
|
69
|
-
);
|
|
70
|
-
err.code = 'PRE_MERGE_GATE_FAILED';
|
|
71
|
-
err.gateName = gate.name;
|
|
72
|
-
err.exitCode = status;
|
|
73
|
-
err.gateCwd = gateCwd ?? null;
|
|
74
|
-
return err;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Run the pre-merge validation gate chain. On failure throws an `Error`
|
|
79
|
-
* whose message embeds the first failed gate's name, exit code, hint, and
|
|
80
|
-
* the working directory the gate ran in — the `runAsCli` boundary in
|
|
81
|
-
* `story-close.js` maps the throw to `process.exit(1)`. (See Story #959 —
|
|
82
|
-
* close-tail scripts must throw rather than route through the logger's
|
|
83
|
-
* fatal sink, so a mocked `process.exit` cannot swallow the failure
|
|
84
|
-
* silently.)
|
|
85
|
-
*
|
|
86
|
-
* Story #1120: pass `worktreePath` (`.worktrees/story-<id>/`) so every
|
|
87
|
-
* gate runs against the Story branch's post-rebase tree, not the main
|
|
88
|
-
* checkout. Without it, gate spawn falls back to `cwd` (the main
|
|
89
|
-
* checkout) — the legacy single-tree path remains intact.
|
|
90
|
-
*
|
|
91
|
-
* `phaseTimer` may be omitted; when present, lint/test starts are timed.
|
|
92
|
-
*
|
|
93
|
-
* Story #2250 — the gate chain is the canonical close-validate sub-phase
|
|
94
|
-
* of the close-tail; this helper emits `close-validate.start` /
|
|
95
|
-
* `close-validate.end` events on the supplied lifecycle bus so the
|
|
96
|
-
* lifecycle ledger captures the sub-phase boundary with non-zero
|
|
97
|
-
* `durationMs`. On gate failure the helper also emits `story.blocked`
|
|
98
|
-
* with a typed `close-validate-failed:<gateName>` reason BEFORE throwing
|
|
99
|
-
* — the existing BlockerHandler listener (Story #2241 / Task #2246)
|
|
100
|
-
* cascades that to `epic.blocked`, so a failed validator routes through
|
|
101
|
-
* the lifecycle cascade rather than being silently swallowed by the
|
|
102
|
-
* caller's try/catch. The throw shape is preserved byte-for-byte so the
|
|
103
|
-
* regex consumers in `runPreMergeGatesWithAttribution` keep matching.
|
|
104
|
-
*/
|
|
105
|
-
export async function runPreMergeGates({
|
|
106
|
-
cwd,
|
|
107
|
-
worktreePath,
|
|
108
|
-
epicBranch,
|
|
109
|
-
config,
|
|
110
|
-
storyId,
|
|
111
|
-
epicId,
|
|
112
|
-
useEvidence = true,
|
|
113
|
-
phaseTimer,
|
|
114
|
-
bus,
|
|
115
|
-
now = Date.now,
|
|
116
|
-
logger = DefaultLogger,
|
|
117
|
-
buildDefaultGates = defaultBuildDefaultGates,
|
|
118
|
-
runCloseValidation = defaultRunCloseValidation,
|
|
119
|
-
}) {
|
|
120
|
-
// Epic #2646 Story C (Task #2700) — `bus` is a hard input. The
|
|
121
|
-
// previous guarded `emitLifecycleSafe` helper that tolerated a null
|
|
122
|
-
// bus is gone. The `emitsActive` outer guard below still skips emits
|
|
123
|
-
// for legacy resume fixtures that pass `storyId: null` (those rows
|
|
124
|
-
// have no Story-scoped lifecycle), but bus must be present.
|
|
125
|
-
if (!bus || typeof bus.emit !== 'function') {
|
|
126
|
-
throw new TypeError(
|
|
127
|
-
'runPreMergeGates: bus is required (object with emit()).',
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
logger.info?.(
|
|
131
|
-
`[close-validation] Running pre-merge gates (typecheck, lint, test, format, maintainability, crap, baselines)${worktreePath ? ` in ${worktreePath}` : ''}${epicBranch ? ` against baseline ref ${epicBranch}` : ''}...`,
|
|
132
|
-
);
|
|
133
|
-
// `buildDefaultGates` reads the canonical resolved config directly:
|
|
134
|
-
// gate commands resolve from `project.commands` and the CRAP toggle
|
|
135
|
-
// from `delivery.quality.gates.crap.enabled`.
|
|
136
|
-
// Probe the coverage script from the gate execution directory (the Story
|
|
137
|
-
// worktree when present) so coverage-capture is only registered when the
|
|
138
|
-
// consumer ships `test:coverage` (#4473).
|
|
139
|
-
const gates = buildDefaultGates({
|
|
140
|
-
config,
|
|
141
|
-
epicBranch,
|
|
142
|
-
cwd: worktreePath || cwd,
|
|
143
|
-
});
|
|
144
|
-
const gateCount = Array.isArray(gates) ? gates.length : 0;
|
|
145
|
-
// Story #2250 — emit `close-validate.start` only when both an epicId
|
|
146
|
-
// and a storyId are present; the schema requires both, and unit
|
|
147
|
-
// fixtures that drive the helper with `storyId: null` (legacy resume
|
|
148
|
-
// tests) must continue to operate without lifecycle observability.
|
|
149
|
-
const emitsActive = lifecycleEmitsActive({ epicId, storyId, bus });
|
|
150
|
-
const startedAt = typeof now === 'function' ? now() : Date.now();
|
|
151
|
-
|
|
152
|
-
// Emit the `close-validate.end` boundary, plus the `story.blocked`
|
|
153
|
-
// cascade trigger on failure (Story #2250). No-op when emits are
|
|
154
|
-
// inactive (legacy resume fixtures with `storyId: null`).
|
|
155
|
-
const emitEnd = async ({ ok, extra = {}, blockedReason } = {}) => {
|
|
156
|
-
if (!emitsActive) return;
|
|
157
|
-
const endedAt = typeof now === 'function' ? now() : Date.now();
|
|
158
|
-
await bus.emit('close-validate.end', {
|
|
159
|
-
epicId,
|
|
160
|
-
storyId,
|
|
161
|
-
ok,
|
|
162
|
-
gateCount,
|
|
163
|
-
...extra,
|
|
164
|
-
durationMs: Math.max(0, endedAt - startedAt),
|
|
165
|
-
});
|
|
166
|
-
if (blockedReason) {
|
|
167
|
-
await bus.emit('story.blocked', { storyId, reason: blockedReason });
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
if (emitsActive) {
|
|
172
|
-
await bus.emit('close-validate.start', { epicId, storyId });
|
|
173
|
-
}
|
|
174
|
-
let validation;
|
|
175
|
-
try {
|
|
176
|
-
validation = await runCloseValidation({
|
|
177
|
-
cwd,
|
|
178
|
-
worktreePath,
|
|
179
|
-
gates,
|
|
180
|
-
log: (m) => logger.info(m),
|
|
181
|
-
onGateStart: (gate) => {
|
|
182
|
-
// Only the canonical phase-enum gates drive `mark()`. Non-enum gates
|
|
183
|
-
// (`typecheck`, `format`, `check-maintainability`) share the
|
|
184
|
-
// currently-open phase's wall clock — a deliberate choice so the
|
|
185
|
-
// `phase-timings` schema stays stable against future gate churn.
|
|
186
|
-
if (phaseTimer && (gate.name === 'lint' || gate.name === 'test')) {
|
|
187
|
-
phaseTimer.mark(gate.name);
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
storyId,
|
|
191
|
-
epicId,
|
|
192
|
-
useEvidence,
|
|
193
|
-
});
|
|
194
|
-
} catch (err) {
|
|
195
|
-
// Reach this branch only when `runCloseValidation` itself throws
|
|
196
|
-
// (spawn-level catastrophe — the per-gate failures route through
|
|
197
|
-
// `validation.failed` below). Emit the matching `close-validate.end`
|
|
198
|
-
// with `ok:false` so the ledger always carries the boundary, then
|
|
199
|
-
// re-throw.
|
|
200
|
-
await emitEnd({
|
|
201
|
-
ok: false,
|
|
202
|
-
extra: { failedGate: 'runner-error' },
|
|
203
|
-
blockedReason: 'close-validate-failed:runner-error',
|
|
204
|
-
});
|
|
205
|
-
throw err;
|
|
206
|
-
}
|
|
207
|
-
if (!validation.ok) {
|
|
208
|
-
const { gate, status, cwd: gateCwd } = validation.failed[0];
|
|
209
|
-
// Story #2250 — emit the boundary + `story.blocked` cascade BEFORE
|
|
210
|
-
// throwing so the lifecycle ledger captures the boundary even when the
|
|
211
|
-
// caller's try/catch swallows the throw, and the BlockerHandler
|
|
212
|
-
// listener cascades to `epic.blocked`.
|
|
213
|
-
await emitEnd({
|
|
214
|
-
ok: false,
|
|
215
|
-
extra: { failedGate: gate.name, exitCode: status },
|
|
216
|
-
blockedReason: `close-validate-failed:${gate.name}`,
|
|
217
|
-
});
|
|
218
|
-
throw buildGateFailureError({ gate, status, gateCwd });
|
|
219
|
-
}
|
|
220
|
-
await emitEnd({ ok: true });
|
|
221
|
-
return validation;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Resolve the maintainability kernel version from the per-kind module so
|
|
226
|
-
* the projection log header can name the kernel currently in scope. Reads
|
|
227
|
-
* are best-effort — a sentinel `'0.0.0'` from the kernel-version
|
|
228
|
-
* resolver (e.g. when typhonjs-escomplex is missing under a partial
|
|
229
|
-
* install) collapses to `null` so the helper never injects a misleading
|
|
230
|
-
* label into the log.
|
|
231
|
-
*
|
|
232
|
-
* Story #1973 / Task #1985 — this is the only call site outside the
|
|
233
|
-
* `baselines/` tree that touches `kinds/maintainability.js` directly; the
|
|
234
|
-
* import is the load-bearing acceptance hook for "no per-kind CLI spawn"
|
|
235
|
-
* because referencing `kindModule.kernelVersion` proves the helper does
|
|
236
|
-
* not need to fork a subprocess to learn what kernel it is running under.
|
|
237
|
-
*
|
|
238
|
-
* @param {object} kindModule - Per-kind maintainability module.
|
|
239
|
-
* @returns {string | null}
|
|
240
|
-
*/
|
|
241
|
-
function resolveKernelLabel(kindModule) {
|
|
242
|
-
try {
|
|
243
|
-
const v = kindModule?.kernelVersion?.();
|
|
244
|
-
if (typeof v !== 'string' || v === '0.0.0') return null;
|
|
245
|
-
return v;
|
|
246
|
-
} catch {
|
|
247
|
-
return null;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Emit the per-file MI ceiling projection advisory. Failure is non-fatal
|
|
253
|
-
* (logged through `logger.warn`) — the projection is informational only,
|
|
254
|
-
* and a missing baseline path skips the helper entirely.
|
|
255
|
-
*
|
|
256
|
-
* Story #1973 / Task #1985 — the projection no longer fans out a
|
|
257
|
-
* per-kind `child_process.spawn(node check-maintainability.js)` to learn
|
|
258
|
-
* the kernel context: the per-kind module under `baselines/kinds/` is
|
|
259
|
-
* imported directly. The `kindModule` collaborator is injectable so unit
|
|
260
|
-
* tests can pin the kernel label without touching the on-disk module.
|
|
261
|
-
*/
|
|
262
|
-
export function emitMaintainabilityProjection({
|
|
263
|
-
cwd,
|
|
264
|
-
epicBranch,
|
|
265
|
-
storyBranch,
|
|
266
|
-
config,
|
|
267
|
-
logger = DefaultLogger,
|
|
268
|
-
getBaselines = defaultGetBaselines,
|
|
269
|
-
projectMaintainabilityRegressions = defaultProjectMaintainabilityRegressions,
|
|
270
|
-
formatMaintainabilityProjection = defaultFormatMaintainabilityProjection,
|
|
271
|
-
kindModule = maintainabilityKind,
|
|
272
|
-
}) {
|
|
273
|
-
try {
|
|
274
|
-
const baselinePath = getBaselines(config)?.maintainability?.path;
|
|
275
|
-
if (!baselinePath) return;
|
|
276
|
-
const projection = projectMaintainabilityRegressions({
|
|
277
|
-
cwd,
|
|
278
|
-
epicBranch,
|
|
279
|
-
storyBranch,
|
|
280
|
-
baselinePath,
|
|
281
|
-
});
|
|
282
|
-
const advisory = formatMaintainabilityProjection(projection);
|
|
283
|
-
if (advisory) {
|
|
284
|
-
const kernel = resolveKernelLabel(kindModule);
|
|
285
|
-
if (kernel) {
|
|
286
|
-
logger.info(
|
|
287
|
-
`[close-validation] Pre-merge MI projection (kernel=${kernel}):`,
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
for (const line of advisory.split('\n')) logger.info(line);
|
|
291
|
-
} else if (projection.skipped) {
|
|
292
|
-
logger.info(
|
|
293
|
-
`[close-validation] Pre-merge MI projection skipped (${projection.skipped}).`,
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
} catch (err) {
|
|
297
|
-
logger.warn?.(
|
|
298
|
-
`[close-validation] Pre-merge MI projection failed: ${err?.message ?? err}`,
|
|
299
|
-
);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* shared-checkout-guard.js — cross-epic contention guard for the merge
|
|
3
|
-
* phase's `git checkout <epicBranch>` in the shared main checkout
|
|
4
|
-
* (Story #4460).
|
|
5
|
-
*
|
|
6
|
-
* `story-close.js`'s merge phase (`runFinalizeMerge` in `merge-runner.js`)
|
|
7
|
-
* runs `git checkout <epicBranch>` directly in the shared main repo
|
|
8
|
-
* checkout — `close-inputs.js` resolves `cwd` to `PROJECT_ROOT`, not an
|
|
9
|
-
* isolated worktree. The only exclusivity guard around that shared
|
|
10
|
-
* checkout is the per-Epic `epic-merge-lock.js` mutex, which only
|
|
11
|
-
* serializes concurrent runs for the SAME epic. Nothing stops a
|
|
12
|
-
* DIFFERENT epic's concurrently-running `story-close.js` from treating
|
|
13
|
-
* the same shared checkout as scratch space at the same time.
|
|
14
|
-
*
|
|
15
|
-
* This was observed live: while delivering Epic #4425 Stories #4427/#4428,
|
|
16
|
-
* the shared checkout repeatedly carried uncommitted stray changes
|
|
17
|
-
* belonging to a concurrently-running Epic #4405 delivery (parked on
|
|
18
|
-
* `epic/4405` with dirty edits), which blocked the `git checkout epic/4425`
|
|
19
|
-
* merge step with a raw `error: Your local changes ... would be
|
|
20
|
-
* overwritten by checkout`.
|
|
21
|
-
*
|
|
22
|
-
* `assertSharedCheckoutAvailable` runs immediately before that checkout
|
|
23
|
-
* and fails fast with an actionable, story-close-specific diagnostic
|
|
24
|
-
* instead of letting the raw git error surface. It COMPOSES with (does
|
|
25
|
-
* not replace) the per-Epic lock: by the time this guard runs, the
|
|
26
|
-
* caller's own epic lock is already held (acquired around the whole
|
|
27
|
-
* close flow in `story-close.js`), so this guard only inspects OTHER
|
|
28
|
-
* epics' lock files plus the tree's overall dirty state — it never
|
|
29
|
-
* contends with same-epic concurrent runs, which continue to serialize
|
|
30
|
-
* solely via `withEpicMergeLock` before this guard ever executes.
|
|
31
|
-
*
|
|
32
|
-
* Breadth trade-off (deliberate): the foreign-lock probe keys on the
|
|
33
|
-
* OTHER epic's per-epic merge lock, which that run holds for its WHOLE
|
|
34
|
-
* close flow — so any overlapping story-close of another epic trips this
|
|
35
|
-
* guard even when that run never actually touches the shared checkout
|
|
36
|
-
* during the overlap. The refusal is deterministic and loud (throws with
|
|
37
|
-
* a diagnostic naming the holder pid), never a deadlock (no waiting),
|
|
38
|
-
* and stale/dead-pid foreign locks are ignored via the pid-liveness
|
|
39
|
-
* probe. Narrowing the window (a dedicated checkout-phase lock) was
|
|
40
|
-
* considered and rejected: the coarse refusal is rare, cheap to retry,
|
|
41
|
-
* and far simpler than a second lock tier.
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
import { findForeignActiveEpicLock as defaultFindForeignActiveEpicLock } from '../../epic-merge-lock.js';
|
|
45
|
-
import { gitSpawn as defaultGitSpawn } from '../../git-utils.js';
|
|
46
|
-
|
|
47
|
-
const MAX_LISTED_DIRTY_FILES = 20;
|
|
48
|
-
|
|
49
|
-
function describeForeignLock(foreign) {
|
|
50
|
-
const acquired = Number.isFinite(foreign.acquiredAt)
|
|
51
|
-
? new Date(foreign.acquiredAt).toISOString()
|
|
52
|
-
: 'an unknown time';
|
|
53
|
-
return (
|
|
54
|
-
`[story-close] shared-checkout guard: refusing to touch the shared main checkout — ` +
|
|
55
|
-
`it is currently held by epic #${foreign.epicId}'s story-close merge phase ` +
|
|
56
|
-
`(lock ${foreign.filePath}, pid ${foreign.pid}, acquired ${acquired}). ` +
|
|
57
|
-
`Wait for that epic's story-close run to finish before retrying this merge. ` +
|
|
58
|
-
`If you have independently confirmed that process is no longer running, remove ` +
|
|
59
|
-
`the lock file by hand — never force a checkout past a live foreign lock. ` +
|
|
60
|
-
`See .agents/rules/git-conventions.md § Shared-checkout contention (Story #4460).`
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function listDirtyFiles(porcelainOutput) {
|
|
65
|
-
// `git status --porcelain` lines are `XY <path>` — a fixed 2-char status
|
|
66
|
-
// column, a space, then the path. Strip only a trailing `\r` (Windows)
|
|
67
|
-
// before slicing off that 3-char prefix; trimming the whole line first
|
|
68
|
-
// would shift the slice offset whenever the status column starts with a
|
|
69
|
-
// space (the common "unstaged modification" case), truncating the path.
|
|
70
|
-
const lines = porcelainOutput
|
|
71
|
-
.split('\n')
|
|
72
|
-
.map((line) => line.replace(/\r$/, ''))
|
|
73
|
-
.filter((line) => line.length > 0);
|
|
74
|
-
const shown = lines
|
|
75
|
-
.slice(0, MAX_LISTED_DIRTY_FILES)
|
|
76
|
-
.map((line) => line.slice(3).trim() || line);
|
|
77
|
-
const overflow = lines.length - shown.length;
|
|
78
|
-
return overflow > 0
|
|
79
|
-
? `${shown.join(', ')}, … (+${overflow} more)`
|
|
80
|
-
: shown.join(', ');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function describeDirtyCheckout({ cwd, epicId, currentBranch, dirtyFiles }) {
|
|
84
|
-
return (
|
|
85
|
-
`[story-close] shared-checkout guard: refusing to check out the epic branch for ` +
|
|
86
|
-
`epic #${epicId} — the shared main checkout at ${cwd} is dirty (currently on ` +
|
|
87
|
-
`\`${currentBranch}\`). Dirty files: ${dirtyFiles}. This usually means another ` +
|
|
88
|
-
`epic's story-close run left uncommitted work in the shared checkout, or a prior ` +
|
|
89
|
-
`run crashed mid-merge. Resolve manually (stash/commit/reset in ${cwd}) before ` +
|
|
90
|
-
`retrying. See .agents/rules/git-conventions.md § Shared-checkout contention ` +
|
|
91
|
-
`(Story #4460).`
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Fail fast when the shared main checkout is not safely available for this
|
|
97
|
-
* epic's merge-phase `git checkout <epicBranch>` — either because another
|
|
98
|
-
* epic's story-close merge phase currently holds it (a live foreign lock),
|
|
99
|
-
* or because it is simply dirty (regardless of whose branch is checked
|
|
100
|
-
* out). Silent no-op when the checkout is clean and uncontended.
|
|
101
|
-
*
|
|
102
|
-
* @param {{
|
|
103
|
-
* cwd: string,
|
|
104
|
-
* epicId: number|string,
|
|
105
|
-
* gitSpawn?: typeof defaultGitSpawn,
|
|
106
|
-
* findForeignActiveEpicLock?: typeof defaultFindForeignActiveEpicLock,
|
|
107
|
-
* }} opts
|
|
108
|
-
* @throws {Error} with an actionable, story-close-specific diagnostic.
|
|
109
|
-
*/
|
|
110
|
-
/**
|
|
111
|
-
* Foreign-lock-only variant for the RESUME merge path (Story #4460
|
|
112
|
-
* follow-up): a resume legitimately re-enters a shared checkout that is
|
|
113
|
-
* dirty with THIS story's own in-progress merge, so the dirty-tree half
|
|
114
|
-
* of `assertSharedCheckoutAvailable` would false-positive there. The
|
|
115
|
-
* cross-epic hazard — another epic's live merge phase holding the
|
|
116
|
-
* checkout — still applies and is the only probe this variant runs.
|
|
117
|
-
*/
|
|
118
|
-
export function assertNoForeignEpicLock({
|
|
119
|
-
cwd,
|
|
120
|
-
epicId,
|
|
121
|
-
findForeignActiveEpicLock = defaultFindForeignActiveEpicLock,
|
|
122
|
-
}) {
|
|
123
|
-
const foreign = findForeignActiveEpicLock(epicId, { repoRoot: cwd });
|
|
124
|
-
if (foreign) {
|
|
125
|
-
throw new Error(describeForeignLock(foreign));
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function assertSharedCheckoutAvailable({
|
|
130
|
-
cwd,
|
|
131
|
-
epicId,
|
|
132
|
-
gitSpawn = defaultGitSpawn,
|
|
133
|
-
findForeignActiveEpicLock = defaultFindForeignActiveEpicLock,
|
|
134
|
-
}) {
|
|
135
|
-
const foreign = findForeignActiveEpicLock(epicId, { repoRoot: cwd });
|
|
136
|
-
if (foreign) {
|
|
137
|
-
throw new Error(describeForeignLock(foreign));
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const statusRes = gitSpawn(cwd, 'status', '--porcelain');
|
|
141
|
-
if (statusRes.status !== 0) {
|
|
142
|
-
// Can't determine dirtiness from here — let the downstream checkout
|
|
143
|
-
// surface whatever git itself reports rather than guessing.
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
const porcelain = statusRes.stdout || '';
|
|
147
|
-
if (porcelain.trim().length === 0) return;
|
|
148
|
-
|
|
149
|
-
const branchRes = gitSpawn(cwd, 'rev-parse', '--abbrev-ref', 'HEAD');
|
|
150
|
-
const currentBranch =
|
|
151
|
-
branchRes.status === 0
|
|
152
|
-
? (branchRes.stdout || '').trim() || 'unknown'
|
|
153
|
-
: 'unknown';
|
|
154
|
-
|
|
155
|
-
throw new Error(
|
|
156
|
-
describeDirtyCheckout({
|
|
157
|
-
cwd,
|
|
158
|
-
epicId,
|
|
159
|
-
currentBranch,
|
|
160
|
-
dirtyFiles: listDirtyFiles(porcelain),
|
|
161
|
-
}),
|
|
162
|
-
);
|
|
163
|
-
}
|