mandrel 2.59.0 → 2.61.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 +21 -19
- package/.agents/agents/acceptance-critic.md +24 -43
- package/.agents/agents/story-worker.md +20 -21
- package/.agents/docs/agentrc-reference.json +5 -84
- package/.agents/docs/configuration.md +48 -132
- package/.agents/docs/workflows.md +2 -2
- package/.agents/instructions.md +5 -8
- package/.agents/rules/ci-remediation.md +41 -8
- package/.agents/rules/gherkin-standards.md +4 -0
- package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
- package/.agents/schemas/agentrc.schema.json +16 -496
- package/.agents/schemas/story-deliver-terminal.schema.json +13 -3
- package/.agents/schemas/validation-evidence.schema.json +2 -1
- package/.agents/scripts/README.md +23 -13
- package/.agents/scripts/acceptance-eval.js +35 -169
- package/.agents/scripts/agents-bootstrap-github.js +27 -129
- package/.agents/scripts/apply-quality-bootstrap.js +4 -40
- package/.agents/scripts/audit-baselines.js +6 -27
- package/.agents/scripts/audit-labels-bootstrap.js +5 -29
- package/.agents/scripts/audit-to-stories.js +91 -361
- package/.agents/scripts/boot-sweep.js +19 -72
- package/.agents/scripts/bootstrap.js +74 -395
- package/.agents/scripts/ceremony-derive.js +10 -41
- package/.agents/scripts/check-arch-cycles.js +14 -64
- package/.agents/scripts/check-baselines.js +8 -48
- package/.agents/scripts/check-context-budget.js +105 -311
- package/.agents/scripts/check-cyclomatic.js +12 -44
- package/.agents/scripts/check-dead-exports.js +13 -64
- package/.agents/scripts/check-doc-links.js +38 -186
- package/.agents/scripts/check-gherkin-corpus.js +24 -127
- package/.agents/scripts/check-test-temp-hygiene.js +28 -169
- package/.agents/scripts/coverage-capture.js +34 -98
- package/.agents/scripts/deliver-light.js +25 -171
- package/.agents/scripts/deliver-recover.js +6 -42
- package/.agents/scripts/deliver-run.js +534 -0
- package/.agents/scripts/diagnose-friction.js +24 -116
- package/.agents/scripts/drain-pending-cleanup.js +1 -1
- package/.agents/scripts/evidence-gate.js +23 -85
- package/.agents/scripts/file-ci-gap.js +57 -49
- package/.agents/scripts/generate-config-docs.js +30 -170
- package/.agents/scripts/generate-lens-checklists.js +8 -52
- package/.agents/scripts/generate-skills-index.js +14 -112
- package/.agents/scripts/generate-workflows-doc.js +10 -70
- package/.agents/scripts/git-cleanup.js +2 -34
- package/.agents/scripts/lib/Graph.js +24 -81
- package/.agents/scripts/lib/ITicketingProvider.js +47 -143
- package/.agents/scripts/lib/Logger.js +14 -76
- package/.agents/scripts/lib/audit-baselines/engine.js +11 -31
- package/.agents/scripts/lib/audit-baselines/gate-surface.js +3 -17
- package/.agents/scripts/lib/audit-baselines/headroom.js +4 -20
- package/.agents/scripts/lib/audit-baselines/hotspots.js +3 -15
- package/.agents/scripts/lib/audit-baselines/kinds.js +23 -89
- package/.agents/scripts/lib/audit-baselines/outliers.js +6 -23
- package/.agents/scripts/lib/audit-baselines/read.js +3 -16
- package/.agents/scripts/lib/audit-baselines/staleness.js +7 -26
- package/.agents/scripts/lib/audit-baselines/surface-entry.js +7 -28
- package/.agents/scripts/lib/audit-baselines/trend.js +7 -20
- package/.agents/scripts/lib/audit-baselines/weights.js +9 -37
- package/.agents/scripts/lib/audit-suite/audit-rules-reader.js +3 -18
- package/.agents/scripts/lib/audit-suite/checklist-threading.js +26 -124
- package/.agents/scripts/lib/audit-suite/dispatch-checklist.js +14 -45
- package/.agents/scripts/lib/audit-suite/findings.js +12 -52
- package/.agents/scripts/lib/audit-suite/frontmatter.js +5 -29
- package/.agents/scripts/lib/audit-suite/index.js +1 -15
- package/.agents/scripts/lib/audit-suite/lens-checklist.js +10 -45
- package/.agents/scripts/lib/audit-suite/lens-diff-floor.js +11 -76
- package/.agents/scripts/lib/audit-suite/runner.js +13 -43
- package/.agents/scripts/lib/audit-suite/selector.js +49 -349
- package/.agents/scripts/lib/audit-suite/substitutions.js +12 -40
- package/.agents/scripts/lib/audit-suite/workflow-loader.js +3 -15
- package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +11 -73
- package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +8 -37
- package/.agents/scripts/lib/audit-to-stories/build-story-body.js +25 -143
- package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +14 -80
- package/.agents/scripts/lib/audit-to-stories/epic-grouping-directive.js +4 -18
- package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +7 -40
- package/.agents/scripts/lib/audit-to-stories/group-findings.js +9 -39
- package/.agents/scripts/lib/audit-to-stories/issue-corpus.js +10 -66
- package/.agents/scripts/lib/audit-to-stories/issue-index.js +6 -30
- package/.agents/scripts/lib/audit-to-stories/issues-file.js +6 -36
- package/.agents/scripts/lib/audit-to-stories/ledger-commit.js +17 -69
- package/.agents/scripts/lib/audit-to-stories/ledger-pr.js +17 -85
- package/.agents/scripts/lib/audit-to-stories/ledger-record.js +10 -48
- package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +38 -146
- package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +7 -42
- package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +10 -57
- package/.agents/scripts/lib/baseline-loader.js +12 -51
- package/.agents/scripts/lib/baseline-schema-registry.js +5 -22
- package/.agents/scripts/lib/baselines/component-matcher.js +3 -12
- package/.agents/scripts/lib/baselines/components.js +10 -61
- package/.agents/scripts/lib/baselines/coverage-updater-cli.js +7 -36
- package/.agents/scripts/lib/baselines/crap-preview-incremental.js +7 -19
- package/.agents/scripts/lib/baselines/crap-preview-scan.js +19 -45
- package/.agents/scripts/lib/baselines/crap-updater-cli.js +16 -65
- package/.agents/scripts/lib/baselines/diff-scope-cli.js +5 -33
- package/.agents/scripts/lib/baselines/duplication-scanner.js +11 -60
- package/.agents/scripts/lib/baselines/env-overrides.js +12 -67
- package/.agents/scripts/lib/baselines/envelope.js +13 -129
- package/.agents/scripts/lib/baselines/exit-codes.js +6 -49
- package/.agents/scripts/lib/baselines/git-base.js +23 -142
- package/.agents/scripts/lib/baselines/kernel.js +11 -111
- package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +9 -47
- package/.agents/scripts/lib/baselines/kinds/_crap-read.js +8 -51
- package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +7 -62
- package/.agents/scripts/lib/baselines/kinds/bundle-size.js +8 -29
- package/.agents/scripts/lib/baselines/kinds/coverage.js +3 -15
- package/.agents/scripts/lib/baselines/kinds/crap.js +94 -415
- package/.agents/scripts/lib/baselines/kinds/duplication.js +4 -30
- package/.agents/scripts/lib/baselines/kinds/kind-factory.js +7 -53
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +15 -80
- package/.agents/scripts/lib/baselines/kinds/mutation.js +12 -72
- package/.agents/scripts/lib/baselines/maintainability-baseline-io.js +4 -11
- package/.agents/scripts/lib/baselines/merge-envelopes.js +30 -146
- package/.agents/scripts/lib/baselines/path-canon.js +19 -128
- package/.agents/scripts/lib/baselines/preview-gates.js +8 -37
- package/.agents/scripts/lib/baselines/reader.js +14 -107
- package/.agents/scripts/lib/baselines/refresh-service.js +35 -252
- package/.agents/scripts/lib/baselines/scope.js +11 -135
- package/.agents/scripts/lib/baselines/writer.js +16 -149
- package/.agents/scripts/lib/bdd-runner-detect.js +18 -113
- package/.agents/scripts/lib/bdd-scenario-budget.js +9 -36
- package/.agents/scripts/lib/bdd-scenario-scanner.js +11 -73
- package/.agents/scripts/lib/bdd-step-index.js +26 -100
- package/.agents/scripts/lib/bootstrap/baseline-merge-driver.js +23 -103
- package/.agents/scripts/lib/bootstrap/branch-protection.js +2 -5
- package/.agents/scripts/lib/bootstrap/commit-push.js +12 -50
- package/.agents/scripts/lib/bootstrap/gh-preflight.js +14 -101
- package/.agents/scripts/lib/bootstrap/hitl-confirm.js +5 -30
- package/.agents/scripts/lib/bootstrap/install-ledger.js +17 -73
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +17 -121
- package/.agents/scripts/lib/bootstrap/manifest.js +15 -86
- package/.agents/scripts/lib/bootstrap/merge-methods.js +4 -33
- package/.agents/scripts/lib/bootstrap/preflight.js +12 -61
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +34 -235
- package/.agents/scripts/lib/bootstrap/prompt.js +21 -129
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +27 -141
- package/.agents/scripts/lib/bootstrap/summary.js +1 -8
- package/.agents/scripts/lib/bootstrap/workflow-audit.js +11 -84
- package/.agents/scripts/lib/branch-name-guard.js +4 -23
- package/.agents/scripts/lib/changed-files.js +39 -121
- package/.agents/scripts/lib/checks/core-bare-clean.js +4 -24
- package/.agents/scripts/lib/checks/index.js +18 -101
- package/.agents/scripts/lib/checks/loop-health.js +11 -53
- package/.agents/scripts/lib/checks/state.js +16 -91
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +10 -61
- package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +14 -83
- package/.agents/scripts/lib/child-exec.js +39 -108
- package/.agents/scripts/lib/cli/standard-args.js +9 -116
- package/.agents/scripts/lib/cli-args.js +31 -146
- package/.agents/scripts/lib/cli-usage.js +5 -27
- package/.agents/scripts/lib/cli-utils.js +2 -12
- package/.agents/scripts/lib/close-validation/commands.js +13 -76
- package/.agents/scripts/lib/close-validation/gates.js +92 -331
- package/.agents/scripts/lib/close-validation/process.js +121 -151
- package/.agents/scripts/lib/close-validation/projections/advisories.js +5 -31
- package/.agents/scripts/lib/close-validation/projections/crap.js +19 -67
- package/.agents/scripts/lib/close-validation/projections/head-sha.js +1 -17
- package/.agents/scripts/lib/close-validation/projections/inputs.js +4 -34
- package/.agents/scripts/lib/close-validation/projections/maintainability.js +11 -58
- package/.agents/scripts/lib/close-validation/runner.js +53 -110
- package/.agents/scripts/lib/command-header.js +6 -28
- package/.agents/scripts/lib/config/acceptance-eval.js +4 -30
- package/.agents/scripts/lib/config/baselines.js +3 -14
- package/.agents/scripts/lib/config/ci.js +8 -38
- package/.agents/scripts/lib/config/commands.js +1 -15
- package/.agents/scripts/lib/config/defaults.js +4 -33
- package/.agents/scripts/lib/config/delivery-routing.js +6 -34
- package/.agents/scripts/lib/config/explain.js +10 -83
- package/.agents/scripts/lib/config/gates/coverage.schema.js +0 -12
- package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +3 -31
- package/.agents/scripts/lib/config/gates/crap.schema.js +1 -34
- package/.agents/scripts/lib/config/gates/duplication.schema.js +1 -8
- package/.agents/scripts/lib/config/gates/index.js +2 -17
- package/.agents/scripts/lib/config/gates/maintainability.schema.js +1 -20
- package/.agents/scripts/lib/config/gates/mutation.schema.js +1 -7
- package/.agents/scripts/lib/config/gates/shared.js +4 -64
- package/.agents/scripts/lib/config/github.js +4 -22
- package/.agents/scripts/lib/config/limits.js +4 -57
- package/.agents/scripts/lib/config/paths.js +2 -21
- package/.agents/scripts/lib/config/qa.js +4 -38
- package/.agents/scripts/lib/config/quality.js +76 -432
- package/.agents/scripts/lib/config/runners.js +12 -56
- package/.agents/scripts/lib/config/runtime.js +13 -57
- package/.agents/scripts/lib/config/shared.js +2 -16
- package/.agents/scripts/lib/config/sync-agentrc.js +9 -50
- package/.agents/scripts/lib/config/temp-paths.js +40 -280
- package/.agents/scripts/lib/config/validate-orchestration.js +5 -17
- package/.agents/scripts/lib/config/worktree-isolation.js +9 -28
- package/.agents/scripts/lib/config-resolver.js +11 -52
- package/.agents/scripts/lib/config-schema-shared.js +1 -4
- package/.agents/scripts/lib/config-settings-schema-delivery.js +16 -291
- package/.agents/scripts/lib/config-settings-schema-quality.js +7 -219
- package/.agents/scripts/lib/config-settings-schema.js +37 -274
- package/.agents/scripts/lib/coverage-baseline.js +20 -110
- package/.agents/scripts/lib/coverage-capture-fullscope.js +18 -35
- package/.agents/scripts/lib/coverage-capture-incremental.js +15 -45
- package/.agents/scripts/lib/coverage-capture-usage.js +8 -25
- package/.agents/scripts/lib/coverage-capture.js +99 -224
- package/.agents/scripts/lib/coverage-utils.js +14 -79
- package/.agents/scripts/lib/cpu-pool.js +17 -123
- package/.agents/scripts/lib/crap-baseline-join.js +16 -88
- package/.agents/scripts/lib/crap-coordinates.js +6 -25
- package/.agents/scripts/lib/crap-engine.js +40 -153
- package/.agents/scripts/lib/crap-method-identity.js +16 -78
- package/.agents/scripts/lib/crap-utils.js +31 -155
- package/.agents/scripts/lib/cyclomatic-ceiling.js +14 -87
- package/.agents/scripts/lib/cyclomatic-scope.js +10 -50
- package/.agents/scripts/lib/dead-exports-knip.js +18 -56
- package/.agents/scripts/lib/dead-exports-mode.js +5 -24
- package/.agents/scripts/lib/degraded-mode.js +3 -26
- package/.agents/scripts/lib/dependency-parser.js +8 -40
- package/.agents/scripts/lib/dependency-version.js +13 -35
- package/.agents/scripts/lib/detect-package-manager.js +6 -36
- package/.agents/scripts/lib/doc-tiers.js +22 -124
- package/.agents/scripts/lib/duplicate-search.js +8 -72
- package/.agents/scripts/lib/env-loader.js +5 -27
- package/.agents/scripts/lib/error-redactor.js +6 -31
- package/.agents/scripts/lib/errors/index.js +2 -22
- package/.agents/scripts/lib/escomplex-ast-compat.js +22 -163
- package/.agents/scripts/lib/escomplex-kernel.js +21 -123
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +94 -419
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +20 -98
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +27 -149
- package/.agents/scripts/lib/findings/audit-ledger.js +23 -97
- package/.agents/scripts/lib/findings/classify-finding.js +14 -69
- package/.agents/scripts/lib/findings/promote-finding.js +14 -112
- package/.agents/scripts/lib/findings/provenance-field.js +11 -52
- package/.agents/scripts/lib/findings/route-finding.js +37 -255
- package/.agents/scripts/lib/findings/semantic-issue-search.js +14 -59
- package/.agents/scripts/lib/findings/severity.js +18 -104
- package/.agents/scripts/lib/format-generated-json.js +12 -44
- package/.agents/scripts/lib/full-suite-lock.js +160 -429
- package/.agents/scripts/lib/full-suite-queue.js +213 -0
- package/.agents/scripts/lib/gates/baseline-store.js +5 -9
- package/.agents/scripts/lib/gates/friction.js +1 -3
- package/.agents/scripts/lib/generated/agentrc-validator.js +2 -2
- package/.agents/scripts/lib/gh-exec.js +123 -191
- package/.agents/scripts/lib/git/cached-fetch.js +9 -52
- package/.agents/scripts/lib/git/sync-from-base.js +15 -107
- package/.agents/scripts/lib/git-branch-cleanup.js +14 -61
- package/.agents/scripts/lib/git-branch-lifecycle.js +16 -87
- package/.agents/scripts/lib/git-utils.js +37 -161
- package/.agents/scripts/lib/github/framework-repo.js +8 -71
- package/.agents/scripts/lib/github-url.js +2 -17
- package/.agents/scripts/lib/import-graph.js +11 -38
- package/.agents/scripts/lib/install-cmd-parser.js +4 -13
- package/.agents/scripts/lib/json-utils.js +3 -18
- package/.agents/scripts/lib/label-constants.js +16 -111
- package/.agents/scripts/lib/label-taxonomy.js +4 -30
- package/.agents/scripts/lib/maintainability-engine.js +12 -80
- package/.agents/scripts/lib/maintainability-unscorable.js +5 -25
- package/.agents/scripts/lib/maintainability-utils.js +16 -92
- package/.agents/scripts/lib/mandrel-catalog.js +12 -70
- package/.agents/scripts/lib/notifications/notifier.js +13 -38
- package/.agents/scripts/lib/npm-scripts.js +4 -23
- package/.agents/scripts/lib/observability/metrics-ledger.js +16 -76
- package/.agents/scripts/lib/observability/runtime-friction.js +44 -286
- package/.agents/scripts/lib/observability/signal-validator.js +5 -37
- package/.agents/scripts/lib/observability/signals-writer.js +11 -121
- package/.agents/scripts/lib/observability/source-classifier.js +22 -203
- package/.agents/scripts/lib/observability/terse-result.js +14 -47
- package/.agents/scripts/lib/onboard/init-tail.js +13 -74
- package/.agents/scripts/lib/onboard/scaffold-docs.js +11 -34
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +25 -139
- package/.agents/scripts/lib/orchestration/auto-merge-cwd.js +11 -66
- package/.agents/scripts/lib/orchestration/behind-recovery.js +10 -55
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +28 -156
- package/.agents/scripts/lib/orchestration/change-set.js +7 -36
- package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +9 -46
- package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +11 -44
- package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +5 -24
- package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +3 -12
- package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +5 -38
- package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +3 -8
- package/.agents/scripts/lib/orchestration/check-baselines/phases/refresh-ack.js +28 -136
- package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +3 -13
- package/.agents/scripts/lib/orchestration/check-state.js +92 -0
- package/.agents/scripts/lib/orchestration/ci-gap-intake.js +37 -144
- package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +121 -157
- package/.agents/scripts/lib/orchestration/code-review.js +24 -128
- package/.agents/scripts/lib/orchestration/column-sync.js +23 -111
- package/.agents/scripts/lib/orchestration/complexity-gate.js +118 -462
- package/.agents/scripts/lib/orchestration/deliver-recover.js +36 -168
- package/.agents/scripts/lib/orchestration/dependency-analyzer.js +4 -35
- package/.agents/scripts/lib/orchestration/dependency-candidates.js +9 -41
- package/.agents/scripts/lib/orchestration/diff-magnitude.js +25 -115
- package/.agents/scripts/lib/orchestration/doc-reader.js +2 -6
- package/.agents/scripts/lib/orchestration/docs-digest.js +13 -51
- package/.agents/scripts/lib/orchestration/epic-candidates.js +13 -53
- package/.agents/scripts/lib/orchestration/epic-checklist.js +9 -33
- package/.agents/scripts/lib/orchestration/epic-container.js +41 -167
- package/.agents/scripts/lib/orchestration/epic-expansion.js +10 -40
- package/.agents/scripts/lib/orchestration/epic-rollup.js +55 -207
- package/.agents/scripts/lib/orchestration/file-assumption-enum.js +2 -22
- package/.agents/scripts/lib/orchestration/file-assumptions.js +45 -253
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-detect.js +9 -46
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +7 -57
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +21 -126
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +2 -6
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +1 -4
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +1 -5
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +9 -34
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +41 -190
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/merged-tip.js +9 -45
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +1 -4
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +19 -85
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +3 -17
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +1 -5
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +16 -100
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +1 -4
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +16 -67
- package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +9 -33
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +8 -29
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +15 -68
- package/.agents/scripts/lib/orchestration/light-backstop.js +11 -49
- package/.agents/scripts/lib/orchestration/light-escalation.js +21 -89
- package/.agents/scripts/lib/orchestration/light-suitability.js +37 -307
- package/.agents/scripts/lib/orchestration/merge-block-class.js +39 -216
- package/.agents/scripts/lib/orchestration/merge-poll.js +104 -377
- package/.agents/scripts/lib/orchestration/pinned-identifier-lint.js +17 -57
- package/.agents/scripts/lib/orchestration/plan-context.js +55 -318
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +22 -79
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +5 -31
- package/.agents/scripts/lib/orchestration/plan-metrics.js +29 -108
- package/.agents/scripts/lib/orchestration/plan-navigation.js +8 -27
- package/.agents/scripts/lib/orchestration/plan-persist/acceptance-handle-repair.js +12 -49
- package/.agents/scripts/lib/orchestration/plan-persist/audit-provenance.js +18 -73
- package/.agents/scripts/lib/orchestration/plan-persist/changes-repair.js +16 -78
- package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +6 -30
- package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +14 -65
- package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +21 -76
- package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +6 -43
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +14 -68
- package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +9 -41
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +71 -289
- package/.agents/scripts/lib/orchestration/plan-persist/soft-findings.js +2 -12
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +96 -362
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +9 -39
- package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +60 -186
- package/.agents/scripts/lib/orchestration/plan-persist/wave-collision-gate.js +9 -49
- package/.agents/scripts/lib/orchestration/plan-persist/wave-serialisation.js +7 -28
- package/.agents/scripts/lib/orchestration/plan-reachability.js +13 -42
- package/.agents/scripts/lib/orchestration/plan-run-labels/reap.js +16 -91
- package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +16 -54
- package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +10 -52
- package/.agents/scripts/lib/orchestration/planning/authoring-context.js +14 -109
- package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +11 -83
- package/.agents/scripts/lib/orchestration/pr-watch.js +48 -306
- package/.agents/scripts/lib/orchestration/project-meta-cache.js +15 -80
- package/.agents/scripts/lib/orchestration/project-meta-resolver.js +10 -51
- package/.agents/scripts/lib/orchestration/reassert-status-column.js +12 -76
- package/.agents/scripts/lib/orchestration/remote-verifier.js +12 -36
- package/.agents/scripts/lib/orchestration/resolve-stories.js +33 -164
- package/.agents/scripts/lib/orchestration/retro-proposals.js +66 -361
- package/.agents/scripts/lib/orchestration/review-base-ref.js +9 -43
- package/.agents/scripts/lib/orchestration/review-depth.js +12 -91
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +10 -111
- package/.agents/scripts/lib/orchestration/review-providers/degraded-gates.js +13 -71
- package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +7 -51
- package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +8 -53
- package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -214
- package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +7 -52
- package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +4 -33
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +11 -71
- package/.agents/scripts/lib/orchestration/review-providers/scoped-lint.js +19 -131
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +6 -89
- package/.agents/scripts/lib/orchestration/review-providers/types.js +26 -56
- package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +3 -46
- package/.agents/scripts/lib/orchestration/run-epilogue.js +245 -326
- package/.agents/scripts/lib/orchestration/run-scoped-config.js +55 -159
- package/.agents/scripts/lib/orchestration/single-story-close/close-note.js +7 -34
- package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +16 -89
- package/.agents/scripts/lib/orchestration/single-story-close/gate-log.js +18 -109
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +83 -239
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +20 -82
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +103 -97
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -64
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +136 -486
- package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +30 -134
- package/.agents/scripts/lib/orchestration/single-story-close/phases/graphql-preflight.js +96 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/lock-wait-pending.js +49 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +13 -86
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +20 -95
- package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +46 -203
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pre-gate-steps.js +8 -50
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +12 -83
- package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +6 -39
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -6
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-outcome.js +4 -28
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +6 -51
- package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +6 -34
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +23 -121
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +180 -273
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +15 -69
- package/.agents/scripts/lib/orchestration/story-body-gate.js +4 -23
- package/.agents/scripts/lib/orchestration/story-close/baseline-upward-writeback.js +50 -179
- package/.agents/scripts/lib/orchestration/story-close/context-budget-writeback.js +11 -41
- package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +23 -311
- package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +22 -147
- package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +16 -67
- package/.agents/scripts/lib/orchestration/story-deliver-terminal-schema.js +12 -68
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +42 -200
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +167 -252
- package/.agents/scripts/lib/orchestration/story-init-envelope.js +52 -0
- package/.agents/scripts/lib/orchestration/story-init-remote.js +2 -6
- package/.agents/scripts/lib/orchestration/story-reachability.js +3 -23
- package/.agents/scripts/lib/orchestration/task-body-validator.js +12 -135
- package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -131
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +15 -149
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +5 -33
- package/.agents/scripts/lib/orchestration/ticket-validator.js +63 -344
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +51 -244
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +39 -261
- package/.agents/scripts/lib/orchestration/ticketing/state.js +14 -68
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +46 -263
- package/.agents/scripts/lib/orchestration/ticketing.js +2 -26
- package/.agents/scripts/lib/orchestration/verify-credit.js +18 -79
- package/.agents/scripts/lib/orchestration/worktree-dirty.js +5 -30
- package/.agents/scripts/lib/path-security.js +3 -6
- package/.agents/scripts/lib/plan-phase-cleanup.js +9 -49
- package/.agents/scripts/lib/preflight-runner.js +13 -69
- package/.agents/scripts/lib/process-group.js +143 -0
- package/.agents/scripts/lib/project-root.js +2 -8
- package/.agents/scripts/lib/provider-factory.js +2 -25
- package/.agents/scripts/lib/qa/console-allowlist.js +10 -59
- package/.agents/scripts/lib/qa/qa-session.js +15 -69
- package/.agents/scripts/lib/qa/redact-evidence.js +18 -129
- package/.agents/scripts/lib/qa/resolve-qa-contract.js +26 -135
- package/.agents/scripts/lib/qa/resolve-selection.js +16 -84
- package/.agents/scripts/lib/reserved-test-ids.js +9 -47
- package/.agents/scripts/lib/runtime-deps/dep-resolution.js +13 -53
- package/.agents/scripts/lib/runtime-deps/ensure-installed.js +10 -44
- package/.agents/scripts/lib/runtime-deps/manifest.js +10 -30
- package/.agents/scripts/lib/runtime-deps/parser-major.js +15 -51
- package/.agents/scripts/lib/runtime-deps/preflight.js +4 -22
- package/.agents/scripts/lib/runtime-deps/scan-imports.js +11 -55
- package/.agents/scripts/lib/signals/detectors/common.js +12 -38
- package/.agents/scripts/lib/signals/index.js +2 -19
- package/.agents/scripts/lib/signals/schema.js +14 -109
- package/.agents/scripts/lib/signals/write.js +2 -11
- package/.agents/scripts/lib/single-story/confirm-merge.js +31 -72
- package/.agents/scripts/lib/single-story/story-merged-notify.js +8 -49
- package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +4 -26
- package/.agents/scripts/lib/single-story-sweep/protection.js +13 -100
- package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +60 -258
- package/.agents/scripts/lib/single-story-sweep.js +14 -97
- package/.agents/scripts/lib/skills/parse-skill.js +13 -59
- package/.agents/scripts/lib/skills/skills-index.js +8 -29
- package/.agents/scripts/lib/skills/walk-skill-files.js +17 -78
- package/.agents/scripts/lib/source-extensions.js +11 -42
- package/.agents/scripts/lib/source-text/strip-js-comments.js +8 -41
- package/.agents/scripts/lib/stdio-flush.js +9 -36
- package/.agents/scripts/lib/story-adjacency.js +8 -40
- package/.agents/scripts/lib/story-body/body-format-lints.js +51 -66
- package/.agents/scripts/lib/story-body/footer-block.js +11 -44
- package/.agents/scripts/lib/story-body/story-body.js +123 -344
- package/.agents/scripts/lib/temp-retention.js +42 -143
- package/.agents/scripts/lib/templates/decomposer-prompts.js +18 -80
- package/.agents/scripts/lib/test-env.js +12 -65
- package/.agents/scripts/lib/test-run-credit.js +10 -65
- package/.agents/scripts/lib/test-runner-contract.js +19 -74
- package/.agents/scripts/lib/test-temp.js +38 -184
- package/.agents/scripts/lib/test-tiers.js +12 -96
- package/.agents/scripts/lib/ticket-body-sections.js +21 -96
- package/.agents/scripts/lib/transpile.js +15 -74
- package/.agents/scripts/lib/util/concurrent-map.js +6 -25
- package/.agents/scripts/lib/util/parse-id-list.js +8 -34
- package/.agents/scripts/lib/util/poll-loop.js +8 -28
- package/.agents/scripts/lib/util/with-timeout.js +2 -11
- package/.agents/scripts/lib/validation-evidence.js +21 -96
- package/.agents/scripts/lib/wave-runner/footprint.js +17 -70
- package/.agents/scripts/lib/wave-runner/live-probe.js +67 -209
- package/.agents/scripts/lib/wave-runner/ready-set.js +72 -301
- package/.agents/scripts/lib/workers/crap-worker.js +11 -64
- package/.agents/scripts/lib/workers/maintainability-report-worker.js +8 -45
- package/.agents/scripts/lib/workers/maintainability-worker.js +5 -21
- package/.agents/scripts/lib/workers/serve-worker-messages.js +2 -18
- package/.agents/scripts/lib/workflow-closure.js +22 -105
- package/.agents/scripts/lib/workspace-provisioner.js +16 -54
- package/.agents/scripts/lib/worktree/git-hooks.js +15 -60
- package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +20 -60
- package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +10 -62
- package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +22 -86
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +24 -126
- package/.agents/scripts/lib/worktree/lifecycle-manager.js +2 -20
- package/.agents/scripts/lib/worktree/node-modules-strategy.js +46 -180
- package/.agents/scripts/lib/worktree-manager.js +15 -40
- package/.agents/scripts/lint-issue-body.js +12 -68
- package/.agents/scripts/mandrel-update-preflight.js +10 -70
- package/.agents/scripts/merge-baseline.js +30 -105
- package/.agents/scripts/nav-registry-diff.js +22 -108
- package/.agents/scripts/notify.js +12 -69
- package/.agents/scripts/plan-context.js +97 -92
- package/.agents/scripts/plan-critics.js +12 -66
- package/.agents/scripts/plan-persist.js +71 -137
- package/.agents/scripts/plan-run-epilogue.js +20 -43
- package/.agents/scripts/pr-watch-with-update.js +79 -263
- package/.agents/scripts/providers/github/auth.js +3 -8
- package/.agents/scripts/providers/github/blocked-by-add.js +14 -61
- package/.agents/scripts/providers/github/board-add.js +5 -21
- package/.agents/scripts/providers/github/branch-protection.js +11 -43
- package/.agents/scripts/providers/github/cache.js +2 -14
- package/.agents/scripts/providers/github/comments.js +7 -40
- package/.agents/scripts/providers/github/compose.js +3 -19
- package/.agents/scripts/providers/github/errors.js +22 -125
- package/.agents/scripts/providers/github/issues.js +31 -123
- package/.agents/scripts/providers/github/labels.js +24 -124
- package/.agents/scripts/providers/github/mappers.js +5 -27
- package/.agents/scripts/providers/github/merge-methods.js +3 -22
- package/.agents/scripts/providers/github/project-board.js +2 -17
- package/.agents/scripts/providers/github/projects-v2-graphql.js +3 -6
- package/.agents/scripts/providers/github/request-helpers.js +5 -32
- package/.agents/scripts/providers/github/search-budget.js +9 -39
- package/.agents/scripts/providers/github/search-query.js +5 -26
- package/.agents/scripts/providers/github/sub-issue-add.js +15 -65
- package/.agents/scripts/providers/github/sub-issues.js +7 -36
- package/.agents/scripts/providers/github/tickets.js +32 -134
- package/.agents/scripts/providers/github.js +18 -59
- package/.agents/scripts/prune-plan-run-labels.js +12 -46
- package/.agents/scripts/quality-preview.js +35 -220
- package/.agents/scripts/resolve-doc-tiers.js +3 -26
- package/.agents/scripts/resolve-stories.js +16 -67
- package/.agents/scripts/resync-status-column.js +6 -25
- package/.agents/scripts/run-tests.js +29 -104
- package/.agents/scripts/single-story-close.js +23 -135
- package/.agents/scripts/single-story-confirm-merge.js +32 -139
- package/.agents/scripts/single-story-init.js +47 -259
- package/.agents/scripts/stories-wave-tick.js +179 -415
- package/.agents/scripts/sync-agentrc.js +3 -21
- package/.agents/scripts/sync-claude-agents.js +9 -55
- package/.agents/scripts/sync-claude-commands.js +20 -110
- package/.agents/scripts/test-wrapper.js +6 -43
- package/.agents/scripts/update-coverage-baseline.js +5 -22
- package/.agents/scripts/update-crap-baseline.js +7 -30
- package/.agents/scripts/update-duplication-baseline.js +16 -92
- package/.agents/scripts/update-maintainability-baseline.js +8 -62
- package/.agents/scripts/update-ticket-state.js +1 -7
- package/.agents/scripts/validate-skills.js +6 -26
- package/.agents/skills/core/gates-and-baselines/reference.md +0 -1
- package/.agents/skills/skills.index.json +2 -2
- package/.agents/skills/stack/qa/playwright/SKILL.md +26 -0
- package/.agents/templates/agent-protocol.md +2 -2
- package/.agents/templates/docs/audit-sweep-runbook.md +3 -4
- package/.agents/workflows/audit-accessibility.md +4 -7
- package/.agents/workflows/audit-adrs.md +3 -6
- package/.agents/workflows/audit-architecture.md +3 -11
- package/.agents/workflows/audit-baselines.md +6 -9
- package/.agents/workflows/audit-clean-code.md +8 -12
- package/.agents/workflows/audit-data-model.md +3 -7
- package/.agents/workflows/audit-dependencies.md +4 -7
- package/.agents/workflows/audit-devops.md +4 -8
- package/.agents/workflows/audit-documentation.md +1 -4
- package/.agents/workflows/audit-mobile.md +4 -7
- package/.agents/workflows/audit-navigability.md +3 -6
- package/.agents/workflows/audit-performance.md +2 -4
- package/.agents/workflows/audit-privacy.md +4 -7
- package/.agents/workflows/audit-quality.md +4 -7
- package/.agents/workflows/audit-security.md +4 -7
- package/.agents/workflows/audit-seo.md +4 -7
- package/.agents/workflows/audit-sre.md +4 -7
- package/.agents/workflows/audit-to-stories.md +17 -30
- package/.agents/workflows/audit-ux-ui.md +4 -7
- package/.agents/workflows/helpers/acceptance-self-eval.md +84 -157
- package/.agents/workflows/helpers/audit-lens-core.md +1 -1
- package/.agents/workflows/helpers/code-quality-guardrails.md +12 -15
- package/.agents/workflows/helpers/code-review.md +4 -2
- package/.agents/workflows/helpers/deliver-digest.md +37 -28
- package/.agents/workflows/helpers/deliver-light.md +92 -101
- package/.agents/workflows/helpers/deliver-reference.md +162 -220
- package/.agents/workflows/helpers/deliver-story-reference.md +197 -607
- package/.agents/workflows/helpers/deliver-story.md +17 -18
- package/.agents/workflows/helpers/plan-reference.md +125 -167
- package/.agents/workflows/helpers/qa-core.md +12 -0
- package/.agents/workflows/mandrel-deliver.md +47 -31
- package/.agents/workflows/mandrel-plan.md +22 -21
- package/.agents/workflows/mandrel-update.md +36 -21
- package/.agents/workflows/memory-consolidate.md +1 -1
- package/.agents/workflows/qa-assist.md +27 -71
- package/.agents/workflows/qa-explore.md +19 -59
- package/.agents/workflows/qa-run.md +11 -33
- package/README.md +1 -1
- package/bin/mandrel.js +5 -46
- package/bin/postinstall.js +18 -107
- package/docs/CHANGELOG.md +60 -0
- package/lib/cli/doctor.js +11 -71
- package/lib/cli/init.js +26 -165
- package/lib/cli/migrate.js +5 -64
- package/lib/cli/registry.js +84 -467
- package/lib/cli/sync-agents.js +4 -64
- package/lib/cli/sync-commands.js +11 -64
- package/lib/cli/sync.js +34 -213
- package/lib/cli/uninstall.js +40 -219
- package/lib/cli/update.js +326 -523
- package/lib/cli/version-check.js +8 -72
- package/lib/cli/version-helpers.js +14 -87
- package/lib/migrations/helpers/retire-agentrc-key.js +11 -52
- package/lib/migrations/index.js +17 -92
- package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +2 -15
- package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +1 -13
- package/lib/migrations/steps/2.11.0-retire-max-seed-words.js +2 -15
- package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +9 -38
- package/lib/migrations/steps/2.20.0-retire-codebase-snapshot.js +1 -13
- package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +2 -27
- package/lib/migrations/steps/2.57.0-retire-delivery-limit-knobs.js +2 -23
- package/lib/migrations/steps/2.57.0-retire-planning-limit-knobs.js +2 -27
- package/lib/migrations/steps/2.60.0-retire-audit-results-autofile.js +21 -0
- package/lib/migrations/steps/strip-removed-agentrc-keys.js +333 -0
- package/package.json +17 -14
- package/.agents/docs/SDLC.md +0 -590
- package/.agents/docs/quality-gates.md +0 -1179
- package/.agents/rules/known-tooling-behavior.md +0 -150
- package/.agents/rules/orchestration-error-handling.md +0 -61
- package/.agents/rules/test-seams.md +0 -59
- package/.agents/schemas/baselines/lighthouse.schema.json +0 -59
- package/.agents/schemas/baselines/lint.schema.json +0 -47
- package/.agents/schemas/model-attribution.schema.json +0 -53
- package/.agents/scripts/check-action-pinning.js +0 -260
- package/.agents/scripts/check-audit-attribution.js +0 -302
- package/.agents/scripts/check-baseline-drift.js +0 -211
- package/.agents/scripts/check-baseline-scope.js +0 -362
- package/.agents/scripts/check-generated-validator.js +0 -202
- package/.agents/scripts/check-knip-entries.js +0 -159
- package/.agents/scripts/check-lifecycle-lint.js +0 -294
- package/.agents/scripts/check-pinned-override-notes.js +0 -102
- package/.agents/scripts/check-schema-references.js +0 -366
- package/.agents/scripts/check-test-portability.js +0 -512
- package/.agents/scripts/check-workflow-citations.js +0 -332
- package/.agents/scripts/check-workflow-cli-lint.js +0 -299
- package/.agents/scripts/check-workflow-timeouts.js +0 -291
- package/.agents/scripts/install-matrix-assert.js +0 -326
- package/.agents/scripts/lib/audit-advisories.js +0 -195
- package/.agents/scripts/lib/audit-attribution.js +0 -134
- package/.agents/scripts/lib/baselines/drift-detector.js +0 -351
- package/.agents/scripts/lib/baselines/kinds/lighthouse.js +0 -87
- package/.agents/scripts/lib/baselines/kinds/lint.js +0 -184
- package/.agents/scripts/lib/baselines/orphan-pruner.js +0 -233
- package/.agents/scripts/lib/baselines/scope-assert.js +0 -223
- package/.agents/scripts/lib/baselines/scope-inventory.js +0 -314
- package/.agents/scripts/lib/c8-cli-path.js +0 -21
- package/.agents/scripts/lib/config/gates/lighthouse.schema.js +0 -51
- package/.agents/scripts/lib/config/gates/lint.schema.js +0 -18
- package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +0 -70
- package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +0 -284
- package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +0 -80
- package/.agents/scripts/lib/dynamic-workflow/degraded-coverage.js +0 -81
- package/.agents/scripts/lib/dynamic-workflow/documentation-report-contract.js +0 -87
- package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +0 -74
- package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +0 -90
- package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +0 -43
- package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +0 -83
- package/.agents/scripts/lib/fs-walk.js +0 -52
- package/.agents/scripts/lib/knip-config-resolver.js +0 -181
- package/.agents/scripts/lib/knip-entry-sync.js +0 -452
- package/.agents/scripts/lib/orchestration/model-attribution.js +0 -418
- package/.agents/scripts/lib/orchestration/story-plan-state.js +0 -33
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +0 -67
- package/.agents/scripts/lib/pinned-override-notes.js +0 -88
- package/.agents/scripts/lib/pinned-override-resolve.js +0 -212
- package/.agents/scripts/lib/test-isolate/cli-options.js +0 -93
- package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +0 -52
- package/.agents/scripts/lib/test-isolate/list-files.js +0 -90
- package/.agents/scripts/lib/test-isolate/parse-tap.js +0 -75
- package/.agents/scripts/lib/test-isolate/progress-log.js +0 -45
- package/.agents/scripts/lib/test-isolate/render-report.js +0 -97
- package/.agents/scripts/lib/test-isolate/run-isolate.js +0 -87
- package/.agents/scripts/lib/test-isolate/runner.js +0 -483
- package/.agents/scripts/lib/test-profile/parse-tap.js +0 -136
- package/.agents/scripts/lib/test-profile/render-report.js +0 -45
- package/.agents/scripts/lint-label-vocabulary.js +0 -214
- package/.agents/scripts/post-structured-comment.js +0 -127
- package/.agents/scripts/provision-git-hooks.js +0 -85
- package/.agents/scripts/prune-baseline-orphans.js +0 -181
- package/.agents/scripts/run-coverage.js +0 -197
- package/.agents/scripts/run-lint.js +0 -133
- package/.agents/scripts/run-test-profile.js +0 -129
- package/.agents/scripts/run-verify.js +0 -118
- package/.agents/scripts/test-isolate.js +0 -55
- package/.agents/scripts/update-dead-exports-baseline.js +0 -321
|
@@ -30,6 +30,8 @@ import { runBaseSyncPhase } from './phases/base-sync.js';
|
|
|
30
30
|
import { runCloseValidationPhase } from './phases/close-validation.js';
|
|
31
31
|
import { parsePrNumber, runStoryScopeReview } from './phases/code-review.js';
|
|
32
32
|
import { runConfirmMergePhase } from './phases/confirm-merge.js';
|
|
33
|
+
import { runGraphqlPreflight } from './phases/graphql-preflight.js';
|
|
34
|
+
import { lockWaitPending } from './phases/lock-wait-pending.js';
|
|
33
35
|
import { parseCloseOptions, resolveWaitForMerge } from './phases/options.js';
|
|
34
36
|
import { ensurePullRequestWith } from './phases/pull-request.js';
|
|
35
37
|
import { pushStoryBranch } from './phases/push.js';
|
|
@@ -41,29 +43,11 @@ import { runWrongTreeGuardPhase } from './phases/wrong-tree-guard.js';
|
|
|
41
43
|
const progress = Logger.createProgress('single-story-close', { stderr: true });
|
|
42
44
|
|
|
43
45
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* #4543), while `STORY CLOSE RESULT` stays byte-compatible for the existing
|
|
48
|
-
* surfaces that grep it. One writer, one place — so the envelope can never
|
|
49
|
-
* be emitted from a path that forgot it.
|
|
50
|
-
*
|
|
51
|
-
* Story #4578 — the same one-place property is why the runtime-derived
|
|
52
|
-
* friction emit hangs here: a close that ends `failed`, or parks `pending`
|
|
53
|
-
* on an exhausted merge-wait budget, is friction the retro must see, and
|
|
54
|
-
* routing it through the single emitter means no terminal path can forget
|
|
55
|
-
* it. `emitTerminalFriction` decides what (if anything) is worth a record —
|
|
56
|
-
* see `frictionForTerminal` for why `blocked` and a `--no-wait-merge`
|
|
57
|
-
* `pending` are deliberately NOT flagged here.
|
|
58
|
-
*
|
|
59
|
-
* Async, and awaited by every caller: the CLI exits via `process.exit` the
|
|
60
|
-
* moment `main` resolves, so a fire-and-forget append would be discarded.
|
|
61
|
-
* The emit is best-effort internally and cannot throw.
|
|
46
|
+
* The single terminal writer: the result summary, the envelope callers parse,
|
|
47
|
+
* and terminal friction — so no ending can forget one. Must be awaited: the
|
|
48
|
+
* CLI `process.exit`s as soon as `main` resolves.
|
|
62
49
|
*/
|
|
63
50
|
async function emitTerminal({ terminal, result, config }) {
|
|
64
|
-
// Story #4685 — the human-facing result dump goes to a temp log; the agent
|
|
65
|
-
// acts on the (separate, unsuppressible) terminal envelope emitted below.
|
|
66
|
-
// The single summary line keeps the fields worth an at-a-glance read.
|
|
67
51
|
if (result) {
|
|
68
52
|
emitTerseResult({
|
|
69
53
|
label: 'STORY CLOSE RESULT',
|
|
@@ -83,21 +67,16 @@ async function emitTerminal({ terminal, result, config }) {
|
|
|
83
67
|
}
|
|
84
68
|
|
|
85
69
|
/**
|
|
86
|
-
* Terminal for
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* issue as `completed` (the `Closes #<id>` footer firing on merge — the work
|
|
90
|
-
* IS on the base branch) or as `not_planned` (superseded by a re-plan,
|
|
91
|
-
* abandoned — nothing ever merged). Reporting the second as `landed` told
|
|
92
|
-
* `/mandrel-deliver` that work had reached `main` when no PR ever merged, which would
|
|
93
|
-
* also satisfy any dependent Story waiting on it. Fail loudly instead: being
|
|
94
|
-
* handed an abandoned Story is an input error only the operator can resolve.
|
|
95
|
-
*
|
|
96
|
-
* A null `stateReason` keeps the `completed` reading — GitHub defaults to it,
|
|
97
|
-
* and issues closed before the field existed carry null.
|
|
70
|
+
* Terminal for an already-closed Story. `not_planned` means nothing merged,
|
|
71
|
+
* so it fails rather than reporting `landed` (which would also unblock
|
|
72
|
+
* dependents); `completed` or null (GitHub's default) reads as landed.
|
|
98
73
|
*/
|
|
99
74
|
async function alreadyClosedResult(storyId, stateReason = null, config) {
|
|
100
75
|
if (stateReason === 'not_planned') {
|
|
76
|
+
progress(
|
|
77
|
+
'NOOP',
|
|
78
|
+
`Story #${storyId} is closed as not planned — nothing to land.`,
|
|
79
|
+
);
|
|
101
80
|
const result = {
|
|
102
81
|
storyId,
|
|
103
82
|
standalone: true,
|
|
@@ -120,15 +99,13 @@ async function alreadyClosedResult(storyId, stateReason = null, config) {
|
|
|
120
99
|
return { success: false, result, terminal };
|
|
121
100
|
}
|
|
122
101
|
|
|
102
|
+
progress('NOOP', `Story #${storyId} is already closed. Nothing to do.`);
|
|
123
103
|
const result = {
|
|
124
104
|
storyId,
|
|
125
105
|
standalone: true,
|
|
126
106
|
action: 'noop',
|
|
127
107
|
reason: 'already-closed',
|
|
128
108
|
};
|
|
129
|
-
// Idempotent re-run against a Story closed as completed. `landed` is the
|
|
130
|
-
// honest status — the issue closed on merge, so the work is on the base
|
|
131
|
-
// branch — and there is nothing left to command.
|
|
132
109
|
const terminal = buildTerminalEnvelope({
|
|
133
110
|
storyId,
|
|
134
111
|
status: 'landed',
|
|
@@ -141,16 +118,49 @@ async function alreadyClosedResult(storyId, stateReason = null, config) {
|
|
|
141
118
|
}
|
|
142
119
|
|
|
143
120
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
121
|
+
* Reuses the classifier's fallback class: the vocabulary is pinned by the
|
|
122
|
+
* terminal schema, so `reason` names the blocker instead.
|
|
123
|
+
*/
|
|
124
|
+
const PREFLIGHT_BLOCK_CLASS = 'api-race-other';
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Returned, not thrown: a classified block, not a crash (a throw surfaces as
|
|
128
|
+
* `failed`). The next command is the same close.
|
|
146
129
|
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
130
|
+
* @param {{ storyId: number, preflight: { verdict: string, reason: string },
|
|
131
|
+
* config: object, startedAtMs: number }} args
|
|
132
|
+
* @returns {Promise<{ success: false, result: object, terminal: object }>}
|
|
133
|
+
*/
|
|
134
|
+
async function preflightBlockedResult({
|
|
135
|
+
storyId,
|
|
136
|
+
preflight,
|
|
137
|
+
config,
|
|
138
|
+
startedAtMs,
|
|
139
|
+
}) {
|
|
140
|
+
const result = {
|
|
141
|
+
storyId,
|
|
142
|
+
standalone: true,
|
|
143
|
+
action: 'noop',
|
|
144
|
+
reason: `graphql-preflight-${preflight.verdict}`,
|
|
145
|
+
};
|
|
146
|
+
const terminal = buildTerminalEnvelope({
|
|
147
|
+
storyId,
|
|
148
|
+
status: 'blocked',
|
|
149
|
+
phase: 'init',
|
|
150
|
+
blocked: {
|
|
151
|
+
blockClass: PREFLIGHT_BLOCK_CLASS,
|
|
152
|
+
reason: preflight.reason,
|
|
153
|
+
frictionCommentId: null,
|
|
154
|
+
},
|
|
155
|
+
nextCommand: NEXT_COMMANDS.close(storyId),
|
|
156
|
+
elapsedSeconds: elapsedSecondsSince(startedAtMs),
|
|
157
|
+
});
|
|
158
|
+
await emitTerminal({ terminal, result, config });
|
|
159
|
+
return { success: false, result, terminal };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* The split baselines gates, by name; only registered ones, never a phantom key.
|
|
154
164
|
*
|
|
155
165
|
* @param {Record<string, string>|null|undefined} validationGates
|
|
156
166
|
* @returns {Record<string, string>}
|
|
@@ -164,6 +174,22 @@ function baselinesEnvelopeGates(validationGates) {
|
|
|
164
174
|
return out;
|
|
165
175
|
}
|
|
166
176
|
|
|
177
|
+
/**
|
|
178
|
+
* @param {{ skipValidation?: boolean, skipSync?: boolean }} options
|
|
179
|
+
* @param {Record<string, string>|null} validationGates
|
|
180
|
+
* @param {object|null} reviewOverride
|
|
181
|
+
* @returns {Record<string, string>}
|
|
182
|
+
*/
|
|
183
|
+
function closeEnvelopeGates(options, validationGates, reviewOverride) {
|
|
184
|
+
return {
|
|
185
|
+
validation: options.skipValidation ? 'skipped' : 'passed',
|
|
186
|
+
...baselinesEnvelopeGates(validationGates),
|
|
187
|
+
baseSync: options.skipSync ? 'skipped' : 'passed',
|
|
188
|
+
// The review did fail; the envelope records the human override.
|
|
189
|
+
codeReview: reviewOverride ? 'overridden' : 'passed',
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
167
193
|
function resolveWorktreePath({ cwd, config, storyId }) {
|
|
168
194
|
const root = config.delivery?.worktreeIsolation?.root ?? '.worktrees';
|
|
169
195
|
const candidate = path.resolve(cwd, root, `story-${storyId}`);
|
|
@@ -171,25 +197,16 @@ function resolveWorktreePath({ cwd, config, storyId }) {
|
|
|
171
197
|
}
|
|
172
198
|
|
|
173
199
|
/**
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* Story #5172 put base-sync AHEAD of close-validation, for two reasons that
|
|
178
|
-
* are really one. The cheap one: a base-sync conflict is a hard block that
|
|
179
|
-
* costs nothing to detect, so paying for the full gate chain before
|
|
180
|
-
* discovering it burns the pipeline's most expensive minutes on a tree that
|
|
181
|
-
* was never going to be pushed. The load-bearing one: with the gates last,
|
|
182
|
-
* **the validated tree is the pushed tree**. Under the old order the merge
|
|
183
|
-
* commit base-sync writes landed AFTER validation, so every close pushed a
|
|
184
|
-
* tree no gate had ever seen.
|
|
185
|
-
*
|
|
186
|
-
* `--skip-sync` and `--skip-validation` stay independent — either, both or
|
|
187
|
-
* neither may be set, and each still elides exactly its own phase.
|
|
200
|
+
* wrong-tree guard → base-sync → close-validation. Validation runs last so
|
|
201
|
+
* the validated tree is the pushed tree (base-sync's merge commit included),
|
|
202
|
+
* and a cheap conflict is found before the expensive gates.
|
|
188
203
|
*
|
|
189
|
-
* @returns {Promise<{
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
204
|
+
* @returns {Promise<{
|
|
205
|
+
* validationGates: Record<string, string>|null,
|
|
206
|
+
* lockWait: { waitedSeconds: number, expired: boolean }|null,
|
|
207
|
+
* pending: boolean,
|
|
208
|
+
* }>} `validationGates` is null when skipped; `pending` means a full-suite
|
|
209
|
+
* lock wait expired and the gates deferred.
|
|
193
210
|
*/
|
|
194
211
|
async function runPrePushPhases({
|
|
195
212
|
cwd,
|
|
@@ -235,7 +252,7 @@ async function runPrePushPhases({
|
|
|
235
252
|
}
|
|
236
253
|
if (skipValidation) {
|
|
237
254
|
progress('VALIDATE', '⏭ Skipped (--skip-validation).');
|
|
238
|
-
return { validationGates: null };
|
|
255
|
+
return { validationGates: null, lockWait: null, pending: false };
|
|
239
256
|
}
|
|
240
257
|
setPhase('close-validation');
|
|
241
258
|
let validation;
|
|
@@ -252,12 +269,7 @@ async function runPrePushPhases({
|
|
|
252
269
|
buildDefaultGates,
|
|
253
270
|
});
|
|
254
271
|
} catch (err) {
|
|
255
|
-
//
|
|
256
|
-
// reconstructing them, so hand it what this run observed. The phase tags
|
|
257
|
-
// `closeGate` with the entry that died; that one name is the whole of
|
|
258
|
-
// what the run observed about gate outcomes, and therefore the whole of
|
|
259
|
-
// what the envelope may claim. Anything else it might have named is a
|
|
260
|
-
// gate the run never proved ran at all.
|
|
272
|
+
// The gate that died is all this run observed; the envelope claims no more.
|
|
261
273
|
if (typeof err?.closeGate === 'string') {
|
|
262
274
|
setObservedGates({ [err.closeGate]: 'failed' });
|
|
263
275
|
}
|
|
@@ -265,7 +277,11 @@ async function runPrePushPhases({
|
|
|
265
277
|
}
|
|
266
278
|
const gates = validation?.gates ?? null;
|
|
267
279
|
setObservedGates(gates);
|
|
268
|
-
return {
|
|
280
|
+
return {
|
|
281
|
+
validationGates: gates,
|
|
282
|
+
lockWait: validation?.lockWait ?? null,
|
|
283
|
+
pending: validation?.pending === true,
|
|
284
|
+
};
|
|
269
285
|
}
|
|
270
286
|
|
|
271
287
|
async function openAndReviewPr({
|
|
@@ -283,17 +299,14 @@ async function openAndReviewPr({
|
|
|
283
299
|
setPhase = () => {},
|
|
284
300
|
}) {
|
|
285
301
|
setPhase('push');
|
|
286
|
-
//
|
|
287
|
-
//
|
|
288
|
-
// caller's `cwd`: they read the shared `.git`, so they resolve identically
|
|
289
|
-
// from either tree.
|
|
302
|
+
// Push from the worktree so `pre-push` measures the tree being sent; the
|
|
303
|
+
// ref-based reads below resolve identically from the shared `.git`.
|
|
290
304
|
pushStoryBranch({ cwd, worktreePath, storyBranch, gitSync, progress });
|
|
291
305
|
setPhase('pull-request');
|
|
292
306
|
const { url: prUrl, alreadyMerged } = await ensurePullRequestWith({
|
|
293
307
|
cwd,
|
|
294
308
|
storyId,
|
|
295
309
|
storyTitle: story.title,
|
|
296
|
-
// Scanned for a declared `BREAKING CHANGE:` footer — see pull-request.js.
|
|
297
310
|
storyBody: story.body,
|
|
298
311
|
storyBranch,
|
|
299
312
|
baseBranch,
|
|
@@ -301,10 +314,7 @@ async function openAndReviewPr({
|
|
|
301
314
|
progress,
|
|
302
315
|
});
|
|
303
316
|
const prNumber = parsePrNumber(prUrl);
|
|
304
|
-
//
|
|
305
|
-
// a previous close invocation was between phases). There is nothing left to
|
|
306
|
-
// review and nothing left to arm; the confirm phase probes the PR, observes
|
|
307
|
-
// MERGED, and lands the Story on the merge that actually happened.
|
|
317
|
+
// Already merged (landed between invocations): skip review and arm; confirm observes it.
|
|
308
318
|
if (alreadyMerged) {
|
|
309
319
|
return { prUrl, prNumber, alreadyMerged: true };
|
|
310
320
|
}
|
|
@@ -318,19 +328,12 @@ async function openAndReviewPr({
|
|
|
318
328
|
prNumber,
|
|
319
329
|
provider,
|
|
320
330
|
runCodeReviewFn: injectedRunCodeReview ?? runCodeReviewDefault,
|
|
321
|
-
// The runner owns the git seam it hands its phases (same as `gitSync` to
|
|
322
|
-
// `pushStoryBranch`). The review needs it to resolve `origin/<base>` —
|
|
323
|
-
// the ref base-sync merged from — before it will score anything
|
|
324
|
-
// (Story #5325).
|
|
325
331
|
gitSpawnFn: gitSpawn,
|
|
326
332
|
progress,
|
|
327
333
|
});
|
|
328
334
|
if (reviewOutcome.halted) {
|
|
329
335
|
const criticalCount = reviewOutcome.severity?.critical ?? 0;
|
|
330
|
-
//
|
|
331
|
-
// transition so an overridden run never touches `agent::blocked`: the
|
|
332
|
-
// Story is proceeding, and parking it would make the label lie for the
|
|
333
|
-
// rest of the close.
|
|
336
|
+
// Checked before the blocked transition: an overridden Story proceeds.
|
|
334
337
|
if (overrideReviewBlock) {
|
|
335
338
|
const override = await handleOverriddenReviewBlock({
|
|
336
339
|
provider,
|
|
@@ -390,30 +393,12 @@ async function releaseLease({
|
|
|
390
393
|
}
|
|
391
394
|
|
|
392
395
|
/**
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
* The two recoverable-blocked close exits (base-sync conflict in
|
|
397
|
-
* `runBaseSyncPhase`, and a critical-blocker review halt in
|
|
398
|
-
* `openAndReviewPr`) throw before the clean-close lease release at the
|
|
399
|
-
* tail of `runSingleStoryClose`, stranding the operator's lease
|
|
400
|
-
* indefinitely. The standalone lease has **no** TTL to expire by (Story
|
|
401
|
-
* #5006 deleted it): `acquireLease` refuses any foreign assignee outright,
|
|
402
|
-
* so a stranded claim is cleared only by `--steal` or de-assignment. That fail-closed-refuses a different operator who picks up
|
|
403
|
-
* the blocked Story — exactly the hand-off case. Releasing here closes
|
|
404
|
-
* that gap.
|
|
405
|
-
*
|
|
406
|
-
* The original throw is preserved verbatim (per
|
|
407
|
-
* `rules/orchestration-error-handling.md` — throw, never `Logger.fatal`),
|
|
408
|
-
* so the CLI boundary still maps it to a non-zero exit; the lease release
|
|
409
|
-
* must not swallow it. `releaseLease` is itself best-effort and never
|
|
410
|
-
* throws, so it cannot mask the real failure. Fail-closed re-acquire
|
|
411
|
-
* semantics are preserved: `releaseStoryLease` no-ops when the operator no
|
|
412
|
-
* longer holds the claim, and a self-held re-acquire on a re-run still
|
|
413
|
-
* succeeds against the now-unclaimed ticket.
|
|
396
|
+
* Release the lease best-effort before re-throwing a blocked-prone phase's
|
|
397
|
+
* error verbatim. The lease has no TTL, so a stranded claim would refuse the
|
|
398
|
+
* next operator who picks up the blocked Story.
|
|
414
399
|
*
|
|
415
400
|
* @template T
|
|
416
|
-
* @param {() => Promise<T>} run
|
|
401
|
+
* @param {() => Promise<T>} run
|
|
417
402
|
* @param {{ provider: object, storyId: number, config: object, injectedReleaseLease?: Function }} leaseArgs
|
|
418
403
|
* @returns {Promise<T>}
|
|
419
404
|
*/
|
|
@@ -427,25 +412,8 @@ async function releaseLeaseOnBlock(run, leaseArgs) {
|
|
|
427
412
|
}
|
|
428
413
|
|
|
429
414
|
/**
|
|
430
|
-
* Did this run OBSERVE the
|
|
431
|
-
*
|
|
432
|
-
* `merged` used to be whatever the caller happened to pass, and the two
|
|
433
|
-
* finishers passed different halves of the truth. Three observations say a
|
|
434
|
-
* merge happened, and each of them reported `merged: false` on at least one
|
|
435
|
-
* path:
|
|
436
|
-
*
|
|
437
|
-
* - the confirm phase watched it land (`waitOutcome.confirmed`);
|
|
438
|
-
* - it landed and only the `agent::done` label write failed
|
|
439
|
-
* (`merged-flip-failed`) — the terminal envelope for that same run
|
|
440
|
-
* already reports `pr.state: MERGED` from the probe, so a result denying
|
|
441
|
-
* the merge made the two halves of one run contradict each other;
|
|
442
|
-
* - the arm phase direct-squash-merged it synchronously because the
|
|
443
|
-
* repository has no native auto-merge (`directMerged`), which the
|
|
444
|
-
* no-wait finisher never consulted at all.
|
|
445
|
-
*
|
|
446
|
-
* Deliberately observation-only: it reads what the run saw, never what the
|
|
447
|
-
* run intended. A `null`/absent `waitOutcome` is the no-wait finisher, whose
|
|
448
|
-
* sole observation is the direct merge.
|
|
415
|
+
* Did this run OBSERVE the merge — confirmed, merged-but-flip-failed, or
|
|
416
|
+
* direct-merged? Observation only, never intent.
|
|
449
417
|
*
|
|
450
418
|
* @param {{ waitOutcome?: object|null, directMerged?: boolean }} args
|
|
451
419
|
* @returns {boolean}
|
|
@@ -486,25 +454,13 @@ function closeResult({
|
|
|
486
454
|
autoMergeReason,
|
|
487
455
|
worktreeReaped,
|
|
488
456
|
leaseReleased,
|
|
489
|
-
//
|
|
490
|
-
// merge/arm stood. Surfaced so the land is auditable as
|
|
491
|
-
// merged-with-deferred-cleanup rather than silently degraded.
|
|
457
|
+
// `gh`'s local branch delete failed while the remote merge/arm stood.
|
|
492
458
|
localCleanupDeferred,
|
|
493
|
-
//
|
|
494
|
-
// an already-clean PR), so the PR was landed by a direct squash-merge.
|
|
495
|
-
// Surfaced so a checks-less land is auditable rather than looking like a
|
|
496
|
-
// queued auto-merge that never fired.
|
|
459
|
+
// No native auto-merge, so the arm squash-merged directly.
|
|
497
460
|
directMerged,
|
|
498
461
|
waitedForMerge,
|
|
499
462
|
merged,
|
|
500
|
-
//
|
|
501
|
-
// never from `waitedForMerge`. A wait that expired unmerged used to write
|
|
502
|
-
// "PR merge confirmed" beside `merged: false`, and this log is what the
|
|
503
|
-
// operator reads first. See close-note.js for the invariant.
|
|
504
|
-
// Story #5279 — `landCompleted` keeps that invariant intact now that
|
|
505
|
-
// `merged: true` no longer implies the flip and the tail ran: a direct
|
|
506
|
-
// merge under `--no-wait-merge`, and a `merged-flip-failed` block, are
|
|
507
|
-
// both merged WITHOUT a completed land.
|
|
463
|
+
// Never from `waitedForMerge`; `merged` can be true without a completed land.
|
|
508
464
|
note: deriveCloseNote({
|
|
509
465
|
merged,
|
|
510
466
|
directMerged,
|
|
@@ -534,6 +490,7 @@ export async function runSingleStoryClose({
|
|
|
534
490
|
injectedGh,
|
|
535
491
|
injectedGitSpawn,
|
|
536
492
|
injectedReleaseLease,
|
|
493
|
+
injectedGraphqlProbe,
|
|
537
494
|
} = {}) {
|
|
538
495
|
const options = parseCloseOptions({
|
|
539
496
|
storyIdParam,
|
|
@@ -554,18 +511,10 @@ export async function runSingleStoryClose({
|
|
|
554
511
|
);
|
|
555
512
|
}
|
|
556
513
|
|
|
557
|
-
//
|
|
558
|
-
//
|
|
559
|
-
//
|
|
560
|
-
// the error with the phase it died in, and the CLI boundary turns that into
|
|
561
|
-
// the `failed` terminal envelope. Tagging rather than swallowing is what
|
|
562
|
-
// lets `failed` name its phase without inventing a second success path.
|
|
514
|
+
// The runner keeps THROWING; it only tags the error with its phase and the
|
|
515
|
+
// gates it observed (null until validation reports), and the CLI boundary
|
|
516
|
+
// builds the `failed` envelope from those tags.
|
|
563
517
|
let phase = 'init';
|
|
564
|
-
// Story #5279 — the per-gate outcomes this run OBSERVED, tagged onto a
|
|
565
|
-
// throwing error alongside the phase so `failedTerminalFor` reports gates
|
|
566
|
-
// instead of reconstructing which ones "must have" run. Stays null until
|
|
567
|
-
// close-validation reports, so a run that died before it claims no gates at
|
|
568
|
-
// all rather than inventing names for gates that were never registered.
|
|
569
518
|
let observedGates = null;
|
|
570
519
|
const setPhase = (next) => {
|
|
571
520
|
phase = next;
|
|
@@ -586,6 +535,7 @@ export async function runSingleStoryClose({
|
|
|
586
535
|
injectedGh,
|
|
587
536
|
injectedGitSpawn,
|
|
588
537
|
injectedReleaseLease,
|
|
538
|
+
injectedGraphqlProbe,
|
|
589
539
|
});
|
|
590
540
|
} catch (err) {
|
|
591
541
|
if (err && typeof err === 'object') {
|
|
@@ -597,10 +547,7 @@ export async function runSingleStoryClose({
|
|
|
597
547
|
}
|
|
598
548
|
|
|
599
549
|
/**
|
|
600
|
-
*
|
|
601
|
-
* to arm — `gh pr merge` against it fails, which would report the arm as a
|
|
602
|
-
* fault and block a Story whose work is already on the base branch. Skip the
|
|
603
|
-
* arm and let the confirm phase observe the merge that happened.
|
|
550
|
+
* An already-merged PR skips the arm (`gh pr merge` would fail and block it).
|
|
604
551
|
*
|
|
605
552
|
* @param {object} args
|
|
606
553
|
* @returns {Promise<{ autoMergeEnabled: boolean, autoMergeReason: string|null,
|
|
@@ -620,10 +567,6 @@ async function resolveAutoMergeOutcome({ alreadyMerged, ...phaseArgs }) {
|
|
|
620
567
|
}
|
|
621
568
|
|
|
622
569
|
/**
|
|
623
|
-
* Report the merge-wait terminal on the progress channel. Three endings, each
|
|
624
|
-
* with its own operator-facing shape — `landed` is done, `pending` is
|
|
625
|
-
* resumable and NOT a failure, anything else is a block naming its class.
|
|
626
|
-
*
|
|
627
570
|
* @param {{ status: string, nextCommand: string, blocked?: {blockClass?: string} }} terminal
|
|
628
571
|
* @param {{ storyId: number, prUrl: string|null }} ctx
|
|
629
572
|
* @returns {void}
|
|
@@ -634,9 +577,7 @@ function reportWaitTerminal(terminal, { storyId, prUrl }) {
|
|
|
634
577
|
return;
|
|
635
578
|
}
|
|
636
579
|
if (terminal.status === 'pending') {
|
|
637
|
-
//
|
|
638
|
-
// host slot with the PR healthy and in flight. The CLI maps this to
|
|
639
|
-
// its own exit code so a caller can resume without classifying.
|
|
580
|
+
// Not a failure: resumable, with its own CLI exit code.
|
|
640
581
|
progress(
|
|
641
582
|
'PENDING',
|
|
642
583
|
`⏸ Story #${storyId}: PR ${prUrl} still in flight — resume with: ${terminal.nextCommand}`,
|
|
@@ -652,11 +593,8 @@ function reportWaitTerminal(terminal, { storyId, prUrl }) {
|
|
|
652
593
|
}
|
|
653
594
|
|
|
654
595
|
/**
|
|
655
|
-
*
|
|
656
|
-
*
|
|
657
|
-
*
|
|
658
|
-
* @param {object} prCtx The shared PR/gate context built by the pipeline.
|
|
659
|
-
* @param {object} deps Runtime seams the confirm phase needs.
|
|
596
|
+
* @param {object} prCtx
|
|
597
|
+
* @param {object} deps
|
|
660
598
|
* @returns {Promise<{ success: boolean, result: object, terminal: object }>}
|
|
661
599
|
*/
|
|
662
600
|
async function finishWithMergeWait(prCtx, deps) {
|
|
@@ -689,6 +627,7 @@ async function finishWithMergeWait(prCtx, deps) {
|
|
|
689
627
|
prUrl: prCtx.prUrl,
|
|
690
628
|
autoMergeEnabled: prCtx.autoMergeEnabled,
|
|
691
629
|
gates: prCtx.gates,
|
|
630
|
+
lockWait: prCtx.lockWait,
|
|
692
631
|
elapsedSeconds: elapsedSecondsSince(prCtx.startedAtMs),
|
|
693
632
|
});
|
|
694
633
|
const result = closeResult({
|
|
@@ -700,22 +639,15 @@ async function finishWithMergeWait(prCtx, deps) {
|
|
|
700
639
|
autoMergeEnabled: prCtx.autoMergeEnabled,
|
|
701
640
|
autoMergeReason: prCtx.autoMergeReason,
|
|
702
641
|
worktreeReaped: prCtx.worktreeReaped,
|
|
703
|
-
//
|
|
704
|
-
// own per-step boolean IS the answer. A wait that ended anything other
|
|
705
|
-
// than landed never ran the tail, and correctly reports `false`: the
|
|
706
|
-
// claim is still held, by design.
|
|
642
|
+
// Released by the post-land tail only; any other ending keeps the claim.
|
|
707
643
|
leaseReleased: waitOutcome.tail?.leaseRelease === true,
|
|
708
644
|
localCleanupDeferred: prCtx.localCleanupDeferred,
|
|
709
645
|
directMerged: prCtx.directMerged,
|
|
710
646
|
waitedForMerge: true,
|
|
711
|
-
// Story #5279 — `confirmed` alone denied the merge behind a
|
|
712
|
-
// `merged-flip-failed` block, whose own envelope (above) reports
|
|
713
|
-
// `pr.state: MERGED` off the probe.
|
|
714
647
|
merged: deriveObservedMerge({
|
|
715
648
|
waitOutcome,
|
|
716
649
|
directMerged: prCtx.directMerged,
|
|
717
650
|
}),
|
|
718
|
-
// Only the confirmed ending runs the flip, the issue close and the tail.
|
|
719
651
|
landCompleted: waitOutcome.confirmed === true,
|
|
720
652
|
});
|
|
721
653
|
await emitTerminal({ terminal, result, config: prCtx.config });
|
|
@@ -724,20 +656,14 @@ async function finishWithMergeWait(prCtx, deps) {
|
|
|
724
656
|
}
|
|
725
657
|
|
|
726
658
|
/**
|
|
727
|
-
* The no-wait ending
|
|
728
|
-
*
|
|
729
|
-
* is not done, nothing is broken, and one named command finishes it — rather
|
|
730
|
-
* than a fourth status invented for this one case.
|
|
659
|
+
* The no-wait ending: a human owns the land, so it is `pending` with one
|
|
660
|
+
* command to finish it. A direct merge by the arm is still observed.
|
|
731
661
|
*
|
|
732
662
|
* @param {object} prCtx
|
|
733
663
|
* @param {string} waitForMergeReason
|
|
734
664
|
* @returns {Promise<{ success: boolean, result: object, terminal: object }>}
|
|
735
665
|
*/
|
|
736
666
|
async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
|
|
737
|
-
// Story #5279 — a repository with no native auto-merge is direct
|
|
738
|
-
// squash-merged synchronously by the arm phase, so this ending can and does
|
|
739
|
-
// hold an OBSERVED merge. It used to report `merged: false` and hard-code
|
|
740
|
-
// `pr.state: 'OPEN'` for a PR the same run had just merged.
|
|
741
667
|
const merged = deriveObservedMerge({ directMerged: prCtx.directMerged });
|
|
742
668
|
const result = closeResult({
|
|
743
669
|
storyId: prCtx.storyId,
|
|
@@ -748,15 +674,11 @@ async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
|
|
|
748
674
|
autoMergeEnabled: prCtx.autoMergeEnabled,
|
|
749
675
|
autoMergeReason: prCtx.autoMergeReason,
|
|
750
676
|
worktreeReaped: prCtx.worktreeReaped,
|
|
751
|
-
// Story #4860 — this is the no-wait ending: the PR is open and a human
|
|
752
|
-
// owns the merge, so the Story stays assigned until the confirm-merge
|
|
753
|
-
// surface lands it and runs the tail.
|
|
754
677
|
leaseReleased: false,
|
|
755
678
|
localCleanupDeferred: prCtx.localCleanupDeferred,
|
|
756
679
|
directMerged: prCtx.directMerged,
|
|
757
680
|
merged,
|
|
758
|
-
//
|
|
759
|
-
// closes the issue and never runs the tail — `nextCommand` does.
|
|
681
|
+
// The flip, issue close and tail belong to `nextCommand`.
|
|
760
682
|
landCompleted: false,
|
|
761
683
|
});
|
|
762
684
|
const terminal = buildTerminalEnvelope({
|
|
@@ -772,6 +694,7 @@ async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
|
|
|
772
694
|
autoMergeEnabled: Boolean(prCtx.autoMergeEnabled),
|
|
773
695
|
},
|
|
774
696
|
gates: prCtx.gates,
|
|
697
|
+
lockWait: prCtx.lockWait,
|
|
775
698
|
nextCommand: NEXT_COMMANDS.confirmMerge(prCtx.storyId),
|
|
776
699
|
elapsedSeconds: elapsedSecondsSince(prCtx.startedAtMs),
|
|
777
700
|
});
|
|
@@ -784,9 +707,25 @@ async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
|
|
|
784
707
|
}
|
|
785
708
|
|
|
786
709
|
/**
|
|
787
|
-
*
|
|
788
|
-
* envelope's `elapsedSeconds`.
|
|
710
|
+
* A full-suite lock wait expired: `pending`, nothing pushed.
|
|
789
711
|
*
|
|
712
|
+
* @param {{ waitedSeconds: number, expired: boolean }|null} lockWait
|
|
713
|
+
* @param {{ storyId: number, storyBranch: string, baseBranch: string,
|
|
714
|
+
* config: object, startedAtMs: number }} ctx
|
|
715
|
+
* @returns {Promise<{ success: false, result: object, terminal: object }>}
|
|
716
|
+
*/
|
|
717
|
+
async function finishDeferred(lockWait, { config, startedAtMs, ...ids }) {
|
|
718
|
+
const { result, terminal, note } = lockWaitPending({
|
|
719
|
+
...ids,
|
|
720
|
+
lockWait,
|
|
721
|
+
elapsedSeconds: elapsedSecondsSince(startedAtMs),
|
|
722
|
+
});
|
|
723
|
+
await emitTerminal({ terminal, result, config });
|
|
724
|
+
progress('PENDING', note);
|
|
725
|
+
return { success: false, result, terminal };
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/**
|
|
790
729
|
* @param {number} startedAtMs
|
|
791
730
|
* @returns {number}
|
|
792
731
|
*/
|
|
@@ -795,10 +734,6 @@ function elapsedSecondsSince(startedAtMs) {
|
|
|
795
734
|
}
|
|
796
735
|
|
|
797
736
|
/**
|
|
798
|
-
* Announce the operator-merge skip: the PR was deliberately left un-armed, so
|
|
799
|
-
* nothing here can land it and the Story rests at `agent::closing`. No-op on
|
|
800
|
-
* every other wait reason.
|
|
801
|
-
*
|
|
802
737
|
* @param {{ waitForMergeReason: string, autoMergeReason: string|null,
|
|
803
738
|
* storyId: number, waitForMergeExplicit?: boolean }} args
|
|
804
739
|
* @returns {void}
|
|
@@ -820,11 +755,6 @@ function reportOperatorMergeSkip({
|
|
|
820
755
|
);
|
|
821
756
|
}
|
|
822
757
|
|
|
823
|
-
/**
|
|
824
|
-
* The close pipeline proper. Split out of `runSingleStoryClose` so the
|
|
825
|
-
* phase-tagging wrapper above stays a thin, obviously-correct boundary rather
|
|
826
|
-
* than a try block wrapped around a hundred lines of pipeline.
|
|
827
|
-
*/
|
|
828
758
|
async function runClosePipeline({
|
|
829
759
|
options,
|
|
830
760
|
setPhase,
|
|
@@ -837,6 +767,7 @@ async function runClosePipeline({
|
|
|
837
767
|
injectedGh,
|
|
838
768
|
injectedGitSpawn,
|
|
839
769
|
injectedReleaseLease,
|
|
770
|
+
injectedGraphqlProbe,
|
|
840
771
|
}) {
|
|
841
772
|
const startedAtMs = Date.now();
|
|
842
773
|
const config = injectedConfig || resolveConfig({ cwd: options.cwd });
|
|
@@ -846,12 +777,6 @@ async function runClosePipeline({
|
|
|
846
777
|
progress('INIT', `Closing standalone Story #${options.storyId}...`);
|
|
847
778
|
const story = await provider.getTicket(options.storyId);
|
|
848
779
|
if (story.state === 'closed') {
|
|
849
|
-
progress(
|
|
850
|
-
'NOOP',
|
|
851
|
-
story.stateReason === 'not_planned'
|
|
852
|
-
? `Story #${options.storyId} is closed as not planned — nothing to land.`
|
|
853
|
-
: `Story #${options.storyId} is already closed. Nothing to do.`,
|
|
854
|
-
);
|
|
855
780
|
return await alreadyClosedResult(
|
|
856
781
|
options.storyId,
|
|
857
782
|
story.stateReason,
|
|
@@ -859,16 +784,35 @@ async function runClosePipeline({
|
|
|
859
784
|
);
|
|
860
785
|
}
|
|
861
786
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
787
|
+
const leaseArgs = {
|
|
788
|
+
provider,
|
|
789
|
+
storyId: options.storyId,
|
|
790
|
+
config,
|
|
791
|
+
injectedReleaseLease,
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
// `gh pr` needs GraphQL; one cheap read here beats the gate chain plus a push.
|
|
795
|
+
const preflight = await runGraphqlPreflight({
|
|
796
|
+
storyId: options.storyId,
|
|
797
|
+
provider,
|
|
798
|
+
progress,
|
|
799
|
+
ghFacade: injectedGh,
|
|
800
|
+
probe: injectedGraphqlProbe,
|
|
801
|
+
});
|
|
802
|
+
if (preflight) {
|
|
803
|
+
await releaseLease(leaseArgs);
|
|
804
|
+
return await preflightBlockedResult({
|
|
805
|
+
storyId: options.storyId,
|
|
806
|
+
preflight,
|
|
807
|
+
config,
|
|
808
|
+
startedAtMs,
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// The base the run was SEEDED from (init receipt); throws before any merge
|
|
813
|
+
// when it disagrees with current config.
|
|
869
814
|
const { values: runScoped, confirmed: baseConfirmed } =
|
|
870
815
|
await resolveRunScopedConfig({
|
|
871
|
-
provider,
|
|
872
816
|
storyId: options.storyId,
|
|
873
817
|
config,
|
|
874
818
|
progress,
|
|
@@ -880,17 +824,7 @@ async function runClosePipeline({
|
|
|
880
824
|
config,
|
|
881
825
|
storyId: options.storyId,
|
|
882
826
|
});
|
|
883
|
-
|
|
884
|
-
// before the clean-close lease release at the tail of this function.
|
|
885
|
-
// Wrap both blocked-prone phases so the lease is released best-effort
|
|
886
|
-
// before the throw propagates; the original error is preserved.
|
|
887
|
-
const leaseArgs = {
|
|
888
|
-
provider,
|
|
889
|
-
storyId: options.storyId,
|
|
890
|
-
config,
|
|
891
|
-
injectedReleaseLease,
|
|
892
|
-
};
|
|
893
|
-
const { validationGates } = await releaseLeaseOnBlock(
|
|
827
|
+
const prePush = await releaseLeaseOnBlock(
|
|
894
828
|
() =>
|
|
895
829
|
runPrePushPhases({
|
|
896
830
|
...options,
|
|
@@ -907,6 +841,15 @@ async function runClosePipeline({
|
|
|
907
841
|
}),
|
|
908
842
|
leaseArgs,
|
|
909
843
|
);
|
|
844
|
+
if (prePush.pending) {
|
|
845
|
+
return await finishDeferred(prePush.lockWait, {
|
|
846
|
+
storyId: options.storyId,
|
|
847
|
+
storyBranch,
|
|
848
|
+
baseBranch,
|
|
849
|
+
config,
|
|
850
|
+
startedAtMs,
|
|
851
|
+
});
|
|
852
|
+
}
|
|
910
853
|
|
|
911
854
|
const { prUrl, prNumber, alreadyMerged, reviewOverride } =
|
|
912
855
|
await releaseLeaseOnBlock(
|
|
@@ -927,16 +870,9 @@ async function runClosePipeline({
|
|
|
927
870
|
}),
|
|
928
871
|
leaseArgs,
|
|
929
872
|
);
|
|
930
|
-
// Reap the
|
|
931
|
-
//
|
|
932
|
-
//
|
|
933
|
-
// `git` to drop `story-<id>`. A live worktree still holding that ref makes
|
|
934
|
-
// the local delete fail, `gh` exit non-zero, and the arm read as failed,
|
|
935
|
-
// which used to strand a genuinely merged PR at `agent::blocked`.
|
|
936
|
-
// Pre-empting the hold is the ordering half of the fix (the tolerate half
|
|
937
|
-
// lives in `phases/auto-merge.js`); it is safe here because push and PR
|
|
938
|
-
// creation already made the work durable off-machine, and `isSafeToRemove`
|
|
939
|
-
// still refuses a dirty tree.
|
|
873
|
+
// Reap BEFORE the arm: `gh pr merge --delete-branch` may merge at once and
|
|
874
|
+
// then fail deleting a branch a live worktree holds, reading as a failed
|
|
875
|
+
// arm. Safe — the work is pushed, and a dirty tree is still refused.
|
|
940
876
|
const worktreeReaped = await reapWorktreePhase({
|
|
941
877
|
cwd: options.cwd,
|
|
942
878
|
storyId: options.storyId,
|
|
@@ -960,7 +896,6 @@ async function runClosePipeline({
|
|
|
960
896
|
prUrl,
|
|
961
897
|
noAutoMerge: options.noAutoMerge,
|
|
962
898
|
autoMergePolicy: ciDelivery.autoMerge,
|
|
963
|
-
// Story #5096 — the pre-arm advisory-gate refusal.
|
|
964
899
|
blockOnAdvisoryFailure: ciDelivery.blockOnAdvisoryFailure,
|
|
965
900
|
advisoryAllowlist: ciDelivery.advisoryAllowlist,
|
|
966
901
|
gh: injectedGh,
|
|
@@ -977,30 +912,11 @@ async function runClosePipeline({
|
|
|
977
912
|
config,
|
|
978
913
|
progress,
|
|
979
914
|
});
|
|
980
|
-
//
|
|
981
|
-
//
|
|
982
|
-
// claim the moment the PR opened, so a ticket read unassigned for the whole
|
|
983
|
-
// time its PR was in flight — and forever on the operator-merge path, where
|
|
984
|
-
// nothing downstream ever re-claimed it. The release now belongs to the
|
|
985
|
-
// post-land tail, which runs only on a CONFIRMED merge and which both
|
|
986
|
-
// landing surfaces reach. Every non-merged ending below — the
|
|
987
|
-
// `merge.unlanded` block, an exhausted wait budget, `--no-wait-merge`,
|
|
988
|
-
// `--no-auto-merge` — deliberately RETAINS the claim: the PR is open and the
|
|
989
|
-
// work still has an owner. The only releases that survive here are
|
|
990
|
-
// `releaseLeaseOnBlock`'s two throwing exits above, which fire before the PR
|
|
991
|
-
// is ever armed (Story #4257's hand-off property).
|
|
915
|
+
// No lease release here: only the post-land tail (confirmed merge) releases
|
|
916
|
+
// it; every non-merged ending keeps the claim while the PR is open.
|
|
992
917
|
|
|
993
|
-
//
|
|
994
|
-
//
|
|
995
|
-
// explicitly with `merge.unlanded`, instead of resting at `agent::closing`.
|
|
996
|
-
// This is the DEFAULT path for attended and headless runs alike.
|
|
997
|
-
//
|
|
998
|
-
// Resolved here rather than at parse time because two inputs do not exist
|
|
999
|
-
// until now: the resolved config (whose cwd the parse produces) and the
|
|
1000
|
-
// actual arm outcome. A PR the operator deliberately left un-armed
|
|
1001
|
-
// (`--no-auto-merge` / `autoMerge: "strict"`) has nothing to land, so it
|
|
1002
|
-
// rests at `agent::closing` for the human instead of burning the poll
|
|
1003
|
-
// budget and then blocking a healthy Story.
|
|
918
|
+
// Resolved now, not at parse time: it needs the config and the arm outcome
|
|
919
|
+
// (an un-armed PR rests at `agent::closing` rather than waiting).
|
|
1004
920
|
const { waitForMerge, reason: waitForMergeReason } = resolveWaitForMerge({
|
|
1005
921
|
waitForMergeExplicit: options.waitForMergeExplicit,
|
|
1006
922
|
noWaitForMerge: options.noWaitForMerge,
|
|
@@ -1027,17 +943,8 @@ async function runClosePipeline({
|
|
|
1027
943
|
directMerged,
|
|
1028
944
|
config,
|
|
1029
945
|
startedAtMs,
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
// Story #5172 — the split baselines entries, named individually so a
|
|
1033
|
-
// reader can tell the two apart. Absent when validation was skipped.
|
|
1034
|
-
...baselinesEnvelopeGates(validationGates),
|
|
1035
|
-
baseSync: options.skipSync ? 'skipped' : 'passed',
|
|
1036
|
-
// An overridden blocker reports `overridden`, never
|
|
1037
|
-
// `passed`. The review DID fail; a human authorized shipping anyway, and
|
|
1038
|
-
// the envelope is the machine-readable trail that says so.
|
|
1039
|
-
codeReview: reviewOverride ? 'overridden' : 'passed',
|
|
1040
|
-
},
|
|
946
|
+
lockWait: prePush.lockWait,
|
|
947
|
+
gates: closeEnvelopeGates(options, prePush.validationGates, reviewOverride),
|
|
1041
948
|
};
|
|
1042
949
|
|
|
1043
950
|
if (waitForMerge) {
|