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
|
@@ -20,42 +20,19 @@ import {
|
|
|
20
20
|
|
|
21
21
|
const CRAP_WORKER_URL = new URL('./workers/crap-worker.js', import.meta.url);
|
|
22
22
|
|
|
23
|
-
//
|
|
24
|
-
// POOL_SERIAL_THRESHOLD docstring for the tuning rationale). Callers may
|
|
25
|
-
// override it per scan via `serialThreshold`, which is how the parity tests
|
|
26
|
-
// drive the pooled path without materialising a batch bigger than the
|
|
27
|
-
// cutover (Story #5109 raised it from 8 to 256).
|
|
23
|
+
// Overridable per scan via `serialThreshold` (parity tests drive the pool).
|
|
28
24
|
const SERIAL_THRESHOLD = POOL_SERIAL_THRESHOLD;
|
|
29
|
-
// 1.1.0 — TypeScript support landed in 5.29.0. Bumped from 1.0.0 because
|
|
30
|
-
// the scanner now emits CRAP rows for TS/TSX paths that the previous
|
|
31
|
-
// kernel could never reach. The CRAP formula and per-method scoring
|
|
32
|
-
// shape are unchanged for JS sources.
|
|
33
25
|
export const KERNEL_VERSION = '1.1.0';
|
|
34
26
|
export { resolveTsTranspilerVersion };
|
|
35
27
|
|
|
36
28
|
const SCHEMA_REF = '.agents/schemas/crap-baseline.schema.json';
|
|
37
29
|
|
|
38
|
-
/**
|
|
39
|
-
* Package whose resolved version is stamped as the scorer identity.
|
|
40
|
-
*
|
|
41
|
-
* `escomplex-plugin-metrics-module` computes the metrics. The retired
|
|
42
|
-
* `typhonjs-escomplex` facade did not, so stamping it described the shell
|
|
43
|
-
* rather than the scorer.
|
|
44
|
-
*/
|
|
30
|
+
/** Stamped as scorer identity: the package that actually computes the metrics. */
|
|
45
31
|
const SCORER_PACKAGE = 'escomplex-plugin-metrics-module';
|
|
46
32
|
|
|
47
33
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* The package read is `escomplex-plugin-metrics-module`, which owns the
|
|
52
|
-
* Halstead and maintainability math — not the displaced `typhonjs-escomplex`
|
|
53
|
-
* shell, which contributed a parser and a plugin bus and never a metric. The
|
|
54
|
-
* stamp is supposed to answer "could this scorer have produced different
|
|
55
|
-
* numbers", so it has to name the package that computes them.
|
|
56
|
-
*
|
|
57
|
-
* Returns `'0.0.0'` when the dependency cannot be found — callers treat that
|
|
58
|
-
* sentinel as "unknown environment" and may refuse to persist a baseline.
|
|
34
|
+
* Nearest installed `SCORER_PACKAGE` version walking up from `cwd`;
|
|
35
|
+
* `'0.0.0'` (unknown environment) when not found.
|
|
59
36
|
*
|
|
60
37
|
* @param {string} [cwd]
|
|
61
38
|
* @returns {string}
|
|
@@ -89,13 +66,8 @@ export function resolveEscomplexVersion(cwd = process.cwd()) {
|
|
|
89
66
|
}
|
|
90
67
|
|
|
91
68
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* `tsTranspilerVersion` stamps the resolved `typescript` package version so
|
|
96
|
-
* consumers can detect transpiler drift on TS rows. Defaults to the
|
|
97
|
-
* sentinel `'0.0.0'` when typescript is unresolvable — drift detection
|
|
98
|
-
* then becomes a no-op rather than failing the bake.
|
|
69
|
+
* Baseline envelope of the scored rows. `tsTranspilerVersion` lets consumers
|
|
70
|
+
* detect TS transpiler drift (`'0.0.0'` when typescript is unresolvable).
|
|
99
71
|
*
|
|
100
72
|
* @param {{
|
|
101
73
|
* rows: Array<{file: string, method: string, startLine: number, crap: number|null}>,
|
|
@@ -132,16 +104,9 @@ export function buildBaselineEnvelope({
|
|
|
132
104
|
}
|
|
133
105
|
|
|
134
106
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* and the CRAP formula's 0%-covered arm is the right answer for it. "No
|
|
139
|
-
* coverage run happened at all" — a freshly initialized story worktree with no
|
|
140
|
-
* `coverage/` directory — is an *absent* observation, and filling it with 0%
|
|
141
|
-
* drives every method to `c² + c`, failing the first commit on files the
|
|
142
|
-
* change never touched. Resolved once per scan and carried on each queue item
|
|
143
|
-
* so the pool workers, which only ever receive their own file's coverage
|
|
144
|
-
* entry, can still tell the two apart.
|
|
107
|
+
* "Tests never reached this method" scores 0% coverage; "no coverage run at
|
|
108
|
+
* all" is absent, not 0% (which would fail untouched files). Carried per queue
|
|
109
|
+
* item because pool workers only see their own file's entry.
|
|
145
110
|
*
|
|
146
111
|
* @param {object|null|undefined} coverage Parsed `coverage-final.json` map.
|
|
147
112
|
* @returns {boolean}
|
|
@@ -150,24 +115,11 @@ function isCoverageArtifactPresent(coverage) {
|
|
|
150
115
|
return coverage !== null && coverage !== undefined;
|
|
151
116
|
}
|
|
152
117
|
|
|
153
|
-
/**
|
|
154
|
-
* How many files to name when reporting the worst unresolved offenders. Long
|
|
155
|
-
* enough to point at a pattern, short enough to stay a readable CLI message.
|
|
156
|
-
*/
|
|
157
118
|
const WORST_OFFENDER_LIMIT = 5;
|
|
158
119
|
|
|
159
120
|
/**
|
|
160
|
-
* Method-resolution
|
|
161
|
-
*
|
|
162
|
-
* The updater used to persist a 100-row baseline built from 5023 dropped
|
|
163
|
-
* methods and log it as success — the rot that let a broken coverage join
|
|
164
|
-
* sit undetected for five weeks across three repos. These three helpers
|
|
165
|
-
* carry the counters that make a thin result *visible* and therefore
|
|
166
|
-
* refusable.
|
|
167
|
-
*
|
|
168
|
-
* The rate is deliberately measured over files that **do** have a coverage
|
|
169
|
-
* entry: a file the test run never touched has no join to fail, so counting
|
|
170
|
-
* it would dilute the signal the floor is meant to catch.
|
|
121
|
+
* Method-resolution counters that make a broken coverage join visible. Only
|
|
122
|
+
* files with a coverage entry count: an untouched file has no join to fail.
|
|
171
123
|
*/
|
|
172
124
|
function newResolutionAccumulator() {
|
|
173
125
|
return { resolved: 0, total: 0, byFile: [] };
|
|
@@ -197,27 +149,12 @@ function summarizeResolution(acc) {
|
|
|
197
149
|
};
|
|
198
150
|
}
|
|
199
151
|
|
|
200
|
-
/**
|
|
201
|
-
* Minimum number of joinable methods before the resolution-rate floor is
|
|
202
|
-
* enforced. A diff-scoped run can legitimately touch a handful of methods,
|
|
203
|
-
* where one unresolved method is a 50% rate and says nothing about the health
|
|
204
|
-
* of the join. Below this sample the rate is reported, never enforced.
|
|
205
|
-
*/
|
|
152
|
+
/** Below this sample (e.g. a small diff scope) the rate is not enforced. */
|
|
206
153
|
const MIN_RESOLUTION_SAMPLE = 25;
|
|
207
154
|
|
|
208
155
|
/**
|
|
209
|
-
* Fail-closed guard on the
|
|
210
|
-
*
|
|
211
|
-
* The updater used to persist a 100-row baseline distilled from 5023 dropped
|
|
212
|
-
* methods and log it as a success — which is exactly how a broken join stayed
|
|
213
|
-
* invisible for five weeks across three repositories. A thin result is now a
|
|
214
|
-
* refusal: the caller throws before anything is written, and the message names
|
|
215
|
-
* the rate, the counts, and the files carrying the most unresolved methods so
|
|
216
|
-
* the operator can tell "my tests do not cover that" apart from "the join is
|
|
217
|
-
* broken".
|
|
218
|
-
*
|
|
219
|
-
* Returns `null` when the run may proceed, or the operator-facing message when
|
|
220
|
-
* it must not.
|
|
156
|
+
* Fail-closed guard on the coverage join: a thin result refuses the write.
|
|
157
|
+
* Returns `null` to proceed, or the refusal message.
|
|
221
158
|
*
|
|
222
159
|
* @param {{resolvedMethods: number, joinableMethods: number, rate: number,
|
|
223
160
|
* worstFiles: Array<{file: string, unresolved: number, total: number}>}
|
|
@@ -248,24 +185,13 @@ export function checkResolutionFloor(resolution, floor) {
|
|
|
248
185
|
}
|
|
249
186
|
|
|
250
187
|
/**
|
|
251
|
-
* Parse
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
* Callers that need both scores for the same source string MUST use this
|
|
255
|
-
* helper rather than calling `calculateCrapForSource` and `calculateForSource`
|
|
256
|
-
* separately — doing so would parse the AST twice.
|
|
257
|
-
*
|
|
258
|
-
* Coverage-dependent CRAP values require a `coverageForFile` entry (the value
|
|
259
|
-
* from `coverage-final.json` for this file). Pass `null` when no coverage is
|
|
260
|
-
* available; method rows whose coverage cannot be resolved will carry
|
|
261
|
-
* `coverage: null` and `crap: null`.
|
|
188
|
+
* Parse once, deriving both MI and CRAP rows. Unresolvable coverage yields
|
|
189
|
+
* `coverage: null, crap: null` rows.
|
|
262
190
|
*
|
|
263
191
|
* @param {string} source Prepared (possibly transpiled) JavaScript source text.
|
|
264
192
|
* @param {object|null} coverageForFile Istanbul coverage entry for this file.
|
|
265
193
|
* @param {((line: number) => number|null)|null} [mapLine] Transpiled →
|
|
266
|
-
* original
|
|
267
|
-
* true})`; `null` for JavaScript, whose coordinates already match the
|
|
268
|
-
* coverage entry's.
|
|
194
|
+
* original line resolver; `null` for JavaScript.
|
|
269
195
|
* @returns {{
|
|
270
196
|
* report: object,
|
|
271
197
|
* miScore: number,
|
|
@@ -293,13 +219,8 @@ function analyzeOnce(source, coverageForFile, mapLine = null) {
|
|
|
293
219
|
}
|
|
294
220
|
|
|
295
221
|
/**
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
* incremental-join fields onto the surviving items.
|
|
299
|
-
*
|
|
300
|
-
* Story #2079: every relPath goes through path-canon so a scan from inside
|
|
301
|
-
* `.worktrees/<workspace>/` (with `cwd` pointing at the main checkout) cannot
|
|
302
|
-
* leak the worktree prefix into the on-disk baseline's `file` / `path` keys.
|
|
222
|
+
* Per-file work queue, scoped by `scopeSet`. Paths are canonicalised so a
|
|
223
|
+
* scan from inside `.worktrees/<ws>/` never leaks that prefix into baselines.
|
|
303
224
|
*
|
|
304
225
|
* @param {string[]} files Absolute paths, already sorted.
|
|
305
226
|
* @param {{
|
|
@@ -331,9 +252,6 @@ function buildScanQueue(
|
|
|
331
252
|
}
|
|
332
253
|
|
|
333
254
|
/**
|
|
334
|
-
* Project one finalized method row onto the enriched scan-row shape
|
|
335
|
-
* `compareCrap` and the baseline writer consume.
|
|
336
|
-
*
|
|
337
255
|
* @param {string} relPath Canonical repo-relative path of the scanned file.
|
|
338
256
|
* @param {object} mr A row from `finalizeMethodRowsWithBaseline`.
|
|
339
257
|
* @returns {object}
|
|
@@ -342,8 +260,7 @@ function projectScanRow(relPath, mr) {
|
|
|
342
260
|
return {
|
|
343
261
|
file: relPath,
|
|
344
262
|
method: mr.method,
|
|
345
|
-
//
|
|
346
|
-
// what lets the persisted row say so.
|
|
263
|
+
// `method` may be a derived anonymous identity.
|
|
347
264
|
anonymous: mr.anonymous === true,
|
|
348
265
|
startLine: mr.startLine,
|
|
349
266
|
cyclomatic: mr.cyclomatic,
|
|
@@ -356,35 +273,13 @@ function projectScanRow(relPath, mr) {
|
|
|
356
273
|
}
|
|
357
274
|
|
|
358
275
|
/**
|
|
359
|
-
*
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
* A file neither path could score at all — unreadable, untranspilable, or one
|
|
368
|
-
* the kernel could not parse — is dropped and counted in `unscorableFiles`
|
|
369
|
-
* (Story #5311). Unscorable is not scored-as-nothing: without this counter a
|
|
370
|
-
* dropped file is indistinguishable from a file with no methods, which is what
|
|
371
|
-
* let a whole parse-failure class leave the baseline silently.
|
|
372
|
-
*
|
|
373
|
-
* When `scopeFiles` is provided (the `--changed-since` code path) files
|
|
374
|
-
* discovered via directory walking are filtered against that set before any
|
|
375
|
-
* I/O or scoring happens — so pre-push / PR-CI runs never pay the
|
|
376
|
-
* parse-and-score cost on untouched files.
|
|
377
|
-
*
|
|
378
|
-
* When `preScannedFiles` is provided (an array of absolute paths already
|
|
379
|
-
* collected by a prior `scanDirectory` pass over the same `targetDirs`), the
|
|
380
|
-
* directory walk is skipped entirely — the supplied list is used as-is.
|
|
381
|
-
* Callers that run both CRAP and MI passes over the same target dirs (e.g.
|
|
382
|
-
* `regenerateMainFromTree`) SHOULD pass the MI scan's file list here so the
|
|
383
|
-
* tree is walked only once per run.
|
|
384
|
-
*
|
|
385
|
-
* `incremental` (Story #4981) resolves an untouched file's methods from
|
|
386
|
-
* `crap-baseline-join.js#finalizeMethodRowsWithBaseline` instead of
|
|
387
|
-
* requiring fresh coverage; omitted (the default), behaviour is unchanged.
|
|
276
|
+
* Score every method under `targetDirs` (no disk writes). Files without
|
|
277
|
+
* coverage are skipped under `requireCoverage`; methods without resolvable
|
|
278
|
+
* coverage are always dropped, so baselines never hold partial rows. A file
|
|
279
|
+
* that cannot be read, transpiled or parsed is counted in `unscorableFiles`
|
|
280
|
+
* so no drop is silent. `scopeFiles` filters before any I/O;
|
|
281
|
+
* `preScannedFiles` skips the walk; `incremental` resolves untouched files
|
|
282
|
+
* from the baseline instead of fresh coverage.
|
|
388
283
|
*
|
|
389
284
|
* @param {{
|
|
390
285
|
* targetDirs: string[],
|
|
@@ -430,8 +325,6 @@ export async function scanAndScore({
|
|
|
430
325
|
: scopeFiles instanceof Set
|
|
431
326
|
? scopeFiles
|
|
432
327
|
: new Set(scopeFiles);
|
|
433
|
-
// When the caller supplies a pre-walked file list (e.g. from a prior MI
|
|
434
|
-
// scan over the same target dirs), skip the directory walk entirely.
|
|
435
328
|
const files = preScannedFiles != null ? [...preScannedFiles] : [];
|
|
436
329
|
if (preScannedFiles == null) {
|
|
437
330
|
for (const dir of targetDirs) {
|
|
@@ -443,8 +336,6 @@ export async function scanAndScore({
|
|
|
443
336
|
|
|
444
337
|
const incrementalCtx = resolveIncrementalContext(incremental);
|
|
445
338
|
|
|
446
|
-
// Build the work-queue first so scopeFile filtering happens before
|
|
447
|
-
// any I/O / IPC. `scannedFiles` is the in-scope count.
|
|
448
339
|
const queue = buildScanQueue(files, {
|
|
449
340
|
cwd,
|
|
450
341
|
scopeSet,
|
|
@@ -454,9 +345,7 @@ export async function scanAndScore({
|
|
|
454
345
|
});
|
|
455
346
|
const scannedFiles = queue.length;
|
|
456
347
|
|
|
457
|
-
//
|
|
458
|
-
// per-file baseline lookup Maps the join needs do not cross the worker
|
|
459
|
-
// boundary (Story #4981).
|
|
348
|
+
// Always serial in incremental mode: the baseline Maps don't cross workers.
|
|
460
349
|
const runSerial = queue.length < serialThreshold || Boolean(incremental);
|
|
461
350
|
const perFile = runSerial
|
|
462
351
|
? queue.map((item) => ({ item, result: scoreFileSerial(item, coverage) }))
|
|
@@ -469,9 +358,7 @@ export async function scanAndScore({
|
|
|
469
358
|
const resolution = newResolutionAccumulator();
|
|
470
359
|
for (const { item, result } of perFile) {
|
|
471
360
|
if (!result) {
|
|
472
|
-
//
|
|
473
|
-
// answered). Dropped like any other unscorable file, and counted — the
|
|
474
|
-
// point of the counter is that no drop is silent.
|
|
361
|
+
// Pool-level error the worker never answered.
|
|
475
362
|
unscorableFiles += 1;
|
|
476
363
|
continue;
|
|
477
364
|
}
|
|
@@ -480,9 +367,6 @@ export async function scanAndScore({
|
|
|
480
367
|
continue;
|
|
481
368
|
}
|
|
482
369
|
if (result.rows === null) {
|
|
483
|
-
// read/transpile/parse failure: drop and move on, but if the worker
|
|
484
|
-
// attached an error message (calculateCrapForSource throw) surface it
|
|
485
|
-
// so the run isn't silent on the ops side.
|
|
486
370
|
unscorableFiles += 1;
|
|
487
371
|
if (result.error) {
|
|
488
372
|
Logger.warn(
|
|
@@ -515,13 +399,7 @@ export async function scanAndScore({
|
|
|
515
399
|
};
|
|
516
400
|
}
|
|
517
401
|
|
|
518
|
-
/**
|
|
519
|
-
* In-process scorer used by both the small-batch fast path and as the
|
|
520
|
-
* reference implementation against which the worker output is asserted
|
|
521
|
-
* byte-for-byte in the cpu-pool tests.
|
|
522
|
-
*
|
|
523
|
-
* Uses `analyzeOnce` so the source is parsed a single time.
|
|
524
|
-
*/
|
|
402
|
+
/** In-process scorer; the reference the worker output must match exactly. */
|
|
525
403
|
function scoreFileSerial(
|
|
526
404
|
{
|
|
527
405
|
abs,
|
|
@@ -576,9 +454,7 @@ function scoreFileSerial(
|
|
|
576
454
|
}
|
|
577
455
|
|
|
578
456
|
async function scoreFilesViaPool(queue, coverage) {
|
|
579
|
-
//
|
|
580
|
-
// receive only their file's entry rather than the whole map. This removes the
|
|
581
|
-
// O(workers × coverageMapSize) structured-clone at spawn time.
|
|
457
|
+
// Send each worker only its file's entry, not the whole coverage map.
|
|
582
458
|
const enrichedQueue = queue.map((item) => ({
|
|
583
459
|
...item,
|
|
584
460
|
coverageEntry: findCoverageEntry(coverage, item.relPath),
|
|
@@ -1,87 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* bootstrap-defaulted and resolver-resolved, and were then read by nothing:
|
|
7
|
-
* `cyclomaticMustFix` had no consumer at all, and `cyclomaticFlag` was
|
|
8
|
-
* shadowed by a hardcoded `8` in a `quality-preview` display column. A ceiling
|
|
9
|
-
* nothing enforces is worse than no ceiling, because the workflow docs promise
|
|
10
|
-
* the merge will be refused.
|
|
11
|
-
*
|
|
12
|
-
* Story #5313 retired the `cyclomaticMustFix` config key: the ratchet's
|
|
13
|
-
* ceiling is the fixed {@link CYCLOMATIC_CEILING} (12), so a consumer cannot
|
|
14
|
-
* bound this gate by tuning a number, and `cyclomaticFlag` is the one
|
|
15
|
-
* advisory knob — `quality-preview.js` reports over-flag methods and exits 0
|
|
16
|
-
* on them.
|
|
17
|
-
*
|
|
18
|
-
* This module is that enforcement, shaped as a **ratchet** rather than a
|
|
19
|
-
* cliff. The repository already carries dozens of functions above the
|
|
20
|
-
* must-fix ceiling; failing every one of them at once would have made the
|
|
21
|
-
* gate un-landable and it would have been disabled the same day. So the
|
|
22
|
-
* committed `baselines/cyclomatic.json` records the existing breaches per
|
|
23
|
-
* file, and the gate fails only when a change **adds** an over-ceiling
|
|
24
|
-
* function to a file that had none, adds one **beyond** that file's recorded
|
|
25
|
-
* count, or pushes a file's worst function **higher** than recorded. Burning
|
|
26
|
-
* the recorded breaches down is a separate, always-permitted motion — a
|
|
27
|
-
* shrinking baseline is the success signal.
|
|
28
|
-
*
|
|
29
|
-
* Scope: the module walks the `maintainability` gate's `targetDirs` /
|
|
30
|
-
* `ignoreGlobs`. Both instruments read the same coverage-free escomplex
|
|
31
|
-
* surface, so re-declaring the scope under `codingGuardrails` would have
|
|
32
|
-
* added two config keys whose only correct value is "whatever maintainability
|
|
33
|
-
* says".
|
|
2
|
+
* Cyclomatic ceiling as a ratchet, not a cliff: `baselines/cyclomatic.json`
|
|
3
|
+
* records existing breaches per file, and the gate fails only when a change
|
|
4
|
+
* adds an over-ceiling function beyond a file's recorded count or raises its
|
|
5
|
+
* worst one. Scope is borrowed from the maintainability gate.
|
|
34
6
|
*
|
|
35
7
|
* @module lib/cyclomatic-ceiling
|
|
36
8
|
*/
|
|
37
9
|
|
|
38
10
|
import path from 'node:path';
|
|
11
|
+
import { CODING_GUARDRAILS } from './config/quality.js';
|
|
39
12
|
import { selectFilesToScore } from './cyclomatic-scope.js';
|
|
40
13
|
import { calculateReportForFile } from './maintainability-engine.js';
|
|
41
14
|
import { scanDirectory } from './maintainability-utils.js';
|
|
42
15
|
|
|
43
|
-
/** Default location of the committed breach baseline. */
|
|
44
16
|
export const DEFAULT_CYCLOMATIC_BASELINE = 'baselines/cyclomatic.json';
|
|
45
17
|
|
|
46
18
|
/**
|
|
47
|
-
*
|
|
48
|
-
* config key — since Story #5313.
|
|
19
|
+
* Fixed, not configurable, so a consumer cannot loosen the gate.
|
|
49
20
|
* @type {number}
|
|
50
21
|
*/
|
|
51
22
|
export const CYCLOMATIC_CEILING = 12;
|
|
52
23
|
|
|
53
|
-
/** Baseline `$schema` marker, matching the sibling ratchet baselines. */
|
|
54
24
|
const CYCLOMATIC_BASELINE_SCHEMA =
|
|
55
25
|
'https://mandrel.dev/baselines/cyclomatic.schema.json';
|
|
56
26
|
|
|
57
27
|
/**
|
|
58
|
-
* Resolve the enforcement policy from a resolved `delivery.quality` block.
|
|
59
|
-
*
|
|
60
|
-
* `mustFix` is the fixed {@link CYCLOMATIC_CEILING}; `flag` comes from
|
|
61
|
-
* `resolveCodingGuardrails` (advisory only). `targetDirs` / `ignoreGlobs`
|
|
62
|
-
* are borrowed from the maintainability gate (see the module note).
|
|
63
|
-
*
|
|
64
28
|
* @param {object | null | undefined} quality resolved `delivery.quality`
|
|
65
29
|
* @returns {{ mustFix: number, flag: number, targetDirs: string[], ignoreGlobs: string[] }}
|
|
66
30
|
*/
|
|
67
31
|
export function resolveCyclomaticPolicy(quality) {
|
|
68
|
-
const guardrails = quality?.codingGuardrails ?? {};
|
|
69
32
|
const mi = quality?.maintainability ?? {};
|
|
70
33
|
return {
|
|
71
34
|
mustFix: CYCLOMATIC_CEILING,
|
|
72
|
-
flag:
|
|
35
|
+
flag: CODING_GUARDRAILS.cyclomaticFlag,
|
|
73
36
|
targetDirs: Array.isArray(mi.targetDirs) ? mi.targetDirs : [],
|
|
74
37
|
ignoreGlobs: Array.isArray(mi.ignoreGlobs) ? mi.ignoreGlobs : [],
|
|
75
38
|
};
|
|
76
39
|
}
|
|
77
40
|
|
|
78
41
|
/**
|
|
79
|
-
*
|
|
80
|
-
* file carries no function above `ceiling`.
|
|
81
|
-
*
|
|
82
|
-
* Pure. Module-private: tests reach it through `scanCyclomatic`'s `scoreFile`
|
|
83
|
-
* seam, which keeps the row math exercised without adding an export whose only
|
|
84
|
-
* importer is a test (the `--production` dead-export pass discounts those).
|
|
42
|
+
* `null` when no function exceeds `ceiling`. Tested via the `scoreFile` seam.
|
|
85
43
|
*
|
|
86
44
|
* @param {string} file repo-relative POSIX path
|
|
87
45
|
* @param {Array<{ cyclomatic?: number }>} methods
|
|
@@ -103,26 +61,10 @@ function breachRowFor(file, methods, ceiling) {
|
|
|
103
61
|
}
|
|
104
62
|
|
|
105
63
|
/**
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* `
|
|
110
|
-
* production callers omit it.
|
|
111
|
-
*
|
|
112
|
-
* **Scoped scoring (Story #5109).** The directory walk is cheap — a few
|
|
113
|
-
* `readdir` calls — but scoring is an escomplex parse per file, and re-parsing
|
|
114
|
-
* the whole tree on every CI run cost 0.94 s to re-derive rows that could not
|
|
115
|
-
* have moved. `scopeFiles`, when supplied, is the set of repo-relative POSIX
|
|
116
|
-
* paths that are still *scored*; everything else is walked, counted, and
|
|
117
|
-
* skipped. That is sound precisely because this gate is a ratchet: a verdict
|
|
118
|
-
* exists only for a file that either changed (so it must be re-scored) or is
|
|
119
|
-
* already recorded in the baseline (so its recorded count must be re-derived
|
|
120
|
-
* to detect an improvement or a removal). A file that is neither cannot
|
|
121
|
-
* produce `added` or `worsened`, and `removed` is computed from baseline files
|
|
122
|
-
* — all of which are in scope by construction. `scannedFiles` therefore keeps
|
|
123
|
-
* reporting the **whole walk**, so the reported scan surface does not shrink
|
|
124
|
-
* just because the scoring did. Callers pass `null` (the default) for the
|
|
125
|
-
* whole-tree scan, which `--update` and `BASELINE_SCOPE=full` always do.
|
|
64
|
+
* Breach rows sorted by path. `scopeFiles` limits which walked files are
|
|
65
|
+
* scored — sound for a ratchet, since only a changed or baseline-recorded
|
|
66
|
+
* file can yield a verdict. `scannedFiles` still reports the whole walk;
|
|
67
|
+
* `null` scope scores everything.
|
|
126
68
|
*
|
|
127
69
|
* @param {{
|
|
128
70
|
* targetDirs: string[],
|
|
@@ -170,17 +112,7 @@ export function scanCyclomatic({
|
|
|
170
112
|
}
|
|
171
113
|
|
|
172
114
|
/**
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* Four buckets, only the first two of which fail the gate:
|
|
176
|
-
*
|
|
177
|
-
* - `added` — a file whose over-ceiling function count rose (including
|
|
178
|
-
* 0 → 1, i.e. a brand-new breach in new or changed code).
|
|
179
|
-
* - `worsened` — a file whose worst function got worse than recorded.
|
|
180
|
-
* - `removed` — a file that no longer breaches at all.
|
|
181
|
-
* - `improved` — a file that breaches less than recorded.
|
|
182
|
-
*
|
|
183
|
-
* Pure; identity is the repo-relative file path.
|
|
115
|
+
* Only `added` (count rose) and `worsened` (worst function rose) fail.
|
|
184
116
|
*
|
|
185
117
|
* @param {Array<{file: string, methodsAboveCeiling: number, maxCyclomatic: number}>} baselineRows
|
|
186
118
|
* @param {Array<{file: string, methodsAboveCeiling: number, maxCyclomatic: number}>} currentRows
|
|
@@ -231,10 +163,6 @@ export function diffCyclomaticRows(baselineRows, currentRows) {
|
|
|
231
163
|
}
|
|
232
164
|
|
|
233
165
|
/**
|
|
234
|
-
* Assemble the committed baseline envelope. The rollup is deliberately
|
|
235
|
-
* derived, never hand-written: a zero-row baseline here reports zero breaches
|
|
236
|
-
* because the repository has none, not because nobody produced it.
|
|
237
|
-
*
|
|
238
166
|
* @param {{ rows: Array<object>, ceiling: number, generatedAt?: string }} args
|
|
239
167
|
* @returns {object}
|
|
240
168
|
*/
|
|
@@ -262,8 +190,7 @@ export function buildCyclomaticEnvelope({ rows, ceiling, generatedAt }) {
|
|
|
262
190
|
}
|
|
263
191
|
|
|
264
192
|
/**
|
|
265
|
-
*
|
|
266
|
-
* operators see the "no drift" signal rather than silence.
|
|
193
|
+
* Always ends with a summary line, even on a clean run.
|
|
267
194
|
*
|
|
268
195
|
* @param {{ added: Array, worsened: Array, removed: Array, improved: Array }} diff
|
|
269
196
|
* @param {number} ceiling
|
|
@@ -1,23 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* cyclomatic-scope.js —
|
|
3
|
-
* (
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* escomplex work to re-derive rows that could not have moved. The scan surface
|
|
7
|
-
* is unchanged; only the *scoring* is narrowed, and it is narrowed to exactly
|
|
8
|
-
* the two sets a ratchet verdict can come from:
|
|
9
|
-
*
|
|
10
|
-
* - **every file already recorded in the baseline**, because `improved`,
|
|
11
|
-
* `worsened` and `removed` are all computed by re-deriving a recorded
|
|
12
|
-
* file's current count;
|
|
13
|
-
* - **everything this branch changed** against `project.baseBranch`,
|
|
14
|
-
* including the staged, unstaged and untracked working tree, because
|
|
15
|
-
* `added` is what a change introduces — and a pre-push gate that only
|
|
16
|
-
* looked at committed work would wave through the breach an operator is
|
|
17
|
-
* about to commit.
|
|
18
|
-
*
|
|
19
|
-
* A file in neither set is unchanged and unrecorded: it cannot produce a
|
|
20
|
-
* verdict in any bucket.
|
|
2
|
+
* cyclomatic-scope.js — narrow cyclomatic scoring to the only files that can
|
|
3
|
+
* produce a ratchet verdict: every baseline-recorded file (improved /
|
|
4
|
+
* worsened / removed) plus everything changed against the base branch,
|
|
5
|
+
* including staged, unstaged and untracked work (added).
|
|
21
6
|
*
|
|
22
7
|
* @module lib/cyclomatic-scope
|
|
23
8
|
*/
|
|
@@ -27,11 +12,7 @@ import { createGitInterface } from './git-utils.js';
|
|
|
27
12
|
import { isIgnoredByGlobs } from './maintainability-utils.js';
|
|
28
13
|
|
|
29
14
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* Three, not four: `git diff --name-only HEAD` already reports the staged
|
|
33
|
-
* *and* unstaged deltas, so a separate `--cached` pass would only re-list
|
|
34
|
-
* paths this one has, at the cost of another process spawn.
|
|
15
|
+
* `diff HEAD` already covers staged and unstaged, so no `--cached` pass.
|
|
35
16
|
*
|
|
36
17
|
* @type {ReadonlyArray<ReadonlyArray<string>>}
|
|
37
18
|
*/
|
|
@@ -42,14 +23,8 @@ const CHANGE_PROBES = Object.freeze([
|
|
|
42
23
|
]);
|
|
43
24
|
|
|
44
25
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* **Fails open, never closed.** Any git failure — a shallow clone, a missing
|
|
49
|
-
* base ref, a fixture directory that is not a repository at all — returns
|
|
50
|
-
* `null`, and the caller scans everything. Narrowing on an unreadable scope
|
|
51
|
-
* is how a ratchet silently stops ratcheting; paying for a whole-tree scan is
|
|
52
|
-
* not.
|
|
26
|
+
* Fails open: any git failure returns `null` (scan everything) — narrowing
|
|
27
|
+
* on an unreadable scope is how a ratchet silently stops ratcheting.
|
|
53
28
|
*
|
|
54
29
|
* @param {{
|
|
55
30
|
* cwd: string,
|
|
@@ -57,10 +32,6 @@ const CHANGE_PROBES = Object.freeze([
|
|
|
57
32
|
* baselineRows?: Array<{ file?: string }>,
|
|
58
33
|
* git?: ReturnType<typeof createGitInterface>,
|
|
59
34
|
* }} args
|
|
60
|
-
* Module-private: `resolveScanScope` below is the only caller, and it is the
|
|
61
|
-
* one the CLI actually asks. Exporting both would ship a seam whose only
|
|
62
|
-
* importer is a test, which the `--production` dead-export pass discounts.
|
|
63
|
-
*
|
|
64
35
|
* @returns {Set<string> | null}
|
|
65
36
|
*/
|
|
66
37
|
function resolveCyclomaticScope({ cwd, baseRef, baselineRows = [], git }) {
|
|
@@ -84,11 +55,7 @@ function resolveCyclomaticScope({ cwd, baseRef, baselineRows = [], git }) {
|
|
|
84
55
|
}
|
|
85
56
|
|
|
86
57
|
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* `--update` rewrites the baseline from the current tree, and
|
|
90
|
-
* `BASELINE_SCOPE=full` is the operator's explicit "re-derive everything" —
|
|
91
|
-
* both must see the whole tree, so both return `null`.
|
|
58
|
+
* `--update` and `BASELINE_SCOPE=full` must see the whole tree.
|
|
92
59
|
*
|
|
93
60
|
* @param {{
|
|
94
61
|
* cwd: string,
|
|
@@ -98,7 +65,7 @@ function resolveCyclomaticScope({ cwd, baseRef, baselineRows = [], git }) {
|
|
|
98
65
|
* baselineRows?: Array<{ file?: string }>,
|
|
99
66
|
* git?: ReturnType<typeof createGitInterface>,
|
|
100
67
|
* }} args
|
|
101
|
-
* @returns {Set<string> | null}
|
|
68
|
+
* @returns {Set<string> | null}
|
|
102
69
|
*/
|
|
103
70
|
export function resolveScanScope({
|
|
104
71
|
cwd,
|
|
@@ -118,14 +85,7 @@ export function resolveScanScope({
|
|
|
118
85
|
}
|
|
119
86
|
|
|
120
87
|
/**
|
|
121
|
-
*
|
|
122
|
-
* scored, applying the gate's `ignoreGlobs` and then the diff scope.
|
|
123
|
-
*
|
|
124
|
-
* Kept here rather than inside `scanCyclomatic` so "which files count" lives
|
|
125
|
-
* in one module: the ignore rule and the scope rule are the same decision
|
|
126
|
-
* asked twice, and splitting them across two files is how they drift.
|
|
127
|
-
*
|
|
128
|
-
* @param {string[]} files Absolute paths, as walked.
|
|
88
|
+
* @param {string[]} files
|
|
129
89
|
* @param {{ cwd: string, ignoreGlobs?: string[], scopeFiles?: Set<string> | null }} args
|
|
130
90
|
* @returns {Array<{ abs: string, rel: string }>}
|
|
131
91
|
*/
|