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,23 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* root**, not against the common git dir. A relative value therefore points
|
|
8
|
-
* at a directory that only exists in the checkout that generated it — husky
|
|
9
|
-
* writes `.husky/_` from its `prepare` script in the main checkout and
|
|
10
|
-
* self-ignores it — so every linked worktree resolves the hooks path to a
|
|
11
|
-
* directory that is not there. Git finds no hooks and proceeds silently:
|
|
12
|
-
* `commit-msg`, `pre-commit` and `pre-push` do not run for any commit made in
|
|
13
|
-
* a worktree, without anyone passing a bypass flag.
|
|
14
|
-
*
|
|
15
|
-
* This module closes that gap by copying the resolved hooks directory into
|
|
16
|
-
* the worktree at the same relative path. It is deliberately total about the
|
|
17
|
-
* cases where there is nothing to do — an unset or absolute `core.hooksPath`,
|
|
18
|
-
* or a source directory that does not exist — because a consumer project
|
|
19
|
-
* without husky must not fail worktree creation. Every other outcome either
|
|
20
|
-
* materializes the hooks or throws: a silent skip is the defect being fixed.
|
|
2
|
+
* Materialize the git hooks directory into a linked worktree. Git resolves a
|
|
3
|
+
* relative `core.hooksPath` per working tree, and husky's gitignored `.husky/_`
|
|
4
|
+
* exists only in the main checkout, so without this no hook runs in a
|
|
5
|
+
* worktree. Nothing-to-do cases skip; every other outcome materializes or
|
|
6
|
+
* throws, never a silent skip.
|
|
21
7
|
*/
|
|
22
8
|
|
|
23
9
|
import { execFileSync } from 'node:child_process';
|
|
@@ -26,27 +12,15 @@ import path from 'node:path';
|
|
|
26
12
|
import * as defaultGit from '../git-utils.js';
|
|
27
13
|
import { assertPathContainment } from '../path-security.js';
|
|
28
14
|
|
|
29
|
-
// Skip reasons
|
|
30
|
-
//
|
|
31
|
-
// strings they are printed as, not through a symbol that could be renamed
|
|
32
|
-
// without anyone noticing the digest changed.
|
|
33
|
-
//
|
|
34
|
-
// hooks-path-unset — git uses the common `hooks` dir, already shared.
|
|
35
|
-
// hooks-path-absolute — resolves alike from every working tree already.
|
|
36
|
-
// source-absent — no hooks directory to mirror (no husky in this project).
|
|
37
|
-
// same-checkout — target is the source; copying it onto itself would
|
|
38
|
-
// destroy the only copy.
|
|
15
|
+
// Skip reasons are printed contract strings, so deliberately not exported.
|
|
16
|
+
// same-checkout: copying the source onto itself would destroy the only copy.
|
|
39
17
|
const SKIP_UNSET = 'hooks-path-unset';
|
|
40
18
|
const SKIP_ABSOLUTE = 'hooks-path-absolute';
|
|
41
19
|
const SKIP_SOURCE_ABSENT = 'source-absent';
|
|
42
20
|
const SKIP_SAME_CHECKOUT = 'same-checkout';
|
|
43
21
|
|
|
44
22
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* `git config --get` exits non-zero when the key is unset, which is a
|
|
48
|
-
* legitimate state rather than an error, so this reports `null` for both an
|
|
49
|
-
* unset key and an empty value.
|
|
23
|
+
* `core.hooksPath`, or `null` when unset or empty.
|
|
50
24
|
*
|
|
51
25
|
* @param {string} repoRoot
|
|
52
26
|
* @param {{ gitSpawn: Function }} gitImpl
|
|
@@ -60,12 +34,7 @@ function readHooksPath(repoRoot, gitImpl) {
|
|
|
60
34
|
}
|
|
61
35
|
|
|
62
36
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* `realpathSync.native` is used so a symlinked temp root (macOS `/var` →
|
|
66
|
-
* `/private/var`) does not make a checkout look distinct from itself. A path
|
|
67
|
-
* that cannot be resolved falls back to `path.resolve`, which is enough for
|
|
68
|
-
* the comparison to stay conservative.
|
|
37
|
+
* Realpath for identity comparison (macOS `/var` → `/private/var`).
|
|
69
38
|
*
|
|
70
39
|
* @param {string} dir
|
|
71
40
|
* @param {typeof fs} fsImpl
|
|
@@ -81,8 +50,6 @@ function canonical(dir, fsImpl) {
|
|
|
81
50
|
}
|
|
82
51
|
|
|
83
52
|
/**
|
|
84
|
-
* Names of the regular files directly inside `dir`, sorted.
|
|
85
|
-
*
|
|
86
53
|
* @param {string} dir
|
|
87
54
|
* @param {typeof fs} fsImpl
|
|
88
55
|
* @returns {string[]}
|
|
@@ -96,14 +63,11 @@ function hookFileNames(dir, fsImpl) {
|
|
|
96
63
|
}
|
|
97
64
|
|
|
98
65
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* Idempotent, and refreshing rather than preserving: an existing target is
|
|
102
|
-
* replaced so an upgraded husky can never leave a stale shim behind.
|
|
66
|
+
* Idempotent; replaces an existing target so no stale shim survives.
|
|
103
67
|
*
|
|
104
68
|
* @param {object} opts
|
|
105
|
-
* @param {string} opts.repoRoot
|
|
106
|
-
* @param {string} opts.worktree
|
|
69
|
+
* @param {string} opts.repoRoot
|
|
70
|
+
* @param {string} opts.worktree
|
|
107
71
|
* @param {{ gitSpawn: Function }} [opts.gitImpl]
|
|
108
72
|
* @param {typeof fs} [opts.fsImpl]
|
|
109
73
|
* @returns {{ action: 'materialized' | 'skipped', reason?: string,
|
|
@@ -145,9 +109,7 @@ export function materializeGitHooks({
|
|
|
145
109
|
if (!fsImpl.existsSync(source)) return skip(SKIP_SOURCE_ABSENT, hooksPath);
|
|
146
110
|
|
|
147
111
|
const target = path.resolve(worktree, hooksPath);
|
|
148
|
-
//
|
|
149
|
-
// remove below — a `../..` value must not be able to delete outside the
|
|
150
|
-
// worktree it claims to provision.
|
|
112
|
+
// The value reaches a recursive remove; `../..` must not escape the worktree.
|
|
151
113
|
assertPathContainment(
|
|
152
114
|
path.resolve(worktree),
|
|
153
115
|
target,
|
|
@@ -165,9 +127,7 @@ export function materializeGitHooks({
|
|
|
165
127
|
);
|
|
166
128
|
}
|
|
167
129
|
|
|
168
|
-
// Verify
|
|
169
|
-
// a hooks directory which is absent behaves exactly like one that is
|
|
170
|
-
// present and empty — git runs neither, and says nothing either way.
|
|
130
|
+
// Verify: missing hooks fail silently in git.
|
|
171
131
|
const expected = hookFileNames(source, fsImpl);
|
|
172
132
|
const actual = new Set(
|
|
173
133
|
fsImpl.existsSync(target) ? hookFileNames(target, fsImpl) : [],
|
|
@@ -183,12 +143,7 @@ export function materializeGitHooks({
|
|
|
183
143
|
}
|
|
184
144
|
|
|
185
145
|
/**
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* `--git-common-dir` reports the common git dir from any working tree —
|
|
189
|
-
* `.git` from the main checkout, an absolute path from a linked worktree —
|
|
190
|
-
* so the owning checkout is its parent. This is what lets the standalone CLI
|
|
191
|
-
* be run from inside a worktree with no arguments.
|
|
146
|
+
* The main checkout: parent of `--git-common-dir`, from any working tree.
|
|
192
147
|
*
|
|
193
148
|
* @param {string} cwd
|
|
194
149
|
* @param {{ execFileSyncImpl?: typeof execFileSync }} [deps]
|
|
@@ -1,22 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* process is still holding handles inside the worktree, this module
|
|
7
|
-
* enumerates the holding processes via PowerShell `Get-CimInstance
|
|
8
|
-
* Win32_Process`, terminates them with `taskkill /T /F`, and re-runs the
|
|
9
|
-
* Stage 2 drain.
|
|
10
|
-
*
|
|
11
|
-
* Detection is best-effort: it matches process `ExecutablePath` and
|
|
12
|
-
* `CommandLine` against the worktree path. Kernel-held locks (Windows
|
|
13
|
-
* Search indexer, AV scanners) won't show up — those entries stay in the
|
|
14
|
-
* manifest and surface again on the next sweep, by which time the
|
|
15
|
-
* indexer/AV has usually moved on.
|
|
16
|
-
*
|
|
17
|
-
* Non-Windows: this module is a no-op (`findHoldersInPath` returns `[]`),
|
|
18
|
-
* so calling `forceDrainPendingCleanup` is safe everywhere — it just
|
|
19
|
-
* degrades to the standard drain.
|
|
2
|
+
* Stage 3 of the reap fallback (Windows): find user-mode processes holding a
|
|
3
|
+
* stuck worktree, `taskkill /T /F` them, and re-drain. Kernel-held locks
|
|
4
|
+
* (indexer, AV) are invisible and wait for the next sweep. A no-op drain
|
|
5
|
+
* elsewhere.
|
|
20
6
|
*/
|
|
21
7
|
|
|
22
8
|
import { spawnSync } from 'node:child_process';
|
|
@@ -24,9 +10,7 @@ import path from 'node:path';
|
|
|
24
10
|
import { NOOP_LOGGER } from '../../Logger.js';
|
|
25
11
|
import { drainPendingCleanup, readManifest } from './pending-cleanup.js';
|
|
26
12
|
|
|
27
|
-
/** Initial wait after `taskkill` before retrying `drainPendingCleanup`. */
|
|
28
13
|
const SETTLE_MS = 1500;
|
|
29
|
-
/** If entries remain stuck after the first post-kill drain, wait again and drain once more. */
|
|
30
14
|
const POST_KILL_RETRY_SETTLE_MS = 800;
|
|
31
15
|
|
|
32
16
|
/**
|
|
@@ -52,15 +36,13 @@ function mergeDrainPasses(prev, next) {
|
|
|
52
36
|
}
|
|
53
37
|
|
|
54
38
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* (timeout, parse error, exit !=0) also returns `[]` — this is best-effort
|
|
58
|
-
* escalation, never a hard error path.
|
|
39
|
+
* Windows processes whose executable or command line references `wtPath`.
|
|
40
|
+
* Best-effort: any failure, or non-Windows, returns `[]`.
|
|
59
41
|
*
|
|
60
|
-
* @param {string} wtPath
|
|
42
|
+
* @param {string} wtPath
|
|
61
43
|
* @param {object} [opts]
|
|
62
|
-
* @param {Function} [opts.spawn]
|
|
63
|
-
* @param {string} [opts.platform]
|
|
44
|
+
* @param {Function} [opts.spawn]
|
|
45
|
+
* @param {string} [opts.platform]
|
|
64
46
|
* @returns {Array<{pid:number, name:string, path?:string, commandLine?:string}>}
|
|
65
47
|
*/
|
|
66
48
|
export function findHoldersInPath(wtPath, opts = {}) {
|
|
@@ -70,7 +52,6 @@ export function findHoldersInPath(wtPath, opts = {}) {
|
|
|
70
52
|
if (!wtPath) return [];
|
|
71
53
|
|
|
72
54
|
const normalized = path.resolve(wtPath);
|
|
73
|
-
// Single-quote escape for PowerShell: double any embedded single quote.
|
|
74
55
|
const psNeedle = normalized.replace(/'/g, "''");
|
|
75
56
|
|
|
76
57
|
const script = [
|
|
@@ -119,11 +100,8 @@ export function findHoldersInPath(wtPath, opts = {}) {
|
|
|
119
100
|
}
|
|
120
101
|
|
|
121
102
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* Cycle-guarded (a corrupt/raced table cannot loop forever). `selfPid` is
|
|
125
|
-
* always included even when the table is empty or missing its row, so the
|
|
126
|
-
* guard fails safe.
|
|
103
|
+
* Pids never to kill: `selfPid` (always, even with an empty table) plus its
|
|
104
|
+
* ancestor chain. Cycle-guarded.
|
|
127
105
|
*
|
|
128
106
|
* @param {number} selfPid
|
|
129
107
|
* @param {Array<{ pid: number, ppid?: number }>} table
|
|
@@ -149,13 +127,11 @@ export function computeProtectedPids(selfPid, table) {
|
|
|
149
127
|
}
|
|
150
128
|
|
|
151
129
|
/**
|
|
152
|
-
*
|
|
153
|
-
* kill set can exclude the invoking shell / orchestrator ancestry.
|
|
154
|
-
* Best-effort: any failure returns `[]` (callers still protect `selfPid`).
|
|
130
|
+
* Windows process table as `{ pid, ppid }`; `[]` on any failure.
|
|
155
131
|
*
|
|
156
132
|
* @param {object} [opts]
|
|
157
|
-
* @param {Function} [opts.spawn]
|
|
158
|
-
* @param {string} [opts.platform]
|
|
133
|
+
* @param {Function} [opts.spawn]
|
|
134
|
+
* @param {string} [opts.platform]
|
|
159
135
|
* @returns {Array<{ pid: number, ppid: number }>}
|
|
160
136
|
*/
|
|
161
137
|
export function fetchProcessTable(opts = {}) {
|
|
@@ -192,15 +168,9 @@ export function fetchProcessTable(opts = {}) {
|
|
|
192
168
|
}
|
|
193
169
|
|
|
194
170
|
/**
|
|
195
|
-
* `taskkill /T /F
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* Self-preservation (Story #4018): holders are matched by command-line
|
|
200
|
-
* substring, which can select the invoking shell or the orchestrator's own
|
|
201
|
-
* ancestor chain (any ancestor whose command line mentions the worktree
|
|
202
|
-
* path). Before any `taskkill /T /F`, the kill set excludes `selfPid` and
|
|
203
|
-
* its full ancestor chain — `/T` on an ancestor would kill this process too.
|
|
171
|
+
* `taskkill /T /F` each holder; returns killed pids, never throws. Excludes
|
|
172
|
+
* self and ancestors: a command-line match can select the invoking shell, and
|
|
173
|
+
* `/T` on an ancestor would kill this process too.
|
|
204
174
|
*/
|
|
205
175
|
export function terminateHolders(holders, opts = {}) {
|
|
206
176
|
const spawn = opts.spawn ?? spawnSync;
|
|
@@ -251,19 +221,9 @@ export function terminateHolders(holders, opts = {}) {
|
|
|
251
221
|
}
|
|
252
222
|
|
|
253
223
|
/**
|
|
254
|
-
* Drain
|
|
255
|
-
* `
|
|
256
|
-
* `
|
|
257
|
-
* terminates them, and re-drains.
|
|
258
|
-
*
|
|
259
|
-
* Result extends the standard drain shape with:
|
|
260
|
-
* - `escalated`: storyIds where holders were detected AND killed.
|
|
261
|
-
* - `killedPids`: { [storyId]: number[] } pids terminated per entry.
|
|
262
|
-
* - `noHolders`: storyIds whose lock could not be attributed to a
|
|
263
|
-
* user-mode process (likely indexer/AV/kernel).
|
|
264
|
-
*
|
|
265
|
-
* Escalation is gated on `escalate: true` (default); pass `false` to
|
|
266
|
-
* mirror the legacy `drainPendingCleanup` behaviour exactly.
|
|
224
|
+
* Drain, then for still-stuck entries kill their holders and re-drain. Adds
|
|
225
|
+
* `escalated`, `killedPids` and `noHolders` (no user-mode holder found) to the
|
|
226
|
+
* drain result; `escalate: false` is a plain drain.
|
|
267
227
|
*/
|
|
268
228
|
export async function forceDrainPendingCleanup({
|
|
269
229
|
repoRoot,
|
|
@@ -1,34 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* worktree
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* `isSafeToRemove`. Runs the two-phase reachability gate the parent
|
|
6
|
-
* documents: primary `merge-base --is-ancestor HEAD baseRef`, and a
|
|
7
|
-
* `git cherry` patch-equivalence fallback when the ancestry check returns
|
|
8
|
-
* "not an ancestor".
|
|
9
|
-
*
|
|
10
|
-
* The fallback exists because a post-merge rebase or force-push can drop
|
|
11
|
-
* the local branch ref off the merged tip, so SHA reachability alone
|
|
12
|
-
* under-reports integration.
|
|
13
|
-
*
|
|
14
|
-
* A third phase used to sit between the two: a `git log --merges
|
|
15
|
-
* --grep=resolves #<storyId>` probe for the `(resolves #N)` token on the
|
|
16
|
-
* Epic's `--no-ff` merge commit. Story #5006 removed it — v2 lands every
|
|
17
|
-
* Story as a **squash** merge onto `main`, which never writes that token,
|
|
18
|
-
* and the `--no-ff` emitter (`story-close/merge-runner.js`) went with the
|
|
19
|
-
* Epic pipeline. The probe could only ever return `false`.
|
|
20
|
-
*
|
|
21
|
-
* Pure with respect to the supplied `ctx` bag; the only side effects are
|
|
22
|
-
* the `gitSpawn` calls.
|
|
2
|
+
* Whether a worktree's work is integrated upstream: HEAD is an ancestor of
|
|
3
|
+
* the base ref, or (after a rebase/force-push moved the tip) every branch
|
|
4
|
+
* commit is patch-equivalent upstream.
|
|
23
5
|
*/
|
|
24
6
|
|
|
25
7
|
/**
|
|
26
|
-
* Resolve a worktree's `HEAD` to a full commit SHA via
|
|
27
|
-
* `git rev-parse HEAD` (run inside the worktree). Returns
|
|
28
|
-
* `{ ok: true, sha, short }` on success, or `{ ok: false, reason }` when
|
|
29
|
-
* the spawn fails. The short form is sliced from the full SHA so callers
|
|
30
|
-
* can build operator-facing reason strings without a second round-trip.
|
|
31
|
-
*
|
|
32
8
|
* @param {object} ctx
|
|
33
9
|
* @param {string} wtPath
|
|
34
10
|
* @returns {{ok: true, sha: string, short: string} | {ok: false, reason: string}}
|
|
@@ -43,13 +19,7 @@ export function resolveHeadSha(ctx, wtPath) {
|
|
|
43
19
|
}
|
|
44
20
|
|
|
45
21
|
/**
|
|
46
|
-
*
|
|
47
|
-
* checkout. Returns one of:
|
|
48
|
-
*
|
|
49
|
-
* - `{ outcome: 'ancestor' }` — exit 0, head is reachable.
|
|
50
|
-
* - `{ outcome: 'not-ancestor' }` — exit 1, head is not reachable; the
|
|
51
|
-
* caller should fall back to the merge-commit-grep path.
|
|
52
|
-
* - `{ outcome: 'error', reason }` — any other exit; treat as unsafe.
|
|
22
|
+
* `merge-base --is-ancestor`: exit 0 ancestor, 1 not, else error (unsafe).
|
|
53
23
|
*
|
|
54
24
|
* @param {object} ctx
|
|
55
25
|
* @param {string} headSha
|
|
@@ -73,30 +43,12 @@ export function checkHeadAncestor(ctx, headSha, epicRef) {
|
|
|
73
43
|
}
|
|
74
44
|
|
|
75
45
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* `true` when every output line starts with `- ` (already upstream by
|
|
79
|
-
* patch-id). Returns `false` when:
|
|
80
|
-
*
|
|
81
|
-
* - `git cherry` exits non-zero,
|
|
82
|
-
* - the output is empty (no commits to compare — the trivial-ancestor
|
|
83
|
-
* case is already covered by `checkHeadAncestor`), or
|
|
84
|
-
* - any output line starts with `+ ` (a commit on `branch` whose
|
|
85
|
-
* patch-id is not present upstream).
|
|
86
|
-
*
|
|
87
|
-
* Surfaces the "Story diff already integrated as rebased equivalents"
|
|
88
|
-
* recovery case: operator manually rebased the Story's content onto
|
|
89
|
-
* `epic/<id>` during recovery, so the diff is on the Epic branch as
|
|
90
|
-
* commits with **different SHAs** but the same patch-ids. The ancestor
|
|
91
|
-
* check returns `false` (Story tip's own commits are not ancestors), and
|
|
92
|
-
* no `(resolves #<id>)` merge commit exists — but the work is
|
|
93
|
-
* functionally integrated.
|
|
94
|
-
*
|
|
95
|
-
* Story #3161 — surfaced during Epic #3078 delivery on Story #3122.
|
|
46
|
+
* True when `git cherry` lists at least one commit and all are `- ` (already
|
|
47
|
+
* upstream by patch-id under different SHAs).
|
|
96
48
|
*
|
|
97
49
|
* @param {object} ctx
|
|
98
|
-
* @param {string} branch
|
|
99
|
-
* @param {string} epicRef
|
|
50
|
+
* @param {string} branch
|
|
51
|
+
* @param {string} epicRef
|
|
100
52
|
* @returns {boolean}
|
|
101
53
|
*/
|
|
102
54
|
export function hasRebasedEquivalents(ctx, branch, epicRef) {
|
|
@@ -111,14 +63,10 @@ export function hasRebasedEquivalents(ctx, branch, epicRef) {
|
|
|
111
63
|
}
|
|
112
64
|
|
|
113
65
|
/**
|
|
114
|
-
* Run the full two-phase merge-reachability gate. Returns the same
|
|
115
|
-
* `{ safe, reason }` envelope `isSafeToRemove` does, so callers can chain
|
|
116
|
-
* the verdict directly into the parent return value.
|
|
117
|
-
*
|
|
118
66
|
* @param {object} ctx
|
|
119
67
|
* @param {string} wtPath
|
|
120
|
-
* @param {string} branch
|
|
121
|
-
* @param {string} epicRef
|
|
68
|
+
* @param {string} branch
|
|
69
|
+
* @param {string} epicRef Base ref the work must be integrated into.
|
|
122
70
|
* @returns {Promise<{safe: boolean, reason: string}>}
|
|
123
71
|
*/
|
|
124
72
|
export async function checkMergeReachability(ctx, wtPath, branch, epicRef) {
|
|
@@ -1,36 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Stage 2 of the reap fallback: worktrees whose removal exhausted Stage 1
|
|
3
|
+
* are recorded in the gitignored `.worktrees/.pending-cleanup.json` and
|
|
4
|
+
* retried by the next plan-time sweep, once OS file locks have usually gone.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* on a Windows lock-class failure, the entry is appended to
|
|
8
|
-
* `.worktrees/.pending-cleanup.json`. The plan-time `worktree-sweep.js`
|
|
9
|
-
* reader (shipped in Epic #349) picks up the manifest on the next
|
|
10
|
-
* `/mandrel-plan` run and retries removal
|
|
11
|
-
* (`git worktree remove` then `fs.rm`) — by then the live file handles from Node / AV / the Windows
|
|
12
|
-
* Search indexer are almost always gone. If `MAX_SWEEP_ATTEMPTS` elapses
|
|
13
|
-
* without clearing, an `OPERATOR ACTION REQUIRED: persistent-lock` line
|
|
14
|
-
* fires and the entry stays in the manifest so the signal persists.
|
|
15
|
-
*
|
|
16
|
-
* The manifest itself lives under `.worktrees/`, which is already
|
|
17
|
-
* git-ignored; no tracked state is mutated.
|
|
18
|
-
*
|
|
19
|
-
* **Story #5112 — the manifest is shared mutable state.** `recordPendingCleanup`
|
|
20
|
-
* runs from the close reap and `drainPendingCleanup` runs from the `/mandrel-plan`
|
|
21
|
-
* boot, so two concurrent delivery sessions can read-modify-write the same
|
|
22
|
-
* file. Three properties close that:
|
|
23
|
-
*
|
|
24
|
-
* 1. **Atomic write.** Every write lands in a pid-scoped temp file and is
|
|
25
|
-
* then `rename`d over the manifest, so a reader never observes a half-
|
|
26
|
-
* written array (`readManifest` treats a torn or absent file as empty,
|
|
27
|
-
* which used to silently *drop* the backlog).
|
|
28
|
-
* 2. **Mutual exclusion.** Read-modify-write runs under the shared
|
|
29
|
-
* `acquireSweepLock` primitive on a manifest-adjacent lockfile.
|
|
30
|
-
* 3. **Merge before write.** The drain holds its snapshot across awaited
|
|
31
|
-
* removals, so it re-reads and merges by `storyId` before its final
|
|
32
|
-
* write — an entry recorded mid-drain survives instead of being erased
|
|
33
|
-
* by a stale snapshot.
|
|
6
|
+
* Concurrent sessions read-modify-write this manifest, so every write is
|
|
7
|
+
* atomic (temp + rename), runs under a lock, and the drain merges by
|
|
8
|
+
* `storyId` against the current file before writing.
|
|
34
9
|
*/
|
|
35
10
|
|
|
36
11
|
import fs from 'node:fs';
|
|
@@ -42,18 +17,9 @@ import { acquireSweepLock } from '../../single-story-sweep/sweep-lock.js';
|
|
|
42
17
|
const MANIFEST_FILENAME = '.pending-cleanup.json';
|
|
43
18
|
const MANIFEST_LOCK_FILENAME = '.pending-cleanup.lock';
|
|
44
19
|
|
|
45
|
-
/**
|
|
46
|
-
* Staleness threshold for the manifest lock. Deliberately short: the guarded
|
|
47
|
-
* section is a read, an in-memory merge and a rename — milliseconds — so a
|
|
48
|
-
* lockfile older than this is a crashed holder, not a slow one.
|
|
49
|
-
*/
|
|
20
|
+
/** Short: the guarded section takes milliseconds, so older means crashed. */
|
|
50
21
|
const MANIFEST_LOCK_TIMEOUT_MS = 5_000;
|
|
51
|
-
/**
|
|
52
|
-
* After a reap hands off to the manifest, `attempts` counts failed
|
|
53
|
-
* `drainPendingCleanup` passes (initial hand-off uses `attempts: 0`). The entry
|
|
54
|
-
* becomes `persistent` when `attempts` reaches this threshold after another
|
|
55
|
-
* failed drain (i.e. three consecutive sweep failures).
|
|
56
|
-
*/
|
|
22
|
+
/** Failed drains (hand-off starts at 0) before an entry is `persistent`. */
|
|
57
23
|
export const MAX_SWEEP_ATTEMPTS = 3;
|
|
58
24
|
|
|
59
25
|
export function manifestPath(worktreeRoot) {
|
|
@@ -61,12 +27,6 @@ export function manifestPath(worktreeRoot) {
|
|
|
61
27
|
}
|
|
62
28
|
|
|
63
29
|
/**
|
|
64
|
-
* Path of the lockfile guarding manifest read-modify-write. Manifest-adjacent
|
|
65
|
-
* (same gitignored `.worktrees/` directory) so it needs no extra config and
|
|
66
|
-
* shares the manifest's lifetime. Module-private: the lock is internal to
|
|
67
|
-
* this manifest's read-modify-write, and callers only ever observe that a
|
|
68
|
-
* mutation completed and left nothing behind.
|
|
69
|
-
*
|
|
70
30
|
* @param {string} worktreeRoot
|
|
71
31
|
* @returns {string}
|
|
72
32
|
*/
|
|
@@ -75,10 +35,9 @@ function manifestLockPath(worktreeRoot) {
|
|
|
75
35
|
}
|
|
76
36
|
|
|
77
37
|
/**
|
|
78
|
-
* Run `fn` under the manifest lock. Best-effort
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* stuck lockfile can never wedge a reap. Always releases.
|
|
38
|
+
* Run `fn` under the manifest lock. Best-effort: on contention `fn` still
|
|
39
|
+
* runs (merge-before-write keeps a lost race harmless), so a stuck lockfile
|
|
40
|
+
* never wedges a reap.
|
|
82
41
|
*
|
|
83
42
|
* @template T
|
|
84
43
|
* @param {string} worktreeRoot
|
|
@@ -116,11 +75,7 @@ export function readManifest(worktreeRoot) {
|
|
|
116
75
|
}
|
|
117
76
|
|
|
118
77
|
/**
|
|
119
|
-
*
|
|
120
|
-
* same directory (so `rename` stays within one filesystem and is therefore
|
|
121
|
-
* atomic), then rename it over the manifest. A concurrent reader sees either
|
|
122
|
-
* the whole previous manifest or the whole new one — never a truncated array
|
|
123
|
-
* that `readManifest`'s catch would silently turn into "no pending cleanups".
|
|
78
|
+
* Atomic write: a torn file would read as empty and silently drop the backlog.
|
|
124
79
|
*/
|
|
125
80
|
function writeManifest(worktreeRoot, entries) {
|
|
126
81
|
const p = manifestPath(worktreeRoot);
|
|
@@ -137,11 +92,8 @@ function writeManifest(worktreeRoot, entries) {
|
|
|
137
92
|
}
|
|
138
93
|
|
|
139
94
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* filesystem and is therefore atomic), then rename it into place. On failure
|
|
143
|
-
* the temp file is reaped and the error propagates — a half-written file is
|
|
144
|
-
* never left where a reader could pick it up.
|
|
95
|
+
* Pid-scoped temp file in the same directory (so rename is atomic), renamed
|
|
96
|
+
* into place; on failure the temp is reaped and the error propagates.
|
|
145
97
|
*
|
|
146
98
|
* @param {string} targetPath
|
|
147
99
|
* @param {string} contents
|
|
@@ -157,28 +109,21 @@ function writeFileAtomic(targetPath, contents) {
|
|
|
157
109
|
}
|
|
158
110
|
}
|
|
159
111
|
|
|
160
|
-
/** Best-effort removal of an abandoned atomic-write temp file. */
|
|
161
112
|
function reapTempFile(tmp) {
|
|
162
113
|
try {
|
|
163
114
|
fs.unlinkSync(tmp);
|
|
164
115
|
} catch {
|
|
165
|
-
//
|
|
116
|
+
// Already gone.
|
|
166
117
|
}
|
|
167
118
|
}
|
|
168
119
|
|
|
169
120
|
/**
|
|
170
|
-
* Upsert
|
|
171
|
-
* repeated failures; always updates `lastFailedAt` and increments
|
|
172
|
-
* `attempts`. New rows start at `attempts: 0` (hand-off, not yet a failed
|
|
173
|
-
* sweep). Called by Stage 1 when fs.rm exhausts its retries.
|
|
121
|
+
* Upsert by storyId, keeping `firstFailedAt`; new rows start at `attempts: 0`.
|
|
174
122
|
*/
|
|
175
123
|
export function recordPendingCleanup(
|
|
176
124
|
worktreeRoot,
|
|
177
125
|
{ storyId, branch, path: wtPath, push = false },
|
|
178
126
|
) {
|
|
179
|
-
// The read, the merge and the write are one critical section: without the
|
|
180
|
-
// lock a concurrent drain's write can land between our read and our write
|
|
181
|
-
// and erase this hand-off entirely.
|
|
182
127
|
return withManifestLock(worktreeRoot, () => {
|
|
183
128
|
const now = new Date().toISOString();
|
|
184
129
|
const entries = readManifest(worktreeRoot);
|
|
@@ -289,18 +234,12 @@ async function retryStage1ForEntry(entry, ctx) {
|
|
|
289
234
|
}
|
|
290
235
|
|
|
291
236
|
/**
|
|
292
|
-
* Write the drain
|
|
293
|
-
*
|
|
294
|
-
* The drain awaits a removal per entry, so its `entries` snapshot can be
|
|
295
|
-
* minutes old by the time it writes. Writing that snapshot back wholesale
|
|
296
|
-
* erased any entry a concurrent `recordPendingCleanup` added mid-drain — the
|
|
297
|
-
* exact hand-off that reap had just decided it could not complete. Merging by
|
|
298
|
-
* `storyId` keeps it: rows this pass re-computed win, rows it successfully
|
|
299
|
-
* drained are dropped, and everything else the manifest has gained survives.
|
|
237
|
+
* Write the drain result merged by `storyId` against the manifest as it is
|
|
238
|
+
* now, so an entry recorded during the (slow) drain survives.
|
|
300
239
|
*
|
|
301
240
|
* @param {string} worktreeRoot
|
|
302
|
-
* @param {object[]} next Rows
|
|
303
|
-
* @param {Set<number|string>} drainedIds
|
|
241
|
+
* @param {object[]} next Rows still pending after this drain.
|
|
242
|
+
* @param {Set<number|string>} drainedIds
|
|
304
243
|
*/
|
|
305
244
|
function commitDrainedManifest(worktreeRoot, next, drainedIds) {
|
|
306
245
|
withManifestLock(worktreeRoot, () => {
|
|
@@ -315,11 +254,8 @@ function commitDrainedManifest(worktreeRoot, next, drainedIds) {
|
|
|
315
254
|
}
|
|
316
255
|
|
|
317
256
|
/**
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
* `attempts` incremented. Entries whose attempts reach `MAX_SWEEP_ATTEMPTS`
|
|
321
|
-
* trigger an `OPERATOR ACTION REQUIRED: persistent-lock` log line but
|
|
322
|
-
* remain in the manifest so the signal persists across subsequent sweeps.
|
|
257
|
+
* Retry each entry; persistent entries log OPERATOR ACTION REQUIRED but stay
|
|
258
|
+
* in the manifest so the signal persists.
|
|
323
259
|
*/
|
|
324
260
|
export async function drainPendingCleanup({
|
|
325
261
|
repoRoot,
|