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,12 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* lib/project-root.js — side-effect-free leaf
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Extracted from `config-resolver.js` (Story #3993) so the ~10 importers
|
|
6
|
-
* that need only the path constant no longer transitively load the
|
|
7
|
-
* stateful config subsystem (module-global caches + `.env` load side
|
|
8
|
-
* effect). `config-resolver.js` re-exports this constant, so its barrel
|
|
9
|
-
* surface is unchanged.
|
|
2
|
+
* lib/project-root.js — side-effect-free leaf for the repo root, so
|
|
3
|
+
* importers avoid loading the stateful config subsystem.
|
|
10
4
|
*/
|
|
11
5
|
|
|
12
6
|
import path from 'node:path';
|
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provider Factory — resolves the configured ticketing provider to a concrete class.
|
|
3
|
-
*
|
|
4
|
-
* Accepts the canonical resolved config object (the wrapper returned by
|
|
5
|
-
* `resolveConfig()` with `config.github` populated). The legacy
|
|
6
|
-
* `orchestration`-shaped argument is no longer supported as part of the
|
|
7
|
-
* Epic #2880 hard cutover; see `.agents/rules/git-conventions-reference.md#contract-cutovers-—-no-shim-layer`.
|
|
8
|
-
*
|
|
9
|
-
* @see docs/v5-implementation-plan.md Sprint 1B
|
|
10
|
-
*/
|
|
1
|
+
/** Provider factory — resolved config → concrete ticketing provider. */
|
|
11
2
|
|
|
12
3
|
import { GitHubProvider } from '../providers/github.js';
|
|
13
4
|
|
|
@@ -17,16 +8,6 @@ const PROVIDERS = {
|
|
|
17
8
|
};
|
|
18
9
|
|
|
19
10
|
/**
|
|
20
|
-
* Create a ticketing provider instance from the canonical resolved config.
|
|
21
|
-
*
|
|
22
|
-
* The canonical contract is:
|
|
23
|
-
* - `config.github` carries the GitHub provider config block
|
|
24
|
-
* (`owner`, `repo`, `projectNumber`, `projectOwner`, `operatorHandle`,
|
|
25
|
-
* and friends).
|
|
26
|
-
* - Today GitHub is the only supported provider, so the provider name is
|
|
27
|
-
* inferred from the presence of `config.github`. When additional
|
|
28
|
-
* providers land, this resolver will gain a `config.provider` discriminator.
|
|
29
|
-
*
|
|
30
11
|
* @param {object|null} config - The resolved config wrapper (`resolveConfig()` output).
|
|
31
12
|
* @param {{ token?: string }} [opts] - Override options (e.g., test token).
|
|
32
13
|
* @returns {import('../lib/ITicketingProvider.js').ITicketingProvider}
|
|
@@ -68,11 +49,7 @@ export function createProvider(config, opts = {}) {
|
|
|
68
49
|
return new ProviderClass(providerConfig, opts);
|
|
69
50
|
}
|
|
70
51
|
|
|
71
|
-
/**
|
|
72
|
-
* Infer the provider name from the resolved config. Today the only
|
|
73
|
-
* supported value is `'github'`; a future provider would add a discriminator
|
|
74
|
-
* field on the top-level config and this helper would consult it.
|
|
75
|
-
*/
|
|
52
|
+
/** An explicit `config.provider` wins; otherwise a `github` block implies it. */
|
|
76
53
|
function resolveProviderName(config) {
|
|
77
54
|
if (typeof config.provider === 'string') return config.provider;
|
|
78
55
|
if (config.github) return 'github';
|
|
@@ -1,46 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* console-allowlist.js — deterministic console-message → finding filter.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Epic #3214). The QA harness captures per-surface console messages via
|
|
6
|
-
* `list_console_messages` and must turn genuine console errors into
|
|
7
|
-
* structured findings while suppressing benign, expected noise. The
|
|
8
|
-
* suppression contract is the `qa.consoleAllowlist` array bound in
|
|
9
|
-
* `.agentrc.json` (landed by Story #3293): a list of inline patterns that
|
|
10
|
-
* mark a console message as expected.
|
|
11
|
-
*
|
|
12
|
-
* This module is the pure, side-effect-free decision layer. Given a list of
|
|
13
|
-
* captured console messages and the consumer's `consoleAllowlist`, it returns
|
|
14
|
-
* one structured finding per non-allowlisted console error and drops every
|
|
15
|
-
* message matched by an allowlist pattern. Determinism is load-bearing:
|
|
16
|
-
* re-running the filter over the same captured console with the same allowlist
|
|
17
|
-
* always yields the same findings in the same order, so the surrounding
|
|
18
|
-
* harness produces stable, diffable evidence.
|
|
19
|
-
*
|
|
20
|
-
* The emitted finding aligns with the `F#` finding shape from Tech Spec #3285
|
|
21
|
-
* (`{ id, classification, surface, symptom, likelyRootCause, disposition,
|
|
22
|
-
* acceptance, evidence: { console[], network[] } }`). This module produces the
|
|
23
|
-
* console-derived subset; `/qa-run` (Story #4330) maps each such finding onto a
|
|
24
|
-
* `QaLedgerItem` (`qa-ledger.schema.json`) before routing it through the shared
|
|
25
|
-
* classify/route/dedup/promote core, leaving richer enrichment
|
|
26
|
-
* (likely-root-cause heuristics, drafting) to those later layers.
|
|
3
|
+
* Each non-allowlisted console error becomes one `F#` finding (console-derived
|
|
4
|
+
* subset); `qa.consoleAllowlist` patterns suppress expected noise.
|
|
27
5
|
*/
|
|
28
6
|
|
|
29
7
|
/**
|
|
30
|
-
*
|
|
31
|
-
* messages at one of these levels can become a finding; `log`, `info`,
|
|
32
|
-
* `debug`, and `warning` are never escalated by this module.
|
|
8
|
+
* Only these levels can become a finding.
|
|
33
9
|
*
|
|
34
10
|
* @type {ReadonlySet<string>}
|
|
35
11
|
*/
|
|
36
12
|
const ERROR_LEVELS = new Set(['error', 'severe']);
|
|
37
13
|
|
|
38
14
|
/**
|
|
39
|
-
*
|
|
40
|
-
* surfaces (`list_console_messages`, raw CDP, etc.) disagree on field names,
|
|
41
|
-
* so accept the common spellings and coerce defensively. A message with no
|
|
42
|
-
* recoverable text normalises to an empty string (which never matches an
|
|
43
|
-
* allowlist pattern and never reads as an error symptom).
|
|
15
|
+
* Capture surfaces disagree on field names, so accept the common spellings.
|
|
44
16
|
*
|
|
45
17
|
* @param {unknown} message
|
|
46
18
|
* @returns {{ level: string, text: string }}
|
|
@@ -59,17 +31,11 @@ function normaliseMessage(message) {
|
|
|
59
31
|
}
|
|
60
32
|
|
|
61
33
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* Each allowlist entry is matched as a case-sensitive substring against the
|
|
65
|
-
* message text. Substring (not regex) matching is the deliberate contract:
|
|
66
|
-
* patterns stay readable in `.agentrc.json`, an operator never has to escape
|
|
67
|
-
* regex metacharacters, and the decision is trivially deterministic. An empty
|
|
68
|
-
* or blank pattern is ignored (it would otherwise match everything and
|
|
69
|
-
* silently swallow every error).
|
|
34
|
+
* Case-sensitive substring match (not regex, so operators never escape
|
|
35
|
+
* metacharacters). A blank pattern is ignored — it would swallow every error.
|
|
70
36
|
*
|
|
71
37
|
* @param {string} text Normalised console message text.
|
|
72
|
-
* @param {string[]} allowlist
|
|
38
|
+
* @param {string[]} allowlist
|
|
73
39
|
* @returns {boolean} `true` when the message is allowlisted (suppress it).
|
|
74
40
|
*/
|
|
75
41
|
export function isAllowlisted(text, allowlist) {
|
|
@@ -85,11 +51,6 @@ export function isAllowlisted(text, allowlist) {
|
|
|
85
51
|
}
|
|
86
52
|
|
|
87
53
|
/**
|
|
88
|
-
* Build a structured finding for a single non-allowlisted console error.
|
|
89
|
-
* The `id` is assigned by the caller (1-based finding index across a surface)
|
|
90
|
-
* so the surrounding harness controls finding numbering across console and
|
|
91
|
-
* network evidence.
|
|
92
|
-
*
|
|
93
54
|
* @param {{ level: string, text: string }} message Normalised console error.
|
|
94
55
|
* @param {{ surface?: string, index: number }} ctx
|
|
95
56
|
* @returns {object} Structured `F#` finding (console-derived subset).
|
|
@@ -111,22 +72,12 @@ function buildFinding(message, ctx) {
|
|
|
111
72
|
}
|
|
112
73
|
|
|
113
74
|
/**
|
|
114
|
-
*
|
|
115
|
-
* structured finding for each non-allowlisted console error.
|
|
116
|
-
*
|
|
117
|
-
* Behaviour contract:
|
|
118
|
-
* - A console **error** (level `error`/`severe`) whose text matches no
|
|
119
|
-
* allowlist pattern becomes exactly one finding.
|
|
120
|
-
* - A console message matched by any allowlist pattern is suppressed — no
|
|
121
|
-
* finding — even when it is an error.
|
|
122
|
-
* - Non-error levels (`log`, `info`, `warning`, …) are never escalated.
|
|
123
|
-
* - Findings are returned in capture order; ids are assigned `F1`, `F2`, …
|
|
124
|
-
* in that order.
|
|
75
|
+
* Findings in capture order, ids `F1`, `F2`, …
|
|
125
76
|
*
|
|
126
77
|
* @param {Array<unknown>} messages Captured console messages.
|
|
127
78
|
* @param {string[]} [allowlist] `qa.consoleAllowlist` patterns.
|
|
128
|
-
* @param {{ surface?: string }} [opts]
|
|
129
|
-
* @returns {object[]}
|
|
79
|
+
* @param {{ surface?: string }} [opts]
|
|
80
|
+
* @returns {object[]}
|
|
130
81
|
*/
|
|
131
82
|
export function filterConsoleMessages(messages, allowlist = [], opts = {}) {
|
|
132
83
|
if (!Array.isArray(messages)) {
|
|
@@ -1,32 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* QA exploratory-session resume helper
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* (
|
|
6
|
-
*
|
|
7
|
-
* *same* session-id must read the on-disk ledger, carry forward the still
|
|
8
|
-
* un-triaged findings as a rolling backlog, and append to — never overwrite —
|
|
9
|
-
* the existing file.
|
|
10
|
-
*
|
|
11
|
-
* This module owns three small seams:
|
|
12
|
-
* - {@link resolveSessionId} — a stable session-id for a run.
|
|
13
|
-
* - {@link ledgerPathFor} — the ledger path under `<tempRoot>/qa/`.
|
|
14
|
-
* - {@link readLedger} — parse an existing ledger into items plus the
|
|
15
|
-
* un-triaged subset (the rolling backlog).
|
|
16
|
-
*
|
|
17
|
-
* {@link resolveQaSession} composes them: it resolves the id and path, reads
|
|
18
|
-
* any existing ledger, and reports whether the file already existed so the
|
|
19
|
-
* caller knows to *reuse* rather than re-create it.
|
|
20
|
-
*
|
|
21
|
-
* Evidence persisted in the ledger MUST already be scrubbed of secrets and
|
|
22
|
-
* PII per `.agents/rules/security-baseline.md` (see `lib/qa/redact-evidence.js`)
|
|
23
|
-
* before it reaches disk; this module only reads what is already there.
|
|
24
|
-
*
|
|
25
|
-
* The ledger round-trip is field-preserving: {@link readLedger} parses each
|
|
26
|
-
* line as a whole `QaLedgerItem` and returns it untouched, so optional fields
|
|
27
|
-
* such as the Triage `routedTo` finding-to-issue link
|
|
28
|
-
* (see `.agents/schemas/qa-ledger.schema.json`) survive a read/append cycle
|
|
29
|
-
* intact rather than being dropped on resume.
|
|
2
|
+
* QA exploratory-session resume helper. A resumed run with the same
|
|
3
|
+
* session-id reads the on-disk NDJSON ledger, carries forward un-triaged items
|
|
4
|
+
* as the rolling backlog, and appends — never overwrites. Items round-trip
|
|
5
|
+
* untouched so optional fields (e.g. `routedTo`) survive. Evidence must be
|
|
6
|
+
* redacted before it reaches the ledger; this module only reads.
|
|
30
7
|
*/
|
|
31
8
|
|
|
32
9
|
import crypto from 'node:crypto';
|
|
@@ -35,22 +12,15 @@ import path from 'node:path';
|
|
|
35
12
|
|
|
36
13
|
import { tempRootFrom } from '../config/temp-paths.js';
|
|
37
14
|
|
|
38
|
-
/** Directory segment (under `tempRoot`) that holds every QA session ledger. */
|
|
39
15
|
const QA_LEDGER_DIRNAME = 'qa';
|
|
40
16
|
|
|
41
17
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* already been triaged; anything else (absent, null, empty, or unrecognized)
|
|
45
|
-
* is still part of the rolling backlog.
|
|
18
|
+
* Mirrors the `disposition` enum in `qa-ledger.schema.json`; anything else
|
|
19
|
+
* (absent, null, unrecognized) is still backlog.
|
|
46
20
|
*/
|
|
47
21
|
export const TRIAGED_DISPOSITIONS = Object.freeze(['file', 'defer', 'dismiss']);
|
|
48
22
|
|
|
49
23
|
/**
|
|
50
|
-
* True when a ledger item has **not** yet been triaged — i.e. its
|
|
51
|
-
* `disposition` is not one of the canonical triaged values. These items are
|
|
52
|
-
* the rolling backlog a resume run carries forward.
|
|
53
|
-
*
|
|
54
24
|
* @param {{ disposition?: unknown }} item
|
|
55
25
|
* @returns {boolean}
|
|
56
26
|
*/
|
|
@@ -60,10 +30,7 @@ export function isUntriaged(item) {
|
|
|
60
30
|
}
|
|
61
31
|
|
|
62
32
|
/**
|
|
63
|
-
*
|
|
64
|
-
* alphanumerics, dot, dash, and underscore; collapses everything else to a
|
|
65
|
-
* single dash. Guards against path traversal so a hostile label can never
|
|
66
|
-
* escape the `qa/` directory.
|
|
33
|
+
* Filesystem-safe slug; guards against a hostile label escaping `qa/`.
|
|
67
34
|
*
|
|
68
35
|
* @param {string} raw
|
|
69
36
|
* @returns {string}
|
|
@@ -77,9 +44,7 @@ function slugifySessionId(raw) {
|
|
|
77
44
|
}
|
|
78
45
|
|
|
79
46
|
/**
|
|
80
|
-
*
|
|
81
|
-
* date-prefixed for human scannability and suffixed with short entropy so two
|
|
82
|
-
* runs on the same day never collide.
|
|
47
|
+
* Date-prefixed with short entropy so same-day runs never collide.
|
|
83
48
|
*
|
|
84
49
|
* @returns {string}
|
|
85
50
|
*/
|
|
@@ -90,11 +55,7 @@ function deriveSessionId() {
|
|
|
90
55
|
}
|
|
91
56
|
|
|
92
57
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* Precedence: an explicit `sessionId` option wins; otherwise the
|
|
96
|
-
* `QA_SESSION_ID` environment variable; otherwise a freshly derived id. An
|
|
97
|
-
* explicit or environment id is slugified so it is safe to use as a filename.
|
|
58
|
+
* Explicit `sessionId`, then `QA_SESSION_ID`, then a derived id.
|
|
98
59
|
*
|
|
99
60
|
* @param {{ sessionId?: string, env?: NodeJS.ProcessEnv }} [opts]
|
|
100
61
|
* @returns {string}
|
|
@@ -112,11 +73,9 @@ export function resolveSessionId(opts = {}) {
|
|
|
112
73
|
}
|
|
113
74
|
|
|
114
75
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* @
|
|
118
|
-
* @param {object} [config] Resolved config bag (for `project.paths.tempRoot`).
|
|
119
|
-
* @returns {string}
|
|
76
|
+
* @param {string} sessionId
|
|
77
|
+
* @param {object} [config]
|
|
78
|
+
* @returns {string} `<tempRoot>/qa/<sessionId>.ndjson`
|
|
120
79
|
*/
|
|
121
80
|
export function ledgerPathFor(sessionId, config) {
|
|
122
81
|
const slug = slugifySessionId(sessionId);
|
|
@@ -124,9 +83,7 @@ export function ledgerPathFor(sessionId, config) {
|
|
|
124
83
|
}
|
|
125
84
|
|
|
126
85
|
/**
|
|
127
|
-
*
|
|
128
|
-
* blank or not valid JSON. Malformed lines are skipped rather than thrown so a
|
|
129
|
-
* partially-written ledger from a crashed run still resumes.
|
|
86
|
+
* Malformed lines are skipped so a crashed run's partial ledger still resumes.
|
|
130
87
|
*
|
|
131
88
|
* @param {string} line
|
|
132
89
|
* @returns {object | null}
|
|
@@ -142,12 +99,6 @@ function parseLine(line) {
|
|
|
142
99
|
}
|
|
143
100
|
|
|
144
101
|
/**
|
|
145
|
-
* Read and parse an existing ledger from disk.
|
|
146
|
-
*
|
|
147
|
-
* Returns the full parsed `items` array plus `untriaged` — the subset whose
|
|
148
|
-
* disposition is not yet triaged (the rolling backlog). A missing ledger is
|
|
149
|
-
* not an error: it yields empty arrays and `exists: false`.
|
|
150
|
-
*
|
|
151
102
|
* @param {string} ledgerPath
|
|
152
103
|
* @param {{ fsImpl?: typeof fs }} [opts]
|
|
153
104
|
* @returns {{ exists: boolean, items: object[], untriaged: object[] }}
|
|
@@ -163,12 +114,7 @@ export function readLedger(ledgerPath, opts = {}) {
|
|
|
163
114
|
}
|
|
164
115
|
|
|
165
116
|
/**
|
|
166
|
-
*
|
|
167
|
-
* under `<tempRoot>/qa/`, and the current ledger contents (parsed items plus
|
|
168
|
-
* the un-triaged rolling backlog).
|
|
169
|
-
*
|
|
170
|
-
* `reused` is `true` when a ledger already exists for this session-id — the
|
|
171
|
-
* signal that a resume run must append to, not overwrite, the file.
|
|
117
|
+
* `reused: true` means a ledger exists and the run must append to it.
|
|
172
118
|
*
|
|
173
119
|
* @param {{
|
|
174
120
|
* sessionId?: string,
|
|
@@ -1,48 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* redact-evidence.js — deterministic secrets/PII scrubber
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* harness captures evidence strings (console text, network bodies, error
|
|
6
|
-
* symptoms) that may carry sensitive material. The security baseline
|
|
7
|
-
* (`.agents/rules/security-baseline.md` § Data Leakage & Logging, § Secrets
|
|
8
|
-
* Management) forbids persisting or posting that material to disk or GitHub.
|
|
9
|
-
* This module is the redaction pass that runs **before** any such persistence.
|
|
10
|
-
*
|
|
11
|
-
* The rule set covers the full security-baseline secret/PII taxonomy:
|
|
12
|
-
* bearer tokens, session cookies, email addresses, **passwords**, **API keys**,
|
|
13
|
-
* **credit-card numbers (PANs)**, and **SSNs**. Story #3737 added the last four
|
|
14
|
-
* classes (the #3686 epic-audit + PR #3736 code-review flagged the original
|
|
15
|
-
* scope as narrower than the baseline it advertises) and tightened the
|
|
16
|
-
* session-cookie rule so a benign `name=value` pair whose name merely
|
|
17
|
-
* *contains* a session word (e.g. `author=Jane`, `outside=cold`) is no longer
|
|
18
|
-
* over-redacted (the M1 cookie over-redaction finding).
|
|
19
|
-
*
|
|
20
|
-
* Like its sibling `console-allowlist.js`, this is the pure, side-effect-free
|
|
21
|
-
* decision layer: given an evidence string, it returns the string with every
|
|
22
|
-
* matched secret/PII span replaced by a fixed placeholder. Determinism is
|
|
23
|
-
* load-bearing — re-running the pass over the same input always yields the
|
|
24
|
-
* same output, which gives the harness two guarantees the acceptance criteria
|
|
25
|
-
* pin directly:
|
|
26
|
-
*
|
|
27
|
-
* 1. Idempotence — running `redactEvidence` over already-redacted text is a
|
|
28
|
-
* no-op, because each placeholder contains none of the patterns that
|
|
29
|
-
* triggered a redaction. The fixed-point property means the harness can
|
|
30
|
-
* redact eagerly without worrying about double-scrubbing corrupting
|
|
31
|
-
* evidence.
|
|
32
|
-
* 2. Pass-through — a string matching no rule is returned byte-for-byte
|
|
33
|
-
* unchanged, so benign evidence is never mangled.
|
|
34
|
-
*
|
|
35
|
-
* Each placeholder is distinct per rule so a reader of the redacted evidence
|
|
36
|
-
* can still tell *what kind* of secret was scrubbed without seeing its value.
|
|
2
|
+
* redact-evidence.js — deterministic secrets/PII scrubber run before QA
|
|
3
|
+
* evidence is persisted or posted (security baseline § Data Leakage).
|
|
4
|
+
* Idempotent (placeholders match no rule) and pass-through for benign text.
|
|
37
5
|
*/
|
|
38
6
|
|
|
39
7
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* charset run long enough to re-trigger, no `=` cookie assignment, no digit
|
|
43
|
-
* run long enough to read as a PAN/SSN), which is what makes the pass a fixed
|
|
44
|
-
* point — feeding a redacted string back in matches nothing and changes
|
|
45
|
-
* nothing.
|
|
8
|
+
* Per-rule placeholders, free of anything a pattern matches (`@`, `=`, long
|
|
9
|
+
* token or digit runs) so the pass is a fixed point.
|
|
46
10
|
*
|
|
47
11
|
* @type {Readonly<Record<string, string>>}
|
|
48
12
|
*/
|
|
@@ -57,44 +21,28 @@ const PLACEHOLDERS = Object.freeze({
|
|
|
57
21
|
});
|
|
58
22
|
|
|
59
23
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* name — so `sessionId`, `connect.sid`, `auth_token`, `csrf_token`, and
|
|
63
|
-
* `JSESSIONID` match, but `author`, `outside`, `presidency`, and `tokenize`
|
|
64
|
-
* (which merely *contain* a session substring) do not. This segment anchoring
|
|
65
|
-
* is the M1 over-redaction fix.
|
|
24
|
+
* Must appear as a whole `_`/`.`/`-` segment of the cookie name, so
|
|
25
|
+
* `connect.sid` matches but `author` or `tokenize` do not.
|
|
66
26
|
*
|
|
67
27
|
* @type {string}
|
|
68
28
|
*/
|
|
69
29
|
const SESSION_WORDS = 'session|sessionid|sid|auth|token|jsessionid|csrf|xsrf';
|
|
70
30
|
|
|
71
31
|
/**
|
|
72
|
-
* Build the case-insensitive session-cookie pattern. The cookie name is one or
|
|
73
|
-
* more `_`/`.`/`-`-delimited segments where at least one segment *is* a session
|
|
74
|
-
* word (boundaries `^`, `_`, `.`, `-`, `$` on both sides), followed by `=` and
|
|
75
|
-
* a value up to the next `;`, whitespace, or end of string.
|
|
76
|
-
*
|
|
77
32
|
* @returns {RegExp}
|
|
78
33
|
*/
|
|
79
34
|
function buildCookiePattern() {
|
|
80
35
|
const segment = '[A-Za-z0-9]+';
|
|
81
36
|
const sessionSegment = `(?:${SESSION_WORDS})`;
|
|
82
|
-
// name = optional leading segments, a session segment, optional trailing
|
|
83
|
-
// segments, all joined by `_`/`.`/`-`. The (?:...) around the whole name is
|
|
84
|
-
// captured so `replace` can preserve it.
|
|
85
37
|
const name = `(?:${segment}[._-])*${sessionSegment}(?:[._-]${segment})*`;
|
|
86
|
-
// The value
|
|
87
|
-
//
|
|
88
|
-
// apiKeyAssignment on `access_token=…`) is not re-matched and re-labelled as
|
|
89
|
-
// a session cookie. This keeps rule order hermetic and the pass idempotent.
|
|
38
|
+
// The value excludes `[` so a placeholder emitted by an earlier rule is not
|
|
39
|
+
// re-labelled as a session cookie.
|
|
90
40
|
return new RegExp(`\\b(${name})=([^;\\s[]+)`, 'gi');
|
|
91
41
|
}
|
|
92
42
|
|
|
93
43
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* digit count after the loose pattern matches, so a longer numeric id is never
|
|
97
|
-
* partially masked.
|
|
44
|
+
* Confirms 13–19 digits after the loose match, so a longer numeric id is
|
|
45
|
+
* never partially masked.
|
|
98
46
|
*
|
|
99
47
|
* @param {string} candidate
|
|
100
48
|
* @returns {boolean}
|
|
@@ -105,59 +53,31 @@ function isCreditCard(candidate) {
|
|
|
105
53
|
}
|
|
106
54
|
|
|
107
55
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* swept up by a broader cookie match;
|
|
112
|
-
* - the password and API-key rules run before the cookie rule so a
|
|
113
|
-
* `password=…` / `api_key=…` assignment is classified by its own
|
|
114
|
-
* placeholder rather than read as a session cookie;
|
|
115
|
-
* - the credit-card and SSN rules run before the email rule so a bare digit
|
|
116
|
-
* run is classified before the email pass; the email rule runs last so an
|
|
117
|
-
* address embedded in an already-redacted span is never re-scrubbed.
|
|
118
|
-
*
|
|
119
|
-
* Each `pattern` is a global `RegExp` (case-insensitive where the surrounding
|
|
120
|
-
* keywords are alphabetic). The `replace` is a function so a rule can preserve
|
|
121
|
-
* a non-secret prefix (the `Bearer ` keyword, the key name, the cookie name)
|
|
122
|
-
* while masking only the secret value.
|
|
56
|
+
* Order matters: bearer, password and API-key rules precede the cookie rule
|
|
57
|
+
* so those assignments get their own placeholder; digit rules precede email;
|
|
58
|
+
* email runs last.
|
|
123
59
|
*
|
|
124
60
|
* @type {ReadonlyArray<{ name: string, pattern: RegExp, replace: (match: string, ...groups: string[]) => string }>}
|
|
125
61
|
*/
|
|
126
62
|
const RULES = Object.freeze([
|
|
127
|
-
//
|
|
128
|
-
// Preserve the `Bearer ` keyword; mask the credential. The token charset
|
|
129
|
-
// covers base64url / JWT-style values (letters, digits, `-`, `_`, `.`, `+`,
|
|
130
|
-
// `/`, `=`). Require at least 8 chars so a literal word like "Bearer none"
|
|
131
|
-
// is not mistaken for a credential.
|
|
63
|
+
// ≥8 chars so "Bearer none" is not a credential.
|
|
132
64
|
{
|
|
133
65
|
name: 'bearer',
|
|
134
66
|
pattern: /\b(Bearer)\s+([A-Za-z0-9\-._+/=]{8,})/gi,
|
|
135
67
|
replace: (_match, keyword) => `${keyword} ${PLACEHOLDERS.bearer}`,
|
|
136
68
|
},
|
|
137
|
-
// Passwords: a `password` / `passwd` / `pwd` assignment in the common
|
|
138
|
-
// shapes — `password=...`, `pwd: ...`, JSON `"password": "..."`. Preserve
|
|
139
|
-
// the key and the assignment punctuation (`=`, `:`, optional quotes); mask
|
|
140
|
-
// the value up to the next delimiter (`&`, `;`, `,`, whitespace, matching
|
|
141
|
-
// quote, or end of string). Requires a non-empty value so a bare
|
|
142
|
-
// `password=` is left alone.
|
|
143
69
|
{
|
|
144
70
|
name: 'password',
|
|
145
71
|
pattern: /\b(passwd|password|pwd)(["']?\s*[:=]\s*)(["']?)([^"'&;,\s]+)\3/gi,
|
|
146
72
|
replace: (_match, key, sep, quote) =>
|
|
147
73
|
`${key}${sep}${quote}${PLACEHOLDERS.password}${quote}`,
|
|
148
74
|
},
|
|
149
|
-
// API keys (provider-prefixed): Stripe / GitHub `<prefix>_<token>`,
|
|
150
|
-
// OpenAI/Anthropic `sk-<token>`, Google `AIza<token>`, AWS `AKIA<id>`.
|
|
151
|
-
// Masked whole.
|
|
152
75
|
{
|
|
153
76
|
name: 'apiKeyPrefixed',
|
|
154
77
|
pattern:
|
|
155
78
|
/\b(?:sk|pk|rk|ghp|gho|ghs|ghu|ghr)[-_][A-Za-z0-9][A-Za-z0-9_-]{10,}\b|\bAIza[A-Za-z0-9\-_]{20,}\b|\bAKIA[A-Z0-9]{16}\b/g,
|
|
156
79
|
replace: () => PLACEHOLDERS.apiKey,
|
|
157
80
|
},
|
|
158
|
-
// API keys (assignment form): `api_key=...`, `apikey: "..."`,
|
|
159
|
-
// `access-token=...`, `secret_key=...`. Preserve the key name; mask the
|
|
160
|
-
// value.
|
|
161
81
|
{
|
|
162
82
|
name: 'apiKeyAssignment',
|
|
163
83
|
pattern:
|
|
@@ -165,35 +85,22 @@ const RULES = Object.freeze([
|
|
|
165
85
|
replace: (_match, key, sep, quote) =>
|
|
166
86
|
`${key}${sep}${quote}${PLACEHOLDERS.apiKey}${quote}`,
|
|
167
87
|
},
|
|
168
|
-
// Session cookies: a cookie assignment whose name carries a session-secret
|
|
169
|
-
// word as a whole delimited segment (see SESSION_WORDS / buildCookiePattern).
|
|
170
|
-
// Preserve the cookie name and `=`; mask the value up to the next `;`,
|
|
171
|
-
// whitespace, or end of string.
|
|
172
88
|
{
|
|
173
89
|
name: 'cookie',
|
|
174
90
|
pattern: buildCookiePattern(),
|
|
175
91
|
replace: (_match, name) => `${name}=${PLACEHOLDERS.cookie}`,
|
|
176
92
|
},
|
|
177
|
-
// Credit-card numbers (PANs): 13–19 digit runs, optionally grouped by single
|
|
178
|
-
// spaces or hyphens (`4111 1111 1111 1111`, `4111-1111-1111-1111`,
|
|
179
|
-
// `4111111111111111`). The loose pattern matches a digit/separator run; the
|
|
180
|
-
// `replace` confirms the 13–19 digit count before masking so a longer
|
|
181
|
-
// numeric id is never partially redacted. Bounded by non-digit edges.
|
|
182
93
|
{
|
|
183
94
|
name: 'creditCard',
|
|
184
95
|
pattern: /(?<![\d-])\d(?:[ -]?\d){12,18}(?![\d-])/g,
|
|
185
96
|
replace: (match) => (isCreditCard(match) ? PLACEHOLDERS.creditCard : match),
|
|
186
97
|
},
|
|
187
|
-
//
|
|
188
|
-
// form only — a bare 9-digit run is intentionally not treated as an SSN to
|
|
189
|
-
// avoid clobbering benign numeric ids.
|
|
98
|
+
// Hyphenated form only; a bare 9-digit run is too often a benign id.
|
|
190
99
|
{
|
|
191
100
|
name: 'ssn',
|
|
192
101
|
pattern: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
193
102
|
replace: () => PLACEHOLDERS.ssn,
|
|
194
103
|
},
|
|
195
|
-
// Email addresses (RFC 5322 pragmatic subset). Masked whole — the local
|
|
196
|
-
// part and domain are both PII.
|
|
197
104
|
{
|
|
198
105
|
name: 'email',
|
|
199
106
|
pattern: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,
|
|
@@ -202,20 +109,8 @@ const RULES = Object.freeze([
|
|
|
202
109
|
]);
|
|
203
110
|
|
|
204
111
|
/**
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
* addresses — from an evidence string before it is persisted to disk or posted
|
|
208
|
-
* to GitHub.
|
|
209
|
-
*
|
|
210
|
-
* Contract:
|
|
211
|
-
* - Each matched secret/PII span is replaced by a rule-specific placeholder.
|
|
212
|
-
* - The pass is **idempotent**: `redactEvidence(redactEvidence(s)) ===
|
|
213
|
-
* redactEvidence(s)` for all `s`, because placeholders match no rule.
|
|
214
|
-
* - A string matching no rule is returned **unchanged** (referential
|
|
215
|
-
* identity is preserved for the no-match case).
|
|
216
|
-
* - A non-string input is coerced defensively: `null`/`undefined` and
|
|
217
|
-
* non-string values return an empty string, so the redactor never throws on
|
|
218
|
-
* malformed evidence and never leaks a stringified secret-bearing object.
|
|
112
|
+
* Non-string input returns '' so a secret-bearing object is never
|
|
113
|
+
* stringified.
|
|
219
114
|
*
|
|
220
115
|
* @param {unknown} evidence Raw captured evidence text.
|
|
221
116
|
* @returns {string} Redacted evidence (or the original string when no rule
|
|
@@ -227,9 +122,6 @@ export function redactEvidence(evidence) {
|
|
|
227
122
|
}
|
|
228
123
|
let result = evidence;
|
|
229
124
|
for (const rule of RULES) {
|
|
230
|
-
// Reset lastIndex defensively — the shared global RegExp instances carry
|
|
231
|
-
// mutable state across calls, and `String.prototype.replace` resets it,
|
|
232
|
-
// but an explicit reset keeps each call hermetic and order-independent.
|
|
233
125
|
rule.pattern.lastIndex = 0;
|
|
234
126
|
result = result.replace(rule.pattern, rule.replace);
|
|
235
127
|
}
|
|
@@ -237,9 +129,6 @@ export function redactEvidence(evidence) {
|
|
|
237
129
|
}
|
|
238
130
|
|
|
239
131
|
/**
|
|
240
|
-
* The placeholder tokens this module substitutes, exported so callers (and
|
|
241
|
-
* tests) can assert on them without hard-coding the literal strings.
|
|
242
|
-
*
|
|
243
132
|
* @type {Readonly<Record<string, string>>}
|
|
244
133
|
*/
|
|
245
134
|
export const REDACTION_PLACEHOLDERS = PLACEHOLDERS;
|