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
|
@@ -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
|
*/
|
|
@@ -44,28 +34,16 @@ import {
|
|
|
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
|
-
*
|
|
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.
|
|
100
76
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
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.
|
|
109
|
-
*
|
|
110
|
-
* @param {string[]} fingerprints Per-Story plan fingerprints.
|
|
111
|
-
* @returns {string} Hex id, {@link PLAN_RUN_ID_LENGTH} chars.
|
|
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 plan comments, 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,25 +392,10 @@ function assertSharedSpecAllowed(tickets, sharedSpec) {
|
|
|
512
392
|
}
|
|
513
393
|
|
|
514
394
|
/**
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
* inside the create loop, which meant "the primary Story" was derived twice
|
|
520
|
-
* from two different orderings: supersede assignment took the first *authored*
|
|
521
|
-
* Story, while the plan summary took the first *created*
|
|
522
|
-
* one. A draft whose authoring order differed from its dependency order made
|
|
523
|
-
* the `superseded-by` comment name a different Story from the summary. One
|
|
524
|
-
* sort, one ordered list threaded on to every consumer, so `stories[0]` is the
|
|
525
|
-
* only primary there is. The sort also refuses an unknown sibling or a cycle,
|
|
526
|
-
* which now fails the write-free pass rather than the first create.
|
|
527
|
-
*
|
|
528
|
-
* The partition pass runs **before** any GitHub write so a mis-authored
|
|
529
|
-
* plan never leaves Stories live against an inconsistent tracker. Story #5332
|
|
530
|
-
* retired the acceptance partition that used to run beside it: it refused
|
|
531
|
-
* only byte-identical acceptance text across siblings, and the split gate is
|
|
532
|
-
* now `assertNoWaveCollisions` in `run-plan-persist.js`, ahead of the first
|
|
533
|
-
* 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.
|
|
534
399
|
*
|
|
535
400
|
* @param {object[]} tickets
|
|
536
401
|
* @param {object} [opts]
|
|
@@ -576,9 +441,8 @@ function orderStoriesByDependencies(stories) {
|
|
|
576
441
|
const scheduled = new Set();
|
|
577
442
|
const pending = [...list];
|
|
578
443
|
while (pending.length > 0) {
|
|
579
|
-
// External refs
|
|
580
|
-
//
|
|
581
|
-
// 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.
|
|
582
446
|
const index = pending.findIndex((story) =>
|
|
583
447
|
story.depends_on
|
|
584
448
|
.filter((slug) => !isExternalDependencyRef(slug))
|
|
@@ -597,21 +461,9 @@ function orderStoriesByDependencies(stories) {
|
|
|
597
461
|
}
|
|
598
462
|
|
|
599
463
|
/**
|
|
600
|
-
* Index
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
* Two indexes come back. `byFingerprint` is the adoption key — an exact match
|
|
604
|
-
* on the authored content (see {@link planStoryFingerprint}). `idsByTitle` is
|
|
605
|
-
* only used to *warn*: it catches the near miss where a Story with this title
|
|
606
|
-
* is already open but its content differs, which is what an abandoned earlier
|
|
607
|
-
* plan or an edited `stories.json` leaves behind. Adoption deliberately does
|
|
608
|
-
* not key on it — a title is not an identity, and adopting on one would let a
|
|
609
|
-
* later unrelated plan overwrite someone else's Story.
|
|
610
|
-
*
|
|
611
|
-
* Best-effort by construction: a provider with no `listIssuesByLabel` (or a
|
|
612
|
-
* listing that errors) yields empty indexes and the create loop proceeds
|
|
613
|
-
* un-deduplicated, exactly as it did before. That degrades resume, not
|
|
614
|
-
* 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.
|
|
615
467
|
*
|
|
616
468
|
* @param {object} provider
|
|
617
469
|
* @returns {Promise<{
|
|
@@ -662,19 +514,9 @@ async function indexExistingStories(provider) {
|
|
|
662
514
|
}
|
|
663
515
|
|
|
664
516
|
/**
|
|
665
|
-
*
|
|
666
|
-
* issue,
|
|
667
|
-
*
|
|
668
|
-
* This is the probe `createIssue` calls before any retry POST (Story #5112).
|
|
669
|
-
* A create whose response was lost has already filed the issue; retrying
|
|
670
|
-
* blind duplicates it. Because the body posted carries the fingerprint
|
|
671
|
-
* marker, the same content-keyed lookup the resume path uses answers "did
|
|
672
|
-
* attempt 1 land?" authoritatively — from the server's state, not from a
|
|
673
|
-
* client-side guess about where the connection broke.
|
|
674
|
-
*
|
|
675
|
-
* Best-effort like {@link indexExistingStories}: a provider without the
|
|
676
|
-
* listing surface, or a listing that throws, yields `null` and the retry
|
|
677
|
-
* 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.
|
|
678
520
|
*
|
|
679
521
|
* @param {{ provider: object, fingerprint: string }} args
|
|
680
522
|
* @returns {Promise<object|null>}
|
|
@@ -698,15 +540,8 @@ async function findOpenStoryByPlanFingerprint({ provider, fingerprint }) {
|
|
|
698
540
|
}
|
|
699
541
|
|
|
700
542
|
/**
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
* to create.
|
|
704
|
-
*
|
|
705
|
-
* This is the visible half of the fingerprint tightening. Keying adoption on
|
|
706
|
-
* content means these cases correctly get a fresh Story rather than a silent
|
|
707
|
-
* stale-body adoption, but the divergent Story stays open, and a duplicate the
|
|
708
|
-
* operator never hears about is its own small trap. Naming it converts silent
|
|
709
|
-
* 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.
|
|
710
545
|
*
|
|
711
546
|
* @param {{ slug: string, title: string }} story
|
|
712
547
|
* @param {Map<string, number[]>} idsByTitle
|
|
@@ -724,9 +559,8 @@ function warnOnDivergentSameTitleStory(story, idsByTitle) {
|
|
|
724
559
|
}
|
|
725
560
|
|
|
726
561
|
/**
|
|
727
|
-
*
|
|
728
|
-
*
|
|
729
|
-
* plan-fingerprint marker that makes the create loop resumable.
|
|
562
|
+
* The posted body: sibling slugs resolved to issue ids, plus the fingerprint
|
|
563
|
+
* marker.
|
|
730
564
|
*
|
|
731
565
|
* @param {object} story
|
|
732
566
|
* @param {Map<string, number>} idBySlug
|
|
@@ -738,19 +572,10 @@ function renderStoryBodyForCreate(story, idBySlug) {
|
|
|
738
572
|
);
|
|
739
573
|
let base = story.body;
|
|
740
574
|
if (dependencyRefs.length > 0) {
|
|
741
|
-
//
|
|
742
|
-
//
|
|
743
|
-
//
|
|
744
|
-
//
|
|
745
|
-
// loss site Story #4935 diagnosed, #4939 fixed, and #4956 reverted
|
|
746
|
-
// wholesale hours later; Story #5056 restored it with a persist-side
|
|
747
|
-
// regression test that reads the POSTed body.
|
|
748
|
-
//
|
|
749
|
-
// `from: story.body` — not the seed — is load-bearing: it re-carries the
|
|
750
|
-
// identities *this* Story was stamped with under Story #5045 attribution
|
|
751
|
-
// rather than reintroducing the whole seed's union. `carryProvenanceFooters`
|
|
752
|
-
// is additive, union-preserving and idempotent, so re-applying is safe by
|
|
753
|
-
// 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.
|
|
754
579
|
const reserialized = serializeStoryBody(
|
|
755
580
|
{ ...story.bodyObject, depends_on: dependencyRefs },
|
|
756
581
|
{ includeFooter: true },
|
|
@@ -764,34 +589,18 @@ function renderStoryBodyForCreate(story, idBySlug) {
|
|
|
764
589
|
}
|
|
765
590
|
|
|
766
591
|
/**
|
|
767
|
-
* Mirror
|
|
768
|
-
*
|
|
769
|
-
*
|
|
770
|
-
* Ordering is authored as slugs and, until now, survived persist only as
|
|
771
|
-
* `blocked by #N` prose in the body footer. That footer stays — it is what
|
|
772
|
-
* `/mandrel-deliver`'s resolver falls back on — but a native edge is the durable,
|
|
773
|
-
* machine-readable form: visible in the GitHub UI, readable without parsing
|
|
774
|
-
* markdown, and settable by an operator later for cross-run order.
|
|
592
|
+
* Mirror sibling `depends_on` into native `blocked_by` edges. Non-fatal: the
|
|
593
|
+
* `blocked by #N` body footer already carries the ordering.
|
|
775
594
|
*
|
|
776
|
-
*
|
|
777
|
-
*
|
|
778
|
-
*
|
|
779
|
-
* no. `/mandrel-deliver`'s *read* of these edges is a real dispatch gate, which is why
|
|
780
|
-
* that side fails loud. Persist reports the failure and completes.
|
|
781
|
-
*
|
|
782
|
-
* Two shape hazards this crossing has to get right, both silent if missed:
|
|
783
|
-
* `applyBlockedByDependencies` indexes `slugToIssueNumber` with property
|
|
784
|
-
* access, so the `Map` the create loop builds must be flattened to a plain
|
|
785
|
-
* object — a `Map` would yield `undefined` for every lookup, skip every edge,
|
|
786
|
-
* and (being non-fatal) report success having written nothing. And it reads
|
|
787
|
-
* `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.
|
|
788
598
|
*
|
|
789
599
|
* @param {object} args
|
|
790
600
|
* @param {object} args.provider
|
|
791
601
|
* @param {Array<{ slug: string, depends_on: string[] }>} args.stories
|
|
792
602
|
* @param {Map<string, number>} args.idBySlug
|
|
793
603
|
* @returns {Promise<{ edgesAdded: number, edgesSkipped: number, edgesFailed: number, storiesProcessed: number }|null>}
|
|
794
|
-
* `null` when there was nothing to mirror or no interface to mirror through.
|
|
795
604
|
*/
|
|
796
605
|
async function mirrorNativeDependencyEdges({ provider, stories, idBySlug }) {
|
|
797
606
|
const withEdges = stories.filter((story) => story.depends_on.length > 0);
|
|
@@ -811,9 +620,7 @@ async function mirrorNativeDependencyEdges({ provider, stories, idBySlug }) {
|
|
|
811
620
|
|
|
812
621
|
try {
|
|
813
622
|
const { gh, owner, repo } = provider.getDependencyWriteContext();
|
|
814
|
-
//
|
|
815
|
-
// so an external `#<id>` ref only needs an identity entry to be mirrored
|
|
816
|
-
// by the same code path as a sibling (Story #5155).
|
|
623
|
+
// An external `#<id>` ref needs only an identity entry here.
|
|
817
624
|
const slugToIssueNumber = Object.fromEntries(idBySlug);
|
|
818
625
|
for (const story of stories) {
|
|
819
626
|
for (const entry of story.depends_on) {
|
|
@@ -855,27 +662,17 @@ async function mirrorNativeDependencyEdges({ provider, stories, idBySlug }) {
|
|
|
855
662
|
}
|
|
856
663
|
|
|
857
664
|
/**
|
|
858
|
-
* Ensure
|
|
859
|
-
*
|
|
860
|
-
*
|
|
861
|
-
* yet.
|
|
862
|
-
*
|
|
863
|
-
* **Non-fatal by design**, matching the native-blocked_by mirroring posture:
|
|
864
|
-
* the label is not load-bearing for correctness (grouping is cosmetic), so
|
|
865
|
-
* it is never a reason to fail persist. On an ensure
|
|
866
|
-
* failure (throw, or the label reported `missing` by the post-loop
|
|
867
|
-
* reconcile) the create loop proceeds **without** the label — applying an
|
|
868
|
-
* unensured label could fail the issue create itself, and the Stories matter
|
|
869
|
-
* more than their metadata. A provider that exposes no `ensureLabels` (test
|
|
870
|
-
* 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.
|
|
871
668
|
*
|
|
872
669
|
* @param {object} args
|
|
873
670
|
* @param {object} args.provider
|
|
874
671
|
* @param {string} args.label
|
|
875
672
|
* @param {string} args.color
|
|
876
673
|
* @param {string} args.description
|
|
877
|
-
* @param {string} args.role
|
|
878
|
-
* @returns {Promise<boolean>} Whether
|
|
674
|
+
* @param {string} args.role
|
|
675
|
+
* @returns {Promise<boolean>} Whether to apply the label.
|
|
879
676
|
*/
|
|
880
677
|
async function ensurePersistLabel({
|
|
881
678
|
provider,
|
|
@@ -911,51 +708,12 @@ async function ensurePersistLabel({
|
|
|
911
708
|
}
|
|
912
709
|
|
|
913
710
|
/**
|
|
914
|
-
* Create Story issues
|
|
915
|
-
*
|
|
916
|
-
*
|
|
917
|
-
* carry it in the creating POST while the `story-plan-state` comment was
|
|
918
|
-
* upserted afterwards, so anything that picked a Story up inside that window —
|
|
919
|
-
* or after a comment failure aborted the loop — found a ready Story carrying
|
|
920
|
-
* none of the operator's delivery instructions. Creation now applies
|
|
921
|
-
* `type::story` plus the sanitized authored labels only; `markStoriesReady`
|
|
922
|
-
* performs the flip as the terminal step, once every plan comment is on the
|
|
923
|
-
* ticket.
|
|
924
|
-
*
|
|
925
|
-
* **The loop is resumable, and adoption is content-keyed.** Each body carries
|
|
926
|
-
* a plan-fingerprint marker, and the open `type::story` backlog is indexed by
|
|
927
|
-
* it before the first POST. A Story whose fingerprint already exists is
|
|
928
|
-
* adopted rather than re-created, so a re-run after a 502 at story *k* of *N*
|
|
929
|
-
* completes the cohort instead of minting a second copy of `1..k-1`.
|
|
930
|
-
*
|
|
931
|
-
* The fingerprint covers the assembled body, not just slug + title, so a hit
|
|
932
|
-
* means the open Story *is* what this run would author and adoption changes
|
|
933
|
-
* nothing. A same-named Story whose content has drifted — an abandoned plan, or
|
|
934
|
-
* an edited `stories.json` — misses the lookup, gets a correct new Story, and
|
|
935
|
-
* is named in a warning. Adoption never rewrites a body, so keying it on
|
|
936
|
-
* anything weaker than content would silently ship a stale one.
|
|
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.
|
|
937
714
|
*
|
|
938
|
-
*
|
|
939
|
-
*
|
|
940
|
-
* authored artifacts ({@link derivePlanRunId}), so a resumed persist derives
|
|
941
|
-
* the identical label its adopted Stories already carry from their original
|
|
942
|
-
* create — no relabel call is needed on the resume path, and the cohort is
|
|
943
|
-
* never split across two labels. The label is ensured to exist before the
|
|
944
|
-
* first POST, **non-fatally**: grouping is cosmetic and never fails the run
|
|
945
|
-
* (see `ensureCohortLabel`). `/mandrel-deliver` never reads it — delivery stays
|
|
946
|
-
* ids-only over live state (Story #4540's actual point).
|
|
947
|
-
*
|
|
948
|
-
* **The create loop stays serial and dependency-ordered** — deliberately, and
|
|
949
|
-
* unlike every other per-Story loop on this path (Story #4952). It is not an
|
|
950
|
-
* independent fan-out: `renderStoryBodyForCreate(story, idBySlug)` resolves a
|
|
951
|
-
* Story's `depends_on` slugs to the real issue ids its siblings were just
|
|
952
|
-
* minted with, and `idBySlug` is filled *in loop order* by the POSTs
|
|
953
|
-
* themselves. Running it concurrently would render `#undefined` dependency
|
|
954
|
-
* refs for any Story whose dependency had not yet returned an id.
|
|
955
|
-
*
|
|
956
|
-
* **Sibling order is mirrored into native GitHub `blocked_by` edges** once
|
|
957
|
-
* every id is known (Story #4544), so plan-created order stops depending on
|
|
958
|
-
* 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.
|
|
959
717
|
*
|
|
960
718
|
* @param {object} args
|
|
961
719
|
* @param {object} args.provider
|
|
@@ -978,9 +736,6 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
978
736
|
|
|
979
737
|
const list = Array.isArray(stories) ? stories : [];
|
|
980
738
|
|
|
981
|
-
// Derived once for the whole cohort, before any write — a pure function of
|
|
982
|
-
// the authored artifacts, so dry-run can report it write-free and a resume
|
|
983
|
-
// re-derives the identical label.
|
|
984
739
|
const cohortLabel = planRunLabel(
|
|
985
740
|
derivePlanRunId(list.map((story) => story.fingerprint)),
|
|
986
741
|
);
|
|
@@ -996,9 +751,6 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
996
751
|
})),
|
|
997
752
|
dependencyEdges: null,
|
|
998
753
|
planRunLabel: cohortLabel,
|
|
999
|
-
// A dry run writes nothing, so nothing was ensured and nothing carries
|
|
1000
|
-
// the label — the derived id is still reported, the application is not
|
|
1001
|
-
// claimed.
|
|
1002
754
|
planRunLabelApplied: false,
|
|
1003
755
|
};
|
|
1004
756
|
}
|
|
@@ -1016,16 +768,11 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
1016
768
|
const created = [];
|
|
1017
769
|
const idBySlug = new Map();
|
|
1018
770
|
|
|
1019
|
-
// Already
|
|
1020
|
-
// sorting again here is what gave the run a second, disagreeing notion of
|
|
1021
|
-
// which Story is primary (Story #5361).
|
|
771
|
+
// Already dependency-ordered; re-sorting would disagree on the primary.
|
|
1022
772
|
for (const story of list) {
|
|
1023
773
|
const already = byFingerprint.get(story.fingerprint);
|
|
1024
774
|
if (!already) warnOnDivergentSameTitleStory(story, idsByTitle);
|
|
1025
775
|
if (already) {
|
|
1026
|
-
// Adopted Stories already carry the cohort label from their original
|
|
1027
|
-
// create — the deterministic derivation guarantees it is the same
|
|
1028
|
-
// label this run derived, so no relabel call is needed here.
|
|
1029
776
|
Logger.info(
|
|
1030
777
|
`[plan-persist] resuming: Story "${story.slug}" already exists as ` +
|
|
1031
778
|
`#${already.id} with byte-identical authored content ` +
|
|
@@ -1046,9 +793,6 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
1046
793
|
title: story.title,
|
|
1047
794
|
body: renderStoryBodyForCreate(story, idBySlug),
|
|
1048
795
|
labels: [...story.labels, ...(applyCohortLabel ? [cohortLabel] : [])],
|
|
1049
|
-
// Story #5112 — hand the provider the same content-keyed lookup this
|
|
1050
|
-
// loop's resume path uses, so a retry after a lost response adopts the
|
|
1051
|
-
// issue attempt 1 already filed instead of creating a twin.
|
|
1052
796
|
findExisting: () =>
|
|
1053
797
|
findOpenStoryByPlanFingerprint({
|
|
1054
798
|
provider,
|
|
@@ -1066,21 +810,15 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
1066
810
|
id,
|
|
1067
811
|
title: story.title,
|
|
1068
812
|
url: result.url,
|
|
1069
|
-
//
|
|
1070
|
-
// database id, which is the only identifier the native sub-issue write
|
|
1071
|
-
// accepts — and dropping it here is what made the Epic linker re-read
|
|
1072
|
-
// every Story this run had just created to recover it.
|
|
813
|
+
// The database id — the only id the native sub-issue write accepts.
|
|
1073
814
|
internalId: result.internalId,
|
|
1074
|
-
// True when the
|
|
1075
|
-
// first attempt had already filed — pre-existing either way.
|
|
815
|
+
// True when the retry probe adopted a lost-response first attempt.
|
|
1076
816
|
adopted: result.adopted === true,
|
|
1077
817
|
});
|
|
1078
818
|
idBySlug.set(story.slug, id);
|
|
1079
819
|
}
|
|
1080
820
|
|
|
1081
|
-
//
|
|
1082
|
-
// so a re-run mirrors the whole cohort's edges, not just the Stories this
|
|
1083
|
-
// invocation happened to POST. Re-application is idempotent.
|
|
821
|
+
// Includes adopted ids, so a resume mirrors the whole cohort (idempotent).
|
|
1084
822
|
const dependencyEdges = await mirrorNativeDependencyEdges({
|
|
1085
823
|
provider,
|
|
1086
824
|
stories: list,
|
|
@@ -1090,35 +828,17 @@ export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
|
1090
828
|
return {
|
|
1091
829
|
created,
|
|
1092
830
|
dependencyEdges,
|
|
1093
|
-
//
|
|
1094
|
-
// is reported either way (a resumed persist re-derives it, and the
|
|
1095
|
-
// dry-run path reports it write-free); the flag is what an epilogue must
|
|
1096
|
-
// consult before advertising a `label:` filter that may match nothing.
|
|
831
|
+
// Check the flag before advertising a `label:` filter that may match nothing.
|
|
1097
832
|
planRunLabel: cohortLabel,
|
|
1098
833
|
planRunLabelApplied: applyCohortLabel,
|
|
1099
834
|
};
|
|
1100
835
|
}
|
|
1101
836
|
|
|
1102
837
|
/**
|
|
1103
|
-
*
|
|
1104
|
-
*
|
|
1105
|
-
*
|
|
1106
|
-
*
|
|
1107
|
-
* lands, the Story's `story-plan-state` comment is already on the ticket, so a
|
|
1108
|
-
* `/mandrel-deliver` that picks it up always has the plan summary beside it.
|
|
1109
|
-
*
|
|
1110
|
-
* Fails closed: an un-flipped Story is invisible to `/mandrel-deliver`, which is the
|
|
1111
|
-
* safe direction — the operator is told exactly which ids need the label.
|
|
1112
|
-
*
|
|
1113
|
-
* **Collect failures, never fast-fail** (preserved verbatim under the
|
|
1114
|
-
* Story #4952 concurrency conversion). Every Story is attempted even when an
|
|
1115
|
-
* earlier one's PATCH rejects, because the whole value of the closing error is
|
|
1116
|
-
* naming the *complete* set of ids that still need the label by hand. The
|
|
1117
|
-
* mapper below therefore absorbs its own rejection into a per-Story outcome
|
|
1118
|
-
* rather than letting `concurrentMap`'s first-rejection-wins policy abandon
|
|
1119
|
-
* the remaining flips. `concurrentMap` preserves input order, so `readied[]`
|
|
1120
|
-
* and the reported failures come back in `created[]` order exactly as the
|
|
1121
|
-
* 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.
|
|
1122
842
|
*
|
|
1123
843
|
* @param {object} args
|
|
1124
844
|
* @param {object} args.provider
|
|
@@ -1147,9 +867,6 @@ export async function markStoriesReady({ provider, created }) {
|
|
|
1147
867
|
};
|
|
1148
868
|
}
|
|
1149
869
|
},
|
|
1150
|
-
// The terminal per-Story `agent::ready` PATCHes (Story #4952): each flip
|
|
1151
|
-
// is an independent single-issue write, so the loop was serial only by
|
|
1152
|
-
// construction. A latency fix, not a throughput one.
|
|
1153
870
|
{ concurrency: FANOUT_CONCURRENCY },
|
|
1154
871
|
);
|
|
1155
872
|
const readied = outcomes
|