mandrel 2.60.0 → 2.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/README.md +10 -10
- package/.agents/agents/story-worker.md +1 -1
- package/.agents/docs/agentrc-reference.json +4 -82
- package/.agents/docs/configuration.md +20 -87
- package/.agents/docs/workflows.md +1 -1
- package/.agents/instructions.md +1 -3
- package/.agents/rules/gherkin-standards.md +4 -0
- package/.agents/schemas/agentrc.schema.json +11 -486
- package/.agents/schemas/story-deliver-terminal.schema.json +10 -0
- package/.agents/schemas/validation-evidence.schema.json +2 -1
- package/.agents/scripts/README.md +14 -14
- package/.agents/scripts/acceptance-eval.js +32 -164
- package/.agents/scripts/agents-bootstrap-github.js +27 -129
- package/.agents/scripts/apply-quality-bootstrap.js +4 -40
- package/.agents/scripts/audit-baselines.js +6 -27
- package/.agents/scripts/audit-labels-bootstrap.js +5 -29
- package/.agents/scripts/audit-to-stories.js +91 -361
- package/.agents/scripts/boot-sweep.js +19 -72
- package/.agents/scripts/bootstrap.js +74 -395
- package/.agents/scripts/ceremony-derive.js +9 -45
- package/.agents/scripts/check-arch-cycles.js +14 -64
- package/.agents/scripts/check-baselines.js +8 -48
- package/.agents/scripts/check-context-budget.js +46 -172
- package/.agents/scripts/check-cyclomatic.js +12 -44
- package/.agents/scripts/check-dead-exports.js +13 -64
- package/.agents/scripts/check-doc-links.js +38 -186
- package/.agents/scripts/check-gherkin-corpus.js +24 -127
- package/.agents/scripts/check-test-temp-hygiene.js +28 -169
- package/.agents/scripts/coverage-capture.js +32 -99
- package/.agents/scripts/deliver-light.js +14 -101
- package/.agents/scripts/deliver-recover.js +6 -42
- package/.agents/scripts/deliver-run.js +36 -133
- package/.agents/scripts/diagnose-friction.js +24 -116
- package/.agents/scripts/drain-pending-cleanup.js +1 -1
- package/.agents/scripts/evidence-gate.js +23 -85
- package/.agents/scripts/file-ci-gap.js +10 -50
- package/.agents/scripts/generate-config-docs.js +30 -170
- package/.agents/scripts/generate-lens-checklists.js +8 -52
- package/.agents/scripts/generate-skills-index.js +14 -112
- package/.agents/scripts/generate-workflows-doc.js +10 -70
- package/.agents/scripts/git-cleanup.js +2 -34
- package/.agents/scripts/lib/Graph.js +24 -81
- package/.agents/scripts/lib/ITicketingProvider.js +47 -143
- package/.agents/scripts/lib/Logger.js +14 -76
- package/.agents/scripts/lib/audit-baselines/engine.js +11 -31
- package/.agents/scripts/lib/audit-baselines/gate-surface.js +3 -17
- package/.agents/scripts/lib/audit-baselines/headroom.js +4 -20
- package/.agents/scripts/lib/audit-baselines/hotspots.js +3 -15
- package/.agents/scripts/lib/audit-baselines/kinds.js +23 -89
- package/.agents/scripts/lib/audit-baselines/outliers.js +6 -23
- package/.agents/scripts/lib/audit-baselines/read.js +3 -16
- package/.agents/scripts/lib/audit-baselines/staleness.js +7 -26
- package/.agents/scripts/lib/audit-baselines/surface-entry.js +7 -28
- package/.agents/scripts/lib/audit-baselines/trend.js +7 -20
- package/.agents/scripts/lib/audit-baselines/weights.js +9 -37
- package/.agents/scripts/lib/audit-suite/audit-rules-reader.js +3 -18
- package/.agents/scripts/lib/audit-suite/checklist-threading.js +26 -124
- package/.agents/scripts/lib/audit-suite/dispatch-checklist.js +14 -45
- package/.agents/scripts/lib/audit-suite/findings.js +12 -52
- package/.agents/scripts/lib/audit-suite/frontmatter.js +5 -29
- package/.agents/scripts/lib/audit-suite/index.js +1 -15
- package/.agents/scripts/lib/audit-suite/lens-checklist.js +10 -45
- package/.agents/scripts/lib/audit-suite/lens-diff-floor.js +11 -76
- package/.agents/scripts/lib/audit-suite/runner.js +13 -43
- package/.agents/scripts/lib/audit-suite/selector.js +49 -349
- package/.agents/scripts/lib/audit-suite/substitutions.js +12 -40
- package/.agents/scripts/lib/audit-suite/workflow-loader.js +3 -15
- package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +11 -73
- package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +8 -37
- package/.agents/scripts/lib/audit-to-stories/build-story-body.js +25 -143
- package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +14 -80
- package/.agents/scripts/lib/audit-to-stories/epic-grouping-directive.js +4 -18
- package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +7 -40
- package/.agents/scripts/lib/audit-to-stories/group-findings.js +9 -39
- package/.agents/scripts/lib/audit-to-stories/issue-corpus.js +10 -66
- package/.agents/scripts/lib/audit-to-stories/issue-index.js +6 -30
- package/.agents/scripts/lib/audit-to-stories/issues-file.js +6 -36
- package/.agents/scripts/lib/audit-to-stories/ledger-commit.js +17 -69
- package/.agents/scripts/lib/audit-to-stories/ledger-pr.js +17 -85
- package/.agents/scripts/lib/audit-to-stories/ledger-record.js +10 -48
- package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +38 -146
- package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +7 -42
- package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +10 -57
- package/.agents/scripts/lib/baseline-loader.js +12 -51
- package/.agents/scripts/lib/baseline-schema-registry.js +5 -22
- package/.agents/scripts/lib/baselines/component-matcher.js +3 -12
- package/.agents/scripts/lib/baselines/components.js +10 -61
- package/.agents/scripts/lib/baselines/coverage-updater-cli.js +7 -36
- package/.agents/scripts/lib/baselines/crap-preview-incremental.js +5 -21
- package/.agents/scripts/lib/baselines/crap-preview-scan.js +19 -45
- package/.agents/scripts/lib/baselines/crap-updater-cli.js +16 -65
- package/.agents/scripts/lib/baselines/diff-scope-cli.js +5 -33
- package/.agents/scripts/lib/baselines/duplication-scanner.js +11 -60
- package/.agents/scripts/lib/baselines/env-overrides.js +12 -67
- package/.agents/scripts/lib/baselines/envelope.js +13 -129
- package/.agents/scripts/lib/baselines/exit-codes.js +6 -49
- package/.agents/scripts/lib/baselines/git-base.js +23 -142
- package/.agents/scripts/lib/baselines/kernel.js +11 -111
- package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +9 -47
- package/.agents/scripts/lib/baselines/kinds/_crap-read.js +8 -51
- package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +7 -62
- package/.agents/scripts/lib/baselines/kinds/bundle-size.js +8 -29
- package/.agents/scripts/lib/baselines/kinds/coverage.js +3 -15
- package/.agents/scripts/lib/baselines/kinds/crap.js +94 -415
- package/.agents/scripts/lib/baselines/kinds/duplication.js +4 -30
- package/.agents/scripts/lib/baselines/kinds/kind-factory.js +7 -53
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +15 -80
- package/.agents/scripts/lib/baselines/kinds/mutation.js +12 -72
- package/.agents/scripts/lib/baselines/maintainability-baseline-io.js +4 -11
- package/.agents/scripts/lib/baselines/merge-envelopes.js +30 -146
- package/.agents/scripts/lib/baselines/path-canon.js +19 -128
- package/.agents/scripts/lib/baselines/preview-gates.js +8 -37
- package/.agents/scripts/lib/baselines/reader.js +14 -107
- package/.agents/scripts/lib/baselines/refresh-service.js +35 -252
- package/.agents/scripts/lib/baselines/scope.js +11 -135
- package/.agents/scripts/lib/baselines/writer.js +16 -149
- package/.agents/scripts/lib/bdd-runner-detect.js +18 -113
- package/.agents/scripts/lib/bdd-scenario-budget.js +9 -36
- package/.agents/scripts/lib/bdd-scenario-scanner.js +11 -73
- package/.agents/scripts/lib/bdd-step-index.js +26 -100
- package/.agents/scripts/lib/bootstrap/baseline-merge-driver.js +23 -103
- package/.agents/scripts/lib/bootstrap/branch-protection.js +2 -5
- package/.agents/scripts/lib/bootstrap/commit-push.js +12 -50
- package/.agents/scripts/lib/bootstrap/gh-preflight.js +14 -101
- package/.agents/scripts/lib/bootstrap/hitl-confirm.js +5 -30
- package/.agents/scripts/lib/bootstrap/install-ledger.js +17 -73
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +17 -121
- package/.agents/scripts/lib/bootstrap/manifest.js +15 -86
- package/.agents/scripts/lib/bootstrap/merge-methods.js +4 -33
- package/.agents/scripts/lib/bootstrap/preflight.js +12 -61
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +34 -235
- package/.agents/scripts/lib/bootstrap/prompt.js +21 -129
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +27 -141
- package/.agents/scripts/lib/bootstrap/summary.js +1 -8
- package/.agents/scripts/lib/bootstrap/workflow-audit.js +11 -84
- package/.agents/scripts/lib/branch-name-guard.js +4 -23
- package/.agents/scripts/lib/changed-files.js +31 -143
- package/.agents/scripts/lib/checks/core-bare-clean.js +4 -24
- package/.agents/scripts/lib/checks/index.js +18 -101
- package/.agents/scripts/lib/checks/loop-health.js +11 -53
- package/.agents/scripts/lib/checks/state.js +16 -91
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +10 -61
- package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +14 -83
- package/.agents/scripts/lib/child-exec.js +39 -108
- package/.agents/scripts/lib/cli/standard-args.js +9 -116
- package/.agents/scripts/lib/cli-args.js +31 -146
- package/.agents/scripts/lib/cli-usage.js +5 -27
- package/.agents/scripts/lib/cli-utils.js +2 -12
- package/.agents/scripts/lib/close-validation/commands.js +13 -76
- package/.agents/scripts/lib/close-validation/gates.js +92 -331
- package/.agents/scripts/lib/close-validation/process.js +121 -151
- package/.agents/scripts/lib/close-validation/projections/advisories.js +5 -31
- package/.agents/scripts/lib/close-validation/projections/crap.js +19 -67
- package/.agents/scripts/lib/close-validation/projections/head-sha.js +1 -17
- package/.agents/scripts/lib/close-validation/projections/inputs.js +4 -34
- package/.agents/scripts/lib/close-validation/projections/maintainability.js +11 -58
- package/.agents/scripts/lib/close-validation/runner.js +53 -110
- package/.agents/scripts/lib/command-header.js +6 -28
- package/.agents/scripts/lib/config/acceptance-eval.js +4 -30
- package/.agents/scripts/lib/config/baselines.js +3 -14
- package/.agents/scripts/lib/config/ci.js +8 -38
- package/.agents/scripts/lib/config/commands.js +1 -15
- package/.agents/scripts/lib/config/defaults.js +4 -33
- package/.agents/scripts/lib/config/delivery-routing.js +6 -35
- package/.agents/scripts/lib/config/explain.js +9 -80
- package/.agents/scripts/lib/config/gates/coverage.schema.js +0 -12
- package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +2 -30
- package/.agents/scripts/lib/config/gates/crap.schema.js +1 -34
- package/.agents/scripts/lib/config/gates/duplication.schema.js +1 -8
- package/.agents/scripts/lib/config/gates/index.js +2 -17
- package/.agents/scripts/lib/config/gates/maintainability.schema.js +1 -20
- package/.agents/scripts/lib/config/gates/mutation.schema.js +1 -7
- package/.agents/scripts/lib/config/gates/shared.js +4 -64
- package/.agents/scripts/lib/config/github.js +4 -22
- package/.agents/scripts/lib/config/limits.js +4 -57
- package/.agents/scripts/lib/config/paths.js +2 -21
- package/.agents/scripts/lib/config/qa.js +4 -38
- package/.agents/scripts/lib/config/quality.js +76 -432
- package/.agents/scripts/lib/config/runners.js +12 -56
- package/.agents/scripts/lib/config/runtime.js +13 -57
- package/.agents/scripts/lib/config/shared.js +2 -16
- package/.agents/scripts/lib/config/sync-agentrc.js +9 -50
- package/.agents/scripts/lib/config/temp-paths.js +40 -280
- package/.agents/scripts/lib/config/validate-orchestration.js +5 -17
- package/.agents/scripts/lib/config/worktree-isolation.js +9 -28
- package/.agents/scripts/lib/config-resolver.js +10 -52
- package/.agents/scripts/lib/config-schema-shared.js +1 -4
- package/.agents/scripts/lib/config-settings-schema-delivery.js +12 -294
- package/.agents/scripts/lib/config-settings-schema-quality.js +7 -219
- package/.agents/scripts/lib/config-settings-schema.js +37 -274
- package/.agents/scripts/lib/coverage-baseline.js +20 -110
- package/.agents/scripts/lib/coverage-capture-fullscope.js +12 -37
- package/.agents/scripts/lib/coverage-capture-incremental.js +12 -43
- package/.agents/scripts/lib/coverage-capture-usage.js +4 -24
- package/.agents/scripts/lib/coverage-capture.js +99 -224
- package/.agents/scripts/lib/coverage-utils.js +14 -79
- package/.agents/scripts/lib/cpu-pool.js +17 -123
- package/.agents/scripts/lib/crap-baseline-join.js +16 -88
- package/.agents/scripts/lib/crap-coordinates.js +6 -25
- package/.agents/scripts/lib/crap-engine.js +40 -153
- package/.agents/scripts/lib/crap-method-identity.js +16 -78
- package/.agents/scripts/lib/crap-utils.js +31 -155
- package/.agents/scripts/lib/cyclomatic-ceiling.js +14 -87
- package/.agents/scripts/lib/cyclomatic-scope.js +10 -50
- package/.agents/scripts/lib/dead-exports-knip.js +18 -56
- package/.agents/scripts/lib/dead-exports-mode.js +5 -24
- package/.agents/scripts/lib/degraded-mode.js +3 -26
- package/.agents/scripts/lib/dependency-parser.js +8 -40
- package/.agents/scripts/lib/dependency-version.js +13 -35
- package/.agents/scripts/lib/detect-package-manager.js +6 -36
- package/.agents/scripts/lib/doc-tiers.js +22 -126
- package/.agents/scripts/lib/duplicate-search.js +8 -72
- package/.agents/scripts/lib/env-loader.js +5 -27
- package/.agents/scripts/lib/error-redactor.js +6 -31
- package/.agents/scripts/lib/errors/index.js +2 -22
- package/.agents/scripts/lib/escomplex-ast-compat.js +22 -163
- package/.agents/scripts/lib/escomplex-kernel.js +21 -123
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +93 -419
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +20 -98
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +27 -151
- package/.agents/scripts/lib/findings/audit-ledger.js +23 -97
- package/.agents/scripts/lib/findings/classify-finding.js +14 -69
- package/.agents/scripts/lib/findings/promote-finding.js +14 -112
- package/.agents/scripts/lib/findings/provenance-field.js +11 -52
- package/.agents/scripts/lib/findings/route-finding.js +37 -255
- package/.agents/scripts/lib/findings/semantic-issue-search.js +14 -59
- package/.agents/scripts/lib/findings/severity.js +18 -104
- package/.agents/scripts/lib/format-generated-json.js +12 -44
- package/.agents/scripts/lib/full-suite-lock.js +160 -429
- package/.agents/scripts/lib/full-suite-queue.js +213 -0
- package/.agents/scripts/lib/gates/baseline-store.js +5 -9
- package/.agents/scripts/lib/gates/friction.js +1 -3
- package/.agents/scripts/lib/generated/agentrc-validator.js +2 -2
- package/.agents/scripts/lib/gh-exec.js +31 -259
- package/.agents/scripts/lib/git/cached-fetch.js +9 -52
- package/.agents/scripts/lib/git/sync-from-base.js +15 -107
- package/.agents/scripts/lib/git-branch-cleanup.js +14 -61
- package/.agents/scripts/lib/git-branch-lifecycle.js +16 -87
- package/.agents/scripts/lib/git-utils.js +37 -161
- package/.agents/scripts/lib/github/framework-repo.js +8 -71
- package/.agents/scripts/lib/github-url.js +2 -17
- package/.agents/scripts/lib/import-graph.js +11 -38
- package/.agents/scripts/lib/install-cmd-parser.js +4 -13
- package/.agents/scripts/lib/json-utils.js +3 -18
- package/.agents/scripts/lib/label-constants.js +16 -111
- package/.agents/scripts/lib/label-taxonomy.js +4 -30
- package/.agents/scripts/lib/maintainability-engine.js +12 -80
- package/.agents/scripts/lib/maintainability-unscorable.js +5 -25
- package/.agents/scripts/lib/maintainability-utils.js +16 -92
- package/.agents/scripts/lib/mandrel-catalog.js +12 -70
- package/.agents/scripts/lib/notifications/notifier.js +13 -38
- package/.agents/scripts/lib/npm-scripts.js +4 -23
- package/.agents/scripts/lib/observability/metrics-ledger.js +16 -76
- package/.agents/scripts/lib/observability/runtime-friction.js +44 -286
- package/.agents/scripts/lib/observability/signal-validator.js +5 -37
- package/.agents/scripts/lib/observability/signals-writer.js +11 -121
- package/.agents/scripts/lib/observability/source-classifier.js +21 -203
- package/.agents/scripts/lib/observability/terse-result.js +14 -47
- package/.agents/scripts/lib/onboard/init-tail.js +13 -74
- package/.agents/scripts/lib/onboard/scaffold-docs.js +11 -34
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +25 -139
- package/.agents/scripts/lib/orchestration/auto-merge-cwd.js +11 -66
- package/.agents/scripts/lib/orchestration/behind-recovery.js +10 -55
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +5 -75
- package/.agents/scripts/lib/orchestration/change-set.js +7 -36
- package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +9 -46
- package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +11 -44
- package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +5 -24
- package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +3 -12
- package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +5 -38
- package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +3 -8
- package/.agents/scripts/lib/orchestration/check-baselines/phases/refresh-ack.js +28 -136
- package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +3 -13
- package/.agents/scripts/lib/orchestration/check-state.js +92 -0
- package/.agents/scripts/lib/orchestration/ci-gap-intake.js +37 -144
- package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +42 -189
- package/.agents/scripts/lib/orchestration/code-review.js +24 -128
- package/.agents/scripts/lib/orchestration/column-sync.js +23 -111
- package/.agents/scripts/lib/orchestration/complexity-gate.js +42 -214
- package/.agents/scripts/lib/orchestration/deliver-recover.js +36 -168
- package/.agents/scripts/lib/orchestration/dependency-analyzer.js +4 -35
- package/.agents/scripts/lib/orchestration/dependency-candidates.js +9 -41
- package/.agents/scripts/lib/orchestration/diff-magnitude.js +25 -115
- package/.agents/scripts/lib/orchestration/doc-reader.js +2 -6
- package/.agents/scripts/lib/orchestration/docs-digest.js +13 -51
- package/.agents/scripts/lib/orchestration/epic-candidates.js +13 -53
- package/.agents/scripts/lib/orchestration/epic-checklist.js +9 -33
- package/.agents/scripts/lib/orchestration/epic-container.js +41 -167
- package/.agents/scripts/lib/orchestration/epic-expansion.js +10 -40
- package/.agents/scripts/lib/orchestration/epic-rollup.js +55 -207
- package/.agents/scripts/lib/orchestration/file-assumption-enum.js +2 -22
- package/.agents/scripts/lib/orchestration/file-assumptions.js +45 -253
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-detect.js +9 -46
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +7 -57
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +21 -126
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +2 -6
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +1 -4
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +1 -5
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +9 -34
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +41 -190
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/merged-tip.js +9 -45
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +1 -4
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +19 -85
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +3 -17
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +1 -5
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +16 -100
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +1 -4
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +16 -67
- package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +9 -33
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +8 -29
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +15 -68
- package/.agents/scripts/lib/orchestration/light-backstop.js +11 -49
- package/.agents/scripts/lib/orchestration/light-escalation.js +21 -89
- package/.agents/scripts/lib/orchestration/light-suitability.js +26 -231
- package/.agents/scripts/lib/orchestration/merge-block-class.js +39 -216
- package/.agents/scripts/lib/orchestration/merge-poll.js +104 -377
- package/.agents/scripts/lib/orchestration/pinned-identifier-lint.js +17 -57
- package/.agents/scripts/lib/orchestration/plan-context.js +52 -303
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +22 -79
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +5 -31
- package/.agents/scripts/lib/orchestration/plan-metrics.js +29 -108
- package/.agents/scripts/lib/orchestration/plan-navigation.js +8 -27
- package/.agents/scripts/lib/orchestration/plan-persist/acceptance-handle-repair.js +12 -49
- package/.agents/scripts/lib/orchestration/plan-persist/audit-provenance.js +18 -73
- package/.agents/scripts/lib/orchestration/plan-persist/changes-repair.js +14 -78
- package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +6 -30
- package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +14 -65
- package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +21 -76
- package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +6 -43
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +14 -68
- package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +9 -41
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +49 -248
- package/.agents/scripts/lib/orchestration/plan-persist/soft-findings.js +2 -12
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +85 -368
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +8 -38
- package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +30 -190
- package/.agents/scripts/lib/orchestration/plan-persist/wave-collision-gate.js +9 -49
- package/.agents/scripts/lib/orchestration/plan-persist/wave-serialisation.js +7 -28
- package/.agents/scripts/lib/orchestration/plan-reachability.js +13 -42
- package/.agents/scripts/lib/orchestration/plan-run-labels/reap.js +16 -91
- package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +16 -54
- package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +10 -52
- package/.agents/scripts/lib/orchestration/planning/authoring-context.js +14 -109
- package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +11 -83
- package/.agents/scripts/lib/orchestration/pr-watch.js +48 -306
- package/.agents/scripts/lib/orchestration/project-meta-cache.js +15 -80
- package/.agents/scripts/lib/orchestration/project-meta-resolver.js +10 -51
- package/.agents/scripts/lib/orchestration/reassert-status-column.js +12 -76
- package/.agents/scripts/lib/orchestration/remote-verifier.js +12 -36
- package/.agents/scripts/lib/orchestration/resolve-stories.js +33 -164
- package/.agents/scripts/lib/orchestration/retro-proposals.js +66 -361
- package/.agents/scripts/lib/orchestration/review-base-ref.js +9 -43
- package/.agents/scripts/lib/orchestration/review-depth.js +12 -94
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +10 -111
- package/.agents/scripts/lib/orchestration/review-providers/degraded-gates.js +13 -71
- package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +7 -51
- package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +8 -53
- package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -214
- package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +7 -52
- package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +4 -33
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +11 -71
- package/.agents/scripts/lib/orchestration/review-providers/scoped-lint.js +19 -131
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +6 -89
- package/.agents/scripts/lib/orchestration/review-providers/types.js +26 -56
- package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +3 -46
- package/.agents/scripts/lib/orchestration/run-epilogue.js +40 -199
- package/.agents/scripts/lib/orchestration/run-scoped-config.js +13 -81
- package/.agents/scripts/lib/orchestration/single-story-close/close-note.js +7 -34
- package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +16 -89
- package/.agents/scripts/lib/orchestration/single-story-close/gate-log.js +18 -109
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +83 -239
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +18 -80
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +103 -97
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -64
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +136 -486
- package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +30 -134
- package/.agents/scripts/lib/orchestration/single-story-close/phases/graphql-preflight.js +9 -50
- package/.agents/scripts/lib/orchestration/single-story-close/phases/lock-wait-pending.js +49 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +13 -86
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +20 -95
- package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +46 -203
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pre-gate-steps.js +8 -50
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +12 -83
- package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +6 -39
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -6
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-outcome.js +4 -28
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +6 -51
- package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +6 -34
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +23 -121
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +110 -290
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +15 -69
- package/.agents/scripts/lib/orchestration/story-body-gate.js +4 -23
- package/.agents/scripts/lib/orchestration/story-close/baseline-upward-writeback.js +50 -179
- package/.agents/scripts/lib/orchestration/story-close/context-budget-writeback.js +11 -41
- package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +23 -311
- package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +22 -147
- package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +16 -67
- package/.agents/scripts/lib/orchestration/story-deliver-terminal-schema.js +12 -68
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +42 -201
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +43 -245
- package/.agents/scripts/lib/orchestration/story-init-envelope.js +4 -23
- package/.agents/scripts/lib/orchestration/story-init-remote.js +2 -6
- package/.agents/scripts/lib/orchestration/story-reachability.js +3 -23
- package/.agents/scripts/lib/orchestration/task-body-validator.js +12 -126
- package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -131
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +15 -149
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +5 -33
- package/.agents/scripts/lib/orchestration/ticket-validator.js +39 -181
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +51 -244
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +39 -250
- package/.agents/scripts/lib/orchestration/ticketing/state.js +14 -68
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +46 -263
- package/.agents/scripts/lib/orchestration/ticketing.js +2 -26
- package/.agents/scripts/lib/orchestration/verify-credit.js +18 -79
- package/.agents/scripts/lib/orchestration/worktree-dirty.js +5 -30
- package/.agents/scripts/lib/path-security.js +3 -6
- package/.agents/scripts/lib/plan-phase-cleanup.js +9 -49
- package/.agents/scripts/lib/preflight-runner.js +13 -69
- package/.agents/scripts/lib/process-group.js +143 -0
- package/.agents/scripts/lib/project-root.js +2 -8
- package/.agents/scripts/lib/provider-factory.js +2 -25
- package/.agents/scripts/lib/qa/console-allowlist.js +10 -59
- package/.agents/scripts/lib/qa/qa-session.js +15 -69
- package/.agents/scripts/lib/qa/redact-evidence.js +18 -129
- package/.agents/scripts/lib/qa/resolve-qa-contract.js +26 -135
- package/.agents/scripts/lib/qa/resolve-selection.js +16 -84
- package/.agents/scripts/lib/reserved-test-ids.js +9 -47
- package/.agents/scripts/lib/runtime-deps/dep-resolution.js +13 -53
- package/.agents/scripts/lib/runtime-deps/ensure-installed.js +10 -44
- package/.agents/scripts/lib/runtime-deps/manifest.js +10 -30
- package/.agents/scripts/lib/runtime-deps/parser-major.js +15 -51
- package/.agents/scripts/lib/runtime-deps/preflight.js +4 -22
- package/.agents/scripts/lib/runtime-deps/scan-imports.js +11 -55
- package/.agents/scripts/lib/signals/detectors/common.js +12 -38
- package/.agents/scripts/lib/signals/index.js +2 -19
- package/.agents/scripts/lib/signals/schema.js +14 -109
- package/.agents/scripts/lib/signals/write.js +2 -11
- package/.agents/scripts/lib/single-story/confirm-merge.js +31 -72
- package/.agents/scripts/lib/single-story/story-merged-notify.js +8 -49
- package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +4 -26
- package/.agents/scripts/lib/single-story-sweep/protection.js +13 -100
- package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +60 -258
- package/.agents/scripts/lib/single-story-sweep.js +14 -97
- package/.agents/scripts/lib/skills/parse-skill.js +13 -59
- package/.agents/scripts/lib/skills/skills-index.js +8 -29
- package/.agents/scripts/lib/skills/walk-skill-files.js +17 -78
- package/.agents/scripts/lib/source-extensions.js +11 -42
- package/.agents/scripts/lib/source-text/strip-js-comments.js +8 -41
- package/.agents/scripts/lib/stdio-flush.js +9 -36
- package/.agents/scripts/lib/story-adjacency.js +8 -40
- package/.agents/scripts/lib/story-body/body-format-lints.js +22 -83
- package/.agents/scripts/lib/story-body/footer-block.js +11 -44
- package/.agents/scripts/lib/story-body/story-body.js +83 -358
- package/.agents/scripts/lib/temp-retention.js +42 -143
- package/.agents/scripts/lib/templates/decomposer-prompts.js +11 -65
- package/.agents/scripts/lib/test-env.js +12 -65
- package/.agents/scripts/lib/test-run-credit.js +10 -65
- package/.agents/scripts/lib/test-runner-contract.js +19 -74
- package/.agents/scripts/lib/test-temp.js +38 -184
- package/.agents/scripts/lib/test-tiers.js +12 -96
- package/.agents/scripts/lib/ticket-body-sections.js +21 -96
- package/.agents/scripts/lib/transpile.js +15 -74
- package/.agents/scripts/lib/util/concurrent-map.js +6 -25
- package/.agents/scripts/lib/util/parse-id-list.js +8 -34
- package/.agents/scripts/lib/util/poll-loop.js +8 -28
- package/.agents/scripts/lib/util/with-timeout.js +2 -11
- package/.agents/scripts/lib/validation-evidence.js +21 -96
- package/.agents/scripts/lib/wave-runner/footprint.js +17 -70
- package/.agents/scripts/lib/wave-runner/live-probe.js +53 -221
- package/.agents/scripts/lib/wave-runner/ready-set.js +72 -301
- package/.agents/scripts/lib/workers/crap-worker.js +11 -64
- package/.agents/scripts/lib/workers/maintainability-report-worker.js +8 -45
- package/.agents/scripts/lib/workers/maintainability-worker.js +5 -21
- package/.agents/scripts/lib/workers/serve-worker-messages.js +2 -18
- package/.agents/scripts/lib/workflow-closure.js +22 -105
- package/.agents/scripts/lib/workspace-provisioner.js +16 -54
- package/.agents/scripts/lib/worktree/git-hooks.js +15 -60
- package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +20 -60
- package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +10 -62
- package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +22 -86
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +24 -126
- package/.agents/scripts/lib/worktree/lifecycle-manager.js +2 -20
- package/.agents/scripts/lib/worktree/node-modules-strategy.js +46 -180
- package/.agents/scripts/lib/worktree-manager.js +15 -40
- package/.agents/scripts/lint-issue-body.js +12 -68
- package/.agents/scripts/mandrel-update-preflight.js +10 -70
- package/.agents/scripts/merge-baseline.js +30 -104
- package/.agents/scripts/nav-registry-diff.js +22 -108
- package/.agents/scripts/notify.js +12 -69
- package/.agents/scripts/plan-context.js +27 -111
- package/.agents/scripts/plan-critics.js +12 -66
- package/.agents/scripts/plan-persist.js +31 -148
- package/.agents/scripts/plan-run-epilogue.js +11 -37
- package/.agents/scripts/pr-watch-with-update.js +76 -267
- package/.agents/scripts/providers/github/auth.js +3 -8
- package/.agents/scripts/providers/github/blocked-by-add.js +14 -61
- package/.agents/scripts/providers/github/board-add.js +5 -21
- package/.agents/scripts/providers/github/branch-protection.js +11 -43
- package/.agents/scripts/providers/github/cache.js +2 -14
- package/.agents/scripts/providers/github/comments.js +7 -40
- package/.agents/scripts/providers/github/compose.js +3 -19
- package/.agents/scripts/providers/github/errors.js +22 -125
- package/.agents/scripts/providers/github/issues.js +31 -123
- package/.agents/scripts/providers/github/labels.js +24 -124
- package/.agents/scripts/providers/github/mappers.js +5 -27
- package/.agents/scripts/providers/github/merge-methods.js +3 -22
- package/.agents/scripts/providers/github/project-board.js +2 -17
- package/.agents/scripts/providers/github/projects-v2-graphql.js +3 -6
- package/.agents/scripts/providers/github/request-helpers.js +5 -32
- package/.agents/scripts/providers/github/search-budget.js +9 -39
- package/.agents/scripts/providers/github/search-query.js +5 -26
- package/.agents/scripts/providers/github/sub-issue-add.js +15 -65
- package/.agents/scripts/providers/github/sub-issues.js +7 -36
- package/.agents/scripts/providers/github/tickets.js +32 -134
- package/.agents/scripts/providers/github.js +18 -59
- package/.agents/scripts/prune-plan-run-labels.js +12 -46
- package/.agents/scripts/quality-preview.js +35 -220
- package/.agents/scripts/resolve-doc-tiers.js +3 -26
- package/.agents/scripts/resolve-stories.js +16 -67
- package/.agents/scripts/resync-status-column.js +6 -25
- package/.agents/scripts/run-tests.js +29 -104
- package/.agents/scripts/single-story-close.js +23 -135
- package/.agents/scripts/single-story-confirm-merge.js +32 -139
- package/.agents/scripts/single-story-init.js +47 -209
- package/.agents/scripts/stories-wave-tick.js +102 -472
- package/.agents/scripts/sync-agentrc.js +3 -21
- package/.agents/scripts/sync-claude-agents.js +9 -55
- package/.agents/scripts/sync-claude-commands.js +20 -110
- package/.agents/scripts/test-wrapper.js +6 -43
- package/.agents/scripts/update-coverage-baseline.js +5 -22
- package/.agents/scripts/update-crap-baseline.js +7 -30
- package/.agents/scripts/update-duplication-baseline.js +16 -92
- package/.agents/scripts/update-maintainability-baseline.js +8 -62
- package/.agents/scripts/update-ticket-state.js +1 -7
- package/.agents/scripts/validate-skills.js +6 -26
- package/.agents/templates/agent-protocol.md +2 -2
- package/.agents/templates/docs/audit-sweep-runbook.md +3 -4
- package/.agents/workflows/audit-accessibility.md +4 -7
- package/.agents/workflows/audit-adrs.md +3 -6
- package/.agents/workflows/audit-architecture.md +3 -11
- package/.agents/workflows/audit-baselines.md +6 -9
- package/.agents/workflows/audit-clean-code.md +8 -12
- package/.agents/workflows/audit-data-model.md +3 -7
- package/.agents/workflows/audit-dependencies.md +4 -7
- package/.agents/workflows/audit-devops.md +4 -8
- package/.agents/workflows/audit-documentation.md +1 -4
- package/.agents/workflows/audit-mobile.md +4 -7
- package/.agents/workflows/audit-navigability.md +3 -6
- package/.agents/workflows/audit-performance.md +2 -4
- package/.agents/workflows/audit-privacy.md +4 -7
- package/.agents/workflows/audit-quality.md +4 -7
- package/.agents/workflows/audit-security.md +4 -7
- package/.agents/workflows/audit-seo.md +4 -7
- package/.agents/workflows/audit-sre.md +4 -7
- package/.agents/workflows/audit-to-stories.md +17 -30
- package/.agents/workflows/audit-ux-ui.md +4 -7
- package/.agents/workflows/helpers/audit-lens-core.md +1 -1
- package/.agents/workflows/helpers/code-quality-guardrails.md +12 -15
- package/.agents/workflows/helpers/deliver-digest.md +6 -4
- package/.agents/workflows/helpers/deliver-reference.md +114 -188
- package/.agents/workflows/helpers/deliver-story-reference.md +189 -533
- package/.agents/workflows/helpers/plan-reference.md +86 -139
- package/.agents/workflows/helpers/qa-core.md +12 -0
- package/.agents/workflows/memory-consolidate.md +1 -1
- package/.agents/workflows/qa-assist.md +27 -71
- package/.agents/workflows/qa-explore.md +19 -59
- package/.agents/workflows/qa-run.md +11 -33
- package/README.md +1 -1
- package/bin/mandrel.js +5 -46
- package/bin/postinstall.js +18 -107
- package/docs/CHANGELOG.md +25 -0
- package/lib/cli/doctor.js +11 -71
- package/lib/cli/init.js +26 -165
- package/lib/cli/migrate.js +5 -64
- package/lib/cli/registry.js +84 -467
- package/lib/cli/sync-agents.js +4 -64
- package/lib/cli/sync-commands.js +11 -64
- package/lib/cli/sync.js +34 -213
- package/lib/cli/uninstall.js +40 -219
- package/lib/cli/update.js +105 -661
- package/lib/cli/version-check.js +8 -72
- package/lib/cli/version-helpers.js +14 -87
- package/lib/migrations/helpers/retire-agentrc-key.js +11 -52
- package/lib/migrations/index.js +15 -92
- package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +2 -15
- package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +1 -13
- package/lib/migrations/steps/2.11.0-retire-max-seed-words.js +2 -15
- package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +9 -38
- package/lib/migrations/steps/2.20.0-retire-codebase-snapshot.js +1 -13
- package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +2 -27
- package/lib/migrations/steps/2.57.0-retire-delivery-limit-knobs.js +2 -23
- package/lib/migrations/steps/2.57.0-retire-planning-limit-knobs.js +2 -27
- package/lib/migrations/steps/2.60.0-retire-audit-results-autofile.js +2 -21
- package/lib/migrations/steps/strip-removed-agentrc-keys.js +333 -0
- package/package.json +16 -14
- package/.agents/docs/SDLC.md +0 -590
- package/.agents/docs/quality-gates.md +0 -1183
- package/.agents/rules/known-tooling-behavior.md +0 -200
- package/.agents/rules/orchestration-error-handling.md +0 -61
- package/.agents/rules/test-seams.md +0 -59
- package/.agents/schemas/baselines/lighthouse.schema.json +0 -59
- package/.agents/schemas/baselines/lint.schema.json +0 -47
- package/.agents/scripts/check-action-pinning.js +0 -260
- package/.agents/scripts/check-audit-attribution.js +0 -302
- package/.agents/scripts/check-baseline-drift.js +0 -211
- package/.agents/scripts/check-baseline-scope.js +0 -362
- package/.agents/scripts/check-generated-validator.js +0 -202
- package/.agents/scripts/check-knip-entries.js +0 -159
- package/.agents/scripts/check-lifecycle-lint.js +0 -294
- package/.agents/scripts/check-pinned-override-notes.js +0 -102
- package/.agents/scripts/check-schema-references.js +0 -368
- package/.agents/scripts/check-test-portability.js +0 -512
- package/.agents/scripts/check-workflow-citations.js +0 -218
- package/.agents/scripts/check-workflow-cli-lint.js +0 -299
- package/.agents/scripts/check-workflow-timeouts.js +0 -291
- package/.agents/scripts/install-matrix-assert.js +0 -326
- package/.agents/scripts/lib/audit-advisories.js +0 -195
- package/.agents/scripts/lib/audit-attribution.js +0 -134
- package/.agents/scripts/lib/baselines/drift-detector.js +0 -351
- package/.agents/scripts/lib/baselines/kinds/lighthouse.js +0 -87
- package/.agents/scripts/lib/baselines/kinds/lint.js +0 -184
- package/.agents/scripts/lib/baselines/orphan-pruner.js +0 -233
- package/.agents/scripts/lib/baselines/scope-assert.js +0 -223
- package/.agents/scripts/lib/baselines/scope-inventory.js +0 -314
- package/.agents/scripts/lib/c8-cli-path.js +0 -21
- package/.agents/scripts/lib/config/gates/lighthouse.schema.js +0 -51
- package/.agents/scripts/lib/config/gates/lint.schema.js +0 -18
- package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +0 -70
- package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +0 -284
- package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +0 -80
- package/.agents/scripts/lib/dynamic-workflow/degraded-coverage.js +0 -81
- package/.agents/scripts/lib/dynamic-workflow/documentation-report-contract.js +0 -87
- package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +0 -74
- package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +0 -90
- package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +0 -43
- package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +0 -83
- package/.agents/scripts/lib/fs-walk.js +0 -52
- package/.agents/scripts/lib/knip-config-resolver.js +0 -181
- package/.agents/scripts/lib/knip-entry-sync.js +0 -452
- package/.agents/scripts/lib/pinned-override-notes.js +0 -88
- package/.agents/scripts/lib/pinned-override-resolve.js +0 -212
- package/.agents/scripts/lib/test-isolate/cli-options.js +0 -93
- package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +0 -52
- package/.agents/scripts/lib/test-isolate/list-files.js +0 -90
- package/.agents/scripts/lib/test-isolate/parse-tap.js +0 -75
- package/.agents/scripts/lib/test-isolate/progress-log.js +0 -45
- package/.agents/scripts/lib/test-isolate/render-report.js +0 -97
- package/.agents/scripts/lib/test-isolate/run-isolate.js +0 -87
- package/.agents/scripts/lib/test-isolate/runner.js +0 -483
- package/.agents/scripts/lib/test-profile/parse-tap.js +0 -136
- package/.agents/scripts/lib/test-profile/render-report.js +0 -45
- package/.agents/scripts/lint-label-vocabulary.js +0 -214
- package/.agents/scripts/post-structured-comment.js +0 -127
- package/.agents/scripts/provision-git-hooks.js +0 -85
- package/.agents/scripts/prune-baseline-orphans.js +0 -181
- package/.agents/scripts/run-coverage.js +0 -197
- package/.agents/scripts/run-lint.js +0 -133
- package/.agents/scripts/run-test-profile.js +0 -129
- package/.agents/scripts/run-verify.js +0 -125
- package/.agents/scripts/test-isolate.js +0 -55
- package/.agents/scripts/update-dead-exports-baseline.js +0 -321
|
@@ -1,31 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* lib/findings/audit-ledger.js —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* `/audit-to-stories` run re-litigates the whole backlog from zero: it cannot
|
|
6
|
-
* tell a brand-new finding from one already filed, an intentionally-rejected
|
|
7
|
-
* finding from an unseen one, or a genuine regression from routine churn. The
|
|
8
|
-
* ledger is that memory. It is a small committed JSON file
|
|
9
|
-
* (`baselines/audit-ledger.json`, the same envelope shape as the arch-cycles
|
|
10
|
-
* baseline — `{ $schema, generatedAt, entries: [] }`) keyed by each finding's
|
|
11
|
-
* shared-helper fingerprint plus a location-based `semanticKey` that survives a
|
|
12
|
-
* reworded title.
|
|
13
|
-
*
|
|
14
|
-
* Each entry carries a lifecycle `status`:
|
|
15
|
-
* - `new` — seen, not yet filed as an Issue.
|
|
16
|
-
* - `filed` — an Issue was opened; re-detections are known, not new.
|
|
17
|
-
* - `fixed` — the tracking Issue closed as completed.
|
|
18
|
-
* - `accepted-risk`— the tracking Issue closed as `not_planned`; the finding
|
|
19
|
-
* is deliberately rejected and is SUPPRESSED on re-detect.
|
|
20
|
-
* - `regressed` — a `fixed` finding re-appeared (closed-completed Issue,
|
|
21
|
-
* finding detected again).
|
|
22
|
-
*
|
|
23
|
-
* `reconcileLedger` folds a fresh scan and the live Issue states onto the prior
|
|
24
|
-
* ledger, returning the next ledger plus a per-finding classification whose
|
|
25
|
-
* `action` (`propose` | `known` | `suppress` | `regressed`) tells the caller
|
|
26
|
-
* whether to open a Story. Pure: filesystem access is confined to the tiny
|
|
27
|
-
* {@link readLedger} / {@link writeLedger} helpers, which take an injectable
|
|
28
|
-
* `fs` so tests never touch disk.
|
|
2
|
+
* lib/findings/audit-ledger.js — committed cross-run memory of audit
|
|
3
|
+
* findings, keyed by fingerprint and `semanticKey`. Status: `new` · `filed` ·
|
|
4
|
+
* `fixed` · `accepted-risk` (closed `not_planned`; suppressed) · `regressed`.
|
|
29
5
|
*/
|
|
30
6
|
|
|
31
7
|
import nodeFs from 'node:fs';
|
|
@@ -36,11 +12,7 @@ export const DEFAULT_LEDGER_PATH = 'baselines/audit-ledger.json';
|
|
|
36
12
|
const LEDGER_SCHEMA_URL =
|
|
37
13
|
'https://mandrel.dev/baselines/audit-ledger.schema.json';
|
|
38
14
|
|
|
39
|
-
// Entry lifecycle states — `new | filed | fixed | accepted-risk | regressed`.
|
|
40
|
-
// The reconcile policy in `decideStatus` is the single source of truth.
|
|
41
|
-
|
|
42
15
|
/**
|
|
43
|
-
* Build an empty ledger envelope (arch-cycles-baseline shape).
|
|
44
16
|
* @param {string} [now] — ISO timestamp to stamp.
|
|
45
17
|
* @returns {{ $schema: string, generatedAt: string, entries: [] }}
|
|
46
18
|
*/
|
|
@@ -49,18 +21,9 @@ function createEmptyLedger(now = new Date().toISOString()) {
|
|
|
49
21
|
}
|
|
50
22
|
|
|
51
23
|
/**
|
|
52
|
-
*
|
|
53
|
-
* its location-based semantic key (title-insensitive).
|
|
24
|
+
* `toCanonical` is injected: importing the audit adapter would close a cycle.
|
|
54
25
|
*
|
|
55
|
-
*
|
|
56
|
-
* `toCanonical`. That is what lets this module live beside `route-finding.js`
|
|
57
|
-
* in the shared findings layer: the audit pipeline's own adapter
|
|
58
|
-
* (`lib/audit-to-stories/finding-adapter.js`) imports *from* here, so importing
|
|
59
|
-
* it back would close a `findings → audit-to-stories → findings` cycle that
|
|
60
|
-
* `check-arch-cycles` rightly refuses. A caller that already holds canonical
|
|
61
|
-
* findings passes nothing.
|
|
62
|
-
*
|
|
63
|
-
* @param {object} finding — a parsed/stamped audit finding.
|
|
26
|
+
* @param {object} finding
|
|
64
27
|
* @param {(finding: object) => object} [toCanonical]
|
|
65
28
|
* @returns {{ fingerprint: string, semanticKey: string }}
|
|
66
29
|
*/
|
|
@@ -73,8 +36,7 @@ function findingIdentity(finding, toCanonical) {
|
|
|
73
36
|
}
|
|
74
37
|
|
|
75
38
|
/**
|
|
76
|
-
*
|
|
77
|
-
* or unparseable — a missing memory is an empty memory, never a hard error.
|
|
39
|
+
* An absent or unparseable file reads as an empty ledger, never an error.
|
|
78
40
|
* @param {string} filePath
|
|
79
41
|
* @param {{ fs?: typeof import('node:fs') }} [deps]
|
|
80
42
|
* @returns {{ $schema?: string, generatedAt?: string, entries: object[] }}
|
|
@@ -92,8 +54,6 @@ export function readLedger(filePath, { fs } = {}) {
|
|
|
92
54
|
}
|
|
93
55
|
|
|
94
56
|
/**
|
|
95
|
-
* Persist the ledger to disk with a stable 2-space indent and a trailing
|
|
96
|
-
* newline (so the committed file diffs cleanly).
|
|
97
57
|
* @param {string} filePath
|
|
98
58
|
* @param {object} ledger
|
|
99
59
|
* @param {{ fs?: typeof import('node:fs'), path?: typeof import('node:path') }} [deps]
|
|
@@ -107,7 +67,6 @@ export function writeLedger(filePath, ledger, { fs, path } = {}) {
|
|
|
107
67
|
}
|
|
108
68
|
|
|
109
69
|
/**
|
|
110
|
-
* Index a ledger's entries by fingerprint and by semanticKey for O(1) lookup.
|
|
111
70
|
* @param {{ entries?: object[] }} ledger
|
|
112
71
|
*/
|
|
113
72
|
function indexLedger(ledger) {
|
|
@@ -121,9 +80,7 @@ function indexLedger(ledger) {
|
|
|
121
80
|
}
|
|
122
81
|
|
|
123
82
|
/**
|
|
124
|
-
*
|
|
125
|
-
* `issueStates` (keyed by fingerprint then semanticKey) wins over whatever the
|
|
126
|
-
* prior ledger entry recorded.
|
|
83
|
+
* An `issueStates` override beats the recorded Issue.
|
|
127
84
|
* @param {{ fingerprint: string, semanticKey: string }} id
|
|
128
85
|
* @param {object|null} existing
|
|
129
86
|
* @param {Record<string, { state?: string, stateReason?: string|null, number?: number }>} issueStates
|
|
@@ -141,9 +98,6 @@ function resolveIssueState(id, existing, issueStates) {
|
|
|
141
98
|
}
|
|
142
99
|
|
|
143
100
|
/**
|
|
144
|
-
* The four verdicts the policy can reach, spelled once. Deduping them keeps
|
|
145
|
-
* `decideStatus` readable as the decision table it is, rather than eight
|
|
146
|
-
* near-identical object literals.
|
|
147
101
|
* @type {Record<string, { status: string, action: string }>}
|
|
148
102
|
*/
|
|
149
103
|
const VERDICT = Object.freeze({
|
|
@@ -154,31 +108,20 @@ const VERDICT = Object.freeze({
|
|
|
154
108
|
});
|
|
155
109
|
|
|
156
110
|
/**
|
|
157
|
-
*
|
|
158
|
-
* the live Issue state. This is the whole reconciliation policy in one place.
|
|
111
|
+
* The whole reconciliation policy.
|
|
159
112
|
* @param {object|null} existing — prior ledger entry (or null when unseen).
|
|
160
113
|
* @param {{ state: string, stateReason: string|null }|null} issue
|
|
161
114
|
* @returns {{ status: string, action: 'propose'|'known'|'suppress'|'regressed' }}
|
|
162
115
|
*/
|
|
163
116
|
function decideStatus(existing, issue) {
|
|
164
|
-
// A closed Issue
|
|
165
|
-
// verdict, and it is read FIRST so a recorded `filed` can never outrank it.
|
|
117
|
+
// A closed Issue outranks any recorded status.
|
|
166
118
|
if (issue && issue.state === 'closed') {
|
|
167
119
|
return issue.stateReason === 'not_planned'
|
|
168
120
|
? VERDICT.suppress
|
|
169
|
-
:
|
|
170
|
-
// → it came back. That is a regression, not a fresh proposal.
|
|
171
|
-
VERDICT.regressed;
|
|
121
|
+
: VERDICT.regressed;
|
|
172
122
|
}
|
|
173
123
|
|
|
174
|
-
// An
|
|
175
|
-
// entry said — including when there is no prior entry at all. Until Story
|
|
176
|
-
// #5305 nothing in the package ever assigned `filed`, so this fell through to
|
|
177
|
-
// `new`/`propose` on every run and the `filed` arm below was unreachable in
|
|
178
|
-
// production: the ledger suppressed nothing, and only the GitHub-search dedup
|
|
179
|
-
// stopped a sweep re-filing what it had already filed. Reading it before the
|
|
180
|
-
// `!existing` guard is what makes a record pass correct on its FIRST run
|
|
181
|
-
// rather than its second.
|
|
124
|
+
// An open Issue means filed even with no prior entry.
|
|
182
125
|
const unseen = issue?.state === 'open' ? VERDICT.filed : VERDICT.propose;
|
|
183
126
|
if (!existing) return unseen;
|
|
184
127
|
|
|
@@ -187,9 +130,7 @@ function decideStatus(existing, issue) {
|
|
|
187
130
|
return VERDICT.suppress;
|
|
188
131
|
case 'filed':
|
|
189
132
|
return VERDICT.filed;
|
|
190
|
-
// Recorded fixed
|
|
191
|
-
// as a regression the operator should look at. An open Issue does not
|
|
192
|
-
// soften that: the finding came back either way.
|
|
133
|
+
// Recorded fixed yet detected again: a regression, open Issue or not.
|
|
193
134
|
case 'fixed':
|
|
194
135
|
return VERDICT.regressed;
|
|
195
136
|
case 'regressed':
|
|
@@ -200,17 +141,15 @@ function decideStatus(existing, issue) {
|
|
|
200
141
|
}
|
|
201
142
|
|
|
202
143
|
/**
|
|
203
|
-
* Fold a
|
|
144
|
+
* Fold a scan and live Issue states onto the prior ledger; untouched entries
|
|
145
|
+
* are preserved.
|
|
204
146
|
*
|
|
205
147
|
* @param {object} params
|
|
206
|
-
* @param {{ entries?: object[] }} [params.ledger]
|
|
207
|
-
* @param {Array<object>} params.findings
|
|
148
|
+
* @param {{ entries?: object[] }} [params.ledger]
|
|
149
|
+
* @param {Array<object>} params.findings
|
|
208
150
|
* @param {Record<string, { state?: string, stateReason?: string|null, number?: number }>} [params.issueStates]
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
* @param {string} [params.now] — ISO timestamp for firstSeen/lastSeen stamping.
|
|
212
|
-
* @param {(finding: object) => object} [params.toCanonical] — projection onto
|
|
213
|
-
* the canonical identity; omit when `findings` are already canonical.
|
|
151
|
+
* @param {string} [params.now]
|
|
152
|
+
* @param {(finding: object) => object} [params.toCanonical]
|
|
214
153
|
* @returns {{
|
|
215
154
|
* ledger: { $schema: string, generatedAt: string, entries: object[] },
|
|
216
155
|
* classifications: Array<{ fingerprint: string, semanticKey: string, status: string, action: string, issue: object|null }>,
|
|
@@ -228,7 +167,6 @@ export function reconcileLedger({
|
|
|
228
167
|
}
|
|
229
168
|
|
|
230
169
|
const { byFingerprint, bySemanticKey } = indexLedger(ledger);
|
|
231
|
-
// Preserve any prior entries NOT touched by this scan (their memory survives).
|
|
232
170
|
const nextByFingerprint = new Map(byFingerprint);
|
|
233
171
|
const classifications = [];
|
|
234
172
|
|
|
@@ -263,8 +201,7 @@ export function reconcileLedger({
|
|
|
263
201
|
lastSeen: now,
|
|
264
202
|
};
|
|
265
203
|
|
|
266
|
-
// Re-key
|
|
267
|
-
// by semanticKey under a now-drifted fingerprint (reworded finding).
|
|
204
|
+
// Re-key a reworded finding matched by semanticKey.
|
|
268
205
|
if (existing?.fingerprint && existing.fingerprint !== id.fingerprint) {
|
|
269
206
|
nextByFingerprint.delete(existing.fingerprint);
|
|
270
207
|
}
|
|
@@ -290,24 +227,13 @@ export function reconcileLedger({
|
|
|
290
227
|
}
|
|
291
228
|
|
|
292
229
|
/**
|
|
293
|
-
* Record
|
|
294
|
-
*
|
|
295
|
-
* The finding-shaped {@link reconcileLedger} cannot serve this caller:
|
|
296
|
-
* `plan-persist` never sees findings. It holds the provenance identities it
|
|
297
|
-
* stamped on a Story body — fingerprints and semantic keys, as strings — plus
|
|
298
|
-
* the issue number it just created. That is enough to record the filing, and
|
|
299
|
-
* demanding a finding it does not have would be the reason the recommended
|
|
300
|
-
* planning path never reached this ledger at all.
|
|
301
|
-
*
|
|
302
|
-
* An identity already carrying a **closed** Issue is left exactly as it is: a
|
|
303
|
-
* finding whose tracking Issue was closed `not_planned` is `accepted-risk` and
|
|
304
|
-
* must stay suppressed, and one closed as completed is a `regressed` the
|
|
305
|
-
* operator still needs to see. A fresh filing never overwrites either verdict.
|
|
230
|
+
* Record identity strings (`plan-persist` has no findings) as filed. An
|
|
231
|
+
* identity whose Issue is closed is skipped, so its verdict survives.
|
|
306
232
|
*
|
|
307
233
|
* @param {object} params
|
|
308
|
-
* @param {{ entries?: object[] }} [params.ledger]
|
|
234
|
+
* @param {{ entries?: object[] }} [params.ledger]
|
|
309
235
|
* @param {Array<{ fingerprint: string, semanticKey?: string, title?: string, dimension?: string, primaryFile?: string }>} params.identities
|
|
310
|
-
* @param {{ number: number }} params.issue
|
|
236
|
+
* @param {{ number: number }} params.issue
|
|
311
237
|
* @param {string} [params.now]
|
|
312
238
|
* @returns {{ ledger: object, recorded: number, skipped: number }}
|
|
313
239
|
*/
|
|
@@ -1,32 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* lib/findings/classify-finding.js —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `class` drawn from a closed enum. `classifyFinding(finding)` resolves that
|
|
7
|
-
* class and routes it to the GitHub label set Triage applies when promoting
|
|
8
|
-
* the item to a follow-up ticket.
|
|
9
|
-
*
|
|
10
|
-
* Pure function: no network I/O. The class → label routing table is the
|
|
11
|
-
* single source of truth for which labels a given finding class maps to;
|
|
12
|
-
* label *names* are pulled from `lib/label-constants.js` so renames land in
|
|
13
|
-
* one place rather than as string literals here.
|
|
14
|
-
*
|
|
15
|
-
* Rejection (not silent defaulting) is the contract: a finding whose class is
|
|
16
|
-
* absent, empty, or outside the enum throws rather than falling back to a
|
|
17
|
-
* default class. A misclassified finding routed to the wrong labels is worse
|
|
18
|
-
* than a loud failure the operator can fix.
|
|
2
|
+
* lib/findings/classify-finding.js — resolve a QA ledger item's `class` and
|
|
3
|
+
* route it to the labels Triage applies on promotion. An absent or unknown
|
|
4
|
+
* class throws rather than defaulting: a mis-routed finding is worse than a
|
|
5
|
+
* loud failure.
|
|
19
6
|
*/
|
|
20
7
|
|
|
21
8
|
import { META_LABELS } from '../label-constants.js';
|
|
22
9
|
import { normalizeSeverity, SEVERITIES } from './severity.js';
|
|
23
10
|
|
|
24
|
-
/**
|
|
25
|
-
* Focus-axis labels (Story #3721). These scope a finding to the area of the
|
|
26
|
-
* framework it concerns. They are not in `label-constants.js` because the
|
|
27
|
-
* focus axis is consumer-extensible; the routing table below is the only
|
|
28
|
-
* in-tree consumer, so the literals are defined here and referenced by symbol.
|
|
29
|
-
*/
|
|
11
|
+
/** Not in `label-constants.js`: the focus axis is consumer-extensible. */
|
|
30
12
|
export const FOCUS_LABELS = {
|
|
31
13
|
PRODUCT: 'focus::product',
|
|
32
14
|
ENVIRONMENT: 'focus::environment',
|
|
@@ -35,11 +17,7 @@ export const FOCUS_LABELS = {
|
|
|
35
17
|
ENHANCEMENT: 'focus::enhancement',
|
|
36
18
|
};
|
|
37
19
|
|
|
38
|
-
/**
|
|
39
|
-
* The closed set of finding classes, mirroring the `class` enum in
|
|
40
|
-
* `.agents/schemas/qa-ledger.schema.json`. Exported so callers can validate
|
|
41
|
-
* against the same source of truth.
|
|
42
|
-
*/
|
|
20
|
+
/** Mirrors the `class` enum in `.agents/schemas/qa-ledger.schema.json`. */
|
|
43
21
|
export const FINDING_CLASSES = Object.freeze([
|
|
44
22
|
'product-bug',
|
|
45
23
|
'environment-setup',
|
|
@@ -49,9 +27,8 @@ export const FINDING_CLASSES = Object.freeze([
|
|
|
49
27
|
]);
|
|
50
28
|
|
|
51
29
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* the `/mandrel-plan` Phase 0 feedback fetcher surfaces it to the planner.
|
|
30
|
+
* `tooling-dx` carries `meta::framework-gap` so `/mandrel-plan` Phase 0
|
|
31
|
+
* surfaces it.
|
|
55
32
|
*/
|
|
56
33
|
const CLASS_TO_LABELS = Object.freeze({
|
|
57
34
|
'product-bug': [FOCUS_LABELS.PRODUCT],
|
|
@@ -61,19 +38,11 @@ const CLASS_TO_LABELS = Object.freeze({
|
|
|
61
38
|
enhancement: [FOCUS_LABELS.ENHANCEMENT, META_LABELS.CONSUMER_IMPROVEMENT],
|
|
62
39
|
});
|
|
63
40
|
|
|
64
|
-
/**
|
|
65
|
-
* The closed set of severity values a finding can carry, re-exported from the
|
|
66
|
-
* canonical {@link ./severity.js} source of truth (Story #3816) so this module
|
|
67
|
-
* does not re-declare its own list. Ordered highest → lowest:
|
|
68
|
-
* `critical | high | medium | low | info`.
|
|
69
|
-
*/
|
|
70
41
|
export { SEVERITIES };
|
|
71
42
|
|
|
72
43
|
/**
|
|
73
|
-
* Tokens
|
|
74
|
-
*
|
|
75
|
-
* orthogonal to the class → label mapping: a `product-bug` and a `tooling-dx`
|
|
76
|
-
* finding can both be security-relevant, so this never alters the class route.
|
|
44
|
+
* Tokens in `area`/`labels` marking a finding security-relevant. Orthogonal
|
|
45
|
+
* to the class route.
|
|
77
46
|
*/
|
|
78
47
|
const SECURITY_TOKENS = Object.freeze([
|
|
79
48
|
'security',
|
|
@@ -92,13 +61,6 @@ const SECURITY_TOKENS = Object.freeze([
|
|
|
92
61
|
]);
|
|
93
62
|
|
|
94
63
|
/**
|
|
95
|
-
* Resolve a finding's severity to one of {@link SEVERITIES} via the shared
|
|
96
|
-
* canonical normaliser. An absent, empty, or unrecognised severity resolves to
|
|
97
|
-
* the canonical floor (`info`). Case- and whitespace-insensitive. Delegating to
|
|
98
|
-
* {@link normalizeSeverity} keeps this path bit-for-bit identical to the
|
|
99
|
-
* `promote-finding` path, so the same finding fingerprints the same regardless
|
|
100
|
-
* of which path produced its severity (Story #3816).
|
|
101
|
-
*
|
|
102
64
|
* @param {object} finding
|
|
103
65
|
* @returns {string} one of {@link SEVERITIES}
|
|
104
66
|
*/
|
|
@@ -107,10 +69,6 @@ function resolveSeverity(finding) {
|
|
|
107
69
|
}
|
|
108
70
|
|
|
109
71
|
/**
|
|
110
|
-
* Detect whether a finding is security-relevant. True when the finding sets an
|
|
111
|
-
* explicit truthy `security` flag, OR when any of its `area` / `labels`
|
|
112
|
-
* carries a known security token. Pure string inspection — no network I/O.
|
|
113
|
-
*
|
|
114
72
|
* @param {object} finding
|
|
115
73
|
* @returns {boolean}
|
|
116
74
|
*/
|
|
@@ -132,8 +90,6 @@ function resolveSecuritySignal(finding) {
|
|
|
132
90
|
}
|
|
133
91
|
|
|
134
92
|
/**
|
|
135
|
-
* Resolve the raw `class` field of a finding to a known, non-empty class.
|
|
136
|
-
*
|
|
137
93
|
* @param {object} finding
|
|
138
94
|
* @returns {string} one of {@link FINDING_CLASSES}
|
|
139
95
|
* @throws {TypeError} when `finding` is not an object
|
|
@@ -159,24 +115,13 @@ function resolveClass(finding) {
|
|
|
159
115
|
}
|
|
160
116
|
|
|
161
117
|
/**
|
|
162
|
-
* Classify a finding
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* The class → label routing is unchanged: every class still maps to exactly
|
|
166
|
-
* the same label set it always did. `severity` and `security` are additive
|
|
167
|
-
* signal fields the caller can act on (e.g. escalate a high-severity security
|
|
168
|
-
* finding) — they never alter the label set, so no existing class-to-label
|
|
169
|
-
* mapping is dropped.
|
|
118
|
+
* Classify a finding and route it to its label set. `severity` and `security`
|
|
119
|
+
* are additive signals; they never alter the labels.
|
|
170
120
|
*
|
|
171
|
-
* @param {object} finding — a ledger item carrying a `class` field
|
|
172
|
-
* optionally `severity` and a `security` flag / security-relevant `area` /
|
|
173
|
-
* `labels`.
|
|
121
|
+
* @param {object} finding — a ledger item carrying a `class` field.
|
|
174
122
|
* @returns {{ class: string, labels: string[], severity: string, security: boolean }}
|
|
175
|
-
* the resolved class, the ordered GitHub labels Triage should apply, the
|
|
176
|
-
* resolved severity (one of {@link SEVERITIES}; `info` when absent), and
|
|
177
|
-
* whether the finding is security-relevant.
|
|
178
123
|
* @throws {TypeError|RangeError} on a non-object finding or an
|
|
179
|
-
* unknown/empty class
|
|
124
|
+
* unknown/empty class.
|
|
180
125
|
*/
|
|
181
126
|
export function classifyFinding(finding) {
|
|
182
127
|
const findingClass = resolveClass(finding);
|
|
@@ -1,66 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* lib/findings/promote-finding.js —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* tail of the exploratory-QA Triage path: once an operator has dispositioned a
|
|
6
|
-
* session's ledger items (see `.agents/schemas/qa-ledger.schema.json` and
|
|
7
|
-
* `lib/qa/qa-session.js`), the still-untriaged backlog is clustered and each
|
|
8
|
-
* cluster is promoted to a follow-up ticket — a single Story (via `/mandrel-plan`)
|
|
9
|
-
* for a tight, one-deliverable cluster, or a multi-Story plan-seed (via `/mandrel-plan --seed`) for
|
|
10
|
-
* a broad cluster that spans multiple coverage surfaces. Each contributing
|
|
11
|
-
* ledger item then has the resulting `routedTo` issue link written back onto it
|
|
12
|
-
* so a resume run sees the item as filed rather than re-promoting it.
|
|
13
|
-
*
|
|
14
|
-
* Routing **reuses the shared findings/route logic** — `routeFinding` from
|
|
15
|
-
* `route-finding.js`, the single dedup/route implementation `audit-to-stories`
|
|
16
|
-
* and `qa-explore` already share. It does NOT call `audit-to-stories`: that
|
|
17
|
-
* workflow parses `audit-*-results.md` markdown and is a different intake path.
|
|
18
|
-
* Here a cluster is adapted onto the canonical finding identity, routed against
|
|
19
|
-
* existing Issues, and only a `new` decision opens a fresh ticket; an
|
|
20
|
-
* `update-existing` / `duplicate` / `regression-of-closed` decision links back
|
|
21
|
-
* to the matched Issue without creating a duplicate.
|
|
22
|
-
*
|
|
23
|
-
* Pure orchestration: **no network I/O lives here.** Every GitHub side-effect
|
|
24
|
-
* (issue search, ticket creation) flows through INJECTED PORTS so the unit test
|
|
25
|
-
* runs with no network. Production wires the ports to the GitHub provider /
|
|
26
|
-
* `/mandrel-plan` / `/mandrel-plan` surfaces; tests pass in-memory stubs.
|
|
2
|
+
* lib/findings/promote-finding.js — promote clustered untriaged QA ledger
|
|
3
|
+
* items to a Story or plan-seed via `routeFinding`, stamping `routedTo` on
|
|
4
|
+
* each item so a resume does not re-promote. Ports are injected.
|
|
27
5
|
*/
|
|
28
6
|
|
|
29
7
|
import { fingerprintFinding, routeFinding } from './route-finding.js';
|
|
30
8
|
import { highestSeverity as highestSeverityOf } from './severity.js';
|
|
31
9
|
|
|
32
|
-
/** Triaged dispositions, mirrored from the `disposition` enum in the schema. */
|
|
33
10
|
const TRIAGED_DISPOSITIONS = Object.freeze(['file', 'defer', 'dismiss']);
|
|
34
11
|
|
|
35
|
-
/**
|
|
36
|
-
* The two promotion targets a cluster routes to.
|
|
37
|
-
*
|
|
38
|
-
* `PLAN_SEED` promotes a broad cluster by seeding a multi-Story `/mandrel-plan`
|
|
39
|
-
* run (`/mandrel-plan --seed`). Its persisted wire token is the legacy string
|
|
40
|
-
* `'epic'`: archived qa-ledger records (and the distributed
|
|
41
|
-
* `qa-ledger.schema.json` `routedTo.kind` enum) still carry `'epic'`, so
|
|
42
|
-
* the value is kept read-compatible while the write-side constant name is
|
|
43
|
-
* modernised.
|
|
44
|
-
*/
|
|
12
|
+
/** `PLAN_SEED` stays `'epic'` on the wire: archived ledgers and the schema enum carry it. */
|
|
45
13
|
export const PROMOTION_TARGETS = Object.freeze({
|
|
46
14
|
STORY: 'story',
|
|
47
15
|
PLAN_SEED: 'epic',
|
|
48
16
|
});
|
|
49
17
|
|
|
50
|
-
/**
|
|
51
|
-
* A cluster of more than this many distinct coverage surfaces is broad enough
|
|
52
|
-
* to warrant a plan-seed (`/mandrel-plan --seed`) rather than a single Story
|
|
53
|
-
* (`/mandrel-plan`). One or two surfaces is a tight, single-deliverable cluster.
|
|
54
|
-
*/
|
|
18
|
+
/** More distinct coverage surfaces than this → plan-seed instead of a Story. */
|
|
55
19
|
const EPIC_COVERAGE_THRESHOLD = 2;
|
|
56
20
|
|
|
57
21
|
/**
|
|
58
|
-
* True when a ledger item has NOT yet been promoted — i.e. it is part of the
|
|
59
|
-
* rolling backlog. An item is untriaged when its `disposition` is not one of
|
|
60
|
-
* the canonical triaged values, OR it is explicitly dispositioned `file` but
|
|
61
|
-
* has not yet been routed (`routedTo` absent). A `defer` / `dismiss` item, or
|
|
62
|
-
* an already-`routedTo` item, is skipped.
|
|
63
|
-
*
|
|
64
22
|
* @param {{ disposition?: unknown, routedTo?: unknown }} item
|
|
65
23
|
* @returns {boolean}
|
|
66
24
|
*/
|
|
@@ -69,20 +27,12 @@ export function isPromotable(item) {
|
|
|
69
27
|
if (item.routedTo) return false;
|
|
70
28
|
const disposition = item.disposition;
|
|
71
29
|
if (disposition === 'defer' || disposition === 'dismiss') return false;
|
|
72
|
-
// `file` items are promotable; anything not in the triaged set (pending,
|
|
73
|
-
// untriaged, null, absent) is the rolling backlog and also promotable.
|
|
74
30
|
if (disposition === 'file') return true;
|
|
75
31
|
return !TRIAGED_DISPOSITIONS.includes(disposition);
|
|
76
32
|
}
|
|
77
33
|
|
|
78
34
|
/**
|
|
79
|
-
*
|
|
80
|
-
* describe the same kind of signal (a product bug, a tooling-DX gap, …) and
|
|
81
|
-
* merge into one follow-up ticket. A class whose items span many distinct
|
|
82
|
-
* coverage surfaces is broad enough to promote to a plan-seed (see
|
|
83
|
-
* {@link targetForCluster}); a class confined to one or two surfaces is a
|
|
84
|
-
* single-deliverable Story. Coverage is therefore a *secondary* signal that
|
|
85
|
-
* sizes the cluster rather than splitting it.
|
|
35
|
+
* Coverage sizes a cluster; it never splits one.
|
|
86
36
|
*
|
|
87
37
|
* @param {{ class?: string }} item
|
|
88
38
|
* @returns {string}
|
|
@@ -94,27 +44,15 @@ function clusterKeyFor(item) {
|
|
|
94
44
|
}
|
|
95
45
|
|
|
96
46
|
/**
|
|
97
|
-
* The highest severity present across a cluster's items, resolved through the
|
|
98
|
-
* shared canonical {@link ./severity.js} vocabulary (Story #3816). This module
|
|
99
|
-
* no longer declares its own severity rank table — the ordering lives in one
|
|
100
|
-
* place so a cluster severity and a `classify-finding` severity for the same
|
|
101
|
-
* input are identical, keeping the `fingerprintFinding` identity stable.
|
|
102
|
-
*
|
|
103
47
|
* @param {Array<{ severity?: string }>} items
|
|
104
|
-
* @returns {string}
|
|
48
|
+
* @returns {string}
|
|
105
49
|
*/
|
|
106
50
|
function highestSeverity(items) {
|
|
107
51
|
return highestSeverityOf(items.map((item) => item?.severity));
|
|
108
52
|
}
|
|
109
53
|
|
|
110
54
|
/**
|
|
111
|
-
*
|
|
112
|
-
* surface + class. Returns one cluster per distinct key, each carrying the
|
|
113
|
-
* contributing items, the distinct coverage surfaces it spans, the highest
|
|
114
|
-
* severity in the merge, and a synthesized title. Deterministic: clusters and
|
|
115
|
-
* their items preserve first-seen order.
|
|
116
|
-
*
|
|
117
|
-
* @param {Array<object>} items — ledger items (the full session ledger).
|
|
55
|
+
* @param {Array<object>} items
|
|
118
56
|
* @returns {Array<{
|
|
119
57
|
* key: string,
|
|
120
58
|
* class: string,
|
|
@@ -166,11 +104,6 @@ export function clusterLedgerItems(items) {
|
|
|
166
104
|
}
|
|
167
105
|
|
|
168
106
|
/**
|
|
169
|
-
* Decide a cluster's promotion target. A cluster that spans more than
|
|
170
|
-
* {@link EPIC_COVERAGE_THRESHOLD} distinct coverage surfaces is broad enough to
|
|
171
|
-
* warrant a plan-seed (`/mandrel-plan --seed`); otherwise it is a single-deliverable
|
|
172
|
-
* Story (`/mandrel-plan`).
|
|
173
|
-
*
|
|
174
107
|
* @param {{ coverages: string[] }} cluster
|
|
175
108
|
* @returns {'story'|'epic'}
|
|
176
109
|
*/
|
|
@@ -184,10 +117,8 @@ export function targetForCluster(cluster) {
|
|
|
184
117
|
}
|
|
185
118
|
|
|
186
119
|
/**
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* The coverage surface stands in for `area`; the class becomes a label so two
|
|
190
|
-
* clusters with the same title but different classes fingerprint distinctly.
|
|
120
|
+
* The class is a label so same-titled clusters of different classes
|
|
121
|
+
* fingerprint distinctly.
|
|
191
122
|
*
|
|
192
123
|
* @param {{ title: string, coverages: string[], class: string, severity: string }} cluster
|
|
193
124
|
* @returns {{ title: string, area: string, primaryFile: string, severity: string, labels: string[] }}
|
|
@@ -203,13 +134,7 @@ function clusterToFinding(cluster) {
|
|
|
203
134
|
}
|
|
204
135
|
|
|
205
136
|
/**
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
* The `routedTo.url` field is `minLength: 1` in `qa-ledger.schema.json`,
|
|
209
|
-
* and the search/create port contract requires a
|
|
210
|
-
* routed issue to carry its canonical URL. So rather than silently stamp an
|
|
211
|
-
* empty string (which would persist a schema-invalid ledger item), this guards
|
|
212
|
-
* the url and throws when it is absent or blank (Story #3816, AC #4).
|
|
137
|
+
* `routedTo.url` is `minLength: 1` in the schema, so an empty url throws.
|
|
213
138
|
*
|
|
214
139
|
* @param {{ number: number, url?: string }} issue
|
|
215
140
|
* @param {'story'|'epic'|'issue'} kind
|
|
@@ -233,35 +158,15 @@ function routedToLink(issue, kind) {
|
|
|
233
158
|
}
|
|
234
159
|
|
|
235
160
|
/**
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
* back onto each contributing ledger item.
|
|
239
|
-
*
|
|
240
|
-
* For each cluster:
|
|
241
|
-
* 1. Adapt the cluster onto the canonical finding shape and route it with the
|
|
242
|
-
* shared `routeFinding` against existing Issues (via the injected search
|
|
243
|
-
* port). This dedups against work already filed.
|
|
244
|
-
* 2. On a `new` decision, open the follow-up ticket through the injected
|
|
245
|
-
* `createStory` (`/mandrel-plan`) or `createPlanSeed` (`/mandrel-plan --seed`) port,
|
|
246
|
-
* chosen by {@link targetForCluster}. On any other decision, link back to
|
|
247
|
-
* the matched Issue rather than creating a duplicate.
|
|
248
|
-
* 3. Stamp the resolved `routedTo` link onto every contributing ledger item
|
|
249
|
-
* (mutating the item objects in place, so a `qa-session` append persists
|
|
250
|
-
* the link).
|
|
251
|
-
*
|
|
252
|
-
* All GitHub side-effects flow through the injected ports — there is no network
|
|
253
|
-
* I/O in this module, so the unit test runs offline.
|
|
161
|
+
* On `new`, create via the target's port; otherwise link to the matched
|
|
162
|
+
* Issue. Items are mutated in place so a `qa-session` append persists the link.
|
|
254
163
|
*
|
|
255
|
-
* @param {Array<object>} ledgerItems
|
|
164
|
+
* @param {Array<object>} ledgerItems
|
|
256
165
|
* @param {object} ports
|
|
257
166
|
* @param {(sha: string) => Promise<Array<{ number: number, state: string, body?: string }>>} [ports.searchIssues]
|
|
258
|
-
* Fingerprint-keyed lookup over open+closed issues, forwarded to `routeFinding`.
|
|
259
167
|
* @param {(finding: object) => Promise<Array<{ number: number, state: string, title?: string, body?: string }>>} [ports.searchCandidates]
|
|
260
|
-
* Optional semantic candidate search, forwarded to `routeFinding`.
|
|
261
168
|
* @param {(cluster: object) => Promise<{ number: number, url?: string }>} ports.createStory
|
|
262
|
-
* Opens a single Story (`/mandrel-plan`) for a tight cluster.
|
|
263
169
|
* @param {(cluster: object) => Promise<{ number: number, url?: string }>} ports.createPlanSeed
|
|
264
|
-
* Opens a plan-seed (`/mandrel-plan --seed`) run for a broad cluster.
|
|
265
170
|
* @returns {Promise<{
|
|
266
171
|
* promotions: Array<{
|
|
267
172
|
* clusterKey: string,
|
|
@@ -312,8 +217,6 @@ export async function promoteFindings(ledgerItems, ports = {}) {
|
|
|
312
217
|
issue = await createPort(cluster);
|
|
313
218
|
created = true;
|
|
314
219
|
} else {
|
|
315
|
-
// Already filed (open match, duplicate, or regression of a closed
|
|
316
|
-
// ticket) — link back to the matched Issue instead of duplicating.
|
|
317
220
|
issue = {
|
|
318
221
|
number: route.matchedIssue.number,
|
|
319
222
|
url: route.matchedIssue.url,
|
|
@@ -323,7 +226,6 @@ export async function promoteFindings(ledgerItems, ports = {}) {
|
|
|
323
226
|
const kind = created ? target : 'issue';
|
|
324
227
|
const link = routedToLink(issue, kind);
|
|
325
228
|
|
|
326
|
-
// Write the routedTo link back onto each contributing ledger item.
|
|
327
229
|
for (const item of cluster.items) {
|
|
328
230
|
item.routedTo = { ...link };
|
|
329
231
|
}
|