mandrel 2.59.0 → 2.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/README.md +21 -19
- package/.agents/agents/acceptance-critic.md +24 -43
- package/.agents/agents/story-worker.md +20 -21
- package/.agents/docs/agentrc-reference.json +5 -84
- package/.agents/docs/configuration.md +48 -132
- package/.agents/docs/workflows.md +2 -2
- package/.agents/instructions.md +5 -8
- package/.agents/rules/ci-remediation.md +41 -8
- package/.agents/rules/gherkin-standards.md +4 -0
- package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
- package/.agents/schemas/agentrc.schema.json +16 -496
- package/.agents/schemas/story-deliver-terminal.schema.json +13 -3
- package/.agents/schemas/validation-evidence.schema.json +2 -1
- package/.agents/scripts/README.md +23 -13
- package/.agents/scripts/acceptance-eval.js +35 -169
- package/.agents/scripts/agents-bootstrap-github.js +27 -129
- package/.agents/scripts/apply-quality-bootstrap.js +4 -40
- package/.agents/scripts/audit-baselines.js +6 -27
- package/.agents/scripts/audit-labels-bootstrap.js +5 -29
- package/.agents/scripts/audit-to-stories.js +91 -361
- package/.agents/scripts/boot-sweep.js +19 -72
- package/.agents/scripts/bootstrap.js +74 -395
- package/.agents/scripts/ceremony-derive.js +10 -41
- package/.agents/scripts/check-arch-cycles.js +14 -64
- package/.agents/scripts/check-baselines.js +8 -48
- package/.agents/scripts/check-context-budget.js +105 -311
- package/.agents/scripts/check-cyclomatic.js +12 -44
- package/.agents/scripts/check-dead-exports.js +13 -64
- package/.agents/scripts/check-doc-links.js +38 -186
- package/.agents/scripts/check-gherkin-corpus.js +24 -127
- package/.agents/scripts/check-test-temp-hygiene.js +28 -169
- package/.agents/scripts/coverage-capture.js +34 -98
- package/.agents/scripts/deliver-light.js +25 -171
- package/.agents/scripts/deliver-recover.js +6 -42
- package/.agents/scripts/deliver-run.js +534 -0
- package/.agents/scripts/diagnose-friction.js +24 -116
- package/.agents/scripts/drain-pending-cleanup.js +1 -1
- package/.agents/scripts/evidence-gate.js +23 -85
- package/.agents/scripts/file-ci-gap.js +57 -49
- package/.agents/scripts/generate-config-docs.js +30 -170
- package/.agents/scripts/generate-lens-checklists.js +8 -52
- package/.agents/scripts/generate-skills-index.js +14 -112
- package/.agents/scripts/generate-workflows-doc.js +10 -70
- package/.agents/scripts/git-cleanup.js +2 -34
- package/.agents/scripts/lib/Graph.js +24 -81
- package/.agents/scripts/lib/ITicketingProvider.js +47 -143
- package/.agents/scripts/lib/Logger.js +14 -76
- package/.agents/scripts/lib/audit-baselines/engine.js +11 -31
- package/.agents/scripts/lib/audit-baselines/gate-surface.js +3 -17
- package/.agents/scripts/lib/audit-baselines/headroom.js +4 -20
- package/.agents/scripts/lib/audit-baselines/hotspots.js +3 -15
- package/.agents/scripts/lib/audit-baselines/kinds.js +23 -89
- package/.agents/scripts/lib/audit-baselines/outliers.js +6 -23
- package/.agents/scripts/lib/audit-baselines/read.js +3 -16
- package/.agents/scripts/lib/audit-baselines/staleness.js +7 -26
- package/.agents/scripts/lib/audit-baselines/surface-entry.js +7 -28
- package/.agents/scripts/lib/audit-baselines/trend.js +7 -20
- package/.agents/scripts/lib/audit-baselines/weights.js +9 -37
- package/.agents/scripts/lib/audit-suite/audit-rules-reader.js +3 -18
- package/.agents/scripts/lib/audit-suite/checklist-threading.js +26 -124
- package/.agents/scripts/lib/audit-suite/dispatch-checklist.js +14 -45
- package/.agents/scripts/lib/audit-suite/findings.js +12 -52
- package/.agents/scripts/lib/audit-suite/frontmatter.js +5 -29
- package/.agents/scripts/lib/audit-suite/index.js +1 -15
- package/.agents/scripts/lib/audit-suite/lens-checklist.js +10 -45
- package/.agents/scripts/lib/audit-suite/lens-diff-floor.js +11 -76
- package/.agents/scripts/lib/audit-suite/runner.js +13 -43
- package/.agents/scripts/lib/audit-suite/selector.js +49 -349
- package/.agents/scripts/lib/audit-suite/substitutions.js +12 -40
- package/.agents/scripts/lib/audit-suite/workflow-loader.js +3 -15
- package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +11 -73
- package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +8 -37
- package/.agents/scripts/lib/audit-to-stories/build-story-body.js +25 -143
- package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +14 -80
- package/.agents/scripts/lib/audit-to-stories/epic-grouping-directive.js +4 -18
- package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +7 -40
- package/.agents/scripts/lib/audit-to-stories/group-findings.js +9 -39
- package/.agents/scripts/lib/audit-to-stories/issue-corpus.js +10 -66
- package/.agents/scripts/lib/audit-to-stories/issue-index.js +6 -30
- package/.agents/scripts/lib/audit-to-stories/issues-file.js +6 -36
- package/.agents/scripts/lib/audit-to-stories/ledger-commit.js +17 -69
- package/.agents/scripts/lib/audit-to-stories/ledger-pr.js +17 -85
- package/.agents/scripts/lib/audit-to-stories/ledger-record.js +10 -48
- package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +38 -146
- package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +7 -42
- package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +10 -57
- package/.agents/scripts/lib/baseline-loader.js +12 -51
- package/.agents/scripts/lib/baseline-schema-registry.js +5 -22
- package/.agents/scripts/lib/baselines/component-matcher.js +3 -12
- package/.agents/scripts/lib/baselines/components.js +10 -61
- package/.agents/scripts/lib/baselines/coverage-updater-cli.js +7 -36
- package/.agents/scripts/lib/baselines/crap-preview-incremental.js +7 -19
- package/.agents/scripts/lib/baselines/crap-preview-scan.js +19 -45
- package/.agents/scripts/lib/baselines/crap-updater-cli.js +16 -65
- package/.agents/scripts/lib/baselines/diff-scope-cli.js +5 -33
- package/.agents/scripts/lib/baselines/duplication-scanner.js +11 -60
- package/.agents/scripts/lib/baselines/env-overrides.js +12 -67
- package/.agents/scripts/lib/baselines/envelope.js +13 -129
- package/.agents/scripts/lib/baselines/exit-codes.js +6 -49
- package/.agents/scripts/lib/baselines/git-base.js +23 -142
- package/.agents/scripts/lib/baselines/kernel.js +11 -111
- package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +9 -47
- package/.agents/scripts/lib/baselines/kinds/_crap-read.js +8 -51
- package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +7 -62
- package/.agents/scripts/lib/baselines/kinds/bundle-size.js +8 -29
- package/.agents/scripts/lib/baselines/kinds/coverage.js +3 -15
- package/.agents/scripts/lib/baselines/kinds/crap.js +94 -415
- package/.agents/scripts/lib/baselines/kinds/duplication.js +4 -30
- package/.agents/scripts/lib/baselines/kinds/kind-factory.js +7 -53
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +15 -80
- package/.agents/scripts/lib/baselines/kinds/mutation.js +12 -72
- package/.agents/scripts/lib/baselines/maintainability-baseline-io.js +4 -11
- package/.agents/scripts/lib/baselines/merge-envelopes.js +30 -146
- package/.agents/scripts/lib/baselines/path-canon.js +19 -128
- package/.agents/scripts/lib/baselines/preview-gates.js +8 -37
- package/.agents/scripts/lib/baselines/reader.js +14 -107
- package/.agents/scripts/lib/baselines/refresh-service.js +35 -252
- package/.agents/scripts/lib/baselines/scope.js +11 -135
- package/.agents/scripts/lib/baselines/writer.js +16 -149
- package/.agents/scripts/lib/bdd-runner-detect.js +18 -113
- package/.agents/scripts/lib/bdd-scenario-budget.js +9 -36
- package/.agents/scripts/lib/bdd-scenario-scanner.js +11 -73
- package/.agents/scripts/lib/bdd-step-index.js +26 -100
- package/.agents/scripts/lib/bootstrap/baseline-merge-driver.js +23 -103
- package/.agents/scripts/lib/bootstrap/branch-protection.js +2 -5
- package/.agents/scripts/lib/bootstrap/commit-push.js +12 -50
- package/.agents/scripts/lib/bootstrap/gh-preflight.js +14 -101
- package/.agents/scripts/lib/bootstrap/hitl-confirm.js +5 -30
- package/.agents/scripts/lib/bootstrap/install-ledger.js +17 -73
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +17 -121
- package/.agents/scripts/lib/bootstrap/manifest.js +15 -86
- package/.agents/scripts/lib/bootstrap/merge-methods.js +4 -33
- package/.agents/scripts/lib/bootstrap/preflight.js +12 -61
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +34 -235
- package/.agents/scripts/lib/bootstrap/prompt.js +21 -129
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +27 -141
- package/.agents/scripts/lib/bootstrap/summary.js +1 -8
- package/.agents/scripts/lib/bootstrap/workflow-audit.js +11 -84
- package/.agents/scripts/lib/branch-name-guard.js +4 -23
- package/.agents/scripts/lib/changed-files.js +39 -121
- package/.agents/scripts/lib/checks/core-bare-clean.js +4 -24
- package/.agents/scripts/lib/checks/index.js +18 -101
- package/.agents/scripts/lib/checks/loop-health.js +11 -53
- package/.agents/scripts/lib/checks/state.js +16 -91
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +10 -61
- package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +14 -83
- package/.agents/scripts/lib/child-exec.js +39 -108
- package/.agents/scripts/lib/cli/standard-args.js +9 -116
- package/.agents/scripts/lib/cli-args.js +31 -146
- package/.agents/scripts/lib/cli-usage.js +5 -27
- package/.agents/scripts/lib/cli-utils.js +2 -12
- package/.agents/scripts/lib/close-validation/commands.js +13 -76
- package/.agents/scripts/lib/close-validation/gates.js +92 -331
- package/.agents/scripts/lib/close-validation/process.js +121 -151
- package/.agents/scripts/lib/close-validation/projections/advisories.js +5 -31
- package/.agents/scripts/lib/close-validation/projections/crap.js +19 -67
- package/.agents/scripts/lib/close-validation/projections/head-sha.js +1 -17
- package/.agents/scripts/lib/close-validation/projections/inputs.js +4 -34
- package/.agents/scripts/lib/close-validation/projections/maintainability.js +11 -58
- package/.agents/scripts/lib/close-validation/runner.js +53 -110
- package/.agents/scripts/lib/command-header.js +6 -28
- package/.agents/scripts/lib/config/acceptance-eval.js +4 -30
- package/.agents/scripts/lib/config/baselines.js +3 -14
- package/.agents/scripts/lib/config/ci.js +8 -38
- package/.agents/scripts/lib/config/commands.js +1 -15
- package/.agents/scripts/lib/config/defaults.js +4 -33
- package/.agents/scripts/lib/config/delivery-routing.js +6 -34
- package/.agents/scripts/lib/config/explain.js +10 -83
- package/.agents/scripts/lib/config/gates/coverage.schema.js +0 -12
- package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +3 -31
- package/.agents/scripts/lib/config/gates/crap.schema.js +1 -34
- package/.agents/scripts/lib/config/gates/duplication.schema.js +1 -8
- package/.agents/scripts/lib/config/gates/index.js +2 -17
- package/.agents/scripts/lib/config/gates/maintainability.schema.js +1 -20
- package/.agents/scripts/lib/config/gates/mutation.schema.js +1 -7
- package/.agents/scripts/lib/config/gates/shared.js +4 -64
- package/.agents/scripts/lib/config/github.js +4 -22
- package/.agents/scripts/lib/config/limits.js +4 -57
- package/.agents/scripts/lib/config/paths.js +2 -21
- package/.agents/scripts/lib/config/qa.js +4 -38
- package/.agents/scripts/lib/config/quality.js +76 -432
- package/.agents/scripts/lib/config/runners.js +12 -56
- package/.agents/scripts/lib/config/runtime.js +13 -57
- package/.agents/scripts/lib/config/shared.js +2 -16
- package/.agents/scripts/lib/config/sync-agentrc.js +9 -50
- package/.agents/scripts/lib/config/temp-paths.js +40 -280
- package/.agents/scripts/lib/config/validate-orchestration.js +5 -17
- package/.agents/scripts/lib/config/worktree-isolation.js +9 -28
- package/.agents/scripts/lib/config-resolver.js +11 -52
- package/.agents/scripts/lib/config-schema-shared.js +1 -4
- package/.agents/scripts/lib/config-settings-schema-delivery.js +16 -291
- package/.agents/scripts/lib/config-settings-schema-quality.js +7 -219
- package/.agents/scripts/lib/config-settings-schema.js +37 -274
- package/.agents/scripts/lib/coverage-baseline.js +20 -110
- package/.agents/scripts/lib/coverage-capture-fullscope.js +18 -35
- package/.agents/scripts/lib/coverage-capture-incremental.js +15 -45
- package/.agents/scripts/lib/coverage-capture-usage.js +8 -25
- package/.agents/scripts/lib/coverage-capture.js +99 -224
- package/.agents/scripts/lib/coverage-utils.js +14 -79
- package/.agents/scripts/lib/cpu-pool.js +17 -123
- package/.agents/scripts/lib/crap-baseline-join.js +16 -88
- package/.agents/scripts/lib/crap-coordinates.js +6 -25
- package/.agents/scripts/lib/crap-engine.js +40 -153
- package/.agents/scripts/lib/crap-method-identity.js +16 -78
- package/.agents/scripts/lib/crap-utils.js +31 -155
- package/.agents/scripts/lib/cyclomatic-ceiling.js +14 -87
- package/.agents/scripts/lib/cyclomatic-scope.js +10 -50
- package/.agents/scripts/lib/dead-exports-knip.js +18 -56
- package/.agents/scripts/lib/dead-exports-mode.js +5 -24
- package/.agents/scripts/lib/degraded-mode.js +3 -26
- package/.agents/scripts/lib/dependency-parser.js +8 -40
- package/.agents/scripts/lib/dependency-version.js +13 -35
- package/.agents/scripts/lib/detect-package-manager.js +6 -36
- package/.agents/scripts/lib/doc-tiers.js +22 -124
- package/.agents/scripts/lib/duplicate-search.js +8 -72
- package/.agents/scripts/lib/env-loader.js +5 -27
- package/.agents/scripts/lib/error-redactor.js +6 -31
- package/.agents/scripts/lib/errors/index.js +2 -22
- package/.agents/scripts/lib/escomplex-ast-compat.js +22 -163
- package/.agents/scripts/lib/escomplex-kernel.js +21 -123
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +94 -419
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +20 -98
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +27 -149
- package/.agents/scripts/lib/findings/audit-ledger.js +23 -97
- package/.agents/scripts/lib/findings/classify-finding.js +14 -69
- package/.agents/scripts/lib/findings/promote-finding.js +14 -112
- package/.agents/scripts/lib/findings/provenance-field.js +11 -52
- package/.agents/scripts/lib/findings/route-finding.js +37 -255
- package/.agents/scripts/lib/findings/semantic-issue-search.js +14 -59
- package/.agents/scripts/lib/findings/severity.js +18 -104
- package/.agents/scripts/lib/format-generated-json.js +12 -44
- package/.agents/scripts/lib/full-suite-lock.js +160 -429
- package/.agents/scripts/lib/full-suite-queue.js +213 -0
- package/.agents/scripts/lib/gates/baseline-store.js +5 -9
- package/.agents/scripts/lib/gates/friction.js +1 -3
- package/.agents/scripts/lib/generated/agentrc-validator.js +2 -2
- package/.agents/scripts/lib/gh-exec.js +123 -191
- package/.agents/scripts/lib/git/cached-fetch.js +9 -52
- package/.agents/scripts/lib/git/sync-from-base.js +15 -107
- package/.agents/scripts/lib/git-branch-cleanup.js +14 -61
- package/.agents/scripts/lib/git-branch-lifecycle.js +16 -87
- package/.agents/scripts/lib/git-utils.js +37 -161
- package/.agents/scripts/lib/github/framework-repo.js +8 -71
- package/.agents/scripts/lib/github-url.js +2 -17
- package/.agents/scripts/lib/import-graph.js +11 -38
- package/.agents/scripts/lib/install-cmd-parser.js +4 -13
- package/.agents/scripts/lib/json-utils.js +3 -18
- package/.agents/scripts/lib/label-constants.js +16 -111
- package/.agents/scripts/lib/label-taxonomy.js +4 -30
- package/.agents/scripts/lib/maintainability-engine.js +12 -80
- package/.agents/scripts/lib/maintainability-unscorable.js +5 -25
- package/.agents/scripts/lib/maintainability-utils.js +16 -92
- package/.agents/scripts/lib/mandrel-catalog.js +12 -70
- package/.agents/scripts/lib/notifications/notifier.js +13 -38
- package/.agents/scripts/lib/npm-scripts.js +4 -23
- package/.agents/scripts/lib/observability/metrics-ledger.js +16 -76
- package/.agents/scripts/lib/observability/runtime-friction.js +44 -286
- package/.agents/scripts/lib/observability/signal-validator.js +5 -37
- package/.agents/scripts/lib/observability/signals-writer.js +11 -121
- package/.agents/scripts/lib/observability/source-classifier.js +22 -203
- package/.agents/scripts/lib/observability/terse-result.js +14 -47
- package/.agents/scripts/lib/onboard/init-tail.js +13 -74
- package/.agents/scripts/lib/onboard/scaffold-docs.js +11 -34
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +25 -139
- package/.agents/scripts/lib/orchestration/auto-merge-cwd.js +11 -66
- package/.agents/scripts/lib/orchestration/behind-recovery.js +10 -55
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +28 -156
- package/.agents/scripts/lib/orchestration/change-set.js +7 -36
- package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +9 -46
- package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +11 -44
- package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +5 -24
- package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +3 -12
- package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +5 -38
- package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +3 -8
- package/.agents/scripts/lib/orchestration/check-baselines/phases/refresh-ack.js +28 -136
- package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +3 -13
- package/.agents/scripts/lib/orchestration/check-state.js +92 -0
- package/.agents/scripts/lib/orchestration/ci-gap-intake.js +37 -144
- package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +121 -157
- package/.agents/scripts/lib/orchestration/code-review.js +24 -128
- package/.agents/scripts/lib/orchestration/column-sync.js +23 -111
- package/.agents/scripts/lib/orchestration/complexity-gate.js +118 -462
- package/.agents/scripts/lib/orchestration/deliver-recover.js +36 -168
- package/.agents/scripts/lib/orchestration/dependency-analyzer.js +4 -35
- package/.agents/scripts/lib/orchestration/dependency-candidates.js +9 -41
- package/.agents/scripts/lib/orchestration/diff-magnitude.js +25 -115
- package/.agents/scripts/lib/orchestration/doc-reader.js +2 -6
- package/.agents/scripts/lib/orchestration/docs-digest.js +13 -51
- package/.agents/scripts/lib/orchestration/epic-candidates.js +13 -53
- package/.agents/scripts/lib/orchestration/epic-checklist.js +9 -33
- package/.agents/scripts/lib/orchestration/epic-container.js +41 -167
- package/.agents/scripts/lib/orchestration/epic-expansion.js +10 -40
- package/.agents/scripts/lib/orchestration/epic-rollup.js +55 -207
- package/.agents/scripts/lib/orchestration/file-assumption-enum.js +2 -22
- package/.agents/scripts/lib/orchestration/file-assumptions.js +45 -253
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-detect.js +9 -46
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +7 -57
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +21 -126
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +2 -6
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +1 -4
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +1 -5
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +9 -34
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +41 -190
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/merged-tip.js +9 -45
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +1 -4
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +19 -85
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +3 -17
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +1 -5
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +16 -100
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +1 -4
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +16 -67
- package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +9 -33
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +8 -29
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +15 -68
- package/.agents/scripts/lib/orchestration/light-backstop.js +11 -49
- package/.agents/scripts/lib/orchestration/light-escalation.js +21 -89
- package/.agents/scripts/lib/orchestration/light-suitability.js +37 -307
- package/.agents/scripts/lib/orchestration/merge-block-class.js +39 -216
- package/.agents/scripts/lib/orchestration/merge-poll.js +104 -377
- package/.agents/scripts/lib/orchestration/pinned-identifier-lint.js +17 -57
- package/.agents/scripts/lib/orchestration/plan-context.js +55 -318
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +22 -79
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +5 -31
- package/.agents/scripts/lib/orchestration/plan-metrics.js +29 -108
- package/.agents/scripts/lib/orchestration/plan-navigation.js +8 -27
- package/.agents/scripts/lib/orchestration/plan-persist/acceptance-handle-repair.js +12 -49
- package/.agents/scripts/lib/orchestration/plan-persist/audit-provenance.js +18 -73
- package/.agents/scripts/lib/orchestration/plan-persist/changes-repair.js +16 -78
- package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +6 -30
- package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +14 -65
- package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +21 -76
- package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +6 -43
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +14 -68
- package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +9 -41
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +71 -289
- package/.agents/scripts/lib/orchestration/plan-persist/soft-findings.js +2 -12
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +96 -362
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +9 -39
- package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +60 -186
- package/.agents/scripts/lib/orchestration/plan-persist/wave-collision-gate.js +9 -49
- package/.agents/scripts/lib/orchestration/plan-persist/wave-serialisation.js +7 -28
- package/.agents/scripts/lib/orchestration/plan-reachability.js +13 -42
- package/.agents/scripts/lib/orchestration/plan-run-labels/reap.js +16 -91
- package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +16 -54
- package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +10 -52
- package/.agents/scripts/lib/orchestration/planning/authoring-context.js +14 -109
- package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +11 -83
- package/.agents/scripts/lib/orchestration/pr-watch.js +48 -306
- package/.agents/scripts/lib/orchestration/project-meta-cache.js +15 -80
- package/.agents/scripts/lib/orchestration/project-meta-resolver.js +10 -51
- package/.agents/scripts/lib/orchestration/reassert-status-column.js +12 -76
- package/.agents/scripts/lib/orchestration/remote-verifier.js +12 -36
- package/.agents/scripts/lib/orchestration/resolve-stories.js +33 -164
- package/.agents/scripts/lib/orchestration/retro-proposals.js +66 -361
- package/.agents/scripts/lib/orchestration/review-base-ref.js +9 -43
- package/.agents/scripts/lib/orchestration/review-depth.js +12 -91
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +10 -111
- package/.agents/scripts/lib/orchestration/review-providers/degraded-gates.js +13 -71
- package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +7 -51
- package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +8 -53
- package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -214
- package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +7 -52
- package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +4 -33
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +11 -71
- package/.agents/scripts/lib/orchestration/review-providers/scoped-lint.js +19 -131
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +6 -89
- package/.agents/scripts/lib/orchestration/review-providers/types.js +26 -56
- package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +3 -46
- package/.agents/scripts/lib/orchestration/run-epilogue.js +245 -326
- package/.agents/scripts/lib/orchestration/run-scoped-config.js +55 -159
- package/.agents/scripts/lib/orchestration/single-story-close/close-note.js +7 -34
- package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +16 -89
- package/.agents/scripts/lib/orchestration/single-story-close/gate-log.js +18 -109
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +83 -239
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +20 -82
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +103 -97
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -64
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +136 -486
- package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +30 -134
- package/.agents/scripts/lib/orchestration/single-story-close/phases/graphql-preflight.js +96 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/lock-wait-pending.js +49 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +13 -86
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +20 -95
- package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +46 -203
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pre-gate-steps.js +8 -50
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +12 -83
- package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +6 -39
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -6
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-outcome.js +4 -28
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +6 -51
- package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +6 -34
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +23 -121
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +180 -273
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +15 -69
- package/.agents/scripts/lib/orchestration/story-body-gate.js +4 -23
- package/.agents/scripts/lib/orchestration/story-close/baseline-upward-writeback.js +50 -179
- package/.agents/scripts/lib/orchestration/story-close/context-budget-writeback.js +11 -41
- package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +23 -311
- package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +22 -147
- package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +16 -67
- package/.agents/scripts/lib/orchestration/story-deliver-terminal-schema.js +12 -68
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +42 -200
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +167 -252
- package/.agents/scripts/lib/orchestration/story-init-envelope.js +52 -0
- package/.agents/scripts/lib/orchestration/story-init-remote.js +2 -6
- package/.agents/scripts/lib/orchestration/story-reachability.js +3 -23
- package/.agents/scripts/lib/orchestration/task-body-validator.js +12 -135
- package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -131
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +15 -149
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +5 -33
- package/.agents/scripts/lib/orchestration/ticket-validator.js +63 -344
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +51 -244
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +39 -261
- package/.agents/scripts/lib/orchestration/ticketing/state.js +14 -68
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +46 -263
- package/.agents/scripts/lib/orchestration/ticketing.js +2 -26
- package/.agents/scripts/lib/orchestration/verify-credit.js +18 -79
- package/.agents/scripts/lib/orchestration/worktree-dirty.js +5 -30
- package/.agents/scripts/lib/path-security.js +3 -6
- package/.agents/scripts/lib/plan-phase-cleanup.js +9 -49
- package/.agents/scripts/lib/preflight-runner.js +13 -69
- package/.agents/scripts/lib/process-group.js +143 -0
- package/.agents/scripts/lib/project-root.js +2 -8
- package/.agents/scripts/lib/provider-factory.js +2 -25
- package/.agents/scripts/lib/qa/console-allowlist.js +10 -59
- package/.agents/scripts/lib/qa/qa-session.js +15 -69
- package/.agents/scripts/lib/qa/redact-evidence.js +18 -129
- package/.agents/scripts/lib/qa/resolve-qa-contract.js +26 -135
- package/.agents/scripts/lib/qa/resolve-selection.js +16 -84
- package/.agents/scripts/lib/reserved-test-ids.js +9 -47
- package/.agents/scripts/lib/runtime-deps/dep-resolution.js +13 -53
- package/.agents/scripts/lib/runtime-deps/ensure-installed.js +10 -44
- package/.agents/scripts/lib/runtime-deps/manifest.js +10 -30
- package/.agents/scripts/lib/runtime-deps/parser-major.js +15 -51
- package/.agents/scripts/lib/runtime-deps/preflight.js +4 -22
- package/.agents/scripts/lib/runtime-deps/scan-imports.js +11 -55
- package/.agents/scripts/lib/signals/detectors/common.js +12 -38
- package/.agents/scripts/lib/signals/index.js +2 -19
- package/.agents/scripts/lib/signals/schema.js +14 -109
- package/.agents/scripts/lib/signals/write.js +2 -11
- package/.agents/scripts/lib/single-story/confirm-merge.js +31 -72
- package/.agents/scripts/lib/single-story/story-merged-notify.js +8 -49
- package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +4 -26
- package/.agents/scripts/lib/single-story-sweep/protection.js +13 -100
- package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +60 -258
- package/.agents/scripts/lib/single-story-sweep.js +14 -97
- package/.agents/scripts/lib/skills/parse-skill.js +13 -59
- package/.agents/scripts/lib/skills/skills-index.js +8 -29
- package/.agents/scripts/lib/skills/walk-skill-files.js +17 -78
- package/.agents/scripts/lib/source-extensions.js +11 -42
- package/.agents/scripts/lib/source-text/strip-js-comments.js +8 -41
- package/.agents/scripts/lib/stdio-flush.js +9 -36
- package/.agents/scripts/lib/story-adjacency.js +8 -40
- package/.agents/scripts/lib/story-body/body-format-lints.js +51 -66
- package/.agents/scripts/lib/story-body/footer-block.js +11 -44
- package/.agents/scripts/lib/story-body/story-body.js +123 -344
- package/.agents/scripts/lib/temp-retention.js +42 -143
- package/.agents/scripts/lib/templates/decomposer-prompts.js +18 -80
- package/.agents/scripts/lib/test-env.js +12 -65
- package/.agents/scripts/lib/test-run-credit.js +10 -65
- package/.agents/scripts/lib/test-runner-contract.js +19 -74
- package/.agents/scripts/lib/test-temp.js +38 -184
- package/.agents/scripts/lib/test-tiers.js +12 -96
- package/.agents/scripts/lib/ticket-body-sections.js +21 -96
- package/.agents/scripts/lib/transpile.js +15 -74
- package/.agents/scripts/lib/util/concurrent-map.js +6 -25
- package/.agents/scripts/lib/util/parse-id-list.js +8 -34
- package/.agents/scripts/lib/util/poll-loop.js +8 -28
- package/.agents/scripts/lib/util/with-timeout.js +2 -11
- package/.agents/scripts/lib/validation-evidence.js +21 -96
- package/.agents/scripts/lib/wave-runner/footprint.js +17 -70
- package/.agents/scripts/lib/wave-runner/live-probe.js +67 -209
- package/.agents/scripts/lib/wave-runner/ready-set.js +72 -301
- package/.agents/scripts/lib/workers/crap-worker.js +11 -64
- package/.agents/scripts/lib/workers/maintainability-report-worker.js +8 -45
- package/.agents/scripts/lib/workers/maintainability-worker.js +5 -21
- package/.agents/scripts/lib/workers/serve-worker-messages.js +2 -18
- package/.agents/scripts/lib/workflow-closure.js +22 -105
- package/.agents/scripts/lib/workspace-provisioner.js +16 -54
- package/.agents/scripts/lib/worktree/git-hooks.js +15 -60
- package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +20 -60
- package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +10 -62
- package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +22 -86
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +24 -126
- package/.agents/scripts/lib/worktree/lifecycle-manager.js +2 -20
- package/.agents/scripts/lib/worktree/node-modules-strategy.js +46 -180
- package/.agents/scripts/lib/worktree-manager.js +15 -40
- package/.agents/scripts/lint-issue-body.js +12 -68
- package/.agents/scripts/mandrel-update-preflight.js +10 -70
- package/.agents/scripts/merge-baseline.js +30 -105
- package/.agents/scripts/nav-registry-diff.js +22 -108
- package/.agents/scripts/notify.js +12 -69
- package/.agents/scripts/plan-context.js +97 -92
- package/.agents/scripts/plan-critics.js +12 -66
- package/.agents/scripts/plan-persist.js +71 -137
- package/.agents/scripts/plan-run-epilogue.js +20 -43
- package/.agents/scripts/pr-watch-with-update.js +79 -263
- package/.agents/scripts/providers/github/auth.js +3 -8
- package/.agents/scripts/providers/github/blocked-by-add.js +14 -61
- package/.agents/scripts/providers/github/board-add.js +5 -21
- package/.agents/scripts/providers/github/branch-protection.js +11 -43
- package/.agents/scripts/providers/github/cache.js +2 -14
- package/.agents/scripts/providers/github/comments.js +7 -40
- package/.agents/scripts/providers/github/compose.js +3 -19
- package/.agents/scripts/providers/github/errors.js +22 -125
- package/.agents/scripts/providers/github/issues.js +31 -123
- package/.agents/scripts/providers/github/labels.js +24 -124
- package/.agents/scripts/providers/github/mappers.js +5 -27
- package/.agents/scripts/providers/github/merge-methods.js +3 -22
- package/.agents/scripts/providers/github/project-board.js +2 -17
- package/.agents/scripts/providers/github/projects-v2-graphql.js +3 -6
- package/.agents/scripts/providers/github/request-helpers.js +5 -32
- package/.agents/scripts/providers/github/search-budget.js +9 -39
- package/.agents/scripts/providers/github/search-query.js +5 -26
- package/.agents/scripts/providers/github/sub-issue-add.js +15 -65
- package/.agents/scripts/providers/github/sub-issues.js +7 -36
- package/.agents/scripts/providers/github/tickets.js +32 -134
- package/.agents/scripts/providers/github.js +18 -59
- package/.agents/scripts/prune-plan-run-labels.js +12 -46
- package/.agents/scripts/quality-preview.js +35 -220
- package/.agents/scripts/resolve-doc-tiers.js +3 -26
- package/.agents/scripts/resolve-stories.js +16 -67
- package/.agents/scripts/resync-status-column.js +6 -25
- package/.agents/scripts/run-tests.js +29 -104
- package/.agents/scripts/single-story-close.js +23 -135
- package/.agents/scripts/single-story-confirm-merge.js +32 -139
- package/.agents/scripts/single-story-init.js +47 -259
- package/.agents/scripts/stories-wave-tick.js +179 -415
- package/.agents/scripts/sync-agentrc.js +3 -21
- package/.agents/scripts/sync-claude-agents.js +9 -55
- package/.agents/scripts/sync-claude-commands.js +20 -110
- package/.agents/scripts/test-wrapper.js +6 -43
- package/.agents/scripts/update-coverage-baseline.js +5 -22
- package/.agents/scripts/update-crap-baseline.js +7 -30
- package/.agents/scripts/update-duplication-baseline.js +16 -92
- package/.agents/scripts/update-maintainability-baseline.js +8 -62
- package/.agents/scripts/update-ticket-state.js +1 -7
- package/.agents/scripts/validate-skills.js +6 -26
- package/.agents/skills/core/gates-and-baselines/reference.md +0 -1
- package/.agents/skills/skills.index.json +2 -2
- package/.agents/skills/stack/qa/playwright/SKILL.md +26 -0
- package/.agents/templates/agent-protocol.md +2 -2
- package/.agents/templates/docs/audit-sweep-runbook.md +3 -4
- package/.agents/workflows/audit-accessibility.md +4 -7
- package/.agents/workflows/audit-adrs.md +3 -6
- package/.agents/workflows/audit-architecture.md +3 -11
- package/.agents/workflows/audit-baselines.md +6 -9
- package/.agents/workflows/audit-clean-code.md +8 -12
- package/.agents/workflows/audit-data-model.md +3 -7
- package/.agents/workflows/audit-dependencies.md +4 -7
- package/.agents/workflows/audit-devops.md +4 -8
- package/.agents/workflows/audit-documentation.md +1 -4
- package/.agents/workflows/audit-mobile.md +4 -7
- package/.agents/workflows/audit-navigability.md +3 -6
- package/.agents/workflows/audit-performance.md +2 -4
- package/.agents/workflows/audit-privacy.md +4 -7
- package/.agents/workflows/audit-quality.md +4 -7
- package/.agents/workflows/audit-security.md +4 -7
- package/.agents/workflows/audit-seo.md +4 -7
- package/.agents/workflows/audit-sre.md +4 -7
- package/.agents/workflows/audit-to-stories.md +17 -30
- package/.agents/workflows/audit-ux-ui.md +4 -7
- package/.agents/workflows/helpers/acceptance-self-eval.md +84 -157
- package/.agents/workflows/helpers/audit-lens-core.md +1 -1
- package/.agents/workflows/helpers/code-quality-guardrails.md +12 -15
- package/.agents/workflows/helpers/code-review.md +4 -2
- package/.agents/workflows/helpers/deliver-digest.md +37 -28
- package/.agents/workflows/helpers/deliver-light.md +92 -101
- package/.agents/workflows/helpers/deliver-reference.md +162 -220
- package/.agents/workflows/helpers/deliver-story-reference.md +197 -607
- package/.agents/workflows/helpers/deliver-story.md +17 -18
- package/.agents/workflows/helpers/plan-reference.md +125 -167
- package/.agents/workflows/helpers/qa-core.md +12 -0
- package/.agents/workflows/mandrel-deliver.md +47 -31
- package/.agents/workflows/mandrel-plan.md +22 -21
- package/.agents/workflows/mandrel-update.md +36 -21
- package/.agents/workflows/memory-consolidate.md +1 -1
- package/.agents/workflows/qa-assist.md +27 -71
- package/.agents/workflows/qa-explore.md +19 -59
- package/.agents/workflows/qa-run.md +11 -33
- package/README.md +1 -1
- package/bin/mandrel.js +5 -46
- package/bin/postinstall.js +18 -107
- package/docs/CHANGELOG.md +60 -0
- package/lib/cli/doctor.js +11 -71
- package/lib/cli/init.js +26 -165
- package/lib/cli/migrate.js +5 -64
- package/lib/cli/registry.js +84 -467
- package/lib/cli/sync-agents.js +4 -64
- package/lib/cli/sync-commands.js +11 -64
- package/lib/cli/sync.js +34 -213
- package/lib/cli/uninstall.js +40 -219
- package/lib/cli/update.js +326 -523
- package/lib/cli/version-check.js +8 -72
- package/lib/cli/version-helpers.js +14 -87
- package/lib/migrations/helpers/retire-agentrc-key.js +11 -52
- package/lib/migrations/index.js +17 -92
- package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +2 -15
- package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +1 -13
- package/lib/migrations/steps/2.11.0-retire-max-seed-words.js +2 -15
- package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +9 -38
- package/lib/migrations/steps/2.20.0-retire-codebase-snapshot.js +1 -13
- package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +2 -27
- package/lib/migrations/steps/2.57.0-retire-delivery-limit-knobs.js +2 -23
- package/lib/migrations/steps/2.57.0-retire-planning-limit-knobs.js +2 -27
- package/lib/migrations/steps/2.60.0-retire-audit-results-autofile.js +21 -0
- package/lib/migrations/steps/strip-removed-agentrc-keys.js +333 -0
- package/package.json +17 -14
- package/.agents/docs/SDLC.md +0 -590
- package/.agents/docs/quality-gates.md +0 -1179
- package/.agents/rules/known-tooling-behavior.md +0 -150
- package/.agents/rules/orchestration-error-handling.md +0 -61
- package/.agents/rules/test-seams.md +0 -59
- package/.agents/schemas/baselines/lighthouse.schema.json +0 -59
- package/.agents/schemas/baselines/lint.schema.json +0 -47
- package/.agents/schemas/model-attribution.schema.json +0 -53
- package/.agents/scripts/check-action-pinning.js +0 -260
- package/.agents/scripts/check-audit-attribution.js +0 -302
- package/.agents/scripts/check-baseline-drift.js +0 -211
- package/.agents/scripts/check-baseline-scope.js +0 -362
- package/.agents/scripts/check-generated-validator.js +0 -202
- package/.agents/scripts/check-knip-entries.js +0 -159
- package/.agents/scripts/check-lifecycle-lint.js +0 -294
- package/.agents/scripts/check-pinned-override-notes.js +0 -102
- package/.agents/scripts/check-schema-references.js +0 -366
- package/.agents/scripts/check-test-portability.js +0 -512
- package/.agents/scripts/check-workflow-citations.js +0 -332
- package/.agents/scripts/check-workflow-cli-lint.js +0 -299
- package/.agents/scripts/check-workflow-timeouts.js +0 -291
- package/.agents/scripts/install-matrix-assert.js +0 -326
- package/.agents/scripts/lib/audit-advisories.js +0 -195
- package/.agents/scripts/lib/audit-attribution.js +0 -134
- package/.agents/scripts/lib/baselines/drift-detector.js +0 -351
- package/.agents/scripts/lib/baselines/kinds/lighthouse.js +0 -87
- package/.agents/scripts/lib/baselines/kinds/lint.js +0 -184
- package/.agents/scripts/lib/baselines/orphan-pruner.js +0 -233
- package/.agents/scripts/lib/baselines/scope-assert.js +0 -223
- package/.agents/scripts/lib/baselines/scope-inventory.js +0 -314
- package/.agents/scripts/lib/c8-cli-path.js +0 -21
- package/.agents/scripts/lib/config/gates/lighthouse.schema.js +0 -51
- package/.agents/scripts/lib/config/gates/lint.schema.js +0 -18
- package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +0 -70
- package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +0 -284
- package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +0 -80
- package/.agents/scripts/lib/dynamic-workflow/degraded-coverage.js +0 -81
- package/.agents/scripts/lib/dynamic-workflow/documentation-report-contract.js +0 -87
- package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +0 -74
- package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +0 -90
- package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +0 -43
- package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +0 -83
- package/.agents/scripts/lib/fs-walk.js +0 -52
- package/.agents/scripts/lib/knip-config-resolver.js +0 -181
- package/.agents/scripts/lib/knip-entry-sync.js +0 -452
- package/.agents/scripts/lib/orchestration/model-attribution.js +0 -418
- package/.agents/scripts/lib/orchestration/story-plan-state.js +0 -33
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +0 -67
- package/.agents/scripts/lib/pinned-override-notes.js +0 -88
- package/.agents/scripts/lib/pinned-override-resolve.js +0 -212
- package/.agents/scripts/lib/test-isolate/cli-options.js +0 -93
- package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +0 -52
- package/.agents/scripts/lib/test-isolate/list-files.js +0 -90
- package/.agents/scripts/lib/test-isolate/parse-tap.js +0 -75
- package/.agents/scripts/lib/test-isolate/progress-log.js +0 -45
- package/.agents/scripts/lib/test-isolate/render-report.js +0 -97
- package/.agents/scripts/lib/test-isolate/run-isolate.js +0 -87
- package/.agents/scripts/lib/test-isolate/runner.js +0 -483
- package/.agents/scripts/lib/test-profile/parse-tap.js +0 -136
- package/.agents/scripts/lib/test-profile/render-report.js +0 -45
- package/.agents/scripts/lint-label-vocabulary.js +0 -214
- package/.agents/scripts/post-structured-comment.js +0 -127
- package/.agents/scripts/provision-git-hooks.js +0 -85
- package/.agents/scripts/prune-baseline-orphans.js +0 -181
- package/.agents/scripts/run-coverage.js +0 -197
- package/.agents/scripts/run-lint.js +0 -133
- package/.agents/scripts/run-test-profile.js +0 -129
- package/.agents/scripts/run-verify.js +0 -118
- package/.agents/scripts/test-isolate.js +0 -55
- package/.agents/scripts/update-dead-exports-baseline.js +0 -321
|
@@ -2,129 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* stories-wave-tick.js — continuous ready-set planner for the standalone
|
|
5
|
-
* `/mandrel-deliver` story-list path
|
|
5
|
+
* `/mandrel-deliver` story-list path: a thin adapter over
|
|
6
|
+
* `lib/wave-runner/ready-set.js#planReadySet` (no wave barrier; a Story is
|
|
7
|
+
* dispatchable the instant its own dependencies are done).
|
|
6
8
|
*
|
|
7
|
-
*
|
|
8
|
-
* (`
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* `lib/wave-runner/ready-set.js` applies everywhere. There is no wave barrier: this no longer batches
|
|
13
|
-
* Stories into fully-draining waves; it selects continuously.
|
|
9
|
+
* Probe mode (`--stories --probe-live`) derives graph, done set and in-flight
|
|
10
|
+
* count from live state; flag mode (`--dag` + `--done`/`--in-flight`) takes
|
|
11
|
+
* them from the caller. They are mutually exclusive: a supplied `--done` under
|
|
12
|
+
* probe mode would reintroduce hand-maintained state. `--dispatched` is
|
|
13
|
+
* additive and live-state-filtered, never authoritative.
|
|
14
14
|
*
|
|
15
|
-
* The
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* this file only gathers input, resolves the cap, and renders the envelope.
|
|
15
|
+
* The cap comes from `delivery.deliverRunner.concurrencyCap`; `--concurrency`
|
|
16
|
+
* overrides it, except that worktree isolation off clamps it to 1 (a shared
|
|
17
|
+
* checkout makes concurrent workers contend for HEAD). `capPrecedence` names
|
|
18
|
+
* the winning source so no override is silent.
|
|
20
19
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* count are resolved from **live state** via `lib/wave-runner/live-probe.js`.
|
|
26
|
-
* The caller supplies ids, so there is no accounting to hand-maintain
|
|
27
|
-
* across beats — the seed-the-first-beat's-`--done` footgun the workflow
|
|
28
|
-
* used to warn about is structurally impossible rather than merely
|
|
29
|
-
* documented. `--dispatched` is the one fact live state cannot yet report
|
|
30
|
-
* ("I spawned this id; its label has not appeared"); it is additive and
|
|
31
|
-
* live-state-filtered, never authoritative (Story #4601).
|
|
32
|
-
* - **Flag mode** (`--dag`/`--dag-file` + `--done`/`--in-flight`) keeps the
|
|
33
|
-
* caller-supplied contract byte-compatible for tests and hand-driven
|
|
34
|
-
* runs. The two are mutually exclusive: honouring a supplied `--done`
|
|
35
|
-
* under `--probe-live` would silently reintroduce exactly the
|
|
36
|
-
* hand-maintained state probe mode retires.
|
|
37
|
-
*
|
|
38
|
-
* Usage:
|
|
39
|
-
* node .agents/scripts/stories-wave-tick.js --stories 101,102 --probe-live
|
|
40
|
-
* node .agents/scripts/stories-wave-tick.js --dag '<json>'
|
|
41
|
-
* node .agents/scripts/stories-wave-tick.js --dag-file <path>
|
|
42
|
-
* node .agents/scripts/stories-wave-tick.js --dag '<json>' --concurrency 5
|
|
43
|
-
* node .agents/scripts/stories-wave-tick.js --dag '<json>' --done 101,103 --in-flight 1
|
|
44
|
-
*
|
|
45
|
-
* DAG input format (JSON):
|
|
46
|
-
* Array of { id: number, dependsOn: number[] } objects where id is a Story
|
|
47
|
-
* ticket number and dependsOn lists Story IDs that must complete first.
|
|
48
|
-
*
|
|
49
|
-
* Output: one JSON object on stdout with shape:
|
|
50
|
-
* {
|
|
51
|
-
* kind: 'stories-ready-set',
|
|
52
|
-
* ready: number[], // Story IDs safe to dispatch on this beat
|
|
53
|
-
* totalStories: number,
|
|
54
|
-
* concurrencyCap: number,
|
|
55
|
-
* inFlight: number,
|
|
56
|
-
* cycleError: string | null,
|
|
57
|
-
* wedged: { reason, stories: [{ id, unmetBlockers }] } | null,
|
|
58
|
-
* inFlightReservation: { available, withheld: [{ id, blockedBy, reason, source, paths }], note },
|
|
59
|
-
* footprintGuard: { mode, withheld: [{ id, blockedBy, scope, source, paths }], advisory, note }
|
|
60
|
-
* }
|
|
61
|
-
*
|
|
62
|
-
* `inFlightReservation` reports the cross-beat half of the co-dispatch guard
|
|
63
|
-
* (Story #4950 made it reserve; Story #5313 narrowed the footprint back to
|
|
64
|
-
* the declared `changes[]`). Under
|
|
65
|
-
* `--probe-live` the in-flight Stories' own records are handed to the kernel,
|
|
66
|
-
* so a candidate sharing a CONCRETE path with a Story dispatched on an EARLIER
|
|
67
|
-
* beat is withheld and named here with its blocker and a `reason`
|
|
68
|
-
* (`in-flight-earlier-beat` or `foreign-lease`). A glob / UNKNOWN footprint
|
|
69
|
-
* reserves nothing across beats — it would withhold the whole run for one
|
|
70
|
-
* blocker's entire implementation window — while still serializing its own
|
|
71
|
-
* beat (Story #4960). Flag mode carries a count and no records, so it reports
|
|
72
|
-
* `available: false` rather than an empty — and therefore indistinguishable —
|
|
73
|
-
* result.
|
|
74
|
-
*
|
|
75
|
-
* `footprintGuard` reports the **beat-local** half, which until Story #5044 was
|
|
76
|
-
* reported nowhere: a same-beat overlap skip was a bare `continue` inside
|
|
77
|
-
* `planReadySet`, so the Story vanished from `ready[]` with no field anywhere
|
|
78
|
-
* naming the collision. Every entry in either report now also carries the
|
|
79
|
-
* colliding `paths` and a `source` tag — `declared-overlap`, the one class
|
|
80
|
-
* left since Story #5313: both Stories' `changes[]` named the path (intended
|
|
81
|
-
* serialization: two Stories really do rewrite the same generated baseline)
|
|
82
|
-
* or one declared a glob. `mode` names the `footprintGuard` config value;
|
|
83
|
-
* under `advisory` the collisions are detected and listed in `advisory[]` but
|
|
84
|
-
* dispatch follows the declared `depends_on` edges alone.
|
|
85
|
-
*
|
|
86
|
-
* Probe mode adds fields the caller can no longer compute for itself:
|
|
87
|
-
* `done: number[]` (the resolved done set, in-set ∪ satisfied foreign
|
|
88
|
-
* blockers), `epilogueDue: boolean` (true exactly when every listed Story
|
|
89
|
-
* is done — the run-end signal for `plan-run-epilogue.js`), and `blocked:
|
|
90
|
-
* number[]` + `blockedReason: string|null` (Story #4601 — the `agent::blocked`
|
|
91
|
-
* HITL pause, which ends the loop rather than being polled).
|
|
92
|
-
*
|
|
93
|
-
* The standalone loop calls this once per beat and dispatches the returned
|
|
94
|
-
* `ready` set (already capped at `concurrencyCap − inFlight` by the core).
|
|
95
|
-
* Under `--probe-live` each beat re-reads reality, so the run is complete
|
|
96
|
-
* when `epilogueDue` is true; under flag mode the caller re-supplies `--done`
|
|
97
|
-
* and `--in-flight` itself, and the run is complete when every Story is in
|
|
98
|
-
* `--done` and `ready` is empty.
|
|
99
|
-
*
|
|
100
|
-
* The per-beat concurrency cap is resolved from the same config seam
|
|
101
|
-
* `/mandrel-deliver` uses — `resolveConfig` + `getRunners` reading
|
|
102
|
-
* `delivery.deliverRunner.concurrencyCap` (default 3) — so a
|
|
103
|
-
* `.agentrc.local.json` override is honored. A `--concurrency <n>` CLI flag
|
|
104
|
-
* overrides the config-resolved value for that run only, and the envelope's
|
|
105
|
-
* `capPrecedence` names which source won so the override is never silent
|
|
106
|
-
* (Story #4875). This shares one
|
|
107
|
-
* deterministic config source (`delivery.deliverRunner.concurrencyCap`) and
|
|
108
|
-
* one scheduling kernel with every `/mandrel-deliver` multi-Story invocation.
|
|
109
|
-
*
|
|
110
|
-
* Exit codes: 0 ok · 1 input error · 2 dependency cycle (`cycleError`) ·
|
|
111
|
-
* 3 wedged (`wedged`) — ready is empty, nothing is in flight, and undone
|
|
112
|
-
* Stories are waiting on blockers that are not done · 4 blocked (`blocked`) —
|
|
113
|
-
* a Story carries `agent::blocked`. A cycle is a self-referential DAG the
|
|
114
|
-
* operator must fix; a wedge is a well-formed DAG whose gates cannot be
|
|
115
|
-
* satisfied from the supplied `--done` set (usually a blocker outside the
|
|
116
|
-
* delivered set that has not landed); a block is the protocol's HITL pause,
|
|
117
|
-
* where a human owes a decision no beat can supply. All three are distinct
|
|
118
|
-
* from the ordinary `ready: []` that means "waiting on in-flight work" — and
|
|
119
|
-
* that distinction is the point: each of them previously presented AS that
|
|
120
|
-
* ordinary empty set, so the loop polled a state that could never improve.
|
|
20
|
+
* Exit codes (see HELP): 0 ok, 1 input error, 2 cycle, 3 wedged, 4 blocked.
|
|
21
|
+
* Each non-zero case is distinct from the ordinary `ready: []` that means
|
|
22
|
+
* "waiting on in-flight work", so the loop never polls a state that cannot
|
|
23
|
+
* improve.
|
|
121
24
|
*/
|
|
122
25
|
|
|
123
26
|
import { readFileSync } from 'node:fs';
|
|
124
27
|
import { parseArgs } from 'node:util';
|
|
125
28
|
|
|
126
29
|
import { runAsCli } from './lib/cli-utils.js';
|
|
127
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
getPaths,
|
|
32
|
+
getRunners,
|
|
33
|
+
getWorktreeIsolation,
|
|
34
|
+
resolveConfig,
|
|
35
|
+
resolveWorktreeEnabled,
|
|
36
|
+
} from './lib/config-resolver.js';
|
|
128
37
|
import { detectCycle } from './lib/Graph.js';
|
|
129
38
|
import { Logger } from './lib/Logger.js';
|
|
130
39
|
import { AGENT_LABELS } from './lib/label-constants.js';
|
|
@@ -143,20 +52,12 @@ import {
|
|
|
143
52
|
WITHHOLD_SCOPES,
|
|
144
53
|
} from './lib/wave-runner/ready-set.js';
|
|
145
54
|
|
|
146
|
-
/**
|
|
147
|
-
* Exit code for a wedged run — deliberately distinct from the cycle exit (2)
|
|
148
|
-
* so a caller can tell "your DAG is self-referential" from "your DAG is fine
|
|
149
|
-
* but its gates can never be satisfied from this `--done` set".
|
|
150
|
-
*/
|
|
55
|
+
/** Wedged run: a well-formed DAG whose gates cannot be satisfied from `--done`. */
|
|
151
56
|
export const WEDGED_EXIT_CODE = 3;
|
|
152
57
|
|
|
153
58
|
/**
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
* different: a cycle is a malformed DAG and a wedge is an unlanded blocker,
|
|
157
|
-
* whereas this is the protocol's one runtime HITL pause. A human must decide
|
|
158
|
-
* something before any beat can help. Probe-mode only: flag-mode nodes carry
|
|
159
|
-
* no labels, so nothing there can classify blocked.
|
|
59
|
+
* A Story carries `agent::blocked` — the HITL pause no beat can clear.
|
|
60
|
+
* Probe mode only: flag-mode nodes carry no labels.
|
|
160
61
|
*/
|
|
161
62
|
export const BLOCKED_EXIT_CODE = 4;
|
|
162
63
|
|
|
@@ -206,6 +107,13 @@ Options:
|
|
|
206
107
|
WINS over the configured value, and the envelope's
|
|
207
108
|
capPrecedence records that it did — including when the
|
|
208
109
|
request exceeds the configured cap.
|
|
110
|
+
ONE EXCEPTION: when worktree isolation resolves off
|
|
111
|
+
(CLAUDE_CODE_REMOTE=true, AP_WORKTREE_ENABLED=false, or
|
|
112
|
+
delivery.worktreeIsolation.enabled: false), the cap is
|
|
113
|
+
clamped to 1 and the clamp outranks this flag — every
|
|
114
|
+
Story would otherwise run in the same checkout and two
|
|
115
|
+
workers would contend for HEAD. capPrecedence reports
|
|
116
|
+
source "worktree-clamp" with the requested value.
|
|
209
117
|
--done <csv> Comma-separated Story IDs already completed this run.
|
|
210
118
|
Their dependents become eligible; they are never
|
|
211
119
|
re-dispatched. Defaults to empty.
|
|
@@ -287,10 +195,6 @@ Exit codes:
|
|
|
287
195
|
`;
|
|
288
196
|
|
|
289
197
|
/**
|
|
290
|
-
* Build the exit-1 input-error result. Shared by both modes so a malformed
|
|
291
|
-
* `--concurrency` reports identically whether it arrived alongside `--dag` or
|
|
292
|
-
* `--probe-live`.
|
|
293
|
-
*
|
|
294
198
|
* @param {string} message
|
|
295
199
|
* @param {number|null} [concurrencyCap]
|
|
296
200
|
* @param {number} [inFlightValue]
|
|
@@ -315,48 +219,18 @@ function inputErrorResult(message, concurrencyCap = null, inFlightValue = 0) {
|
|
|
315
219
|
};
|
|
316
220
|
}
|
|
317
221
|
|
|
318
|
-
/**
|
|
319
|
-
* Why a reservation withheld a Story. Machine-readable companion to the
|
|
320
|
-
* operator-facing `note`, so a consumer never has to parse prose to tell an
|
|
321
|
-
* earlier-beat blocker from a foreign-lease one (Story #4960).
|
|
322
|
-
*/
|
|
222
|
+
/** Machine-readable reason a reservation withheld a Story. */
|
|
323
223
|
const RESERVATION_REASONS = Object.freeze({
|
|
324
224
|
EARLIER_BEAT: 'in-flight-earlier-beat',
|
|
325
225
|
FOREIGN_LEASE: 'foreign-lease',
|
|
326
226
|
});
|
|
327
227
|
|
|
328
228
|
/**
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
* mode rather than of the run:
|
|
335
|
-
*
|
|
336
|
-
* - **Probe mode** hands over the records `live-probe.js` already fetched,
|
|
337
|
-
* so `inFlightRecords` is an array (possibly empty) and reservation is
|
|
338
|
-
* `available: true`.
|
|
339
|
-
* - **Flag mode** (`--dag` + `--in-flight <n>`) supplies a graph and a
|
|
340
|
-
* count; no node carries a label, so nothing there can even classify as
|
|
341
|
-
* in-flight. There is no footprint to reserve against, and selection is
|
|
342
|
-
* unchanged from before #4950. Saying so explicitly is the point: a
|
|
343
|
-
* silently-absent guard reads exactly like a guard that found nothing.
|
|
344
|
-
*
|
|
345
|
-
* A reservation is held either by a Story **this run** dispatched on an
|
|
346
|
-
* earlier beat or by one **another operator's lease** holds — `live-probe.js`
|
|
347
|
-
* folds both into the in-flight set, and they reserve identically but read
|
|
348
|
-
* very differently to an operator. Reporting a foreign-held peer as "still in
|
|
349
|
-
* flight from an earlier beat" is simply false: this run never dispatched it
|
|
350
|
-
* and no later beat of this run will clear it. `foreignHeldIds` splits the two
|
|
351
|
-
* so each carries its own reason (Story #4960).
|
|
352
|
-
*
|
|
353
|
-
* Each entry also carries the **colliding paths** and an
|
|
354
|
-
* `OVERLAP_SOURCES` tag (Story #5044). A withhold that names no path is one an
|
|
355
|
-
* operator cannot act on, and `declared-overlap` vs `scraped-overlap` is the
|
|
356
|
-
* difference between "these two Stories both declared this generated baseline,
|
|
357
|
-
* serializing them is the point" and "one Story's body happened to mention a
|
|
358
|
-
* path the other declared" — the same unfilled slot for two very different
|
|
359
|
-
* reasons.
|
|
229
|
+
* Report the cross-beat footprint reservation. It needs the in-flight
|
|
230
|
+
* Stories' records, which only probe mode has; flag mode reports
|
|
231
|
+
* `available: false` explicitly, since an absent guard reads like one that
|
|
232
|
+
* found nothing. Foreign-lease holders get their own reason because no beat
|
|
233
|
+
* of this run clears them.
|
|
360
234
|
*
|
|
361
235
|
* @param {object[]|null|undefined} inFlightRecords
|
|
362
236
|
* @param {Array<{id: number, blockedBy: number, source?: string, paths?: string[]}>} withheld
|
|
@@ -401,21 +275,9 @@ export function buildReservationReport(
|
|
|
401
275
|
}
|
|
402
276
|
|
|
403
277
|
/**
|
|
404
|
-
* Report the
|
|
405
|
-
*
|
|
406
|
-
*
|
|
407
|
-
* Until now a same-beat overlap skip was an anonymous `continue` inside
|
|
408
|
-
* `planReadySet`: the Story simply did not appear in `ready[]` and no field
|
|
409
|
-
* anywhere said why. That is the same unexplained-unfilled-slot failure the
|
|
410
|
-
* cross-beat `inFlightReservation` report was built to remove, left standing on
|
|
411
|
-
* the other half of the guard — and it is how a plan whose siblings collided
|
|
412
|
-
* only on machine-generated footer text ran fully serial without leaving a
|
|
413
|
-
* trace to notice.
|
|
414
|
-
*
|
|
415
|
-
* `withheld` and `advisory` are disjoint by construction: under `enforce` every
|
|
416
|
-
* detection withheld, under `advisory` none did. Reporting them as separate
|
|
417
|
-
* lists rather than one flagged list means a consumer counting withheld
|
|
418
|
-
* dispatches never has to inspect a boolean to get the count right.
|
|
278
|
+
* Report the beat-local half of the footprint guard and its mode. `withheld`
|
|
279
|
+
* and `advisory` are disjoint: under `enforce` every detection withheld,
|
|
280
|
+
* under `advisory` none did.
|
|
419
281
|
*
|
|
420
282
|
* @param {Array<object>} footprintWithholds The kernel's complete ledger.
|
|
421
283
|
* @param {'enforce'|'advisory'} mode
|
|
@@ -443,10 +305,6 @@ export function buildFootprintGuardReport(footprintWithholds, mode) {
|
|
|
443
305
|
}
|
|
444
306
|
|
|
445
307
|
/**
|
|
446
|
-
* Render the operator-facing note for the beat-local guard, naming the
|
|
447
|
-
* colliding path(s) for every entry. `null` when the guard neither withheld nor
|
|
448
|
-
* waved anything through.
|
|
449
|
-
*
|
|
450
308
|
* @param {object[]} beat
|
|
451
309
|
* @param {object[]} advisory
|
|
452
310
|
* @param {string} mode
|
|
@@ -482,9 +340,7 @@ function footprintGuardNote(beat, advisory, mode) {
|
|
|
482
340
|
}
|
|
483
341
|
|
|
484
342
|
/**
|
|
485
|
-
*
|
|
486
|
-
* present. Neither class is a failure or a wedge, but they clear by different
|
|
487
|
-
* events, so each names its own.
|
|
343
|
+
* One sentence per reason class present; they clear by different events.
|
|
488
344
|
*
|
|
489
345
|
* @param {Array<{id: number, blockedBy: number, reason: string}>} withheld
|
|
490
346
|
* @returns {string}
|
|
@@ -519,14 +375,8 @@ function reservationNote(withheld) {
|
|
|
519
375
|
}
|
|
520
376
|
|
|
521
377
|
/**
|
|
522
|
-
*
|
|
523
|
-
*
|
|
524
|
-
* Each entry must carry `{ id, dependsOn }`. An optional `files` string
|
|
525
|
-
* array (the canonical footprint shape) is preserved and forwarded to the
|
|
526
|
-
* ready-set core so the file-overlap co-dispatch guard the Epic path uses is
|
|
527
|
-
* genuinely active on the standalone path too: two ready Stories that
|
|
528
|
-
* declare an intersecting footprint are never dispatched onto parallel
|
|
529
|
-
* `story-<id>` branches in the same beat.
|
|
378
|
+
* Validate the raw DAG array. An optional `files` footprint is forwarded so
|
|
379
|
+
* the overlap guard is active in flag mode too.
|
|
530
380
|
*
|
|
531
381
|
* @param {unknown} raw Parsed JSON value from --dag or --dag-file.
|
|
532
382
|
* @returns {{ nodes: Array<{id: number, dependsOn: number[], files?: string[]}>, error: string|null }}
|
|
@@ -589,14 +439,8 @@ export function parseDag(raw) {
|
|
|
589
439
|
}
|
|
590
440
|
|
|
591
441
|
/**
|
|
592
|
-
* Parse a
|
|
593
|
-
*
|
|
594
|
-
* empty set. Rejects any token that is not a positive integer or a valid
|
|
595
|
-
* range, so a typo never silently drops a dependency gate (`--done`) or a
|
|
596
|
-
* held dispatch slot (`--dispatched`).
|
|
597
|
-
*
|
|
598
|
-
* Ranges are accepted here for the same reason `--stories` accepts them: an
|
|
599
|
-
* operator delivering `4922-4926` writes the dispatched set back the same way.
|
|
442
|
+
* Parse a CSV of ids or `A-B` ranges into a deduped set. Rejects any bad
|
|
443
|
+
* token so a typo never silently drops a gate or a held slot.
|
|
600
444
|
*
|
|
601
445
|
* @param {string|undefined} raw
|
|
602
446
|
* @param {string} flag Flag name, for the error message.
|
|
@@ -608,8 +452,6 @@ export function parseIdCsv(raw, flag) {
|
|
|
608
452
|
}
|
|
609
453
|
|
|
610
454
|
/**
|
|
611
|
-
* Parse the `--done` CSV of already-completed Story IDs (flag mode).
|
|
612
|
-
*
|
|
613
455
|
* @param {string|undefined} raw
|
|
614
456
|
* @returns {{ ids: Set<number>|null, error: string|null }}
|
|
615
457
|
*/
|
|
@@ -618,10 +460,7 @@ export function parseDoneIds(raw) {
|
|
|
618
460
|
}
|
|
619
461
|
|
|
620
462
|
/**
|
|
621
|
-
*
|
|
622
|
-
* input defaults to 0. Rejects negatives and non-integers.
|
|
623
|
-
*
|
|
624
|
-
* @param {unknown} raw
|
|
463
|
+
* @param {unknown} raw Absent defaults to 0.
|
|
625
464
|
* @returns {{ value: number|null, error: string|null }}
|
|
626
465
|
*/
|
|
627
466
|
export function parseInFlight(raw) {
|
|
@@ -639,11 +478,12 @@ export function parseInFlight(raw) {
|
|
|
639
478
|
}
|
|
640
479
|
|
|
641
480
|
/**
|
|
642
|
-
*
|
|
643
|
-
*
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
481
|
+
* Cap when worktree isolation resolves off — a safety floor, so it outranks
|
|
482
|
+
* even an explicit `--concurrency`.
|
|
483
|
+
*/
|
|
484
|
+
export const WORKTREE_DISABLED_CONCURRENCY_CAP = 1;
|
|
485
|
+
|
|
486
|
+
/**
|
|
647
487
|
* @param {unknown} raw
|
|
648
488
|
* @returns {{ value: number|null, error: string|null }}
|
|
649
489
|
*/
|
|
@@ -662,100 +502,110 @@ export function parseConcurrencyOverride(raw) {
|
|
|
662
502
|
}
|
|
663
503
|
|
|
664
504
|
/**
|
|
665
|
-
* Resolve the per-beat concurrency cap.
|
|
666
|
-
*
|
|
667
|
-
* Mirrors the `/mandrel-deliver` multi-Story seam (`helpers/deliver-story.md`): resolve the
|
|
668
|
-
* project config (which deep-merges `.agentrc.local.json` over `.agentrc.json`)
|
|
669
|
-
* then read `delivery.deliverRunner.concurrencyCap` via `getRunners` (default
|
|
670
|
-
* 3). An explicit `override` (the `--concurrency <n>` CLI flag) wins over
|
|
671
|
-
* config for that run only.
|
|
672
|
-
*
|
|
673
505
|
* @param {object} [opts]
|
|
674
|
-
* @param {string} [opts.cwd]
|
|
675
|
-
* @param {object} [opts.config]
|
|
676
|
-
*
|
|
677
|
-
* @param {
|
|
678
|
-
*
|
|
679
|
-
* @returns {number} The resolved positive-integer concurrency cap.
|
|
506
|
+
* @param {string} [opts.cwd]
|
|
507
|
+
* @param {object} [opts.config] Pre-resolved config (test injection).
|
|
508
|
+
* @param {number} [opts.override] Validated `--concurrency`.
|
|
509
|
+
* @param {NodeJS.ProcessEnv} [opts.env]
|
|
510
|
+
* @returns {number}
|
|
680
511
|
*/
|
|
681
512
|
export function resolveConcurrencyCap(opts = {}) {
|
|
682
513
|
return resolveCapPrecedence(opts).cap;
|
|
683
514
|
}
|
|
684
515
|
|
|
685
516
|
/**
|
|
686
|
-
* Resolve the per-beat cap
|
|
687
|
-
*
|
|
688
|
-
*
|
|
689
|
-
*
|
|
690
|
-
* is the intended contract — a flag an operator typed for one run should not be
|
|
691
|
-
* outranked by a checked-in default. What was wrong is that it won *silently*:
|
|
692
|
-
* the envelope reported a single `concurrencyCap` number with no record of
|
|
693
|
-
* which source set it, so a run at 8 when the project configured 3 was
|
|
694
|
-
* indistinguishable from a project configured at 8. A reader could not tell an
|
|
695
|
-
* override from a default, and an override that ran the repo above its own
|
|
696
|
-
* configured ceiling left no trace at all.
|
|
697
|
-
*
|
|
698
|
-
* So the flag still wins, but never quietly: the source is named, the
|
|
699
|
-
* configured value is carried alongside the requested one, and a request that
|
|
700
|
-
* exceeds the configured cap is called out as such. Reporting rather than
|
|
701
|
-
* refusing is deliberate — the configured cap is a project default, not a
|
|
702
|
-
* safety limit, and refusing a deliberate operator escalation would trade a
|
|
703
|
-
* silent override for a silent stall.
|
|
517
|
+
* Resolve the per-beat cap and the precedence that produced it. The flag wins
|
|
518
|
+
* over config but never silently: a request above the configured cap is
|
|
519
|
+
* reported, not refused (the configured cap is a default, not a safety
|
|
520
|
+
* limit). The worktree clamp outranks both.
|
|
704
521
|
*
|
|
705
522
|
* @param {object} [opts]
|
|
706
|
-
* @param {string} [opts.cwd]
|
|
523
|
+
* @param {string} [opts.cwd]
|
|
707
524
|
* @param {object} [opts.config] Pre-resolved config (test injection).
|
|
708
|
-
* @param {number} [opts.override] Validated
|
|
709
|
-
*
|
|
525
|
+
* @param {number} [opts.override] Validated `--concurrency`.
|
|
526
|
+
* @param {NodeJS.ProcessEnv} [opts.env]
|
|
710
527
|
* @returns {{
|
|
711
528
|
* cap: number,
|
|
712
|
-
* source: 'flag'|'config',
|
|
529
|
+
* source: 'flag'|'config'|'worktree-clamp',
|
|
713
530
|
* configuredCap: number,
|
|
714
531
|
* requestedCap: number|null,
|
|
715
532
|
* exceedsConfigured: boolean,
|
|
716
533
|
* note: string,
|
|
717
534
|
* }}
|
|
718
535
|
*/
|
|
719
|
-
export function resolveCapPrecedence({ cwd, config, override } = {}) {
|
|
536
|
+
export function resolveCapPrecedence({ cwd, config, override, env } = {}) {
|
|
720
537
|
const resolved = config ?? resolveConfig({ cwd });
|
|
721
538
|
const { deliverRunner } = getRunners(resolved);
|
|
722
539
|
const configuredCap = deliverRunner.concurrencyCap;
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
540
|
+
const requested =
|
|
541
|
+
override == null
|
|
542
|
+
? {
|
|
543
|
+
cap: configuredCap,
|
|
544
|
+
source: 'config',
|
|
545
|
+
configuredCap,
|
|
546
|
+
requestedCap: null,
|
|
547
|
+
exceedsConfigured: false,
|
|
548
|
+
note: `cap ${configuredCap} from delivery.deliverRunner.concurrencyCap (no --concurrency given)`,
|
|
549
|
+
}
|
|
550
|
+
: {
|
|
551
|
+
cap: override,
|
|
552
|
+
source: 'flag',
|
|
553
|
+
configuredCap,
|
|
554
|
+
requestedCap: override,
|
|
555
|
+
exceedsConfigured: override > configuredCap,
|
|
556
|
+
note:
|
|
557
|
+
override > configuredCap
|
|
558
|
+
? `cap ${override} from --concurrency, which OVERRIDES and EXCEEDS the configured delivery.deliverRunner.concurrencyCap ${configuredCap} — this run is deliberately above the project default`
|
|
559
|
+
: `cap ${override} from --concurrency, which overrides the configured delivery.deliverRunner.concurrencyCap ${configuredCap}`,
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
return resolveWorktreeClamp({ requested, config: resolved, env });
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Apply the worktree-isolation floor. Keyed off `resolveWorktreeEnabled` so
|
|
567
|
+
* every route to isolation-off is covered. The config is normalised through
|
|
568
|
+
* `getWorktreeIsolation` first: a raw read of an omitted block is `false` and
|
|
569
|
+
* would clamp as if isolation had been disabled. The clamp record is emitted
|
|
570
|
+
* even when the requested cap was already 1, so sequentiality is attributable.
|
|
571
|
+
*
|
|
572
|
+
* @param {object} args
|
|
573
|
+
* @param {{cap: number, source: string, configuredCap: number, requestedCap: number|null, exceedsConfigured: boolean, note: string}} args.requested
|
|
574
|
+
* @param {object|null} [args.config]
|
|
575
|
+
* @param {NodeJS.ProcessEnv} [args.env]
|
|
576
|
+
* @returns {typeof args.requested}
|
|
577
|
+
*/
|
|
578
|
+
export function resolveWorktreeClamp({ requested, config, env } = {}) {
|
|
579
|
+
const worktreeEnabled = resolveWorktreeEnabled(
|
|
580
|
+
{
|
|
581
|
+
config: { delivery: { worktreeIsolation: getWorktreeIsolation(config) } },
|
|
582
|
+
},
|
|
583
|
+
env ?? process.env,
|
|
584
|
+
);
|
|
585
|
+
if (worktreeEnabled) return requested;
|
|
586
|
+
|
|
587
|
+
const from =
|
|
588
|
+
requested.source === 'flag'
|
|
589
|
+
? '--concurrency'
|
|
590
|
+
: 'delivery.deliverRunner.concurrencyCap';
|
|
734
591
|
return {
|
|
735
|
-
cap:
|
|
736
|
-
source: '
|
|
737
|
-
configuredCap,
|
|
738
|
-
requestedCap:
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
: `cap ${override} from --concurrency, which overrides the configured delivery.deliverRunner.concurrencyCap ${configuredCap}`,
|
|
592
|
+
cap: WORKTREE_DISABLED_CONCURRENCY_CAP,
|
|
593
|
+
source: 'worktree-clamp',
|
|
594
|
+
configuredCap: requested.configuredCap,
|
|
595
|
+
requestedCap: requested.cap,
|
|
596
|
+
// The escalation never took effect.
|
|
597
|
+
exceedsConfigured: false,
|
|
598
|
+
note: `cap clamped to ${WORKTREE_DISABLED_CONCURRENCY_CAP} because worktree isolation resolved OFF — requested ${requested.cap} from ${from}. Concurrent dispatch shares one checkout without per-Story worktrees, so two workers would contend for HEAD; this floor outranks an explicit --concurrency.`,
|
|
743
599
|
};
|
|
744
600
|
}
|
|
745
601
|
|
|
746
602
|
/**
|
|
747
|
-
*
|
|
748
|
-
*
|
|
749
|
-
*
|
|
750
|
-
* `tempRoot` is threaded rather than hardcoded because the evidence scrape must
|
|
751
|
-
* exclude the project's *configured* scratch root: a consumer that sets
|
|
752
|
-
* `project.paths.tempRoot: '.scratch'` would otherwise have every sibling
|
|
753
|
-
* citing a report under it collide, which is the exact defect this Story
|
|
754
|
-
* removes for the default `temp/`.
|
|
603
|
+
* `tempRoot` is the configured one, not a hardcoded `temp/`, so the overlap
|
|
604
|
+
* guard excludes the project's actual scratch root.
|
|
755
605
|
*
|
|
756
606
|
* @param {object} [opts]
|
|
757
|
-
* @param {string} [opts.cwd]
|
|
758
|
-
* @param {object} [opts.config]
|
|
607
|
+
* @param {string} [opts.cwd]
|
|
608
|
+
* @param {object} [opts.config]
|
|
759
609
|
* @returns {{ footprintGuard: 'enforce'|'advisory', tempRoot: string }}
|
|
760
610
|
*/
|
|
761
611
|
export function resolveFootprintGuardSettings({ cwd, config } = {}) {
|
|
@@ -767,32 +617,18 @@ export function resolveFootprintGuardSettings({ cwd, config } = {}) {
|
|
|
767
617
|
}
|
|
768
618
|
|
|
769
619
|
/**
|
|
770
|
-
* Build the per-beat
|
|
771
|
-
*
|
|
772
|
-
* Maps each operator-DAG node onto a Story record the ready-set core
|
|
773
|
-
* understands (`{ id, dependsOn }`), tags any node already in the done set
|
|
774
|
-
* as `agent::done` so the core's classifier excludes it from the dispatch
|
|
775
|
-
* set **and** counts it as a satisfied dependency, then delegates the
|
|
776
|
-
* scheduling decision to `planReadySet`. A cyclic operator DAG is a
|
|
777
|
-
* planning error (the core would silently never schedule the cycle), so we
|
|
778
|
-
* detect it up front via the shared `detectCycle` kernel and short-circuit
|
|
779
|
-
* with a `cycleError` and exit code 2.
|
|
620
|
+
* Build the per-beat envelope. A cyclic DAG is rejected up front (exit 2)
|
|
621
|
+
* because the core would silently never schedule it.
|
|
780
622
|
*
|
|
781
623
|
* @param {Array<{id: number, dependsOn: number[]}>} nodes
|
|
782
624
|
* @param {object} args
|
|
783
|
-
* @param {number} args.concurrencyCap
|
|
784
|
-
* @param {object|null} [args.capPrecedence]
|
|
785
|
-
*
|
|
786
|
-
* @param {
|
|
787
|
-
* @param {
|
|
788
|
-
*
|
|
789
|
-
*
|
|
790
|
-
* merely counting them (Story #4950). `null` (flag mode) means reservation
|
|
791
|
-
* is structurally unavailable — see {@link buildReservationReport}.
|
|
792
|
-
* @param {number[]} [args.foreignHeldIds] Ids among `inFlightRecords` that a
|
|
793
|
-
* **foreign operator's lease** holds rather than this run's own earlier
|
|
794
|
-
* beat, so a withholding against one is reported for what it is
|
|
795
|
-
* (Story #4960). Flag mode has no lease view and passes none.
|
|
625
|
+
* @param {number} args.concurrencyCap
|
|
626
|
+
* @param {object|null} [args.capPrecedence]
|
|
627
|
+
* @param {Set<number>} [args.doneIds]
|
|
628
|
+
* @param {number} [args.inFlight]
|
|
629
|
+
* @param {object[]|null} [args.inFlightRecords] `null` (flag mode) means
|
|
630
|
+
* reservation is unavailable, not empty.
|
|
631
|
+
* @param {number[]} [args.foreignHeldIds] Ids held by a foreign lease.
|
|
796
632
|
* @returns {{
|
|
797
633
|
* envelope: {
|
|
798
634
|
* kind: 'stories-ready-set',
|
|
@@ -825,21 +661,13 @@ export function buildReadySetEnvelope(
|
|
|
825
661
|
ready: [],
|
|
826
662
|
totalStories,
|
|
827
663
|
concurrencyCap,
|
|
828
|
-
//
|
|
829
|
-
//
|
|
830
|
-
// missing precedence record is what made a silent override possible.
|
|
664
|
+
// The reports below are never omitted: an absent report reads like an
|
|
665
|
+
// empty one.
|
|
831
666
|
capPrecedence,
|
|
832
667
|
inFlight,
|
|
833
668
|
cycleError: null,
|
|
834
669
|
wedged: null,
|
|
835
|
-
// Whether this beat could reserve the in-flight Stories' footprints, and
|
|
836
|
-
// which Stories a reservation withheld (Story #4950). Never omitted on a
|
|
837
|
-
// resolved beat: an absent report reads exactly like an empty one.
|
|
838
670
|
inFlightReservation: buildReservationReport(inFlightRecords, []),
|
|
839
|
-
// The beat-local half of the same guard, plus the mode it ran in (Story
|
|
840
|
-
// #5044). Also never omitted: a same-beat skip used to be reported nowhere
|
|
841
|
-
// at all, which is precisely how an evidence-widening artifact could
|
|
842
|
-
// serialize a whole run unnoticed.
|
|
843
671
|
footprintGuard: buildFootprintGuardReport([], footprintGuard),
|
|
844
672
|
};
|
|
845
673
|
|
|
@@ -847,10 +675,7 @@ export function buildReadySetEnvelope(
|
|
|
847
675
|
return { envelope: base, exitCode: 0 };
|
|
848
676
|
}
|
|
849
677
|
|
|
850
|
-
//
|
|
851
|
-
// operator must fix. dropForeign:false preserves the operator-DAG contract
|
|
852
|
-
// (a dependency on an id outside the supplied set is honored, not pruned),
|
|
853
|
-
// matching the same builder seam planReadySet uses internally.
|
|
678
|
+
// dropForeign:false: a dependency outside the supplied set is honored.
|
|
854
679
|
const adjacency = buildStoryAdjacency(nodes, { dropForeign: false });
|
|
855
680
|
const cycle = detectCycle(adjacency);
|
|
856
681
|
if (cycle) {
|
|
@@ -863,26 +688,16 @@ export function buildReadySetEnvelope(
|
|
|
863
688
|
};
|
|
864
689
|
}
|
|
865
690
|
|
|
866
|
-
//
|
|
867
|
-
//
|
|
868
|
-
//
|
|
869
|
-
// Forward any declared file footprint so the core's overlap guard fires.
|
|
691
|
+
// Done nodes are tagged agent::done so the core both excludes them and
|
|
692
|
+
// counts them as satisfied dependencies. Probe-mode live labels are kept so
|
|
693
|
+
// an in-flight Story is never re-dispatched onto a second branch.
|
|
870
694
|
const records = nodes.map((node) => {
|
|
871
695
|
const rec = {
|
|
872
696
|
id: node.id,
|
|
873
697
|
dependsOn: node.dependsOn,
|
|
874
|
-
// A node's own live labels (probe mode) are preserved so the core's
|
|
875
|
-
// classifier withholds an in-flight `agent::executing` / `agent::closing`
|
|
876
|
-
// Story rather than re-dispatching it onto a second branch. Flag-mode
|
|
877
|
-
// nodes carry none — `parseDag` accepts no labels — so this is inert
|
|
878
|
-
// there and the legacy contract is unchanged.
|
|
879
698
|
labels: doneIds.has(node.id) ? [AGENT_LABELS.DONE] : (node.labels ?? []),
|
|
880
699
|
};
|
|
881
700
|
if (node.files !== undefined) rec.files = node.files;
|
|
882
|
-
// Probe-mode nodes carry the Story body so the overlap guard can widen a
|
|
883
|
-
// declared footprint from the paths the Story's own text names (Story
|
|
884
|
-
// #4875). Flag-mode nodes carry none — `parseDag` accepts no body — so
|
|
885
|
-
// this is inert there and the legacy contract is unchanged.
|
|
886
701
|
if (typeof node.body === 'string') rec.body = node.body;
|
|
887
702
|
return rec;
|
|
888
703
|
});
|
|
@@ -892,17 +707,11 @@ export function buildReadySetEnvelope(
|
|
|
892
707
|
doneIds,
|
|
893
708
|
inFlight,
|
|
894
709
|
globalCap: concurrencyCap,
|
|
895
|
-
// Flag mode has no in-flight records at all; `?? []` keeps the kernel's
|
|
896
|
-
// contract (an array) while `base.inFlightReservation` reports that the
|
|
897
|
-
// reservation itself was unavailable rather than merely empty.
|
|
898
710
|
inFlightRecords: inFlightRecords ?? [],
|
|
899
711
|
footprintGuard,
|
|
900
712
|
tempRoot,
|
|
901
713
|
});
|
|
902
714
|
const ready = selected.map((rec) => rec.id);
|
|
903
|
-
// The cross-beat report reads the enforced in-flight slice of the kernel's
|
|
904
|
-
// ledger rather than the legacy `withheldByInFlight` list, so it carries the
|
|
905
|
-
// colliding paths and the overlap source through to the operator.
|
|
906
715
|
const reservation = buildReservationReport(
|
|
907
716
|
inFlightRecords,
|
|
908
717
|
footprintWithholds.filter(
|
|
@@ -912,17 +721,6 @@ export function buildReadySetEnvelope(
|
|
|
912
721
|
);
|
|
913
722
|
const guardReport = buildFootprintGuardReport(footprintWithholds, guardMode);
|
|
914
723
|
|
|
915
|
-
// Wedge detection (Story #4540). `ready: []` is normal while work is in
|
|
916
|
-
// flight — the loop is simply waiting. But ready-empty AND nothing in
|
|
917
|
-
// flight AND undone Stories remaining means no beat can ever make
|
|
918
|
-
// progress: the run is stuck, and the previous behaviour was to return
|
|
919
|
-
// exit 0 with an empty ready set forever, indistinguishable from
|
|
920
|
-
// "waiting". Name the stuck ids and their unmet blockers.
|
|
921
|
-
//
|
|
922
|
-
// Distinct from `cycleError`/exit 2: a cycle is a self-referential DAG,
|
|
923
|
-
// whereas this is a DAG whose gates are real but unsatisfiable from the
|
|
924
|
-
// supplied `done` set (typically a blocker outside the delivered set that
|
|
925
|
-
// has not landed).
|
|
926
724
|
const wedge = detectWedge({ nodes, doneIds, ready, inFlight });
|
|
927
725
|
if (wedge) {
|
|
928
726
|
return {
|
|
@@ -968,9 +766,7 @@ export function detectWedge({ nodes, doneIds, ready, inFlight }) {
|
|
|
968
766
|
}))
|
|
969
767
|
.filter((s) => s.unmetBlockers.length > 0);
|
|
970
768
|
|
|
971
|
-
// Undone work with no unmet blockers
|
|
972
|
-
// is the whole set, the cap or in-flight accounting explains the empty
|
|
973
|
-
// ready set rather than a wedge.
|
|
769
|
+
// Undone work with no unmet blockers is capacity-limited, not wedged.
|
|
974
770
|
if (stories.length === 0) return null;
|
|
975
771
|
|
|
976
772
|
const detail = stories
|
|
@@ -986,20 +782,17 @@ export function detectWedge({ nodes, doneIds, ready, inFlight }) {
|
|
|
986
782
|
}
|
|
987
783
|
|
|
988
784
|
/**
|
|
989
|
-
*
|
|
990
|
-
* compute the per-beat ready set via the shared scheduling core.
|
|
991
|
-
*
|
|
992
|
-
* Exported for unit tests; the CLI `main` function is a thin wrapper. Tests
|
|
993
|
-
* inject `config` so they never depend on a real `.agentrc`.
|
|
785
|
+
* Flag-mode beat.
|
|
994
786
|
*
|
|
995
787
|
* @param {object} args
|
|
996
|
-
* @param {string} [args.dagJson]
|
|
997
|
-
* @param {string} [args.dagFile]
|
|
998
|
-
* @param {string|number} [args.concurrency]
|
|
999
|
-
* @param {string} [args.done]
|
|
1000
|
-
* @param {string|number} [args.inFlight]
|
|
1001
|
-
* @param {string} [args.cwd]
|
|
1002
|
-
* @param {object} [args.config]
|
|
788
|
+
* @param {string} [args.dagJson]
|
|
789
|
+
* @param {string} [args.dagFile]
|
|
790
|
+
* @param {string|number} [args.concurrency]
|
|
791
|
+
* @param {string} [args.done]
|
|
792
|
+
* @param {string|number} [args.inFlight]
|
|
793
|
+
* @param {string} [args.cwd]
|
|
794
|
+
* @param {object} [args.config] Pre-resolved config (test injection).
|
|
795
|
+
* @param {NodeJS.ProcessEnv} [args.env]
|
|
1003
796
|
* @returns {{
|
|
1004
797
|
* envelope: {kind: string, ready: number[], totalStories: number, concurrencyCap: number, inFlight: number, cycleError: string|null},
|
|
1005
798
|
* exitCode: number
|
|
@@ -1013,9 +806,8 @@ export function runStoriesWaveTick({
|
|
|
1013
806
|
inFlight,
|
|
1014
807
|
cwd,
|
|
1015
808
|
config,
|
|
809
|
+
env,
|
|
1016
810
|
} = {}) {
|
|
1017
|
-
// Validate the --concurrency override before resolving config so an invalid
|
|
1018
|
-
// value fails fast with exit code 1 regardless of DAG validity.
|
|
1019
811
|
const { value: override, error: concurrencyError } =
|
|
1020
812
|
parseConcurrencyOverride(concurrency);
|
|
1021
813
|
if (concurrencyError) {
|
|
@@ -1033,7 +825,7 @@ export function runStoriesWaveTick({
|
|
|
1033
825
|
return inputErrorResult(doneError, null, inFlightValue);
|
|
1034
826
|
}
|
|
1035
827
|
|
|
1036
|
-
const capPrecedence = resolveCapPrecedence({ cwd, config, override });
|
|
828
|
+
const capPrecedence = resolveCapPrecedence({ cwd, config, override, env });
|
|
1037
829
|
const concurrencyCap = capPrecedence.cap;
|
|
1038
830
|
|
|
1039
831
|
let rawJson;
|
|
@@ -1084,32 +876,22 @@ export function runStoriesWaveTick({
|
|
|
1084
876
|
}
|
|
1085
877
|
|
|
1086
878
|
/**
|
|
1087
|
-
* Probe
|
|
1088
|
-
*
|
|
1089
|
-
*
|
|
1090
|
-
*
|
|
1091
|
-
* asked to deliver; `done` and `inFlight` are probed rather than transcribed,
|
|
1092
|
-
* which is what makes the `/mandrel-deliver` loop's old seed-the-first-beat footgun
|
|
1093
|
-
* structurally impossible instead of merely documented.
|
|
1094
|
-
*
|
|
1095
|
-
* The envelope is the flag mode's, plus three probe-only fields the caller can
|
|
1096
|
-
* no longer compute for itself:
|
|
1097
|
-
* - `done` — the resolved done set (in-set ∪ satisfied foreign blockers).
|
|
1098
|
-
* - `epilogueDue` — true exactly when every listed Story is done, which is
|
|
1099
|
-
* the run-end signal for `plan-run-epilogue.js`.
|
|
1100
|
-
* - `blocked` — ids carrying `agent::blocked` (Story #4601). Non-empty means
|
|
1101
|
-
* the loop must END, not poll: see `BLOCKED_EXIT_CODE`.
|
|
879
|
+
* Probe-mode beat: graph and progress from live state. Adds `done`,
|
|
880
|
+
* `epilogueDue` (every listed Story done — the run-end signal), `blocked`
|
|
881
|
+
* (non-empty ends the loop) and `stalledDispatch` (`--dispatched` ids still
|
|
882
|
+
* `agent::ready`, which only the caller can tell from a dead spawn).
|
|
1102
883
|
*
|
|
1103
884
|
* @param {object} args
|
|
1104
|
-
* @param {string} args.stories
|
|
1105
|
-
* @param {string|number} [args.concurrency]
|
|
1106
|
-
* @param {string} [args.dispatched]
|
|
1107
|
-
*
|
|
1108
|
-
* @param {
|
|
1109
|
-
* @param {
|
|
1110
|
-
* @param {Function} [args.probe]
|
|
1111
|
-
* @param {Function} [args.context]
|
|
1112
|
-
* @returns {Promise<{ envelope: object, exitCode: number }>}
|
|
885
|
+
* @param {string} args.stories
|
|
886
|
+
* @param {string|number} [args.concurrency]
|
|
887
|
+
* @param {string} [args.dispatched]
|
|
888
|
+
* @param {string} [args.cwd]
|
|
889
|
+
* @param {object} [args.config]
|
|
890
|
+
* @param {NodeJS.ProcessEnv} [args.env]
|
|
891
|
+
* @param {Function} [args.probe] Test seam.
|
|
892
|
+
* @param {Function} [args.context] Test seam.
|
|
893
|
+
* @returns {Promise<{ envelope: object, exitCode: number, records: object[] }>}
|
|
894
|
+
* `records` are the probed nodes, kept off stdout.
|
|
1113
895
|
*/
|
|
1114
896
|
export async function runProbedStoriesWaveTick({
|
|
1115
897
|
stories,
|
|
@@ -1117,6 +899,7 @@ export async function runProbedStoriesWaveTick({
|
|
|
1117
899
|
dispatched,
|
|
1118
900
|
cwd,
|
|
1119
901
|
config,
|
|
902
|
+
env,
|
|
1120
903
|
probe = probeLiveState,
|
|
1121
904
|
context = createProbeContext,
|
|
1122
905
|
} = {}) {
|
|
@@ -1141,7 +924,7 @@ export async function runProbedStoriesWaveTick({
|
|
|
1141
924
|
return inputErrorResult(dispatchedError);
|
|
1142
925
|
}
|
|
1143
926
|
|
|
1144
|
-
const capPrecedence = resolveCapPrecedence({ cwd, config, override });
|
|
927
|
+
const capPrecedence = resolveCapPrecedence({ cwd, config, override, env });
|
|
1145
928
|
const concurrencyCap = capPrecedence.cap;
|
|
1146
929
|
|
|
1147
930
|
let probed;
|
|
@@ -1157,9 +940,7 @@ export async function runProbedStoriesWaveTick({
|
|
|
1157
940
|
warn: (m) => Logger.warn(m),
|
|
1158
941
|
});
|
|
1159
942
|
} catch (err) {
|
|
1160
|
-
//
|
|
1161
|
-
// indistinguishable from a healthy waiting beat and would silently stall
|
|
1162
|
-
// the run. Fail loud with the input-error contract instead.
|
|
943
|
+
// Never degrade into "nothing is ready": that reads as a healthy wait.
|
|
1163
944
|
return inputErrorResult(
|
|
1164
945
|
`Could not probe live state: ${err?.message ?? err}`,
|
|
1165
946
|
concurrencyCap,
|
|
@@ -1171,6 +952,7 @@ export async function runProbedStoriesWaveTick({
|
|
|
1171
952
|
doneIds,
|
|
1172
953
|
inFlight,
|
|
1173
954
|
blockedIds = [],
|
|
955
|
+
stalledDispatch = [],
|
|
1174
956
|
foreignHeld = [],
|
|
1175
957
|
inFlightRecords = [],
|
|
1176
958
|
} = probed;
|
|
@@ -1179,11 +961,7 @@ export async function runProbedStoriesWaveTick({
|
|
|
1179
961
|
capPrecedence,
|
|
1180
962
|
doneIds,
|
|
1181
963
|
inFlight,
|
|
1182
|
-
// Probe mode is the only mode that HAS the in-flight Stories' records, so
|
|
1183
|
-
// it is the only mode that can reserve their footprints (Story #4950).
|
|
1184
964
|
inFlightRecords,
|
|
1185
|
-
// ...and the only mode that can tell a foreign lease-holder apart from
|
|
1186
|
-
// this run's own earlier-beat dispatch (Story #4960).
|
|
1187
965
|
foreignHeldIds: foreignHeld.map((h) => h.id),
|
|
1188
966
|
...resolveFootprintGuardSettings({ cwd, config }),
|
|
1189
967
|
});
|
|
@@ -1198,16 +976,13 @@ export async function runProbedStoriesWaveTick({
|
|
|
1198
976
|
epilogueDue,
|
|
1199
977
|
blocked: blockedIds,
|
|
1200
978
|
blockedReason: blockedReasonFor(blockedIds),
|
|
1201
|
-
|
|
1202
|
-
// beat (folded into in-flight) and surfaced so the run can report
|
|
1203
|
-
// "#<id> held by @<holder>" instead of dispatching into an init refusal.
|
|
979
|
+
stalledDispatch,
|
|
1204
980
|
foreignHeld,
|
|
1205
981
|
foreignHeldReason: foreignHeldReasonFor(foreignHeld),
|
|
1206
982
|
},
|
|
1207
|
-
|
|
1208
|
-
// wedge
|
|
1209
|
-
//
|
|
1210
|
-
// that must be fixed before any of this run's state means anything.
|
|
983
|
+
records: nodes,
|
|
984
|
+
// Blocked outranks a wedge (its blockers are moot while a human owes a
|
|
985
|
+
// decision) but not a cycle, which invalidates the run's state.
|
|
1211
986
|
exitCode:
|
|
1212
987
|
blockedIds.length > 0 && !envelope.cycleError
|
|
1213
988
|
? BLOCKED_EXIT_CODE
|
|
@@ -1216,9 +991,6 @@ export async function runProbedStoriesWaveTick({
|
|
|
1216
991
|
}
|
|
1217
992
|
|
|
1218
993
|
/**
|
|
1219
|
-
* Render the operator-facing reason for a blocked run, or `null` when nothing
|
|
1220
|
-
* is blocked.
|
|
1221
|
-
*
|
|
1222
994
|
* @param {number[]} blockedIds
|
|
1223
995
|
* @returns {string|null}
|
|
1224
996
|
*/
|
|
@@ -1235,14 +1007,6 @@ function blockedReasonFor(blockedIds) {
|
|
|
1235
1007
|
}
|
|
1236
1008
|
|
|
1237
1009
|
/**
|
|
1238
|
-
* Render the operator-facing note for Stories held by another operator's
|
|
1239
|
-
* lease, or `null` when none are held.
|
|
1240
|
-
*
|
|
1241
|
-
* These are not errors and not a wedge: the holder's run is progressing
|
|
1242
|
-
* normally, this run simply must not join it on the same branch. The Story
|
|
1243
|
-
* stays withheld and re-probes each beat, so it dispatches on its own the
|
|
1244
|
-
* moment the holder's lease clears (their run lands or is stolen).
|
|
1245
|
-
*
|
|
1246
1010
|
* @param {Array<{id: number, holder: string}>} foreignHeld
|
|
1247
1011
|
* @returns {string|null}
|
|
1248
1012
|
*/
|