mandrel 2.60.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 +10 -10
- package/.agents/agents/story-worker.md +1 -1
- package/.agents/docs/agentrc-reference.json +4 -82
- package/.agents/docs/configuration.md +20 -87
- package/.agents/docs/workflows.md +1 -1
- package/.agents/instructions.md +1 -3
- package/.agents/rules/gherkin-standards.md +4 -0
- package/.agents/schemas/agentrc.schema.json +11 -486
- package/.agents/schemas/story-deliver-terminal.schema.json +10 -0
- package/.agents/schemas/validation-evidence.schema.json +2 -1
- package/.agents/scripts/README.md +14 -14
- package/.agents/scripts/acceptance-eval.js +32 -164
- 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 +9 -45
- package/.agents/scripts/check-arch-cycles.js +14 -64
- package/.agents/scripts/check-baselines.js +8 -48
- package/.agents/scripts/check-context-budget.js +46 -172
- 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 +32 -99
- package/.agents/scripts/deliver-light.js +14 -101
- package/.agents/scripts/deliver-recover.js +6 -42
- package/.agents/scripts/deliver-run.js +36 -133
- 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 +10 -50
- 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 +5 -21
- 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 +31 -143
- 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 -35
- package/.agents/scripts/lib/config/explain.js +9 -80
- package/.agents/scripts/lib/config/gates/coverage.schema.js +0 -12
- package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +2 -30
- 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 +10 -52
- package/.agents/scripts/lib/config-schema-shared.js +1 -4
- package/.agents/scripts/lib/config-settings-schema-delivery.js +12 -294
- 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 +12 -37
- package/.agents/scripts/lib/coverage-capture-incremental.js +12 -43
- package/.agents/scripts/lib/coverage-capture-usage.js +4 -24
- 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 -126
- 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 +93 -419
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +20 -98
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +27 -151
- 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 +31 -259
- 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 +21 -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 +5 -75
- 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 +42 -189
- 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 +42 -214
- 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 +26 -231
- 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 +52 -303
- 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 +14 -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 +49 -248
- package/.agents/scripts/lib/orchestration/plan-persist/soft-findings.js +2 -12
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +85 -368
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +8 -38
- package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +30 -190
- 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 -94
- 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 +40 -199
- package/.agents/scripts/lib/orchestration/run-scoped-config.js +13 -81
- 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 +18 -80
- 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 +9 -50
- 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 +110 -290
- 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 -201
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +43 -245
- package/.agents/scripts/lib/orchestration/story-init-envelope.js +4 -23
- 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 -126
- 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 +39 -181
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +51 -244
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +39 -250
- 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 +22 -83
- package/.agents/scripts/lib/story-body/footer-block.js +11 -44
- package/.agents/scripts/lib/story-body/story-body.js +83 -358
- package/.agents/scripts/lib/temp-retention.js +42 -143
- package/.agents/scripts/lib/templates/decomposer-prompts.js +11 -65
- 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 +53 -221
- 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 -104
- package/.agents/scripts/nav-registry-diff.js +22 -108
- package/.agents/scripts/notify.js +12 -69
- package/.agents/scripts/plan-context.js +27 -111
- package/.agents/scripts/plan-critics.js +12 -66
- package/.agents/scripts/plan-persist.js +31 -148
- package/.agents/scripts/plan-run-epilogue.js +11 -37
- package/.agents/scripts/pr-watch-with-update.js +76 -267
- 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 -209
- package/.agents/scripts/stories-wave-tick.js +102 -472
- 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/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/audit-lens-core.md +1 -1
- package/.agents/workflows/helpers/code-quality-guardrails.md +12 -15
- package/.agents/workflows/helpers/deliver-digest.md +6 -4
- package/.agents/workflows/helpers/deliver-reference.md +114 -188
- package/.agents/workflows/helpers/deliver-story-reference.md +189 -533
- package/.agents/workflows/helpers/plan-reference.md +86 -139
- package/.agents/workflows/helpers/qa-core.md +12 -0
- 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 +25 -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 +105 -661
- 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 +15 -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 +2 -21
- package/lib/migrations/steps/strip-removed-agentrc-keys.js +333 -0
- package/package.json +16 -14
- package/.agents/docs/SDLC.md +0 -590
- package/.agents/docs/quality-gates.md +0 -1183
- package/.agents/rules/known-tooling-behavior.md +0 -200
- 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/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 -368
- package/.agents/scripts/check-test-portability.js +0 -512
- package/.agents/scripts/check-workflow-citations.js +0 -218
- 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/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 -125
- package/.agents/scripts/test-isolate.js +0 -55
- package/.agents/scripts/update-dead-exports-baseline.js +0 -321
|
@@ -1,57 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* merge-poll.js — merge-wait constants and check-rollup derivation
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Story #4545 — these three symbols used to live in the Epic-era
|
|
6
|
-
* `lifecycle/listeners/merge-watcher.js`. That listener class had no
|
|
7
|
-
* production caller after the v2.0.0 Story-only cutover, but it was not
|
|
8
|
-
* importer-less: the live close path (`single-story-close/phases/confirm-merge.js`)
|
|
9
|
-
* and `deliver-recover.js` both reached into it for the poll defaults and
|
|
10
|
-
* `deriveChecksStatus`. Relocating them here lets the listener go without
|
|
11
|
-
* leaving the close path importing a lifecycle module it does not otherwise
|
|
12
|
-
* participate in.
|
|
13
|
-
*
|
|
14
|
-
* Sits beside `merge-block-class.js`, its sole consumer pairing:
|
|
15
|
-
* `deriveChecksStatus` produces the `prProbe.checksStatus` value that
|
|
16
|
-
* `classifyMergeBlock` reads.
|
|
2
|
+
* merge-poll.js — merge-wait constants and check-rollup derivation for the
|
|
3
|
+
* close path. `deriveChecksStatus` feeds `classifyMergeBlock`'s
|
|
4
|
+
* `prProbe.checksStatus`.
|
|
17
5
|
*/
|
|
18
6
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
* `delivery.mergeWatch.intervalSeconds` (default 30) and
|
|
23
|
-
* `delivery.mergeWatch.maxBudgetSeconds` (default 3600). Hard-coding the same
|
|
24
|
-
* numbers here keeps the close path self-contained when no config is wired in
|
|
25
|
-
* (e.g. unit tests).
|
|
26
|
-
*/
|
|
7
|
+
import { checkVerdict, classifyRollupEntry } from './check-state.js';
|
|
8
|
+
|
|
9
|
+
/** Fixed poll interval; default for `delivery.mergeWatch.maxBudgetSeconds`. */
|
|
27
10
|
export const DEFAULT_INTERVAL_SECONDS = 30;
|
|
28
11
|
export const DEFAULT_MAX_BUDGET_SECONDS = 3600;
|
|
29
12
|
|
|
30
|
-
/**
|
|
31
|
-
* Wall-clock bound for every `gh` subprocess the merge wait spawns (Story
|
|
32
|
-
* #4710). The wait is now routinely unattended (`delivery.mergeWatch.mode:
|
|
33
|
-
* "async"` runs it in a background invocation with no host tool ceiling), so
|
|
34
|
-
* a hung `gh pr view` / `gh pr update-branch` used to strand the wait with no
|
|
35
|
-
* terminal envelope, no label flip, and no friction record. Sixty seconds is
|
|
36
|
-
* generous for a single API round-trip while staying inside the async probe
|
|
37
|
-
* window; a timeout maps to the existing probe-error path, so the wait
|
|
38
|
-
* degrades to conservative-pending / `api-race-other` semantics instead of
|
|
39
|
-
* hanging. A framework constant by design — not config (Story #4710
|
|
40
|
-
* Non-Goals).
|
|
41
|
-
*/
|
|
13
|
+
/** Bounds every `gh` spawn so a hang degrades to the probe-error path. */
|
|
42
14
|
export const MERGE_WAIT_GH_TIMEOUT_MS = 60_000;
|
|
43
15
|
|
|
44
16
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* statusCheckRollup` shape: `{ status, conclusion }` per check). Mirrors the
|
|
48
|
-
* values `classifyMergeBlock` expects on `prProbe.checksStatus`.
|
|
49
|
-
*
|
|
50
|
-
* **Scope: EVERY check reported on the PR, required or not.** The rollup
|
|
51
|
-
* carries no required-vs-optional discriminator (`gh`'s projection has no
|
|
52
|
-
* `isRequired` field), so `failure` here means "something on this PR is red",
|
|
53
|
-
* NOT "the merge is blocked". Use {@link failingChecksBlockMerge} before
|
|
54
|
-
* treating a `failure` as terminal.
|
|
17
|
+
* Aggregate over EVERY check (the rollup has no `isRequired`): `failure`
|
|
18
|
+
* means "something is red", not "blocked" — see {@link failingChecksBlockMerge}.
|
|
55
19
|
*/
|
|
56
20
|
export function deriveChecksStatus(statusCheckRollup) {
|
|
57
21
|
if (!Array.isArray(statusCheckRollup) || statusCheckRollup.length === 0) {
|
|
@@ -59,73 +23,26 @@ export function deriveChecksStatus(statusCheckRollup) {
|
|
|
59
23
|
}
|
|
60
24
|
let anyPending = false;
|
|
61
25
|
for (const check of statusCheckRollup) {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
return 'failure';
|
|
66
|
-
}
|
|
67
|
-
if (status !== 'COMPLETED') {
|
|
68
|
-
anyPending = true;
|
|
69
|
-
}
|
|
26
|
+
const verdict = checkVerdict(classifyRollupEntry(check));
|
|
27
|
+
if (verdict === 'fail') return 'failure';
|
|
28
|
+
if (verdict === 'pending') anyPending = true;
|
|
70
29
|
}
|
|
71
30
|
return anyPending ? 'still-running' : 'success';
|
|
72
31
|
}
|
|
73
32
|
|
|
74
33
|
/**
|
|
75
|
-
*
|
|
76
|
-
* array, distinguishing a genuinely red required run from the pending /
|
|
77
|
-
* superseded noise the aggregate {@link deriveChecksStatus} folds together.
|
|
78
|
-
*
|
|
79
|
-
* {@link deriveChecksStatus} returns `failure` the instant it sees ANY
|
|
80
|
-
* non-passing conclusion — including a `CANCELLED` superseded-push run or a
|
|
81
|
-
* sibling-invalidated run — even while the real required check is still
|
|
82
|
-
* queued. Paired with `mergeStateStatus: BLOCKED` (the protected-branch steady
|
|
83
|
-
* state while required checks run), that matched a merely *pending* PR and
|
|
84
|
-
* hard-blocked Stories whose PRs merged untouched. This derivation reads the
|
|
85
|
-
* two signals the fail-fast decision actually needs:
|
|
86
|
-
*
|
|
87
|
-
* - `requiredRunFailed` — a run on the head concluded `FAILURE` (or a
|
|
88
|
-
* legacy status context is `FAILURE`/`ERROR`).
|
|
89
|
-
* Deliberately NOT `CANCELLED`/`TIMED_OUT`/
|
|
90
|
-
* `SKIPPED`: those are the superseded-push and
|
|
91
|
-
* sibling-invalidated runs, not a red required
|
|
92
|
-
* check.
|
|
93
|
-
* - `requiredRunInFlight` — any run on the head is still QUEUED /
|
|
94
|
-
* IN_PROGRESS (a CheckRun whose status is not
|
|
95
|
-
* `COMPLETED`, or a legacy status context still
|
|
96
|
-
* `PENDING`/`EXPECTED`).
|
|
97
|
-
*
|
|
98
|
-
* Returns `null` when the rollup is absent or empty — the evidence is
|
|
99
|
-
* unavailable and the caller must fall back to the consecutive-probe path
|
|
100
|
-
* (a single evidence-free failing snapshot must never fail-fast).
|
|
101
|
-
*
|
|
102
|
-
* **Contract honesty (Story #4710).** The `requiredRun*` field names describe
|
|
103
|
-
* what the evidence is USED to establish, not what this function reads: the
|
|
104
|
-
* `gh pr view` rollup projection carries no `isRequired` discriminator, so
|
|
105
|
-
* this derivation reads EVERY run on the head, required or not. On its own,
|
|
106
|
-
* `requiredRunFailed: true` therefore means "a head run genuinely concluded
|
|
107
|
-
* failure", and required-ness attribution is supplied downstream by
|
|
108
|
-
* {@link requiredCheckFailedBlocksMerge}, which admits the verdict only when
|
|
109
|
-
* `mergeStateStatus: BLOCKED` says GitHub itself gates the merge AND no
|
|
110
|
-
* review-required signal offers a competing explanation for that BLOCKED
|
|
111
|
-
* state. Do not treat this function's output as a required-only reading.
|
|
34
|
+
* `mergedAt` counts even when `state` lags. A closed issue proves nothing.
|
|
112
35
|
*
|
|
113
|
-
* @param {
|
|
114
|
-
* @returns {
|
|
36
|
+
* @param {{ state?: string|null, mergedAt?: string|null }|null|undefined} pr
|
|
37
|
+
* @returns {boolean}
|
|
115
38
|
*/
|
|
39
|
+
export function isPrMerged(pr) {
|
|
40
|
+
return pr?.state === 'MERGED' || Boolean(pr?.mergedAt);
|
|
41
|
+
}
|
|
42
|
+
|
|
116
43
|
/**
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* Red means `FAILURE` / `ERROR` only — never `CANCELLED` / `TIMED_OUT` /
|
|
121
|
-
* `SKIPPED`, which are the superseded-push and sibling-invalidated runs a bare
|
|
122
|
-
* rollup read miscounts (the #4695 / #4710 trap). A CheckRun carries the
|
|
123
|
-
* verdict on `conclusion`; a legacy StatusContext carries it on `state`, so
|
|
124
|
-
* both are read and the one that is red is the one returned.
|
|
125
|
-
*
|
|
126
|
-
* Extracted (Story #5266) because {@link deriveRequiredRunEvidence} and
|
|
127
|
-
* {@link deriveRedHeadRuns} were carrying byte-identical copies of this test:
|
|
128
|
-
* two places that must agree about what "red" means, and nothing making them.
|
|
44
|
+
* Red is `FAILURE` / `ERROR` only; `CANCELLED` / `TIMED_OUT` / `SKIPPED` are
|
|
45
|
+
* superseded or sibling-invalidated runs.
|
|
129
46
|
*
|
|
130
47
|
* @param {{ conclusion?: string, state?: string }} [check]
|
|
131
48
|
* @returns {string|null}
|
|
@@ -139,13 +56,7 @@ function redConclusionOf(check) {
|
|
|
139
56
|
}
|
|
140
57
|
|
|
141
58
|
/**
|
|
142
|
-
*
|
|
143
|
-
* legacy StatusContext's `context`, and `null` when the projection carries
|
|
144
|
-
* neither.
|
|
145
|
-
*
|
|
146
|
-
* A run with no readable name can never match an allowlist entry, so it always
|
|
147
|
-
* blocks. That is the conservative direction for a gate whose whole purpose is
|
|
148
|
-
* to stop a silent landing.
|
|
59
|
+
* An unnamed run never matches an allowlist entry, so it always blocks.
|
|
149
60
|
*
|
|
150
61
|
* @param {{ name?: string, context?: string }} [check]
|
|
151
62
|
* @returns {string|null}
|
|
@@ -157,6 +68,14 @@ function readRunName(check) {
|
|
|
157
68
|
return null;
|
|
158
69
|
}
|
|
159
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Head-anchored evidence; `null` on an empty rollup (the caller falls back
|
|
73
|
+
* to consecutive probes). Reads EVERY run despite the names — required-ness
|
|
74
|
+
* is attributed via `BLOCKED` in {@link requiredCheckFailedBlocksMerge}.
|
|
75
|
+
*
|
|
76
|
+
* @param {Array<{status?: string, conclusion?: string, state?: string}>} statusCheckRollup
|
|
77
|
+
* @returns {{ requiredRunFailed: boolean, requiredRunInFlight: boolean } | null}
|
|
78
|
+
*/
|
|
160
79
|
export function deriveRequiredRunEvidence(statusCheckRollup) {
|
|
161
80
|
if (!Array.isArray(statusCheckRollup) || statusCheckRollup.length === 0) {
|
|
162
81
|
return null;
|
|
@@ -166,9 +85,7 @@ export function deriveRequiredRunEvidence(statusCheckRollup) {
|
|
|
166
85
|
for (const check of statusCheckRollup) {
|
|
167
86
|
const status = String(check?.status ?? '').toUpperCase();
|
|
168
87
|
const state = String(check?.state ?? '').toUpperCase();
|
|
169
|
-
//
|
|
170
|
-
// PENDING/EXPECTED. `status` is empty on a StatusContext, so it degrades to
|
|
171
|
-
// the `state` branch rather than counting as in-flight.
|
|
88
|
+
// `status` is empty on a StatusContext, so it falls to the `state` branch.
|
|
172
89
|
if (status && status !== 'COMPLETED') {
|
|
173
90
|
requiredRunInFlight = true;
|
|
174
91
|
} else if (state === 'PENDING' || state === 'EXPECTED') {
|
|
@@ -181,41 +98,13 @@ export function deriveRequiredRunEvidence(statusCheckRollup) {
|
|
|
181
98
|
return { requiredRunFailed, requiredRunInFlight };
|
|
182
99
|
}
|
|
183
100
|
|
|
184
|
-
/**
|
|
185
|
-
* The one `mergeStateStatus` value that means GitHub itself is gating the
|
|
186
|
-
* merge. See {@link failingChecksBlockMerge}.
|
|
187
|
-
*/
|
|
101
|
+
/** The `mergeStateStatus` meaning GitHub itself gates the merge. */
|
|
188
102
|
const MERGE_GATED_STATE = 'BLOCKED';
|
|
189
103
|
|
|
190
104
|
/**
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
* for a red check of any kind. Branch protection — and therefore GitHub
|
|
195
|
-
* native auto-merge — gates only on REQUIRED checks. A red optional check
|
|
196
|
-
* (an advisory bot, or a `CANCELLED` superseded workflow run, which the
|
|
197
|
-
* rollup derivation counts as a failure) says nothing about whether the PR
|
|
198
|
-
* will land: auto-merge lands it regardless. Treating that as terminal is
|
|
199
|
-
* what stranded a Story `agent::blocked` on a PR that merged anyway.
|
|
200
|
-
*
|
|
201
|
-
* `mergeStateStatus` is GitHub's own verdict, computed against the live
|
|
202
|
-
* branch-protection rules, so it supplies the required-vs-optional
|
|
203
|
-
* discrimination the rollup lacks:
|
|
204
|
-
*
|
|
205
|
-
* - `BLOCKED` — merging is gated. With red checks observed, the red
|
|
206
|
-
* required check is the gate.
|
|
207
|
-
* - `UNSTABLE` — "mergeable with non-passing commit status": the red
|
|
208
|
-
* checks are NOT required. Auto-merge will land it.
|
|
209
|
-
* - `CLEAN` / `BEHIND` / `UNKNOWN` / absent — not evidence that the red
|
|
210
|
-
* check gates the merge.
|
|
211
|
-
*
|
|
212
|
-
* Deliberately conservative: only `BLOCKED` returns `true`. A transient
|
|
213
|
-
* `UNKNOWN` (GitHub has not finished computing the merge state) or a token
|
|
214
|
-
* that cannot see the field degrades to "keep waiting" — the caller's poll
|
|
215
|
-
* budget still bounds the wait and the budget-exhausted classification still
|
|
216
|
-
* fires. The asymmetry is intentional: failing to fail fast costs poll time,
|
|
217
|
-
* whereas failing fast wrongly costs a merged-but-`agent::blocked` strand
|
|
218
|
-
* that only an operator can unpick.
|
|
105
|
+
* Does the red status gate the merge? Only `BLOCKED` (GitHub's verdict
|
|
106
|
+
* against live protection rules) says so; `UNKNOWN` keeps waiting, since a
|
|
107
|
+
* wrong fail-fast strands a merged PR while waiting only costs poll time.
|
|
219
108
|
*
|
|
220
109
|
* @param {{ checksStatus?: string, mergeStateStatus?: string }} [prProbe]
|
|
221
110
|
* @returns {boolean}
|
|
@@ -228,39 +117,29 @@ export function failingChecksBlockMerge(prProbe) {
|
|
|
228
117
|
}
|
|
229
118
|
|
|
230
119
|
/**
|
|
231
|
-
*
|
|
232
|
-
* genuinely red — enough to fail-fast the merge wait as `checks-failed`?
|
|
233
|
-
*
|
|
234
|
-
* This is the single gated decision Story #4695 adds, and the named predicate
|
|
235
|
-
* a downstream async-confirm Story imports rather than reopening the poll
|
|
236
|
-
* loop's classification internals. It layers on {@link failingChecksBlockMerge}
|
|
237
|
-
* (the rollup-`failure` + `mergeStateStatus: BLOCKED` gate) the head-anchored
|
|
238
|
-
* refinement the raw gate lacked: classify `checks-failed` ONLY when a run
|
|
239
|
-
* genuinely concluded failure AND none is still in flight. A red rollup while
|
|
240
|
-
* a required run is queued/in-progress is the protected-branch pending steady
|
|
241
|
-
* state, not a failure.
|
|
120
|
+
* A missing review competes as the explanation for `BLOCKED`.
|
|
242
121
|
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
*
|
|
263
|
-
*
|
|
122
|
+
* @param {{ reviewDecision?: string }} [prProbe]
|
|
123
|
+
* @returns {boolean}
|
|
124
|
+
*/
|
|
125
|
+
function reviewOwnsBlockedState(prProbe) {
|
|
126
|
+
return prProbe?.reviewDecision === 'REVIEW_REQUIRED';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export const CHECKS_FAILED_CLASS = 'checks-failed';
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @param {{ mergeStateStatus?: string }} [prProbe]
|
|
133
|
+
* @param {string} [evidencePath]
|
|
134
|
+
* @returns {string}
|
|
135
|
+
*/
|
|
136
|
+
export function formatChecksFailedReason(prProbe, evidencePath) {
|
|
137
|
+
return `a required check failed (mergeStateStatus=${prProbe?.mergeStateStatus ?? 'n/a'}${evidencePath ? `, evidence=${evidencePath}` : ''})`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* A genuinely red REQUIRED check: gated, no review owns `BLOCKED`, a run is
|
|
142
|
+
* red and none in flight. No evidence → false (consecutive-probe path).
|
|
264
143
|
*
|
|
265
144
|
* @param {{ checksStatus?: string, mergeStateStatus?: string,
|
|
266
145
|
* reviewDecision?: string,
|
|
@@ -268,8 +147,9 @@ export function failingChecksBlockMerge(prProbe) {
|
|
|
268
147
|
* @returns {boolean}
|
|
269
148
|
*/
|
|
270
149
|
export function requiredCheckFailedBlocksMerge(prProbe) {
|
|
271
|
-
if (!failingChecksBlockMerge(prProbe))
|
|
272
|
-
|
|
150
|
+
if (!failingChecksBlockMerge(prProbe) || reviewOwnsBlockedState(prProbe)) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
273
153
|
const evidence = prProbe?.requiredRunEvidence;
|
|
274
154
|
if (!evidence || typeof evidence.requiredRunFailed !== 'boolean') {
|
|
275
155
|
return false;
|
|
@@ -280,30 +160,15 @@ export function requiredCheckFailedBlocksMerge(prProbe) {
|
|
|
280
160
|
}
|
|
281
161
|
|
|
282
162
|
/**
|
|
283
|
-
*
|
|
284
|
-
* red runs — GitHub's own words are "mergeable with non-passing commit
|
|
285
|
-
* status". It is the required-vs-advisory discriminator the rollup itself
|
|
286
|
-
* cannot supply: under `UNSTABLE` the red runs are, by definition, not
|
|
287
|
-
* required, so native auto-merge will land the PR over them.
|
|
288
|
-
*
|
|
289
|
-
* The exact complement of {@link MERGE_GATED_STATE}: `BLOCKED` means the red
|
|
290
|
-
* run gates the merge (`failingChecksBlockMerge`), `UNSTABLE` means it does
|
|
291
|
-
* not and only mandrel can stop the landing.
|
|
163
|
+
* Red runs are not required: auto-merge lands over them unless mandrel stops it.
|
|
292
164
|
*/
|
|
293
165
|
const MERGE_ADVISORY_STATE = 'UNSTABLE';
|
|
294
166
|
|
|
295
167
|
/**
|
|
296
|
-
* The
|
|
297
|
-
* red. A legacy StatusContext carries `description`; a GitHub Actions CheckRun
|
|
298
|
-
* carries none of them in `gh pr view`'s fixed `statusCheckRollup` projection,
|
|
299
|
-
* so the merge wait enriches the run with the check-run API's
|
|
300
|
-
* `output.title` / `output.summary` before classifying (Story #5266). Both
|
|
301
|
-
* shapes are read here so the projection has ONE text extractor.
|
|
168
|
+
* The run's own account of why it went red (rollup or enriched check-run).
|
|
302
169
|
*
|
|
303
170
|
* @param {object} [check] A rollup entry, or an enriched check-run record.
|
|
304
|
-
* @returns {string|undefined}
|
|
305
|
-
* carries none — which is itself the signal that the run cannot be
|
|
306
|
-
* classified beyond "red".
|
|
171
|
+
* @returns {string|undefined} `undefined` when the record carries no text.
|
|
307
172
|
*/
|
|
308
173
|
export function readRunSummary(check) {
|
|
309
174
|
const parts = [];
|
|
@@ -316,11 +181,7 @@ export function readRunSummary(check) {
|
|
|
316
181
|
}
|
|
317
182
|
|
|
318
183
|
/**
|
|
319
|
-
*
|
|
320
|
-
* (`.../actions/runs/<runId>/job/<jobId>`), or `null` when the URL is absent
|
|
321
|
-
* or shaped otherwise (a legacy StatusContext's `targetUrl`, a third-party
|
|
322
|
-
* app's own page). A run with no id can never be re-run, which is why the
|
|
323
|
-
* rerun path treats `null` as "nothing to re-run" rather than an error.
|
|
184
|
+
* `null` means "nothing to re-run".
|
|
324
185
|
*
|
|
325
186
|
* @param {string} [detailsUrl]
|
|
326
187
|
* @returns {number|null}
|
|
@@ -334,30 +195,8 @@ export function parseWorkflowRunId(detailsUrl) {
|
|
|
334
195
|
}
|
|
335
196
|
|
|
336
197
|
/**
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
* Same red-ness test as {@link deriveRequiredRunEvidence} — `FAILURE` /
|
|
341
|
-
* `ERROR` only, never `CANCELLED` / `TIMED_OUT` / `SKIPPED`, which are the
|
|
342
|
-
* superseded-push and sibling-invalidated runs a bare rollup read miscounts
|
|
343
|
-
* (the #4695 / #4710 trap) — but it returns the runs rather than a boolean, so
|
|
344
|
-
* a block summary can name the offending job and the advisory allowlist can
|
|
345
|
-
* match on it.
|
|
346
|
-
*
|
|
347
|
-
* `name` is the CheckRun's `name`, falling back to a legacy StatusContext's
|
|
348
|
-
* `context`, and is `null` when the projection carries neither. A run with no
|
|
349
|
-
* readable name can never match an allowlist entry, so it always blocks — the
|
|
350
|
-
* conservative direction for a gate whose whole purpose is to stop a silent
|
|
351
|
-
* landing.
|
|
352
|
-
*
|
|
353
|
-
* **Widened by Story #5266** from `{name, conclusion}` to carry what a red run
|
|
354
|
-
* is classified and acted on by: `summary` (the run's own account of why it
|
|
355
|
-
* failed — see {@link readRunSummary}), `runId` (the workflow run behind it,
|
|
356
|
-
* so a rerun can be requested), and `completedAt` (the observation stamp that
|
|
357
|
-
* tells a re-run's verdict apart from the stale pre-rerun one). Every added
|
|
358
|
-
* field is OMITTED when the projection carries no value for it, so a run the
|
|
359
|
-
* rollup describes as thinly as before still projects to exactly the old two
|
|
360
|
-
* keys — and a thin run classifies as a violation, i.e. the pre-#5266 verdict.
|
|
198
|
+
* Red head runs. Optional fields are omitted when absent; `completedAt`
|
|
199
|
+
* separates a rerun's verdict from the stale one.
|
|
361
200
|
*
|
|
362
201
|
* @param {Array<{name?: string, context?: string, status?: string, conclusion?: string, state?: string, detailsUrl?: string, completedAt?: string, description?: string, output?: object}>} statusCheckRollup
|
|
363
202
|
* @returns {Array<{ name: string|null, conclusion: string, summary?: string, runId?: number, completedAt?: string }>}
|
|
@@ -385,17 +224,13 @@ export function deriveRedHeadRuns(statusCheckRollup) {
|
|
|
385
224
|
}
|
|
386
225
|
|
|
387
226
|
/**
|
|
388
|
-
*
|
|
389
|
-
* `delivery.ci.advisoryAllowlist`, returning the ones that still block.
|
|
390
|
-
*
|
|
391
|
-
* Matching is exact on the run name. An unnamed run never matches (see
|
|
392
|
-
* {@link deriveRedHeadRuns}).
|
|
227
|
+
* Red runs not exempted by the allowlist (exact name match).
|
|
393
228
|
*
|
|
394
229
|
* @param {Array<{ name: string|null, conclusion: string }>} redHeadRuns
|
|
395
230
|
* @param {string[]} [allowlist]
|
|
396
231
|
* @returns {Array<{ name: string|null, conclusion: string }>}
|
|
397
232
|
*/
|
|
398
|
-
|
|
233
|
+
function selectBlockingRedRuns(redHeadRuns, allowlist = []) {
|
|
399
234
|
if (!Array.isArray(redHeadRuns) || redHeadRuns.length === 0) return [];
|
|
400
235
|
const exempt = new Set(
|
|
401
236
|
(Array.isArray(allowlist) ? allowlist : [])
|
|
@@ -407,28 +242,14 @@ export function selectBlockingRedRuns(redHeadRuns, allowlist = []) {
|
|
|
407
242
|
}
|
|
408
243
|
|
|
409
244
|
/**
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
* (Story #5096.)
|
|
413
|
-
*
|
|
414
|
-
* The complement of {@link requiredCheckFailedBlocksMerge}. That predicate
|
|
415
|
-
* answers "is a red REQUIRED check gating the merge" (`BLOCKED`); this one
|
|
416
|
-
* answers "is a red NON-required check about to be merged straight past"
|
|
417
|
-
* (`UNSTABLE`). The two are mutually exclusive by construction, so a red
|
|
418
|
-
* required check keeps its existing `checks-failed` treatment untouched.
|
|
419
|
-
*
|
|
420
|
-
* **Fails OPEN by design.** `UNKNOWN`, `CLEAN`, `BEHIND`, or an absent
|
|
421
|
-
* `mergeStateStatus` all return `false`. The asymmetry is the same one
|
|
422
|
-
* {@link failingChecksBlockMerge} documents and is deliberate: failing to
|
|
423
|
-
* block costs an unattended landing the operator can still revert, whereas
|
|
424
|
-
* blocking wrongly strands a mergeable PR at `agent::blocked` that only an
|
|
425
|
-
* operator can unpick. A transient `UNKNOWN` must never do the latter.
|
|
245
|
+
* A red advisory run about to be merged past (`UNSTABLE`). Fails open on any
|
|
246
|
+
* other state: a wrong block strands a PR; a miss is a revertable landing.
|
|
426
247
|
*
|
|
427
248
|
* @param {{ mergeStateStatus?: string, redHeadRuns?: Array<{name: string|null, conclusion: string}> }} [prProbe]
|
|
428
249
|
* @param {string[]} [allowlist] `delivery.ci.advisoryAllowlist`.
|
|
429
250
|
* @returns {boolean}
|
|
430
251
|
*/
|
|
431
|
-
|
|
252
|
+
function advisoryCheckFailedBlocksArm(prProbe, allowlist = []) {
|
|
432
253
|
if (
|
|
433
254
|
String(prProbe?.mergeStateStatus ?? '').toUpperCase() !==
|
|
434
255
|
MERGE_ADVISORY_STATE
|
|
@@ -439,31 +260,15 @@ export function advisoryCheckFailedBlocksArm(prProbe, allowlist = []) {
|
|
|
439
260
|
}
|
|
440
261
|
|
|
441
262
|
/**
|
|
442
|
-
*
|
|
443
|
-
*
|
|
444
|
-
* which is the whole reason they are two:
|
|
445
|
-
*
|
|
446
|
-
* - `advisory-gate-red` A red advisory run that REPORTED a
|
|
447
|
-
* violation. The change is implicated;
|
|
448
|
-
* landing over it is a deliberate override.
|
|
449
|
-
* - `advisory-gate-inconclusive` A red advisory run that never finished — a
|
|
450
|
-
* scan or navigation timeout that reported
|
|
451
|
-
* no violation at all. Nothing here says the
|
|
452
|
-
* change is bad, so the proportionate remedy
|
|
453
|
-
* is to re-run the job, not to grant the
|
|
454
|
-
* permanent global exemption
|
|
455
|
-
* `advisoryAllowlist` is.
|
|
263
|
+
* Both block; `-inconclusive` (never finished, e.g. a timeout) warrants a
|
|
264
|
+
* rerun rather than a permanent allowlist exemption.
|
|
456
265
|
*/
|
|
457
266
|
export const ADVISORY_GATE_RED_CLASS = 'advisory-gate-red';
|
|
458
267
|
export const ADVISORY_GATE_INCONCLUSIVE_CLASS = 'advisory-gate-inconclusive';
|
|
459
268
|
|
|
460
269
|
/**
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
* exceeded` line with an empty violation set, and anything this list does not
|
|
464
|
-
* recognise keeps the pre-#5266 `advisory-gate-red` verdict — the conservative
|
|
465
|
-
* direction, since misreading a real violation as a timeout would offer the
|
|
466
|
-
* operator a rerun for a finding that will come back every time.
|
|
270
|
+
* Deliberately narrow: misreading a violation as a timeout offers a rerun
|
|
271
|
+
* that fails every time.
|
|
467
272
|
*/
|
|
468
273
|
const INCONCLUSIVE_MARKERS = Object.freeze([
|
|
469
274
|
/navigation timeout/i,
|
|
@@ -477,19 +282,10 @@ const INCONCLUSIVE_MARKERS = Object.freeze([
|
|
|
477
282
|
/** A counted finding — `0 violations` is explicitly NOT one. */
|
|
478
283
|
const VIOLATION_COUNT =
|
|
479
284
|
/\b(\d+)\s+(?:violation|error|issue|failure|problem|finding)s?\b/i;
|
|
480
|
-
/** An uncounted finding — enough on its own, because it names a verdict. */
|
|
481
285
|
const VIOLATION_WORD = /\bviolations?\b|\bfailed assertion/i;
|
|
482
286
|
|
|
483
287
|
/**
|
|
484
|
-
*
|
|
485
|
-
* nothing, or saying it never got that far)?
|
|
486
|
-
*
|
|
487
|
-
* A counted phrase wins over the bare word so `0 violations found` — a scan
|
|
488
|
-
* that completed cleanly and then died — is not read as a finding.
|
|
489
|
-
*
|
|
490
|
-
* Takes the text, not the run: its one caller has already established the
|
|
491
|
-
* run says something, so a second empty-text guard here would be a branch no
|
|
492
|
-
* input can reach.
|
|
288
|
+
* A counted phrase wins over the bare word.
|
|
493
289
|
*
|
|
494
290
|
* @param {string} text A non-empty run summary.
|
|
495
291
|
* @returns {boolean}
|
|
@@ -501,12 +297,7 @@ function reportsViolations(text) {
|
|
|
501
297
|
}
|
|
502
298
|
|
|
503
299
|
/**
|
|
504
|
-
*
|
|
505
|
-
* unfinished job (Story #5266).
|
|
506
|
-
*
|
|
507
|
-
* A run whose projection carries no text at all classifies as `violation`:
|
|
508
|
-
* absence of evidence is not evidence the job timed out, and `violation` is
|
|
509
|
-
* the verdict every red advisory run already got before this Story.
|
|
300
|
+
* No text is a `violation`: absence of evidence is not a timeout.
|
|
510
301
|
*
|
|
511
302
|
* @param {{ summary?: string }} [run]
|
|
512
303
|
* @returns {'violation'|'inconclusive'}
|
|
@@ -520,16 +311,8 @@ function classifyAdvisoryRedRun(run) {
|
|
|
520
311
|
}
|
|
521
312
|
|
|
522
313
|
/**
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
* `advisory-gate-inconclusive` requires EVERY blocking run to be inconclusive.
|
|
526
|
-
* One genuine violation beside a timeout is still a genuine violation, and the
|
|
527
|
-
* operator must not be offered a rerun as the remedy for it.
|
|
528
|
-
*
|
|
529
|
-
* Module-private: {@link resolveAdvisoryGateVerdict} is the one door, so a
|
|
530
|
-
* caller cannot take the class without the reason that matches it — and, being
|
|
531
|
-
* the one door, it is also what normalises `blockingRuns` to an array, so
|
|
532
|
-
* neither this nor {@link formatAdvisoryGateReason} re-guards the shape.
|
|
314
|
+
* Inconclusive only when EVERY run is. Private: the class travels with its
|
|
315
|
+
* reason via {@link resolveAdvisoryGateVerdict}.
|
|
533
316
|
*
|
|
534
317
|
* @param {Array<{ summary?: string }>} runs
|
|
535
318
|
* @returns {string} one of the two advisory classes above
|
|
@@ -542,10 +325,6 @@ function deriveAdvisoryGateClass(runs) {
|
|
|
542
325
|
}
|
|
543
326
|
|
|
544
327
|
/**
|
|
545
|
-
* Pure: the advisory gate's whole verdict — class AND the reason text that
|
|
546
|
-
* matches it (Story #5266). One function so a caller can never pair an
|
|
547
|
-
* inconclusive class with the violation wording.
|
|
548
|
-
*
|
|
549
328
|
* @param {{ blockingRuns?: Array<object>, rerunAllowance?: number }} [args]
|
|
550
329
|
* @returns {{ blockClass: string, blockingRuns: Array<object>, reason: string }}
|
|
551
330
|
*/
|
|
@@ -563,22 +342,8 @@ export function resolveAdvisoryGateVerdict({
|
|
|
563
342
|
}
|
|
564
343
|
|
|
565
344
|
/**
|
|
566
|
-
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
* Encapsulates the whole policy — the knob, the predicate, and the allowlist
|
|
570
|
-
* projection — so the poll body carries a single assignment rather than three
|
|
571
|
-
* decision points. `runMergePoll` sits above `check-cyclomatic`'s ceiling
|
|
572
|
-
* already; every branch added inline there is a real regression, and this
|
|
573
|
-
* policy has a natural home beside the predicate it consumes.
|
|
574
|
-
*
|
|
575
|
-
* Returns `null` when the wait should keep polling — the knob is off, the PR
|
|
576
|
-
* is not in the advisory-red state, or every red run is allowlisted.
|
|
577
|
-
*
|
|
578
|
-
* The verdict it returns is provisional on the text the ROLLUP carried
|
|
579
|
-
* (Story #5266): the caller may enrich the blocking runs with the check-run
|
|
580
|
-
* API's output and re-resolve via {@link resolveAdvisoryGateVerdict} before
|
|
581
|
-
* recording the block.
|
|
345
|
+
* `null` means keep polling. Reflects rollup text only; the caller may enrich
|
|
346
|
+
* and re-resolve.
|
|
582
347
|
*
|
|
583
348
|
* @param {object} args
|
|
584
349
|
* @returns {{ blockingRuns: Array<object>, reason: string, blockClass: string } | null}
|
|
@@ -599,19 +364,6 @@ export function decideAdvisoryGateBlock({
|
|
|
599
364
|
}
|
|
600
365
|
|
|
601
366
|
/**
|
|
602
|
-
* Format the one-line reason a `merge.unlanded` record and the operator-facing
|
|
603
|
-
* block carry for an advisory-gate verdict, naming each offending job and its
|
|
604
|
-
* conclusion.
|
|
605
|
-
*
|
|
606
|
-
* Story #5266 splits the wording by class: an unfinished job is reported as
|
|
607
|
-
* one, because telling an operator a timed-out scan "concluded red" invites
|
|
608
|
-
* them to grant a permanent `advisoryAllowlist` exemption for a transient
|
|
609
|
-
* failure. Both wordings name the same three remedies — rerun, hand-merge,
|
|
610
|
-
* allowlist — in the order proportionate to the class.
|
|
611
|
-
*
|
|
612
|
-
* Module-private for the same reason {@link deriveAdvisoryGateClass} is: the
|
|
613
|
-
* class and the wording must travel together.
|
|
614
|
-
*
|
|
615
367
|
* @param {Array<{ name: string|null, conclusion: string }>} runs
|
|
616
368
|
* @param {{ blockClass: string, rerunAllowance: number }} options
|
|
617
369
|
* @returns {string}
|
|
@@ -652,33 +404,16 @@ function formatAdvisoryGateReason(runs, { blockClass, rerunAllowance }) {
|
|
|
652
404
|
}
|
|
653
405
|
|
|
654
406
|
/**
|
|
655
|
-
*
|
|
656
|
-
*
|
|
657
|
-
* loop, beside its sibling predicates).
|
|
658
|
-
*
|
|
659
|
-
* Encapsulates the Story #4695 evidence policy in one place:
|
|
660
|
-
*
|
|
661
|
-
* - **Per-run evidence available** — decide on this single probe via
|
|
662
|
-
* {@link requiredCheckFailedBlocksMerge}; a required run still in flight
|
|
663
|
-
* (or only superseded / non-required noise red) resets the counter and
|
|
664
|
-
* keeps polling.
|
|
665
|
-
* - **Evidence unavailable** (older `gh`, API error, empty rollup) — require
|
|
666
|
-
* TWO consecutive failing probes at least one poll interval apart, then
|
|
667
|
-
* synthesize the evidence shape the classifier's gate reads so both paths
|
|
668
|
-
* classify `checks-failed` through the same predicate.
|
|
669
|
-
*
|
|
670
|
-
* Returns the next counter value alongside the verdict; the caller owns the
|
|
671
|
-
* mutable counter and the terminal side effects. When `failFast` is `true`,
|
|
672
|
-
* `prProbe` is the evidence-stamped probe to hand to the classifier and
|
|
673
|
-
* `evidencePath` names which path fired (`per-run` | `consecutive-probe`) for
|
|
674
|
-
* the `merge.unlanded` telemetry.
|
|
407
|
+
* Fail-fast: decide on per-run evidence, else require two consecutive
|
|
408
|
+
* failing probes. The verdict is carried to the terminal, never re-derived.
|
|
675
409
|
*
|
|
676
410
|
* @param {object} args
|
|
677
411
|
* @param {object} args.probe The current poll's {@code readPrWaitProbe} result.
|
|
678
412
|
* @param {number} args.consecutiveRequiredFailSnapshots Evidence-free failing
|
|
679
413
|
* probes observed so far.
|
|
680
414
|
* @returns {{ failFast: boolean, consecutiveRequiredFailSnapshots: number,
|
|
681
|
-
*
|
|
415
|
+
* blockClass?: string, reason?: string, prProbe?: object,
|
|
416
|
+
* evidencePath?: 'per-run'|'consecutive-probe' }}
|
|
682
417
|
*/
|
|
683
418
|
export function decideMergeWaitFailFast({
|
|
684
419
|
probe,
|
|
@@ -689,37 +424,29 @@ export function decideMergeWaitFailFast({
|
|
|
689
424
|
}
|
|
690
425
|
if (probe?.requiredRunEvidence) {
|
|
691
426
|
if (requiredCheckFailedBlocksMerge(probe)) {
|
|
692
|
-
return
|
|
693
|
-
failFast: true,
|
|
694
|
-
consecutiveRequiredFailSnapshots: 0,
|
|
695
|
-
evidencePath: 'per-run',
|
|
696
|
-
prProbe: { ...probe, evidencePath: 'per-run' },
|
|
697
|
-
};
|
|
427
|
+
return checksFailedVerdict(probe, 'per-run', 0);
|
|
698
428
|
}
|
|
699
|
-
//
|
|
700
|
-
// are red, or a missing required review owns the BLOCKED state: the
|
|
701
|
-
// protected-branch steady state, not a failure. Keep polling.
|
|
429
|
+
// In flight, only non-required red, or review owns BLOCKED: keep polling.
|
|
702
430
|
return { failFast: false, consecutiveRequiredFailSnapshots: 0 };
|
|
703
431
|
}
|
|
704
432
|
const next = consecutiveRequiredFailSnapshots + 1;
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
// predicate as the per-run path (including its review-required softening).
|
|
708
|
-
const synthesized = {
|
|
709
|
-
...probe,
|
|
710
|
-
requiredRunEvidence: {
|
|
711
|
-
requiredRunFailed: true,
|
|
712
|
-
requiredRunInFlight: false,
|
|
713
|
-
},
|
|
714
|
-
evidencePath: 'consecutive-probe',
|
|
715
|
-
};
|
|
716
|
-
if (next >= 2 && requiredCheckFailedBlocksMerge(synthesized)) {
|
|
717
|
-
return {
|
|
718
|
-
failFast: true,
|
|
719
|
-
consecutiveRequiredFailSnapshots: next,
|
|
720
|
-
evidencePath: 'consecutive-probe',
|
|
721
|
-
prProbe: synthesized,
|
|
722
|
-
};
|
|
433
|
+
if (next >= 2 && !reviewOwnsBlockedState(probe)) {
|
|
434
|
+
return checksFailedVerdict(probe, 'consecutive-probe', next);
|
|
723
435
|
}
|
|
724
436
|
return { failFast: false, consecutiveRequiredFailSnapshots: next };
|
|
725
437
|
}
|
|
438
|
+
|
|
439
|
+
function checksFailedVerdict(
|
|
440
|
+
probe,
|
|
441
|
+
evidencePath,
|
|
442
|
+
consecutiveRequiredFailSnapshots,
|
|
443
|
+
) {
|
|
444
|
+
return {
|
|
445
|
+
failFast: true,
|
|
446
|
+
consecutiveRequiredFailSnapshots,
|
|
447
|
+
evidencePath,
|
|
448
|
+
blockClass: CHECKS_FAILED_CLASS,
|
|
449
|
+
reason: formatChecksFailedReason(probe, evidencePath),
|
|
450
|
+
prProbe: { ...probe, evidencePath },
|
|
451
|
+
};
|
|
452
|
+
}
|