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
|
@@ -1,17 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* zero-or-more Story issues directly — no Epic parent, no reconciler tree,
|
|
6
|
-
* no `deliveryShape` mode matrix. Default is **one Story**; N>1 is gated by
|
|
7
|
-
* the supersede partition check.
|
|
8
|
-
*
|
|
9
|
-
* Each Story body is the single executable document: Tech Spec stays inline
|
|
10
|
-
* under `## Spec`, at whatever length the work needs (Story #5312 deleted
|
|
11
|
-
* the token budget that used to refuse it) — never spilled to `docs/`.
|
|
12
|
-
* Top-level `acceptance[]` / `verify[]` are the machine
|
|
13
|
-
* contract and are synced into the body so the GitHub issue stays complete
|
|
14
|
-
* without requiring the LLM to dual-author the same lists.
|
|
2
|
+
* Flat Story creation for plan-persist. Each Story body is the single
|
|
3
|
+
* executable document: the Spec stays inline at any length, and top-level
|
|
4
|
+
* `acceptance[]` / `verify[]` (the machine contract) are synced into it.
|
|
15
5
|
*
|
|
16
6
|
* @module lib/orchestration/plan-persist/story-ops
|
|
17
7
|
*/
|
|
@@ -39,33 +29,21 @@ import {
|
|
|
39
29
|
isExternalDependencyRef,
|
|
40
30
|
} from './external-deps.js';
|
|
41
31
|
import {
|
|
42
|
-
assertSupersedePartition,
|
|
43
32
|
normalizeSupersedes,
|
|
33
|
+
resolveSupersedePartition,
|
|
44
34
|
} from './supersede-ops.js';
|
|
45
35
|
|
|
46
36
|
/**
|
|
47
|
-
* Label prefix grouping the Stories one plan-persist run authored.
|
|
48
|
-
*
|
|
49
|
-
* Reintroduced (Story #4692) after Story #4540 retired it: #4540 was right
|
|
50
|
-
* that batch identity is the wrong axis for *ordering delivery across runs*
|
|
51
|
-
* (`/mandrel-deliver` takes ids and resolves the graph from live state — that stays),
|
|
52
|
-
* but it is the correct axis for *grouping the Stories one plan run created*
|
|
53
|
-
* so a cohort is filterable and traceable in the GitHub UI. The label is
|
|
54
|
-
* metadata only; nothing in persist or delivery reads it as a
|
|
55
|
-
* delivery-resolution input.
|
|
37
|
+
* Label prefix grouping the Stories one plan-persist run authored. Metadata
|
|
38
|
+
* only: delivery never reads it as an ordering input.
|
|
56
39
|
*/
|
|
57
40
|
export const PLAN_RUN_LABEL_PREFIX = 'plan-run::';
|
|
58
41
|
|
|
59
|
-
/** Stable color for the cohort grouping label (`ensureLabels`). */
|
|
60
42
|
const PLAN_RUN_LABEL_COLOR = '#C5DEF5';
|
|
61
43
|
|
|
62
|
-
/** Length of the derived plan-run id (hex chars). */
|
|
63
44
|
const PLAN_RUN_ID_LENGTH = 8;
|
|
64
45
|
|
|
65
46
|
/**
|
|
66
|
-
* Normalize a caller-supplied plan-run token. Kept shared so human-readable
|
|
67
|
-
* ids map to one canonical label shape.
|
|
68
|
-
*
|
|
69
47
|
* @param {string} id
|
|
70
48
|
* @returns {string}
|
|
71
49
|
*/
|
|
@@ -82,11 +60,8 @@ export function normalizePlanRunId(id) {
|
|
|
82
60
|
}
|
|
83
61
|
|
|
84
62
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* Unlike the pre-#4540 shape, this never mints a random token — a random id
|
|
88
|
-
* would split a resumed persist's cohort across two labels. Derive the id
|
|
89
|
-
* from the authored artifacts via {@link derivePlanRunId} instead.
|
|
63
|
+
* Never mints a random token — that would split a resumed persist's cohort
|
|
64
|
+
* across two labels; derive the id via {@link derivePlanRunId}.
|
|
90
65
|
*
|
|
91
66
|
* @param {string} id
|
|
92
67
|
* @returns {string}
|
|
@@ -96,19 +71,11 @@ export function planRunLabel(id) {
|
|
|
96
71
|
}
|
|
97
72
|
|
|
98
73
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* Hashes the **sorted** set of per-Story plan fingerprints (the same
|
|
102
|
-
* content identities the resumable-create contract adopts on), so the id is
|
|
103
|
-
* a pure function of the authored artifacts: the same `stories.json` yields
|
|
104
|
-
* the same `plan-run::<id>` on every run — a persist resumed after a
|
|
105
|
-
* mid-run failure applies the identical label to the newly-created
|
|
106
|
-
* remainder that the already-created (adopted) Stories carry — while a
|
|
107
|
-
* different plan derives a different label. Sorting makes the id
|
|
108
|
-
* independent of creation order.
|
|
74
|
+
* Hash of the sorted per-Story fingerprints, so a resumed persist derives the
|
|
75
|
+
* same label its adopted Stories already carry, independent of creation order.
|
|
109
76
|
*
|
|
110
|
-
* @param {string[]} fingerprints
|
|
111
|
-
* @returns {string}
|
|
77
|
+
* @param {string[]} fingerprints
|
|
78
|
+
* @returns {string}
|
|
112
79
|
*/
|
|
113
80
|
export function derivePlanRunId(fingerprints) {
|
|
114
81
|
const sorted = (Array.isArray(fingerprints) ? fingerprints : [])
|
|
@@ -121,59 +88,27 @@ export function derivePlanRunId(fingerprints) {
|
|
|
121
88
|
}
|
|
122
89
|
|
|
123
90
|
/**
|
|
124
|
-
* Marker prefix
|
|
125
|
-
*
|
|
126
|
-
* `<!-- plan-story: <fingerprint> -->` to decide whether a Story already
|
|
127
|
-
* exists — the idempotency half of the resumable-create contract.
|
|
91
|
+
* Marker prefix stamped into every created body; the resume path adopts an
|
|
92
|
+
* open Story whose marker matches.
|
|
128
93
|
*/
|
|
129
94
|
const PLAN_FINGERPRINT_MARKER_PREFIX = 'plan-story:';
|
|
130
95
|
|
|
131
|
-
/** Length of the hex fingerprint digest. Collision-free at plan scale. */
|
|
132
96
|
const PLAN_FINGERPRINT_LENGTH = 16;
|
|
133
97
|
|
|
134
98
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* resume path: a fingerprint hit means the open Story on the tracker is
|
|
141
|
-
* byte-identical to what this run would author, so adopting it instead of
|
|
142
|
-
* creating it is a genuine no-op.
|
|
143
|
-
*
|
|
144
|
-
* **Why the body is in scope.** It used to be excluded, on the rationale that
|
|
145
|
-
* creation rewrites the body to substitute real issue ids into `depends_on`
|
|
146
|
-
* footers, so a body-derived fingerprint would differ between an aborted run
|
|
147
|
-
* and its resume. That conflated two different bodies. The fingerprint is
|
|
148
|
-
* computed in `assembleOnePlanStory` over the *assembled* body — whose
|
|
149
|
-
* `depends_on` are still sibling **slugs**, and which is a pure function of
|
|
150
|
-
* `stories.json` plus the shared Spec. The id substitution happens later, and
|
|
151
|
-
* only inside `renderStoryBodyForCreate`, which produces the *posted* body.
|
|
152
|
-
* Nothing ever re-derives a fingerprint from a posted body; the lookup reads
|
|
153
|
-
* the marker that body carries. The assembled body is therefore stable across
|
|
154
|
-
* a run and its resume, and folding it in defeats no lookup.
|
|
155
|
-
*
|
|
156
|
-
* Excluding it cost two silent failures, both closed by this:
|
|
157
|
-
*
|
|
158
|
-
* 1. A later, unrelated plan that reused a slug **and** title adopted the
|
|
159
|
-
* stale open Story — never rewriting its body or Spec, and landing this
|
|
160
|
-
* run's checkpoints, ready-flip, and supersede comments on the wrong
|
|
161
|
-
* issue.
|
|
162
|
-
* 2. A legitimate resume after the operator edited `stories.json` adopted
|
|
163
|
-
* the pre-edit Story and kept its stale body, discarding the edit.
|
|
164
|
-
*
|
|
165
|
-
* With the body in scope both cases simply miss the lookup, and a correct new
|
|
166
|
-
* Story is created; only a genuinely identical Story is ever adopted.
|
|
99
|
+
* Content identity of one authored Story: slug + title + the *assembled* body
|
|
100
|
+
* (whose `depends_on` are still slugs, so it is stable across a run and its
|
|
101
|
+
* resume). A hit means the open Story is byte-identical to what this run
|
|
102
|
+
* would author; a reused slug/title or an edited `stories.json` misses and
|
|
103
|
+
* gets a fresh Story instead of a stale adoption.
|
|
167
104
|
*
|
|
168
105
|
* The fields are joined on NUL separators, written as the `\u0000` escape and
|
|
169
106
|
* never as a raw byte — a literal NUL would make git classify this file as
|
|
170
|
-
* binary and silently drop its diffs. NUL cannot occur in
|
|
171
|
-
*
|
|
172
|
-
* `{slug:'a', title:'b-c'}` cannot collide the way a hyphen or space separator
|
|
173
|
-
* would let them.
|
|
107
|
+
* binary and silently drop its diffs. NUL cannot occur in any field, so the
|
|
108
|
+
* join is unambiguous.
|
|
174
109
|
*
|
|
175
110
|
* @param {{ slug: string, title: string, body?: string }} story
|
|
176
|
-
* @returns {string}
|
|
111
|
+
* @returns {string}
|
|
177
112
|
*/
|
|
178
113
|
export function planStoryFingerprint({ slug, title, body = '' }) {
|
|
179
114
|
return createHash('sha256')
|
|
@@ -183,10 +118,6 @@ export function planStoryFingerprint({ slug, title, body = '' }) {
|
|
|
183
118
|
}
|
|
184
119
|
|
|
185
120
|
/**
|
|
186
|
-
* Render the HTML-comment marker carrying a Story's plan fingerprint. It is
|
|
187
|
-
* invisible in GitHub's rendered issue body and survives edits to every
|
|
188
|
-
* other section.
|
|
189
|
-
*
|
|
190
121
|
* @param {string} fingerprint
|
|
191
122
|
* @returns {string}
|
|
192
123
|
*/
|
|
@@ -194,16 +125,13 @@ function planFingerprintMarker(fingerprint) {
|
|
|
194
125
|
return `<!-- ${PLAN_FINGERPRINT_MARKER_PREFIX} ${fingerprint} -->`;
|
|
195
126
|
}
|
|
196
127
|
|
|
197
|
-
/** The one parser for the marker {@link planFingerprintMarker} renders. */
|
|
198
128
|
const PLAN_FINGERPRINT_MARKER_RE = new RegExp(
|
|
199
129
|
`<!--\\s*${PLAN_FINGERPRINT_MARKER_PREFIX}\\s*([0-9a-f]+)\\s*-->`,
|
|
200
130
|
);
|
|
201
131
|
|
|
202
132
|
/**
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
* resume index and the create-retry adoption probe) go through it so they can
|
|
206
|
-
* never drift into recognising different Stories as "already created".
|
|
133
|
+
* The single marker reader, shared by the resume index and the create-retry
|
|
134
|
+
* probe so they never disagree on "already created".
|
|
207
135
|
*
|
|
208
136
|
* @param {unknown} body
|
|
209
137
|
* @returns {string|null}
|
|
@@ -215,13 +143,8 @@ function extractPlanFingerprint(body) {
|
|
|
215
143
|
}
|
|
216
144
|
|
|
217
145
|
/**
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
* flip itself), `type::*` is fixed to `type::story` by the v2 hierarchy,
|
|
221
|
-
* `persona::*` and `route::*` are retired axes (the latter with the
|
|
222
|
-
* plan-side lite claim, Story #5312), and `plan-run::*` is the
|
|
223
|
-
* runtime-derived cohort grouping axis (Story #4692) — a hand-authored entry
|
|
224
|
-
* on it would compete with the deterministic label persist applies itself.
|
|
146
|
+
* Label axes the runtime owns (lifecycle, type, cohort) or has retired
|
|
147
|
+
* (persona, route); authored entries on them are dropped.
|
|
225
148
|
*/
|
|
226
149
|
const FORBIDDEN_LABEL_PREFIXES = Object.freeze([
|
|
227
150
|
'agent::',
|
|
@@ -235,17 +158,11 @@ const FORBIDDEN_LABEL_PREFIXES = Object.freeze([
|
|
|
235
158
|
const MAX_LABEL_LENGTH = 50;
|
|
236
159
|
|
|
237
160
|
/**
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
* The schema descriptor and the authoring prompt both ask for `labels[]`,
|
|
241
|
-
* but persist never read the field — it hard-coded its own list, so every
|
|
242
|
-
* authored label was silently discarded. Rather than keep asking for input
|
|
243
|
-
* that goes nowhere, apply it: drop the axes the runtime owns, drop
|
|
244
|
-
* malformed entries, dedupe, and always guarantee `type::story`.
|
|
161
|
+
* Drop runtime-owned and malformed labels, dedupe, and guarantee `type::story`.
|
|
245
162
|
*
|
|
246
163
|
* @param {unknown} rawLabels
|
|
247
|
-
* @param {string} slug
|
|
248
|
-
* @returns {string[]}
|
|
164
|
+
* @param {string} slug
|
|
165
|
+
* @returns {string[]}
|
|
249
166
|
*/
|
|
250
167
|
export function sanitizeAuthoredLabels(rawLabels, slug) {
|
|
251
168
|
const kept = new Set([TYPE_LABELS.STORY]);
|
|
@@ -306,10 +223,8 @@ function arraysEqual(a, b) {
|
|
|
306
223
|
}
|
|
307
224
|
|
|
308
225
|
/**
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
* When the body already lists the same items, keep them; when the body is
|
|
312
|
-
* empty, fill from top-level; when both disagree, fail closed.
|
|
226
|
+
* Sync a top-level contract field into the body; fail closed when both are
|
|
227
|
+
* set and disagree.
|
|
313
228
|
*
|
|
314
229
|
* @param {object} ticket
|
|
315
230
|
* @param {object} bodyObject
|
|
@@ -330,16 +245,8 @@ function syncContractFieldFromTopLevel(ticket, bodyObject, field) {
|
|
|
330
245
|
}
|
|
331
246
|
|
|
332
247
|
/**
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
* `supersedes[]` is a top-level-only field (Story #4535) — it is planning
|
|
337
|
-
* bookkeeping for the `--tickets` source issues, not part of the Story's
|
|
338
|
-
* executable body, so it is deliberately not serialized into the markdown.
|
|
339
|
-
*
|
|
340
|
-
* `provenance` is likewise top-level-only (Story #5045) — it names the audit
|
|
341
|
-
* identities *this* Story owns, and is stamped into the body as footers rather
|
|
342
|
-
* than serialized as a section.
|
|
248
|
+
* `supersedes[]` and `provenance` are top-level-only: planning bookkeeping and
|
|
249
|
+
* footer input respectively, never serialized as body sections.
|
|
343
250
|
*
|
|
344
251
|
* @param {object} ticket
|
|
345
252
|
* @returns {{ slug: string, title: string, bodyObject: object, depends_on: string[], labels: string[], supersedes: Array<{ id: number, note: string|null }>, provenance: { fingerprints: string[], semanticKeys: string[] }|null }}
|
|
@@ -386,11 +293,7 @@ export function normalizeStoryTicket(ticket) {
|
|
|
386
293
|
}
|
|
387
294
|
|
|
388
295
|
/**
|
|
389
|
-
*
|
|
390
|
-
* no inline Spec. Specs stay inline, verbatim, at any length.
|
|
391
|
-
*
|
|
392
|
-
* Precedence: per-Story `body.spec` wins; otherwise `sharedSpec` is used
|
|
393
|
-
* (N===1 convenience only — callers must not share one Spec across N>1).
|
|
296
|
+
* Per-Story `body.spec` wins; otherwise `sharedSpec` (N===1 only).
|
|
394
297
|
*
|
|
395
298
|
* @param {object} bodyObject
|
|
396
299
|
* @param {string} slug
|
|
@@ -424,25 +327,13 @@ export function foldSpecIntoStoryBody(bodyObject, slug, opts = {}) {
|
|
|
424
327
|
}
|
|
425
328
|
|
|
426
329
|
/**
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
* - **Attributed** — the Story authored a `provenance` field naming the audit
|
|
432
|
-
* identities *it* owns. Exactly those are stamped. This is what makes the
|
|
433
|
-
* footers answer "which Story tracks this finding?" instead of "which sweep
|
|
434
|
-
* planned it?": under the union every sibling carried every key, so the next
|
|
435
|
-
* sweep's confirmation pass could only pick an arbitrary open Story, and a
|
|
436
|
-
* key whose owner had since closed was masked by any open neighbour.
|
|
437
|
-
* - **Union fallback** — no `provenance` field, so the whole seed's footers are
|
|
438
|
-
* carried, exactly as before. This is **not** dead weight to be tidied away:
|
|
439
|
-
* hand-carried provenance is the failure Stories #4626 / #4877 measured, and
|
|
440
|
-
* the union is what closed it. Attribution is additive and recall-safe;
|
|
441
|
-
* deleting the fallback would re-open that hole for every plan that does not
|
|
442
|
-
* attribute.
|
|
330
|
+
* An authored `provenance` stamps exactly the identities this Story owns;
|
|
331
|
+
* otherwise the whole seed's footers are carried. Keep that union fallback:
|
|
332
|
+
* without it a non-attributing plan persists Stories with no provenance and
|
|
333
|
+
* the next audit sweep re-files planned work.
|
|
443
334
|
*
|
|
444
335
|
* @param {{ fingerprints: string[], semanticKeys: string[] }|null} provenance
|
|
445
|
-
* @param {object} opts
|
|
336
|
+
* @param {object} opts
|
|
446
337
|
* @returns {string}
|
|
447
338
|
*/
|
|
448
339
|
function resolveProvenanceSource(provenance, opts) {
|
|
@@ -463,17 +354,9 @@ function assembleOnePlanStory(ticket, opts) {
|
|
|
463
354
|
const { bodyObject: folded } = foldSpecIntoStoryBody(bodyObject, slug, {
|
|
464
355
|
sharedSpec: opts.sharedSpec ?? null,
|
|
465
356
|
});
|
|
466
|
-
// Body first: the fingerprint is an identity over the *assembled* content,
|
|
467
|
-
// so it cannot be computed until that content exists.
|
|
468
357
|
const serialized = serializeStoryBody({ ...folded, depends_on });
|
|
469
|
-
//
|
|
470
|
-
// audit
|
|
471
|
-
// `audit-semantic-keys` footers into the seed it hands `/mandrel-plan`; without this
|
|
472
|
-
// the persisted Story carries no provenance and the next sweep re-files work
|
|
473
|
-
// it already planned. Mechanical on purpose — the authoring agent is not
|
|
474
|
-
// asked to notice HTML comments in a one-pager. A non-audit seed carries no
|
|
475
|
-
// footers, so this is a no-op there. Which identities reach *this* Story is
|
|
476
|
-
// `resolveProvenanceSource`'s call (Story #5045).
|
|
358
|
+
// Mechanical on purpose: the authoring agent is not asked to hand-carry
|
|
359
|
+
// audit footers. A non-audit seed has none, so this is a no-op there.
|
|
477
360
|
const { body } = carryProvenanceFooters({
|
|
478
361
|
from: resolveProvenanceSource(provenance, opts),
|
|
479
362
|
into: serialized,
|
|
@@ -495,9 +378,6 @@ function assembleOnePlanStory(ticket, opts) {
|
|
|
495
378
|
}
|
|
496
379
|
|
|
497
380
|
/**
|
|
498
|
-
* Shared techspec.md is an N===1 convenience only — folding one Spec into
|
|
499
|
-
* every sibling duplicates approach prose and breaks Story-as-SSOT.
|
|
500
|
-
*
|
|
501
381
|
* @param {object[]} tickets
|
|
502
382
|
* @param {string|null|undefined} sharedSpec
|
|
503
383
|
*/
|
|
@@ -512,21 +392,16 @@ function assertSharedSpecAllowed(tickets, sharedSpec) {
|
|
|
512
392
|
}
|
|
513
393
|
|
|
514
394
|
/**
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
* plan never leaves Stories live against an inconsistent tracker. Story #5332
|
|
520
|
-
* retired the acceptance partition that used to run beside it: it refused
|
|
521
|
-
* only byte-identical acceptance text across siblings, and the split gate is
|
|
522
|
-
* now `assertNoWaveCollisions` in `run-plan-persist.js`, ahead of the first
|
|
523
|
-
* create.
|
|
395
|
+
* Normalize → fold spec → dependency-order → supersede partition, all before
|
|
396
|
+
* any GitHub write. The dependency sort runs here only, so `stories[0]` is the
|
|
397
|
+
* one primary Story every consumer sees; an unknown sibling or cycle fails
|
|
398
|
+
* this write-free pass.
|
|
524
399
|
*
|
|
525
400
|
* @param {object[]} tickets
|
|
526
401
|
* @param {object} [opts]
|
|
527
402
|
* @param {string|null} [opts.sharedSpec]
|
|
528
403
|
* @param {number[]} [opts.sourceTicketIds] Ids passed to `/mandrel-plan --tickets`.
|
|
529
|
-
* @returns {{ stories: Array<{ slug: string, title: string, body: string, acceptance: string[], depends_on: string[], supersedes: Array<{ id: number, note: string|null }> }
|
|
404
|
+
* @returns {{ stories: Array<{ slug: string, title: string, body: string, acceptance: string[], depends_on: string[], supersedes: Array<{ id: number, note: string|null }> }>, warnings: string[] }}
|
|
530
405
|
*/
|
|
531
406
|
export function assemblePlanStories(tickets, opts = {}) {
|
|
532
407
|
if (!Array.isArray(tickets) || tickets.length === 0) {
|
|
@@ -537,13 +412,16 @@ export function assemblePlanStories(tickets, opts = {}) {
|
|
|
537
412
|
|
|
538
413
|
assertSharedSpecAllowed(tickets, opts.sharedSpec);
|
|
539
414
|
|
|
540
|
-
const stories =
|
|
541
|
-
(ticket) => assembleOnePlanStory(ticket, opts).story,
|
|
415
|
+
const stories = orderStoriesByDependencies(
|
|
416
|
+
tickets.map((ticket) => assembleOnePlanStory(ticket, opts).story),
|
|
542
417
|
);
|
|
543
418
|
|
|
544
|
-
|
|
419
|
+
const warnings = resolveSupersedePartition(
|
|
420
|
+
stories,
|
|
421
|
+
opts.sourceTicketIds ?? [],
|
|
422
|
+
);
|
|
545
423
|
|
|
546
|
-
return { stories };
|
|
424
|
+
return { stories, warnings };
|
|
547
425
|
}
|
|
548
426
|
|
|
549
427
|
function orderStoriesByDependencies(stories) {
|
|
@@ -563,9 +441,8 @@ function orderStoriesByDependencies(stories) {
|
|
|
563
441
|
const scheduled = new Set();
|
|
564
442
|
const pending = [...list];
|
|
565
443
|
while (pending.length > 0) {
|
|
566
|
-
// External refs
|
|
567
|
-
//
|
|
568
|
-
// otherwise wedge the sort into a false cycle (Story #5155).
|
|
444
|
+
// External refs are already live, never "scheduled" here; counting them
|
|
445
|
+
// would wedge the sort into a false cycle.
|
|
569
446
|
const index = pending.findIndex((story) =>
|
|
570
447
|
story.depends_on
|
|
571
448
|
.filter((slug) => !isExternalDependencyRef(slug))
|
|
@@ -584,21 +461,9 @@ function orderStoriesByDependencies(stories) {
|
|
|
584
461
|
}
|
|
585
462
|
|
|
586
463
|
/**
|
|
587
|
-
* Index
|
|
588
|
-
*
|
|
589
|
-
*
|
|
590
|
-
* Two indexes come back. `byFingerprint` is the adoption key — an exact match
|
|
591
|
-
* on the authored content (see {@link planStoryFingerprint}). `idsByTitle` is
|
|
592
|
-
* only used to *warn*: it catches the near miss where a Story with this title
|
|
593
|
-
* is already open but its content differs, which is what an abandoned earlier
|
|
594
|
-
* plan or an edited `stories.json` leaves behind. Adoption deliberately does
|
|
595
|
-
* not key on it — a title is not an identity, and adopting on one would let a
|
|
596
|
-
* later unrelated plan overwrite someone else's Story.
|
|
597
|
-
*
|
|
598
|
-
* Best-effort by construction: a provider with no `listIssuesByLabel` (or a
|
|
599
|
-
* listing that errors) yields empty indexes and the create loop proceeds
|
|
600
|
-
* un-deduplicated, exactly as it did before. That degrades resume, not
|
|
601
|
-
* correctness of a first run — so it warns rather than throws.
|
|
464
|
+
* Index open Stories for resume. `byFingerprint` is the adoption key;
|
|
465
|
+
* `idsByTitle` only warns (a title is not an identity). Best-effort: a
|
|
466
|
+
* missing or failing listing degrades resume, not a first run, so it warns.
|
|
602
467
|
*
|
|
603
468
|
* @param {object} provider
|
|
604
469
|
* @returns {Promise<{
|
|
@@ -649,19 +514,9 @@ async function indexExistingStories(provider) {
|
|
|
649
514
|
}
|
|
650
515
|
|
|
651
516
|
/**
|
|
652
|
-
*
|
|
653
|
-
* issue,
|
|
654
|
-
*
|
|
655
|
-
* This is the probe `createIssue` calls before any retry POST (Story #5112).
|
|
656
|
-
* A create whose response was lost has already filed the issue; retrying
|
|
657
|
-
* blind duplicates it. Because the body posted carries the fingerprint
|
|
658
|
-
* marker, the same content-keyed lookup the resume path uses answers "did
|
|
659
|
-
* attempt 1 land?" authoritatively — from the server's state, not from a
|
|
660
|
-
* client-side guess about where the connection broke.
|
|
661
|
-
*
|
|
662
|
-
* Best-effort like {@link indexExistingStories}: a provider without the
|
|
663
|
-
* listing surface, or a listing that throws, yields `null` and the retry
|
|
664
|
-
* proceeds exactly as it did before.
|
|
517
|
+
* Probe `createIssue` runs before a retry POST: a create whose response was
|
|
518
|
+
* lost already filed the issue, and the posted marker answers that from
|
|
519
|
+
* server state. Best-effort — `null` lets the retry proceed.
|
|
665
520
|
*
|
|
666
521
|
* @param {{ provider: object, fingerprint: string }} args
|
|
667
522
|
* @returns {Promise<object|null>}
|
|
@@ -685,15 +540,8 @@ async function findOpenStoryByPlanFingerprint({ provider, fingerprint }) {
|
|
|
685
540
|
}
|
|
686
541
|
|
|
687
542
|
/**
|
|
688
|
-
*
|
|
689
|
-
*
|
|
690
|
-
* to create.
|
|
691
|
-
*
|
|
692
|
-
* This is the visible half of the fingerprint tightening. Keying adoption on
|
|
693
|
-
* content means these cases correctly get a fresh Story rather than a silent
|
|
694
|
-
* stale-body adoption, but the divergent Story stays open, and a duplicate the
|
|
695
|
-
* operator never hears about is its own small trap. Naming it converts silent
|
|
696
|
-
* litter into a decision.
|
|
543
|
+
* Name a same-title open Story whose content differs, so the duplicate a fresh
|
|
544
|
+
* create leaves behind is a visible decision rather than silent litter.
|
|
697
545
|
*
|
|
698
546
|
* @param {{ slug: string, title: string }} story
|
|
699
547
|
* @param {Map<string, number[]>} idsByTitle
|
|
@@ -711,9 +559,8 @@ function warnOnDivergentSameTitleStory(story, idsByTitle) {
|
|
|
711
559
|
}
|
|
712
560
|
|
|
713
561
|
/**
|
|
714
|
-
*
|
|
715
|
-
*
|
|
716
|
-
* plan-fingerprint marker that makes the create loop resumable.
|
|
562
|
+
* The posted body: sibling slugs resolved to issue ids, plus the fingerprint
|
|
563
|
+
* marker.
|
|
717
564
|
*
|
|
718
565
|
* @param {object} story
|
|
719
566
|
* @param {Map<string, number>} idBySlug
|
|
@@ -725,19 +572,10 @@ function renderStoryBodyForCreate(story, idBySlug) {
|
|
|
725
572
|
);
|
|
726
573
|
let base = story.body;
|
|
727
574
|
if (dependencyRefs.length > 0) {
|
|
728
|
-
//
|
|
729
|
-
//
|
|
730
|
-
//
|
|
731
|
-
//
|
|
732
|
-
// loss site Story #4935 diagnosed, #4939 fixed, and #4956 reverted
|
|
733
|
-
// wholesale hours later; Story #5056 restored it with a persist-side
|
|
734
|
-
// regression test that reads the POSTed body.
|
|
735
|
-
//
|
|
736
|
-
// `from: story.body` — not the seed — is load-bearing: it re-carries the
|
|
737
|
-
// identities *this* Story was stamped with under Story #5045 attribution
|
|
738
|
-
// rather than reintroducing the whole seed's union. `carryProvenanceFooters`
|
|
739
|
-
// is additive, union-preserving and idempotent, so re-applying is safe by
|
|
740
|
-
// construction.
|
|
575
|
+
// `bodyObject` never held the provenance footers (they were appended to
|
|
576
|
+
// the body string), so re-serializing drops them unless re-carried.
|
|
577
|
+
// `from: story.body`, not the seed, keeps this Story's attributed
|
|
578
|
+
// identities; the carry is idempotent.
|
|
741
579
|
const reserialized = serializeStoryBody(
|
|
742
580
|
{ ...story.bodyObject, depends_on: dependencyRefs },
|
|
743
581
|
{ includeFooter: true },
|
|
@@ -751,34 +589,18 @@ function renderStoryBodyForCreate(story, idBySlug) {
|
|
|
751
589
|
}
|
|
752
590
|
|
|
753
591
|
/**
|
|
754
|
-
* Mirror
|
|
755
|
-
*
|
|
756
|
-
*
|
|
757
|
-
* Ordering is authored as slugs and, until now, survived persist only as
|
|
758
|
-
* `blocked by #N` prose in the body footer. That footer stays — it is what
|
|
759
|
-
* `/mandrel-deliver`'s resolver falls back on — but a native edge is the durable,
|
|
760
|
-
* machine-readable form: visible in the GitHub UI, readable without parsing
|
|
761
|
-
* markdown, and settable by an operator later for cross-run order.
|
|
762
|
-
*
|
|
763
|
-
* **Non-fatal by design, and deliberately asymmetric with the read path.** A
|
|
764
|
-
* missing native edge is cosmetic here: `renderStoryBodyForCreate` has already
|
|
765
|
-
* written the footer, so ordering is not lost when the dependencies API says
|
|
766
|
-
* no. `/mandrel-deliver`'s *read* of these edges is a real dispatch gate, which is why
|
|
767
|
-
* that side fails loud. Persist reports the failure and completes.
|
|
592
|
+
* Mirror sibling `depends_on` into native `blocked_by` edges. Non-fatal: the
|
|
593
|
+
* `blocked by #N` body footer already carries the ordering.
|
|
768
594
|
*
|
|
769
|
-
*
|
|
770
|
-
*
|
|
771
|
-
*
|
|
772
|
-
* object — a `Map` would yield `undefined` for every lookup, skip every edge,
|
|
773
|
-
* and (being non-fatal) report success having written nothing. And it reads
|
|
774
|
-
* `dependsOn`, not the `depends_on` the assembled Story carries.
|
|
595
|
+
* `applyBlockedByDependencies` indexes `slugToIssueNumber` by property access
|
|
596
|
+
* and reads `dependsOn`, so the Map must be flattened to an object and the key
|
|
597
|
+
* renamed — either miss silently skips every edge and reports success.
|
|
775
598
|
*
|
|
776
599
|
* @param {object} args
|
|
777
600
|
* @param {object} args.provider
|
|
778
601
|
* @param {Array<{ slug: string, depends_on: string[] }>} args.stories
|
|
779
602
|
* @param {Map<string, number>} args.idBySlug
|
|
780
603
|
* @returns {Promise<{ edgesAdded: number, edgesSkipped: number, edgesFailed: number, storiesProcessed: number }|null>}
|
|
781
|
-
* `null` when there was nothing to mirror or no interface to mirror through.
|
|
782
604
|
*/
|
|
783
605
|
async function mirrorNativeDependencyEdges({ provider, stories, idBySlug }) {
|
|
784
606
|
const withEdges = stories.filter((story) => story.depends_on.length > 0);
|
|
@@ -798,9 +620,7 @@ async function mirrorNativeDependencyEdges({ provider, stories, idBySlug }) {
|
|
|
798
620
|
|
|
799
621
|
try {
|
|
800
622
|
const { gh, owner, repo } = provider.getDependencyWriteContext();
|
|
801
|
-
//
|
|
802
|
-
// so an external `#<id>` ref only needs an identity entry to be mirrored
|
|
803
|
-
// by the same code path as a sibling (Story #5155).
|
|
623
|
+
// An external `#<id>` ref needs only an identity entry here.
|
|
804
624
|
const slugToIssueNumber = Object.fromEntries(idBySlug);
|
|
805
625
|
for (const story of stories) {
|
|
806
626
|
for (const entry of story.depends_on) {
|
|
@@ -842,27 +662,17 @@ async function mirrorNativeDependencyEdges({ provider, stories, idBySlug }) {
|
|
|
842
662
|
}
|
|
843
663
|
|
|
844
664
|
/**
|
|
845
|
-
* Ensure
|
|
846
|
-
*
|
|
847
|
-
*
|
|
848
|
-
* yet.
|
|
849
|
-
*
|
|
850
|
-
* **Non-fatal by design**, matching the native-blocked_by mirroring posture:
|
|
851
|
-
* the label is not load-bearing for correctness (grouping is cosmetic), so
|
|
852
|
-
* it is never a reason to fail persist. On an ensure
|
|
853
|
-
* failure (throw, or the label reported `missing` by the post-loop
|
|
854
|
-
* reconcile) the create loop proceeds **without** the label — applying an
|
|
855
|
-
* unensured label could fail the issue create itself, and the Stories matter
|
|
856
|
-
* more than their metadata. A provider that exposes no `ensureLabels` (test
|
|
857
|
-
* fakes, minimal providers) is assumed to accept arbitrary labels on create.
|
|
665
|
+
* Ensure a label exists before it is applied (create-issue does not always
|
|
666
|
+
* auto-create). Non-fatal: on failure the Stories are created without it,
|
|
667
|
+
* since an unensured label could fail the create itself.
|
|
858
668
|
*
|
|
859
669
|
* @param {object} args
|
|
860
670
|
* @param {object} args.provider
|
|
861
671
|
* @param {string} args.label
|
|
862
672
|
* @param {string} args.color
|
|
863
673
|
* @param {string} args.description
|
|
864
|
-
* @param {string} args.role
|
|
865
|
-
* @returns {Promise<boolean>} Whether
|
|
674
|
+
* @param {string} args.role
|
|
675
|
+
* @returns {Promise<boolean>} Whether to apply the label.
|
|
866
676
|
*/
|
|
867
677
|
async function ensurePersistLabel({
|
|
868
678
|
provider,
|
|
@@ -898,50 +708,12 @@ async function ensurePersistLabel({
|
|
|
898
708
|
}
|
|
899
709
|
|
|
900
710
|
/**
|
|
901
|
-
* Create Story issues
|
|
902
|
-
*
|
|
903
|
-
*
|
|
904
|
-
* carry it in the creating POST while the `story-plan-state` checkpoint was
|
|
905
|
-
* upserted afterwards, so anything that picked a Story up inside that window —
|
|
906
|
-
* or after a comment failure aborted the loop — read the checkpoint as `null`.
|
|
907
|
-
* Creation now applies `type::story` plus the sanitized authored labels only;
|
|
908
|
-
* `markStoriesReady` performs the flip as the terminal step, once every
|
|
909
|
-
* checkpoint is on the ticket.
|
|
910
|
-
*
|
|
911
|
-
* **The loop is resumable, and adoption is content-keyed.** Each body carries
|
|
912
|
-
* a plan-fingerprint marker, and the open `type::story` backlog is indexed by
|
|
913
|
-
* it before the first POST. A Story whose fingerprint already exists is
|
|
914
|
-
* adopted rather than re-created, so a re-run after a 502 at story *k* of *N*
|
|
915
|
-
* completes the cohort instead of minting a second copy of `1..k-1`.
|
|
916
|
-
*
|
|
917
|
-
* The fingerprint covers the assembled body, not just slug + title, so a hit
|
|
918
|
-
* means the open Story *is* what this run would author and adoption changes
|
|
919
|
-
* nothing. A same-named Story whose content has drifted — an abandoned plan, or
|
|
920
|
-
* an edited `stories.json` — misses the lookup, gets a correct new Story, and
|
|
921
|
-
* is named in a warning. Adoption never rewrites a body, so keying it on
|
|
922
|
-
* anything weaker than content would silently ship a stale one.
|
|
923
|
-
*
|
|
924
|
-
* **Every created Story carries the cohort's `plan-run::<id>` grouping
|
|
925
|
-
* label** (Story #4692, metadata only). The id is deterministic over the
|
|
926
|
-
* authored artifacts ({@link derivePlanRunId}), so a resumed persist derives
|
|
927
|
-
* the identical label its adopted Stories already carry from their original
|
|
928
|
-
* create — no relabel call is needed on the resume path, and the cohort is
|
|
929
|
-
* never split across two labels. The label is ensured to exist before the
|
|
930
|
-
* first POST, **non-fatally**: grouping is cosmetic and never fails the run
|
|
931
|
-
* (see `ensureCohortLabel`). `/mandrel-deliver` never reads it — delivery stays
|
|
932
|
-
* ids-only over live state (Story #4540's actual point).
|
|
711
|
+
* Create Story issues resumably, adopting any open Story whose fingerprint
|
|
712
|
+
* matches. Stories are born without `agent::ready`; `markStoriesReady` flips
|
|
713
|
+
* it last, once every plan comment is on the ticket.
|
|
933
714
|
*
|
|
934
|
-
*
|
|
935
|
-
*
|
|
936
|
-
* independent fan-out: `renderStoryBodyForCreate(story, idBySlug)` resolves a
|
|
937
|
-
* Story's `depends_on` slugs to the real issue ids its siblings were just
|
|
938
|
-
* minted with, and `idBySlug` is filled *in loop order* by the POSTs
|
|
939
|
-
* themselves. Running it concurrently would render `#undefined` dependency
|
|
940
|
-
* refs for any Story whose dependency had not yet returned an id.
|
|
941
|
-
*
|
|
942
|
-
* **Sibling order is mirrored into native GitHub `blocked_by` edges** once
|
|
943
|
-
* every id is known (Story #4544), so plan-created order stops depending on
|
|
944
|
-
* prose. That pass is non-fatal — see `mirrorNativeDependencyEdges`.
|
|
715
|
+
* The loop stays serial: `idBySlug` is filled in loop order by the POSTs, and
|
|
716
|
+
* a concurrent create would render `#undefined` dependency refs.
|
|
945
717
|
*
|
|
946
718
|
* @param {object} args
|
|
947
719
|
* @param {object} args.provider
|
|
@@ -964,9 +736,6 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
964
736
|
|
|
965
737
|
const list = Array.isArray(stories) ? stories : [];
|
|
966
738
|
|
|
967
|
-
// Derived once for the whole cohort, before any write — a pure function of
|
|
968
|
-
// the authored artifacts, so dry-run can report it write-free and a resume
|
|
969
|
-
// re-derives the identical label.
|
|
970
739
|
const cohortLabel = planRunLabel(
|
|
971
740
|
derivePlanRunId(list.map((story) => story.fingerprint)),
|
|
972
741
|
);
|
|
@@ -982,9 +751,6 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
982
751
|
})),
|
|
983
752
|
dependencyEdges: null,
|
|
984
753
|
planRunLabel: cohortLabel,
|
|
985
|
-
// A dry run writes nothing, so nothing was ensured and nothing carries
|
|
986
|
-
// the label — the derived id is still reported, the application is not
|
|
987
|
-
// claimed.
|
|
988
754
|
planRunLabelApplied: false,
|
|
989
755
|
};
|
|
990
756
|
}
|
|
@@ -1002,13 +768,11 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
1002
768
|
const created = [];
|
|
1003
769
|
const idBySlug = new Map();
|
|
1004
770
|
|
|
1005
|
-
|
|
771
|
+
// Already dependency-ordered; re-sorting would disagree on the primary.
|
|
772
|
+
for (const story of list) {
|
|
1006
773
|
const already = byFingerprint.get(story.fingerprint);
|
|
1007
774
|
if (!already) warnOnDivergentSameTitleStory(story, idsByTitle);
|
|
1008
775
|
if (already) {
|
|
1009
|
-
// Adopted Stories already carry the cohort label from their original
|
|
1010
|
-
// create — the deterministic derivation guarantees it is the same
|
|
1011
|
-
// label this run derived, so no relabel call is needed here.
|
|
1012
776
|
Logger.info(
|
|
1013
777
|
`[plan-persist] resuming: Story "${story.slug}" already exists as ` +
|
|
1014
778
|
`#${already.id} with byte-identical authored content ` +
|
|
@@ -1029,9 +793,6 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
1029
793
|
title: story.title,
|
|
1030
794
|
body: renderStoryBodyForCreate(story, idBySlug),
|
|
1031
795
|
labels: [...story.labels, ...(applyCohortLabel ? [cohortLabel] : [])],
|
|
1032
|
-
// Story #5112 — hand the provider the same content-keyed lookup this
|
|
1033
|
-
// loop's resume path uses, so a retry after a lost response adopts the
|
|
1034
|
-
// issue attempt 1 already filed instead of creating a twin.
|
|
1035
796
|
findExisting: () =>
|
|
1036
797
|
findOpenStoryByPlanFingerprint({
|
|
1037
798
|
provider,
|
|
@@ -1049,21 +810,15 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
1049
810
|
id,
|
|
1050
811
|
title: story.title,
|
|
1051
812
|
url: result.url,
|
|
1052
|
-
//
|
|
1053
|
-
// database id, which is the only identifier the native sub-issue write
|
|
1054
|
-
// accepts — and dropping it here is what made the Epic linker re-read
|
|
1055
|
-
// every Story this run had just created to recover it.
|
|
813
|
+
// The database id — the only id the native sub-issue write accepts.
|
|
1056
814
|
internalId: result.internalId,
|
|
1057
|
-
// True when the
|
|
1058
|
-
// first attempt had already filed — pre-existing either way.
|
|
815
|
+
// True when the retry probe adopted a lost-response first attempt.
|
|
1059
816
|
adopted: result.adopted === true,
|
|
1060
817
|
});
|
|
1061
818
|
idBySlug.set(story.slug, id);
|
|
1062
819
|
}
|
|
1063
820
|
|
|
1064
|
-
//
|
|
1065
|
-
// so a re-run mirrors the whole cohort's edges, not just the Stories this
|
|
1066
|
-
// invocation happened to POST. Re-application is idempotent.
|
|
821
|
+
// Includes adopted ids, so a resume mirrors the whole cohort (idempotent).
|
|
1067
822
|
const dependencyEdges = await mirrorNativeDependencyEdges({
|
|
1068
823
|
provider,
|
|
1069
824
|
stories: list,
|
|
@@ -1073,35 +828,17 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
1073
828
|
return {
|
|
1074
829
|
created,
|
|
1075
830
|
dependencyEdges,
|
|
1076
|
-
//
|
|
1077
|
-
// is reported either way (a resumed persist re-derives it, and the
|
|
1078
|
-
// dry-run path reports it write-free); the flag is what an epilogue must
|
|
1079
|
-
// consult before advertising a `label:` filter that may match nothing.
|
|
831
|
+
// Check the flag before advertising a `label:` filter that may match nothing.
|
|
1080
832
|
planRunLabel: cohortLabel,
|
|
1081
833
|
planRunLabelApplied: applyCohortLabel,
|
|
1082
834
|
};
|
|
1083
835
|
}
|
|
1084
836
|
|
|
1085
837
|
/**
|
|
1086
|
-
*
|
|
1087
|
-
*
|
|
1088
|
-
*
|
|
1089
|
-
*
|
|
1090
|
-
* lands, the Story's `story-plan-state` checkpoint is already on the ticket, so
|
|
1091
|
-
* a `/mandrel-deliver` that picks it up cannot read a null checkpoint.
|
|
1092
|
-
*
|
|
1093
|
-
* Fails closed: an un-flipped Story is invisible to `/mandrel-deliver`, which is the
|
|
1094
|
-
* safe direction — the operator is told exactly which ids need the label.
|
|
1095
|
-
*
|
|
1096
|
-
* **Collect failures, never fast-fail** (preserved verbatim under the
|
|
1097
|
-
* Story #4952 concurrency conversion). Every Story is attempted even when an
|
|
1098
|
-
* earlier one's PATCH rejects, because the whole value of the closing error is
|
|
1099
|
-
* naming the *complete* set of ids that still need the label by hand. The
|
|
1100
|
-
* mapper below therefore absorbs its own rejection into a per-Story outcome
|
|
1101
|
-
* rather than letting `concurrentMap`'s first-rejection-wins policy abandon
|
|
1102
|
-
* the remaining flips. `concurrentMap` preserves input order, so `readied[]`
|
|
1103
|
-
* and the reported failures come back in `created[]` order exactly as the
|
|
1104
|
-
* serial loop produced them.
|
|
838
|
+
* Terminal step: flip every created Story to `agent::ready`, so the label
|
|
839
|
+
* means "fully persisted". Fails closed, but attempts every Story first — the
|
|
840
|
+
* mapper absorbs its own rejection so the error names the complete set of ids
|
|
841
|
+
* still needing the label.
|
|
1105
842
|
*
|
|
1106
843
|
* @param {object} args
|
|
1107
844
|
* @param {object} args.provider
|
|
@@ -1130,9 +867,6 @@ export async function markStoriesReady({ provider, created }) {
|
|
|
1130
867
|
};
|
|
1131
868
|
}
|
|
1132
869
|
},
|
|
1133
|
-
// The terminal per-Story `agent::ready` PATCHes (Story #4952): each flip
|
|
1134
|
-
// is an independent single-issue write, so the loop was serial only by
|
|
1135
|
-
// construction. A latency fix, not a throughput one.
|
|
1136
870
|
{ concurrency: FANOUT_CONCURRENCY },
|
|
1137
871
|
);
|
|
1138
872
|
const readied = outcomes
|
|
@@ -1144,7 +878,7 @@ export async function markStoriesReady({ provider, created }) {
|
|
|
1144
878
|
if (failed.length > 0) {
|
|
1145
879
|
throw new Error(
|
|
1146
880
|
`[plan-persist] ${failed.length} Story(ies) were created with their ` +
|
|
1147
|
-
'
|
|
881
|
+
'plan comments but could not be flipped to agent::ready:\n' +
|
|
1148
882
|
`${failed.map((f) => ` - ${f}`).join('\n')}\n` +
|
|
1149
883
|
'They are invisible to /mandrel-deliver until the label lands. Re-run persist ' +
|
|
1150
884
|
'(it resumes rather than duplicating) or add the label by hand.',
|