mandrel 2.60.0 → 2.62.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/merge-queue.js +158 -0
- 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 +190 -280
- 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 +183 -485
- 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 +32 -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
|
@@ -2,134 +2,25 @@
|
|
|
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
|
-
* **The cap is clamped to 1 when worktree isolation resolves off** (Story
|
|
111
|
-
* #5357). Concurrent dispatch is safe only because each Story gets its own
|
|
112
|
-
* checkout; with isolation off every Story resolves to the same `workCwd`, so
|
|
113
|
-
* two workers contend for `HEAD` and one takes the branch from under the
|
|
114
|
-
* other — the #5339/#5340 web run, where both wave-1 workers were initialised
|
|
115
|
-
* into the same tree. The clamp reads `resolveWorktreeEnabled`'s result, so all
|
|
116
|
-
* three routes to off (`CLAUDE_CODE_REMOTE=true`, `AP_WORKTREE_ENABLED=false`,
|
|
117
|
-
* `delivery.worktreeIsolation.enabled: false`) are covered by construction. It
|
|
118
|
-
* is a safety floor rather than a preference, so it is the one case where an
|
|
119
|
-
* explicit `--concurrency` does NOT win — and `capPrecedence` names
|
|
120
|
-
* `worktree-clamp` as the winning source and carries the requested value.
|
|
121
|
-
*
|
|
122
|
-
* Exit codes: 0 ok · 1 input error · 2 dependency cycle (`cycleError`) ·
|
|
123
|
-
* 3 wedged (`wedged`) — ready is empty, nothing is in flight, and undone
|
|
124
|
-
* Stories are waiting on blockers that are not done · 4 blocked (`blocked`) —
|
|
125
|
-
* a Story carries `agent::blocked`. A cycle is a self-referential DAG the
|
|
126
|
-
* operator must fix; a wedge is a well-formed DAG whose gates cannot be
|
|
127
|
-
* satisfied from the supplied `--done` set (usually a blocker outside the
|
|
128
|
-
* delivered set that has not landed); a block is the protocol's HITL pause,
|
|
129
|
-
* where a human owes a decision no beat can supply. All three are distinct
|
|
130
|
-
* from the ordinary `ready: []` that means "waiting on in-flight work" — and
|
|
131
|
-
* that distinction is the point: each of them previously presented AS that
|
|
132
|
-
* 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.
|
|
133
24
|
*/
|
|
134
25
|
|
|
135
26
|
import { readFileSync } from 'node:fs';
|
|
@@ -161,20 +52,12 @@ import {
|
|
|
161
52
|
WITHHOLD_SCOPES,
|
|
162
53
|
} from './lib/wave-runner/ready-set.js';
|
|
163
54
|
|
|
164
|
-
/**
|
|
165
|
-
* Exit code for a wedged run — deliberately distinct from the cycle exit (2)
|
|
166
|
-
* so a caller can tell "your DAG is self-referential" from "your DAG is fine
|
|
167
|
-
* but its gates can never be satisfied from this `--done` set".
|
|
168
|
-
*/
|
|
55
|
+
/** Wedged run: a well-formed DAG whose gates cannot be satisfied from `--done`. */
|
|
169
56
|
export const WEDGED_EXIT_CODE = 3;
|
|
170
57
|
|
|
171
58
|
/**
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* different: a cycle is a malformed DAG and a wedge is an unlanded blocker,
|
|
175
|
-
* whereas this is the protocol's one runtime HITL pause. A human must decide
|
|
176
|
-
* something before any beat can help. Probe-mode only: flag-mode nodes carry
|
|
177
|
-
* 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.
|
|
178
61
|
*/
|
|
179
62
|
export const BLOCKED_EXIT_CODE = 4;
|
|
180
63
|
|
|
@@ -312,10 +195,6 @@ Exit codes:
|
|
|
312
195
|
`;
|
|
313
196
|
|
|
314
197
|
/**
|
|
315
|
-
* Build the exit-1 input-error result. Shared by both modes so a malformed
|
|
316
|
-
* `--concurrency` reports identically whether it arrived alongside `--dag` or
|
|
317
|
-
* `--probe-live`.
|
|
318
|
-
*
|
|
319
198
|
* @param {string} message
|
|
320
199
|
* @param {number|null} [concurrencyCap]
|
|
321
200
|
* @param {number} [inFlightValue]
|
|
@@ -340,48 +219,18 @@ function inputErrorResult(message, concurrencyCap = null, inFlightValue = 0) {
|
|
|
340
219
|
};
|
|
341
220
|
}
|
|
342
221
|
|
|
343
|
-
/**
|
|
344
|
-
* Why a reservation withheld a Story. Machine-readable companion to the
|
|
345
|
-
* operator-facing `note`, so a consumer never has to parse prose to tell an
|
|
346
|
-
* earlier-beat blocker from a foreign-lease one (Story #4960).
|
|
347
|
-
*/
|
|
222
|
+
/** Machine-readable reason a reservation withheld a Story. */
|
|
348
223
|
const RESERVATION_REASONS = Object.freeze({
|
|
349
224
|
EARLIER_BEAT: 'in-flight-earlier-beat',
|
|
350
225
|
FOREIGN_LEASE: 'foreign-lease',
|
|
351
226
|
});
|
|
352
227
|
|
|
353
228
|
/**
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
359
|
-
* mode rather than of the run:
|
|
360
|
-
*
|
|
361
|
-
* - **Probe mode** hands over the records `live-probe.js` already fetched,
|
|
362
|
-
* so `inFlightRecords` is an array (possibly empty) and reservation is
|
|
363
|
-
* `available: true`.
|
|
364
|
-
* - **Flag mode** (`--dag` + `--in-flight <n>`) supplies a graph and a
|
|
365
|
-
* count; no node carries a label, so nothing there can even classify as
|
|
366
|
-
* in-flight. There is no footprint to reserve against, and selection is
|
|
367
|
-
* unchanged from before #4950. Saying so explicitly is the point: a
|
|
368
|
-
* silently-absent guard reads exactly like a guard that found nothing.
|
|
369
|
-
*
|
|
370
|
-
* A reservation is held either by a Story **this run** dispatched on an
|
|
371
|
-
* earlier beat or by one **another operator's lease** holds — `live-probe.js`
|
|
372
|
-
* folds both into the in-flight set, and they reserve identically but read
|
|
373
|
-
* very differently to an operator. Reporting a foreign-held peer as "still in
|
|
374
|
-
* flight from an earlier beat" is simply false: this run never dispatched it
|
|
375
|
-
* and no later beat of this run will clear it. `foreignHeldIds` splits the two
|
|
376
|
-
* so each carries its own reason (Story #4960).
|
|
377
|
-
*
|
|
378
|
-
* Each entry also carries the **colliding paths** and an
|
|
379
|
-
* `OVERLAP_SOURCES` tag (Story #5044). A withhold that names no path is one an
|
|
380
|
-
* operator cannot act on, and `declared-overlap` vs `scraped-overlap` is the
|
|
381
|
-
* difference between "these two Stories both declared this generated baseline,
|
|
382
|
-
* serializing them is the point" and "one Story's body happened to mention a
|
|
383
|
-
* path the other declared" — the same unfilled slot for two very different
|
|
384
|
-
* 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.
|
|
385
234
|
*
|
|
386
235
|
* @param {object[]|null|undefined} inFlightRecords
|
|
387
236
|
* @param {Array<{id: number, blockedBy: number, source?: string, paths?: string[]}>} withheld
|
|
@@ -426,21 +275,9 @@ export function buildReservationReport(
|
|
|
426
275
|
}
|
|
427
276
|
|
|
428
277
|
/**
|
|
429
|
-
* Report the
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
* Until now a same-beat overlap skip was an anonymous `continue` inside
|
|
433
|
-
* `planReadySet`: the Story simply did not appear in `ready[]` and no field
|
|
434
|
-
* anywhere said why. That is the same unexplained-unfilled-slot failure the
|
|
435
|
-
* cross-beat `inFlightReservation` report was built to remove, left standing on
|
|
436
|
-
* the other half of the guard — and it is how a plan whose siblings collided
|
|
437
|
-
* only on machine-generated footer text ran fully serial without leaving a
|
|
438
|
-
* trace to notice.
|
|
439
|
-
*
|
|
440
|
-
* `withheld` and `advisory` are disjoint by construction: under `enforce` every
|
|
441
|
-
* detection withheld, under `advisory` none did. Reporting them as separate
|
|
442
|
-
* lists rather than one flagged list means a consumer counting withheld
|
|
443
|
-
* 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.
|
|
444
281
|
*
|
|
445
282
|
* @param {Array<object>} footprintWithholds The kernel's complete ledger.
|
|
446
283
|
* @param {'enforce'|'advisory'} mode
|
|
@@ -468,10 +305,6 @@ export function buildFootprintGuardReport(footprintWithholds, mode) {
|
|
|
468
305
|
}
|
|
469
306
|
|
|
470
307
|
/**
|
|
471
|
-
* Render the operator-facing note for the beat-local guard, naming the
|
|
472
|
-
* colliding path(s) for every entry. `null` when the guard neither withheld nor
|
|
473
|
-
* waved anything through.
|
|
474
|
-
*
|
|
475
308
|
* @param {object[]} beat
|
|
476
309
|
* @param {object[]} advisory
|
|
477
310
|
* @param {string} mode
|
|
@@ -507,9 +340,7 @@ function footprintGuardNote(beat, advisory, mode) {
|
|
|
507
340
|
}
|
|
508
341
|
|
|
509
342
|
/**
|
|
510
|
-
*
|
|
511
|
-
* present. Neither class is a failure or a wedge, but they clear by different
|
|
512
|
-
* events, so each names its own.
|
|
343
|
+
* One sentence per reason class present; they clear by different events.
|
|
513
344
|
*
|
|
514
345
|
* @param {Array<{id: number, blockedBy: number, reason: string}>} withheld
|
|
515
346
|
* @returns {string}
|
|
@@ -544,14 +375,8 @@ function reservationNote(withheld) {
|
|
|
544
375
|
}
|
|
545
376
|
|
|
546
377
|
/**
|
|
547
|
-
*
|
|
548
|
-
*
|
|
549
|
-
* Each entry must carry `{ id, dependsOn }`. An optional `files` string
|
|
550
|
-
* array (the canonical footprint shape) is preserved and forwarded to the
|
|
551
|
-
* ready-set core so the file-overlap co-dispatch guard the Epic path uses is
|
|
552
|
-
* genuinely active on the standalone path too: two ready Stories that
|
|
553
|
-
* declare an intersecting footprint are never dispatched onto parallel
|
|
554
|
-
* `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.
|
|
555
380
|
*
|
|
556
381
|
* @param {unknown} raw Parsed JSON value from --dag or --dag-file.
|
|
557
382
|
* @returns {{ nodes: Array<{id: number, dependsOn: number[], files?: string[]}>, error: string|null }}
|
|
@@ -614,14 +439,8 @@ export function parseDag(raw) {
|
|
|
614
439
|
}
|
|
615
440
|
|
|
616
441
|
/**
|
|
617
|
-
* Parse a
|
|
618
|
-
*
|
|
619
|
-
* empty set. Rejects any token that is not a positive integer or a valid
|
|
620
|
-
* range, so a typo never silently drops a dependency gate (`--done`) or a
|
|
621
|
-
* held dispatch slot (`--dispatched`).
|
|
622
|
-
*
|
|
623
|
-
* Ranges are accepted here for the same reason `--stories` accepts them: an
|
|
624
|
-
* 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.
|
|
625
444
|
*
|
|
626
445
|
* @param {string|undefined} raw
|
|
627
446
|
* @param {string} flag Flag name, for the error message.
|
|
@@ -633,8 +452,6 @@ export function parseIdCsv(raw, flag) {
|
|
|
633
452
|
}
|
|
634
453
|
|
|
635
454
|
/**
|
|
636
|
-
* Parse the `--done` CSV of already-completed Story IDs (flag mode).
|
|
637
|
-
*
|
|
638
455
|
* @param {string|undefined} raw
|
|
639
456
|
* @returns {{ ids: Set<number>|null, error: string|null }}
|
|
640
457
|
*/
|
|
@@ -643,10 +460,7 @@ export function parseDoneIds(raw) {
|
|
|
643
460
|
}
|
|
644
461
|
|
|
645
462
|
/**
|
|
646
|
-
*
|
|
647
|
-
* input defaults to 0. Rejects negatives and non-integers.
|
|
648
|
-
*
|
|
649
|
-
* @param {unknown} raw
|
|
463
|
+
* @param {unknown} raw Absent defaults to 0.
|
|
650
464
|
* @returns {{ value: number|null, error: string|null }}
|
|
651
465
|
*/
|
|
652
466
|
export function parseInFlight(raw) {
|
|
@@ -664,20 +478,12 @@ export function parseInFlight(raw) {
|
|
|
664
478
|
}
|
|
665
479
|
|
|
666
480
|
/**
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
* preference; this is a safety floor, so it outranks even an explicit
|
|
670
|
-
* `--concurrency`. Why the two are coupled, and why the clamp is never silent:
|
|
671
|
-
* ADR `20260917-5357` in `docs/decisions.md`.
|
|
481
|
+
* Cap when worktree isolation resolves off — a safety floor, so it outranks
|
|
482
|
+
* even an explicit `--concurrency`.
|
|
672
483
|
*/
|
|
673
484
|
export const WORKTREE_DISABLED_CONCURRENCY_CAP = 1;
|
|
674
485
|
|
|
675
486
|
/**
|
|
676
|
-
* Validate a raw `--concurrency` value into a positive integer.
|
|
677
|
-
*
|
|
678
|
-
* Accepts a number or a numeric string (from the CLI). Rejects anything that
|
|
679
|
-
* is not a positive integer (zero, negative, fractional, non-numeric).
|
|
680
|
-
*
|
|
681
487
|
* @param {unknown} raw
|
|
682
488
|
* @returns {{ value: number|null, error: string|null }}
|
|
683
489
|
*/
|
|
@@ -696,63 +502,28 @@ export function parseConcurrencyOverride(raw) {
|
|
|
696
502
|
}
|
|
697
503
|
|
|
698
504
|
/**
|
|
699
|
-
* Resolve the per-beat concurrency cap.
|
|
700
|
-
*
|
|
701
|
-
* Mirrors the `/mandrel-deliver` multi-Story seam (`helpers/deliver-story.md`): resolve the
|
|
702
|
-
* project config (which deep-merges `.agentrc.local.json` over `.agentrc.json`)
|
|
703
|
-
* then read `delivery.deliverRunner.concurrencyCap` via `getRunners` (default
|
|
704
|
-
* 3). An explicit `override` (the `--concurrency <n>` CLI flag) wins over
|
|
705
|
-
* config for that run only.
|
|
706
|
-
*
|
|
707
505
|
* @param {object} [opts]
|
|
708
|
-
* @param {string} [opts.cwd]
|
|
709
|
-
* @param {object} [opts.config]
|
|
710
|
-
*
|
|
711
|
-
* @param {
|
|
712
|
-
*
|
|
713
|
-
* the worktree-isolation floor clamps it.
|
|
714
|
-
* @param {NodeJS.ProcessEnv} [opts.env] Environment (test injection).
|
|
715
|
-
* @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}
|
|
716
511
|
*/
|
|
717
512
|
export function resolveConcurrencyCap(opts = {}) {
|
|
718
513
|
return resolveCapPrecedence(opts).cap;
|
|
719
514
|
}
|
|
720
515
|
|
|
721
516
|
/**
|
|
722
|
-
* Resolve the per-beat cap
|
|
723
|
-
*
|
|
724
|
-
*
|
|
725
|
-
*
|
|
726
|
-
* is the intended contract — a flag an operator typed for one run should not be
|
|
727
|
-
* outranked by a checked-in default. What was wrong is that it won *silently*:
|
|
728
|
-
* the envelope reported a single `concurrencyCap` number with no record of
|
|
729
|
-
* which source set it, so a run at 8 when the project configured 3 was
|
|
730
|
-
* indistinguishable from a project configured at 8. A reader could not tell an
|
|
731
|
-
* override from a default, and an override that ran the repo above its own
|
|
732
|
-
* configured ceiling left no trace at all.
|
|
733
|
-
*
|
|
734
|
-
* So the flag still wins, but never quietly: the source is named, the
|
|
735
|
-
* configured value is carried alongside the requested one, and a request that
|
|
736
|
-
* exceeds the configured cap is called out as such. Reporting rather than
|
|
737
|
-
* refusing is deliberate — the configured cap is a project default, not a
|
|
738
|
-
* safety limit, and refusing a deliberate operator escalation would trade a
|
|
739
|
-
* silent override for a silent stall.
|
|
740
|
-
*
|
|
741
|
-
* **The one exception (Story #5357).** When worktree isolation resolves off,
|
|
742
|
-
* the cap is clamped to {@link WORKTREE_DISABLED_CONCURRENCY_CAP} and the
|
|
743
|
-
* clamp outranks the flag. That is not a reversal of the paragraph above: the
|
|
744
|
-
* configured cap is a preference and a flag may outrank a preference, but a
|
|
745
|
-
* shared checkout is not a preference at all. Dispatching two workers into one
|
|
746
|
-
* working tree corrupts the run whatever number either source asked for, so
|
|
747
|
-
* the floor wins — loudly, per {@link resolveWorktreeClamp}.
|
|
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.
|
|
748
521
|
*
|
|
749
522
|
* @param {object} [opts]
|
|
750
|
-
* @param {string} [opts.cwd]
|
|
523
|
+
* @param {string} [opts.cwd]
|
|
751
524
|
* @param {object} [opts.config] Pre-resolved config (test injection).
|
|
752
|
-
* @param {number} [opts.override] Validated
|
|
753
|
-
*
|
|
754
|
-
* @param {NodeJS.ProcessEnv} [opts.env] Environment the worktree-isolation
|
|
755
|
-
* rules read (test injection).
|
|
525
|
+
* @param {number} [opts.override] Validated `--concurrency`.
|
|
526
|
+
* @param {NodeJS.ProcessEnv} [opts.env]
|
|
756
527
|
* @returns {{
|
|
757
528
|
* cap: number,
|
|
758
529
|
* source: 'flag'|'config'|'worktree-clamp',
|
|
@@ -792,37 +563,17 @@ export function resolveCapPrecedence({ cwd, config, override, env } = {}) {
|
|
|
792
563
|
}
|
|
793
564
|
|
|
794
565
|
/**
|
|
795
|
-
* Apply the worktree-isolation
|
|
796
|
-
*
|
|
797
|
-
*
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
* and `delivery.worktreeIsolation.enabled: false` are the others and are
|
|
801
|
-
* exactly as unsafe — so this reads {@link resolveWorktreeEnabled}'s result and
|
|
802
|
-
* all three are covered by construction rather than by enumeration.
|
|
803
|
-
*
|
|
804
|
-
* **The config is normalised through `getWorktreeIsolation` first**, and that
|
|
805
|
-
* is load-bearing. `resolveWorktreeEnabled` reads
|
|
806
|
-
* `Boolean(config.delivery.worktreeIsolation.enabled)` raw, so a config that
|
|
807
|
-
* simply omits the block — every test-injected partial, and any consumer who
|
|
808
|
-
* never wrote one — reads `Boolean(undefined) === false` and would be clamped
|
|
809
|
-
* as though an operator had disabled isolation. `getWorktreeIsolation` applies
|
|
810
|
-
* the framework default (`enabled: true`) the same way `resolveConfig` does for
|
|
811
|
-
* a real `.agentrc`, so the clamp fires on a deliberate off, never on an
|
|
812
|
-
* absent key.
|
|
813
|
-
*
|
|
814
|
-
* The record is emitted whenever isolation is off, **including when the
|
|
815
|
-
* requested cap was already 1**: the point is that the run's sequentiality is
|
|
816
|
-
* always attributable to the reason that forced it, not left to coincide with
|
|
817
|
-
* a preference that happened to agree.
|
|
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.
|
|
818
571
|
*
|
|
819
572
|
* @param {object} args
|
|
820
573
|
* @param {{cap: number, source: string, configuredCap: number, requestedCap: number|null, exceedsConfigured: boolean, note: string}} args.requested
|
|
821
|
-
*
|
|
822
|
-
* @param {
|
|
823
|
-
* @
|
|
824
|
-
* @returns {typeof args.requested} The record unchanged when isolation is on,
|
|
825
|
-
* or the clamped record naming `worktree-clamp` as the winning source.
|
|
574
|
+
* @param {object|null} [args.config]
|
|
575
|
+
* @param {NodeJS.ProcessEnv} [args.env]
|
|
576
|
+
* @returns {typeof args.requested}
|
|
826
577
|
*/
|
|
827
578
|
export function resolveWorktreeClamp({ requested, config, env } = {}) {
|
|
828
579
|
const worktreeEnabled = resolveWorktreeEnabled(
|
|
@@ -842,27 +593,19 @@ export function resolveWorktreeClamp({ requested, config, env } = {}) {
|
|
|
842
593
|
source: 'worktree-clamp',
|
|
843
594
|
configuredCap: requested.configuredCap,
|
|
844
595
|
requestedCap: requested.cap,
|
|
845
|
-
// The
|
|
846
|
-
// asked for — the escalation never took effect and must not be reported
|
|
847
|
-
// as though it had.
|
|
596
|
+
// The escalation never took effect.
|
|
848
597
|
exceedsConfigured: false,
|
|
849
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.`,
|
|
850
599
|
};
|
|
851
600
|
}
|
|
852
601
|
|
|
853
602
|
/**
|
|
854
|
-
*
|
|
855
|
-
*
|
|
856
|
-
*
|
|
857
|
-
* `tempRoot` is threaded rather than hardcoded because the evidence scrape must
|
|
858
|
-
* exclude the project's *configured* scratch root: a consumer that sets
|
|
859
|
-
* `project.paths.tempRoot: '.scratch'` would otherwise have every sibling
|
|
860
|
-
* citing a report under it collide, which is the exact defect this Story
|
|
861
|
-
* 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.
|
|
862
605
|
*
|
|
863
606
|
* @param {object} [opts]
|
|
864
|
-
* @param {string} [opts.cwd]
|
|
865
|
-
* @param {object} [opts.config]
|
|
607
|
+
* @param {string} [opts.cwd]
|
|
608
|
+
* @param {object} [opts.config]
|
|
866
609
|
* @returns {{ footprintGuard: 'enforce'|'advisory', tempRoot: string }}
|
|
867
610
|
*/
|
|
868
611
|
export function resolveFootprintGuardSettings({ cwd, config } = {}) {
|
|
@@ -874,32 +617,18 @@ export function resolveFootprintGuardSettings({ cwd, config } = {}) {
|
|
|
874
617
|
}
|
|
875
618
|
|
|
876
619
|
/**
|
|
877
|
-
* Build the per-beat
|
|
878
|
-
*
|
|
879
|
-
* Maps each operator-DAG node onto a Story record the ready-set core
|
|
880
|
-
* understands (`{ id, dependsOn }`), tags any node already in the done set
|
|
881
|
-
* as `agent::done` so the core's classifier excludes it from the dispatch
|
|
882
|
-
* set **and** counts it as a satisfied dependency, then delegates the
|
|
883
|
-
* scheduling decision to `planReadySet`. A cyclic operator DAG is a
|
|
884
|
-
* planning error (the core would silently never schedule the cycle), so we
|
|
885
|
-
* detect it up front via the shared `detectCycle` kernel and short-circuit
|
|
886
|
-
* 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.
|
|
887
622
|
*
|
|
888
623
|
* @param {Array<{id: number, dependsOn: number[]}>} nodes
|
|
889
624
|
* @param {object} args
|
|
890
|
-
* @param {number} args.concurrencyCap
|
|
891
|
-
* @param {object|null} [args.capPrecedence]
|
|
892
|
-
*
|
|
893
|
-
* @param {
|
|
894
|
-
* @param {
|
|
895
|
-
*
|
|
896
|
-
*
|
|
897
|
-
* merely counting them (Story #4950). `null` (flag mode) means reservation
|
|
898
|
-
* is structurally unavailable — see {@link buildReservationReport}.
|
|
899
|
-
* @param {number[]} [args.foreignHeldIds] Ids among `inFlightRecords` that a
|
|
900
|
-
* **foreign operator's lease** holds rather than this run's own earlier
|
|
901
|
-
* beat, so a withholding against one is reported for what it is
|
|
902
|
-
* (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.
|
|
903
632
|
* @returns {{
|
|
904
633
|
* envelope: {
|
|
905
634
|
* kind: 'stories-ready-set',
|
|
@@ -932,21 +661,13 @@ export function buildReadySetEnvelope(
|
|
|
932
661
|
ready: [],
|
|
933
662
|
totalStories,
|
|
934
663
|
concurrencyCap,
|
|
935
|
-
//
|
|
936
|
-
//
|
|
937
|
-
// 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.
|
|
938
666
|
capPrecedence,
|
|
939
667
|
inFlight,
|
|
940
668
|
cycleError: null,
|
|
941
669
|
wedged: null,
|
|
942
|
-
// Whether this beat could reserve the in-flight Stories' footprints, and
|
|
943
|
-
// which Stories a reservation withheld (Story #4950). Never omitted on a
|
|
944
|
-
// resolved beat: an absent report reads exactly like an empty one.
|
|
945
670
|
inFlightReservation: buildReservationReport(inFlightRecords, []),
|
|
946
|
-
// The beat-local half of the same guard, plus the mode it ran in (Story
|
|
947
|
-
// #5044). Also never omitted: a same-beat skip used to be reported nowhere
|
|
948
|
-
// at all, which is precisely how an evidence-widening artifact could
|
|
949
|
-
// serialize a whole run unnoticed.
|
|
950
671
|
footprintGuard: buildFootprintGuardReport([], footprintGuard),
|
|
951
672
|
};
|
|
952
673
|
|
|
@@ -954,10 +675,7 @@ export function buildReadySetEnvelope(
|
|
|
954
675
|
return { envelope: base, exitCode: 0 };
|
|
955
676
|
}
|
|
956
677
|
|
|
957
|
-
//
|
|
958
|
-
// operator must fix. dropForeign:false preserves the operator-DAG contract
|
|
959
|
-
// (a dependency on an id outside the supplied set is honored, not pruned),
|
|
960
|
-
// matching the same builder seam planReadySet uses internally.
|
|
678
|
+
// dropForeign:false: a dependency outside the supplied set is honored.
|
|
961
679
|
const adjacency = buildStoryAdjacency(nodes, { dropForeign: false });
|
|
962
680
|
const cycle = detectCycle(adjacency);
|
|
963
681
|
if (cycle) {
|
|
@@ -970,26 +688,16 @@ export function buildReadySetEnvelope(
|
|
|
970
688
|
};
|
|
971
689
|
}
|
|
972
690
|
|
|
973
|
-
//
|
|
974
|
-
//
|
|
975
|
-
//
|
|
976
|
-
// 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.
|
|
977
694
|
const records = nodes.map((node) => {
|
|
978
695
|
const rec = {
|
|
979
696
|
id: node.id,
|
|
980
697
|
dependsOn: node.dependsOn,
|
|
981
|
-
// A node's own live labels (probe mode) are preserved so the core's
|
|
982
|
-
// classifier withholds an in-flight `agent::executing` / `agent::closing`
|
|
983
|
-
// Story rather than re-dispatching it onto a second branch. Flag-mode
|
|
984
|
-
// nodes carry none — `parseDag` accepts no labels — so this is inert
|
|
985
|
-
// there and the legacy contract is unchanged.
|
|
986
698
|
labels: doneIds.has(node.id) ? [AGENT_LABELS.DONE] : (node.labels ?? []),
|
|
987
699
|
};
|
|
988
700
|
if (node.files !== undefined) rec.files = node.files;
|
|
989
|
-
// Probe-mode nodes carry the Story body so the overlap guard can widen a
|
|
990
|
-
// declared footprint from the paths the Story's own text names (Story
|
|
991
|
-
// #4875). Flag-mode nodes carry none — `parseDag` accepts no body — so
|
|
992
|
-
// this is inert there and the legacy contract is unchanged.
|
|
993
701
|
if (typeof node.body === 'string') rec.body = node.body;
|
|
994
702
|
return rec;
|
|
995
703
|
});
|
|
@@ -999,17 +707,11 @@ export function buildReadySetEnvelope(
|
|
|
999
707
|
doneIds,
|
|
1000
708
|
inFlight,
|
|
1001
709
|
globalCap: concurrencyCap,
|
|
1002
|
-
// Flag mode has no in-flight records at all; `?? []` keeps the kernel's
|
|
1003
|
-
// contract (an array) while `base.inFlightReservation` reports that the
|
|
1004
|
-
// reservation itself was unavailable rather than merely empty.
|
|
1005
710
|
inFlightRecords: inFlightRecords ?? [],
|
|
1006
711
|
footprintGuard,
|
|
1007
712
|
tempRoot,
|
|
1008
713
|
});
|
|
1009
714
|
const ready = selected.map((rec) => rec.id);
|
|
1010
|
-
// The cross-beat report reads the enforced in-flight slice of the kernel's
|
|
1011
|
-
// ledger rather than the legacy `withheldByInFlight` list, so it carries the
|
|
1012
|
-
// colliding paths and the overlap source through to the operator.
|
|
1013
715
|
const reservation = buildReservationReport(
|
|
1014
716
|
inFlightRecords,
|
|
1015
717
|
footprintWithholds.filter(
|
|
@@ -1019,17 +721,6 @@ export function buildReadySetEnvelope(
|
|
|
1019
721
|
);
|
|
1020
722
|
const guardReport = buildFootprintGuardReport(footprintWithholds, guardMode);
|
|
1021
723
|
|
|
1022
|
-
// Wedge detection (Story #4540). `ready: []` is normal while work is in
|
|
1023
|
-
// flight — the loop is simply waiting. But ready-empty AND nothing in
|
|
1024
|
-
// flight AND undone Stories remaining means no beat can ever make
|
|
1025
|
-
// progress: the run is stuck, and the previous behaviour was to return
|
|
1026
|
-
// exit 0 with an empty ready set forever, indistinguishable from
|
|
1027
|
-
// "waiting". Name the stuck ids and their unmet blockers.
|
|
1028
|
-
//
|
|
1029
|
-
// Distinct from `cycleError`/exit 2: a cycle is a self-referential DAG,
|
|
1030
|
-
// whereas this is a DAG whose gates are real but unsatisfiable from the
|
|
1031
|
-
// supplied `done` set (typically a blocker outside the delivered set that
|
|
1032
|
-
// has not landed).
|
|
1033
724
|
const wedge = detectWedge({ nodes, doneIds, ready, inFlight });
|
|
1034
725
|
if (wedge) {
|
|
1035
726
|
return {
|
|
@@ -1075,9 +766,7 @@ export function detectWedge({ nodes, doneIds, ready, inFlight }) {
|
|
|
1075
766
|
}))
|
|
1076
767
|
.filter((s) => s.unmetBlockers.length > 0);
|
|
1077
768
|
|
|
1078
|
-
// Undone work with no unmet blockers
|
|
1079
|
-
// is the whole set, the cap or in-flight accounting explains the empty
|
|
1080
|
-
// ready set rather than a wedge.
|
|
769
|
+
// Undone work with no unmet blockers is capacity-limited, not wedged.
|
|
1081
770
|
if (stories.length === 0) return null;
|
|
1082
771
|
|
|
1083
772
|
const detail = stories
|
|
@@ -1093,22 +782,17 @@ export function detectWedge({ nodes, doneIds, ready, inFlight }) {
|
|
|
1093
782
|
}
|
|
1094
783
|
|
|
1095
784
|
/**
|
|
1096
|
-
*
|
|
1097
|
-
* compute the per-beat ready set via the shared scheduling core.
|
|
1098
|
-
*
|
|
1099
|
-
* Exported for unit tests; the CLI `main` function is a thin wrapper. Tests
|
|
1100
|
-
* inject `config` so they never depend on a real `.agentrc`.
|
|
785
|
+
* Flag-mode beat.
|
|
1101
786
|
*
|
|
1102
787
|
* @param {object} args
|
|
1103
|
-
* @param {string} [args.dagJson]
|
|
1104
|
-
* @param {string} [args.dagFile]
|
|
1105
|
-
* @param {string|number} [args.concurrency]
|
|
1106
|
-
* @param {string} [args.done]
|
|
1107
|
-
* @param {string|number} [args.inFlight]
|
|
1108
|
-
* @param {string} [args.cwd]
|
|
1109
|
-
* @param {object} [args.config]
|
|
1110
|
-
* @param {NodeJS.ProcessEnv} [args.env]
|
|
1111
|
-
* clamp reads (test injection).
|
|
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]
|
|
1112
796
|
* @returns {{
|
|
1113
797
|
* envelope: {kind: string, ready: number[], totalStories: number, concurrencyCap: number, inFlight: number, cycleError: string|null},
|
|
1114
798
|
* exitCode: number
|
|
@@ -1124,8 +808,6 @@ export function runStoriesWaveTick({
|
|
|
1124
808
|
config,
|
|
1125
809
|
env,
|
|
1126
810
|
} = {}) {
|
|
1127
|
-
// Validate the --concurrency override before resolving config so an invalid
|
|
1128
|
-
// value fails fast with exit code 1 regardless of DAG validity.
|
|
1129
811
|
const { value: override, error: concurrencyError } =
|
|
1130
812
|
parseConcurrencyOverride(concurrency);
|
|
1131
813
|
if (concurrencyError) {
|
|
@@ -1194,41 +876,22 @@ export function runStoriesWaveTick({
|
|
|
1194
876
|
}
|
|
1195
877
|
|
|
1196
878
|
/**
|
|
1197
|
-
* Probe
|
|
1198
|
-
*
|
|
1199
|
-
*
|
|
1200
|
-
*
|
|
1201
|
-
* asked to deliver; `done` and `inFlight` are probed rather than transcribed,
|
|
1202
|
-
* which is what makes the `/mandrel-deliver` loop's old seed-the-first-beat footgun
|
|
1203
|
-
* structurally impossible instead of merely documented.
|
|
1204
|
-
*
|
|
1205
|
-
* The envelope is the flag mode's, plus three probe-only fields the caller can
|
|
1206
|
-
* no longer compute for itself:
|
|
1207
|
-
* - `done` — the resolved done set (in-set ∪ satisfied foreign blockers).
|
|
1208
|
-
* - `epilogueDue` — true exactly when every listed Story is done, which is
|
|
1209
|
-
* the run-end signal for `plan-run-epilogue.js`.
|
|
1210
|
-
* - `blocked` — ids carrying `agent::blocked` (Story #4601). Non-empty means
|
|
1211
|
-
* the loop must END, not poll: see `BLOCKED_EXIT_CODE`.
|
|
1212
|
-
* - `stalledDispatch` — `--dispatched` ids live state still reports as
|
|
1213
|
-
* `agent::ready`. They stay withheld; the field exists so a caller keeping
|
|
1214
|
-
* an append-only dispatched list can see an id that is pinned rather than
|
|
1215
|
-
* merely initializing (Story #5363).
|
|
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).
|
|
1216
883
|
*
|
|
1217
884
|
* @param {object} args
|
|
1218
|
-
* @param {string} args.stories
|
|
1219
|
-
* @param {string|number} [args.concurrency]
|
|
1220
|
-
* @param {string} [args.dispatched]
|
|
1221
|
-
*
|
|
1222
|
-
* @param {
|
|
1223
|
-
* @param {
|
|
1224
|
-
* @param {
|
|
1225
|
-
*
|
|
1226
|
-
* @param {Function} [args.probe] Probe seam (test injection).
|
|
1227
|
-
* @param {Function} [args.context] Provider-context seam (test injection).
|
|
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.
|
|
1228
893
|
* @returns {Promise<{ envelope: object, exitCode: number, records: object[] }>}
|
|
1229
|
-
* `records` are the probed nodes
|
|
1230
|
-
* bodies this beat already fetched, handed to the caller beside the envelope
|
|
1231
|
-
* rather than serialized into it.
|
|
894
|
+
* `records` are the probed nodes, kept off stdout.
|
|
1232
895
|
*/
|
|
1233
896
|
export async function runProbedStoriesWaveTick({
|
|
1234
897
|
stories,
|
|
@@ -1277,9 +940,7 @@ export async function runProbedStoriesWaveTick({
|
|
|
1277
940
|
warn: (m) => Logger.warn(m),
|
|
1278
941
|
});
|
|
1279
942
|
} catch (err) {
|
|
1280
|
-
//
|
|
1281
|
-
// indistinguishable from a healthy waiting beat and would silently stall
|
|
1282
|
-
// the run. Fail loud with the input-error contract instead.
|
|
943
|
+
// Never degrade into "nothing is ready": that reads as a healthy wait.
|
|
1283
944
|
return inputErrorResult(
|
|
1284
945
|
`Could not probe live state: ${err?.message ?? err}`,
|
|
1285
946
|
concurrencyCap,
|
|
@@ -1300,11 +961,7 @@ export async function runProbedStoriesWaveTick({
|
|
|
1300
961
|
capPrecedence,
|
|
1301
962
|
doneIds,
|
|
1302
963
|
inFlight,
|
|
1303
|
-
// Probe mode is the only mode that HAS the in-flight Stories' records, so
|
|
1304
|
-
// it is the only mode that can reserve their footprints (Story #4950).
|
|
1305
964
|
inFlightRecords,
|
|
1306
|
-
// ...and the only mode that can tell a foreign lease-holder apart from
|
|
1307
|
-
// this run's own earlier-beat dispatch (Story #4960).
|
|
1308
965
|
foreignHeldIds: foreignHeld.map((h) => h.id),
|
|
1309
966
|
...resolveFootprintGuardSettings({ cwd, config }),
|
|
1310
967
|
});
|
|
@@ -1319,29 +976,13 @@ export async function runProbedStoriesWaveTick({
|
|
|
1319
976
|
epilogueDue,
|
|
1320
977
|
blocked: blockedIds,
|
|
1321
978
|
blockedReason: blockedReasonFor(blockedIds),
|
|
1322
|
-
// Ids the caller listed in `--dispatched` that live state still reports
|
|
1323
|
-
// as `agent::ready`. Withheld as in flight (that is the flag's whole
|
|
1324
|
-
// job) and named here, because the same reading covers a healthy init
|
|
1325
|
-
// window and a spawn that died before init — and only the caller, who
|
|
1326
|
-
// owns the dispatched list, can tell those apart (Story #5363).
|
|
1327
979
|
stalledDispatch,
|
|
1328
|
-
// Stories another operator's lease holds — withheld from dispatch this
|
|
1329
|
-
// beat (folded into in-flight) and surfaced so the run can report
|
|
1330
|
-
// "#<id> held by @<holder>" instead of dispatching into an init refusal.
|
|
1331
980
|
foreignHeld,
|
|
1332
981
|
foreignHeldReason: foreignHeldReasonFor(foreignHeld),
|
|
1333
982
|
},
|
|
1334
|
-
// The probed nodes, beside the envelope rather than inside it. The
|
|
1335
|
-
// envelope is a list of ids by design — a Story body is several KB and has
|
|
1336
|
-
// no business on stdout — but the probe has already fetched every body,
|
|
1337
|
-
// and the one caller that needs them (`deliver-run.js`, building each
|
|
1338
|
-
// ready Story's dispatch prompt from its declared `changes[]`) would
|
|
1339
|
-
// otherwise re-fetch the whole set to read what this beat already holds.
|
|
1340
983
|
records: nodes,
|
|
1341
|
-
//
|
|
1342
|
-
//
|
|
1343
|
-
// A cycle (2) does not yield: a self-referential DAG is a planning error
|
|
1344
|
-
// that must be fixed before any of this run's state means anything.
|
|
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.
|
|
1345
986
|
exitCode:
|
|
1346
987
|
blockedIds.length > 0 && !envelope.cycleError
|
|
1347
988
|
? BLOCKED_EXIT_CODE
|
|
@@ -1350,9 +991,6 @@ export async function runProbedStoriesWaveTick({
|
|
|
1350
991
|
}
|
|
1351
992
|
|
|
1352
993
|
/**
|
|
1353
|
-
* Render the operator-facing reason for a blocked run, or `null` when nothing
|
|
1354
|
-
* is blocked.
|
|
1355
|
-
*
|
|
1356
994
|
* @param {number[]} blockedIds
|
|
1357
995
|
* @returns {string|null}
|
|
1358
996
|
*/
|
|
@@ -1369,14 +1007,6 @@ function blockedReasonFor(blockedIds) {
|
|
|
1369
1007
|
}
|
|
1370
1008
|
|
|
1371
1009
|
/**
|
|
1372
|
-
* Render the operator-facing note for Stories held by another operator's
|
|
1373
|
-
* lease, or `null` when none are held.
|
|
1374
|
-
*
|
|
1375
|
-
* These are not errors and not a wedge: the holder's run is progressing
|
|
1376
|
-
* normally, this run simply must not join it on the same branch. The Story
|
|
1377
|
-
* stays withheld and re-probes each beat, so it dispatches on its own the
|
|
1378
|
-
* moment the holder's lease clears (their run lands or is stolen).
|
|
1379
|
-
*
|
|
1380
1010
|
* @param {Array<{id: number, holder: string}>} foreignHeld
|
|
1381
1011
|
* @returns {string|null}
|
|
1382
1012
|
*/
|