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,53 +1,21 @@
|
|
|
1
1
|
// .agents/scripts/lib/story-body/story-body.js
|
|
2
2
|
/**
|
|
3
|
-
* Canonical Story-body parser/serializer
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* through these exports — do not inline ad-hoc parsing elsewhere.
|
|
8
|
-
*
|
|
9
|
-
* ## Structured Story body shape
|
|
10
|
-
*
|
|
11
|
-
* ```js
|
|
12
|
-
* {
|
|
13
|
-
* goal: string, // one-sentence purpose
|
|
14
|
-
* slicing: string, // v2 intra-Story delivery slice plan (optional; '' when absent)
|
|
15
|
-
* spec: string, // folded Tech Spec text block (optional; '' when absent)
|
|
16
|
-
* changes: PathEntry[], // files/globs this Story touches
|
|
17
|
-
* acceptance: string[], // observable criteria
|
|
18
|
-
* verify: string[], // exact commands / tier annotation
|
|
19
|
-
* references: PathEntry[], // read-only paths (optional)
|
|
20
|
-
* non_goals: string[], // negative-scope bullets (optional, advisory)
|
|
21
|
-
* depends_on: string[], // blocker story slugs or #ids
|
|
22
|
-
* }
|
|
23
|
-
* ```
|
|
24
|
-
*
|
|
25
|
-
* Where `PathEntry` is:
|
|
26
|
-
* - `{ path: string, assumption: "creates"|"refactors-existing"|"exists"|"deletes" }`
|
|
27
|
-
* (canonical form — string bullets are rejected at parse time)
|
|
28
|
-
*
|
|
29
|
-
* ## Round-trip contract
|
|
30
|
-
*
|
|
31
|
-
* `serialize(parse(markdown)) === markdown` when the input is already
|
|
32
|
-
* in the canonical serialized form. Non-canonical whitespace or
|
|
33
|
-
* section ordering may produce a normalized (but equivalent) output.
|
|
34
|
-
*
|
|
35
|
-
* The parser MUST fail closed: a body that cannot be mapped to the
|
|
36
|
-
* canonical shape throws `StoryBodyParseError` — it does NOT silently
|
|
37
|
-
* coerce malformed input. This prevents a corrupt body from supplying
|
|
38
|
-
* wrong `depends_on` edges that reorder the wave DAG.
|
|
3
|
+
* Canonical Story-body parser/serializer — the single source of truth for
|
|
4
|
+
* the Story body shape. The parser fails closed: a body that cannot be mapped
|
|
5
|
+
* to the canonical shape throws, so a corrupt body cannot supply wrong
|
|
6
|
+
* `depends_on` edges. `serialize(parse(md)) === md` for canonical input.
|
|
39
7
|
*
|
|
40
8
|
* @module story-body
|
|
41
9
|
*/
|
|
42
10
|
|
|
43
11
|
import { FILE_ASSUMPTION_VALUES } from '../orchestration/file-assumption-enum.js';
|
|
44
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
isProseBullet,
|
|
14
|
+
matchBarePathToken,
|
|
15
|
+
suggestPathEntryFix,
|
|
16
|
+
} from './body-format-lints.js';
|
|
45
17
|
import { isFooterSeparator, parseFooterBlockedByRefs } from './footer-block.js';
|
|
46
18
|
|
|
47
|
-
// ---------------------------------------------------------------------------
|
|
48
|
-
// Public types (JSDoc only — no runtime schema file)
|
|
49
|
-
// ---------------------------------------------------------------------------
|
|
50
|
-
|
|
51
19
|
/**
|
|
52
20
|
* @typedef {'creates'|'refactors-existing'|'exists'|'deletes'} AssumptionEnum
|
|
53
21
|
*/
|
|
@@ -62,52 +30,45 @@ import { isFooterSeparator, parseFooterBlockedByRefs } from './footer-block.js';
|
|
|
62
30
|
|
|
63
31
|
/**
|
|
64
32
|
* @typedef {object} StoryBody
|
|
65
|
-
* @property {string} goal
|
|
66
|
-
* @property {string} slicing -
|
|
67
|
-
* @property {string} spec -
|
|
68
|
-
* @property {PathEntry[]} changes
|
|
69
|
-
* @property {string[]} acceptance
|
|
70
|
-
* @property {string[]} verify
|
|
71
|
-
* @property {PathEntry[]} references - Read-only paths
|
|
72
|
-
* @property {string[]} non_goals -
|
|
33
|
+
* @property {string} goal
|
|
34
|
+
* @property {string} slicing - Intra-Story slice plan; '' when absent.
|
|
35
|
+
* @property {string} spec - Folded Tech Spec; '' when absent.
|
|
36
|
+
* @property {PathEntry[]} changes
|
|
37
|
+
* @property {string[]} acceptance
|
|
38
|
+
* @property {string[]} verify
|
|
39
|
+
* @property {PathEntry[]} references - Read-only paths.
|
|
40
|
+
* @property {string[]} non_goals - Advisory negative scope.
|
|
73
41
|
* @property {string[]} depends_on - Blocking story slugs / issue refs.
|
|
74
42
|
*/
|
|
75
43
|
|
|
76
44
|
/**
|
|
77
45
|
* @typedef {object} ParseResult
|
|
78
|
-
* @property {StoryBody} body
|
|
79
|
-
* @property {string[]} warnings
|
|
80
|
-
* @property {ParseInfo} info
|
|
46
|
+
* @property {StoryBody} body
|
|
47
|
+
* @property {string[]} warnings
|
|
48
|
+
* @property {ParseInfo} info
|
|
81
49
|
*/
|
|
82
50
|
|
|
83
51
|
/**
|
|
84
52
|
* @typedef {object} ParseInfo
|
|
85
|
-
* @property {boolean} hasGoalSection
|
|
86
|
-
* @property {boolean} hasChangesSection
|
|
87
|
-
* @property {boolean} hasAcceptanceSection
|
|
88
|
-
* @property {boolean} hasVerifySection
|
|
89
|
-
* @property {boolean} hasReferencesSection
|
|
90
|
-
* @property {boolean} hasNonGoalsSection
|
|
91
|
-
* @property {boolean} hasSlicingSection
|
|
92
|
-
* @property {boolean} hasSpecSection
|
|
53
|
+
* @property {boolean} hasGoalSection
|
|
54
|
+
* @property {boolean} hasChangesSection
|
|
55
|
+
* @property {boolean} hasAcceptanceSection
|
|
56
|
+
* @property {boolean} hasVerifySection
|
|
57
|
+
* @property {boolean} hasReferencesSection
|
|
58
|
+
* @property {boolean} hasNonGoalsSection
|
|
59
|
+
* @property {boolean} hasSlicingSection
|
|
60
|
+
* @property {boolean} hasSpecSection
|
|
93
61
|
* @property {boolean} isUnstructuredBody - True when no structured sections were found.
|
|
94
62
|
*/
|
|
95
63
|
|
|
96
64
|
/**
|
|
97
65
|
* @typedef {object} SerializeOptions
|
|
98
66
|
* @property {boolean} [includeFooter=false] - Include `---\nparent/blocked-by` footer.
|
|
99
|
-
* @property {object} [footer]
|
|
100
|
-
* @property {number} [footer.parent]
|
|
67
|
+
* @property {object} [footer]
|
|
68
|
+
* @property {number} [footer.parent]
|
|
101
69
|
*/
|
|
102
70
|
|
|
103
|
-
|
|
104
|
-
// Error class
|
|
105
|
-
// ---------------------------------------------------------------------------
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Thrown when the Story body cannot be parsed into the canonical shape.
|
|
109
|
-
* The parser fails closed — do not catch this to silently continue.
|
|
110
|
-
*/
|
|
71
|
+
/** Thrown when a Story body cannot be parsed; never catch to continue. */
|
|
111
72
|
export class StoryBodyParseError extends Error {
|
|
112
73
|
/**
|
|
113
74
|
* @param {string} message
|
|
@@ -121,13 +82,7 @@ export class StoryBodyParseError extends Error {
|
|
|
121
82
|
}
|
|
122
83
|
}
|
|
123
84
|
|
|
124
|
-
//
|
|
125
|
-
// Section heading map
|
|
126
|
-
// ---------------------------------------------------------------------------
|
|
127
|
-
|
|
128
|
-
// Heading text → body field name. Keys are normalized: lower-cased with `-`
|
|
129
|
-
// folded to `_` (see splitSections), so the hyphenated `## Non-Goals` heading
|
|
130
|
-
// maps to the `non_goals` field.
|
|
85
|
+
// Keys are lower-cased with `-` folded to `_` (see splitSections).
|
|
131
86
|
const HEADING_TO_FIELD = new Map([
|
|
132
87
|
['goal', 'goal'],
|
|
133
88
|
['slicing', 'slicing'],
|
|
@@ -140,14 +95,7 @@ const HEADING_TO_FIELD = new Map([
|
|
|
140
95
|
]);
|
|
141
96
|
const TEXT_BLOCK_FIELDS = new Set(['slicing', 'spec']);
|
|
142
97
|
|
|
143
|
-
// ---------------------------------------------------------------------------
|
|
144
|
-
// Helpers
|
|
145
|
-
// ---------------------------------------------------------------------------
|
|
146
|
-
|
|
147
98
|
/**
|
|
148
|
-
* Strip leading `- ` or `- [ ] ` from a markdown list item, returning the
|
|
149
|
-
* raw content.
|
|
150
|
-
*
|
|
151
99
|
* @param {string} line
|
|
152
100
|
* @returns {string}
|
|
153
101
|
*/
|
|
@@ -155,88 +103,87 @@ function stripListMarker(line) {
|
|
|
155
103
|
return line.replace(/^-\s+(?:\[\s*[xX ]?\s*\]\s+)?/, '').trim();
|
|
156
104
|
}
|
|
157
105
|
|
|
158
|
-
//
|
|
159
|
-
//
|
|
160
|
-
// inline-JSON object bullet remains accepted at parse time indefinitely (live
|
|
161
|
-
// issue bodies are never rewritten).
|
|
106
|
+
// `path` — assumption: the shape serialize() emits. The inline-JSON bullet is
|
|
107
|
+
// still accepted at parse time because live issue bodies are never rewritten.
|
|
162
108
|
const HUMANIZED_PATH_ENTRY_RE = /^`([^`]+)`\s+—\s+(\S+)$/;
|
|
163
109
|
|
|
164
|
-
// AC-<n
|
|
165
|
-
//
|
|
166
|
-
// top-level acceptance[] machine contract round-trips byte-identical.
|
|
167
|
-
//
|
|
168
|
-
// The lettered form (`AC-14a:`) is accepted too (Story #5323). Nothing emits
|
|
169
|
-
// one — `serialize()` numbers from the array index — but a Story planned from
|
|
170
|
-
// an existing ticket can copy one out of the source issue's rendered
|
|
171
|
-
// checkboxes, and a body that already carries one must still parse to the
|
|
172
|
-
// handle-free text or the round-trip invariant breaks for it alone. Trailing
|
|
173
|
-
// whitespace is optional so `AC-3:text` normalises as readily as `AC-3: text`.
|
|
110
|
+
// Presentation-only `AC-<n>:` handle (lettered `AC-14a:` too, copied from
|
|
111
|
+
// source tickets); parse() strips it so acceptance[] round-trips.
|
|
174
112
|
const AC_PREFIX_RE = /^AC-\d+[a-z]?:\s*/i;
|
|
175
113
|
|
|
176
|
-
//
|
|
177
|
-
// carry
|
|
178
|
-
//
|
|
179
|
-
// `<!-- meta: {...} -->` block. Nothing writes them any more — the `wide` /
|
|
180
|
-
// `reason_to_exist` fields and the provenance stamp went with the plan-time
|
|
181
|
-
// sizing model — but live issue bodies are never rewritten, so the parser
|
|
182
|
-
// still skips them wherever they appear rather than absorbing a stray line
|
|
183
|
-
// into the last structured section. A skipped block is dropped on
|
|
184
|
-
// re-serialize, which is the cutover working as intended.
|
|
114
|
+
// Retired machine-managed marker lines nothing writes any more. Live bodies
|
|
115
|
+
// still carry them, so the parser skips them rather than absorbing them into
|
|
116
|
+
// the last section; they are dropped on re-serialize.
|
|
185
117
|
const WIDE_MARKER_LINE_RE = /^>\s*\*\*Wide:\*\*/;
|
|
186
118
|
const AUTHORED_MARKER_LINE_RE = /^\s*>\s*🏷️\s+Authored with Mandrel\b/;
|
|
187
119
|
const META_BLOCK_RE = /<!--\s*meta:[\s\S]*?-->/;
|
|
188
120
|
|
|
189
121
|
/**
|
|
190
|
-
* Parse
|
|
191
|
-
*
|
|
192
|
-
* Accepted markdown shapes (both parsed indefinitely — live issue bodies
|
|
193
|
-
* are never rewritten):
|
|
194
|
-
* - Humanized bullet (canonical serialize() output since Story #4600):
|
|
195
|
-
* `` `src/x.js` — refactors-existing ``
|
|
196
|
-
* - Legacy inline-JSON object bullet:
|
|
197
|
-
* `- { "path": "...", "assumption": "..." }`
|
|
198
|
-
*
|
|
199
|
-
* A structured object entry (from a parsed JSON body that was never
|
|
200
|
-
* serialized to markdown) arrives as-is and is validated directly.
|
|
122
|
+
* Parse one `changes` / `references` bullet: bare path (`assumption: null`),
|
|
123
|
+
* humanized `` `path` — assumption ``, or inline-JSON object.
|
|
201
124
|
*
|
|
202
125
|
* @param {string|object} raw
|
|
203
126
|
* @param {string[]} warnings
|
|
204
127
|
* @returns {PathEntry}
|
|
205
128
|
*/
|
|
206
129
|
function parsePathEntry(raw, warnings) {
|
|
207
|
-
// Already a structured object (from a parsed JSON body, not markdown).
|
|
208
130
|
if (raw !== null && typeof raw === 'object') {
|
|
209
131
|
return pathEntryFromObject(raw);
|
|
210
132
|
}
|
|
211
133
|
|
|
212
|
-
const str =
|
|
134
|
+
const str = String(raw).trim();
|
|
213
135
|
if (str.length === 0) return null;
|
|
214
136
|
|
|
215
137
|
const entry = pathEntryFromHumanized(str) ?? pathEntryFromInlineJson(str);
|
|
216
138
|
if (entry) return entry;
|
|
139
|
+
return pathEntryFromBare(str);
|
|
140
|
+
}
|
|
217
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Last shape tried, so it owns the rejection. A `{`-leading string here is
|
|
144
|
+
* malformed JSON, not a path. Prose and non-path tokens get distinct refusals
|
|
145
|
+
* because they need different fixes.
|
|
146
|
+
*
|
|
147
|
+
* @param {string} str
|
|
148
|
+
* @returns {PathEntry}
|
|
149
|
+
*/
|
|
150
|
+
function pathEntryFromBare(str) {
|
|
151
|
+
const bare = str.startsWith('{') ? null : matchBarePathToken(str);
|
|
152
|
+
if (bare !== null) return { path: bare, assumption: null };
|
|
153
|
+
|
|
154
|
+
const shape = isProseBullet(str)
|
|
155
|
+
? 'is prose, not a path'
|
|
156
|
+
: 'names no usable path';
|
|
218
157
|
throw new StoryBodyParseError(
|
|
219
|
-
`changes/references entry
|
|
158
|
+
`changes/references entry ${shape} — a bullet must be a single ` +
|
|
159
|
+
`whitespace-free path token, or a { path, assumption } object: ` +
|
|
160
|
+
`${str.slice(0, 120)}${pathEntryFixIt(str)}`,
|
|
220
161
|
{ field: 'changes', raw: str },
|
|
221
162
|
);
|
|
222
163
|
}
|
|
223
164
|
|
|
224
165
|
/**
|
|
225
|
-
*
|
|
226
|
-
*
|
|
166
|
+
* A canonical value (pinned), `null` (omitted — persist derives it), or
|
|
167
|
+
* `undefined` (not an assumption — a typo must fail closed).
|
|
227
168
|
*
|
|
169
|
+
* @param {unknown} raw
|
|
170
|
+
* @returns {string|null|undefined}
|
|
171
|
+
*/
|
|
172
|
+
function readAssumption(raw) {
|
|
173
|
+
if (FILE_ASSUMPTION_VALUES.includes(raw)) return raw;
|
|
174
|
+
return raw == null ? null : undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
228
178
|
* @param {object} raw
|
|
229
179
|
* @returns {PathEntry}
|
|
230
180
|
*/
|
|
231
181
|
function pathEntryFromObject(raw) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
) {
|
|
237
|
-
return { path: raw.path.trim(), assumption: raw.assumption };
|
|
182
|
+
const path = typeof raw.path === 'string' ? raw.path.trim() : '';
|
|
183
|
+
const assumption = readAssumption(raw.assumption);
|
|
184
|
+
if (path !== '' && assumption !== undefined) {
|
|
185
|
+
return { path, assumption };
|
|
238
186
|
}
|
|
239
|
-
// Malformed object: fail closed.
|
|
240
187
|
throw new StoryBodyParseError(
|
|
241
188
|
`changes/references entry is an object but not a valid PathEntry: ${JSON.stringify(raw)}`,
|
|
242
189
|
{ field: 'changes', raw: JSON.stringify(raw) },
|
|
@@ -244,10 +191,7 @@ function pathEntryFromObject(raw) {
|
|
|
244
191
|
}
|
|
245
192
|
|
|
246
193
|
/**
|
|
247
|
-
*
|
|
248
|
-
* Story #4600): `` `path` — assumption ``. Returns `null` when the line is
|
|
249
|
-
* not that shape at all; fails closed when the shape is recognized but the
|
|
250
|
-
* fields are invalid.
|
|
194
|
+
* `null` when not the humanized shape; throws when recognized but invalid.
|
|
251
195
|
*
|
|
252
196
|
* @param {string} str
|
|
253
197
|
* @returns {PathEntry|null}
|
|
@@ -259,7 +203,6 @@ function pathEntryFromHumanized(str) {
|
|
|
259
203
|
if (path.length > 0 && FILE_ASSUMPTION_VALUES.includes(humanized[2])) {
|
|
260
204
|
return { path, assumption: humanized[2] };
|
|
261
205
|
}
|
|
262
|
-
// Recognized the humanized shape but the fields are invalid: fail closed.
|
|
263
206
|
throw new StoryBodyParseError(
|
|
264
207
|
`changes/references entry is a humanized bullet but not a valid PathEntry: ${str.slice(0, 120)}${pathEntryFixIt(str)}`,
|
|
265
208
|
{ field: 'changes', raw: str },
|
|
@@ -267,11 +210,7 @@ function pathEntryFromHumanized(str) {
|
|
|
267
210
|
}
|
|
268
211
|
|
|
269
212
|
/**
|
|
270
|
-
*
|
|
271
|
-
* `{ "path": "...", "assumption": "..." }`. Returns `null` when the line is
|
|
272
|
-
* not a JSON object at all (including a JSON parse failure — the caller then
|
|
273
|
-
* rejects the plain-string form); fails closed when it parses to an object
|
|
274
|
-
* without valid PathEntry fields.
|
|
213
|
+
* `null` when not a JSON object (the caller then tries the bare form).
|
|
275
214
|
*
|
|
276
215
|
* @param {string} str
|
|
277
216
|
* @returns {PathEntry|null}
|
|
@@ -282,28 +221,16 @@ function pathEntryFromInlineJson(str) {
|
|
|
282
221
|
try {
|
|
283
222
|
parsed = JSON.parse(str);
|
|
284
223
|
} catch {
|
|
285
|
-
// JSON parse failed — the caller rejects the plain-string form.
|
|
286
224
|
return null;
|
|
287
225
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
FILE_ASSUMPTION_VALUES.includes(parsed.assumption)
|
|
292
|
-
) {
|
|
293
|
-
return { path: parsed.path.trim(), assumption: parsed.assumption };
|
|
294
|
-
}
|
|
295
|
-
// Parsed successfully as JSON object but has invalid fields — fail closed.
|
|
296
|
-
throw new StoryBodyParseError(
|
|
297
|
-
`changes/references entry is a JSON object but not a valid PathEntry: ${str}`,
|
|
298
|
-
{ field: 'changes', raw: str },
|
|
299
|
-
);
|
|
226
|
+
return parsed !== null && typeof parsed === 'object'
|
|
227
|
+
? pathEntryFromObject(parsed)
|
|
228
|
+
: null;
|
|
300
229
|
}
|
|
301
230
|
|
|
302
231
|
/**
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
* an empty string when nothing is inferable, so callers can append it
|
|
306
|
-
* unconditionally (Story #4684 — mechanical auto-fix in the failure output).
|
|
232
|
+
* ` Suggested fix: …` suffix for a rejected bullet, or '' when nothing is
|
|
233
|
+
* inferable.
|
|
307
234
|
*
|
|
308
235
|
* @param {string} raw The rejected bullet text.
|
|
309
236
|
* @returns {string}
|
|
@@ -315,11 +242,7 @@ function pathEntryFixIt(raw) {
|
|
|
315
242
|
}
|
|
316
243
|
|
|
317
244
|
/**
|
|
318
|
-
*
|
|
319
|
-
* the last `---` separator). Returns an array of "#N" strings.
|
|
320
|
-
*
|
|
321
|
-
* Delegates to `./footer-block.js`, which owns the footer-block grammar
|
|
322
|
-
* (Story #5046) so the body parser and the dispatch-edge parser cannot
|
|
245
|
+
* Delegates to footer-block.js so the body and dispatch-edge parsers cannot
|
|
323
246
|
* disagree about what declares an edge.
|
|
324
247
|
*
|
|
325
248
|
* @param {string} footerBlock
|
|
@@ -330,15 +253,8 @@ function extractBlockedBy(footerBlock) {
|
|
|
330
253
|
}
|
|
331
254
|
|
|
332
255
|
/**
|
|
333
|
-
* Split markdown into named sections plus
|
|
334
|
-
*
|
|
335
|
-
* Returns `{ sections: Map<string, string[]>, footer: string }`.
|
|
336
|
-
* Each map value is the raw non-empty content lines under that heading
|
|
337
|
-
* (heading line stripped).
|
|
338
|
-
*
|
|
339
|
-
* A `---` followed by recognised footer keys (`parent:`, `Epic:`,
|
|
340
|
-
* `blocked by`) marks the start of the footer block. Content after the
|
|
341
|
-
* footer separator is NOT parsed as sections.
|
|
256
|
+
* Split markdown into named sections plus the footer block; content after
|
|
257
|
+
* the footer separator is not parsed as sections.
|
|
342
258
|
*
|
|
343
259
|
* @param {string} markdown
|
|
344
260
|
* @returns {{ sections: Map<string, string[]>, footer: string, preamble: string }}
|
|
@@ -359,20 +275,9 @@ function splitSections(markdown) {
|
|
|
359
275
|
break;
|
|
360
276
|
}
|
|
361
277
|
|
|
362
|
-
//
|
|
363
|
-
//
|
|
364
|
-
//
|
|
365
|
-
// parser accepts both levels. Any other heading depth is ignored.
|
|
366
|
-
//
|
|
367
|
-
// The token class is `[\w-]+` (not bare `\w+`) so a single hyphenated
|
|
368
|
-
// heading word — the canonical `## Non-Goals` negative-scope section —
|
|
369
|
-
// matches as one token. The captured name is normalized (lower-cased,
|
|
370
|
-
// `-` folded to `_`) before the HEADING_TO_FIELD lookup, so `Non-Goals`
|
|
371
|
-
// resolves to the `non_goals` field. Multi-word headings that contain a
|
|
372
|
-
// space (`## Out of Scope`, `## Agent Prompts`) still do NOT match this
|
|
373
|
-
// single-token shape — they fall through to the section-terminator branch
|
|
374
|
-
// below, which closes the open section. The chosen canonical spelling is
|
|
375
|
-
// therefore the hyphenated single token `## Non-Goals`.
|
|
278
|
+
// `##` or `###` (GitHub Issue Forms render labels as level 3). The token
|
|
279
|
+
// is a single `[\w-]+` word so `Non-Goals` matches; multi-word headings
|
|
280
|
+
// fall through to the terminator branch below.
|
|
376
281
|
const fieldHeadingMatch = line.match(/^#{2,3}\s+([\w-]+)\s*$/i);
|
|
377
282
|
const fieldName = fieldHeadingMatch?.[1]?.toLowerCase().replace(/-/g, '_');
|
|
378
283
|
if (HEADING_TO_FIELD.has(fieldName)) {
|
|
@@ -403,14 +308,9 @@ function splitSections(markdown) {
|
|
|
403
308
|
}
|
|
404
309
|
|
|
405
310
|
/**
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
* / `## Sequencing` blocks, for instance — must not bleed into the last
|
|
410
|
-
* structured section's bullet list (Story #4270). Without this, those
|
|
411
|
-
* lines were silently absorbed into `verify[]` / `acceptance[]`. The
|
|
412
|
-
* heading and everything under it is dropped from structured parsing
|
|
413
|
-
* (it is extended, non-canonical markdown).
|
|
311
|
+
* A non-canonical heading closes the current section so appended extended
|
|
312
|
+
* content (e.g. `## Agent Prompts`) never bleeds into `verify[]` /
|
|
313
|
+
* `acceptance[]`. Text-block sections keep their own headings.
|
|
414
314
|
*
|
|
415
315
|
* @param {string} line
|
|
416
316
|
* @param {boolean} inPreamble
|
|
@@ -426,11 +326,6 @@ function isSectionTerminatorHeading(line, inPreamble, currentSection) {
|
|
|
426
326
|
}
|
|
427
327
|
|
|
428
328
|
/**
|
|
429
|
-
* True for the legacy machine-managed marker lines section parsing skips
|
|
430
|
-
* wherever they appear (see the regexes above): a `## References` section
|
|
431
|
-
* immediately followed by a retired meta block must not swallow the comment
|
|
432
|
-
* as a references entry.
|
|
433
|
-
*
|
|
434
329
|
* @param {string} line
|
|
435
330
|
* @returns {boolean}
|
|
436
331
|
*/
|
|
@@ -442,19 +337,13 @@ function isMachineMarkerLine(line) {
|
|
|
442
337
|
);
|
|
443
338
|
}
|
|
444
339
|
|
|
445
|
-
// ---------------------------------------------------------------------------
|
|
446
|
-
// Parser — per-section sub-parsers
|
|
447
|
-
// ---------------------------------------------------------------------------
|
|
448
|
-
|
|
449
340
|
/**
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
* back to the preamble text (or the whole trimmed input), `depends_on` is
|
|
453
|
-
* still recovered from the footer, and all section arrays are empty.
|
|
341
|
+
* Minimal result for a body with no structured section: goal falls back to
|
|
342
|
+
* the preamble, `depends_on` is still read from the footer.
|
|
454
343
|
*
|
|
455
|
-
* @param {string} input
|
|
456
|
-
* @param {string} preamble
|
|
457
|
-
* @param {string} footer
|
|
344
|
+
* @param {string} input
|
|
345
|
+
* @param {string} preamble
|
|
346
|
+
* @param {string} footer
|
|
458
347
|
* @returns {ParseResult}
|
|
459
348
|
*/
|
|
460
349
|
function parseUnstructuredBody(input, preamble, footer) {
|
|
@@ -490,10 +379,7 @@ function parseUnstructuredBody(input, preamble, footer) {
|
|
|
490
379
|
}
|
|
491
380
|
|
|
492
381
|
/**
|
|
493
|
-
*
|
|
494
|
-
* single one-line goal string.
|
|
495
|
-
*
|
|
496
|
-
* @param {string[]} lines - Raw content lines under the heading.
|
|
382
|
+
* @param {string[]} lines
|
|
497
383
|
* @returns {string}
|
|
498
384
|
*/
|
|
499
385
|
function parseGoalSection(lines) {
|
|
@@ -504,10 +390,8 @@ function parseGoalSection(lines) {
|
|
|
504
390
|
}
|
|
505
391
|
|
|
506
392
|
/**
|
|
507
|
-
*
|
|
508
|
-
*
|
|
509
|
-
* preserved so a bullet list, compact table, or folded Tech Spec survives the
|
|
510
|
-
* round-trip; only blank lines and trailing whitespace are normalized.
|
|
393
|
+
* Line breaks are preserved so lists and tables round-trip; only blank edge
|
|
394
|
+
* lines and trailing whitespace are normalized.
|
|
511
395
|
*
|
|
512
396
|
* @param {string[]} lines
|
|
513
397
|
* @returns {string}
|
|
@@ -520,12 +404,8 @@ function parseTextBlockSection(lines) {
|
|
|
520
404
|
}
|
|
521
405
|
|
|
522
406
|
/**
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
* dropped, and each surviving entry is normalized via {@link parsePathEntry}.
|
|
526
|
-
*
|
|
527
|
-
* @param {string[]} lines - Raw content lines under the heading.
|
|
528
|
-
* @param {string[]} warnings - Mutable warnings sink.
|
|
407
|
+
* @param {string[]} lines
|
|
408
|
+
* @param {string[]} warnings
|
|
529
409
|
* @returns {PathEntry[]}
|
|
530
410
|
*/
|
|
531
411
|
function parsePathEntrySection(lines, warnings) {
|
|
@@ -540,46 +420,17 @@ function parsePathEntrySection(lines, warnings) {
|
|
|
540
420
|
}
|
|
541
421
|
|
|
542
422
|
/**
|
|
543
|
-
*
|
|
544
|
-
* list of trimmed strings, dropping blank entries.
|
|
545
|
-
*
|
|
546
|
-
* @param {string[]} lines - Raw content lines under the heading.
|
|
423
|
+
* @param {string[]} lines
|
|
547
424
|
* @returns {string[]}
|
|
548
425
|
*/
|
|
549
426
|
function parseTextListSection(lines) {
|
|
550
427
|
return lines.map((l) => stripListMarker(l)).filter(Boolean);
|
|
551
428
|
}
|
|
552
429
|
|
|
553
|
-
// ---------------------------------------------------------------------------
|
|
554
|
-
// Parser
|
|
555
|
-
// ---------------------------------------------------------------------------
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* Parse a GitHub Story issue body (markdown string) into a structured
|
|
559
|
-
* {@link StoryBody}. Fails closed on malformed input.
|
|
560
|
-
*
|
|
561
|
-
* Returns a {@link ParseResult} containing the body, any non-fatal
|
|
562
|
-
* warnings, and parse metadata. Use `result.body` directly; inspect
|
|
563
|
-
* `result.warnings` to detect legacy path entries that should be
|
|
564
|
-
* migrated.
|
|
565
|
-
*
|
|
566
|
-
* @param {string|object} input - Markdown string or already-structured body object.
|
|
567
|
-
* @returns {ParseResult}
|
|
568
|
-
* @throws {StoryBodyParseError} When the body is structurally unrecoverable.
|
|
569
|
-
*/
|
|
570
430
|
/**
|
|
571
|
-
* Strip
|
|
572
|
-
*
|
|
573
|
-
*
|
|
574
|
-
* its position in `acceptance[]`; an authored item that already carries one
|
|
575
|
-
* would render doubled (`- [ ] AC-1: AC-1: …`) and a lettered handle copied
|
|
576
|
-
* from a source ticket would survive into the machine contract. Both parse
|
|
577
|
-
* and the persist-side normalisation resolve the grammar here so the two can
|
|
578
|
-
* never disagree about what a handle is (Story #5323).
|
|
579
|
-
*
|
|
580
|
-
* Stacked handles are peeled in full — a body persisted while the doubling
|
|
581
|
-
* was live carries two, and leaving the inner one would normalise to
|
|
582
|
-
* something that still is not the authored text.
|
|
431
|
+
* Strip every stacked `AC-<n>:` handle. serialize() numbers checkboxes from
|
|
432
|
+
* position, so a kept handle would render doubled; parse and persist share
|
|
433
|
+
* this so they agree on the grammar.
|
|
583
434
|
*
|
|
584
435
|
* @param {string} item
|
|
585
436
|
* @returns {{ text: string, stripped: boolean }} The handle-free text, and
|
|
@@ -594,6 +445,13 @@ export function stripAcceptanceHandle(item) {
|
|
|
594
445
|
return { text, stripped: text !== original };
|
|
595
446
|
}
|
|
596
447
|
|
|
448
|
+
/**
|
|
449
|
+
* Parse a Story issue body (markdown or structured object).
|
|
450
|
+
*
|
|
451
|
+
* @param {string|object} input - Markdown string or already-structured body object.
|
|
452
|
+
* @returns {ParseResult}
|
|
453
|
+
* @throws {StoryBodyParseError} When the body is structurally unrecoverable.
|
|
454
|
+
*/
|
|
597
455
|
export function parse(input) {
|
|
598
456
|
if (input === null || input === undefined) {
|
|
599
457
|
throw new StoryBodyParseError('Story body is null or undefined', {
|
|
@@ -601,8 +459,6 @@ export function parse(input) {
|
|
|
601
459
|
});
|
|
602
460
|
}
|
|
603
461
|
|
|
604
|
-
// If the caller already has a structured object (e.g. from the decomposer
|
|
605
|
-
// before it's serialized to markdown), parse it directly.
|
|
606
462
|
if (typeof input === 'object' && !Array.isArray(input)) {
|
|
607
463
|
return parseStructuredObject(input);
|
|
608
464
|
}
|
|
@@ -626,7 +482,6 @@ export function parse(input) {
|
|
|
626
482
|
const hasSlicingSection = sections.has('slicing');
|
|
627
483
|
const hasSpecSection = sections.has('spec');
|
|
628
484
|
|
|
629
|
-
// If no structured sections found, treat as unstructured body.
|
|
630
485
|
const isUnstructuredBody =
|
|
631
486
|
!hasGoalSection &&
|
|
632
487
|
!hasChangesSection &&
|
|
@@ -638,19 +493,12 @@ export function parse(input) {
|
|
|
638
493
|
}
|
|
639
494
|
|
|
640
495
|
const goal = parseGoalSection(sections.get('goal') ?? []);
|
|
641
|
-
// Optional v2 intra-Story delivery slice plan (`## Slicing`). Preserved as
|
|
642
|
-
// a verbatim text block — a large Story (what v1 called an Epic) folds its
|
|
643
|
-
// Delivery Slicing here instead of fanning out into sibling Stories; a
|
|
644
|
-
// trivial Story omits it entirely. Parsed as a text block so a bullet list
|
|
645
|
-
// or compact table round-trips.
|
|
646
496
|
const slicing = parseTextBlockSection(sections.get('slicing') ?? []);
|
|
647
497
|
const spec = parseTextBlockSection(sections.get('spec') ?? []);
|
|
648
498
|
const changes = parsePathEntrySection(
|
|
649
499
|
sections.get('changes') ?? [],
|
|
650
500
|
warnings,
|
|
651
501
|
);
|
|
652
|
-
// The AC-<n> checkbox prefix is presentation-only (Story #4600): strip it
|
|
653
|
-
// so acceptance[] round-trips byte-identical to the authored array.
|
|
654
502
|
const acceptance = parseTextListSection(sections.get('acceptance') ?? []).map(
|
|
655
503
|
(a) => stripAcceptanceHandle(a).text,
|
|
656
504
|
);
|
|
@@ -692,9 +540,7 @@ export function parse(input) {
|
|
|
692
540
|
}
|
|
693
541
|
|
|
694
542
|
/**
|
|
695
|
-
*
|
|
696
|
-
* output, before markdown serialization). Normalizes all fields to the
|
|
697
|
-
* canonical shape.
|
|
543
|
+
* Normalize a structured body object (pre-serialization decomposer output).
|
|
698
544
|
*
|
|
699
545
|
* @param {object} obj
|
|
700
546
|
* @returns {ParseResult}
|
|
@@ -702,10 +548,6 @@ export function parse(input) {
|
|
|
702
548
|
function parseStructuredObject(obj) {
|
|
703
549
|
const warnings = [];
|
|
704
550
|
|
|
705
|
-
// The declarative half of the normalization: every field whose value is a
|
|
706
|
-
// pure function of its raw input (plus the shared warnings sink) is one
|
|
707
|
-
// table row, walked in canonical body-key order. Adding a field of an
|
|
708
|
-
// existing kind is a one-row change.
|
|
709
551
|
const body = {};
|
|
710
552
|
for (const { name, kind } of STRUCTURED_FIELD_SPECS) {
|
|
711
553
|
body[name] = STRUCTURED_FIELD_NORMALIZERS[kind](obj[name], warnings);
|
|
@@ -729,36 +571,23 @@ function parseStructuredObject(obj) {
|
|
|
729
571
|
}
|
|
730
572
|
|
|
731
573
|
/**
|
|
732
|
-
*
|
|
733
|
-
* body-key order. `kind` selects the normalizer from
|
|
734
|
-
* {@link STRUCTURED_FIELD_NORMALIZERS}:
|
|
735
|
-
* - `text` — trimmed string, or `''` when absent/non-string.
|
|
736
|
-
* - `stringList` — array filtered to non-empty strings, else `[]`.
|
|
737
|
-
* - `pathEntryList` — array normalized entry-wise via `parsePathEntry`
|
|
738
|
-
* (fails closed on a malformed entry), else `[]`.
|
|
574
|
+
* Field specs in canonical body-key order.
|
|
739
575
|
*
|
|
740
576
|
* @type {Array<{ name: string, kind: keyof typeof STRUCTURED_FIELD_NORMALIZERS }>}
|
|
741
577
|
*/
|
|
742
578
|
const STRUCTURED_FIELD_SPECS = [
|
|
743
579
|
{ name: 'goal', kind: 'text' },
|
|
744
|
-
// slicing — optional v2 intra-Story delivery slice plan (verbatim text).
|
|
745
580
|
{ name: 'slicing', kind: 'text' },
|
|
746
|
-
// spec — optional folded Tech Spec (verbatim text).
|
|
747
581
|
{ name: 'spec', kind: 'text' },
|
|
748
582
|
{ name: 'changes', kind: 'pathEntryList' },
|
|
749
583
|
{ name: 'acceptance', kind: 'stringList' },
|
|
750
584
|
{ name: 'verify', kind: 'stringList' },
|
|
751
585
|
{ name: 'references', kind: 'pathEntryList' },
|
|
752
|
-
// non_goals — advisory negative-scope bullets.
|
|
753
586
|
{ name: 'non_goals', kind: 'stringList' },
|
|
754
|
-
// depends_on — may be at top level or in body.
|
|
755
587
|
{ name: 'depends_on', kind: 'stringList' },
|
|
756
588
|
];
|
|
757
589
|
|
|
758
590
|
/**
|
|
759
|
-
* One normalizer per {@link STRUCTURED_FIELD_SPECS} kind. Each takes the raw
|
|
760
|
-
* field value plus the shared warnings sink and returns the canonical value.
|
|
761
|
-
*
|
|
762
591
|
* @type {Record<string, (raw: unknown, warnings: string[]) => unknown>}
|
|
763
592
|
*/
|
|
764
593
|
const STRUCTURED_FIELD_NORMALIZERS = {
|
|
@@ -777,34 +606,19 @@ const STRUCTURED_FIELD_NORMALIZERS = {
|
|
|
777
606
|
},
|
|
778
607
|
};
|
|
779
608
|
|
|
780
|
-
// ---------------------------------------------------------------------------
|
|
781
|
-
// Serializer
|
|
782
|
-
// ---------------------------------------------------------------------------
|
|
783
|
-
|
|
784
609
|
/**
|
|
785
|
-
* Render a `PathEntry | string` as a markdown list item.
|
|
786
|
-
*
|
|
787
610
|
* @param {PathEntry | string} entry
|
|
788
611
|
* @returns {string}
|
|
789
612
|
*/
|
|
790
613
|
function serializePathEntry(entry) {
|
|
791
614
|
if (typeof entry === 'string') return entry;
|
|
792
|
-
//
|
|
793
|
-
|
|
794
|
-
// shape (and the legacy inline-JSON shape) for round-trip fidelity.
|
|
795
|
-
return `\`${entry.path}\` — ${entry.assumption}`;
|
|
615
|
+
// A bare entry (no assumption) stays bare; persist derives the assumption.
|
|
616
|
+
return [`\`${entry.path}\``, entry.assumption].filter(Boolean).join(' — ');
|
|
796
617
|
}
|
|
797
618
|
|
|
798
619
|
/**
|
|
799
|
-
*
|
|
800
|
-
*
|
|
801
|
-
* `## Acceptance`, `## Verify`, `## References`, `## Non-Goals`). Each
|
|
802
|
-
* descriptor reads one body field and returns the section's markdown block
|
|
803
|
-
* when the field is present and non-empty, or `null` to omit the section.
|
|
804
|
-
*
|
|
805
|
-
* Standardising the section ladder as a single data table makes adding a new
|
|
806
|
-
* optional section a one-line edit here rather than a new control-flow branch
|
|
807
|
-
* in {@link serialize}.
|
|
620
|
+
* Sections in canonical emit order; `render` returns `null` to omit, so an
|
|
621
|
+
* absent optional field keeps older bodies round-tripping byte-identically.
|
|
808
622
|
*
|
|
809
623
|
* @type {Array<{ field: string, render: (value: unknown) => string | null }>}
|
|
810
624
|
*/
|
|
@@ -817,10 +631,6 @@ const SERIALIZE_SECTIONS = [
|
|
|
817
631
|
: null,
|
|
818
632
|
},
|
|
819
633
|
{
|
|
820
|
-
// Optional v2 intra-Story delivery slice plan. Single-token `## Slicing`
|
|
821
|
-
// heading (recognized by the `[\w-]+` field-heading regex). Verbatim text
|
|
822
|
-
// block. Render-when-non-empty: an absent/empty `slicing` emits nothing,
|
|
823
|
-
// so every pre-v2 body round-trips byte-identically.
|
|
824
634
|
field: 'slicing',
|
|
825
635
|
render: (slicing) =>
|
|
826
636
|
typeof slicing === 'string' && slicing.trim().length > 0
|
|
@@ -828,8 +638,6 @@ const SERIALIZE_SECTIONS = [
|
|
|
828
638
|
: null,
|
|
829
639
|
},
|
|
830
640
|
{
|
|
831
|
-
// Optional folded Tech Spec. Like `## Slicing`, this is a verbatim text
|
|
832
|
-
// block and emits nothing for absent/empty pre-v2 bodies.
|
|
833
641
|
field: 'spec',
|
|
834
642
|
render: (spec) =>
|
|
835
643
|
typeof spec === 'string' && spec.trim().length > 0
|
|
@@ -844,10 +652,6 @@ const SERIALIZE_SECTIONS = [
|
|
|
844
652
|
: null,
|
|
845
653
|
},
|
|
846
654
|
{
|
|
847
|
-
// Each checkbox carries a stable 1-based `AC-<n>:` handle (Story #4600)
|
|
848
|
-
// so humans and reviewers can reference criteria by number. The prefix
|
|
849
|
-
// is presentation-only — parse() strips it, and validators compare the
|
|
850
|
-
// top-level acceptance[] array, so numbering never affects gating.
|
|
851
655
|
field: 'acceptance',
|
|
852
656
|
render: (acceptance) =>
|
|
853
657
|
Array.isArray(acceptance) && acceptance.length > 0
|
|
@@ -869,11 +673,6 @@ const SERIALIZE_SECTIONS = [
|
|
|
869
673
|
: null,
|
|
870
674
|
},
|
|
871
675
|
{
|
|
872
|
-
// Advisory negative-scope bullets. Rendered as the hyphenated canonical
|
|
873
|
-
// `## Non-Goals` heading (the spelling the parser's widened
|
|
874
|
-
// `[\w-]+` field-heading regex recognizes). Render-when-non-empty: an
|
|
875
|
-
// empty or absent `non_goals` emits nothing, so every pre-existing body
|
|
876
|
-
// round-trips byte-identically.
|
|
877
676
|
field: 'non_goals',
|
|
878
677
|
render: (nonGoals) =>
|
|
879
678
|
Array.isArray(nonGoals) && nonGoals.length > 0
|
|
@@ -883,9 +682,6 @@ const SERIALIZE_SECTIONS = [
|
|
|
883
682
|
];
|
|
884
683
|
|
|
885
684
|
/**
|
|
886
|
-
* Build the optional `---` footer block (`parent` / `blocked by` lines).
|
|
887
|
-
* Returns the empty string when `opts.includeFooter` is falsy.
|
|
888
|
-
*
|
|
889
685
|
* @param {StoryBody} body
|
|
890
686
|
* @param {SerializeOptions} opts
|
|
891
687
|
* @returns {string}
|
|
@@ -894,9 +690,7 @@ function serializeFooter(body, opts) {
|
|
|
894
690
|
if (!opts.includeFooter) return '';
|
|
895
691
|
const footerLines = ['---'];
|
|
896
692
|
if (opts.footer?.parent) footerLines.push(`parent: #${opts.footer.parent}`);
|
|
897
|
-
//
|
|
898
|
-
// Story body carrying that footer, so composing one here would let the
|
|
899
|
-
// framework generate work it would then reject at delivery.
|
|
693
|
+
// Never an `Epic: #N` line: pr-base-guard.js refuses a body carrying one.
|
|
900
694
|
if (Array.isArray(body.depends_on)) {
|
|
901
695
|
for (const dep of body.depends_on) {
|
|
902
696
|
footerLines.push(`blocked by ${dep}`);
|
|
@@ -906,13 +700,6 @@ function serializeFooter(body, opts) {
|
|
|
906
700
|
}
|
|
907
701
|
|
|
908
702
|
/**
|
|
909
|
-
* Serialize a structured {@link StoryBody} back to the canonical markdown
|
|
910
|
-
* format written to GitHub issue bodies.
|
|
911
|
-
*
|
|
912
|
-
* The output matches the section order the spec-renderer uses:
|
|
913
|
-
* `## Goal`, `## Slicing`, `## Spec`, `## Changes`, `## Acceptance`,
|
|
914
|
-
* `## Verify`, `## References`, `## Non-Goals` (each omitted when empty).
|
|
915
|
-
*
|
|
916
703
|
* @param {StoryBody} body
|
|
917
704
|
* @param {SerializeOptions} [opts]
|
|
918
705
|
* @returns {string}
|
|
@@ -933,17 +720,9 @@ export function serialize(body, opts = {}) {
|
|
|
933
720
|
return sections.join('\n\n') + serializeFooter(body, opts);
|
|
934
721
|
}
|
|
935
722
|
|
|
936
|
-
// ---------------------------------------------------------------------------
|
|
937
|
-
// Convenience: extract changes paths for the wave planner
|
|
938
|
-
// ---------------------------------------------------------------------------
|
|
939
|
-
|
|
940
723
|
/**
|
|
941
|
-
*
|
|
942
|
-
*
|
|
943
|
-
*
|
|
944
|
-
* The wave planner (Feature 3) uses this to compute file-overlap
|
|
945
|
-
* serialization between Stories: if any entry `isGlob`, the Story's
|
|
946
|
-
* footprint is `unknown-width`.
|
|
724
|
+
* Path strings from `changes[]`; any glob entry makes the footprint
|
|
725
|
+
* unknown-width for the wave planner.
|
|
947
726
|
*
|
|
948
727
|
* @param {ChangeEntry[]} changes
|
|
949
728
|
* @returns {Array<{ path: string, isGlob: boolean }>}
|