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,74 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* gh-exec.js —
|
|
3
|
-
*
|
|
4
|
-
* Story #1356 (Epic #1179 — v6 Epic A: MCP + gh CLI rebase). This is the
|
|
5
|
-
* core shim that subsequent provider rewrites build on. It deliberately
|
|
6
|
-
* stays narrow:
|
|
7
|
-
*
|
|
8
|
-
* - `exec({ args, input, timeoutMs })` shells out via
|
|
9
|
-
* `child_process.spawn('gh', args, { stdio: ['pipe','pipe','pipe'] })`.
|
|
10
|
-
* `args` is always an array — no string-interpolated command line, no
|
|
11
|
-
* `shell: true`. That keeps argument injection impossible by
|
|
12
|
-
* construction.
|
|
13
|
-
* - When `args` contains the literal `--json` flag, stdout is run through
|
|
14
|
-
* `JSON.parse` before returning. Callers that pass `--json` are asking
|
|
15
|
-
* for structured data; honor that.
|
|
16
|
-
* - When `args` does not contain `--json`, the raw `{ stdout, stderr, code }`
|
|
17
|
-
* envelope is returned. This is what `gh api` callers and the few
|
|
18
|
-
* "read raw text" call sites want.
|
|
19
|
-
*
|
|
20
|
-
* Error surface is intentionally a single base class in this Task —
|
|
21
|
-
* `GhExecTimeoutError` is the only specialization required by the
|
|
22
|
-
* acceptance criteria. Task #1369 layers the rest of the typed error
|
|
23
|
-
* classes (auth-required, not-found, GraphQL, etc.) on top of `GhExecError`.
|
|
24
|
-
* Task #1370 adds the typed convenience wrappers (`issue.view`, `pr.create`,
|
|
25
|
-
* `api`, etc.).
|
|
26
|
-
*
|
|
27
|
-
* The module exports `exec` as the default export plus named exports for
|
|
28
|
-
* the error classes so callers can `instanceof`-check without importing
|
|
29
|
-
* the whole module namespace.
|
|
2
|
+
* gh-exec.js — `gh` CLI wrapper. `args` is always an array spawned without a
|
|
3
|
+
* shell, so argument injection is impossible by construction.
|
|
30
4
|
*/
|
|
31
5
|
|
|
32
6
|
import { spawn as defaultSpawn } from 'node:child_process';
|
|
33
7
|
|
|
34
|
-
/**
|
|
35
|
-
* Throw-away in-process spawn counter (Story #1795 / Epic #1788).
|
|
36
|
-
*
|
|
37
|
-
* Incremented once per `exec()` invocation that successfully reaches the
|
|
38
|
-
* `spawnImpl('gh', ...)` call. Exported via `getSpawnCount` so the
|
|
39
|
-
* Story-close structured comment can emit it under `ghSpawnCount` for
|
|
40
|
-
* the ">=100 fewer spawns" acceptance criterion. This counter is
|
|
41
|
-
* deliberately ephemeral — Story #1795's acceptance includes removing
|
|
42
|
-
* the counter and `getSpawnCount` helper in a follow-up cleanup commit
|
|
43
|
-
* before the Story merges to the Epic branch.
|
|
44
|
-
*/
|
|
45
8
|
let _spawnCount = 0;
|
|
46
9
|
|
|
47
10
|
/**
|
|
48
|
-
* Return the running total of `gh` spawns since this module was loaded
|
|
49
|
-
* (or since the last `resetSpawnCount()` call). Counts every spawn
|
|
50
|
-
* attempt, including those that error before the child exits.
|
|
51
|
-
*
|
|
52
11
|
* @returns {number}
|
|
53
12
|
*/
|
|
54
13
|
export function getSpawnCount() {
|
|
55
14
|
return _spawnCount;
|
|
56
15
|
}
|
|
57
16
|
|
|
58
|
-
/**
|
|
59
|
-
* Reset the spawn counter to zero. Test seam — production code never
|
|
60
|
-
* calls this. Tests that exercise the counter MUST reset it in
|
|
61
|
-
* `beforeEach` so test order doesn't bleed across cases.
|
|
62
|
-
*/
|
|
63
17
|
export function resetSpawnCount() {
|
|
64
18
|
_spawnCount = 0;
|
|
65
19
|
}
|
|
66
20
|
|
|
67
|
-
/**
|
|
68
|
-
* Base class for all gh-exec errors. Carries the args that were passed to
|
|
69
|
-
* `gh`, the captured stdout/stderr, and the process exit code (or null when
|
|
70
|
-
* the process never produced one — e.g. timeout, spawn error).
|
|
71
|
-
*/
|
|
21
|
+
/** `code` is null when the process never produced one. */
|
|
72
22
|
export class GhExecError extends Error {
|
|
73
23
|
constructor(message, { args, stdout = '', stderr = '', code = null } = {}) {
|
|
74
24
|
super(message);
|
|
@@ -80,11 +30,6 @@ export class GhExecError extends Error {
|
|
|
80
30
|
}
|
|
81
31
|
}
|
|
82
32
|
|
|
83
|
-
/**
|
|
84
|
-
* Raised when the child process is killed by the `timeout` option before it
|
|
85
|
-
* exits on its own. Distinct from `GhExecError` so callers (retry loops,
|
|
86
|
-
* watchdog code) can match on `instanceof GhExecTimeoutError`.
|
|
87
|
-
*/
|
|
88
33
|
export class GhExecTimeoutError extends GhExecError {
|
|
89
34
|
constructor(message, details = {}) {
|
|
90
35
|
super(message, details);
|
|
@@ -93,12 +38,6 @@ export class GhExecTimeoutError extends GhExecError {
|
|
|
93
38
|
}
|
|
94
39
|
}
|
|
95
40
|
|
|
96
|
-
/**
|
|
97
|
-
* `gh` is not on PATH (ENOENT on spawn, or stderr literally contains the
|
|
98
|
-
* "command not found" / "is not recognized" phrasing for Windows). Callers
|
|
99
|
-
* (`agents-bootstrap-github`) treat this as a hard preflight failure and
|
|
100
|
-
* print install instructions.
|
|
101
|
-
*/
|
|
102
41
|
export class GhNotInstalledError extends GhExecError {
|
|
103
42
|
constructor(message, details = {}) {
|
|
104
43
|
super(message, details);
|
|
@@ -106,7 +45,6 @@ export class GhNotInstalledError extends GhExecError {
|
|
|
106
45
|
}
|
|
107
46
|
}
|
|
108
47
|
|
|
109
|
-
/** `gh auth login` has not been run (or the token expired). */
|
|
110
48
|
export class GhAuthError extends GhExecError {
|
|
111
49
|
constructor(message, details = {}) {
|
|
112
50
|
super(message, details);
|
|
@@ -114,10 +52,7 @@ export class GhAuthError extends GhExecError {
|
|
|
114
52
|
}
|
|
115
53
|
}
|
|
116
54
|
|
|
117
|
-
/**
|
|
118
|
-
* Hit a primary or secondary rate limit. Distinct from auth so caller retry
|
|
119
|
-
* loops can back off rather than re-prompt for credentials.
|
|
120
|
-
*/
|
|
55
|
+
/** Primary or secondary rate limit — callers back off, not re-auth. */
|
|
121
56
|
export class GhRateLimitError extends GhExecError {
|
|
122
57
|
constructor(message, details = {}) {
|
|
123
58
|
super(message, details);
|
|
@@ -125,7 +60,6 @@ export class GhRateLimitError extends GhExecError {
|
|
|
125
60
|
}
|
|
126
61
|
}
|
|
127
62
|
|
|
128
|
-
/** Resource (issue, PR, repo, branch) does not exist or is not visible. */
|
|
129
63
|
export class GhNotFoundError extends GhExecError {
|
|
130
64
|
constructor(message, details = {}) {
|
|
131
65
|
super(message, details);
|
|
@@ -133,11 +67,6 @@ export class GhNotFoundError extends GhExecError {
|
|
|
133
67
|
}
|
|
134
68
|
}
|
|
135
69
|
|
|
136
|
-
/**
|
|
137
|
-
* The authenticated user is authenticated but missing a required scope (e.g.
|
|
138
|
-
* `project` for Projects V2). `gh auth refresh -s <scope>` is the canonical
|
|
139
|
-
* recovery.
|
|
140
|
-
*/
|
|
141
70
|
export class GhScopeError extends GhExecError {
|
|
142
71
|
constructor(message, details = {}) {
|
|
143
72
|
super(message, details);
|
|
@@ -145,12 +74,6 @@ export class GhScopeError extends GhExecError {
|
|
|
145
74
|
}
|
|
146
75
|
}
|
|
147
76
|
|
|
148
|
-
/**
|
|
149
|
-
* GraphQL endpoint returned `errors[]` (most commonly emitted by
|
|
150
|
-
* `gh api graphql`). The stderr carries the rendered error string; we
|
|
151
|
-
* surface it as-is so callers can pattern-match on the specific GraphQL
|
|
152
|
-
* failure if they care.
|
|
153
|
-
*/
|
|
154
77
|
export class GhGraphqlError extends GhExecError {
|
|
155
78
|
constructor(message, details = {}) {
|
|
156
79
|
super(message, details);
|
|
@@ -159,23 +82,11 @@ export class GhGraphqlError extends GhExecError {
|
|
|
159
82
|
}
|
|
160
83
|
|
|
161
84
|
/**
|
|
162
|
-
*
|
|
163
|
-
* the
|
|
164
|
-
*
|
|
165
|
-
* Every `GhExecError` carries the captured `stderr`, but the classified
|
|
166
|
-
* message keeps only the exit status — so a caller that logs `err.message`
|
|
167
|
-
* alone flattens every unclassified failure to `gh-exec: gh exited with code
|
|
168
|
-
* 1`. That is exactly what hid an HTTP 422 `description is too long` behind
|
|
169
|
-
* three identical "label ensure failed" warnings (Story #5201). `gh` prints
|
|
170
|
-
* the actionable sentence on the *last* stderr line — the leading lines are
|
|
171
|
-
* the `HTTP 422:` banner and the API URL — so that line is what is appended.
|
|
172
|
-
*
|
|
173
|
-
* Non-`GhExecError` inputs (a plain `Error` from a provider fake, a thrown
|
|
174
|
-
* string) degrade to their own message, so this is safe on any catch path.
|
|
85
|
+
* Message plus the last stderr line — where `gh` prints the actionable
|
|
86
|
+
* reason, which the classified message omits.
|
|
175
87
|
*
|
|
176
88
|
* @param {unknown} err
|
|
177
|
-
* @returns {string}
|
|
178
|
-
* when no stderr was captured.
|
|
89
|
+
* @returns {string}
|
|
179
90
|
*/
|
|
180
91
|
export function describeGhFailure(err) {
|
|
181
92
|
const message = String(err?.message ?? err ?? 'unknown error');
|
|
@@ -188,44 +99,22 @@ export function describeGhFailure(err) {
|
|
|
188
99
|
}
|
|
189
100
|
|
|
190
101
|
/**
|
|
191
|
-
* Classify a non-zero `gh` invocation into the most specific typed error
|
|
192
|
-
* subclass available. Pure function — no side effects, no I/O.
|
|
193
|
-
*
|
|
194
|
-
* Pattern table (order-sensitive: more specific patterns first):
|
|
195
|
-
*
|
|
196
|
-
* spawnError.code === 'ENOENT' → GhNotInstalledError
|
|
197
|
-
* /command not found|not recognized/i (no spawnError) → GhNotInstalledError
|
|
198
|
-
* /requires authentication|auth (login|status)/i → GhAuthError
|
|
199
|
-
* /rate limit|secondary rate limit|API rate limit/i → GhRateLimitError
|
|
200
|
-
* /missing.*scope|requires the .* scope/i → GhScopeError
|
|
201
|
-
* /HTTP 404|not found|could not resolve/i → GhNotFoundError
|
|
202
|
-
* /GraphQL: |graphql.*error/i → GhGraphqlError
|
|
203
|
-
* anything else → GhExecError
|
|
204
|
-
*
|
|
205
102
|
* @param {object} ctx
|
|
206
103
|
* @param {string} [ctx.stderr]
|
|
207
104
|
* @param {number|null} [ctx.code]
|
|
208
105
|
* @param {string[]} [ctx.args]
|
|
209
106
|
* @param {string} [ctx.stdout]
|
|
210
107
|
* @param {Error} [ctx.spawnError]
|
|
211
|
-
* Raw error thrown by `spawn` (e.g. ENOENT). Passed through so the auth
|
|
212
|
-
* path can distinguish "missing binary" from "binary present, said no".
|
|
213
108
|
* @returns {GhExecError}
|
|
214
109
|
*/
|
|
215
110
|
/**
|
|
216
|
-
*
|
|
217
|
-
* is truthy wins. Pulling these out of the function body collapses
|
|
218
|
-
* `classify` from a giant if/else chain (cc ≈ 4 with many condition
|
|
219
|
-
* literals → CRAP 22) to a simple find-then-construct (cc = 2).
|
|
111
|
+
* First match wins.
|
|
220
112
|
*
|
|
221
113
|
* @type {Array<{
|
|
222
114
|
* test: (h: string) => boolean,
|
|
223
115
|
* build: (details: object) => Error,
|
|
224
116
|
* }>}
|
|
225
117
|
*/
|
|
226
|
-
// Per-category combined regexes. Alternation keeps each pattern at cc=1
|
|
227
|
-
// (regex literals don't carry control-flow weight) so `classify`'s
|
|
228
|
-
// dispatch loop stays well under the CRAP=20 ceiling for the file.
|
|
229
118
|
const CLASSIFY_RULES = [
|
|
230
119
|
{
|
|
231
120
|
pattern:
|
|
@@ -289,8 +178,7 @@ export function classify({
|
|
|
289
178
|
const spawnVerdict = classifySpawnError(spawnError, details);
|
|
290
179
|
if (spawnVerdict) return spawnVerdict;
|
|
291
180
|
const haystack = `${stderr}`.toLowerCase();
|
|
292
|
-
//
|
|
293
|
-
// callers can distinguish "binary missing" from "binary present, refused".
|
|
181
|
+
// With a spawnError, skip the not-installed text rule.
|
|
294
182
|
const startIdx = spawnError ? 1 : 0;
|
|
295
183
|
for (let i = startIdx; i < CLASSIFY_RULES.length; i += 1) {
|
|
296
184
|
if (CLASSIFY_RULES[i].pattern.test(haystack))
|
|
@@ -300,24 +188,13 @@ export function classify({
|
|
|
300
188
|
}
|
|
301
189
|
|
|
302
190
|
/**
|
|
303
|
-
* Spawn `gh` with the given args. Returns a Promise.
|
|
304
|
-
*
|
|
305
191
|
* @param {object} opts
|
|
306
192
|
* @param {string[]} opts.args
|
|
307
|
-
* Positional + flag arguments to pass to `gh`. Must be an array — string
|
|
308
|
-
* command lines are rejected so callers cannot accidentally invite shell
|
|
309
|
-
* interpolation.
|
|
310
193
|
* @param {string} [opts.input]
|
|
311
|
-
* Optional stdin payload. Written to the child once and then closed.
|
|
312
194
|
* @param {number} [opts.timeoutMs]
|
|
313
|
-
* Optional wall-clock timeout. When the child is killed by this timeout
|
|
314
|
-
* the returned Promise rejects with `GhExecTimeoutError`.
|
|
315
195
|
* @param {Function} [opts.spawnImpl]
|
|
316
|
-
* Test seam — defaults to `child_process.spawn`. Tests inject a fake that
|
|
317
|
-
* returns an `EventEmitter`-shaped object.
|
|
318
196
|
* @returns {Promise<object|{stdout:string,stderr:string,code:number}>}
|
|
319
|
-
*
|
|
320
|
-
* Otherwise resolves to `{ stdout, stderr, code }`.
|
|
197
|
+
* Parsed JSON when `args` contains `--json`, else the raw envelope.
|
|
321
198
|
*/
|
|
322
199
|
export function exec({
|
|
323
200
|
args,
|
|
@@ -344,10 +221,7 @@ export function exec({
|
|
|
344
221
|
return new Promise((resolve, reject) => {
|
|
345
222
|
let child;
|
|
346
223
|
try {
|
|
347
|
-
//
|
|
348
|
-
// before the spawnImpl call so an immediate-throw spawnError still
|
|
349
|
-
// reflects in the total — the measurement we care about is "did we
|
|
350
|
-
// attempt to launch gh", not "did gh exit cleanly".
|
|
224
|
+
// Counted before the call so an immediate-throw spawn still counts.
|
|
351
225
|
_spawnCount += 1;
|
|
352
226
|
child = spawnImpl('gh', args, spawnOpts);
|
|
353
227
|
} catch (err) {
|
|
@@ -420,47 +294,22 @@ export function exec({
|
|
|
420
294
|
});
|
|
421
295
|
}
|
|
422
296
|
|
|
423
|
-
/* ---------------------------------------------------------------------- */
|
|
424
|
-
/* Typed convenience wrappers (Task #1370) */
|
|
425
|
-
/* ---------------------------------------------------------------------- */
|
|
426
|
-
|
|
427
297
|
/**
|
|
428
|
-
*
|
|
429
|
-
* factory exists so tests can inject a fake `exec` (which itself wraps a fake
|
|
430
|
-
* `spawn`) and assert the argv shape each wrapper produces. Production code
|
|
431
|
-
* just imports the pre-bound `gh` singleton.
|
|
432
|
-
*
|
|
433
|
-
* The wrappers are deliberately thin: each one builds the argv array,
|
|
434
|
-
* delegates to `exec`, and returns the parsed result. The only logic worth
|
|
435
|
-
* naming lives in `gh.api`, which translates the structured
|
|
436
|
-
* `{ method, endpoint, body, fields, paginate }` shape into the right
|
|
437
|
-
* `-X / -f / --paginate / --input -` flag combination.
|
|
298
|
+
* Typed `gh` facade over an `exec` implementation (tests inject a fake).
|
|
438
299
|
*
|
|
439
|
-
* @param {Function} execImpl
|
|
440
|
-
* @param {object} [defaultExecOpts] —
|
|
441
|
-
* wrapper's invocation (e.g. `{ timeoutMs: 60_000 }`). Per-call options
|
|
442
|
-
* override the defaults via spread order. Story #2860.
|
|
300
|
+
* @param {Function} execImpl
|
|
301
|
+
* @param {object} [defaultExecOpts] — per-call options win.
|
|
443
302
|
*/
|
|
444
303
|
export function createGh(execImpl = exec, defaultExecOpts = {}) {
|
|
445
|
-
// Wrap execImpl so every wrapper inherits defaultExecOpts (e.g. timeoutMs)
|
|
446
|
-
// without having to thread the option through each callsite. Per-call opts
|
|
447
|
-
// win because they spread after the defaults. Story #2860.
|
|
448
304
|
const execWithDefaults = (opts) => execImpl({ ...defaultExecOpts, ...opts });
|
|
449
305
|
/**
|
|
450
|
-
* `gh api` wrapper.
|
|
451
|
-
*
|
|
452
306
|
* @param {object} opts
|
|
453
|
-
* @param {string} [opts.method='GET']
|
|
454
|
-
* @param {string} opts.endpoint
|
|
455
|
-
* @param {object} [opts.body]
|
|
456
|
-
* @param {string[]} [opts.fields]
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
* `--jq .${fields.join(',.')}` only when
|
|
460
|
-
* set. Most callers will leave it unset
|
|
461
|
-
* and pass `endpoint` directly.
|
|
462
|
-
* @param {boolean} [opts.paginate] Add --paginate for list endpoints.
|
|
463
|
-
* @param {object} [opts.execOpts] Forwarded to exec (timeoutMs, etc.).
|
|
307
|
+
* @param {string} [opts.method='GET']
|
|
308
|
+
* @param {string} opts.endpoint
|
|
309
|
+
* @param {object} [opts.body] Written to stdin via --input -.
|
|
310
|
+
* @param {string[]} [opts.fields] Projected as `--jq .a,.b`.
|
|
311
|
+
* @param {boolean} [opts.paginate]
|
|
312
|
+
* @param {object} [opts.execOpts]
|
|
464
313
|
*/
|
|
465
314
|
function api({
|
|
466
315
|
method = 'GET',
|
|
@@ -488,19 +337,11 @@ export function createGh(execImpl = exec, defaultExecOpts = {}) {
|
|
|
488
337
|
return execWithDefaults({ args, input, ...execOpts });
|
|
489
338
|
}
|
|
490
339
|
|
|
491
|
-
/**
|
|
492
|
-
* Build a `--json a,b,c` flag pair from a fields array. Returns `[]` when
|
|
493
|
-
* fields is unset so callers can spread without branching.
|
|
494
|
-
*/
|
|
495
340
|
function jsonFlag(fields) {
|
|
496
341
|
if (!Array.isArray(fields) || fields.length === 0) return [];
|
|
497
342
|
return ['--json', fields.join(',')];
|
|
498
343
|
}
|
|
499
344
|
|
|
500
|
-
/**
|
|
501
|
-
* Coerce numeric ids to strings — gh accepts both but tests assert on
|
|
502
|
-
* stringly args.
|
|
503
|
-
*/
|
|
504
345
|
function idStr(id) {
|
|
505
346
|
return typeof id === 'number' ? String(id) : id;
|
|
506
347
|
}
|
|
@@ -534,12 +375,7 @@ export function createGh(execImpl = exec, defaultExecOpts = {}) {
|
|
|
534
375
|
execWithDefaults({ args: ['pr', 'edit', idStr(id), ...flags] }),
|
|
535
376
|
merge: (id, flags = []) =>
|
|
536
377
|
execWithDefaults({ args: ['pr', 'merge', idStr(id), ...flags] }),
|
|
537
|
-
/**
|
|
538
|
-
* Bring a `mergeStateStatus: BEHIND` PR up to date with its base
|
|
539
|
-
* (Story #4543). The close-and-land merge wait calls this a bounded
|
|
540
|
-
* number of times rather than waiting out its budget behind a base it
|
|
541
|
-
* could have caught up to.
|
|
542
|
-
*/
|
|
378
|
+
/** Bring a `mergeStateStatus: BEHIND` PR up to date with its base. */
|
|
543
379
|
updateBranch: (id, flags = []) =>
|
|
544
380
|
execWithDefaults({ args: ['pr', 'update-branch', idStr(id), ...flags] }),
|
|
545
381
|
list: (flags = [], fields) =>
|
|
@@ -574,31 +410,15 @@ export function createGh(execImpl = exec, defaultExecOpts = {}) {
|
|
|
574
410
|
},
|
|
575
411
|
};
|
|
576
412
|
|
|
577
|
-
// Expose the resolved defaults so callers (and tests) can introspect what
|
|
578
|
-
// ceiling the facade enforces. Frozen to discourage post-construction
|
|
579
|
-
// mutation. Story #2860.
|
|
580
413
|
const defaults = Object.freeze({ ...defaultExecOpts });
|
|
581
414
|
return { api, issue, pr, label, repo, defaults };
|
|
582
415
|
}
|
|
583
416
|
|
|
584
|
-
/**
|
|
585
|
-
* Module-level singleton bound to the real `exec`. Production callers
|
|
586
|
-
* import this; tests reach for `createGh(fakeExec)` instead.
|
|
587
|
-
*/
|
|
588
417
|
export const gh = createGh();
|
|
589
418
|
|
|
590
|
-
/* ---------------------------------------------------------------------- */
|
|
591
|
-
/* GraphQL reachability preflight (Story #5355) */
|
|
592
|
-
/* ---------------------------------------------------------------------- */
|
|
593
|
-
|
|
594
419
|
/**
|
|
595
|
-
*
|
|
596
|
-
* surface
|
|
597
|
-
* GraphQL API, so they stand or fall together: where GraphQL answers HTTP
|
|
598
|
-
* 403 there is no PR operation left to attempt, not a degraded subset.
|
|
599
|
-
*
|
|
600
|
-
* Kept beside the `pr` facade it enumerates, and module-private, so the
|
|
601
|
-
* refusal text below cannot drift from the surface it claims to describe.
|
|
420
|
+
* `gh` routes every one of these through GraphQL, so a GraphQL 403 gates the
|
|
421
|
+
* whole PR surface. Kept beside `pr` so the refusal text cannot drift.
|
|
602
422
|
*/
|
|
603
423
|
const GH_PR_SUBCOMMANDS = Object.freeze([
|
|
604
424
|
'view',
|
|
@@ -609,39 +429,17 @@ const GH_PR_SUBCOMMANDS = Object.freeze([
|
|
|
609
429
|
'list',
|
|
610
430
|
]);
|
|
611
431
|
|
|
612
|
-
/**
|
|
613
|
-
* The cheapest authenticated GraphQL read there is — "who am I". It touches
|
|
614
|
-
* no repository, needs no scope beyond the one `gh` already has, and costs a
|
|
615
|
-
* single API read, which is the whole budget the preflight is allowed.
|
|
616
|
-
*/
|
|
432
|
+
/** Cheapest authenticated GraphQL read: no repo, no extra scope. */
|
|
617
433
|
const GRAPHQL_PROBE_QUERY = 'query{viewer{login}}';
|
|
618
434
|
|
|
619
|
-
/** Wall-clock ceiling for the probe. A hung probe must never hold a close. */
|
|
620
435
|
const GRAPHQL_PROBE_TIMEOUT_MS = 15_000;
|
|
621
436
|
|
|
622
437
|
/**
|
|
623
|
-
*
|
|
624
|
-
*
|
|
625
|
-
*
|
|
626
|
-
* The fall-through is deliberate and it is **fail-open**: a timeout, a DNS
|
|
627
|
-
* blip or a novel `gh` error is not evidence that this session cannot reach
|
|
628
|
-
* GraphQL, and blocking a healthy close on an ambiguous probe would trade a
|
|
629
|
-
* rare late failure for a common early one. Such a probe reports `available`
|
|
630
|
-
* with `reason: 'probe-inconclusive'`, so the log still shows it happened.
|
|
631
|
-
*
|
|
632
|
-
* A **rate limit is that same fail-open case wearing a 403** (Story #5362).
|
|
633
|
-
* GitHub answers both its primary and its secondary rate limits with HTTP
|
|
634
|
-
* 403, and a throttled session says nothing about whether GraphQL is
|
|
635
|
-
* reachable from here — so the rate-limit test runs *before* the bare status
|
|
636
|
-
* match, and it accepts either shape the evidence arrives in: the typed
|
|
637
|
-
* {@link GhRateLimitError} the shared classifier already produces, or
|
|
638
|
-
* rate-limit text riding on an otherwise untyped 403. Classifying it
|
|
639
|
-
* `unavailable` would block the Story behind a remedy that cannot work —
|
|
640
|
-
* "re-run from a local session" is an instruction to go reproduce the same
|
|
641
|
-
* throttle. A 403 with no rate-limit evidence is still the web-session shape
|
|
642
|
-
* this preflight was built for and still refuses.
|
|
438
|
+
* Fail-open: an ambiguous error reports `available`. A rate limit also
|
|
439
|
+
* arrives as a 403 but says nothing about reachability, so it is matched
|
|
440
|
+
* before the bare 403.
|
|
643
441
|
*
|
|
644
|
-
* @param {unknown} err
|
|
442
|
+
* @param {unknown} err
|
|
645
443
|
* @returns {{ verdict: 'available'|'unavailable'|'auth-failed', reason: string }}
|
|
646
444
|
*/
|
|
647
445
|
function classifyGraphqlProbeFailure(err) {
|
|
@@ -663,29 +461,11 @@ function classifyGraphqlProbeFailure(err) {
|
|
|
663
461
|
}
|
|
664
462
|
|
|
665
463
|
/**
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
*
|
|
670
|
-
* - `available` — GraphQL answered (or the probe failed in a way that
|
|
671
|
-
* says nothing about reachability — an ambiguous error
|
|
672
|
-
* or a rate limit; see the fail-open note on
|
|
673
|
-
* {@link classifyGraphqlProbeFailure}).
|
|
674
|
-
* - `unavailable` — GraphQL answered HTTP 403. This is the Claude Code
|
|
675
|
-
* web-session shape: the token is fine, the endpoint
|
|
676
|
-
* is simply not reachable from here, so the entire
|
|
677
|
-
* `gh pr` surface is gated.
|
|
678
|
-
* - `auth-failed` — `gh` has no usable token (missing, expired or
|
|
679
|
-
* under-scoped). A different fault with a different
|
|
680
|
-
* remedy, deliberately NOT flattened into the one
|
|
681
|
-
* above: telling an unauthenticated operator to "run
|
|
682
|
-
* this somewhere else" sends them to reproduce it.
|
|
683
|
-
*
|
|
684
|
-
* Never throws — a preflight that can fail a close is worse than no
|
|
685
|
-
* preflight at all.
|
|
464
|
+
* Is GraphQL reachable from this session? `unavailable` is the web-session
|
|
465
|
+
* 403 shape; `auth-failed` has a different remedy and is kept distinct.
|
|
466
|
+
* Never throws.
|
|
686
467
|
*
|
|
687
468
|
* @param {{ ghFacade?: { api: Function } }} [opts]
|
|
688
|
-
* `ghFacade` is the injection seam; production passes nothing.
|
|
689
469
|
* @returns {Promise<{ verdict: string, available: boolean, reason: string,
|
|
690
470
|
* detail: string|null }>}
|
|
691
471
|
*/
|
|
@@ -715,14 +495,6 @@ export async function probeGraphqlAvailability({ ghFacade = gh } = {}) {
|
|
|
715
495
|
}
|
|
716
496
|
|
|
717
497
|
/**
|
|
718
|
-
* Render a refusing probe verdict as the operator-facing blocker.
|
|
719
|
-
*
|
|
720
|
-
* The two refusals get two messages because they have two remedies. The
|
|
721
|
-
* unavailable text names all three things the operator needs — that GraphQL
|
|
722
|
-
* is unavailable *in this session*, the whole `gh pr` surface that gates, and
|
|
723
|
-
* that the fix is to run the close from a local session rather than to retry
|
|
724
|
-
* here.
|
|
725
|
-
*
|
|
726
498
|
* @param {{ verdict?: string, detail?: string|null }} probe
|
|
727
499
|
* @returns {string}
|
|
728
500
|
*/
|
|
@@ -1,38 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* cached-fetch.js — coalesce redundant `git fetch origin <ref>` calls
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* fetches the same epic ref before creating its worktree. The fetches are
|
|
6
|
-
* idempotent w.r.t. the local refs but cost wall-clock and contend on
|
|
7
|
-
* `packed-refs.lock`. This module caches successful fetches by
|
|
8
|
-
* `(cwd, ref)` for a configurable window (default 30s) so subsequent
|
|
9
|
-
* callers within the window are no-ops.
|
|
10
|
-
*
|
|
11
|
-
* Two wrappers are exported because callers in the codebase split along a
|
|
12
|
-
* sync/async line:
|
|
13
|
-
* - `cachedGitFetch` — async, wraps `gitFetchWithRetry` (used by
|
|
14
|
-
* story-init's `bootstrapWorktree`).
|
|
15
|
-
* - `cachedGitFetchSync` — sync, wraps a `gitSpawn(cwd, 'fetch', ref)`
|
|
16
|
-
* style call (used by `projectMaintainabilityRegressions` in
|
|
17
|
-
* close-validation).
|
|
18
|
-
*
|
|
19
|
-
* Both share the same underlying cache state, so a fetch issued by
|
|
20
|
-
* story-init satisfies a later sync caller (and vice versa) inside the
|
|
21
|
-
* window.
|
|
22
|
-
*
|
|
23
|
-
* The cache lives at module scope — invocations within one Node process
|
|
24
|
-
* (one wave-runner) see the same state. Callers that need an isolated
|
|
25
|
-
* cache (mostly tests) can construct a `FetchCache` directly.
|
|
2
|
+
* cached-fetch.js — coalesce redundant `git fetch origin <ref>` calls (they
|
|
3
|
+
* contend on `packed-refs.lock`) by caching successes per `(cwd, ref)` for a
|
|
4
|
+
* window; the async and sync wrappers share one cache.
|
|
26
5
|
*/
|
|
27
6
|
|
|
28
7
|
import { gitFetchWithRetry as defaultGitFetchWithRetry } from '../git-utils.js';
|
|
29
8
|
|
|
30
9
|
const DEFAULT_WINDOW_MS = 30_000;
|
|
31
10
|
|
|
32
|
-
/**
|
|
33
|
-
* Pure-ish cache state keyed by `(cwd, ref)`. Exposed so tests can build
|
|
34
|
-
* fresh instances without poking module globals.
|
|
35
|
-
*/
|
|
11
|
+
/** Cache state keyed by `(cwd, ref)`; constructible for isolated tests. */
|
|
36
12
|
export class FetchCache {
|
|
37
13
|
constructor({ now = () => Date.now() } = {}) {
|
|
38
14
|
/** @type {Map<string, number>} */
|
|
@@ -44,11 +20,6 @@ export class FetchCache {
|
|
|
44
20
|
return `${cwd}\u0000${ref}`;
|
|
45
21
|
}
|
|
46
22
|
|
|
47
|
-
/**
|
|
48
|
-
* Return true when a fetch for `(cwd, ref)` is needed because either no
|
|
49
|
-
* fetch has been recorded yet, or the recorded one is older than
|
|
50
|
-
* `windowMs`.
|
|
51
|
-
*/
|
|
52
23
|
shouldFetch(cwd, ref, windowMs = DEFAULT_WINDOW_MS) {
|
|
53
24
|
const key = FetchCache._key(cwd, ref);
|
|
54
25
|
const last = this._lastFetchAt.get(key);
|
|
@@ -56,17 +27,14 @@ export class FetchCache {
|
|
|
56
27
|
return this._now() - last >= windowMs;
|
|
57
28
|
}
|
|
58
29
|
|
|
59
|
-
/** Record that a fetch for `(cwd, ref)` just succeeded. */
|
|
60
30
|
recordFetch(cwd, ref) {
|
|
61
31
|
this._lastFetchAt.set(FetchCache._key(cwd, ref), this._now());
|
|
62
32
|
}
|
|
63
33
|
|
|
64
|
-
/** Test seam: drop all cached entries. */
|
|
65
34
|
reset() {
|
|
66
35
|
this._lastFetchAt.clear();
|
|
67
36
|
}
|
|
68
37
|
|
|
69
|
-
/** Diagnostics: number of cached `(cwd, ref)` entries. */
|
|
70
38
|
size() {
|
|
71
39
|
return this._lastFetchAt.size;
|
|
72
40
|
}
|
|
@@ -74,28 +42,22 @@ export class FetchCache {
|
|
|
74
42
|
|
|
75
43
|
const moduleCache = new FetchCache();
|
|
76
44
|
|
|
77
|
-
/**
|
|
78
|
-
* Reset the module-level cache. Test-only — production code should never
|
|
79
|
-
* call this.
|
|
80
|
-
*/
|
|
45
|
+
/** Test-only. */
|
|
81
46
|
export function __resetModuleCache() {
|
|
82
47
|
moduleCache.reset();
|
|
83
48
|
}
|
|
84
49
|
|
|
85
|
-
/** Test
|
|
50
|
+
/** Test-only. */
|
|
86
51
|
export function __moduleCacheSize() {
|
|
87
52
|
return moduleCache.size();
|
|
88
53
|
}
|
|
89
54
|
|
|
90
55
|
/**
|
|
91
|
-
* Async fetch with `(cwd, ref, windowMs)` caching.
|
|
92
|
-
*
|
|
93
56
|
* @param {string} cwd
|
|
94
|
-
* @param {string} ref
|
|
95
|
-
* Pass `'origin'` (no second arg) by using ref=''.
|
|
57
|
+
* @param {string} ref `''` fetches without a ref.
|
|
96
58
|
* @param {object} [opts]
|
|
97
59
|
* @param {number} [opts.windowMs=30000]
|
|
98
|
-
* @param {FetchCache} [opts.cache]
|
|
60
|
+
* @param {FetchCache} [opts.cache]
|
|
99
61
|
* @param {typeof defaultGitFetchWithRetry} [opts.fetchFn]
|
|
100
62
|
* @returns {Promise<{ status: 0, cached: true, attempts: 0 } | { status: number, stdout: string, stderr: string, attempts: number, cached: false }>}
|
|
101
63
|
*/
|
|
@@ -120,13 +82,8 @@ export async function cachedGitFetch(
|
|
|
120
82
|
}
|
|
121
83
|
|
|
122
84
|
/**
|
|
123
|
-
* Sync fetch with `(cwd, ref, windowMs)` caching. Wraps a `gitSpawn`-style
|
|
124
|
-
* synchronous fetch (used by `close-validation`'s MI projection helper,
|
|
125
|
-
* which must stay synchronous).
|
|
126
|
-
*
|
|
127
85
|
* @param {string} cwd
|
|
128
|
-
* @param {string} ref
|
|
129
|
-
* always passes an explicit epic branch ref.
|
|
86
|
+
* @param {string} ref
|
|
130
87
|
* @param {object} opts
|
|
131
88
|
* @param {(cwd: string, ...args: string[]) => { status: number, stdout: string, stderr: string }} opts.gitSpawn
|
|
132
89
|
* @param {number} [opts.windowMs=30000]
|