mandrel 2.59.0 → 2.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/README.md +21 -19
- package/.agents/agents/acceptance-critic.md +24 -43
- package/.agents/agents/story-worker.md +20 -21
- package/.agents/docs/agentrc-reference.json +5 -84
- package/.agents/docs/configuration.md +48 -132
- package/.agents/docs/workflows.md +2 -2
- package/.agents/instructions.md +5 -8
- package/.agents/rules/ci-remediation.md +41 -8
- package/.agents/rules/gherkin-standards.md +4 -0
- package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
- package/.agents/schemas/agentrc.schema.json +16 -496
- package/.agents/schemas/story-deliver-terminal.schema.json +13 -3
- package/.agents/schemas/validation-evidence.schema.json +2 -1
- package/.agents/scripts/README.md +23 -13
- package/.agents/scripts/acceptance-eval.js +35 -169
- package/.agents/scripts/agents-bootstrap-github.js +27 -129
- package/.agents/scripts/apply-quality-bootstrap.js +4 -40
- package/.agents/scripts/audit-baselines.js +6 -27
- package/.agents/scripts/audit-labels-bootstrap.js +5 -29
- package/.agents/scripts/audit-to-stories.js +91 -361
- package/.agents/scripts/boot-sweep.js +19 -72
- package/.agents/scripts/bootstrap.js +74 -395
- package/.agents/scripts/ceremony-derive.js +10 -41
- package/.agents/scripts/check-arch-cycles.js +14 -64
- package/.agents/scripts/check-baselines.js +8 -48
- package/.agents/scripts/check-context-budget.js +105 -311
- package/.agents/scripts/check-cyclomatic.js +12 -44
- package/.agents/scripts/check-dead-exports.js +13 -64
- package/.agents/scripts/check-doc-links.js +38 -186
- package/.agents/scripts/check-gherkin-corpus.js +24 -127
- package/.agents/scripts/check-test-temp-hygiene.js +28 -169
- package/.agents/scripts/coverage-capture.js +34 -98
- package/.agents/scripts/deliver-light.js +25 -171
- package/.agents/scripts/deliver-recover.js +6 -42
- package/.agents/scripts/deliver-run.js +534 -0
- package/.agents/scripts/diagnose-friction.js +24 -116
- package/.agents/scripts/drain-pending-cleanup.js +1 -1
- package/.agents/scripts/evidence-gate.js +23 -85
- package/.agents/scripts/file-ci-gap.js +57 -49
- package/.agents/scripts/generate-config-docs.js +30 -170
- package/.agents/scripts/generate-lens-checklists.js +8 -52
- package/.agents/scripts/generate-skills-index.js +14 -112
- package/.agents/scripts/generate-workflows-doc.js +10 -70
- package/.agents/scripts/git-cleanup.js +2 -34
- package/.agents/scripts/lib/Graph.js +24 -81
- package/.agents/scripts/lib/ITicketingProvider.js +47 -143
- package/.agents/scripts/lib/Logger.js +14 -76
- package/.agents/scripts/lib/audit-baselines/engine.js +11 -31
- package/.agents/scripts/lib/audit-baselines/gate-surface.js +3 -17
- package/.agents/scripts/lib/audit-baselines/headroom.js +4 -20
- package/.agents/scripts/lib/audit-baselines/hotspots.js +3 -15
- package/.agents/scripts/lib/audit-baselines/kinds.js +23 -89
- package/.agents/scripts/lib/audit-baselines/outliers.js +6 -23
- package/.agents/scripts/lib/audit-baselines/read.js +3 -16
- package/.agents/scripts/lib/audit-baselines/staleness.js +7 -26
- package/.agents/scripts/lib/audit-baselines/surface-entry.js +7 -28
- package/.agents/scripts/lib/audit-baselines/trend.js +7 -20
- package/.agents/scripts/lib/audit-baselines/weights.js +9 -37
- package/.agents/scripts/lib/audit-suite/audit-rules-reader.js +3 -18
- package/.agents/scripts/lib/audit-suite/checklist-threading.js +26 -124
- package/.agents/scripts/lib/audit-suite/dispatch-checklist.js +14 -45
- package/.agents/scripts/lib/audit-suite/findings.js +12 -52
- package/.agents/scripts/lib/audit-suite/frontmatter.js +5 -29
- package/.agents/scripts/lib/audit-suite/index.js +1 -15
- package/.agents/scripts/lib/audit-suite/lens-checklist.js +10 -45
- package/.agents/scripts/lib/audit-suite/lens-diff-floor.js +11 -76
- package/.agents/scripts/lib/audit-suite/runner.js +13 -43
- package/.agents/scripts/lib/audit-suite/selector.js +49 -349
- package/.agents/scripts/lib/audit-suite/substitutions.js +12 -40
- package/.agents/scripts/lib/audit-suite/workflow-loader.js +3 -15
- package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +11 -73
- package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +8 -37
- package/.agents/scripts/lib/audit-to-stories/build-story-body.js +25 -143
- package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +14 -80
- package/.agents/scripts/lib/audit-to-stories/epic-grouping-directive.js +4 -18
- package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +7 -40
- package/.agents/scripts/lib/audit-to-stories/group-findings.js +9 -39
- package/.agents/scripts/lib/audit-to-stories/issue-corpus.js +10 -66
- package/.agents/scripts/lib/audit-to-stories/issue-index.js +6 -30
- package/.agents/scripts/lib/audit-to-stories/issues-file.js +6 -36
- package/.agents/scripts/lib/audit-to-stories/ledger-commit.js +17 -69
- package/.agents/scripts/lib/audit-to-stories/ledger-pr.js +17 -85
- package/.agents/scripts/lib/audit-to-stories/ledger-record.js +10 -48
- package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +38 -146
- package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +7 -42
- package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +10 -57
- package/.agents/scripts/lib/baseline-loader.js +12 -51
- package/.agents/scripts/lib/baseline-schema-registry.js +5 -22
- package/.agents/scripts/lib/baselines/component-matcher.js +3 -12
- package/.agents/scripts/lib/baselines/components.js +10 -61
- package/.agents/scripts/lib/baselines/coverage-updater-cli.js +7 -36
- package/.agents/scripts/lib/baselines/crap-preview-incremental.js +7 -19
- package/.agents/scripts/lib/baselines/crap-preview-scan.js +19 -45
- package/.agents/scripts/lib/baselines/crap-updater-cli.js +16 -65
- package/.agents/scripts/lib/baselines/diff-scope-cli.js +5 -33
- package/.agents/scripts/lib/baselines/duplication-scanner.js +11 -60
- package/.agents/scripts/lib/baselines/env-overrides.js +12 -67
- package/.agents/scripts/lib/baselines/envelope.js +13 -129
- package/.agents/scripts/lib/baselines/exit-codes.js +6 -49
- package/.agents/scripts/lib/baselines/git-base.js +23 -142
- package/.agents/scripts/lib/baselines/kernel.js +11 -111
- package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +9 -47
- package/.agents/scripts/lib/baselines/kinds/_crap-read.js +8 -51
- package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +7 -62
- package/.agents/scripts/lib/baselines/kinds/bundle-size.js +8 -29
- package/.agents/scripts/lib/baselines/kinds/coverage.js +3 -15
- package/.agents/scripts/lib/baselines/kinds/crap.js +94 -415
- package/.agents/scripts/lib/baselines/kinds/duplication.js +4 -30
- package/.agents/scripts/lib/baselines/kinds/kind-factory.js +7 -53
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +15 -80
- package/.agents/scripts/lib/baselines/kinds/mutation.js +12 -72
- package/.agents/scripts/lib/baselines/maintainability-baseline-io.js +4 -11
- package/.agents/scripts/lib/baselines/merge-envelopes.js +30 -146
- package/.agents/scripts/lib/baselines/path-canon.js +19 -128
- package/.agents/scripts/lib/baselines/preview-gates.js +8 -37
- package/.agents/scripts/lib/baselines/reader.js +14 -107
- package/.agents/scripts/lib/baselines/refresh-service.js +35 -252
- package/.agents/scripts/lib/baselines/scope.js +11 -135
- package/.agents/scripts/lib/baselines/writer.js +16 -149
- package/.agents/scripts/lib/bdd-runner-detect.js +18 -113
- package/.agents/scripts/lib/bdd-scenario-budget.js +9 -36
- package/.agents/scripts/lib/bdd-scenario-scanner.js +11 -73
- package/.agents/scripts/lib/bdd-step-index.js +26 -100
- package/.agents/scripts/lib/bootstrap/baseline-merge-driver.js +23 -103
- package/.agents/scripts/lib/bootstrap/branch-protection.js +2 -5
- package/.agents/scripts/lib/bootstrap/commit-push.js +12 -50
- package/.agents/scripts/lib/bootstrap/gh-preflight.js +14 -101
- package/.agents/scripts/lib/bootstrap/hitl-confirm.js +5 -30
- package/.agents/scripts/lib/bootstrap/install-ledger.js +17 -73
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +17 -121
- package/.agents/scripts/lib/bootstrap/manifest.js +15 -86
- package/.agents/scripts/lib/bootstrap/merge-methods.js +4 -33
- package/.agents/scripts/lib/bootstrap/preflight.js +12 -61
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +34 -235
- package/.agents/scripts/lib/bootstrap/prompt.js +21 -129
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +27 -141
- package/.agents/scripts/lib/bootstrap/summary.js +1 -8
- package/.agents/scripts/lib/bootstrap/workflow-audit.js +11 -84
- package/.agents/scripts/lib/branch-name-guard.js +4 -23
- package/.agents/scripts/lib/changed-files.js +39 -121
- package/.agents/scripts/lib/checks/core-bare-clean.js +4 -24
- package/.agents/scripts/lib/checks/index.js +18 -101
- package/.agents/scripts/lib/checks/loop-health.js +11 -53
- package/.agents/scripts/lib/checks/state.js +16 -91
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +10 -61
- package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +14 -83
- package/.agents/scripts/lib/child-exec.js +39 -108
- package/.agents/scripts/lib/cli/standard-args.js +9 -116
- package/.agents/scripts/lib/cli-args.js +31 -146
- package/.agents/scripts/lib/cli-usage.js +5 -27
- package/.agents/scripts/lib/cli-utils.js +2 -12
- package/.agents/scripts/lib/close-validation/commands.js +13 -76
- package/.agents/scripts/lib/close-validation/gates.js +92 -331
- package/.agents/scripts/lib/close-validation/process.js +121 -151
- package/.agents/scripts/lib/close-validation/projections/advisories.js +5 -31
- package/.agents/scripts/lib/close-validation/projections/crap.js +19 -67
- package/.agents/scripts/lib/close-validation/projections/head-sha.js +1 -17
- package/.agents/scripts/lib/close-validation/projections/inputs.js +4 -34
- package/.agents/scripts/lib/close-validation/projections/maintainability.js +11 -58
- package/.agents/scripts/lib/close-validation/runner.js +53 -110
- package/.agents/scripts/lib/command-header.js +6 -28
- package/.agents/scripts/lib/config/acceptance-eval.js +4 -30
- package/.agents/scripts/lib/config/baselines.js +3 -14
- package/.agents/scripts/lib/config/ci.js +8 -38
- package/.agents/scripts/lib/config/commands.js +1 -15
- package/.agents/scripts/lib/config/defaults.js +4 -33
- package/.agents/scripts/lib/config/delivery-routing.js +6 -34
- package/.agents/scripts/lib/config/explain.js +10 -83
- package/.agents/scripts/lib/config/gates/coverage.schema.js +0 -12
- package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +3 -31
- package/.agents/scripts/lib/config/gates/crap.schema.js +1 -34
- package/.agents/scripts/lib/config/gates/duplication.schema.js +1 -8
- package/.agents/scripts/lib/config/gates/index.js +2 -17
- package/.agents/scripts/lib/config/gates/maintainability.schema.js +1 -20
- package/.agents/scripts/lib/config/gates/mutation.schema.js +1 -7
- package/.agents/scripts/lib/config/gates/shared.js +4 -64
- package/.agents/scripts/lib/config/github.js +4 -22
- package/.agents/scripts/lib/config/limits.js +4 -57
- package/.agents/scripts/lib/config/paths.js +2 -21
- package/.agents/scripts/lib/config/qa.js +4 -38
- package/.agents/scripts/lib/config/quality.js +76 -432
- package/.agents/scripts/lib/config/runners.js +12 -56
- package/.agents/scripts/lib/config/runtime.js +13 -57
- package/.agents/scripts/lib/config/shared.js +2 -16
- package/.agents/scripts/lib/config/sync-agentrc.js +9 -50
- package/.agents/scripts/lib/config/temp-paths.js +40 -280
- package/.agents/scripts/lib/config/validate-orchestration.js +5 -17
- package/.agents/scripts/lib/config/worktree-isolation.js +9 -28
- package/.agents/scripts/lib/config-resolver.js +11 -52
- package/.agents/scripts/lib/config-schema-shared.js +1 -4
- package/.agents/scripts/lib/config-settings-schema-delivery.js +16 -291
- package/.agents/scripts/lib/config-settings-schema-quality.js +7 -219
- package/.agents/scripts/lib/config-settings-schema.js +37 -274
- package/.agents/scripts/lib/coverage-baseline.js +20 -110
- package/.agents/scripts/lib/coverage-capture-fullscope.js +18 -35
- package/.agents/scripts/lib/coverage-capture-incremental.js +15 -45
- package/.agents/scripts/lib/coverage-capture-usage.js +8 -25
- package/.agents/scripts/lib/coverage-capture.js +99 -224
- package/.agents/scripts/lib/coverage-utils.js +14 -79
- package/.agents/scripts/lib/cpu-pool.js +17 -123
- package/.agents/scripts/lib/crap-baseline-join.js +16 -88
- package/.agents/scripts/lib/crap-coordinates.js +6 -25
- package/.agents/scripts/lib/crap-engine.js +40 -153
- package/.agents/scripts/lib/crap-method-identity.js +16 -78
- package/.agents/scripts/lib/crap-utils.js +31 -155
- package/.agents/scripts/lib/cyclomatic-ceiling.js +14 -87
- package/.agents/scripts/lib/cyclomatic-scope.js +10 -50
- package/.agents/scripts/lib/dead-exports-knip.js +18 -56
- package/.agents/scripts/lib/dead-exports-mode.js +5 -24
- package/.agents/scripts/lib/degraded-mode.js +3 -26
- package/.agents/scripts/lib/dependency-parser.js +8 -40
- package/.agents/scripts/lib/dependency-version.js +13 -35
- package/.agents/scripts/lib/detect-package-manager.js +6 -36
- package/.agents/scripts/lib/doc-tiers.js +22 -124
- package/.agents/scripts/lib/duplicate-search.js +8 -72
- package/.agents/scripts/lib/env-loader.js +5 -27
- package/.agents/scripts/lib/error-redactor.js +6 -31
- package/.agents/scripts/lib/errors/index.js +2 -22
- package/.agents/scripts/lib/escomplex-ast-compat.js +22 -163
- package/.agents/scripts/lib/escomplex-kernel.js +21 -123
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +94 -419
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +20 -98
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +27 -149
- package/.agents/scripts/lib/findings/audit-ledger.js +23 -97
- package/.agents/scripts/lib/findings/classify-finding.js +14 -69
- package/.agents/scripts/lib/findings/promote-finding.js +14 -112
- package/.agents/scripts/lib/findings/provenance-field.js +11 -52
- package/.agents/scripts/lib/findings/route-finding.js +37 -255
- package/.agents/scripts/lib/findings/semantic-issue-search.js +14 -59
- package/.agents/scripts/lib/findings/severity.js +18 -104
- package/.agents/scripts/lib/format-generated-json.js +12 -44
- package/.agents/scripts/lib/full-suite-lock.js +160 -429
- package/.agents/scripts/lib/full-suite-queue.js +213 -0
- package/.agents/scripts/lib/gates/baseline-store.js +5 -9
- package/.agents/scripts/lib/gates/friction.js +1 -3
- package/.agents/scripts/lib/generated/agentrc-validator.js +2 -2
- package/.agents/scripts/lib/gh-exec.js +123 -191
- package/.agents/scripts/lib/git/cached-fetch.js +9 -52
- package/.agents/scripts/lib/git/sync-from-base.js +15 -107
- package/.agents/scripts/lib/git-branch-cleanup.js +14 -61
- package/.agents/scripts/lib/git-branch-lifecycle.js +16 -87
- package/.agents/scripts/lib/git-utils.js +37 -161
- package/.agents/scripts/lib/github/framework-repo.js +8 -71
- package/.agents/scripts/lib/github-url.js +2 -17
- package/.agents/scripts/lib/import-graph.js +11 -38
- package/.agents/scripts/lib/install-cmd-parser.js +4 -13
- package/.agents/scripts/lib/json-utils.js +3 -18
- package/.agents/scripts/lib/label-constants.js +16 -111
- package/.agents/scripts/lib/label-taxonomy.js +4 -30
- package/.agents/scripts/lib/maintainability-engine.js +12 -80
- package/.agents/scripts/lib/maintainability-unscorable.js +5 -25
- package/.agents/scripts/lib/maintainability-utils.js +16 -92
- package/.agents/scripts/lib/mandrel-catalog.js +12 -70
- package/.agents/scripts/lib/notifications/notifier.js +13 -38
- package/.agents/scripts/lib/npm-scripts.js +4 -23
- package/.agents/scripts/lib/observability/metrics-ledger.js +16 -76
- package/.agents/scripts/lib/observability/runtime-friction.js +44 -286
- package/.agents/scripts/lib/observability/signal-validator.js +5 -37
- package/.agents/scripts/lib/observability/signals-writer.js +11 -121
- package/.agents/scripts/lib/observability/source-classifier.js +22 -203
- package/.agents/scripts/lib/observability/terse-result.js +14 -47
- package/.agents/scripts/lib/onboard/init-tail.js +13 -74
- package/.agents/scripts/lib/onboard/scaffold-docs.js +11 -34
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +25 -139
- package/.agents/scripts/lib/orchestration/auto-merge-cwd.js +11 -66
- package/.agents/scripts/lib/orchestration/behind-recovery.js +10 -55
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +28 -156
- package/.agents/scripts/lib/orchestration/change-set.js +7 -36
- package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +9 -46
- package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +11 -44
- package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +5 -24
- package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +3 -12
- package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +5 -38
- package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +3 -8
- package/.agents/scripts/lib/orchestration/check-baselines/phases/refresh-ack.js +28 -136
- package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +3 -13
- package/.agents/scripts/lib/orchestration/check-state.js +92 -0
- package/.agents/scripts/lib/orchestration/ci-gap-intake.js +37 -144
- package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +121 -157
- package/.agents/scripts/lib/orchestration/code-review.js +24 -128
- package/.agents/scripts/lib/orchestration/column-sync.js +23 -111
- package/.agents/scripts/lib/orchestration/complexity-gate.js +118 -462
- package/.agents/scripts/lib/orchestration/deliver-recover.js +36 -168
- package/.agents/scripts/lib/orchestration/dependency-analyzer.js +4 -35
- package/.agents/scripts/lib/orchestration/dependency-candidates.js +9 -41
- package/.agents/scripts/lib/orchestration/diff-magnitude.js +25 -115
- package/.agents/scripts/lib/orchestration/doc-reader.js +2 -6
- package/.agents/scripts/lib/orchestration/docs-digest.js +13 -51
- package/.agents/scripts/lib/orchestration/epic-candidates.js +13 -53
- package/.agents/scripts/lib/orchestration/epic-checklist.js +9 -33
- package/.agents/scripts/lib/orchestration/epic-container.js +41 -167
- package/.agents/scripts/lib/orchestration/epic-expansion.js +10 -40
- package/.agents/scripts/lib/orchestration/epic-rollup.js +55 -207
- package/.agents/scripts/lib/orchestration/file-assumption-enum.js +2 -22
- package/.agents/scripts/lib/orchestration/file-assumptions.js +45 -253
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-detect.js +9 -46
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +7 -57
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +21 -126
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +2 -6
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +1 -4
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +1 -5
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +9 -34
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +41 -190
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/merged-tip.js +9 -45
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +1 -4
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +19 -85
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +3 -17
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +1 -5
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +16 -100
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +1 -4
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +16 -67
- package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +9 -33
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +8 -29
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +15 -68
- package/.agents/scripts/lib/orchestration/light-backstop.js +11 -49
- package/.agents/scripts/lib/orchestration/light-escalation.js +21 -89
- package/.agents/scripts/lib/orchestration/light-suitability.js +37 -307
- package/.agents/scripts/lib/orchestration/merge-block-class.js +39 -216
- package/.agents/scripts/lib/orchestration/merge-poll.js +104 -377
- package/.agents/scripts/lib/orchestration/pinned-identifier-lint.js +17 -57
- package/.agents/scripts/lib/orchestration/plan-context.js +55 -318
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +22 -79
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +5 -31
- package/.agents/scripts/lib/orchestration/plan-metrics.js +29 -108
- package/.agents/scripts/lib/orchestration/plan-navigation.js +8 -27
- package/.agents/scripts/lib/orchestration/plan-persist/acceptance-handle-repair.js +12 -49
- package/.agents/scripts/lib/orchestration/plan-persist/audit-provenance.js +18 -73
- package/.agents/scripts/lib/orchestration/plan-persist/changes-repair.js +16 -78
- package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +6 -30
- package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +14 -65
- package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +21 -76
- package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +6 -43
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +14 -68
- package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +9 -41
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +71 -289
- package/.agents/scripts/lib/orchestration/plan-persist/soft-findings.js +2 -12
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +96 -362
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +9 -39
- package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +60 -186
- package/.agents/scripts/lib/orchestration/plan-persist/wave-collision-gate.js +9 -49
- package/.agents/scripts/lib/orchestration/plan-persist/wave-serialisation.js +7 -28
- package/.agents/scripts/lib/orchestration/plan-reachability.js +13 -42
- package/.agents/scripts/lib/orchestration/plan-run-labels/reap.js +16 -91
- package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +16 -54
- package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +10 -52
- package/.agents/scripts/lib/orchestration/planning/authoring-context.js +14 -109
- package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +11 -83
- package/.agents/scripts/lib/orchestration/pr-watch.js +48 -306
- package/.agents/scripts/lib/orchestration/project-meta-cache.js +15 -80
- package/.agents/scripts/lib/orchestration/project-meta-resolver.js +10 -51
- package/.agents/scripts/lib/orchestration/reassert-status-column.js +12 -76
- package/.agents/scripts/lib/orchestration/remote-verifier.js +12 -36
- package/.agents/scripts/lib/orchestration/resolve-stories.js +33 -164
- package/.agents/scripts/lib/orchestration/retro-proposals.js +66 -361
- package/.agents/scripts/lib/orchestration/review-base-ref.js +9 -43
- package/.agents/scripts/lib/orchestration/review-depth.js +12 -91
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +10 -111
- package/.agents/scripts/lib/orchestration/review-providers/degraded-gates.js +13 -71
- package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +7 -51
- package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +8 -53
- package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -214
- package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +7 -52
- package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +4 -33
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +11 -71
- package/.agents/scripts/lib/orchestration/review-providers/scoped-lint.js +19 -131
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +6 -89
- package/.agents/scripts/lib/orchestration/review-providers/types.js +26 -56
- package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +3 -46
- package/.agents/scripts/lib/orchestration/run-epilogue.js +245 -326
- package/.agents/scripts/lib/orchestration/run-scoped-config.js +55 -159
- package/.agents/scripts/lib/orchestration/single-story-close/close-note.js +7 -34
- package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +16 -89
- package/.agents/scripts/lib/orchestration/single-story-close/gate-log.js +18 -109
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +83 -239
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +20 -82
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +103 -97
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -64
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +136 -486
- package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +30 -134
- package/.agents/scripts/lib/orchestration/single-story-close/phases/graphql-preflight.js +96 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/lock-wait-pending.js +49 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +13 -86
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +20 -95
- package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +46 -203
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pre-gate-steps.js +8 -50
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +12 -83
- package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +6 -39
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -6
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-outcome.js +4 -28
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +6 -51
- package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +6 -34
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +23 -121
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +180 -273
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +15 -69
- package/.agents/scripts/lib/orchestration/story-body-gate.js +4 -23
- package/.agents/scripts/lib/orchestration/story-close/baseline-upward-writeback.js +50 -179
- package/.agents/scripts/lib/orchestration/story-close/context-budget-writeback.js +11 -41
- package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +23 -311
- package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +22 -147
- package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +16 -67
- package/.agents/scripts/lib/orchestration/story-deliver-terminal-schema.js +12 -68
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +42 -200
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +167 -252
- package/.agents/scripts/lib/orchestration/story-init-envelope.js +52 -0
- package/.agents/scripts/lib/orchestration/story-init-remote.js +2 -6
- package/.agents/scripts/lib/orchestration/story-reachability.js +3 -23
- package/.agents/scripts/lib/orchestration/task-body-validator.js +12 -135
- package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -131
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +15 -149
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +5 -33
- package/.agents/scripts/lib/orchestration/ticket-validator.js +63 -344
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +51 -244
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +39 -261
- package/.agents/scripts/lib/orchestration/ticketing/state.js +14 -68
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +46 -263
- package/.agents/scripts/lib/orchestration/ticketing.js +2 -26
- package/.agents/scripts/lib/orchestration/verify-credit.js +18 -79
- package/.agents/scripts/lib/orchestration/worktree-dirty.js +5 -30
- package/.agents/scripts/lib/path-security.js +3 -6
- package/.agents/scripts/lib/plan-phase-cleanup.js +9 -49
- package/.agents/scripts/lib/preflight-runner.js +13 -69
- package/.agents/scripts/lib/process-group.js +143 -0
- package/.agents/scripts/lib/project-root.js +2 -8
- package/.agents/scripts/lib/provider-factory.js +2 -25
- package/.agents/scripts/lib/qa/console-allowlist.js +10 -59
- package/.agents/scripts/lib/qa/qa-session.js +15 -69
- package/.agents/scripts/lib/qa/redact-evidence.js +18 -129
- package/.agents/scripts/lib/qa/resolve-qa-contract.js +26 -135
- package/.agents/scripts/lib/qa/resolve-selection.js +16 -84
- package/.agents/scripts/lib/reserved-test-ids.js +9 -47
- package/.agents/scripts/lib/runtime-deps/dep-resolution.js +13 -53
- package/.agents/scripts/lib/runtime-deps/ensure-installed.js +10 -44
- package/.agents/scripts/lib/runtime-deps/manifest.js +10 -30
- package/.agents/scripts/lib/runtime-deps/parser-major.js +15 -51
- package/.agents/scripts/lib/runtime-deps/preflight.js +4 -22
- package/.agents/scripts/lib/runtime-deps/scan-imports.js +11 -55
- package/.agents/scripts/lib/signals/detectors/common.js +12 -38
- package/.agents/scripts/lib/signals/index.js +2 -19
- package/.agents/scripts/lib/signals/schema.js +14 -109
- package/.agents/scripts/lib/signals/write.js +2 -11
- package/.agents/scripts/lib/single-story/confirm-merge.js +31 -72
- package/.agents/scripts/lib/single-story/story-merged-notify.js +8 -49
- package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +4 -26
- package/.agents/scripts/lib/single-story-sweep/protection.js +13 -100
- package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +60 -258
- package/.agents/scripts/lib/single-story-sweep.js +14 -97
- package/.agents/scripts/lib/skills/parse-skill.js +13 -59
- package/.agents/scripts/lib/skills/skills-index.js +8 -29
- package/.agents/scripts/lib/skills/walk-skill-files.js +17 -78
- package/.agents/scripts/lib/source-extensions.js +11 -42
- package/.agents/scripts/lib/source-text/strip-js-comments.js +8 -41
- package/.agents/scripts/lib/stdio-flush.js +9 -36
- package/.agents/scripts/lib/story-adjacency.js +8 -40
- package/.agents/scripts/lib/story-body/body-format-lints.js +51 -66
- package/.agents/scripts/lib/story-body/footer-block.js +11 -44
- package/.agents/scripts/lib/story-body/story-body.js +123 -344
- package/.agents/scripts/lib/temp-retention.js +42 -143
- package/.agents/scripts/lib/templates/decomposer-prompts.js +18 -80
- package/.agents/scripts/lib/test-env.js +12 -65
- package/.agents/scripts/lib/test-run-credit.js +10 -65
- package/.agents/scripts/lib/test-runner-contract.js +19 -74
- package/.agents/scripts/lib/test-temp.js +38 -184
- package/.agents/scripts/lib/test-tiers.js +12 -96
- package/.agents/scripts/lib/ticket-body-sections.js +21 -96
- package/.agents/scripts/lib/transpile.js +15 -74
- package/.agents/scripts/lib/util/concurrent-map.js +6 -25
- package/.agents/scripts/lib/util/parse-id-list.js +8 -34
- package/.agents/scripts/lib/util/poll-loop.js +8 -28
- package/.agents/scripts/lib/util/with-timeout.js +2 -11
- package/.agents/scripts/lib/validation-evidence.js +21 -96
- package/.agents/scripts/lib/wave-runner/footprint.js +17 -70
- package/.agents/scripts/lib/wave-runner/live-probe.js +67 -209
- package/.agents/scripts/lib/wave-runner/ready-set.js +72 -301
- package/.agents/scripts/lib/workers/crap-worker.js +11 -64
- package/.agents/scripts/lib/workers/maintainability-report-worker.js +8 -45
- package/.agents/scripts/lib/workers/maintainability-worker.js +5 -21
- package/.agents/scripts/lib/workers/serve-worker-messages.js +2 -18
- package/.agents/scripts/lib/workflow-closure.js +22 -105
- package/.agents/scripts/lib/workspace-provisioner.js +16 -54
- package/.agents/scripts/lib/worktree/git-hooks.js +15 -60
- package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +20 -60
- package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +10 -62
- package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +22 -86
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +24 -126
- package/.agents/scripts/lib/worktree/lifecycle-manager.js +2 -20
- package/.agents/scripts/lib/worktree/node-modules-strategy.js +46 -180
- package/.agents/scripts/lib/worktree-manager.js +15 -40
- package/.agents/scripts/lint-issue-body.js +12 -68
- package/.agents/scripts/mandrel-update-preflight.js +10 -70
- package/.agents/scripts/merge-baseline.js +30 -105
- package/.agents/scripts/nav-registry-diff.js +22 -108
- package/.agents/scripts/notify.js +12 -69
- package/.agents/scripts/plan-context.js +97 -92
- package/.agents/scripts/plan-critics.js +12 -66
- package/.agents/scripts/plan-persist.js +71 -137
- package/.agents/scripts/plan-run-epilogue.js +20 -43
- package/.agents/scripts/pr-watch-with-update.js +79 -263
- package/.agents/scripts/providers/github/auth.js +3 -8
- package/.agents/scripts/providers/github/blocked-by-add.js +14 -61
- package/.agents/scripts/providers/github/board-add.js +5 -21
- package/.agents/scripts/providers/github/branch-protection.js +11 -43
- package/.agents/scripts/providers/github/cache.js +2 -14
- package/.agents/scripts/providers/github/comments.js +7 -40
- package/.agents/scripts/providers/github/compose.js +3 -19
- package/.agents/scripts/providers/github/errors.js +22 -125
- package/.agents/scripts/providers/github/issues.js +31 -123
- package/.agents/scripts/providers/github/labels.js +24 -124
- package/.agents/scripts/providers/github/mappers.js +5 -27
- package/.agents/scripts/providers/github/merge-methods.js +3 -22
- package/.agents/scripts/providers/github/project-board.js +2 -17
- package/.agents/scripts/providers/github/projects-v2-graphql.js +3 -6
- package/.agents/scripts/providers/github/request-helpers.js +5 -32
- package/.agents/scripts/providers/github/search-budget.js +9 -39
- package/.agents/scripts/providers/github/search-query.js +5 -26
- package/.agents/scripts/providers/github/sub-issue-add.js +15 -65
- package/.agents/scripts/providers/github/sub-issues.js +7 -36
- package/.agents/scripts/providers/github/tickets.js +32 -134
- package/.agents/scripts/providers/github.js +18 -59
- package/.agents/scripts/prune-plan-run-labels.js +12 -46
- package/.agents/scripts/quality-preview.js +35 -220
- package/.agents/scripts/resolve-doc-tiers.js +3 -26
- package/.agents/scripts/resolve-stories.js +16 -67
- package/.agents/scripts/resync-status-column.js +6 -25
- package/.agents/scripts/run-tests.js +29 -104
- package/.agents/scripts/single-story-close.js +23 -135
- package/.agents/scripts/single-story-confirm-merge.js +32 -139
- package/.agents/scripts/single-story-init.js +47 -259
- package/.agents/scripts/stories-wave-tick.js +179 -415
- package/.agents/scripts/sync-agentrc.js +3 -21
- package/.agents/scripts/sync-claude-agents.js +9 -55
- package/.agents/scripts/sync-claude-commands.js +20 -110
- package/.agents/scripts/test-wrapper.js +6 -43
- package/.agents/scripts/update-coverage-baseline.js +5 -22
- package/.agents/scripts/update-crap-baseline.js +7 -30
- package/.agents/scripts/update-duplication-baseline.js +16 -92
- package/.agents/scripts/update-maintainability-baseline.js +8 -62
- package/.agents/scripts/update-ticket-state.js +1 -7
- package/.agents/scripts/validate-skills.js +6 -26
- package/.agents/skills/core/gates-and-baselines/reference.md +0 -1
- package/.agents/skills/skills.index.json +2 -2
- package/.agents/skills/stack/qa/playwright/SKILL.md +26 -0
- package/.agents/templates/agent-protocol.md +2 -2
- package/.agents/templates/docs/audit-sweep-runbook.md +3 -4
- package/.agents/workflows/audit-accessibility.md +4 -7
- package/.agents/workflows/audit-adrs.md +3 -6
- package/.agents/workflows/audit-architecture.md +3 -11
- package/.agents/workflows/audit-baselines.md +6 -9
- package/.agents/workflows/audit-clean-code.md +8 -12
- package/.agents/workflows/audit-data-model.md +3 -7
- package/.agents/workflows/audit-dependencies.md +4 -7
- package/.agents/workflows/audit-devops.md +4 -8
- package/.agents/workflows/audit-documentation.md +1 -4
- package/.agents/workflows/audit-mobile.md +4 -7
- package/.agents/workflows/audit-navigability.md +3 -6
- package/.agents/workflows/audit-performance.md +2 -4
- package/.agents/workflows/audit-privacy.md +4 -7
- package/.agents/workflows/audit-quality.md +4 -7
- package/.agents/workflows/audit-security.md +4 -7
- package/.agents/workflows/audit-seo.md +4 -7
- package/.agents/workflows/audit-sre.md +4 -7
- package/.agents/workflows/audit-to-stories.md +17 -30
- package/.agents/workflows/audit-ux-ui.md +4 -7
- package/.agents/workflows/helpers/acceptance-self-eval.md +84 -157
- package/.agents/workflows/helpers/audit-lens-core.md +1 -1
- package/.agents/workflows/helpers/code-quality-guardrails.md +12 -15
- package/.agents/workflows/helpers/code-review.md +4 -2
- package/.agents/workflows/helpers/deliver-digest.md +37 -28
- package/.agents/workflows/helpers/deliver-light.md +92 -101
- package/.agents/workflows/helpers/deliver-reference.md +162 -220
- package/.agents/workflows/helpers/deliver-story-reference.md +197 -607
- package/.agents/workflows/helpers/deliver-story.md +17 -18
- package/.agents/workflows/helpers/plan-reference.md +125 -167
- package/.agents/workflows/helpers/qa-core.md +12 -0
- package/.agents/workflows/mandrel-deliver.md +47 -31
- package/.agents/workflows/mandrel-plan.md +22 -21
- package/.agents/workflows/mandrel-update.md +36 -21
- package/.agents/workflows/memory-consolidate.md +1 -1
- package/.agents/workflows/qa-assist.md +27 -71
- package/.agents/workflows/qa-explore.md +19 -59
- package/.agents/workflows/qa-run.md +11 -33
- package/README.md +1 -1
- package/bin/mandrel.js +5 -46
- package/bin/postinstall.js +18 -107
- package/docs/CHANGELOG.md +60 -0
- package/lib/cli/doctor.js +11 -71
- package/lib/cli/init.js +26 -165
- package/lib/cli/migrate.js +5 -64
- package/lib/cli/registry.js +84 -467
- package/lib/cli/sync-agents.js +4 -64
- package/lib/cli/sync-commands.js +11 -64
- package/lib/cli/sync.js +34 -213
- package/lib/cli/uninstall.js +40 -219
- package/lib/cli/update.js +326 -523
- package/lib/cli/version-check.js +8 -72
- package/lib/cli/version-helpers.js +14 -87
- package/lib/migrations/helpers/retire-agentrc-key.js +11 -52
- package/lib/migrations/index.js +17 -92
- package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +2 -15
- package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +1 -13
- package/lib/migrations/steps/2.11.0-retire-max-seed-words.js +2 -15
- package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +9 -38
- package/lib/migrations/steps/2.20.0-retire-codebase-snapshot.js +1 -13
- package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +2 -27
- package/lib/migrations/steps/2.57.0-retire-delivery-limit-knobs.js +2 -23
- package/lib/migrations/steps/2.57.0-retire-planning-limit-knobs.js +2 -27
- package/lib/migrations/steps/2.60.0-retire-audit-results-autofile.js +21 -0
- package/lib/migrations/steps/strip-removed-agentrc-keys.js +333 -0
- package/package.json +17 -14
- package/.agents/docs/SDLC.md +0 -590
- package/.agents/docs/quality-gates.md +0 -1179
- package/.agents/rules/known-tooling-behavior.md +0 -150
- package/.agents/rules/orchestration-error-handling.md +0 -61
- package/.agents/rules/test-seams.md +0 -59
- package/.agents/schemas/baselines/lighthouse.schema.json +0 -59
- package/.agents/schemas/baselines/lint.schema.json +0 -47
- package/.agents/schemas/model-attribution.schema.json +0 -53
- package/.agents/scripts/check-action-pinning.js +0 -260
- package/.agents/scripts/check-audit-attribution.js +0 -302
- package/.agents/scripts/check-baseline-drift.js +0 -211
- package/.agents/scripts/check-baseline-scope.js +0 -362
- package/.agents/scripts/check-generated-validator.js +0 -202
- package/.agents/scripts/check-knip-entries.js +0 -159
- package/.agents/scripts/check-lifecycle-lint.js +0 -294
- package/.agents/scripts/check-pinned-override-notes.js +0 -102
- package/.agents/scripts/check-schema-references.js +0 -366
- package/.agents/scripts/check-test-portability.js +0 -512
- package/.agents/scripts/check-workflow-citations.js +0 -332
- package/.agents/scripts/check-workflow-cli-lint.js +0 -299
- package/.agents/scripts/check-workflow-timeouts.js +0 -291
- package/.agents/scripts/install-matrix-assert.js +0 -326
- package/.agents/scripts/lib/audit-advisories.js +0 -195
- package/.agents/scripts/lib/audit-attribution.js +0 -134
- package/.agents/scripts/lib/baselines/drift-detector.js +0 -351
- package/.agents/scripts/lib/baselines/kinds/lighthouse.js +0 -87
- package/.agents/scripts/lib/baselines/kinds/lint.js +0 -184
- package/.agents/scripts/lib/baselines/orphan-pruner.js +0 -233
- package/.agents/scripts/lib/baselines/scope-assert.js +0 -223
- package/.agents/scripts/lib/baselines/scope-inventory.js +0 -314
- package/.agents/scripts/lib/c8-cli-path.js +0 -21
- package/.agents/scripts/lib/config/gates/lighthouse.schema.js +0 -51
- package/.agents/scripts/lib/config/gates/lint.schema.js +0 -18
- package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +0 -70
- package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +0 -284
- package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +0 -80
- package/.agents/scripts/lib/dynamic-workflow/degraded-coverage.js +0 -81
- package/.agents/scripts/lib/dynamic-workflow/documentation-report-contract.js +0 -87
- package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +0 -74
- package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +0 -90
- package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +0 -43
- package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +0 -83
- package/.agents/scripts/lib/fs-walk.js +0 -52
- package/.agents/scripts/lib/knip-config-resolver.js +0 -181
- package/.agents/scripts/lib/knip-entry-sync.js +0 -452
- package/.agents/scripts/lib/orchestration/model-attribution.js +0 -418
- package/.agents/scripts/lib/orchestration/story-plan-state.js +0 -33
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +0 -67
- package/.agents/scripts/lib/pinned-override-notes.js +0 -88
- package/.agents/scripts/lib/pinned-override-resolve.js +0 -212
- package/.agents/scripts/lib/test-isolate/cli-options.js +0 -93
- package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +0 -52
- package/.agents/scripts/lib/test-isolate/list-files.js +0 -90
- package/.agents/scripts/lib/test-isolate/parse-tap.js +0 -75
- package/.agents/scripts/lib/test-isolate/progress-log.js +0 -45
- package/.agents/scripts/lib/test-isolate/render-report.js +0 -97
- package/.agents/scripts/lib/test-isolate/run-isolate.js +0 -87
- package/.agents/scripts/lib/test-isolate/runner.js +0 -483
- package/.agents/scripts/lib/test-profile/parse-tap.js +0 -136
- package/.agents/scripts/lib/test-profile/render-report.js +0 -45
- package/.agents/scripts/lint-label-vocabulary.js +0 -214
- package/.agents/scripts/post-structured-comment.js +0 -127
- package/.agents/scripts/provision-git-hooks.js +0 -85
- package/.agents/scripts/prune-baseline-orphans.js +0 -181
- package/.agents/scripts/run-coverage.js +0 -197
- package/.agents/scripts/run-lint.js +0 -133
- package/.agents/scripts/run-test-profile.js +0 -129
- package/.agents/scripts/run-verify.js +0 -118
- package/.agents/scripts/test-isolate.js +0 -55
- package/.agents/scripts/update-dead-exports-baseline.js +0 -321
|
@@ -1,55 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* graduator
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `spawn`-based child runner, the `git cat-file` path probe, the
|
|
7
|
-
* `gh search issues` idempotency probe, the `gh issue create` filer, the
|
|
8
|
-
* `isAutoFileEnabled` toggle reader, and the route → probe → file
|
|
9
|
-
* envelope walk. This module folds all of that into one place so a
|
|
10
|
-
* graduator becomes a thin shell that injects the bits that genuinely
|
|
11
|
-
* differ (the body/title/label builders).
|
|
12
|
-
*
|
|
13
|
-
* Story #5003 removed the structured-comment read limb. Both comment-reading
|
|
14
|
-
* graduators were Epic-era — they walked an Epic's `verification-results`
|
|
15
|
-
* comment, and v2 has no Epics — leaving `retro-proposals-graduator.js` and
|
|
16
|
-
* its pre-parsed `findings[]` as the one live caller.
|
|
17
|
-
*
|
|
18
|
-
* The third `runGh` spawn copy in `prior-feedback-fetcher.js` is also
|
|
19
|
-
* collapsed onto the single `runChild` helper here.
|
|
20
|
-
*
|
|
21
|
-
* Story #4415 / Epic #4406 hardens the walk so it is bounded and
|
|
22
|
-
* replay-safe — the shared mechanism the retro auto-filer will reuse:
|
|
23
|
-
*
|
|
24
|
-
* - **Content-hash idempotency markers.** Follow-up markers derive from
|
|
25
|
-
* a `category|path|title` digest (`contentFingerprint`) instead of a
|
|
26
|
-
* `(epicId, parse-index)` ordinal, so a finding keeps its marker when
|
|
27
|
-
* sibling findings are added, removed, or reordered in the source
|
|
28
|
-
* comment, and two distinct findings never collide.
|
|
29
|
-
* - **Legacy-marker recognition.** The idempotency probe also checks the
|
|
30
|
-
* legacy `(epicId, parse-index)` marker so findings filed before the
|
|
31
|
-
* fingerprint cutover are not re-filed.
|
|
32
|
-
* - **Bounded spawns.** `runChild` enforces a caller-overridable timeout
|
|
33
|
-
* (default 30000 ms) and kills a child that overruns instead of
|
|
34
|
-
* hanging finalize forever.
|
|
35
|
-
* - **Probe-error vs confirmed-missing.** A `git cat-file` spawn failure
|
|
36
|
-
* (or timeout) records the finding as skipped `probe-error`, not the
|
|
37
|
-
* confirmed-missing `file-removed`.
|
|
38
|
-
* - **Per-run filing cap.** `graduate()` stops filing once
|
|
39
|
-
* `maxFilingsPerRun` issues are created and records the excess as
|
|
40
|
-
* skipped `cap-reached`.
|
|
41
|
-
* - **Pre-parsed / path-less seam.** `graduate()` takes its findings as a
|
|
42
|
-
* pre-parsed array, and a path-less finding skips the path-exists gate
|
|
43
|
-
* instead of being misclassified `file-removed` — the seam the retro
|
|
44
|
-
* auto-filer consumes.
|
|
45
|
-
* - **Durable cross-repo deferral.** Cross-repo-deferred findings are
|
|
46
|
-
* upserted into a structured comment on the Epic instead of only a
|
|
47
|
-
* log line.
|
|
48
|
-
* - **Routed, never re-pointed.** Ownership routing is delegated to
|
|
49
|
-
* `github/framework-repo.js#routeOwnership`; an unroutable bucket is
|
|
50
|
-
* skipped `unroutable` and named in that same durable comment. The
|
|
51
|
-
* predecessor resolved an absent framework slug to the consumer's own
|
|
52
|
-
* repo, which silently mis-filed framework-owned work.
|
|
2
|
+
* Shared graduator walk: route → path probe → idempotency probe → cap → file.
|
|
3
|
+
* A graduator injects only its title/body/label/marker builders (`spec`).
|
|
4
|
+
* The walk is bounded (spawn timeouts, per-run filing cap) and replay-safe
|
|
5
|
+
* (content-hash markers survive sibling reordering).
|
|
53
6
|
*/
|
|
54
7
|
|
|
55
8
|
import { spawn as defaultSpawn } from 'node:child_process';
|
|
@@ -61,71 +14,25 @@ import { LABEL_COLORS } from '../label-constants.js';
|
|
|
61
14
|
import { classifyPathSource as defaultClassifier } from '../observability/source-classifier.js';
|
|
62
15
|
import { upsertStructuredComment } from '../orchestration/ticketing.js';
|
|
63
16
|
|
|
64
|
-
/**
|
|
65
|
-
* Default child-process timeout. A hung `gh`/`git` spawn previously blocked
|
|
66
|
-
* finalize indefinitely; the walk now caps every spawn at this bound unless
|
|
67
|
-
* a caller overrides it.
|
|
68
|
-
*/
|
|
69
17
|
const DEFAULT_RUN_CHILD_TIMEOUT_MS = 30000;
|
|
70
18
|
|
|
71
|
-
/**
|
|
72
|
-
* Default per-run filing cap. `graduate()` files at most this many follow-up
|
|
73
|
-
* issues per invocation; the remainder is recorded as skipped `cap-reached`.
|
|
74
|
-
*/
|
|
75
19
|
export const DEFAULT_MAX_FILINGS_PER_RUN = 20;
|
|
76
20
|
|
|
77
|
-
/**
|
|
78
|
-
* Structured-comment type used to durably persist cross-repo-deferred
|
|
79
|
-
* findings on the Epic. Registered in `STRUCTURED_COMMENT_TYPES`.
|
|
80
|
-
*/
|
|
21
|
+
/** Registered in `STRUCTURED_COMMENT_TYPES`. */
|
|
81
22
|
const CROSS_REPO_DEFERRED_COMMENT_TYPE = 'cross-repo-deferred';
|
|
82
23
|
|
|
83
|
-
/**
|
|
84
|
-
* Explicit, greppable opt-back-in to live issue filing from a context the
|
|
85
|
-
* guard below refuses (Story #4837). Deliberately shaped like
|
|
86
|
-
* `MANDREL_TEST_ALLOW_REAL_TEMP` (`config/temp-paths.js`) rather than a new
|
|
87
|
-
* bespoke flag: same env-var idiom, same "an escape hatch must be visible in
|
|
88
|
-
* a grep" posture.
|
|
89
|
-
*/
|
|
24
|
+
/** Explicit, greppable opt-in to live filing from a context the guard refuses. */
|
|
90
25
|
const ALLOW_LIVE_FILING_ENV = 'MANDREL_ALLOW_LIVE_ISSUE_FILING';
|
|
91
26
|
|
|
92
|
-
/**
|
|
93
|
-
* Skip reason recorded for every finding a refused filing context drops.
|
|
94
|
-
* Module-local: it reaches callers as data on the returned envelope, so
|
|
95
|
-
* exporting the constant would only add a symbol nothing imports.
|
|
96
|
-
*/
|
|
97
27
|
const LIVE_FILING_BLOCKED_REASON = 'live-api-guard';
|
|
98
28
|
|
|
99
|
-
/** `NODE_ENV` values that declare this process is not a production run. */
|
|
100
29
|
const NON_PRODUCTION_NODE_ENVS = new Set(['test', 'development']);
|
|
101
30
|
|
|
102
31
|
/**
|
|
103
|
-
* Decide whether
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* `dsj1984/mandrel` tracker — from fixture findings anchored to `epic-101`
|
|
108
|
-
* and `epic-777` — by a development run of the filing path. Nothing in the
|
|
109
|
-
* walk distinguished "a real close is filing a real follow-up" from "someone
|
|
110
|
-
* is exercising this module", so the only thing standing between a test and
|
|
111
|
-
* the production tracker was the author remembering to stub `spawnImpl`.
|
|
112
|
-
*
|
|
113
|
-
* **The seam.** There are exactly two ways to be safe, and this returns
|
|
114
|
-
* `allowed` only for them:
|
|
115
|
-
*
|
|
116
|
-
* 1. `spawnImpl` was injected — the walk then spawns the caller's stub and
|
|
117
|
-
* no child process reaches `gh` at all. This is the seam
|
|
118
|
-
* `.agents/rules/test-seams.md` already mandates, so a well-behaved test
|
|
119
|
-
* is unaffected.
|
|
120
|
-
* 2. The process provably is **not** a test or development context — not a
|
|
121
|
-
* node:test run (per the single shared detector in
|
|
122
|
-
* `config/temp-paths.js#inNodeTestContext`) and not a run that declared
|
|
123
|
-
* itself non-production via `NODE_ENV`.
|
|
124
|
-
*
|
|
125
|
-
* **Fail closed.** Anything else refuses: a test context with the real
|
|
126
|
-
* `spawn` (the #4833/#4834 shape), and — critically — a context that cannot
|
|
127
|
-
* be *decided*, because an unreadable env is not evidence of production. The
|
|
128
|
-
* refusal is a skip, not a throw: observability must never fail a close.
|
|
32
|
+
* Decide whether the walk may reach the live GitHub API. Allowed only when
|
|
33
|
+
* `spawnImpl` is injected (no child reaches `gh`) or the process is provably
|
|
34
|
+
* not a test/development run. Fails closed — an undecidable env refuses — and
|
|
35
|
+
* refusal is a skip, never a throw: observability must not fail a close.
|
|
129
36
|
*
|
|
130
37
|
* @param {object} opts
|
|
131
38
|
* @param {Function} [opts.spawnImpl]
|
|
@@ -141,38 +48,26 @@ function resolveFilingContext({
|
|
|
141
48
|
const refuse = { allowed: false, reason: LIVE_FILING_BLOCKED_REASON };
|
|
142
49
|
const allow = { allowed: true, reason: null };
|
|
143
50
|
|
|
144
|
-
// An injected seam cannot reach the live API by construction.
|
|
145
51
|
if (typeof spawnImpl === 'function') return allow;
|
|
146
52
|
|
|
147
|
-
// Undecidable context → refuse. Both inputs must be readable for the
|
|
148
|
-
// detector's answer to mean anything.
|
|
149
53
|
if (env === null || typeof env !== 'object' || !Array.isArray(execArgv)) {
|
|
150
54
|
return refuse;
|
|
151
55
|
}
|
|
152
56
|
try {
|
|
153
57
|
if (env[ALLOW_LIVE_FILING_ENV] === '1') return allow;
|
|
154
58
|
if (inNodeTestContext(env, execArgv)) return refuse;
|
|
155
|
-
//
|
|
156
|
-
// development context". `lib/test-env.js` stamps `NODE_ENV=test` on the
|
|
157
|
-
// whole suite environment, and `development` is the universal marker for
|
|
158
|
-
// a hand-run session; nothing on the close path sets either.
|
|
59
|
+
// The suite stamps NODE_ENV=test; the close path sets neither value.
|
|
159
60
|
return NON_PRODUCTION_NODE_ENVS.has(String(env.NODE_ENV ?? ''))
|
|
160
61
|
? refuse
|
|
161
62
|
: allow;
|
|
162
63
|
} catch {
|
|
163
|
-
// An env we cannot even read is not evidence of production.
|
|
164
64
|
return refuse;
|
|
165
65
|
}
|
|
166
66
|
}
|
|
167
67
|
|
|
168
68
|
/**
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* finding content, never on its position in the source comment, so the
|
|
172
|
-
* marker survives sibling insert/remove/reorder churn. Distinct triples
|
|
173
|
-
* yield distinct digests (SHA-256, truncated to 16 hex chars for a compact
|
|
174
|
-
* marker that still has a negligible collision probability across a single
|
|
175
|
-
* Epic's finding set).
|
|
69
|
+
* Position-independent `category|path|title` digest, so a marker survives
|
|
70
|
+
* sibling reordering (SHA-256 truncated to 16 hex).
|
|
176
71
|
*
|
|
177
72
|
* @param {{ category?: unknown, path?: unknown, title?: unknown }} parts
|
|
178
73
|
* @returns {string} 16-char lowercase hex digest.
|
|
@@ -184,29 +79,16 @@ export function contentFingerprint({ category, path, title } = {}) {
|
|
|
184
79
|
}
|
|
185
80
|
|
|
186
81
|
/**
|
|
187
|
-
*
|
|
188
|
-
* `
|
|
189
|
-
*
|
|
190
|
-
* `timedOut: true` with a matching `spawnError`.
|
|
191
|
-
*
|
|
192
|
-
* This is the single spawn helper for the feedback-loop modules. Both
|
|
193
|
-
* graduators and `prior-feedback-fetcher.js` route their child-process
|
|
194
|
-
* reads through it so the error envelope stays consistent. `stdio` is
|
|
195
|
-
* always `['ignore', 'pipe', 'pipe']`; callers that need extra spawn
|
|
196
|
-
* options (e.g. omitting `cwd`) pass `undefined` and the option is
|
|
197
|
-
* dropped by the child_process layer.
|
|
198
|
-
*
|
|
199
|
-
* A caller-overridable `timeoutMs` (default {@link DEFAULT_RUN_CHILD_TIMEOUT_MS})
|
|
200
|
-
* bounds the wait: when it elapses the child is SIGKILL'd and the promise
|
|
201
|
-
* resolves with `{ code: null, timedOut: true, spawnError }` rather than
|
|
202
|
-
* hanging. Pass `0`/`Infinity` to disable the watchdog.
|
|
82
|
+
* The feedback loop's single spawn helper. Never throws: spawn errors land in
|
|
83
|
+
* `spawnError`; an overrun is SIGKILL'd and resolves `timedOut: true`.
|
|
84
|
+
* `timeoutMs` of `0`/`Infinity` disables the watchdog.
|
|
203
85
|
*
|
|
204
86
|
* @param {object} opts
|
|
205
|
-
* @param {string} opts.cmd
|
|
206
|
-
* @param {string[]} opts.args
|
|
207
|
-
* @param {Function} [opts.spawnImpl]
|
|
208
|
-
* @param {string} [opts.cwd]
|
|
209
|
-
* @param {number} [opts.timeoutMs]
|
|
87
|
+
* @param {string} opts.cmd
|
|
88
|
+
* @param {string[]} opts.args
|
|
89
|
+
* @param {Function} [opts.spawnImpl]
|
|
90
|
+
* @param {string} [opts.cwd]
|
|
91
|
+
* @param {number} [opts.timeoutMs]
|
|
210
92
|
* @returns {Promise<{ code: number|null, stdout: string, stderr: string, spawnError: Error|null, timedOut: boolean }>}
|
|
211
93
|
*/
|
|
212
94
|
export function runChild({
|
|
@@ -249,7 +131,7 @@ export function runChild({
|
|
|
249
131
|
try {
|
|
250
132
|
child.kill?.('SIGKILL');
|
|
251
133
|
} catch {
|
|
252
|
-
//
|
|
134
|
+
// already dead / stub child
|
|
253
135
|
}
|
|
254
136
|
finish({
|
|
255
137
|
code: null,
|
|
@@ -264,14 +146,9 @@ export function runChild({
|
|
|
264
146
|
timedOut: true,
|
|
265
147
|
});
|
|
266
148
|
}, timeoutMs);
|
|
267
|
-
//
|
|
268
|
-
// the
|
|
269
|
-
//
|
|
270
|
-
// child whose handles close early — or a stub in tests — leaves the
|
|
271
|
-
// loop idle; an unref'd timer would then never fire, so the timeout
|
|
272
|
-
// silently would not bound a hung spawn (and the awaiting promise
|
|
273
|
-
// would hang forever). `finish()` always clearTimeout()s it, so the
|
|
274
|
-
// ref'd timer never outlives its purpose.
|
|
149
|
+
// Deliberately NOT unref'd: a child whose handles close early (or a
|
|
150
|
+
// stub) leaves the loop idle, and an unref'd watchdog would never fire.
|
|
151
|
+
// `finish()` always clears it.
|
|
275
152
|
}
|
|
276
153
|
child.stdout?.on('data', (chunk) => {
|
|
277
154
|
stdout += chunk.toString();
|
|
@@ -289,30 +166,21 @@ export function runChild({
|
|
|
289
166
|
}
|
|
290
167
|
|
|
291
168
|
/**
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
* toggle defaults to `true` and only an explicit `false` disables it.
|
|
169
|
+
* Opt-in `delivery.feedbackLoop.<key>` reader: only an explicit `true`
|
|
170
|
+
* enables filing, because unattended filings were dominated by noise.
|
|
295
171
|
*
|
|
296
|
-
* @param {string} toggleKey
|
|
297
|
-
* (e.g. "auditResultsAutoFile", "retroProposals")
|
|
172
|
+
* @param {string} toggleKey
|
|
298
173
|
* @returns {(config: object|undefined|null) => boolean}
|
|
299
174
|
*/
|
|
300
175
|
export function makeIsAutoFileEnabled(toggleKey) {
|
|
301
176
|
return function isAutoFileEnabled(config) {
|
|
302
|
-
|
|
303
|
-
if (value === false) return false;
|
|
304
|
-
return true;
|
|
177
|
+
return config?.delivery?.feedbackLoop?.[toggleKey] === true;
|
|
305
178
|
};
|
|
306
179
|
}
|
|
307
180
|
|
|
308
181
|
/**
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
* Resolves `{ exists, probeError }`:
|
|
312
|
-
*
|
|
313
|
-
* - `git cat-file -e <ref>:<path>` exit 0 → `{ exists: true, probeError: false }`
|
|
314
|
-
* - clean non-zero exit (file genuinely absent) → `{ exists: false, probeError: false }`
|
|
315
|
-
* - spawn failure / timeout (cannot decide) → `{ exists: false, probeError: true }`
|
|
182
|
+
* `git cat-file -e <ref>:<path>`; a spawn failure/timeout is `probeError`,
|
|
183
|
+
* distinct from a confirmed-missing file.
|
|
316
184
|
*
|
|
317
185
|
* @param {object} opts
|
|
318
186
|
* @param {string} opts.ref
|
|
@@ -343,16 +211,8 @@ export async function probePathStatus({
|
|
|
343
211
|
}
|
|
344
212
|
|
|
345
213
|
/**
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
* without leaking into the visible body, but the `<` / `>` delimiters are
|
|
349
|
-
* NOT index-safe as a query: GitHub full-text search DOES index the text
|
|
350
|
-
* inside an HTML comment, yet a query that carries the `<!--` / `-->`
|
|
351
|
-
* delimiters never matches that indexed text (measured against this repo,
|
|
352
|
-
* Story #4657). Stripping the delimiters and trimming yields the bare marker
|
|
353
|
-
* text — `retro-proposal-followup: <fp>` — which the index matches.
|
|
354
|
-
* The caller-facing marker is left untouched; normalization is the probe's
|
|
355
|
-
* own concern.
|
|
214
|
+
* GitHub search indexes the text inside an HTML-comment marker, but a query
|
|
215
|
+
* carrying the `<!--`/`-->` delimiters never matches it; strip them.
|
|
356
216
|
*
|
|
357
217
|
* @param {string} marker
|
|
358
218
|
* @returns {string}
|
|
@@ -363,11 +223,8 @@ function normalizeMarkerQuery(marker) {
|
|
|
363
223
|
}
|
|
364
224
|
|
|
365
225
|
/**
|
|
366
|
-
*
|
|
367
|
-
*
|
|
368
|
-
* the empty string — deliberately NOT to `'open'`: an unknown state must
|
|
369
|
-
* never authorize editing somebody's issue (see
|
|
370
|
-
* {@link resolveFollowUpRecurrence}).
|
|
226
|
+
* `state` defaults to `''`, never `'open'`: an unknown state must not
|
|
227
|
+
* authorize editing an issue.
|
|
371
228
|
*
|
|
372
229
|
* @param {object} row
|
|
373
230
|
* @returns {{ number: number|null, state: string, url: string }}
|
|
@@ -382,15 +239,8 @@ function toFollowUpRef(row) {
|
|
|
382
239
|
}
|
|
383
240
|
|
|
384
241
|
/**
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
* so we hit the body field directly, querying the delimiter-stripped marker
|
|
388
|
-
* text (see {@link normalizeMarkerQuery}) — the raw `<!-- … -->` form never
|
|
389
|
-
* matches the index.
|
|
390
|
-
*
|
|
391
|
-
* Returns `null` when nothing matched OR when the probe could not decide
|
|
392
|
-
* (spawn/parse error): the deliberate degrade-toward-filing posture, better
|
|
393
|
-
* to risk a duplicate than swallow the finding entirely.
|
|
242
|
+
* `null` on no match OR an undecidable probe — degrade toward filing: a
|
|
243
|
+
* duplicate beats a swallowed finding.
|
|
394
244
|
*
|
|
395
245
|
* @returns {Promise<{ number: number|null, state: string, url: string }|null>}
|
|
396
246
|
*/
|
|
@@ -427,46 +277,23 @@ async function searchFollowUpByMarker({
|
|
|
427
277
|
}
|
|
428
278
|
}
|
|
429
279
|
|
|
430
|
-
/**
|
|
431
|
-
* Probe whether a follow-up issue carrying the given idempotency marker
|
|
432
|
-
* already exists in the routed repo. Thin boolean façade over
|
|
433
|
-
* {@link searchFollowUpByMarker} — kept as the module's exported probe seam
|
|
434
|
-
* so callers that only need the yes/no do not have to know about the issue
|
|
435
|
-
* identity the recurrence path resolves.
|
|
436
|
-
*
|
|
437
|
-
* @returns {Promise<boolean>}
|
|
438
|
-
*/
|
|
280
|
+
/** @returns {Promise<boolean>} */
|
|
439
281
|
export async function probeMarkerExists(opts) {
|
|
440
282
|
return (await searchFollowUpByMarker(opts)) !== null;
|
|
441
283
|
}
|
|
442
284
|
|
|
443
285
|
/**
|
|
444
|
-
* Strongly-consistent
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
* label-scoped `gh issue list … --state all` is strongly consistent, so it
|
|
450
|
-
* closes that window. The list is narrowed by the follow-up's own labels
|
|
451
|
-
* (supplied by the same `spec.buildFollowUp` that writes the marker, so the
|
|
452
|
-
* two agree by construction) to keep the read bounded.
|
|
453
|
-
*
|
|
454
|
-
* `markers` is a LIST of body substrings, any one of which identifies a prior
|
|
455
|
-
* filing (Story #4837). One finding can have been filed under more than one
|
|
456
|
-
* marker shape — the retro graduator's pre-cutover marker embedded the run
|
|
457
|
-
* anchor, so the same finding sits behind `epic-<anchor>-<fp>` on already-
|
|
458
|
-
* filed issues and behind the anchor-free `<fp>` on new ones. Matching any of
|
|
459
|
-
* them is what stops a marker-format change from re-filing the whole backlog.
|
|
460
|
-
*
|
|
461
|
-
* Returns `null` when nothing matched, or on any spawn/parse error — the
|
|
462
|
-
* deliberate degrade-toward-filing posture: an undecidable probe risks a
|
|
463
|
-
* duplicate rather than swallowing the finding.
|
|
286
|
+
* Strongly-consistent last gate before creating: the search index can lag
|
|
287
|
+
* long enough to miss a duplicate filed seconds earlier, while a
|
|
288
|
+
* label-scoped `gh issue list --state all` cannot. Any of `markers` matching
|
|
289
|
+
* counts, so a marker-format change does not re-file the backlog. `null` on
|
|
290
|
+
* no match or error (degrade toward filing).
|
|
464
291
|
*
|
|
465
292
|
* @param {object} opts
|
|
466
|
-
* @param {string[]} opts.markers
|
|
293
|
+
* @param {string[]} opts.markers
|
|
467
294
|
* @param {string} opts.owner
|
|
468
295
|
* @param {string} opts.repo
|
|
469
|
-
* @param {string[]} [opts.labels]
|
|
296
|
+
* @param {string[]} [opts.labels]
|
|
470
297
|
* @param {string} [opts.ghPath]
|
|
471
298
|
* @param {Function} [opts.spawnImpl]
|
|
472
299
|
* @param {string} [opts.cwd]
|
|
@@ -517,9 +344,7 @@ async function findExistingFollowUp({
|
|
|
517
344
|
tokens.some((token) => issue.body.includes(token)),
|
|
518
345
|
);
|
|
519
346
|
if (matches.length === 0) return null;
|
|
520
|
-
// Prefer an
|
|
521
|
-
// one is a decided follow-up. When several match, the open one is the one a
|
|
522
|
-
// human is still looking at.
|
|
347
|
+
// Prefer an open match: a closed one is a decided follow-up.
|
|
523
348
|
const open = matches.find(
|
|
524
349
|
(issue) => String(issue?.state ?? '').toLowerCase() === 'open',
|
|
525
350
|
);
|
|
@@ -527,13 +352,8 @@ async function findExistingFollowUp({
|
|
|
527
352
|
}
|
|
528
353
|
|
|
529
354
|
/**
|
|
530
|
-
*
|
|
531
|
-
*
|
|
532
|
-
* to keep one issue current, not to mint issue #N+1 whose only new
|
|
533
|
-
* information is that the count went up.
|
|
534
|
-
*
|
|
535
|
-
* Body-only: labels, title, assignees and state are left exactly as a human
|
|
536
|
-
* may have curated them.
|
|
355
|
+
* Recurrence path: refresh the body only, leaving human-curated labels,
|
|
356
|
+
* title, assignees and state untouched.
|
|
537
357
|
*
|
|
538
358
|
* @returns {Promise<{ url: string|null, error: string|null }>}
|
|
539
359
|
*/
|
|
@@ -573,14 +393,10 @@ export async function updateFollowUpIssue({
|
|
|
573
393
|
return { url: (res.stdout || '').trim(), error: null };
|
|
574
394
|
}
|
|
575
395
|
|
|
576
|
-
/** Prefix of the per-category friction axis the feedback loop mints. */
|
|
577
396
|
const FRICTION_LABEL_PREFIX = 'friction::';
|
|
578
397
|
|
|
579
398
|
/**
|
|
580
|
-
*
|
|
581
|
-
* mint. Only two axes reach this path — `meta::*` (routing) and
|
|
582
|
-
* `friction::<category>` (the telemetry bucket) — so the mapping is a
|
|
583
|
-
* two-branch lookup rather than a registry.
|
|
399
|
+
* Only `meta::*` and `friction::<category>` labels reach this path.
|
|
584
400
|
*
|
|
585
401
|
* @param {string} name
|
|
586
402
|
* @returns {{ color: string, description: string }}
|
|
@@ -599,11 +415,7 @@ function describeMintedLabel(name) {
|
|
|
599
415
|
}
|
|
600
416
|
|
|
601
417
|
/**
|
|
602
|
-
*
|
|
603
|
-
* `labelCache`. Returns `null` when the set could not be established —
|
|
604
|
-
* "verification unavailable", which is deliberately NOT the same as "the repo
|
|
605
|
-
* has no labels": an unreadable set must not be read as proof that every
|
|
606
|
-
* label is missing.
|
|
418
|
+
* Memoized per repo. `known: null` means unverifiable, not "no labels".
|
|
607
419
|
*
|
|
608
420
|
* @returns {Promise<{ known: Set<string>|null, error: string|null }>}
|
|
609
421
|
*/
|
|
@@ -653,28 +465,16 @@ async function readLiveLabelNames({
|
|
|
653
465
|
}
|
|
654
466
|
|
|
655
467
|
/**
|
|
656
|
-
* Mint
|
|
657
|
-
*
|
|
658
|
-
*
|
|
659
|
-
*
|
|
660
|
-
* the repo before it creates anything, and fails the whole call when one is
|
|
661
|
-
* absent. The feedback loop mints two axes that no bootstrap can enumerate
|
|
662
|
-
* ahead of time — `meta::consumer-improvement` is absent from `LABEL_TAXONOMY`
|
|
663
|
-
* outright, and `friction::<category>` names come from live telemetry — so on
|
|
664
|
-
* a repo that never had them, *every* filing failed. The failure landed in the
|
|
665
|
-
* graduator's `errors[]`, which the run epilogue did not surface, so a
|
|
666
|
-
* hard-failing feedback loop rendered as `filed: 0`: indistinguishable from
|
|
667
|
-
* "nothing was actionable".
|
|
668
|
-
*
|
|
669
|
-
* Degrades rather than blocks: when the live set cannot be read, this returns
|
|
670
|
-
* no `missing` entries so the caller still attempts the filing (the old
|
|
671
|
-
* behaviour) instead of refusing on an unproven premise.
|
|
468
|
+
* Mint absent labels: `gh issue create` fails the whole call on any unknown
|
|
469
|
+
* `--label`, and `friction::<category>` names come from live telemetry so no
|
|
470
|
+
* bootstrap can pre-create them. An unreadable live set reports nothing
|
|
471
|
+
* `missing`, so the caller still attempts the filing.
|
|
672
472
|
*
|
|
673
473
|
* @param {object} opts
|
|
674
474
|
* @param {string} opts.owner
|
|
675
475
|
* @param {string} opts.repo
|
|
676
476
|
* @param {string[]} opts.labels
|
|
677
|
-
* @param {Map<string, Set<string>>} [opts.labelCache]
|
|
477
|
+
* @param {Map<string, Set<string>>} [opts.labelCache]
|
|
678
478
|
* @param {string} [opts.ghPath]
|
|
679
479
|
* @param {Function} [opts.spawnImpl]
|
|
680
480
|
* @param {string} [opts.cwd]
|
|
@@ -705,7 +505,6 @@ export async function ensureIssueLabels({
|
|
|
705
505
|
cwd,
|
|
706
506
|
timeoutMs,
|
|
707
507
|
});
|
|
708
|
-
// Verification unavailable — attempt the filing anyway rather than refuse.
|
|
709
508
|
if (!known) return { created: [], missing: [], errors: error ? [error] : [] };
|
|
710
509
|
|
|
711
510
|
const created = [];
|
|
@@ -734,8 +533,7 @@ export async function ensureIssueLabels({
|
|
|
734
533
|
const failed =
|
|
735
534
|
Boolean(res.spawnError) ||
|
|
736
535
|
(typeof res.code === 'number' && res.code !== 0);
|
|
737
|
-
// A concurrent
|
|
738
|
-
// that is the idempotent outcome, not a failure.
|
|
536
|
+
// A concurrent mint between list and create is success.
|
|
739
537
|
const raced = /label\b[\s\S]*?already exists/i.test(
|
|
740
538
|
`${res.stderr ?? ''}${res.spawnError?.message ?? ''}`,
|
|
741
539
|
);
|
|
@@ -752,12 +550,7 @@ export async function ensureIssueLabels({
|
|
|
752
550
|
return { created, missing, errors };
|
|
753
551
|
}
|
|
754
552
|
|
|
755
|
-
/**
|
|
756
|
-
* File a new follow-up issue via `gh issue create` and resolve to
|
|
757
|
-
* `{ url, error }`. On success `url` is the trimmed stdout and `error` is
|
|
758
|
-
* null; on failure `url` is null and `error` carries a human-readable
|
|
759
|
-
* message.
|
|
760
|
-
*/
|
|
553
|
+
/** Resolves `{ url, error }`; exactly one is non-null. */
|
|
761
554
|
export async function createFollowUpIssue({
|
|
762
555
|
owner,
|
|
763
556
|
repo,
|
|
@@ -796,16 +589,9 @@ export async function createFollowUpIssue({
|
|
|
796
589
|
}
|
|
797
590
|
|
|
798
591
|
/**
|
|
799
|
-
*
|
|
800
|
-
*
|
|
801
|
-
*
|
|
802
|
-
* `graduate` so the orchestrating body holds no guard-chain branching.
|
|
803
|
-
*
|
|
804
|
-
* Story #5003 dropped the `provider.getTicketComments` gate with the
|
|
805
|
-
* structured-comment read limb. The provider is now consulted only by the
|
|
806
|
-
* best-effort cross-repo-deferred upsert, which reports its own faults into
|
|
807
|
-
* `errors[]` — gating the whole walk on a shape only that path needs would
|
|
808
|
-
* refuse work the walk can complete.
|
|
592
|
+
* `null` when all pass, else a partial envelope to short-circuit on. The
|
|
593
|
+
* provider is deliberately not gated: only the best-effort cross-repo upsert
|
|
594
|
+
* needs it, and that reports its own faults.
|
|
809
595
|
*/
|
|
810
596
|
function checkGraduatePreconditions({ epicId, currentRepo, config, spec }) {
|
|
811
597
|
if (!spec.isAutoFileEnabled(config)) {
|
|
@@ -825,16 +611,9 @@ function checkGraduatePreconditions({ epicId, currentRepo, config, spec }) {
|
|
|
825
611
|
}
|
|
826
612
|
|
|
827
613
|
/**
|
|
828
|
-
*
|
|
829
|
-
*
|
|
830
|
-
*
|
|
831
|
-
* content-hash marker is passed in precomputed so a caller can consult an
|
|
832
|
-
* in-process memo before spending a spawn.
|
|
833
|
-
*
|
|
834
|
-
* Resolves `{ alreadyFiled, existing }` — `existing` carries the matched
|
|
835
|
-
* issue's `{ number, state, url }` when the search index surfaced it, so a
|
|
836
|
-
* recurrence can update that issue rather than only knowing that one exists.
|
|
837
|
-
* `existing` is `null` on the not-found path.
|
|
614
|
+
* Checks the content-hash marker, then the legacy ordinal marker so
|
|
615
|
+
* pre-fingerprint filings are not re-filed. `existing` identifies the match
|
|
616
|
+
* so a recurrence can update it.
|
|
838
617
|
*/
|
|
839
618
|
async function resolveAlreadyFiled({
|
|
840
619
|
finding,
|
|
@@ -860,8 +639,6 @@ async function resolveAlreadyFiled({
|
|
|
860
639
|
|
|
861
640
|
const hit = await probe(contentMarker);
|
|
862
641
|
if (hit) return { alreadyFiled: true, existing: hit };
|
|
863
|
-
// Legacy recognition — a pre-cutover follow-up carries the ordinal
|
|
864
|
-
// marker, not the content hash. Skip re-filing when it is present.
|
|
865
642
|
if (typeof spec.buildLegacyMarker === 'function') {
|
|
866
643
|
const legacyMarker = spec.buildLegacyMarker(epicId, finding.index);
|
|
867
644
|
if (legacyMarker) {
|
|
@@ -873,18 +650,9 @@ async function resolveAlreadyFiled({
|
|
|
873
650
|
}
|
|
874
651
|
|
|
875
652
|
/**
|
|
876
|
-
*
|
|
877
|
-
* (
|
|
878
|
-
*
|
|
879
|
-
* An **open** issue with a resolvable number is refreshed in place and
|
|
880
|
-
* recorded on `envelope.filed` with `action: 'updated'` — same array as a
|
|
881
|
-
* creation, because both are live writes this run performed and the roll-up
|
|
882
|
-
* that reports "filed" must count them alike.
|
|
883
|
-
*
|
|
884
|
-
* Anything else records `already-filed` and touches nothing: a closed
|
|
885
|
-
* follow-up is a decided one (reopening it would relitigate a human's call),
|
|
886
|
-
* and an unresolvable number or state is not licence to edit an issue we
|
|
887
|
-
* cannot identify.
|
|
653
|
+
* An open, numbered match is refreshed and recorded on `filed` as
|
|
654
|
+
* `action: 'updated'` (a live write, counted like a creation). Anything else
|
|
655
|
+
* is `already-filed` and untouched: a closed follow-up is a human's decision.
|
|
888
656
|
*
|
|
889
657
|
* @returns {Promise<boolean>} `true` when the recurrence was handled here.
|
|
890
658
|
*/
|
|
@@ -940,13 +708,6 @@ async function resolveFollowUpRecurrence({
|
|
|
940
708
|
return true;
|
|
941
709
|
}
|
|
942
710
|
|
|
943
|
-
/**
|
|
944
|
-
* Route a single finding (path-exists probe → repo routing → idempotency
|
|
945
|
-
* probe → cap → file) and fold the outcome into the running envelope. Story
|
|
946
|
-
* #4075 extracted this from `graduate`'s per-finding loop; Story #4415
|
|
947
|
-
* hardened it (path-less seam, probe-error distinction, legacy-marker
|
|
948
|
-
* recognition, filing cap, and cross-repo-deferred collection).
|
|
949
|
-
*/
|
|
950
711
|
async function processGraduateFinding({
|
|
951
712
|
finding,
|
|
952
713
|
envelope,
|
|
@@ -980,9 +741,7 @@ async function processGraduateFinding({
|
|
|
980
741
|
),
|
|
981
742
|
);
|
|
982
743
|
|
|
983
|
-
//
|
|
984
|
-
// the path-exists gate does not apply — probing an empty path would
|
|
985
|
-
// misclassify them `file-removed`. Only file-scoped findings are probed.
|
|
744
|
+
// A path-less finding would misclassify as `file-removed`; skip the probe.
|
|
986
745
|
const hasPath =
|
|
987
746
|
typeof finding.path === 'string' && finding.path.trim().length > 0;
|
|
988
747
|
if (hasPath) {
|
|
@@ -993,18 +752,13 @@ async function processGraduateFinding({
|
|
|
993
752
|
cwd,
|
|
994
753
|
timeoutMs,
|
|
995
754
|
});
|
|
996
|
-
// A probe failure is not proof the file is gone — record it distinctly
|
|
997
|
-
// so a transient git/spawn fault does not masquerade as a removal.
|
|
998
755
|
if (probeError) return skip('probe-error');
|
|
999
756
|
if (!exists) return skip('file-removed');
|
|
1000
757
|
}
|
|
1001
758
|
|
|
1002
759
|
const source = classifier(finding.path, null);
|
|
1003
|
-
//
|
|
1004
|
-
//
|
|
1005
|
-
// framework slug to the CONSUMER's repo, silently filing framework-owned
|
|
1006
|
-
// work in the wrong place (see `github/framework-repo.js`). Unroutable
|
|
1007
|
-
// findings are deferred and named, never re-pointed.
|
|
760
|
+
// Unroutable findings are deferred and named, never re-pointed at the
|
|
761
|
+
// consumer's repo.
|
|
1008
762
|
const routing = routeOwnership({ bucket: source, repos, currentRepo });
|
|
1009
763
|
if (!routing.routable) {
|
|
1010
764
|
const logLine = `[${spec.fnName}] unroutable ${source} finding (${routing.missingKey} is unset) — not filed: ${finding.title ?? finding.path ?? `finding ${finding.index}`}`;
|
|
@@ -1028,11 +782,7 @@ async function processGraduateFinding({
|
|
|
1028
782
|
|
|
1029
783
|
const contentMarker = spec.buildContentMarker(epicId, finding);
|
|
1030
784
|
|
|
1031
|
-
// In-process memo
|
|
1032
|
-
// invocation — e.g. the framework bucket of a retro rollup that also has
|
|
1033
|
-
// the same category in the consumer bucket — short-circuits a repeat in a
|
|
1034
|
-
// later bucket without spending a single spawn, and closes the same-rollup
|
|
1035
|
-
// race the eventually-consistent search index cannot.
|
|
785
|
+
// In-process memo closes the same-invocation race the search index cannot.
|
|
1036
786
|
if (filedMarkers?.has(contentMarker)) return skip('already-filed');
|
|
1037
787
|
|
|
1038
788
|
const { alreadyFiled, existing } = await resolveAlreadyFiled({
|
|
@@ -1047,10 +797,8 @@ async function processGraduateFinding({
|
|
|
1047
797
|
spec,
|
|
1048
798
|
});
|
|
1049
799
|
|
|
1050
|
-
//
|
|
1051
|
-
//
|
|
1052
|
-
// filing would carry (they agree with the marker by construction), and so
|
|
1053
|
-
// the recurrence path has the refreshed body to write.
|
|
800
|
+
// Built before dedup: the strong read scopes by these labels and a
|
|
801
|
+
// recurrence writes this body.
|
|
1054
802
|
const { title, body, labels } = spec.buildFollowUp({
|
|
1055
803
|
finding,
|
|
1056
804
|
source,
|
|
@@ -1077,15 +825,10 @@ async function processGraduateFinding({
|
|
|
1077
825
|
return;
|
|
1078
826
|
}
|
|
1079
827
|
|
|
1080
|
-
// Per-run filing cap — bounds the live writes this run performs. Checked
|
|
1081
|
-
// only on the would-file path: an `already-filed` finding resolved above
|
|
1082
|
-
// never reaches here. The excess is surfaced so a re-run picks it up.
|
|
1083
828
|
if (envelope.filed.length >= maxFilingsPerRun) return skip('cap-reached');
|
|
1084
829
|
|
|
1085
|
-
//
|
|
1086
|
-
//
|
|
1087
|
-
// --label <absent>` exits 0 with `[]`, so an absent label silently degrades
|
|
1088
|
-
// the dedup confirm too, not just the filing.
|
|
830
|
+
// Before the strong read too: `gh issue list --label <absent>` exits 0
|
|
831
|
+
// with `[]`, silently defeating the dedup confirm.
|
|
1089
832
|
const ensured = await ensureIssueLabels({
|
|
1090
833
|
owner: routedRepo.owner,
|
|
1091
834
|
repo: routedRepo.repo,
|
|
@@ -1098,17 +841,9 @@ async function processGraduateFinding({
|
|
|
1098
841
|
});
|
|
1099
842
|
envelope.errors.push(...ensured.errors);
|
|
1100
843
|
if (ensured.missing.length > 0) {
|
|
1101
|
-
// `gh issue create` would reject the whole call on the absent name; say
|
|
1102
|
-
// which label blocked it rather than replaying an opaque CLI failure.
|
|
1103
844
|
return skip('label-ensure-failed');
|
|
1104
845
|
}
|
|
1105
846
|
|
|
1106
|
-
// Strong read (would-file path only, Story #4657): the search probe reads
|
|
1107
|
-
// an eventually-consistent index that can miss a byte-identical duplicate
|
|
1108
|
-
// filed seconds earlier. Confirm against a strongly-consistent,
|
|
1109
|
-
// label-scoped `gh issue list` before creating. Skipped entirely on the
|
|
1110
|
-
// already-filed path above, so it never fires when the search probe
|
|
1111
|
-
// already matched.
|
|
1112
847
|
const confirmed = await findExistingFollowUp({
|
|
1113
848
|
markers:
|
|
1114
849
|
typeof spec.buildMatchTokens === 'function'
|
|
@@ -1175,12 +910,6 @@ async function processGraduateFinding({
|
|
|
1175
910
|
);
|
|
1176
911
|
}
|
|
1177
912
|
|
|
1178
|
-
/**
|
|
1179
|
-
* Render the durable cross-repo-deferred comment body from the collected
|
|
1180
|
-
* deferrals. Each row names the finding path/severity plus the would-be
|
|
1181
|
-
* `gh issue create` command so an operator (or a later cross-repo pass)
|
|
1182
|
-
* can act on it.
|
|
1183
|
-
*/
|
|
1184
913
|
function renderCrossRepoDeferredBody(deferred, spec) {
|
|
1185
914
|
const header =
|
|
1186
915
|
spec.crossRepoCommentHeader ??
|
|
@@ -1190,8 +919,6 @@ function renderCrossRepoDeferredBody(deferred, spec) {
|
|
|
1190
919
|
typeof finding.path === 'string' && finding.path.length > 0
|
|
1191
920
|
? `\`${finding.path}\``
|
|
1192
921
|
: '_(no path)_';
|
|
1193
|
-
// An unroutable finding has no destination to name — say which config
|
|
1194
|
-
// key would give it one instead of inventing a repo for the row.
|
|
1195
922
|
const destination = routedRepo
|
|
1196
923
|
? `${routedRepo.owner}/${routedRepo.repo}`
|
|
1197
924
|
: `**unroutable** (\`${missingKey}\` is unset)`;
|
|
@@ -1203,12 +930,7 @@ function renderCrossRepoDeferredBody(deferred, spec) {
|
|
|
1203
930
|
return [header, '', ...rows].join('\n');
|
|
1204
931
|
}
|
|
1205
932
|
|
|
1206
|
-
/**
|
|
1207
|
-
* Durably persist the cross-repo-deferred findings as a structured comment
|
|
1208
|
-
* on the Epic (upserted — one comment per graduator, refreshed in place).
|
|
1209
|
-
* Best-effort: a provider that cannot post comments is a no-op, and an
|
|
1210
|
-
* upsert failure lands in `envelope.errors` rather than throwing.
|
|
1211
|
-
*/
|
|
933
|
+
/** Best-effort upsert; failures land in `envelope.errors`, never thrown. */
|
|
1212
934
|
async function persistCrossRepoDeferred({
|
|
1213
935
|
epicId,
|
|
1214
936
|
provider,
|
|
@@ -1234,74 +956,36 @@ async function persistCrossRepoDeferred({
|
|
|
1234
956
|
}
|
|
1235
957
|
|
|
1236
958
|
/**
|
|
1237
|
-
*
|
|
1238
|
-
*
|
|
1239
|
-
*
|
|
1240
|
-
* `
|
|
1241
|
-
*
|
|
1242
|
-
* Each finding MUST carry `{ severity, path, summary, index }` and MAY carry
|
|
1243
|
-
* additional fields (e.g. `category`) that the builders use.
|
|
1244
|
-
*
|
|
1245
|
-
* The per-graduator variation lives entirely in the injected callbacks:
|
|
1246
|
-
*
|
|
1247
|
-
* - `buildContentMarker(epicId, finding)` — the content-hash HTML-comment
|
|
1248
|
-
* marker embedded in (and searched for in) follow-up bodies.
|
|
1249
|
-
* - `buildLegacyMarker(epicId, index)` — the pre-cutover ordinal marker,
|
|
1250
|
-
* probed for idempotency so legacy filings are not duplicated.
|
|
1251
|
-
* - `buildMatchTokens({ epicId, finding, contentMarker })` — optional; the
|
|
1252
|
-
* body substrings the strong read accepts as proof of a prior filing.
|
|
1253
|
-
* Defaults to `[contentMarker]`. A graduator whose marker format changed
|
|
1254
|
-
* returns the old shape here too, so the cutover recognizes the backlog
|
|
1255
|
-
* it already filed instead of duplicating it.
|
|
1256
|
-
* - `buildFollowUp({ finding, source, epicId, idMarker })` — returns
|
|
1257
|
-
* `{ title, body, labels }` for the issue to file.
|
|
1258
|
-
* - `buildCrossRepoLog({ finding, routedRepo, source })` — returns the
|
|
1259
|
-
* human-readable would-be-command string for a cross-repo skip.
|
|
1260
|
-
* - `decorateRecord(record, finding)` — copies finding-specific fields
|
|
1261
|
-
* (e.g. `lens`) onto a `skipped`/`filed` record before it is pushed.
|
|
1262
|
-
* - `crossRepoCommentAttrs` — discriminator attrs for the durable
|
|
1263
|
-
* cross-repo-deferred comment (so the two graduators do not clobber
|
|
1264
|
-
* each other's comment).
|
|
959
|
+
* Never throws; every failure lands in `errors[]`. Each finding carries
|
|
960
|
+
* `{ severity, path, summary, index }`. `spec` supplies `buildContentMarker`,
|
|
961
|
+
* `buildLegacyMarker`, optional `buildMatchTokens` (strong-read substrings,
|
|
962
|
+
* default `[contentMarker]`), `buildFollowUp`, `buildCrossRepoLog`,
|
|
963
|
+
* `decorateRecord`, and `crossRepoCommentAttrs`.
|
|
1265
964
|
*
|
|
1266
965
|
* @param {object} opts
|
|
1267
966
|
* @param {number} opts.epicId
|
|
1268
|
-
* @param {object} opts.provider
|
|
1269
|
-
* the durable cross-repo-deferred persistence
|
|
967
|
+
* @param {object} opts.provider
|
|
1270
968
|
* @param {object} [opts.config]
|
|
1271
969
|
* @param {{owner: string, repo: string}} opts.currentRepo
|
|
1272
|
-
* @param {{owner: string, repo: string}} [opts.frameworkRepo] —
|
|
1273
|
-
*
|
|
1274
|
-
*
|
|
1275
|
-
* named rather than filed in the wrong tracker.
|
|
1276
|
-
* @param {{owner: string, repo: string}} [opts.platformRepo] — the shared
|
|
1277
|
-
* platform/infra bucket, for a caller whose classifier can reach it.
|
|
970
|
+
* @param {{owner: string, repo: string}} [opts.frameworkRepo] — absent means
|
|
971
|
+
* unroutable, never the consumer's repo.
|
|
972
|
+
* @param {{owner: string, repo: string}} [opts.platformRepo]
|
|
1278
973
|
* @param {string} [opts.gitRef='HEAD']
|
|
1279
974
|
* @param {Function} [opts.classifier=classifyPathSource]
|
|
1280
975
|
* @param {string} [opts.ghPath='gh']
|
|
1281
976
|
* @param {Function} [opts.spawnImpl]
|
|
1282
977
|
* @param {string} [opts.cwd]
|
|
1283
|
-
* @param {number} [opts.timeoutMs]
|
|
1284
|
-
* @param {number} [opts.maxFilingsPerRun]
|
|
1285
|
-
* @param {Array<object>} opts.findings —
|
|
1286
|
-
*
|
|
1287
|
-
*
|
|
1288
|
-
* @param {Set<string
|
|
1289
|
-
*
|
|
1290
|
-
*
|
|
1291
|
-
* buckets) so a marker filed in one call short-circuits a repeat in the
|
|
1292
|
-
* next without a spawn. Defaults to a fresh per-call Set.
|
|
1293
|
-
* @param {Map<string, Set<string>>} [opts.labelCache] — per-repo memo of the
|
|
1294
|
-
* live label set, so the just-in-time label mint (Story #4828) costs one
|
|
1295
|
-
* `gh label list` per routed repo rather than one per finding. Share it
|
|
1296
|
-
* across the calls of one logical invocation, like `filedMarkers`.
|
|
1297
|
-
* @param {NodeJS.ProcessEnv} [opts.env] — injectable for the blast-radius
|
|
1298
|
-
* guard's context decision; defaults to `process.env`.
|
|
1299
|
-
* @param {string[]} [opts.execArgv] — ditto; defaults to `process.execArgv`.
|
|
978
|
+
* @param {number} [opts.timeoutMs]
|
|
979
|
+
* @param {number} [opts.maxFilingsPerRun]
|
|
980
|
+
* @param {Array<object>} opts.findings — a non-array is an error, not a no-op.
|
|
981
|
+
* @param {Set<string>} [opts.filedMarkers] — share across calls of one
|
|
982
|
+
* invocation so a repeat short-circuits without a spawn.
|
|
983
|
+
* @param {Map<string, Set<string>>} [opts.labelCache] — share likewise.
|
|
984
|
+
* @param {NodeJS.ProcessEnv} [opts.env]
|
|
985
|
+
* @param {string[]} [opts.execArgv]
|
|
1300
986
|
* @param {{info?: Function, warn?: Function, debug?: Function}} [opts.logger]
|
|
1301
|
-
* @param {object} opts.spec
|
|
987
|
+
* @param {object} opts.spec
|
|
1302
988
|
* @returns {Promise<{ filed: object[], skipped: object[], errors: string[] }>}
|
|
1303
|
-
* Each `filed` record carries `action: 'created'|'updated'` — both are live
|
|
1304
|
-
* writes this run performed, so a roll-up counting "filed" counts both.
|
|
1305
989
|
*/
|
|
1306
990
|
export async function graduate({
|
|
1307
991
|
epicId,
|
|
@@ -1339,10 +1023,6 @@ export async function graduate({
|
|
|
1339
1023
|
});
|
|
1340
1024
|
if (precondition) return { ...envelope, ...precondition };
|
|
1341
1025
|
|
|
1342
|
-
// Pre-parsed findings are the only source (Story #5003). The
|
|
1343
|
-
// structured-comment read/parse limb went with the audit-results
|
|
1344
|
-
// graduator: it walked an Epic's `verification-results` comment, and v2
|
|
1345
|
-
// has no Epics, so it could only ever resolve zero findings.
|
|
1346
1026
|
if (!Array.isArray(preParsedFindings)) {
|
|
1347
1027
|
return {
|
|
1348
1028
|
...envelope,
|
|
@@ -1351,8 +1031,7 @@ export async function graduate({
|
|
|
1351
1031
|
}
|
|
1352
1032
|
const findings = preParsedFindings;
|
|
1353
1033
|
|
|
1354
|
-
//
|
|
1355
|
-
// first spawn, so a refused context costs no child process at all.
|
|
1034
|
+
// Decided once, before any spawn.
|
|
1356
1035
|
const filing = resolveFilingContext({
|
|
1357
1036
|
spawnImpl,
|
|
1358
1037
|
...(env === undefined ? {} : { env }),
|
|
@@ -1378,10 +1057,6 @@ export async function graduate({
|
|
|
1378
1057
|
return envelope;
|
|
1379
1058
|
}
|
|
1380
1059
|
|
|
1381
|
-
// The ownership map the routing SSOT resolves against. `platform` is
|
|
1382
|
-
// absent for both graduators today (their classifier is binary) and is
|
|
1383
|
-
// threaded so a caller that does know a shared-infra repo routes there
|
|
1384
|
-
// rather than into the nearest plausible tracker.
|
|
1385
1060
|
const repos = {
|
|
1386
1061
|
consumer: currentRepo,
|
|
1387
1062
|
framework: frameworkRepo ?? null,
|