mandrel 1.93.0 → 2.0.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 +59 -73
- package/.agents/agents/acceptance-critic.md +129 -0
- package/.agents/agents/story-worker.md +161 -0
- package/.agents/docs/SDLC.md +489 -1285
- package/.agents/docs/agentrc-reference.json +177 -67
- package/.agents/docs/configuration.md +108 -136
- package/.agents/docs/execution-reference.md +44 -22
- package/.agents/docs/quality-gates.md +13 -19
- package/.agents/docs/workflows.md +3 -3
- package/.agents/instructions.md +107 -108
- package/.agents/rules/ci-remediation.md +8 -12
- package/.agents/rules/git-conventions-reference.md +224 -0
- package/.agents/rules/git-conventions.md +42 -223
- package/.agents/rules/security-baseline.md +5 -0
- package/.agents/rules/testing-standards.md +106 -13
- package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
- package/.agents/schemas/agentrc.schema.json +71 -201
- package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
- package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
- package/.agents/schemas/risk-verdict.schema.json +0 -13
- package/.agents/scripts/acceptance-eval.js +62 -18
- package/.agents/scripts/agents-bootstrap-github.js +1 -1
- package/.agents/scripts/analyze-execution.js +1 -1
- package/.agents/scripts/audit-to-stories.js +7 -7
- package/.agents/scripts/boot-sweep.js +1 -1
- package/.agents/scripts/check-context-budget.js +62 -5
- package/.agents/scripts/check-lifecycle-lint.js +6 -9
- package/.agents/scripts/check-prepush-recovery.js +1 -1
- package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
- package/.agents/scripts/diagnose-friction.js +0 -6
- package/.agents/scripts/lib/Logger.js +6 -10
- package/.agents/scripts/lib/audit-suite/runner.js +2 -2
- package/.agents/scripts/lib/audit-suite/selector.js +5 -5
- package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
- package/.agents/scripts/lib/baselines/kernel.js +206 -18
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -4
- package/.agents/scripts/lib/baselines/reader.js +1 -6
- package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
- package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +56 -18
- package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
- package/.agents/scripts/lib/checks/index.js +2 -1
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
- package/.agents/scripts/lib/cli/standard-args.js +13 -22
- package/.agents/scripts/lib/cli-args.js +16 -7
- package/.agents/scripts/lib/close-validation/gates.js +160 -22
- package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
- package/.agents/scripts/lib/config/ci.js +6 -31
- package/.agents/scripts/lib/config/delivery-routing.js +103 -0
- package/.agents/scripts/lib/config/explain.js +57 -36
- package/.agents/scripts/lib/config/limits.js +17 -58
- package/.agents/scripts/lib/config/paths.js +0 -2
- package/.agents/scripts/lib/config/quality.js +1 -1
- package/.agents/scripts/lib/config/runners.js +17 -50
- package/.agents/scripts/lib/config/temp-paths.js +19 -14
- package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
- package/.agents/scripts/lib/config-resolver.js +3 -8
- package/.agents/scripts/lib/config-settings-schema-delivery.js +46 -136
- package/.agents/scripts/lib/config-settings-schema-quality.js +17 -14
- package/.agents/scripts/lib/config-settings-schema.js +52 -38
- package/.agents/scripts/lib/dependency-parser.js +3 -2
- package/.agents/scripts/lib/doc-tiers.js +39 -4
- package/.agents/scripts/lib/duplicate-search.js +211 -41
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
- package/.agents/scripts/lib/findings/promote-finding.js +5 -5
- package/.agents/scripts/lib/framework-version.js +2 -3
- package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
- package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
- package/.agents/scripts/lib/git-utils.js +32 -6
- package/.agents/scripts/lib/github/framework-repo.js +6 -0
- package/.agents/scripts/lib/label-constants.js +10 -23
- package/.agents/scripts/lib/label-taxonomy.js +9 -43
- package/.agents/scripts/lib/observability/active-story-env.js +112 -3
- package/.agents/scripts/lib/observability/hook-heartbeat.js +187 -0
- package/.agents/scripts/lib/observability/source-classifier.js +3 -3
- package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
- package/.agents/scripts/lib/onboard/init-tail.js +1 -3
- package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
- package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
- package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +273 -0
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +204 -0
- package/.agents/scripts/lib/orchestration/code-review.js +20 -268
- package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
- package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
- package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
- package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
- package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +8 -8
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
- package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
- package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
- package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +3 -2
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
- package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
- package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
- package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
- package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
- package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +14 -14
- package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
- package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
- package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
- package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
- package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
- package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
- package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
- package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
- package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
- package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
- package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
- package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
- package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +1 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
- package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
- package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
- package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
- package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -12
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
- package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
- package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
- package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
- package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
- package/.agents/scripts/lib/orchestration/ticket-validator.js +3 -8
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
- package/.agents/scripts/lib/planning-corpus.js +16 -11
- package/.agents/scripts/lib/preflight-runner.js +2 -2
- package/.agents/scripts/lib/provider-factory.js +1 -1
- package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
- package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
- package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
- package/.agents/scripts/lib/story-adjacency.js +11 -14
- package/.agents/scripts/lib/story-body/story-body.js +124 -70
- package/.agents/scripts/lib/story-plan.js +2 -4
- package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
- package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
- package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
- package/.agents/scripts/lib/validation-evidence.js +1 -1
- package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
- package/.agents/scripts/lib/workspace-provisioner.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
- package/.agents/scripts/lint-issue-body.js +71 -40
- package/.agents/scripts/mandrel-update-preflight.js +1 -1
- package/.agents/scripts/notify.js +4 -3
- package/.agents/scripts/plan-context.js +64 -74
- package/.agents/scripts/plan-persist.js +121 -280
- package/.agents/scripts/plan-run-epilogue.js +97 -0
- package/.agents/scripts/post-structured-comment.js +38 -0
- package/.agents/scripts/providers/github/issues.js +17 -33
- package/.agents/scripts/providers/github/mappers.js +0 -12
- package/.agents/scripts/providers/github/tickets.js +2 -5
- package/.agents/scripts/resolve-plan-run.js +117 -0
- package/.agents/scripts/signals-view.js +24 -19
- package/.agents/scripts/single-story-close.js +11 -14
- package/.agents/scripts/single-story-confirm-merge.js +39 -23
- package/.agents/scripts/single-story-init.js +29 -20
- package/.agents/scripts/stories-wave-tick.js +6 -6
- package/.agents/scripts/story-plan.js +26 -47
- package/.agents/scripts/sync-claude-agents.js +165 -0
- package/.agents/scripts/update-ticket-state.js +37 -15
- package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
- package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
- package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
- package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
- package/.agents/skills/core/idea-refinement/SKILL.md +8 -14
- package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
- package/.agents/skills/core/scope-triage/SKILL.md +28 -172
- package/.agents/skills/skills.index.json +8 -418
- package/.agents/starter-agentrc.json +0 -5
- package/.agents/templates/agent-protocol.md +9 -10
- package/.agents/workflows/audit-architecture.md +3 -3
- package/.agents/workflows/audit-clean-code.md +3 -3
- package/.agents/workflows/audit-dependencies.md +3 -3
- package/.agents/workflows/audit-devops.md +3 -3
- package/.agents/workflows/audit-documentation.md +5 -5
- package/.agents/workflows/audit-lighthouse.md +3 -3
- package/.agents/workflows/audit-navigability.md +3 -2
- package/.agents/workflows/audit-performance.md +3 -3
- package/.agents/workflows/audit-privacy.md +3 -3
- package/.agents/workflows/audit-quality.md +3 -3
- package/.agents/workflows/audit-security.md +3 -3
- package/.agents/workflows/audit-seo.md +3 -3
- package/.agents/workflows/audit-sre.md +3 -3
- package/.agents/workflows/audit-to-stories.md +20 -20
- package/.agents/workflows/audit-ux-ui.md +3 -3
- package/.agents/workflows/deliver.md +122 -131
- package/.agents/workflows/git-cleanup.md +3 -4
- package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
- package/.agents/workflows/helpers/acceptance-self-eval.md +52 -40
- package/.agents/workflows/helpers/code-review.md +70 -193
- package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
- package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
- package/.agents/workflows/helpers/diagnose.md +10 -10
- package/.agents/workflows/helpers/mandrel-sync-config.md +1 -1
- package/.agents/workflows/helpers/parallel-tooling.md +1 -1
- package/.agents/workflows/helpers/signals.md +16 -16
- package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
- package/.agents/workflows/mandrel-update.md +3 -2
- package/.agents/workflows/plan.md +112 -145
- package/.agents/workflows/qa-assist.md +24 -30
- package/.agents/workflows/qa-explore.md +29 -38
- package/.agents/workflows/qa-run.md +2 -2
- package/README.md +9 -8
- package/docs/CHANGELOG.md +46 -0
- package/lib/cli/registry.js +95 -0
- package/lib/migrations/index.js +6 -5
- package/package.json +5 -3
- package/.agents/personas/architect.md +0 -113
- package/.agents/personas/devops-engineer.md +0 -38
- package/.agents/personas/engineer-mobile.md +0 -120
- package/.agents/personas/engineer-web.md +0 -111
- package/.agents/personas/engineer.md +0 -119
- package/.agents/personas/product.md +0 -94
- package/.agents/personas/project-manager.md +0 -114
- package/.agents/personas/qa-engineer.md +0 -95
- package/.agents/personas/refactorer.md +0 -113
- package/.agents/personas/security-engineer.md +0 -112
- package/.agents/personas/sre.md +0 -86
- package/.agents/personas/technical-writer.md +0 -101
- package/.agents/personas/ux-designer.md +0 -95
- package/.agents/schemas/dispatch-manifest.json +0 -232
- package/.agents/schemas/epic-spec.schema.json +0 -153
- package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
- package/.agents/scripts/dispatcher.js +0 -295
- package/.agents/scripts/epic-audit-prepare.js +0 -497
- package/.agents/scripts/epic-audit-recheck.js +0 -274
- package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
- package/.agents/scripts/epic-deliver-preflight.js +0 -462
- package/.agents/scripts/epic-deliver-prepare.js +0 -590
- package/.agents/scripts/epic-execute-record-wave.js +0 -449
- package/.agents/scripts/epic-plan-clarity.js +0 -211
- package/.agents/scripts/epic-plan-decompose.js +0 -54
- package/.agents/scripts/epic-plan-healthcheck.js +0 -581
- package/.agents/scripts/epic-plan-spec.js +0 -64
- package/.agents/scripts/epic-reconcile.js +0 -625
- package/.agents/scripts/lib/baseline-snapshot.js +0 -979
- package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
- package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
- package/.agents/scripts/lib/config/lifecycle.js +0 -40
- package/.agents/scripts/lib/config/preflight.js +0 -58
- package/.agents/scripts/lib/config/retro.js +0 -77
- package/.agents/scripts/lib/epic-merge-lock.js +0 -322
- package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
- package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -660
- package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
- package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
- package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
- package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -388
- package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
- package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
- package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
- package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
- package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
- package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
- package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
- package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
- package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -384
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -278
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
- package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
- package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
- package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
- package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
- package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
- package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
- package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
- package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
- package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
- package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
- package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
- package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +0 -109
- package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
- package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
- package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
- package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
- package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
- package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
- package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
- package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
- package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
- package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
- package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
- package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
- package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
- package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
- package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
- package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
- package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -301
- package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
- package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
- package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
- package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
- package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
- package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
- package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
- package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
- package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
- package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
- package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
- package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
- package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
- package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
- package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
- package/.agents/scripts/lib/push-epic-retry.js +0 -209
- package/.agents/scripts/lib/spec/index.js +0 -36
- package/.agents/scripts/lib/spec/loader.js +0 -425
- package/.agents/scripts/lib/spec/state.js +0 -208
- package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
- package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
- package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
- package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
- package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
- package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
- package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
- package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
- package/.agents/scripts/lib/wave-runner/tick.js +0 -754
- package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
- package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
- package/.agents/scripts/lifecycle-emit.js +0 -510
- package/.agents/scripts/plan-critics.js +0 -199
- package/.agents/scripts/retro-run.js +0 -218
- package/.agents/scripts/standalone-feedback-rollup.js +0 -188
- package/.agents/scripts/story-close.js +0 -294
- package/.agents/scripts/story-init.js +0 -599
- package/.agents/scripts/story-phase.js +0 -369
- package/.agents/scripts/wave-tick.js +0 -335
- package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
- package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
- package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
- package/.agents/skills/core/code-simplification/SKILL.md +0 -389
- package/.agents/skills/core/context-engineering/SKILL.md +0 -309
- package/.agents/skills/core/context-engineering/examples.md +0 -58
- package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
- package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
- package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
- package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
- package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -413
- package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
- package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
- package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
- package/.agents/skills/core/idea-refinement/examples.md +0 -437
- package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
- package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
- package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
- package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
- package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
- package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
- package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
- package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
- package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
- package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
- package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
- package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
- package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
- package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
- package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
- package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
- package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
- package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
- package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
- package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
- package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
- package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
- package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
- package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
- package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
- package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
- package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
- package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
- package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
- package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
- package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
- package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
- package/.agents/workflows/helpers/deliver-epic-reference.md +0 -534
- package/.agents/workflows/helpers/deliver-epic.md +0 -955
- package/.agents/workflows/helpers/deliver-stories.md +0 -440
- package/.agents/workflows/helpers/epic-audit.md +0 -189
- package/.agents/workflows/helpers/epic-deliver-story.md +0 -427
- package/.agents/workflows/helpers/epic-testing.md +0 -125
- package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
- package/.agents/workflows/helpers/plan-epic.md +0 -351
- package/.agents/workflows/helpers/plan-story.md +0 -251
- package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
- /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/lifecycle/ledger-record.schema.json",
|
|
4
4
|
"title": "Lifecycle ledger record (emitted | completed | failed)",
|
|
5
|
-
"description": "Append-only NDJSON record shape for temp/
|
|
5
|
+
"description": "Append-only NDJSON record shape for temp/run-<id>/lifecycle.ndjson. Three discriminated kinds; consumers (LedgerWriter, the ledger-diff assertion helpers, TraceLogger) discriminate on `kind`.",
|
|
6
6
|
"oneOf": [
|
|
7
7
|
{ "$ref": "#/$defs/emitted" },
|
|
8
8
|
{ "$ref": "#/$defs/completed" },
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/lifecycle/retro.end.schema.json",
|
|
4
4
|
"title": "retro.end",
|
|
5
|
-
"description": "Emitted at the end of the retro sub-phase. `posted` indicates whether the retro structured comment was upserted onto the Epic; `retroPath` is the local mirror path under temp/
|
|
5
|
+
"description": "Emitted at the end of the retro sub-phase. `posted` indicates whether the retro structured comment was upserted onto the Epic; `retroPath` is the local mirror path under temp/run-<id>/ when written. Story #2252.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["epicId", "posted"],
|
|
8
8
|
"properties": {
|
|
@@ -47,20 +47,7 @@
|
|
|
47
47
|
"type": "string",
|
|
48
48
|
"minLength": 1,
|
|
49
49
|
"description": "One-paragraph overall risk narrative for the audit trail (the rationale the retired regex classifier could never produce)."
|
|
50
|
-
},
|
|
51
|
-
"deliveryShape": {
|
|
52
|
-
"type": "string",
|
|
53
|
-
"enum": ["fan-out", "single"],
|
|
54
|
-
"description": "Planner-judged delivery shape for the Epic (Epic #4474 PR4, design §2 mode matrix). 'fan-out' persists a Story tree (the default when the field is absent — existing verdicts stay valid); 'single' is the spec-only single-delivery mode: no tickets are authored, the ticket validator + DAG are skipped, and plan-persist applies the delivery::single routing marker instead of a Story tree. The marker is inert until #4475 lands the deliver-side reader."
|
|
55
|
-
},
|
|
56
|
-
"deliveryShapeRationale": {
|
|
57
|
-
"type": "string",
|
|
58
|
-
"minLength": 1,
|
|
59
|
-
"description": "Concrete justification for the declared deliveryShape, grounded in the Delivery Slicing table (slice count / chain shape). Required whenever deliveryShape is present; surfaced as the routingReasons of the single-mode plan summary."
|
|
60
50
|
}
|
|
61
51
|
},
|
|
62
|
-
"dependentRequired": {
|
|
63
|
-
"deliveryShape": ["deliveryShapeRationale"]
|
|
64
|
-
},
|
|
65
52
|
"additionalProperties": false
|
|
66
53
|
}
|
|
@@ -32,9 +32,20 @@
|
|
|
32
32
|
* — this CLI is the decision + signal boundary, mirroring how the existing
|
|
33
33
|
* gates separate decision from ticket mutation.
|
|
34
34
|
*
|
|
35
|
+
* Two invocation shapes (Epic #4475, M4-B):
|
|
36
|
+
* - Per-Story (fan-out): the diff is one Story's; round scoping is per
|
|
37
|
+
* Story off the Story's `signals.ndjson`.
|
|
38
|
+
* - Per-AC-cluster (single delivery): `--epic <id> --cluster <clusterId>`
|
|
39
|
+
* with NO `--story`. The verdict scores one AC cluster of the Epic's
|
|
40
|
+
* `## Acceptance Table` against the cumulative `main..epic/<id>` diff;
|
|
41
|
+
* round scoping is per cluster off the Epic's `signals.ndjson`. This is
|
|
42
|
+
* the acceptance-dilution guard — `ceil(totalACs / clusterCeiling)`
|
|
43
|
+
* independent maker-blind critic passes, one per cluster.
|
|
44
|
+
*
|
|
35
45
|
* CLI:
|
|
36
|
-
* --story <id>
|
|
37
|
-
* --epic <id> Parent Epic ID (
|
|
46
|
+
* --story <id> Story ID (required unless --cluster is given).
|
|
47
|
+
* --epic <id> Parent Epic ID (required with --cluster).
|
|
48
|
+
* --cluster <id> AC-cluster id for the single-delivery critic.
|
|
38
49
|
* --verdict <path> Path to the round's verdict JSON (required).
|
|
39
50
|
* --no-signal Suppress the signal emit (tests).
|
|
40
51
|
*
|
|
@@ -57,7 +68,10 @@ import addFormats from 'ajv-formats';
|
|
|
57
68
|
import { runAsCli } from './lib/cli-utils.js';
|
|
58
69
|
import { getAcceptanceEval, resolveConfig } from './lib/config-resolver.js';
|
|
59
70
|
import { Logger } from './lib/Logger.js';
|
|
60
|
-
import {
|
|
71
|
+
import {
|
|
72
|
+
appendEpicSignal,
|
|
73
|
+
appendSignal,
|
|
74
|
+
} from './lib/observability/signals-writer.js';
|
|
61
75
|
import {
|
|
62
76
|
buildAcceptanceEvalSignal,
|
|
63
77
|
decideAcceptanceEval,
|
|
@@ -126,6 +140,7 @@ function parseCliArgs(argv) {
|
|
|
126
140
|
options: {
|
|
127
141
|
story: { type: 'string' },
|
|
128
142
|
epic: { type: 'string' },
|
|
143
|
+
cluster: { type: 'string' },
|
|
129
144
|
verdict: { type: 'string' },
|
|
130
145
|
'no-signal': { type: 'boolean', default: false },
|
|
131
146
|
},
|
|
@@ -136,6 +151,10 @@ function parseCliArgs(argv) {
|
|
|
136
151
|
return {
|
|
137
152
|
storyId: Number.isInteger(storyId) && storyId > 0 ? storyId : null,
|
|
138
153
|
epicId: Number.isInteger(epicRaw) && epicRaw > 0 ? epicRaw : null,
|
|
154
|
+
clusterId:
|
|
155
|
+
typeof values.cluster === 'string' && values.cluster.length > 0
|
|
156
|
+
? values.cluster
|
|
157
|
+
: null,
|
|
139
158
|
verdictPath: values.verdict ?? null,
|
|
140
159
|
emitSignal: values['no-signal'] !== true,
|
|
141
160
|
};
|
|
@@ -163,18 +182,23 @@ function parseCliArgs(argv) {
|
|
|
163
182
|
* @returns {Promise<{ envelope: object, exitCode: number }>}
|
|
164
183
|
*/
|
|
165
184
|
export async function runAcceptanceEval(
|
|
166
|
-
{ storyId, epicId, verdict, config, emitSignal, round },
|
|
185
|
+
{ storyId, epicId, clusterId = null, verdict, config, emitSignal, round },
|
|
167
186
|
deps = {},
|
|
168
187
|
) {
|
|
169
188
|
const {
|
|
170
189
|
appendSignalFn = appendSignal,
|
|
190
|
+
appendEpicSignalFn = appendEpicSignal,
|
|
171
191
|
deriveRoundFn = deriveAcceptanceEvalRound,
|
|
172
192
|
} = deps;
|
|
193
|
+
const clusterMode =
|
|
194
|
+
typeof clusterId === 'string' &&
|
|
195
|
+
clusterId.length > 0 &&
|
|
196
|
+
Number.isInteger(epicId);
|
|
173
197
|
const { maxRounds } = getAcceptanceEval(config);
|
|
174
198
|
const resolvedRound =
|
|
175
199
|
Number.isInteger(round) && round >= 1
|
|
176
200
|
? round
|
|
177
|
-
: deriveRoundFn({ epicId: epicId ?? null, storyId, config });
|
|
201
|
+
: deriveRoundFn({ epicId: epicId ?? null, storyId, clusterId, config });
|
|
178
202
|
const outcome = decideAcceptanceEval({
|
|
179
203
|
verdict,
|
|
180
204
|
maxRounds,
|
|
@@ -184,16 +208,21 @@ export async function runAcceptanceEval(
|
|
|
184
208
|
let signalEmitted = false;
|
|
185
209
|
if (emitSignal) {
|
|
186
210
|
const signal = {
|
|
187
|
-
...buildAcceptanceEvalSignal({ storyId, epicId, outcome }),
|
|
211
|
+
...buildAcceptanceEvalSignal({ storyId, epicId, outcome, clusterId }),
|
|
188
212
|
ts: new Date().toISOString(),
|
|
189
213
|
};
|
|
190
214
|
try {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
config
|
|
196
|
-
|
|
215
|
+
// Cluster mode (single delivery) writes to the epic-level signals
|
|
216
|
+
// stream so per-cluster round counts survive resume; the per-Story
|
|
217
|
+
// path writes to the Story stream (unchanged).
|
|
218
|
+
signalEmitted = clusterMode
|
|
219
|
+
? await appendEpicSignalFn({ epicId, signal, config })
|
|
220
|
+
: await appendSignalFn({
|
|
221
|
+
epicId,
|
|
222
|
+
storyId,
|
|
223
|
+
signal,
|
|
224
|
+
config,
|
|
225
|
+
});
|
|
197
226
|
} catch (err) {
|
|
198
227
|
// Observability is best-effort — a failed signal write must never
|
|
199
228
|
// take down the gate. The decision still stands.
|
|
@@ -206,8 +235,9 @@ export async function runAcceptanceEval(
|
|
|
206
235
|
}
|
|
207
236
|
|
|
208
237
|
const envelope = {
|
|
209
|
-
storyId,
|
|
238
|
+
storyId: storyId ?? null,
|
|
210
239
|
epicId: epicId ?? null,
|
|
240
|
+
...(clusterMode ? { clusterId } : {}),
|
|
211
241
|
decision: outcome.decision,
|
|
212
242
|
round: outcome.round,
|
|
213
243
|
cap: outcome.cap,
|
|
@@ -231,11 +261,19 @@ export async function runAcceptanceEval(
|
|
|
231
261
|
}
|
|
232
262
|
|
|
233
263
|
export async function main(argv = process.argv.slice(2)) {
|
|
234
|
-
const { storyId, epicId, verdictPath, emitSignal } =
|
|
264
|
+
const { storyId, epicId, clusterId, verdictPath, emitSignal } =
|
|
265
|
+
parseCliArgs(argv);
|
|
235
266
|
|
|
236
|
-
|
|
267
|
+
// Epic #4475 (M4-B): two invocation shapes.
|
|
268
|
+
// - Per-Story (fan-out): --story <id> [--epic <id>].
|
|
269
|
+
// - Per-AC-cluster (single delivery): --epic <id> --cluster <id> (no
|
|
270
|
+
// --story); the verdict scores one AC cluster of the Epic's Acceptance
|
|
271
|
+
// Table against the cumulative main..epic/<id> diff.
|
|
272
|
+
const clusterMode = Boolean(clusterId) && Number.isInteger(epicId);
|
|
273
|
+
if (!storyId && !clusterMode) {
|
|
237
274
|
throw new Error(
|
|
238
|
-
'Usage: node acceptance-eval.js --story <id> [--epic <id>] --verdict <path> [--no-signal]'
|
|
275
|
+
'Usage: node acceptance-eval.js --story <id> [--epic <id>] --verdict <path> [--no-signal]\n' +
|
|
276
|
+
' or: node acceptance-eval.js --epic <id> --cluster <clusterId> --verdict <path> [--no-signal]',
|
|
239
277
|
);
|
|
240
278
|
}
|
|
241
279
|
if (!verdictPath) {
|
|
@@ -267,8 +305,13 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
267
305
|
const verdict = validateVerdict(parsed);
|
|
268
306
|
|
|
269
307
|
// A verdict whose embedded storyId disagrees with the CLI flag is a
|
|
270
|
-
// wiring error worth failing on, not a silent mismatch.
|
|
271
|
-
|
|
308
|
+
// wiring error worth failing on, not a silent mismatch. Skipped in cluster
|
|
309
|
+
// mode (no --story; the verdict scores an AC cluster, not a Story).
|
|
310
|
+
if (
|
|
311
|
+
!clusterMode &&
|
|
312
|
+
Number.isInteger(verdict.storyId) &&
|
|
313
|
+
verdict.storyId !== storyId
|
|
314
|
+
) {
|
|
272
315
|
throw new Error(
|
|
273
316
|
`acceptance-eval: verdict storyId (${verdict.storyId}) does not match --story ${storyId}.`,
|
|
274
317
|
);
|
|
@@ -278,6 +321,7 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
278
321
|
const { envelope, exitCode } = await runAcceptanceEval({
|
|
279
322
|
storyId,
|
|
280
323
|
epicId,
|
|
324
|
+
clusterId,
|
|
281
325
|
verdict,
|
|
282
326
|
config,
|
|
283
327
|
emitSignal,
|
|
@@ -237,7 +237,7 @@ async function ensureProjectFields(provider, project, log) {
|
|
|
237
237
|
*
|
|
238
238
|
* Accepts the canonical resolved config (output of `resolveConfig()` —
|
|
239
239
|
* `config.github` holds the GitHub provider block). Epic #2880 removed the
|
|
240
|
-
* legacy shim parameters; see `.agents/rules/git-conventions.md#contract-cutovers-—-no-shim-layer`.
|
|
240
|
+
* legacy shim parameters; see `.agents/rules/git-conventions-reference.md#contract-cutovers-—-no-shim-layer`.
|
|
241
241
|
*
|
|
242
242
|
* Consent-first install (Story #3526, Feature #3515, Epic #3438): every
|
|
243
243
|
* mutation this function performs — labels, Projects V2, branch protection,
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* NDJSON for a Story, no children for an Epic) so the close pipelines
|
|
28
28
|
* never block on observability output. Hard failures (bad CLI args,
|
|
29
29
|
* provider error, schema-violating payload) exit non-zero — the call
|
|
30
|
-
* sites in
|
|
30
|
+
* sites in `single-story-close.js` / `helpers/deliver-story.md` treat that
|
|
31
31
|
* as a non-fatal warning.
|
|
32
32
|
*
|
|
33
33
|
* This file is a thin CLI: it wires the I/O readers from
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* Emits a single `audit-to-stories-plan.json` envelope to --out (or
|
|
13
13
|
* stdout when --json is set).
|
|
14
14
|
*
|
|
15
|
-
* --emit-
|
|
16
|
-
* Read the plan envelope from disk, render the `/plan --
|
|
15
|
+
* --emit-plan-seed --plan <plan.json> --out <path>
|
|
16
|
+
* Read the plan envelope from disk, render the `/plan --seed`
|
|
17
17
|
* seed markdown, persist to --out.
|
|
18
18
|
*
|
|
19
19
|
* --emit-stories --plan <plan.json>
|
|
@@ -37,7 +37,7 @@ import { classifyGroupsAgainstGitHub } from './lib/audit-to-stories/dedupe-again
|
|
|
37
37
|
import { withFingerprints } from './lib/audit-to-stories/finding-adapter.js';
|
|
38
38
|
import { groupFindings } from './lib/audit-to-stories/group-findings.js';
|
|
39
39
|
import { parseAuditReports } from './lib/audit-to-stories/parse-audit-md.js';
|
|
40
|
-
import {
|
|
40
|
+
import { buildPlanSeedMarkdown } from './lib/audit-to-stories/seed-from-findings.js';
|
|
41
41
|
import { runAsCli } from './lib/cli-utils.js';
|
|
42
42
|
import { Logger } from './lib/Logger.js';
|
|
43
43
|
import { parse as parseStoryBody } from './lib/story-body/story-body.js';
|
|
@@ -291,7 +291,7 @@ async function main() {
|
|
|
291
291
|
args: process.argv.slice(2),
|
|
292
292
|
options: {
|
|
293
293
|
scan: { type: 'boolean' },
|
|
294
|
-
'emit-
|
|
294
|
+
'emit-plan-seed': { type: 'boolean' },
|
|
295
295
|
'emit-stories': { type: 'boolean' },
|
|
296
296
|
glob: { type: 'string' },
|
|
297
297
|
severity: { type: 'string' },
|
|
@@ -315,9 +315,9 @@ async function main() {
|
|
|
315
315
|
return;
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
-
if (values['emit-
|
|
318
|
+
if (values['emit-plan-seed']) {
|
|
319
319
|
const plan = loadPlan(values.plan);
|
|
320
|
-
const md =
|
|
320
|
+
const md = buildPlanSeedMarkdown({
|
|
321
321
|
groups: plan.groups ?? [],
|
|
322
322
|
findings: plan.findings ?? [],
|
|
323
323
|
sourceReports: plan.sourceReports ?? [],
|
|
@@ -346,7 +346,7 @@ async function main() {
|
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
throw new Error(
|
|
349
|
-
'Usage: node audit-to-stories.js (--scan | --emit-
|
|
349
|
+
'Usage: node audit-to-stories.js (--scan | --emit-plan-seed | --emit-stories) [options]',
|
|
350
350
|
);
|
|
351
351
|
}
|
|
352
352
|
|
|
@@ -72,7 +72,7 @@ Options:
|
|
|
72
72
|
* returns the sweep envelope so no caller can be blocked by a failure.
|
|
73
73
|
*
|
|
74
74
|
* DI-friendly: `injectedConfig` / `injectedProvider` let a caller (e.g.
|
|
75
|
-
* `
|
|
75
|
+
* `single-story-init.js`) reuse an already-resolved config + provider,
|
|
76
76
|
* and `injectedSweep` swaps the engine for unit tests.
|
|
77
77
|
*
|
|
78
78
|
* @param {{
|
|
@@ -12,7 +12,13 @@
|
|
|
12
12
|
* session and every subagent spawn (instructions.md § 4).
|
|
13
13
|
* - `mandatoryRead` — the resolved `project.docsContextFiles` set.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
15
|
+
* It additionally enforces a **per-file** ceiling on the role-scoped agent-boot
|
|
16
|
+
* tier (`.agents/agents/*.md`, #4478): no single boot context may exceed
|
|
17
|
+
* `agentBoot.ceilingBytes` (default 8192). This is a per-agent cap, not a sum
|
|
18
|
+
* ratchet — each role def is a standalone system prompt a converted spawn boots
|
|
19
|
+
* on, and adding another role def is legitimate.
|
|
20
|
+
*
|
|
21
|
+
* A read-tier that resolves **empty** is skipped silently (the `docsContextFiles`
|
|
16
22
|
* half skips when unconfigured / its files are absent), so a repo with no
|
|
17
23
|
* `CLAUDE.md` and no context docs is a clean no-op.
|
|
18
24
|
*
|
|
@@ -60,6 +66,31 @@ export const GATED_TIERS = ['alwaysLoaded', 'mandatoryRead'];
|
|
|
60
66
|
*/
|
|
61
67
|
export const DEFAULT_TOLERANCE_BYTES = 2048;
|
|
62
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Per-file ceiling (bytes) for the role-scoped agent-boot tier (#4478). Unlike
|
|
71
|
+
* the read-tiers (gated by a total-byte ratchet), each `.agents/agents/*.md`
|
|
72
|
+
* boot context is a **standalone** system prompt a converted spawn boots on, so
|
|
73
|
+
* the meaningful budget is per-agent, not the sum: no single role def may
|
|
74
|
+
* exceed this ceiling. Adding another role def is legitimate — a per-file gate
|
|
75
|
+
* (rather than a sum ratchet) does not false-positive on that.
|
|
76
|
+
* @type {number}
|
|
77
|
+
*/
|
|
78
|
+
export const AGENT_BOOT_CEILING_BYTES = 8192;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Return the agent-boot files that exceed the per-file ceiling.
|
|
82
|
+
*
|
|
83
|
+
* @param {{ tiers: Record<string, Array<{ path: string, bytes: number }>> }} tierMap
|
|
84
|
+
* @param {number} ceiling
|
|
85
|
+
* @returns {Array<{ path: string, bytes: number, ceiling: number }>}
|
|
86
|
+
*/
|
|
87
|
+
export function agentBootOverflow(tierMap, ceiling = AGENT_BOOT_CEILING_BYTES) {
|
|
88
|
+
const files = tierMap?.tiers?.agentBoot ?? [];
|
|
89
|
+
return files
|
|
90
|
+
.filter((f) => Number.isFinite(f?.bytes) && f.bytes > ceiling)
|
|
91
|
+
.map((f) => ({ path: f.path, bytes: f.bytes, ceiling }));
|
|
92
|
+
}
|
|
93
|
+
|
|
63
94
|
/**
|
|
64
95
|
* Parse argv for `--baseline <path>`, `--root <path>`, `--update`, `--json`.
|
|
65
96
|
* Exported so unit tests can pin the parser.
|
|
@@ -127,11 +158,19 @@ export function buildBaseline(tierMap, toleranceBytes) {
|
|
|
127
158
|
const files = tierMap.tiers[name] ?? [];
|
|
128
159
|
tiers[name] = { totalBytes: tierTotalBytes(files), files };
|
|
129
160
|
}
|
|
161
|
+
// The agent-boot tier is recorded top-level (not under `tiers`) because it is
|
|
162
|
+
// gated by a per-file ceiling, not the total-byte ratchet the `tiers` entries
|
|
163
|
+
// use — keeping it out of `tiers` keeps the ratchet diff loop unambiguous.
|
|
164
|
+
const agentBootFiles = tierMap.tiers.agentBoot ?? [];
|
|
130
165
|
return {
|
|
131
166
|
$schema: 'https://mandrel.dev/baselines/context-budget.schema.json',
|
|
132
167
|
generatedAt: new Date().toISOString(),
|
|
133
168
|
toleranceBytes,
|
|
134
169
|
tiers,
|
|
170
|
+
agentBoot: {
|
|
171
|
+
ceilingBytes: AGENT_BOOT_CEILING_BYTES,
|
|
172
|
+
files: agentBootFiles,
|
|
173
|
+
},
|
|
135
174
|
};
|
|
136
175
|
}
|
|
137
176
|
|
|
@@ -278,7 +317,11 @@ export async function runCli({
|
|
|
278
317
|
}
|
|
279
318
|
|
|
280
319
|
const diff = diffBudget(tierMap, baseline);
|
|
281
|
-
const
|
|
320
|
+
const ceiling = Number.isFinite(baseline?.agentBoot?.ceilingBytes)
|
|
321
|
+
? baseline.agentBoot.ceilingBytes
|
|
322
|
+
: AGENT_BOOT_CEILING_BYTES;
|
|
323
|
+
const bootOverflow = agentBootOverflow(tierMap, ceiling);
|
|
324
|
+
const exitCode = diff.grown.length > 0 || bootOverflow.length > 0 ? 1 : 0;
|
|
282
325
|
|
|
283
326
|
if (json) {
|
|
284
327
|
const envelope = {
|
|
@@ -293,17 +336,31 @@ export async function runCli({
|
|
|
293
336
|
grown: diff.grown,
|
|
294
337
|
shrunk: diff.shrunk,
|
|
295
338
|
skipped: diff.skipped,
|
|
339
|
+
agentBootCeilingBytes: ceiling,
|
|
340
|
+
agentBootOverflow: bootOverflow,
|
|
296
341
|
exitCode,
|
|
297
342
|
};
|
|
298
343
|
stdout.write(`${JSON.stringify(envelope, null, 2)}\n`);
|
|
299
344
|
} else {
|
|
300
345
|
stdout.write(`\n--- context-budget preview ---\n`);
|
|
301
346
|
stdout.write(`${renderDiff(diff)}\n`);
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
347
|
+
for (const o of bootOverflow) {
|
|
348
|
+
stdout.write(
|
|
349
|
+
`+ agentBoot: ${o.path} is ${o.bytes} bytes, over the ${o.ceiling}-byte per-agent ceiling\n`,
|
|
305
350
|
);
|
|
306
351
|
}
|
|
352
|
+
if (exitCode === 1) {
|
|
353
|
+
if (bootOverflow.length > 0) {
|
|
354
|
+
stderr.write(
|
|
355
|
+
`[context-budget] ❌ a role-agent boot context exceeds the ${ceiling}-byte per-agent ceiling — trim the role def (the ceiling is a hard cap, not a starve target)\n`,
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
if (diff.grown.length > 0) {
|
|
359
|
+
stderr.write(
|
|
360
|
+
`[context-budget] ❌ a documentation tier grew beyond tolerance — refresh the budget consciously with \`node .agents/scripts/check-context-budget.js --update\` once the growth is intentional\n`,
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
307
364
|
}
|
|
308
365
|
|
|
309
366
|
return exitCode;
|
|
@@ -80,17 +80,14 @@ const SCRIPTS_DIR = path.join(REPO_ROOT, '.agents', 'scripts');
|
|
|
80
80
|
* auto-merge call could re-enter the codebase.
|
|
81
81
|
*/
|
|
82
82
|
const MERGE_LOCKOUT_ALLOWED_SUFFIXES = Object.freeze([
|
|
83
|
-
// Story
|
|
84
|
-
//
|
|
85
|
-
// The legacy `.agents/scripts/epic-deliver-automerge.js` exemption was
|
|
86
|
-
// removed in Story #2336 / Task #2340 once the CLI was reduced to a
|
|
87
|
-
// pure `epic.automerge.start` emit shim.
|
|
83
|
+
// v2 Story close path — the sole production code path authorized to
|
|
84
|
+
// call `gh pr merge` after the Epic AutomergeArmer listener was removed.
|
|
88
85
|
path.join(
|
|
89
86
|
'lib',
|
|
90
87
|
'orchestration',
|
|
91
|
-
'
|
|
92
|
-
'
|
|
93
|
-
'
|
|
88
|
+
'single-story-close',
|
|
89
|
+
'phases',
|
|
90
|
+
'auto-merge.js',
|
|
94
91
|
),
|
|
95
92
|
]);
|
|
96
93
|
|
|
@@ -339,7 +336,7 @@ export function findMergeLockoutViolations(
|
|
|
339
336
|
violations.push({
|
|
340
337
|
file,
|
|
341
338
|
line: i + 1,
|
|
342
|
-
hint: `String literal containing '${FORBIDDEN}' is forbidden outside
|
|
339
|
+
hint: `String literal containing '${FORBIDDEN}' is forbidden outside single-story-close/phases/auto-merge.js. Auto-merge enablement must flow through the Story close path.`,
|
|
343
340
|
});
|
|
344
341
|
break; // one violation per line is enough
|
|
345
342
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* check-prepush-recovery.js — gate decision for the pre-push coverage step.
|
|
4
4
|
*
|
|
5
5
|
* Story #3162. The pre-push hook normally runs `coverage-capture.js` +
|
|
6
|
-
* `crap:check` on every push. During a `story-close.js` recovery (operator
|
|
6
|
+
* `crap:check` on every push. During a pre-v2 `story-close.js` recovery (operator
|
|
7
7
|
* pushing `epic/<id>` to unblock a run after a merge-orchestrator failure),
|
|
8
8
|
* a pre-existing coverage regression on `epic/<id>` — unrelated to the
|
|
9
9
|
* Story under recovery — hard-blocks the push and forces a `--no-verify`
|
|
@@ -20,7 +20,12 @@
|
|
|
20
20
|
import { existsSync, readdirSync, rmSync } from 'node:fs';
|
|
21
21
|
import path from 'node:path';
|
|
22
22
|
import { runAsCli } from './lib/cli-utils.js';
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
const RESERVED_TEST_EPIC_TEMP_DIR = /^epic-999\d{3}$/;
|
|
25
|
+
|
|
26
|
+
function isReservedTestEpicTempDirName(name) {
|
|
27
|
+
return RESERVED_TEST_EPIC_TEMP_DIR.test(name);
|
|
28
|
+
}
|
|
24
29
|
|
|
25
30
|
/**
|
|
26
31
|
* @param {object} [opts]
|
|
@@ -81,12 +81,6 @@ const FRICTION_RULES = [
|
|
|
81
81
|
remediation:
|
|
82
82
|
' - Syntax/parsing error. Check recently modified files for missing brackets, quotes, or invalid structures.',
|
|
83
83
|
},
|
|
84
|
-
{
|
|
85
|
-
markers: ['Astro', 'astro'],
|
|
86
|
-
category: 'Missing Skill',
|
|
87
|
-
remediation:
|
|
88
|
-
' - Framework error: Refer to `.agents/skills/stack/frontend/astro/SKILL.md` for Astro rules.',
|
|
89
|
-
},
|
|
90
84
|
];
|
|
91
85
|
|
|
92
86
|
const FRICTION_DEFAULT = {
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
* - `silent` → only `fatal` emits.
|
|
19
19
|
* - `info` → default. Emits `info` and above; suppresses `debug`.
|
|
20
20
|
* - `verbose` → emits everything (including `debug`).
|
|
21
|
-
* - `debug` → alias for `verbose` (backward compatible).
|
|
22
21
|
*/
|
|
23
22
|
/**
|
|
24
23
|
* Recognized log levels, lowest-noise first. Anything outside this set
|
|
@@ -26,9 +25,7 @@
|
|
|
26
25
|
*
|
|
27
26
|
* @type {ReadonlySet<string>}
|
|
28
27
|
*/
|
|
29
|
-
const VALID_LEVELS = Object.freeze(
|
|
30
|
-
new Set(['silent', 'info', 'verbose', 'debug']),
|
|
31
|
-
);
|
|
28
|
+
const VALID_LEVELS = Object.freeze(new Set(['silent', 'info', 'verbose']));
|
|
32
29
|
|
|
33
30
|
/**
|
|
34
31
|
* Process-wide level override. `null` means "no explicit override — read
|
|
@@ -50,7 +47,7 @@ let levelOverride = null;
|
|
|
50
47
|
* the level branches react in-process, without a child process per level
|
|
51
48
|
* (Story #3329).
|
|
52
49
|
*
|
|
53
|
-
* @returns {'silent'|'info'|'verbose'
|
|
50
|
+
* @returns {'silent'|'info'|'verbose'}
|
|
54
51
|
*/
|
|
55
52
|
export function resolveLevel() {
|
|
56
53
|
const raw = (
|
|
@@ -63,12 +60,12 @@ export function resolveLevel() {
|
|
|
63
60
|
|
|
64
61
|
/**
|
|
65
62
|
* Pin the process-wide log level, bypassing `AGENT_LOG_LEVEL`. Pass a
|
|
66
|
-
* recognized level (`silent` / `info` / `verbose`
|
|
63
|
+
* recognized level (`silent` / `info` / `verbose`) to force it,
|
|
67
64
|
* or `null` to clear the pin and restore env-driven resolution. An
|
|
68
65
|
* unrecognized non-null value throws so callers cannot silently pin a
|
|
69
66
|
* level that resolves to `info`.
|
|
70
67
|
*
|
|
71
|
-
* @param {('silent'|'info'|'verbose'
|
|
68
|
+
* @param {('silent'|'info'|'verbose')|null} level
|
|
72
69
|
* @returns {void}
|
|
73
70
|
*/
|
|
74
71
|
export function setLevel(level) {
|
|
@@ -78,15 +75,14 @@ export function setLevel(level) {
|
|
|
78
75
|
}
|
|
79
76
|
if (typeof level !== 'string' || !VALID_LEVELS.has(level.toLowerCase())) {
|
|
80
77
|
throw new RangeError(
|
|
81
|
-
`setLevel: level must be one of silent|info|verbose
|
|
78
|
+
`setLevel: level must be one of silent|info|verbose or null (got ${level})`,
|
|
82
79
|
);
|
|
83
80
|
}
|
|
84
81
|
levelOverride = level.toLowerCase();
|
|
85
82
|
}
|
|
86
83
|
|
|
87
84
|
function debugEnabled() {
|
|
88
|
-
|
|
89
|
-
return level === 'verbose' || level === 'debug';
|
|
85
|
+
return resolveLevel() === 'verbose';
|
|
90
86
|
}
|
|
91
87
|
|
|
92
88
|
function infoEnabled() {
|
|
@@ -189,8 +189,8 @@ export async function runAuditSuite({
|
|
|
189
189
|
injectedRules,
|
|
190
190
|
injectedWriteArtifact,
|
|
191
191
|
}) {
|
|
192
|
-
const
|
|
193
|
-
const paths = getPaths(
|
|
192
|
+
const config = resolveConfig();
|
|
193
|
+
const paths = getPaths(config);
|
|
194
194
|
const callerSubstitutions = substitutions ?? {};
|
|
195
195
|
const rules = injectedRules ?? (await loadRules(paths));
|
|
196
196
|
|
|
@@ -109,10 +109,10 @@ export const LENS_TIERS = Object.freeze(['local', 'cumulative', 'global']);
|
|
|
109
109
|
* @throws {Error} When the manifest cannot be read or parsed.
|
|
110
110
|
*/
|
|
111
111
|
function readAuditRulesSync() {
|
|
112
|
-
const
|
|
112
|
+
const config = resolveConfig();
|
|
113
113
|
const rulesPath = path.join(
|
|
114
114
|
PROJECT_ROOT,
|
|
115
|
-
getPaths(
|
|
115
|
+
getPaths(config).schemasRoot,
|
|
116
116
|
'audit-rules.json',
|
|
117
117
|
);
|
|
118
118
|
try {
|
|
@@ -160,7 +160,7 @@ export function resolveLensTier(lens) {
|
|
|
160
160
|
* every path) matches every change set here, so its concern is verified at
|
|
161
161
|
* BOTH innermost tiers — the
|
|
162
162
|
* write-time checklist threading and this Story-scope lens pass — and excluded
|
|
163
|
-
* from Epic
|
|
163
|
+
* from the retired Epic-close roster (local lenses stay Story-scope only).
|
|
164
164
|
* A local lens with an empty `filePatterns` list matches nothing here, so a
|
|
165
165
|
* diff matching no local lens's patterns yields an empty roster and adds no
|
|
166
166
|
* lens work.
|
|
@@ -300,12 +300,12 @@ export async function selectAudits({
|
|
|
300
300
|
gitTimeoutMsOverride,
|
|
301
301
|
gateModeOpts,
|
|
302
302
|
}) {
|
|
303
|
-
const
|
|
303
|
+
const config = resolveConfig();
|
|
304
304
|
const timeoutMs = gitTimeoutMsOverride ?? DEFAULT_GIT_TIMEOUT_MS;
|
|
305
305
|
|
|
306
306
|
const rulesPath = path.join(
|
|
307
307
|
PROJECT_ROOT,
|
|
308
|
-
getPaths(
|
|
308
|
+
getPaths(config).schemasRoot,
|
|
309
309
|
'audit-rules.json',
|
|
310
310
|
);
|
|
311
311
|
let rulesData;
|
package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js}
RENAMED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* lib/audit-to-stories/seed-
|
|
2
|
+
* lib/audit-to-stories/seed-from-findings.js
|
|
3
3
|
*
|
|
4
|
-
* Build the
|
|
5
|
-
*
|
|
4
|
+
* Build the `/plan --seed`-shaped one-pager markdown that the audit-to-
|
|
5
|
+
* stories Single-plan grouping path emits for `/plan` to consume.
|
|
6
6
|
*
|
|
7
|
-
* The seed renders the canonical one-pager sections so the
|
|
8
|
-
*
|
|
7
|
+
* The seed renders the canonical one-pager sections so the authoring
|
|
8
|
+
* pass can sharpen it without having to invent context:
|
|
9
9
|
* - Problem Statement (aggregated severity profile)
|
|
10
10
|
* - Recommended Direction (rollup of recommendations by dimension)
|
|
11
11
|
* - Key Assumptions (carries the source-report links forward)
|
|
12
12
|
* - MVP Scope (the proposed Stories, one bullet per group)
|
|
13
|
-
* - Key Files (explicit file paths so
|
|
14
|
-
*
|
|
13
|
+
* - Key Files (explicit file paths so `/plan` authoring has concrete
|
|
14
|
+
* anchors)
|
|
15
15
|
* - Not Doing (out-of-scope items by convention)
|
|
16
16
|
*
|
|
17
17
|
* Pure: returns a string. The caller decides where to persist it.
|
|
@@ -112,14 +112,14 @@ function formatKeyAssumptions(sourceReports) {
|
|
|
112
112
|
* @param {string[]} params.sourceReports — list of source report paths.
|
|
113
113
|
* @returns {string}
|
|
114
114
|
*/
|
|
115
|
-
export function
|
|
115
|
+
export function buildPlanSeedMarkdown({ groups, findings, sourceReports }) {
|
|
116
116
|
if (
|
|
117
117
|
!Array.isArray(groups) ||
|
|
118
118
|
!Array.isArray(findings) ||
|
|
119
119
|
!Array.isArray(sourceReports)
|
|
120
120
|
) {
|
|
121
121
|
throw new Error(
|
|
122
|
-
'
|
|
122
|
+
'buildPlanSeedMarkdown: groups, findings, sourceReports must all be arrays',
|
|
123
123
|
);
|
|
124
124
|
}
|
|
125
125
|
const problem = formatProblemStatement(findings);
|