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
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* story-ops.js — flat Story creation for v2 plan-persist (Stage 3).
|
|
3
|
+
*
|
|
4
|
+
* Under the Story collapse (`docs/roadmap.md` § Stage 3), `/plan` persists
|
|
5
|
+
* zero-or-more Story issues directly — no Epic parent, no reconciler tree,
|
|
6
|
+
* no `deliveryShape` mode matrix. Default is **one Story**; N>1 is gated by
|
|
7
|
+
* the Stage-1 split-policy validator (`assertAcceptancePartition`).
|
|
8
|
+
*
|
|
9
|
+
* Each Story body is the single executable document: Tech Spec stays inline
|
|
10
|
+
* under `## Spec`. Over-budget Specs fail closed (split / tighten) — never
|
|
11
|
+
* spill to `docs/`. Top-level `acceptance[]` / `verify[]` are the machine
|
|
12
|
+
* contract and are synced into the body so the GitHub issue stays complete
|
|
13
|
+
* without requiring the LLM to dual-author the same lists.
|
|
14
|
+
*
|
|
15
|
+
* @module lib/orchestration/plan-persist/story-ops
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { randomBytes } from 'node:crypto';
|
|
19
|
+
|
|
20
|
+
import { AGENT_LABELS, TYPE_LABELS } from '../../label-constants.js';
|
|
21
|
+
import {
|
|
22
|
+
parse as parseStoryBody,
|
|
23
|
+
serialize as serializeStoryBody,
|
|
24
|
+
} from '../../story-body/story-body.js';
|
|
25
|
+
import { assertSpecWithinBudget } from '../spec-spill.js';
|
|
26
|
+
import { assertAcceptancePartition } from '../split-policy-validator.js';
|
|
27
|
+
|
|
28
|
+
/** Label prefix grouping sibling Stories from one plan run (N>1). */
|
|
29
|
+
export const PLAN_RUN_LABEL_PREFIX = 'plan-run::';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Normalize a caller-supplied plan-run token. Persistence and resolution
|
|
33
|
+
* share this helper so human-readable ids map to one canonical label.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} id
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
export function normalizePlanRunId(id) {
|
|
39
|
+
const token = String(id ?? '')
|
|
40
|
+
.trim()
|
|
41
|
+
.toLowerCase()
|
|
42
|
+
.replace(/^plan-run::/, '')
|
|
43
|
+
.replace(/[^a-z0-9._-]+/g, '-');
|
|
44
|
+
if (!token) {
|
|
45
|
+
throw new Error('plan-run id requires a non-empty planRunId');
|
|
46
|
+
}
|
|
47
|
+
return token;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Build a `plan-run::<id>` label. When `id` is omitted, generates a short
|
|
52
|
+
* random hex token (8 chars) suitable for a rare multi-Story plan.
|
|
53
|
+
*
|
|
54
|
+
* @param {string} [id]
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
57
|
+
export function planRunLabel(id) {
|
|
58
|
+
const token =
|
|
59
|
+
typeof id === 'string' && id.trim() !== ''
|
|
60
|
+
? normalizePlanRunId(id)
|
|
61
|
+
: randomBytes(4).toString('hex');
|
|
62
|
+
return `${PLAN_RUN_LABEL_PREFIX}${token}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function bodyObjectFromTicket(ticket) {
|
|
66
|
+
if (typeof ticket.body === 'string') {
|
|
67
|
+
return parseStoryBody(ticket.body).body;
|
|
68
|
+
}
|
|
69
|
+
if (ticket.body && typeof ticket.body === 'object') {
|
|
70
|
+
return parseStoryBody(ticket.body).body;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Allow top-level structured fields (goal/changes/…) without a `body` key.
|
|
74
|
+
return parseStoryBody({
|
|
75
|
+
goal: ticket.goal ?? '',
|
|
76
|
+
slicing: ticket.slicing ?? '',
|
|
77
|
+
spec: ticket.spec ?? '',
|
|
78
|
+
changes: ticket.changes ?? [],
|
|
79
|
+
acceptance: ticket.acceptance ?? [],
|
|
80
|
+
verify: ticket.verify ?? [],
|
|
81
|
+
references: ticket.references ?? [],
|
|
82
|
+
non_goals: ticket.non_goals ?? [],
|
|
83
|
+
wide: ticket.wide ?? null,
|
|
84
|
+
reason_to_exist: ticket.reason_to_exist ?? null,
|
|
85
|
+
depends_on: ticket.depends_on ?? [],
|
|
86
|
+
estimated_test_files: ticket.estimated_test_files ?? null,
|
|
87
|
+
}).body;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function normalizeDependsOn(ticket, bodyObject) {
|
|
91
|
+
if (Array.isArray(ticket.depends_on)) {
|
|
92
|
+
return ticket.depends_on.filter((d) => typeof d === 'string');
|
|
93
|
+
}
|
|
94
|
+
return Array.isArray(bodyObject.depends_on) ? bodyObject.depends_on : [];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function arraysEqual(a, b) {
|
|
98
|
+
return a.length === b.length && a.every((value, index) => value === b[index]);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Top-level `acceptance[]` / `verify[]` are the machine contract (validator
|
|
103
|
+
* SSOT). Sync them into the body so the persisted GitHub issue is complete.
|
|
104
|
+
* When the body already lists the same items, keep them; when the body is
|
|
105
|
+
* empty, fill from top-level; when both disagree, fail closed.
|
|
106
|
+
*
|
|
107
|
+
* @param {object} ticket
|
|
108
|
+
* @param {object} bodyObject
|
|
109
|
+
* @param {'acceptance'|'verify'} field
|
|
110
|
+
*/
|
|
111
|
+
function syncContractFieldFromTopLevel(ticket, bodyObject, field) {
|
|
112
|
+
if (!Array.isArray(ticket[field])) return;
|
|
113
|
+
const topLevel = ticket[field].map(String);
|
|
114
|
+
const bodyValue = Array.isArray(bodyObject[field])
|
|
115
|
+
? bodyObject[field].map(String)
|
|
116
|
+
: [];
|
|
117
|
+
if (bodyValue.length > 0 && !arraysEqual(topLevel, bodyValue)) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
`[plan-persist] Story "${ticket.slug ?? ticket.title ?? 'unknown'}" has mismatched top-level and body ${field} arrays`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
bodyObject[field] = topLevel;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Normalize a plan Story ticket into `{ slug, title, bodyObject }`.
|
|
127
|
+
* Accepts either a serialized markdown `body` string or a structured body.
|
|
128
|
+
*
|
|
129
|
+
* @param {object} ticket
|
|
130
|
+
* @returns {{ slug: string, title: string, bodyObject: object, depends_on: string[] }}
|
|
131
|
+
*/
|
|
132
|
+
export function normalizeStoryTicket(ticket) {
|
|
133
|
+
if (!ticket || typeof ticket !== 'object') {
|
|
134
|
+
throw new Error('[plan-persist] each story ticket must be an object');
|
|
135
|
+
}
|
|
136
|
+
const slug =
|
|
137
|
+
typeof ticket.slug === 'string' && ticket.slug.trim() !== ''
|
|
138
|
+
? ticket.slug.trim()
|
|
139
|
+
: null;
|
|
140
|
+
if (!slug) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
'[plan-persist] each story ticket requires a non-empty slug',
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
const title =
|
|
146
|
+
typeof ticket.title === 'string' && ticket.title.trim() !== ''
|
|
147
|
+
? ticket.title.trim()
|
|
148
|
+
: `Story ${slug}`;
|
|
149
|
+
const bodyObject = bodyObjectFromTicket(ticket);
|
|
150
|
+
syncContractFieldFromTopLevel(ticket, bodyObject, 'acceptance');
|
|
151
|
+
syncContractFieldFromTopLevel(ticket, bodyObject, 'verify');
|
|
152
|
+
const depends_on = normalizeDependsOn(ticket, bodyObject);
|
|
153
|
+
|
|
154
|
+
return { slug, title, bodyObject, depends_on };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Fold optional shared Tech Spec prose into a Story body when the Story has
|
|
159
|
+
* no inline Spec. Specs stay inline; over-budget Specs throw.
|
|
160
|
+
*
|
|
161
|
+
* Precedence: per-Story `body.spec` wins; otherwise `sharedSpec` is used
|
|
162
|
+
* (N===1 convenience only — callers must not share one Spec across N>1).
|
|
163
|
+
*
|
|
164
|
+
* @param {object} bodyObject
|
|
165
|
+
* @param {string} slug
|
|
166
|
+
* @param {object} [opts]
|
|
167
|
+
* @param {string|null} [opts.sharedSpec]
|
|
168
|
+
* @returns {{ bodyObject: object }}
|
|
169
|
+
*/
|
|
170
|
+
export function foldSpecIntoStoryBody(bodyObject, slug, opts = {}) {
|
|
171
|
+
const { sharedSpec = null } = opts;
|
|
172
|
+
|
|
173
|
+
const next = {
|
|
174
|
+
...bodyObject,
|
|
175
|
+
references: Array.isArray(bodyObject.references)
|
|
176
|
+
? [...bodyObject.references]
|
|
177
|
+
: [],
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const inline =
|
|
181
|
+
typeof next.spec === 'string' && next.spec.trim() !== ''
|
|
182
|
+
? next.spec.trim()
|
|
183
|
+
: typeof sharedSpec === 'string' && sharedSpec.trim() !== ''
|
|
184
|
+
? sharedSpec.trim()
|
|
185
|
+
: '';
|
|
186
|
+
|
|
187
|
+
if (inline === '') {
|
|
188
|
+
return { bodyObject: next };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const { content } = assertSpecWithinBudget({ storyId: slug, spec: inline });
|
|
192
|
+
next.spec = content;
|
|
193
|
+
return { bodyObject: next };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function assembleOnePlanStory(ticket, opts) {
|
|
197
|
+
const { slug, title, bodyObject, depends_on } = normalizeStoryTicket(ticket);
|
|
198
|
+
const { bodyObject: folded } = foldSpecIntoStoryBody(bodyObject, slug, {
|
|
199
|
+
sharedSpec: opts.sharedSpec ?? null,
|
|
200
|
+
});
|
|
201
|
+
const body = serializeStoryBody({ ...folded, depends_on });
|
|
202
|
+
return {
|
|
203
|
+
story: {
|
|
204
|
+
slug,
|
|
205
|
+
title,
|
|
206
|
+
body,
|
|
207
|
+
bodyObject: { ...folded, depends_on },
|
|
208
|
+
acceptance: Array.isArray(folded.acceptance) ? folded.acceptance : [],
|
|
209
|
+
depends_on,
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Shared techspec.md is an N===1 convenience only — folding one Spec into
|
|
216
|
+
* every sibling duplicates approach prose and breaks Story-as-SSOT.
|
|
217
|
+
*
|
|
218
|
+
* @param {object[]} tickets
|
|
219
|
+
* @param {string|null|undefined} sharedSpec
|
|
220
|
+
*/
|
|
221
|
+
function assertSharedSpecAllowed(tickets, sharedSpec) {
|
|
222
|
+
if (tickets.length <= 1) return;
|
|
223
|
+
if (typeof sharedSpec !== 'string' || sharedSpec.trim() === '') return;
|
|
224
|
+
throw new Error(
|
|
225
|
+
'[plan-persist] a shared techspec.md cannot be folded into N>1 Stories — ' +
|
|
226
|
+
"put each Story's approach in its own ## Spec so every Story stays a " +
|
|
227
|
+
'complete executable document.',
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Assemble markdown bodies for every Story: normalize → fold spec →
|
|
233
|
+
* assertAcceptancePartition → serialize.
|
|
234
|
+
*
|
|
235
|
+
* @param {object[]} tickets
|
|
236
|
+
* @param {object} [opts]
|
|
237
|
+
* @param {string|null} [opts.sharedSpec]
|
|
238
|
+
* @param {string[]} [opts.planAcceptance]
|
|
239
|
+
* @returns {{ stories: Array<{ slug: string, title: string, body: string, acceptance: string[], depends_on: string[] }> }}
|
|
240
|
+
*/
|
|
241
|
+
export function assemblePlanStories(tickets, opts = {}) {
|
|
242
|
+
if (!Array.isArray(tickets) || tickets.length === 0) {
|
|
243
|
+
throw new Error(
|
|
244
|
+
'[plan-persist] stories payload must be a non-empty array — author at least one Story (default-single).',
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
assertSharedSpecAllowed(tickets, opts.sharedSpec);
|
|
249
|
+
|
|
250
|
+
const stories = tickets.map(
|
|
251
|
+
(ticket) => assembleOnePlanStory(ticket, opts).story,
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
assertAcceptancePartition(stories, {
|
|
255
|
+
planAcceptance: opts.planAcceptance,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
return { stories };
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function orderStoriesByDependencies(stories) {
|
|
262
|
+
const list = Array.isArray(stories) ? stories : [];
|
|
263
|
+
const known = new Set(list.map((story) => story.slug));
|
|
264
|
+
for (const story of list) {
|
|
265
|
+
const unknown = story.depends_on.filter((slug) => !known.has(slug));
|
|
266
|
+
if (unknown.length > 0) {
|
|
267
|
+
throw new Error(
|
|
268
|
+
`[plan-persist] Story "${story.slug}" depends on unknown sibling(s): ${unknown.join(', ')}`,
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const ordered = [];
|
|
273
|
+
const scheduled = new Set();
|
|
274
|
+
const pending = [...list];
|
|
275
|
+
while (pending.length > 0) {
|
|
276
|
+
const index = pending.findIndex((story) =>
|
|
277
|
+
story.depends_on.every((slug) => scheduled.has(slug)),
|
|
278
|
+
);
|
|
279
|
+
if (index === -1) {
|
|
280
|
+
throw new Error(
|
|
281
|
+
`[plan-persist] dependency cycle prevents Story creation: ${pending.map((story) => story.slug).join(', ')}`,
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
const [story] = pending.splice(index, 1);
|
|
285
|
+
ordered.push(story);
|
|
286
|
+
scheduled.add(story.slug);
|
|
287
|
+
}
|
|
288
|
+
return ordered;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Create Story issues via `provider.createIssue`. Applies `type::story`,
|
|
293
|
+
* `agent::ready`, and — when N>1 — a shared plan-run label.
|
|
294
|
+
*
|
|
295
|
+
* @param {object} args
|
|
296
|
+
* @param {object} args.provider
|
|
297
|
+
* @param {ReturnType<typeof assemblePlanStories>['stories']} args.stories
|
|
298
|
+
* @param {object} [args.opts]
|
|
299
|
+
* @param {string} [args.opts.planRunId]
|
|
300
|
+
* @param {boolean} [args.opts.dryRun=false]
|
|
301
|
+
* @returns {Promise<{ created: Array<{ slug: string, id: number, url?: string, title: string }>, planRunLabel: string|null }>}
|
|
302
|
+
*/
|
|
303
|
+
export async function createStoryIssues({ provider, stories, opts = {} }) {
|
|
304
|
+
if (typeof provider?.createIssue !== 'function') {
|
|
305
|
+
throw new Error(
|
|
306
|
+
'[plan-persist] provider does not expose createIssue; cannot persist Stories.',
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const list = Array.isArray(stories) ? stories : [];
|
|
311
|
+
const planLabel = list.length > 1 ? planRunLabel(opts.planRunId) : null;
|
|
312
|
+
const labels = [TYPE_LABELS.STORY, AGENT_LABELS.READY];
|
|
313
|
+
if (planLabel) labels.push(planLabel);
|
|
314
|
+
|
|
315
|
+
if (opts.dryRun) {
|
|
316
|
+
return {
|
|
317
|
+
created: list.map((s, i) => ({
|
|
318
|
+
slug: s.slug,
|
|
319
|
+
id: -(i + 1),
|
|
320
|
+
title: s.title,
|
|
321
|
+
url: undefined,
|
|
322
|
+
})),
|
|
323
|
+
planRunLabel: planLabel,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const created = [];
|
|
328
|
+
const createdBySlug = new Map();
|
|
329
|
+
for (const story of orderStoriesByDependencies(list)) {
|
|
330
|
+
const dependencyRefs = story.depends_on.map(
|
|
331
|
+
(slug) => `#${createdBySlug.get(slug)}`,
|
|
332
|
+
);
|
|
333
|
+
const body =
|
|
334
|
+
dependencyRefs.length === 0
|
|
335
|
+
? story.body
|
|
336
|
+
: serializeStoryBody(
|
|
337
|
+
{ ...story.bodyObject, depends_on: dependencyRefs },
|
|
338
|
+
{ includeFooter: true },
|
|
339
|
+
);
|
|
340
|
+
const result = await provider.createIssue({
|
|
341
|
+
title: story.title,
|
|
342
|
+
body,
|
|
343
|
+
labels: [...labels],
|
|
344
|
+
});
|
|
345
|
+
const id = result?.id ?? result?.number;
|
|
346
|
+
if (!Number.isInteger(id)) {
|
|
347
|
+
throw new Error(
|
|
348
|
+
`[plan-persist] createIssue for slug "${story.slug}" did not return a numeric id`,
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
created.push({
|
|
352
|
+
slug: story.slug,
|
|
353
|
+
id,
|
|
354
|
+
title: story.title,
|
|
355
|
+
url: result.url,
|
|
356
|
+
});
|
|
357
|
+
createdBySlug.set(story.slug, id);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return { created, planRunLabel: planLabel };
|
|
361
|
+
}
|
|
@@ -1,21 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* summary.js — plan-persist terminal summary (
|
|
2
|
+
* summary.js — plan-persist terminal summary (v2 Stage 3).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - the Phase 9 plan-time `dispatch-manifest` comment, whose claimed
|
|
9
|
-
* consumer ("Wave Completeness Gate, /deliver Step 0.5") does not exist
|
|
10
|
-
* — the live manifest is written at deliver time by `wave-record-io.js`
|
|
11
|
-
* (#4474 design §3: DROP, keep the wave table as summary text only);
|
|
12
|
-
* - the Phase 12 notify round-trip ("informational — no webhook for
|
|
13
|
-
* planning").
|
|
14
|
-
*
|
|
15
|
-
* The wave table is computed from the validated ticket set's `depends_on`
|
|
16
|
-
* slug edges via the same `computeStoryWaves` layering the deliver-time
|
|
17
|
-
* dispatch pipeline uses, so the preview matches what `/deliver` will
|
|
18
|
-
* actually fan out (barring later manual ticket edits).
|
|
4
|
+
* Upserts a single `plan-summary` structured comment on the primary Story
|
|
5
|
+
* at terminal success. Carries risk / routing receipts and the dry-run
|
|
6
|
+
* `depends_on` ordering table for the rare N>1 plan.
|
|
19
7
|
*
|
|
20
8
|
* @module lib/orchestration/plan-persist/summary
|
|
21
9
|
*/
|
|
@@ -23,23 +11,15 @@
|
|
|
23
11
|
import { computeStoryWaves } from '../dependency-analyzer.js';
|
|
24
12
|
|
|
25
13
|
/**
|
|
26
|
-
* Structured-comment type for the persist summary.
|
|
27
|
-
* `ticketing/reads.js` `STRUCTURED_COMMENT_TYPES`; upsert-idempotent so a
|
|
28
|
-
* `--force`/`--resume` re-persist replaces the prior summary in place.
|
|
14
|
+
* Structured-comment type for the persist summary.
|
|
29
15
|
*/
|
|
30
16
|
export const PLAN_SUMMARY_COMMENT_TYPE = 'plan-summary';
|
|
31
17
|
|
|
32
18
|
/**
|
|
33
19
|
* Compute the dry-run wave assignment for a validated ticket set.
|
|
34
20
|
*
|
|
35
|
-
* Adapts the slug-keyed ticket shape onto `computeStoryWaves`' storyGroups
|
|
36
|
-
* contract (slug → { storyId, tasks: [] }; explicit deps from `depends_on`).
|
|
37
|
-
* Under the 2-tier hierarchy Stories carry no tasks, so all edges are
|
|
38
|
-
* explicit.
|
|
39
|
-
*
|
|
40
21
|
* @param {Array<{ slug: string, title?: string, depends_on?: string[] }>} tickets
|
|
41
22
|
* @returns {Array<{ wave: number, stories: Array<{ slug: string, title: string }> }>}
|
|
42
|
-
* Waves in execution order.
|
|
43
23
|
*/
|
|
44
24
|
export function buildWaveTable(tickets) {
|
|
45
25
|
const list = Array.isArray(tickets) ? tickets : [];
|
|
@@ -66,53 +46,24 @@ export function buildWaveTable(tickets) {
|
|
|
66
46
|
}
|
|
67
47
|
|
|
68
48
|
/**
|
|
69
|
-
* Render the dry-run wave table as GitHub-flavoured markdown.
|
|
70
|
-
*
|
|
71
49
|
* @param {ReturnType<typeof buildWaveTable>} waveTable
|
|
72
|
-
* @returns {string[]}
|
|
50
|
+
* @returns {string[]}
|
|
73
51
|
*/
|
|
74
52
|
function renderWaveTableLines(waveTable) {
|
|
75
53
|
if (!Array.isArray(waveTable) || waveTable.length === 0) {
|
|
76
|
-
return ['_No stories to
|
|
54
|
+
return ['_No stories to sequence (empty plan)._'];
|
|
77
55
|
}
|
|
78
56
|
const rows = waveTable.map(
|
|
79
57
|
({ wave, stories }) =>
|
|
80
58
|
`| ${wave + 1} | ${stories.map((s) => `\`${s.slug}\``).join(', ')} |`,
|
|
81
59
|
);
|
|
82
|
-
return ['|
|
|
60
|
+
return ['| Order | Stories |', '| --- | --- |', ...rows];
|
|
83
61
|
}
|
|
84
62
|
|
|
85
63
|
/**
|
|
86
|
-
* Build the `plan-summary` structured-comment body
|
|
87
|
-
* freshness + healthcheck receipts, closing with the mode-specific tail —
|
|
88
|
-
* the dry-run wave table for fan-out/amend, or the single-delivery routing
|
|
89
|
-
* record `{ deliveryShape, sliceCount, routingReasons }` (Epic #4474 PR4)
|
|
90
|
-
* for the spec-only mode.
|
|
91
|
-
*
|
|
92
|
-
* Every auto-waiver the persist derived is printed WITH its reason
|
|
93
|
-
* (#4496 fix 2) — e.g. the no-BDD-runner acceptance-disposition waiver
|
|
94
|
-
* (`planningRisk.acceptanceWaivedReason`) — so the summary is
|
|
95
|
-
* self-explanatory and a headless reader never has to re-derive a persist
|
|
96
|
-
* outcome from framework source.
|
|
64
|
+
* Build the `plan-summary` structured-comment body.
|
|
97
65
|
*
|
|
98
|
-
* @param {
|
|
99
|
-
* epicId: number,
|
|
100
|
-
* ticketCount: number,
|
|
101
|
-
* planningRisk: { overallLevel?: string, gateDecision?: string, acceptanceDisposition?: string, acceptanceWaivedReason?: string },
|
|
102
|
-
* reviewRouting: { decision?: string },
|
|
103
|
-
* freshness?: { stale?: number, ambiguous?: number },
|
|
104
|
-
* healthcheck?: { ok?: boolean, waived?: boolean, skipped?: boolean },
|
|
105
|
-
* waveTable: ReturnType<typeof buildWaveTable>,
|
|
106
|
-
* mode?: 'fan-out'|'single'|'amend',
|
|
107
|
-
* planMetricsLine?: string|null,
|
|
108
|
-
* single?: { deliveryShape: 'single', sliceCount: number|null, routingReasons: string[] }|null,
|
|
109
|
-
* amend?: {
|
|
110
|
-
* closed: Array<{ slug: string, issueNumber: number }>,
|
|
111
|
-
* recreated: Array<{ slug: string, oldIssueNumber: number, issueNumber: number }>,
|
|
112
|
-
* created: Array<{ slug: string, issueNumber: number }>,
|
|
113
|
-
* keptCount: number,
|
|
114
|
-
* }|null,
|
|
115
|
-
* }} input
|
|
66
|
+
* @param {object} input
|
|
116
67
|
* @returns {string}
|
|
117
68
|
*/
|
|
118
69
|
export function buildPlanSummaryCommentBody({
|
|
@@ -123,84 +74,60 @@ export function buildPlanSummaryCommentBody({
|
|
|
123
74
|
freshness,
|
|
124
75
|
healthcheck,
|
|
125
76
|
waveTable,
|
|
126
|
-
mode = '
|
|
77
|
+
mode = 'stories',
|
|
127
78
|
planMetricsLine = null,
|
|
79
|
+
stories = null,
|
|
80
|
+
planRunLabel = null,
|
|
81
|
+
// legacy unused knobs kept so older test call sites don't crash mid-migration
|
|
128
82
|
single = null,
|
|
129
83
|
amend = null,
|
|
130
84
|
}) {
|
|
85
|
+
void mode;
|
|
86
|
+
void single;
|
|
87
|
+
void amend;
|
|
88
|
+
|
|
131
89
|
const freshnessLine =
|
|
132
90
|
(freshness?.stale ?? 0) > 0 || (freshness?.ambiguous ?? 0) > 0
|
|
133
|
-
? `- ⚠️ Spec freshness: ${freshness.stale} stale / ${freshness.ambiguous} ambiguous reference(s)
|
|
91
|
+
? `- ⚠️ Spec freshness: ${freshness.stale} stale / ${freshness.ambiguous} ambiguous reference(s).`
|
|
134
92
|
: '- Spec freshness: clean.';
|
|
135
93
|
const healthcheckLine = healthcheck?.skipped
|
|
136
|
-
? '- Healthcheck: skipped (
|
|
94
|
+
? '- Healthcheck: skipped (v2 flat Story persist — ticket validators are the gate).'
|
|
137
95
|
: healthcheck?.ok
|
|
138
96
|
? '- Healthcheck: passed.'
|
|
139
97
|
: `- Healthcheck: failed, waived by operator label.`;
|
|
140
98
|
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
?
|
|
144
|
-
:
|
|
99
|
+
const storyList =
|
|
100
|
+
Array.isArray(stories) && stories.length > 0
|
|
101
|
+
? stories.map((s) => `#${s.id} (\`${s.slug}\`)`).join(', ')
|
|
102
|
+
: `${ticketCount} Story(ies)`;
|
|
145
103
|
|
|
146
|
-
// Auto-waivers always ship with their reason (#4496 fix 2): the summary
|
|
147
|
-
// is authoritative, so the line must be self-explanatory on its own.
|
|
148
104
|
const waiverLines = planningRisk?.acceptanceWaivedReason
|
|
149
105
|
? [
|
|
150
106
|
`- ⚠️ Acceptance disposition auto-waived to \`not-applicable\` — ${planningRisk.acceptanceWaivedReason}`,
|
|
151
107
|
]
|
|
152
108
|
: [];
|
|
153
109
|
|
|
154
|
-
const
|
|
155
|
-
?
|
|
156
|
-
|
|
157
|
-
]
|
|
158
|
-
: [];
|
|
159
|
-
|
|
160
|
-
const tail =
|
|
161
|
-
mode === 'single'
|
|
162
|
-
? [
|
|
163
|
-
'#### Delivery routing record',
|
|
164
|
-
'',
|
|
165
|
-
'```json',
|
|
166
|
-
JSON.stringify(
|
|
167
|
-
{
|
|
168
|
-
deliveryShape: 'single',
|
|
169
|
-
sliceCount: single?.sliceCount ?? null,
|
|
170
|
-
routingReasons: single?.routingReasons ?? [],
|
|
171
|
-
},
|
|
172
|
-
null,
|
|
173
|
-
2,
|
|
174
|
-
),
|
|
175
|
-
'```',
|
|
176
|
-
'',
|
|
177
|
-
'_Marker is inert until #4475 lands the deliver-side reader — `/deliver` still treats this Epic as fan-out until then._',
|
|
178
|
-
]
|
|
179
|
-
: [
|
|
180
|
-
'#### Dry-run wave table',
|
|
181
|
-
'',
|
|
182
|
-
...renderWaveTableLines(waveTable),
|
|
183
|
-
'',
|
|
184
|
-
'_Preview only — the authoritative dispatch manifest is written at deliver time (`wave-record-io.js`)._',
|
|
185
|
-
];
|
|
110
|
+
const runLine = planRunLabel
|
|
111
|
+
? `- Plan-run label: \`${planRunLabel}\` (N>1 — deliver with \`/deliver --run <planRunId>\`).`
|
|
112
|
+
: '- Plan-run: single Story (default).';
|
|
186
113
|
|
|
187
114
|
return [
|
|
188
|
-
`### 📋 Plan Summary —
|
|
115
|
+
`### 📋 Plan Summary — Story #${epicId} is \`agent::ready\``,
|
|
189
116
|
'',
|
|
190
|
-
|
|
191
|
-
|
|
117
|
+
`- ${ticketCount} Story ticket(s) persisted: ${storyList}.`,
|
|
118
|
+
runLine,
|
|
192
119
|
`- Risk: ${planningRisk?.overallLevel ?? 'unknown'} · ${planningRisk?.gateDecision ?? 'unknown'} (review routing: ${reviewRouting?.decision ?? 'unknown'}).`,
|
|
193
120
|
...waiverLines,
|
|
194
121
|
freshnessLine,
|
|
195
122
|
healthcheckLine,
|
|
196
|
-
// G2 measurement receipt (Epic #4474 PR1/PR7): the plan-CLI invocation
|
|
197
|
-
// ledger roll-up (turns-per-plan proxy, per-mode counts, critic skips)
|
|
198
|
-
// rides the summary comment so the cohort reader never has to pull the
|
|
199
|
-
// temp ledger off the runner's disk. Omitted when the ledger is empty.
|
|
200
123
|
...(typeof planMetricsLine === 'string' && planMetricsLine.length > 0
|
|
201
124
|
? [`- ${planMetricsLine}`]
|
|
202
125
|
: []),
|
|
203
126
|
'',
|
|
204
|
-
|
|
127
|
+
'#### Delivery order (`depends_on`)',
|
|
128
|
+
'',
|
|
129
|
+
...renderWaveTableLines(waveTable),
|
|
130
|
+
'',
|
|
131
|
+
'_Deliver with `/deliver <storyId>` (N=1) or `/deliver --run <planRunId>` (N>1)._',
|
|
205
132
|
].join('\n');
|
|
206
133
|
}
|
|
@@ -3,13 +3,11 @@
|
|
|
3
3
|
* the persist surface (Epic #4474 PR6, design §4: the 8.4 reachability
|
|
4
4
|
* critic demoted from a fresh-context sub-agent to a persist-side scan).
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* while a one-line targeted amend is still free (nothing has been written
|
|
12
|
-
* to GitHub yet).
|
|
6
|
+
* Route-glob scan of the paths a Story declares vs the
|
|
7
|
+
* `planning.navigation.navRegistry` token list, run over the **draft**
|
|
8
|
+
* ticket set inside `plan-persist.js` step 4.5, before any provider call,
|
|
9
|
+
* so an orphaned surface is caught while a one-line targeted amend is
|
|
10
|
+
* still free (nothing has been written to GitHub yet).
|
|
13
11
|
*
|
|
14
12
|
* Plan-level coverage semantics (the convergence contract): a route-adding
|
|
15
13
|
* story that never references the nav registry produces orphan surfaces —
|
|
@@ -20,9 +18,8 @@
|
|
|
20
18
|
* registry) in one targeted amend, and the re-run persist passes.
|
|
21
19
|
*
|
|
22
20
|
* Silent no-op when `planning.navigation` is unconfigured (`routeGlobs`
|
|
23
|
-
* empty) —
|
|
24
|
-
*
|
|
25
|
-
* plan-metrics ledger.
|
|
21
|
+
* empty) — reported as `status: 'skipped'` so the caller can append the
|
|
22
|
+
* audit record to the plan-metrics ledger.
|
|
26
23
|
*
|
|
27
24
|
* Pure over its inputs (tickets + resolved config), no I/O.
|
|
28
25
|
*/
|
|
@@ -31,12 +28,10 @@ import {
|
|
|
31
28
|
extractStoryPaths,
|
|
32
29
|
globToRegExp,
|
|
33
30
|
resolveNavConfig,
|
|
34
|
-
} from '
|
|
31
|
+
} from './plan-navigation.js';
|
|
35
32
|
|
|
36
33
|
/**
|
|
37
|
-
* Fallback tokens when `navRegistry` is unconfigured but `routeGlobs` is
|
|
38
|
-
* identical to the F7 healthcheck's fallback, so the two checks agree on
|
|
39
|
-
* what counts as a registry reference.
|
|
34
|
+
* Fallback tokens when `navRegistry` is unconfigured but `routeGlobs` is.
|
|
40
35
|
*/
|
|
41
36
|
const FALLBACK_REGISTRY_TOKENS = ['nav registry', 'navigation'];
|
|
42
37
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* The `--force` flag is intentional. By the time a Story is `agent::done`
|
|
11
11
|
* its branch has already been merged into the Epic branch (via
|
|
12
|
-
* `story-close.js`), so any residue left in the worktree — dirty
|
|
12
|
+
* `single-story-close.js`), so any residue left in the worktree — dirty
|
|
13
13
|
* build artifacts, an interrupted rebase, a stray Windows lock — is noise.
|
|
14
14
|
* The safety rails in `WorktreeManager.reap` exist for the _active_ close
|
|
15
15
|
* path; at plan time we already know the Story is done and want the
|
package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js
RENAMED
|
@@ -12,17 +12,17 @@ import path from 'node:path';
|
|
|
12
12
|
import {
|
|
13
13
|
resolveFeatureRoots,
|
|
14
14
|
verifyBddRunnerPendingTag,
|
|
15
|
-
} from '
|
|
16
|
-
import { scanBddScenarios } from '
|
|
17
|
-
import { buildCodebaseSnapshot } from '
|
|
18
|
-
import { getLimits, getPaths, PROJECT_ROOT } from '
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { ensureDocsDigest } from '
|
|
24
|
-
import { applyBudget } from '
|
|
25
|
-
import { collectReferences, hasNewFileCue } from '
|
|
15
|
+
} from '../../bdd-runner-detect.js';
|
|
16
|
+
import { scanBddScenarios } from '../../bdd-scenario-scanner.js';
|
|
17
|
+
import { buildCodebaseSnapshot } from '../../codebase-snapshot.js';
|
|
18
|
+
import { getLimits, getPaths, PROJECT_ROOT } from '../../config-resolver.js';
|
|
19
|
+
import { scanMemoryFreshness } from '../../feedback-loop/memory-freshness.js';
|
|
20
|
+
import { fetchPriorFeedback } from '../../feedback-loop/prior-feedback-fetcher.js';
|
|
21
|
+
import { Logger } from '../../Logger.js';
|
|
22
|
+
import { hasTicketSection } from '../../ticket-body-sections.js';
|
|
23
|
+
import { ensureDocsDigest } from '../docs-digest.js';
|
|
24
|
+
import { applyBudget } from '../planning-context-budget.js';
|
|
25
|
+
import { collectReferences, hasNewFileCue } from '../spec-freshness.js';
|
|
26
26
|
import { buildAuthoringGrounding } from './spec-authoring-grounding.js';
|
|
27
27
|
|
|
28
28
|
/**
|
|
@@ -41,7 +41,7 @@ import { buildAuthoringGrounding } from './spec-authoring-grounding.js';
|
|
|
41
41
|
* @param {{ github?: { owner?: string, repo?: string }|null }} opts
|
|
42
42
|
* @returns {string|null}
|
|
43
43
|
*/
|
|
44
|
-
|
|
44
|
+
function resolveMemoryDir({ github } = {}) {
|
|
45
45
|
if (
|
|
46
46
|
typeof process.env.MANDREL_MEMORY_DIR === 'string' &&
|
|
47
47
|
process.env.MANDREL_MEMORY_DIR.length > 0
|
|
@@ -256,8 +256,8 @@ export async function buildAuthoringContext(
|
|
|
256
256
|
// inside `body` (managed sections), which is how the author keeps
|
|
257
257
|
// AC IDs stable across re-plans.
|
|
258
258
|
planningSections: {
|
|
259
|
-
techSpec:
|
|
260
|
-
acceptanceTable:
|
|
259
|
+
techSpec: hasTicketSection(epic.body ?? '', 'techSpec'),
|
|
260
|
+
acceptanceTable: hasTicketSection(epic.body ?? '', 'acceptanceTable'),
|
|
261
261
|
},
|
|
262
262
|
},
|
|
263
263
|
docsContext,
|