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,51 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GitHub Provider —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* helper translates those slug-to-issueNumber pairs into native GitHub
|
|
7
|
-
* "blocked by" dependency edges so maintainers can see blocking
|
|
8
|
-
* relationships directly in the GitHub UI.
|
|
9
|
-
*
|
|
10
|
-
* API surface used:
|
|
11
|
-
* Read: GET /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by
|
|
12
|
-
* Write: POST /repos/{owner}/{repo}/issues/{issue_number}/dependencies/blocked_by
|
|
13
|
-
* body: { "issue_id": <integer db id of the blocking issue> }
|
|
14
|
-
*
|
|
15
|
-
* Contract:
|
|
16
|
-
* - **Idempotent** — reads existing edges first; only POSTs missing ones.
|
|
17
|
-
* - **Non-fatal** — catches all errors per edge, warns, and continues.
|
|
18
|
-
* The overall function never throws; errors are returned in a summary.
|
|
19
|
-
* - **No-op on empty input** — returns immediately when no depends_on
|
|
20
|
-
* edges are present or the slug→issueNumber map is empty.
|
|
2
|
+
* GitHub Provider — writes Story `depends_on` slugs as native "blocked by"
|
|
3
|
+
* edges (`POST .../dependencies/blocked_by` with the blocker's db id).
|
|
4
|
+
* Idempotent (reads existing edges first) and non-fatal: errors are counted
|
|
5
|
+
* in the summary, never thrown.
|
|
21
6
|
*/
|
|
22
7
|
|
|
23
8
|
import { Logger } from '../../lib/Logger.js';
|
|
24
9
|
import { concurrentMap } from '../../lib/util/concurrent-map.js';
|
|
25
10
|
import { paginateRest } from './request-helpers.js';
|
|
26
11
|
|
|
27
|
-
/**
|
|
28
|
-
* Bounded concurrency for the GitHub dependency-edge round-trips. Kept modest
|
|
29
|
-
* to respect GitHub's secondary rate limits while still collapsing the wall-
|
|
30
|
-
* clock latency from `sum(round-trips)` toward `sum(round-trips) / concurrency`.
|
|
31
|
-
*/
|
|
12
|
+
/** Modest, to stay clear of GitHub's secondary rate limits. */
|
|
32
13
|
const EDGE_CONCURRENCY = 5;
|
|
33
14
|
|
|
34
15
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* Reading only the first page therefore made the writer non-idempotent past
|
|
40
|
-
* the page boundary — every edge beyond it looked missing on every run
|
|
41
|
-
* (Story #5046). `paginateRest` walks the pages and carries the shared
|
|
42
|
-
* transient-retry and page-cap guards.
|
|
43
|
-
*
|
|
44
|
-
* Returns `[]` on any error so the caller falls back to posting the full
|
|
45
|
-
* set of missing edges (worst case: a duplicate POST, which GitHub
|
|
46
|
-
* handles idempotently). That non-fatal contract is deliberate and is the
|
|
47
|
-
* inverse of the READ path in `lib/orchestration/resolve-stories.js`: a lost
|
|
48
|
-
* write-side edge is cosmetic, a lost read-side edge removes a dispatch gate.
|
|
16
|
+
* Existing blocker db ids, paginated to exhaustion — this read is the
|
|
17
|
+
* idempotency check, so an unseen page means re-POSTed edges. Returns `[]` on
|
|
18
|
+
* error (worst case a duplicate POST): a lost write-side edge is cosmetic,
|
|
19
|
+
* unlike the read path in `resolve-stories.js`, where it drops a gate.
|
|
49
20
|
*
|
|
50
21
|
* @param {{ gh: object, owner: string, repo: string, issueNumber: number, paginate?: Function }} opts
|
|
51
22
|
* @returns {Promise<number[]>} Database ids of the issues that currently block `issueNumber`.
|
|
@@ -74,11 +45,7 @@ async function fetchExistingBlockedBy({
|
|
|
74
45
|
}
|
|
75
46
|
|
|
76
47
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* For each entry in `blockerInternalIds`, checks whether the edge already
|
|
80
|
-
* exists and POSTs only the missing ones. Every individual POST failure is
|
|
81
|
-
* caught, logged as a warning, and counted — the function never throws.
|
|
48
|
+
* POST only the missing edges for one issue; never throws.
|
|
82
49
|
*
|
|
83
50
|
* @param {{
|
|
84
51
|
* gh: object,
|
|
@@ -108,9 +75,7 @@ async function addBlockedByEdges({
|
|
|
108
75
|
});
|
|
109
76
|
const existingSet = new Set(existing);
|
|
110
77
|
|
|
111
|
-
// Partition
|
|
112
|
-
// concurrent POST dispatch order, then POST only the missing edges in
|
|
113
|
-
// parallel under a modest cap.
|
|
78
|
+
// Partition first so the skip count doesn't depend on POST ordering.
|
|
114
79
|
const missing = blockerInternalIds.filter((id) => !existingSet.has(id));
|
|
115
80
|
const skipped = blockerInternalIds.length - missing.length;
|
|
116
81
|
|
|
@@ -145,16 +110,8 @@ async function addBlockedByEdges({
|
|
|
145
110
|
}
|
|
146
111
|
|
|
147
112
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* state and a `getTicket` hook to resolve database ids.
|
|
151
|
-
*
|
|
152
|
-
* Iterates every Story that has a non-empty `dependsOn` array; for each
|
|
153
|
-
* depended-on slug, resolves the blocker's issue number (via the slug map),
|
|
154
|
-
* then resolves the blocker's database id via `getTicket`, and calls
|
|
155
|
-
* `addBlockedByEdges`. Any failure at any step is caught, logged as a
|
|
156
|
-
* warning, and reflected in the returned summary — the function never
|
|
157
|
-
* throws.
|
|
113
|
+
* For each Story's `dependsOn` slugs, resolve blocker issue number (slug map)
|
|
114
|
+
* then db id (`getTicket`), and add the edges. Never throws.
|
|
158
115
|
*
|
|
159
116
|
* @param {{
|
|
160
117
|
* stories: Array<{ slug: string, dependsOn?: string[] }>,
|
|
@@ -184,11 +141,7 @@ export async function applyBlockedByDependencies({
|
|
|
184
141
|
let edgesFailed = 0;
|
|
185
142
|
let storiesProcessed = 0;
|
|
186
143
|
|
|
187
|
-
//
|
|
188
|
-
// so the per-story round-trips overlap. Each mapper returns its own counter
|
|
189
|
-
// contribution; we sum them after the pass. The bodies swallow their own
|
|
190
|
-
// errors (per-edge try/catch + the non-fatal contract), so concurrentMap
|
|
191
|
-
// never sees a rejection and the no-throw guarantee is preserved.
|
|
144
|
+
// Mappers swallow their own errors, so concurrentMap never rejects.
|
|
192
145
|
const perStory = await concurrentMap(
|
|
193
146
|
stories,
|
|
194
147
|
async (story) => {
|
|
@@ -1,30 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GitHub Provider —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `createIssue` — which backs `/mandrel-plan` persist and the `/mandrel-plan`
|
|
7
|
-
* Phase 4 Epic open) must land on the configured Projects V2 board
|
|
8
|
-
* without relying on GitHub's "Auto-add to project" built-in workflow,
|
|
9
|
-
* which is off by default on fresh boards and cannot be enabled via API.
|
|
10
|
-
*
|
|
11
|
-
* Contract:
|
|
12
|
-
* - **No-op when no project number resolves** — returns
|
|
13
|
-
* `{ added: false, reason: 'no-project-number' }` without touching
|
|
14
|
-
* the network.
|
|
15
|
-
* - **Non-fatal** — a failed add warns and returns
|
|
16
|
-
* `{ added: false, reason: 'error' }`; it never throws, so issue
|
|
17
|
-
* creation always survives a board hiccup.
|
|
18
|
-
* - **Idempotent** — the underlying `addProjectV2ItemById` mutation
|
|
19
|
-
* returns the existing item when the issue is already on the board,
|
|
20
|
-
* so re-running the helper is safe.
|
|
2
|
+
* GitHub Provider — post-create "add issue to the Projects V2 board" step.
|
|
3
|
+
* Needed because GitHub's auto-add workflow is off on fresh boards and can't
|
|
4
|
+
* be enabled via API. Never throws (issue creation survives a board failure)
|
|
5
|
+
* and is idempotent (the mutation returns an existing item).
|
|
21
6
|
*/
|
|
22
7
|
|
|
23
8
|
import { Logger } from '../../lib/Logger.js';
|
|
24
9
|
|
|
25
10
|
/**
|
|
26
|
-
*
|
|
27
|
-
* board.
|
|
11
|
+
* No project number → no-op without network.
|
|
28
12
|
*
|
|
29
13
|
* @param {{
|
|
30
14
|
* nodeId: string|null|undefined,
|
|
@@ -1,33 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GitHub Provider — BranchProtectionGateway
|
|
3
|
-
*
|
|
4
|
-
* Owns `getBranchProtection` / `setBranchProtection` against
|
|
5
|
-
* `/repos/{owner}/{repo}/branches/{branch}/protection`. Also exports the
|
|
6
|
-
* shared `isNotFoundError` predicate that `branchExists` reuses on the
|
|
7
|
-
* parent provider — keeping the 404-classification logic single-sourced.
|
|
8
|
-
*
|
|
9
|
-
* Extracted from `../github.js` in Story #2462 / Task #2478. Public
|
|
10
|
-
* surface on `GitHubProvider` is unchanged — both branch-protection
|
|
11
|
-
* methods delegate here.
|
|
12
|
-
*
|
|
13
|
-
* @see Story #2462 — Split GitHubProvider god class into seven composed gateways.
|
|
2
|
+
* GitHub Provider — BranchProtectionGateway, plus the shared
|
|
3
|
+
* `isNotFoundError` predicate.
|
|
14
4
|
*/
|
|
15
5
|
|
|
16
6
|
import { withTransientRetry } from './errors.js';
|
|
17
7
|
import { parseApiJson } from './request-helpers.js';
|
|
18
8
|
|
|
19
9
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* - `gh-exec`-classified errors land as `GhNotFoundError`
|
|
23
|
-
* (`err.name === 'GhNotFoundError'`); the underlying stderr may carry
|
|
24
|
-
* "HTTP 404" / "not found" / "Resource not accessible".
|
|
25
|
-
* - The legacy `GithubHttpClient` produced `Error('... failed (404): ...')`
|
|
26
|
-
* strings; some tests still throw those (and submodules that still
|
|
27
|
-
* delegate to the old transport do too).
|
|
28
|
-
*
|
|
29
|
-
* Used by `getBranchProtection` (distinguishes "no rule exists" from
|
|
30
|
-
* transport failures) and `branchExists` on the parent provider.
|
|
10
|
+
* 404 across `GhNotFoundError`, `HTTP 404`/"not found" stderr, and the
|
|
11
|
+
* legacy `failed (404)` message shape some callers still throw.
|
|
31
12
|
*/
|
|
32
13
|
export function isNotFoundError(err) {
|
|
33
14
|
if (!err) return false;
|
|
@@ -39,7 +20,6 @@ export function isNotFoundError(err) {
|
|
|
39
20
|
/HTTP 404/i.test(stderr) ||
|
|
40
21
|
/HTTP 404/i.test(message) ||
|
|
41
22
|
/\bnot found\b/i.test(stderr) ||
|
|
42
|
-
// gh-exec carries the failing code on err.code for the test mock path.
|
|
43
23
|
err?.code === 404
|
|
44
24
|
);
|
|
45
25
|
}
|
|
@@ -55,9 +35,8 @@ export class BranchProtectionGateway {
|
|
|
55
35
|
}
|
|
56
36
|
|
|
57
37
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* "intentionally unprotected" from "transport failure."
|
|
38
|
+
* 404 → `{ enabled: false }`; other errors propagate so "unprotected" and
|
|
39
|
+
* "transport failure" stay distinct.
|
|
61
40
|
*
|
|
62
41
|
* @field-manifest GET /repos/{owner}/{repo}/branches/{branch}/protection:
|
|
63
42
|
* required_status_checks, enforce_admins,
|
|
@@ -78,12 +57,9 @@ export class BranchProtectionGateway {
|
|
|
78
57
|
}
|
|
79
58
|
|
|
80
59
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* (`enforceAdmins`, `requiredApprovingReviewCount`) so the consumer-
|
|
85
|
-
* facing bootstrap can promote the framework's hands-off-pipeline
|
|
86
|
-
* stance without silently flipping operator-tuned values.
|
|
60
|
+
* Create or merge protection. `contexts` are added, never removed; other
|
|
61
|
+
* operator-tuned values are kept unless `enforceAdmins` /
|
|
62
|
+
* `requiredApprovingReviewCount` explicitly override them.
|
|
87
63
|
*
|
|
88
64
|
* Returns `{ created, added, existing }`.
|
|
89
65
|
*
|
|
@@ -109,9 +85,6 @@ export class BranchProtectionGateway {
|
|
|
109
85
|
? (current.raw?.required_status_checks?.contexts ?? [])
|
|
110
86
|
: [];
|
|
111
87
|
|
|
112
|
-
// Additive merge: keep every context the operator already configured
|
|
113
|
-
// and append only those the prGate suite contributes that are not yet
|
|
114
|
-
// present.
|
|
115
88
|
const merged = [...existingContexts];
|
|
116
89
|
const added = [];
|
|
117
90
|
for (const ctx of contexts) {
|
|
@@ -121,9 +94,6 @@ export class BranchProtectionGateway {
|
|
|
121
94
|
}
|
|
122
95
|
}
|
|
123
96
|
|
|
124
|
-
// Decide whether to override behaviour-shifting fields. Explicit
|
|
125
|
-
// `undefined` from legacy callers falls through to the operator's
|
|
126
|
-
// existing values (or the create-from-scratch defaults).
|
|
127
97
|
const overrideEnforceAdmins = typeof opts?.enforceAdmins === 'boolean';
|
|
128
98
|
const overrideApprovalCount =
|
|
129
99
|
typeof opts?.requiredApprovingReviewCount === 'number';
|
|
@@ -139,8 +109,7 @@ export class BranchProtectionGateway {
|
|
|
139
109
|
|
|
140
110
|
let prReviews;
|
|
141
111
|
if (overrideApprovalCount) {
|
|
142
|
-
//
|
|
143
|
-
// etc.) — only the count is promoted.
|
|
112
|
+
// Keep operator review flags; only the count is promoted.
|
|
144
113
|
const baseReviews = current.enabled
|
|
145
114
|
? (current.raw?.required_pull_request_reviews ?? {})
|
|
146
115
|
: {};
|
|
@@ -154,8 +123,7 @@ export class BranchProtectionGateway {
|
|
|
154
123
|
: null;
|
|
155
124
|
}
|
|
156
125
|
|
|
157
|
-
// PUT requires every top-level field
|
|
158
|
-
// section.
|
|
126
|
+
// PUT requires every top-level field; null disables a section.
|
|
159
127
|
const body = current.enabled
|
|
160
128
|
? {
|
|
161
129
|
required_status_checks: {
|
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GitHub Provider — per-instance ticket cache.
|
|
3
|
-
*
|
|
4
|
-
* One bare `Map<id, { ticket, insertedAt }>` scoped to the lifetime of a
|
|
5
|
-
* single `GitHubProvider`, shared by dispatcher, reconciler, and cascade.
|
|
6
|
-
* The outer TTL wrapper is deliberately omitted because `peekFresh` already
|
|
7
|
-
* bounds entries by a caller-supplied `maxAgeMs`, and every other reader
|
|
8
|
-
* trusts the ticket mutators (`updateTicket` / `postComment`) to call
|
|
9
|
-
* `invalidate` explicitly.
|
|
10
|
-
*
|
|
11
|
-
* Surface is intentionally narrow: only the methods the provider itself
|
|
12
|
-
* reaches for live here (`has` / `peek` / `peekFresh` / `set` /
|
|
13
|
-
* `primeIfAbsent` / `primeMany` / `invalidate`).
|
|
14
|
-
*
|
|
15
|
-
* Extracted from `../github.js` in Story #1846 / Task #1858.
|
|
2
|
+
* GitHub Provider — per-instance ticket cache. No TTL: `peekFresh` bounds age
|
|
3
|
+
* per call, and mutators invalidate explicitly.
|
|
16
4
|
*
|
|
17
5
|
* @param {{ now?: () => number }} [opts]
|
|
18
6
|
* @returns {{
|
|
@@ -1,30 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GitHub Provider — CommentGateway.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* `postComment` is the structured-comment writer (it prepends the visible
|
|
6
|
-
* type-badge); the `<!-- ap:structured-comment ... -->` marker is added by
|
|
7
|
-
* the upstream `upsertStructuredComment` ticketing helper before the body
|
|
8
|
-
* lands here.
|
|
9
|
-
*
|
|
10
|
-
* Extracted from `../github.js` in Story #2462 / Task #2480. `postComment`,
|
|
11
|
-
* `getTicketComments`, and `deleteComment` on `GitHubProvider` all delegate
|
|
12
|
-
* here. Story #5008 dropped the repo-wide `getRecentComments` feed — the
|
|
13
|
-
* telemetry dashboard that read it was retired and nothing else polls a
|
|
14
|
-
* cross-issue comment stream.
|
|
15
|
-
*
|
|
16
|
-
* @see Story #2462 — Split GitHubProvider god class into seven composed gateways.
|
|
2
|
+
* GitHub Provider — CommentGateway: issue-comment CRUD. The structured
|
|
3
|
+
* marker is added upstream by `upsertStructuredComment`; this layer adds only
|
|
4
|
+
* the visible type badge.
|
|
17
5
|
*/
|
|
18
6
|
|
|
19
7
|
import { paginateRest, parseApiJson } from './request-helpers.js';
|
|
20
8
|
|
|
21
|
-
//
|
|
22
|
-
// `./github/comments.js`. The upstream `upsertStructuredComment` ticketing
|
|
23
|
-
// helper prepends the `<!-- ap:structured-comment ... -->` marker before
|
|
24
|
-
// the body reaches `postComment`; this badge is the visible header
|
|
25
|
-
// consumers (Slack notifier, dashboard) grep for. Keeping the emoji + bold
|
|
26
|
-
// marker stable is what makes the round-trip with structured-comment
|
|
27
|
-
// detection work across the rewrite.
|
|
9
|
+
// Visible headers downstream consumers grep for — keep them byte-stable.
|
|
28
10
|
const TYPE_BADGES = {
|
|
29
11
|
progress: '🔄 **Progress**',
|
|
30
12
|
friction: '⚠️ **Friction**',
|
|
@@ -48,10 +30,7 @@ export class CommentGateway {
|
|
|
48
30
|
}
|
|
49
31
|
|
|
50
32
|
/**
|
|
51
|
-
*
|
|
52
|
-
* `findStructuredComment` ticketing helper, which greps each comment
|
|
53
|
-
* body for the `<!-- ap:structured-comment type="..." -->` marker — so
|
|
54
|
-
* the per-comment `body` field must round-trip verbatim.
|
|
33
|
+
* `body` must round-trip verbatim: structured-comment lookup greps it.
|
|
55
34
|
*
|
|
56
35
|
* @field-manifest /repos/{owner}/{repo}/issues/{n}/comments:
|
|
57
36
|
* id, body, created_at, user
|
|
@@ -63,11 +42,6 @@ export class CommentGateway {
|
|
|
63
42
|
);
|
|
64
43
|
}
|
|
65
44
|
|
|
66
|
-
/**
|
|
67
|
-
* Delete a comment by id. Called by `upsertStructuredComment` before
|
|
68
|
-
* posting the replacement, so the in-place semantics hold even though
|
|
69
|
-
* the underlying GitHub API has no native upsert.
|
|
70
|
-
*/
|
|
71
45
|
async deleteComment(commentId) {
|
|
72
46
|
await this._gh.api({
|
|
73
47
|
method: 'DELETE',
|
|
@@ -76,13 +50,8 @@ export class CommentGateway {
|
|
|
76
50
|
}
|
|
77
51
|
|
|
78
52
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* see the same header the old client produced.
|
|
82
|
-
*
|
|
83
|
-
* Accepts either `{ body, type }` (canonical) or a bare string (legacy
|
|
84
|
-
* shape exercised by `tests/lib/github-provider.test.js` and a handful
|
|
85
|
-
* of direct callers under `notify.js`).
|
|
53
|
+
* Accepts `{ body, type }` or a bare string; a known `type` gets its badge
|
|
54
|
+
* prepended.
|
|
86
55
|
*
|
|
87
56
|
* @field-manifest POST /repos/{owner}/{repo}/issues/{n}/comments:
|
|
88
57
|
* id (returned for the caller's `commentId`)
|
|
@@ -99,8 +68,6 @@ export class CommentGateway {
|
|
|
99
68
|
body: { body },
|
|
100
69
|
});
|
|
101
70
|
const comment = parseApiJson(result);
|
|
102
|
-
// Posting a comment mutates the ticket's comment thread. Invalidate so
|
|
103
|
-
// the next `getTicketComments` / `getTicket` reflects the new comment.
|
|
104
71
|
if (typeof this._hooks.invalidateTicket === 'function') {
|
|
105
72
|
this._hooks.invalidateTicket(ticketId);
|
|
106
73
|
}
|
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GitHub Provider — gateway
|
|
3
|
-
*
|
|
4
|
-
* Pulled out of `../github.js` in Story #2462 / Task #2481 so the parent
|
|
5
|
-
* file can stay under the thin-composer LOC ceiling. This module owns the
|
|
6
|
-
* mechanical wiring: it builds each gateway, threads the hooks that
|
|
7
|
-
* cross-link them, and constructs the shared `_ctx` object the projects-v2
|
|
8
|
-
* shim reads from.
|
|
9
|
-
*
|
|
10
|
-
* The provider holds the public surface; this helper holds the wiring.
|
|
11
|
-
* Splitting the two keeps the composer file readable and reviewable as a
|
|
12
|
-
* delegation manifest rather than a constructor-shaped wall of new-up
|
|
13
|
-
* calls.
|
|
14
|
-
*
|
|
15
|
-
* @see Story #2462 — Split GitHubProvider god class into seven composed gateways.
|
|
2
|
+
* GitHub Provider — gateway wiring: builds each gateway, cross-links them
|
|
3
|
+
* via hooks, and builds the shared `_ctx` the projects-v2 shim reads.
|
|
16
4
|
*/
|
|
17
5
|
|
|
18
6
|
import { BranchProtectionGateway } from './branch-protection.js';
|
|
@@ -26,11 +14,7 @@ import * as projects from './projects-v2-graphql.js';
|
|
|
26
14
|
import { SubIssueGateway } from './sub-issues.js';
|
|
27
15
|
import { TicketGateway } from './tickets.js';
|
|
28
16
|
|
|
29
|
-
/**
|
|
30
|
-
* Wire every gateway onto `provider` and attach the shared `_ctx` object.
|
|
31
|
-
* Mutates the provider in place — the constructor passes `this` in and
|
|
32
|
-
* lets this helper own the wiring decisions.
|
|
33
|
-
*/
|
|
17
|
+
/** Mutates `provider` in place. */
|
|
34
18
|
export function composeGateways(provider) {
|
|
35
19
|
const p = provider;
|
|
36
20
|
const ghDeps = { gh: p._gh, owner: p.owner, repo: p.repo };
|
|
@@ -1,35 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GitHub Provider — error classifier
|
|
2
|
+
* GitHub Provider — error classifier, the shared transient-retry loop, and
|
|
3
|
+
* the sub-issues GraphQL shape.
|
|
3
4
|
*
|
|
4
|
-
* `classifyGithubError` buckets `
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* switch. Rate-limit detection wins over the 401/403 → permission rule
|
|
8
|
-
* because GitHub's secondary rate limit is delivered as HTTP 403 with a
|
|
9
|
-
* known message; if we bucketed it as 'permission' it would never be
|
|
10
|
-
* retried.
|
|
11
|
-
*
|
|
12
|
-
* `SUB_ISSUES_QUERY` is the GraphQL shape the sub-issues read path uses.
|
|
13
|
-
* Story #5008 removed the add/remove mutations with the write surface.
|
|
14
|
-
*
|
|
15
|
-
* Extracted from `../github.js` in Story #1846 / Task #1857.
|
|
5
|
+
* `classifyGithubError` buckets errors as `feature-disabled` / `permission` /
|
|
6
|
+
* `transient` / `permanent`. Transient rules run before the 401/403
|
|
7
|
+
* permission rule because a secondary rate limit arrives as HTTP 403.
|
|
16
8
|
*/
|
|
17
9
|
|
|
18
10
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* The bare `sub-issues` needle used to sit in this list and had to go: it
|
|
24
|
-
* matches the endpoint's own name, so any error that merely *mentions* the
|
|
25
|
-
* surface classified as `feature-disabled`. A secondary rate limit delivered
|
|
26
|
-
* as `HTTP 403: API rate limit exceeded while fetching sub-issues` is the live
|
|
27
|
-
* case — genuinely transient, but bucketed here it bypassed
|
|
28
|
-
* `withTransientRetry` entirely and the Epic rollup read the burst as "this
|
|
29
|
-
* repo has no sub-issues", degrading to the body checklist on a read that
|
|
30
|
-
* would have succeeded a second later. The narrower `subissues` spellings
|
|
31
|
-
* below still catch the real schema errors, because GraphQL names the field
|
|
32
|
-
* without the hyphen.
|
|
11
|
+
* Schema facts (absent field, disabled feature) no retry can change. Never
|
|
12
|
+
* add a bare `sub-issues` needle: it matches the endpoint name, so a rate
|
|
13
|
+
* limit "while fetching sub-issues" would skip retry; GraphQL spells the
|
|
14
|
+
* field without the hyphen.
|
|
33
15
|
*/
|
|
34
16
|
const FEATURE_DISABLED_MESSAGES = [
|
|
35
17
|
'feature not available',
|
|
@@ -37,9 +19,7 @@ const FEATURE_DISABLED_MESSAGES = [
|
|
|
37
19
|
"field 'subissues'",
|
|
38
20
|
'field "subissues"',
|
|
39
21
|
'subissues is not available',
|
|
40
|
-
//
|
|
41
|
-
// fetching sub-issues", which is what makes these safe to keep after the
|
|
42
|
-
// bare needle's removal.
|
|
22
|
+
// `<x> field` names the field, never the endpoint.
|
|
43
23
|
'subissues field',
|
|
44
24
|
'sub_issues field',
|
|
45
25
|
'sub-issues field',
|
|
@@ -69,27 +49,12 @@ const TRANSIENT_MESSAGES = [
|
|
|
69
49
|
|
|
70
50
|
const PERMISSION_MESSAGES = ['unauthorized', 'forbidden', 'permission'];
|
|
71
51
|
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
// path surfaces as `TypeError: fetch failed` with the real reason on
|
|
75
|
-
// `err.cause` (e.g. `ETIMEDOUT`, `ENOTFOUND`). Folded in from the former
|
|
76
|
-
// `transient-retry.js` predicate (Story #4298) so the single canonical
|
|
77
|
-
// classifier retries the **union** of transient HTTP statuses/codes AND
|
|
78
|
-
// transient network errors. The `\b50[234]\b` alternative also catches a
|
|
79
|
-
// bare 502/503/504 surfaced only in an error message string (no `.status`).
|
|
52
|
+
// Connectivity blips: gh-CLI puts Go HTTP errors on stderr; `fetch` puts the
|
|
53
|
+
// reason on `err.cause`. `\b50[234]\b` catches a status present only in text.
|
|
80
54
|
const TRANSIENT_NETWORK_RE =
|
|
81
55
|
/i\/o timeout|dial tcp|TLS handshake timeout|connection reset|connection refused|temporary failure|could not resolve host|no such host|network is unreachable|socket hang up|fetch failed|ConnectTimeoutError|UND_ERR_CONNECT_TIMEOUT|ETIMEDOUT|ECONNRESET|ECONNREFUSED|ENOTFOUND|EAI_AGAIN|\b50[234]\b/i;
|
|
82
56
|
|
|
83
|
-
/**
|
|
84
|
-
* True when an error looks like a retryable network/connectivity blip.
|
|
85
|
-
* Scans the union of fields both transport paths populate (`stderr`,
|
|
86
|
-
* `message`, `code`, and the nested `cause.message` / `cause.code` the
|
|
87
|
-
* `fetch` path uses). Module-private — folded in from the former
|
|
88
|
-
* `transient-retry.js` predicate (Story #4298) and consumed only by
|
|
89
|
-
* `classifyGithubError` below; its behavior is exercised through that public
|
|
90
|
-
* classifier rather than as a standalone export (keeps the dead-export gate
|
|
91
|
-
* green — nothing outside this module imports it).
|
|
92
|
-
*/
|
|
57
|
+
/** Scans stderr, message, code and `cause.*` from both transport paths. */
|
|
93
58
|
function isTransientNetworkError(err) {
|
|
94
59
|
const hay = [
|
|
95
60
|
err?.stderr,
|
|
@@ -112,11 +77,7 @@ function matchesAny(haystack, needles) {
|
|
|
112
77
|
const GH_STDERR_STATUS_RE = /\bHTTP (\d{3})\b/i;
|
|
113
78
|
|
|
114
79
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* Its own function so {@link extractErrorFields} keeps the cyclomatic weight it
|
|
118
|
-
* had before stderr became a classification input — the field is read twice
|
|
119
|
-
* there, and inlining the guard twice is what pushed the CRAP ratchet.
|
|
80
|
+
* Separate function to keep {@link extractErrorFields}'s complexity down.
|
|
120
81
|
*
|
|
121
82
|
* @param {unknown} err
|
|
122
83
|
* @returns {string}
|
|
@@ -126,13 +87,7 @@ function stderrText(err) {
|
|
|
126
87
|
}
|
|
127
88
|
|
|
128
89
|
/**
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
* The `fetch` transport sets `err.status`; the `gh` transport does not — it
|
|
132
|
-
* has only an exit code, and puts the status in the text it printed. Without
|
|
133
|
-
* this, every `gh`-path failure reached the status rules as `undefined` and a
|
|
134
|
-
* 403 or a 429 was indistinguishable from an unclassifiable error (Story
|
|
135
|
-
* #5210).
|
|
90
|
+
* The `gh` transport has no `err.status`, only the status printed on stderr.
|
|
136
91
|
*
|
|
137
92
|
* @param {unknown} stderr
|
|
138
93
|
* @returns {number|undefined}
|
|
@@ -144,19 +99,9 @@ function statusFromStderr(stderr) {
|
|
|
144
99
|
}
|
|
145
100
|
|
|
146
101
|
/**
|
|
147
|
-
*
|
|
148
|
-
* `gh
|
|
149
|
-
*
|
|
150
|
-
* objects, plain `{message,status,code}` bags, or non-Errors stringified into
|
|
151
|
-
* `String(err)`.
|
|
152
|
-
*
|
|
153
|
-
* `lower` is the message alone. `detail` is the message **plus** any captured
|
|
154
|
-
* `stderr`, and is what the keyword rules read: on the `gh` path the message
|
|
155
|
-
* is the classified summary (`gh-exec: gh exited with code 1`) and every
|
|
156
|
-
* actionable word — the status line, `secondary rate limit`, the missing
|
|
157
|
-
* GraphQL field — lives only on stderr. Matching the keyword lists against the
|
|
158
|
-
* message alone is what flattened a retryable 403 to `permanent` and let the
|
|
159
|
-
* Epic rollup treat a rate-limit burst as a settled answer (Story #5210).
|
|
102
|
+
* Pure. `detail` is message + stderr and is what keyword rules must read: on
|
|
103
|
+
* the `gh` path the message is only `gh exited with code 1` and every
|
|
104
|
+
* actionable word (status, rate limit, missing field) lives on stderr.
|
|
160
105
|
*/
|
|
161
106
|
export function extractErrorFields(err) {
|
|
162
107
|
const message = typeof err.message === 'string' ? err.message : String(err);
|
|
@@ -164,8 +109,6 @@ export function extractErrorFields(err) {
|
|
|
164
109
|
const lower = message.toLowerCase();
|
|
165
110
|
return {
|
|
166
111
|
lower,
|
|
167
|
-
// Unconditional concatenation: with no stderr this is the message plus a
|
|
168
|
-
// trailing space, which every `includes` rule below reads identically.
|
|
169
112
|
detail: `${lower} ${stderr.toLowerCase()}`,
|
|
170
113
|
status:
|
|
171
114
|
typeof err.status === 'number' ? err.status : statusFromStderr(stderr),
|
|
@@ -173,19 +116,16 @@ export function extractErrorFields(err) {
|
|
|
173
116
|
};
|
|
174
117
|
}
|
|
175
118
|
|
|
176
|
-
/** Pure predicate: HTTP status that signals "transient — retry-eligible". */
|
|
177
119
|
export function isTransientStatus(status) {
|
|
178
120
|
if (status === 429) return true;
|
|
179
121
|
return typeof status === 'number' && status >= 500;
|
|
180
122
|
}
|
|
181
123
|
|
|
182
|
-
/** Pure predicate: error code/message signals "transient — retry-eligible". */
|
|
183
124
|
export function isTransientByCodeOrMessage(code, lower) {
|
|
184
125
|
if (TRANSIENT_CODES.has(code)) return true;
|
|
185
126
|
return matchesAny(lower, TRANSIENT_MESSAGES);
|
|
186
127
|
}
|
|
187
128
|
|
|
188
|
-
/** Pure predicate: HTTP status / message signals "permission denied". */
|
|
189
129
|
export function isPermissionSignal(status, lower) {
|
|
190
130
|
if (status === 401 || status === 403) return true;
|
|
191
131
|
return matchesAny(lower, PERMISSION_MESSAGES);
|
|
@@ -193,52 +133,18 @@ export function isPermissionSignal(status, lower) {
|
|
|
193
133
|
|
|
194
134
|
export function classifyGithubError(err) {
|
|
195
135
|
if (!err) return 'permanent';
|
|
196
|
-
//
|
|
197
|
-
// shape `"gh-exec: gh <args> exceeded <N>ms"` — no transient keyword and
|
|
198
|
-
// no `.status` / `.code`. Match by `err.name` to avoid a circular import
|
|
199
|
-
// between this module and `lib/gh-exec.js`. Story #2860.
|
|
136
|
+
// Matched by name to avoid a circular import with `lib/gh-exec.js`.
|
|
200
137
|
if (err.name === 'GhExecTimeoutError') return 'transient';
|
|
201
|
-
//
|
|
202
|
-
// alone: the `gh` transport carries its reason exclusively on stderr, so a
|
|
203
|
-
// message-only match sees nothing but the exit code. Rule ORDER is
|
|
204
|
-
// load-bearing and unchanged — a secondary rate limit is delivered as HTTP
|
|
205
|
-
// 403, so the transient rules must stay ahead of the permission rule or it
|
|
206
|
-
// would bucket as 'permission' and never retry.
|
|
138
|
+
// Rule order is load-bearing: every transient rule precedes permission.
|
|
207
139
|
const { detail, status, code } = extractErrorFields(err);
|
|
208
140
|
if (matchesAny(detail, FEATURE_DISABLED_MESSAGES)) return 'feature-disabled';
|
|
209
141
|
if (isTransientStatus(status)) return 'transient';
|
|
210
142
|
if (isTransientByCodeOrMessage(code, detail)) return 'transient';
|
|
211
|
-
// Union with the former `transient-retry.js` predicate (Story #4298):
|
|
212
|
-
// retry on network/connectivity blips the status/code checks above miss
|
|
213
|
-
// (e.g. a `dial tcp ... i/o timeout` on `err.stderr` from the gh-CLI path,
|
|
214
|
-
// or `ECONNREFUSED` / `ENETUNREACH`). Checked before the permission rule so
|
|
215
|
-
// a transient network failure never masquerades as a permanent denial.
|
|
216
143
|
if (isTransientNetworkError(err)) return 'transient';
|
|
217
144
|
if (isPermissionSignal(status, detail)) return 'permission';
|
|
218
145
|
return 'permanent';
|
|
219
146
|
}
|
|
220
147
|
|
|
221
|
-
// ---------------------------------------------------------------------------
|
|
222
|
-
// Transient-retry helper (Story #2852; unified in Story #4298)
|
|
223
|
-
// ---------------------------------------------------------------------------
|
|
224
|
-
//
|
|
225
|
-
// The single canonical `withTransientRetry` for the GitHub provider. Story
|
|
226
|
-
// #4298 collapsed the former two divergent same-named implementations (this
|
|
227
|
-
// one + the network-only one in the deleted `transient-retry.js`) into this
|
|
228
|
-
// one primitive. Its default classifier (`classifyGithubError`) is the
|
|
229
|
-
// **union** predicate — it retries on transient HTTP statuses/codes AND on
|
|
230
|
-
// transient network/connectivity errors — so every former consumer of either
|
|
231
|
-
// module keeps (or gains) its prior retry coverage with no shim.
|
|
232
|
-
//
|
|
233
|
-
// Read-path callers (paginateRest, getTicket, getNativeSubIssues, …) all
|
|
234
|
-
// absorb the same jittered exponential backoff on transient GitHub errors
|
|
235
|
-
// through this one primitive, instead of bubbling a one-shot
|
|
236
|
-
// 502/429/ECONNRESET that kills a longer pipeline (e.g. the /mandrel-deliver
|
|
237
|
-
// Phase E retro). The network consumers repointed here
|
|
238
|
-
// (branch-protection, labels, projects-v2-graphql) call with no opts, so
|
|
239
|
-
// they adopt these defaults; their retry *classes* (the network blips) are
|
|
240
|
-
// preserved via the unified classifier above.
|
|
241
|
-
|
|
242
148
|
export const TRANSIENT_RETRY_DEFAULTS = Object.freeze({
|
|
243
149
|
maxAttempts: 6,
|
|
244
150
|
baseDelayMs: 500,
|
|
@@ -247,14 +153,8 @@ export const TRANSIENT_RETRY_DEFAULTS = Object.freeze({
|
|
|
247
153
|
});
|
|
248
154
|
|
|
249
155
|
/**
|
|
250
|
-
*
|
|
251
|
-
* `
|
|
252
|
-
* failure is retry-eligible: only `'transient'` retries; every other
|
|
253
|
-
* bucket (`feature-disabled` / `permission` / `permanent`) bubbles on the
|
|
254
|
-
* first failure.
|
|
255
|
-
*
|
|
256
|
-
* `sleep` and `random` are injectable so tests can drive deterministic
|
|
257
|
-
* retry paths without real-world timing.
|
|
156
|
+
* The provider's single retry primitive: jittered exponential backoff; only
|
|
157
|
+
* a `'transient'` classification retries, anything else throws at once.
|
|
258
158
|
*
|
|
259
159
|
* @template T
|
|
260
160
|
* @param {() => Promise<T>} fn
|
|
@@ -310,9 +210,6 @@ export async function withTransientRetry(fn, opts = {}) {
|
|
|
310
210
|
throw lastErr;
|
|
311
211
|
}
|
|
312
212
|
|
|
313
|
-
// ---------------------------------------------------------------------------
|
|
314
|
-
// Sub-issues GraphQL shapes
|
|
315
|
-
// ---------------------------------------------------------------------------
|
|
316
213
|
export const SUB_ISSUES_QUERY = `query($id: ID!, $cursor: String) {
|
|
317
214
|
node(id: $id) {
|
|
318
215
|
... on Issue {
|