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
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* manifest-render-waves.js
|
|
3
|
-
*
|
|
4
|
-
* Presentation-only: emits the per-wave `## <emoji> Wave N` H2 sections
|
|
5
|
-
* (with nested per-Story H3 headings) that sit beneath the Wave Summary
|
|
6
|
-
* table in the dispatch manifest. Under the 2-tier hierarchy (Epic
|
|
7
|
-
* #3163) Stories are leaves with no child Task tickets, so each wave
|
|
8
|
-
* counts Stories (done/total) and renders one H3 per Story. The TOC
|
|
9
|
-
* links emitted by `renderWaveSections` jump directly into the H2
|
|
10
|
-
* anchors emitted here.
|
|
11
|
-
*
|
|
12
|
-
* Extracted from `manifest-formatter.js` (Story #1849 Task #1870). The
|
|
13
|
-
* shape-guard cascade lives behind a single private `validateWaveSection`
|
|
14
|
-
* predicate so `renderNestedWaveSections` reads as a straight projection
|
|
15
|
-
* and lands below CRAP 12.
|
|
16
|
-
*
|
|
17
|
-
* Imports the small pure helpers from `manifest-helpers.js` ā the
|
|
18
|
-
* formatter re-exports them so existing call-sites that read these
|
|
19
|
-
* names off `manifest-formatter.js` keep working.
|
|
20
|
-
*
|
|
21
|
-
* Story #4157 ā the per-wave grouping key is now a **render-time
|
|
22
|
-
* dependency depth** derived from each Story entry's `dependsOn` edges via
|
|
23
|
-
* `assignLayers` (`lib/Graph.js`), not the persisted `earliestWave` field
|
|
24
|
-
* the planner stamped on the manifest. Scheduling no longer persists waves
|
|
25
|
-
* onto the run checkpoint (Epic #4151 / Story #4155), so the rollup
|
|
26
|
-
* re-derives depth from the dependency graph at the moment it renders. The
|
|
27
|
-
* shared `deriveStoryDepths` lens below is the single home for that
|
|
28
|
-
* derivation; `dispatch-manifest-render.js` imports it so both
|
|
29
|
-
* operator-facing surfaces group by the same render-time depths.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
import { assignLayers } from '../Graph.js';
|
|
33
|
-
import { AGENT_LABELS } from '../label-constants.js';
|
|
34
|
-
import { buildStoryAdjacency } from '../story-adjacency.js';
|
|
35
|
-
import {
|
|
36
|
-
deriveStorySymbol,
|
|
37
|
-
deriveWaveStatus,
|
|
38
|
-
waveHeadingText,
|
|
39
|
-
} from './manifest-helpers.js';
|
|
40
|
-
|
|
41
|
-
// ---------------------------------------------------------------------------
|
|
42
|
-
// Render-time dependency-depth lens (Story #4157)
|
|
43
|
-
// ---------------------------------------------------------------------------
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Derive a render-time dependency depth for every Story entry in a
|
|
47
|
-
* `storyManifest`, keyed by storyId.
|
|
48
|
-
*
|
|
49
|
-
* The depth is computed by feeding the entries' `dependsOn` edges through
|
|
50
|
-
* the canonical `buildStoryAdjacency` builder (the same one the dispatch
|
|
51
|
-
* pipeline and `stories-wave-tick.js` use) and then `assignLayers`
|
|
52
|
-
* (`lib/Graph.js`): a Story with no dependency edges is depth 0, and a
|
|
53
|
-
* Story sits one layer deeper than its deepest in-set dependency. This
|
|
54
|
-
* replaces the planner's persisted `earliestWave` as the grouping key so
|
|
55
|
-
* the rollup renders correctly from the per-Story checkpoint shape, which
|
|
56
|
-
* no longer carries a wave field (Epic #4151 / Story #4155).
|
|
57
|
-
*
|
|
58
|
-
* `buildStoryAdjacency` reads each entry's id from `id ?? number`, so the
|
|
59
|
-
* entries are adapted to expose `id: storyId` and `dependsOn`. Foreign
|
|
60
|
-
* edges (pointing outside the supplied entry set) are dropped ā the
|
|
61
|
-
* default `dropForeign: true` ā so the DAG stays closed over the rendered
|
|
62
|
-
* Stories and depth never deepens on a reference the rollup cannot show.
|
|
63
|
-
* The ungrouped sentinel (`storyId === '__ungrouped__'`) and any non-object
|
|
64
|
-
* entry are skipped; they never participate in the graph.
|
|
65
|
-
*
|
|
66
|
-
* Pure: no IO, no clock. Returns a `Map<storyId, depth>` covering exactly
|
|
67
|
-
* the graph-eligible entries.
|
|
68
|
-
*
|
|
69
|
-
* @param {object[]} storyManifest
|
|
70
|
-
* @returns {Map<number|string, number>}
|
|
71
|
-
*/
|
|
72
|
-
export function deriveStoryDepths(storyManifest) {
|
|
73
|
-
if (!Array.isArray(storyManifest)) return new Map();
|
|
74
|
-
const eligible = storyManifest.filter(
|
|
75
|
-
(s) =>
|
|
76
|
-
s !== null &&
|
|
77
|
-
typeof s === 'object' &&
|
|
78
|
-
s.storyId !== '__ungrouped__' &&
|
|
79
|
-
Number.isInteger(Number(s.storyId)),
|
|
80
|
-
);
|
|
81
|
-
const records = eligible.map((s) => ({
|
|
82
|
-
id: Number(s.storyId),
|
|
83
|
-
dependsOn: Array.isArray(s.dependsOn) ? s.dependsOn : [],
|
|
84
|
-
}));
|
|
85
|
-
const adjacency = buildStoryAdjacency(records);
|
|
86
|
-
const layers = assignLayers(adjacency);
|
|
87
|
-
|
|
88
|
-
const depths = new Map();
|
|
89
|
-
for (const s of eligible) {
|
|
90
|
-
depths.set(s.storyId, layers.get(Number(s.storyId)) ?? 0);
|
|
91
|
-
}
|
|
92
|
-
return depths;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// ---------------------------------------------------------------------------
|
|
96
|
-
// ---------------------------------------------------------------------------
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Private: shape-guard for the per-level nodes touched by the wave
|
|
100
|
-
* renderer. Centralising the checks keeps `renderNestedWaveSections`
|
|
101
|
-
* linear ā the function reads as a straight projection from `storyManifest`
|
|
102
|
-
* into Markdown without re-asserting Array-ness at each loop.
|
|
103
|
-
*
|
|
104
|
-
* `level` describes which input the renderer is about to walk:
|
|
105
|
-
* - `'storyManifest'` ā top-level `storyManifest[]` array
|
|
106
|
-
* - `'story'` ā a single Story manifest entry (object)
|
|
107
|
-
*
|
|
108
|
-
* Returns `true` when the node satisfies the contract; the caller skips
|
|
109
|
-
* or substitutes an empty list when `false`.
|
|
110
|
-
*
|
|
111
|
-
* @param {string} level
|
|
112
|
-
* @param {unknown} value
|
|
113
|
-
* @returns {boolean}
|
|
114
|
-
*/
|
|
115
|
-
function validateWaveSection(level, value) {
|
|
116
|
-
switch (level) {
|
|
117
|
-
case 'storyManifest':
|
|
118
|
-
return Array.isArray(value);
|
|
119
|
-
case 'story':
|
|
120
|
-
return value !== null && typeof value === 'object';
|
|
121
|
-
default:
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Pick the inline tail rendered after the per-wave count blockquote.
|
|
128
|
-
* Pure derivation ā only adds context the table doesn't already carry:
|
|
129
|
-
* the gating wave when this one is Blocked, or the parallel-fan-out
|
|
130
|
-
* count when multiple Stories run in parallel in a Ready wave.
|
|
131
|
-
*
|
|
132
|
-
* @param {{ word: string }} status
|
|
133
|
-
* @param {number} waveIdx
|
|
134
|
-
* @param {number[]} sortedWaves
|
|
135
|
-
* @param {number} storyCount
|
|
136
|
-
* @returns {string}
|
|
137
|
-
*/
|
|
138
|
-
function pickWaveTail(status, waveIdx, sortedWaves, storyCount) {
|
|
139
|
-
if (status.word === 'Blocked') {
|
|
140
|
-
const priorWaves = sortedWaves.filter((sw) => sw < waveIdx);
|
|
141
|
-
const lastPrior = priorWaves[priorWaves.length - 1];
|
|
142
|
-
if (lastPrior !== undefined) return ` Ā· gated on Wave ${lastPrior}`;
|
|
143
|
-
return '';
|
|
144
|
-
}
|
|
145
|
-
if (status.word === 'Ready' && storyCount > 1) {
|
|
146
|
-
return ` Ā· ${storyCount} run in parallel`;
|
|
147
|
-
}
|
|
148
|
-
return '';
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Group Stories into per-wave buckets and accumulate per-wave Story
|
|
153
|
-
* totals. Pure helper ā keeps the bookkeeping outside the main render
|
|
154
|
-
* loop. Under the 2-tier hierarchy (Epic #3163) Stories are leaves with
|
|
155
|
-
* no child Task tickets, so each wave's `total` / `done` counts Stories
|
|
156
|
-
* (a Story is "done" when it carries `agent::done`) ā the unit
|
|
157
|
-
* `deriveWaveStatus` consumes.
|
|
158
|
-
*
|
|
159
|
-
* Story #4157 ā the bucket key is the render-time dependency depth from
|
|
160
|
-
* `depths` (keyed by storyId), not the persisted `earliestWave`. The
|
|
161
|
-
* ungrouped sentinel and any entry the lens could not place fall into the
|
|
162
|
-
* `-1` "Ungrouped" bucket so they still render.
|
|
163
|
-
*
|
|
164
|
-
* @param {object[]} waveStories
|
|
165
|
-
* @param {Map<number|string, number>} depths
|
|
166
|
-
* @returns {{ waveGroups: Map<number, object[]>, waveStats: Map<number, { total: number, done: number }> }}
|
|
167
|
-
*/
|
|
168
|
-
function groupStoriesByWave(waveStories, depths) {
|
|
169
|
-
const waveGroups = new Map();
|
|
170
|
-
const waveStats = new Map();
|
|
171
|
-
for (const story of waveStories) {
|
|
172
|
-
const w = depths.get(story.storyId) ?? -1;
|
|
173
|
-
if (!waveGroups.has(w)) {
|
|
174
|
-
waveGroups.set(w, []);
|
|
175
|
-
waveStats.set(w, { total: 0, done: 0 });
|
|
176
|
-
}
|
|
177
|
-
waveGroups.get(w).push(story);
|
|
178
|
-
const stat = waveStats.get(w);
|
|
179
|
-
stat.total++;
|
|
180
|
-
if (story.status === AGENT_LABELS.DONE) stat.done++;
|
|
181
|
-
}
|
|
182
|
-
return { waveGroups, waveStats };
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Render one `## <emoji> Wave N` section per wave with nested per-Story H3
|
|
187
|
-
* headings. The TOC links from `renderWaveSections` jump straight into
|
|
188
|
-
* these H2 anchors.
|
|
189
|
-
*
|
|
190
|
-
* @param {object[]} storyManifest
|
|
191
|
-
* @returns {string} Markdown block, or empty string when nothing to render.
|
|
192
|
-
*/
|
|
193
|
-
export function renderNestedWaveSections(storyManifest) {
|
|
194
|
-
if (!validateWaveSection('storyManifest', storyManifest)) return '';
|
|
195
|
-
if (storyManifest.length === 0) return '';
|
|
196
|
-
|
|
197
|
-
const waveStories = storyManifest.filter((s) =>
|
|
198
|
-
validateWaveSection('story', s),
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
const depths = deriveStoryDepths(waveStories);
|
|
202
|
-
const { waveGroups, waveStats } = groupStoriesByWave(waveStories, depths);
|
|
203
|
-
const sortedWaves = [...waveGroups.keys()].sort((a, b) => a - b);
|
|
204
|
-
const lines = [];
|
|
205
|
-
|
|
206
|
-
for (const waveIdx of sortedWaves) {
|
|
207
|
-
const stories = waveGroups.get(waveIdx);
|
|
208
|
-
const stat = waveStats.get(waveIdx);
|
|
209
|
-
const waveLabel = waveIdx === -1 ? 'Ungrouped' : `Wave ${waveIdx}`;
|
|
210
|
-
const status = deriveWaveStatus(waveIdx, waveStats, sortedWaves);
|
|
211
|
-
|
|
212
|
-
// The H2 text and slug must match `renderWaveSections` exactly so the
|
|
213
|
-
// TOC links land on the right anchor.
|
|
214
|
-
lines.push(`## ${waveHeadingText(waveLabel, status.emoji)}`);
|
|
215
|
-
lines.push('');
|
|
216
|
-
|
|
217
|
-
const tail = pickWaveTail(status, waveIdx, sortedWaves, stories.length);
|
|
218
|
-
lines.push(
|
|
219
|
-
`> ${stories.length} stor${stories.length === 1 ? 'y' : 'ies'} Ā· ${stat.done}/${stat.total} done${tail}`,
|
|
220
|
-
);
|
|
221
|
-
lines.push('');
|
|
222
|
-
|
|
223
|
-
for (const story of stories) {
|
|
224
|
-
const symbol = deriveStorySymbol(story);
|
|
225
|
-
const titleCandidate = story.storyTitle || story.storySlug || '';
|
|
226
|
-
lines.push(`### ${symbol} #${story.storyId} ā ${titleCandidate}`);
|
|
227
|
-
lines.push('');
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return lines.join('\n');
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Render the "Concurrency hazards" block that sits at the foot of the
|
|
236
|
-
* dispatch manifest. Consumes the structured findings array emitted by
|
|
237
|
-
* `computeConflictFindings` (Story #2296):
|
|
238
|
-
*
|
|
239
|
-
* - `shared-editor` findings ā one bullet per path with the conflicting
|
|
240
|
-
* Story identifiers and a `depends_on` remediation hint.
|
|
241
|
-
* - `implicit-cross-story-dep` findings ā one bullet per missing dep
|
|
242
|
-
* with the producer/consumer pair and a `depends_on` remediation hint.
|
|
243
|
-
*
|
|
244
|
-
* When `findings` is empty the renderer emits a single-line confirmation
|
|
245
|
-
* (`ā No concurrency hazards detected.`) so absence is explicit in the
|
|
246
|
-
* dry-run log rather than silently dropped.
|
|
247
|
-
*
|
|
248
|
-
* Story identifiers are rendered verbatim ā the validator carries planning
|
|
249
|
-
* slugs (e.g. `s-foo`) while persisted findings carry GitHub issue numbers
|
|
250
|
-
* (e.g. `201`). The renderer is agnostic; whichever identifier the caller
|
|
251
|
-
* passes is what shows up.
|
|
252
|
-
*
|
|
253
|
-
* @param {object[]} findings
|
|
254
|
-
* @returns {string} Markdown block, or empty string when `findings` is
|
|
255
|
-
* neither an array nor undefined (defensive no-op).
|
|
256
|
-
*/
|
|
257
|
-
export function renderConcurrencyHazards(findings) {
|
|
258
|
-
if (findings === undefined || findings === null) return '';
|
|
259
|
-
if (!Array.isArray(findings)) return '';
|
|
260
|
-
const lines = ['## ā ļø Concurrency Hazards', ''];
|
|
261
|
-
if (findings.length === 0) {
|
|
262
|
-
lines.push('ā No concurrency hazards detected.');
|
|
263
|
-
lines.push('');
|
|
264
|
-
return lines.join('\n');
|
|
265
|
-
}
|
|
266
|
-
const sharedEditors = findings.filter((f) => f?.kind === 'shared-editor');
|
|
267
|
-
const implicit = findings.filter(
|
|
268
|
-
(f) => f?.kind === 'implicit-cross-story-dep',
|
|
269
|
-
);
|
|
270
|
-
for (const f of sharedEditors.sort((a, b) =>
|
|
271
|
-
(a.path ?? '').localeCompare(b.path ?? ''),
|
|
272
|
-
)) {
|
|
273
|
-
lines.push(...renderSharedEditorBullet(f));
|
|
274
|
-
}
|
|
275
|
-
for (const f of implicit.sort((a, b) =>
|
|
276
|
-
(a.path ?? '').localeCompare(b.path ?? ''),
|
|
277
|
-
)) {
|
|
278
|
-
lines.push(...renderImplicitDepBullet(f));
|
|
279
|
-
}
|
|
280
|
-
lines.push('');
|
|
281
|
-
return lines.join('\n');
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function renderSharedEditorBullet(finding) {
|
|
285
|
-
const stories = Array.isArray(finding.storySlugs) ? finding.storySlugs : [];
|
|
286
|
-
const storyList = stories.map((s) => `\`${s}\``).join(', ');
|
|
287
|
-
const sev = finding.severity === 'hard' ? ' **(blocking)**' : '';
|
|
288
|
-
return [
|
|
289
|
-
`- **\`${finding.path}\`** ā written by ${stories.length} concurrent Stories: ${storyList}${sev}`,
|
|
290
|
-
' - Recommend serializing via `depends_on` chains or a dedicated late-wave "wiring" Story.',
|
|
291
|
-
];
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
function renderImplicitDepBullet(finding) {
|
|
295
|
-
const producer = finding.producer ?? {};
|
|
296
|
-
const consumer = finding.consumer ?? {};
|
|
297
|
-
const sev = finding.severity === 'hard' ? ' **(blocking)**' : '';
|
|
298
|
-
return [
|
|
299
|
-
`- **\`${finding.path}\`** ā produced by Story \`${producer.storySlug ?? '?'}\` (Task \`${producer.taskSlug ?? '?'}\`), consumed by Story \`${consumer.storySlug ?? '?'}\` (Task \`${consumer.taskSlug ?? '?'}\`, \`body.${consumer.sourceField ?? '?'}\`)${sev}`,
|
|
300
|
-
` - Recommend: add \`depends_on: ["${producer.storySlug ?? '?'}"]\` to the consumer Story.`,
|
|
301
|
-
];
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Test-only: surface the private predicate so the sibling unit test can
|
|
305
|
-
// exercise each branch without going through the full renderer.
|
|
306
|
-
export const __testables = { validateWaveSection, groupStoriesByWave };
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* manifest-renderer.js
|
|
3
|
-
*
|
|
4
|
-
* Facade that composes the presentation layer:
|
|
5
|
-
* - `manifest-formatter.js` ā pure Markdown / CLI rendering.
|
|
6
|
-
* - `manifest-persistence.js` ā write manifests to `temp/`.
|
|
7
|
-
* - GitHub comment upserts ā `postManifestEpicComment` / `postParkedFollowOnsComment`.
|
|
8
|
-
*
|
|
9
|
-
* Keeps every export that external callers consume today so the split is
|
|
10
|
-
* internal: dispatcher.js and tests all continue to import from this path.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { resolveConfig } from '../config-resolver.js';
|
|
14
|
-
import { TYPE_LABELS } from '../label-constants.js';
|
|
15
|
-
import {
|
|
16
|
-
classifyStoriesAgainstManifest,
|
|
17
|
-
renderParkedFollowOnsComment,
|
|
18
|
-
} from '../orchestration/parked-follow-ons.js';
|
|
19
|
-
import { upsertStructuredComment } from '../orchestration/ticketing.js';
|
|
20
|
-
import { renderManifestFromManifest } from './dispatch-manifest-render.js';
|
|
21
|
-
import {
|
|
22
|
-
buildManifestFromSpec,
|
|
23
|
-
formatManifestMarkdown,
|
|
24
|
-
formatStoryManifestMarkdown,
|
|
25
|
-
fromManifest,
|
|
26
|
-
fromSpec,
|
|
27
|
-
printStoryDispatchTable,
|
|
28
|
-
renderManifestMarkdown,
|
|
29
|
-
} from './manifest-formatter.js';
|
|
30
|
-
import { persistManifest } from './manifest-persistence.js';
|
|
31
|
-
|
|
32
|
-
export {
|
|
33
|
-
buildManifestFromSpec,
|
|
34
|
-
formatManifestMarkdown,
|
|
35
|
-
fromManifest,
|
|
36
|
-
fromSpec,
|
|
37
|
-
persistManifest,
|
|
38
|
-
printStoryDispatchTable,
|
|
39
|
-
renderManifestMarkdown,
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Backwards-compatible Markdown renderer for story-execution manifests.
|
|
44
|
-
* Resolves config internally to cite the canonical script paths. The pure
|
|
45
|
-
* variant lives at `manifest-formatter.js::formatStoryManifestMarkdown` ā new
|
|
46
|
-
* call-sites should prefer that and inject the canonical `config` bag
|
|
47
|
-
* explicitly.
|
|
48
|
-
*
|
|
49
|
-
* @param {object} manifest
|
|
50
|
-
* @returns {string}
|
|
51
|
-
*/
|
|
52
|
-
export function renderStoryManifestMarkdown(manifest) {
|
|
53
|
-
const config = resolveConfig();
|
|
54
|
-
return formatStoryManifestMarkdown(manifest, { config });
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Pure: a manifest qualifies for an Epic comment upsert when it exists, is
|
|
59
|
-
* not a story-execution dry-run, and carries an epicId.
|
|
60
|
-
*
|
|
61
|
-
* @param {unknown} manifest
|
|
62
|
-
*/
|
|
63
|
-
export function isEpicManifest(manifest) {
|
|
64
|
-
if (!manifest || typeof manifest !== 'object') return false;
|
|
65
|
-
return manifest.type !== 'story-execution' && Boolean(manifest.epicId);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Pure: a provider can upsert a comment when it is non-nullish and exposes a
|
|
70
|
-
* callable `postComment`.
|
|
71
|
-
*
|
|
72
|
-
* @param {unknown} provider
|
|
73
|
-
*/
|
|
74
|
-
export function providerCanPostComment(provider) {
|
|
75
|
-
return Boolean(provider) && typeof provider?.postComment === 'function';
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Classify whether `(manifest, provider)` are eligible for an Epic comment
|
|
80
|
-
* upsert. Returns `null` when eligible, otherwise the skip-reason string.
|
|
81
|
-
*
|
|
82
|
-
* @param {unknown} manifest
|
|
83
|
-
* @param {unknown} provider
|
|
84
|
-
* @returns {null | 'not-an-epic-manifest' | 'no-provider'}
|
|
85
|
-
*/
|
|
86
|
-
export function classifyEpicCommentEligibility(manifest, provider) {
|
|
87
|
-
if (!isEpicManifest(manifest)) return 'not-an-epic-manifest';
|
|
88
|
-
if (!providerCanPostComment(provider)) return 'no-provider';
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Persist the Epic's dispatch manifest as a structured comment on the Epic
|
|
94
|
-
* issue. Idempotent ā replaces any existing `dispatch-manifest` comment.
|
|
95
|
-
* No-op in dry-run-only story manifests (no epicId).
|
|
96
|
-
*
|
|
97
|
-
* @param {object} manifest
|
|
98
|
-
* @param {import('../ITicketingProvider.js').ITicketingProvider} provider
|
|
99
|
-
* @returns {Promise<{ posted: boolean, reason?: string }>}
|
|
100
|
-
*/
|
|
101
|
-
export async function postManifestEpicComment(manifest, provider) {
|
|
102
|
-
const skipReason = classifyEpicCommentEligibility(manifest, provider);
|
|
103
|
-
if (skipReason) return { posted: false, reason: skipReason };
|
|
104
|
-
|
|
105
|
-
// Body rendering lives in the pure `dispatch-manifest-render.js`
|
|
106
|
-
// helper so the wave-runner's in-process refresh hop can produce a
|
|
107
|
-
// byte-identical body without spawning `dispatcher.js --dry-run`.
|
|
108
|
-
const body = renderManifestFromManifest(manifest);
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
await upsertStructuredComment(
|
|
112
|
-
provider,
|
|
113
|
-
manifest.epicId,
|
|
114
|
-
'dispatch-manifest',
|
|
115
|
-
body,
|
|
116
|
-
);
|
|
117
|
-
return { posted: true };
|
|
118
|
-
} catch (err) {
|
|
119
|
-
process.stderr.write(
|
|
120
|
-
`[Dispatcher] Failed to persist dispatch-manifest comment to Epic #${manifest.epicId}: ${err.message}\n`,
|
|
121
|
-
);
|
|
122
|
-
return { posted: false, reason: err.message };
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Classify Stories under the Epic against the frozen dispatch manifest and
|
|
128
|
-
* upsert a `parked-follow-ons` structured comment on the Epic. Idempotent.
|
|
129
|
-
*
|
|
130
|
-
* @param {object} manifest
|
|
131
|
-
* @param {import('../ITicketingProvider.js').ITicketingProvider} provider
|
|
132
|
-
* @returns {Promise<{ posted: boolean, recuts: number, parked: number, reason?: string }>}
|
|
133
|
-
*/
|
|
134
|
-
export async function postParkedFollowOnsComment(manifest, provider) {
|
|
135
|
-
const skipReason = classifyEpicCommentEligibility(manifest, provider);
|
|
136
|
-
if (skipReason) {
|
|
137
|
-
return { posted: false, recuts: 0, parked: 0, reason: skipReason };
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const storyManifest = manifest.storyManifest ?? [];
|
|
141
|
-
const manifestStoryIds = storyManifest
|
|
142
|
-
.filter((s) => s.storyId !== '__ungrouped__')
|
|
143
|
-
.map((s) => Number(s.storyId))
|
|
144
|
-
.filter((n) => Number.isFinite(n));
|
|
145
|
-
|
|
146
|
-
let storiesUnderEpic = [];
|
|
147
|
-
try {
|
|
148
|
-
const all = await provider.getTickets(manifest.epicId);
|
|
149
|
-
if (all) {
|
|
150
|
-
provider.primeTicketCache(all);
|
|
151
|
-
}
|
|
152
|
-
storiesUnderEpic = (all ?? []).filter((t) =>
|
|
153
|
-
(t.labels ?? []).includes(TYPE_LABELS.STORY),
|
|
154
|
-
);
|
|
155
|
-
} catch (err) {
|
|
156
|
-
return { posted: false, recuts: 0, parked: 0, reason: err.message };
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const classification = classifyStoriesAgainstManifest(
|
|
160
|
-
manifestStoryIds,
|
|
161
|
-
storiesUnderEpic,
|
|
162
|
-
);
|
|
163
|
-
const body = renderParkedFollowOnsComment(manifest.epicId, classification);
|
|
164
|
-
|
|
165
|
-
try {
|
|
166
|
-
await upsertStructuredComment(
|
|
167
|
-
provider,
|
|
168
|
-
manifest.epicId,
|
|
169
|
-
'parked-follow-ons',
|
|
170
|
-
body,
|
|
171
|
-
);
|
|
172
|
-
return {
|
|
173
|
-
posted: true,
|
|
174
|
-
recuts: classification.recuts.length,
|
|
175
|
-
parked: classification.parked.length,
|
|
176
|
-
};
|
|
177
|
-
} catch (err) {
|
|
178
|
-
process.stderr.write(
|
|
179
|
-
`[Dispatcher] Failed to persist parked-follow-ons comment to Epic #${manifest.epicId}: ${err.message}\n`,
|
|
180
|
-
);
|
|
181
|
-
return {
|
|
182
|
-
posted: false,
|
|
183
|
-
recuts: classification.recuts.length,
|
|
184
|
-
parked: classification.parked.length,
|
|
185
|
-
reason: err.message,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* manifest-story-views.js
|
|
3
|
-
*
|
|
4
|
-
* Story-execution manifest renderer (`formatStoryManifestMarkdown`) plus
|
|
5
|
-
* the CLI dispatch-table printer (`printStoryDispatchTable`). Split out
|
|
6
|
-
* of `manifest-formatter.js` (Story #1849 Task #1871) so the parent
|
|
7
|
-
* collapses to the dispatch-manifest wiring facade.
|
|
8
|
-
*
|
|
9
|
-
* Re-exported from `manifest-formatter.js` so existing call-sites and
|
|
10
|
-
* tests that import from there keep working without a path change.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { Logger } from '../Logger.js';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Format the per-story execution manifest. Pure: caller must supply
|
|
17
|
-
* `opts.config` (the canonical resolved config bag) so we can cite the
|
|
18
|
-
* canonical `story-init.js` / `story-close.js` paths without touching
|
|
19
|
-
* `resolveConfig` (fs).
|
|
20
|
-
*
|
|
21
|
-
* Reads `config.project.paths.scriptsRoot` and `config.project.commands.*`
|
|
22
|
-
* from the post-reshape canonical blocks (Epic #1720). The fallback
|
|
23
|
-
* strings keep the formatter usable in tiny test fixtures that omit the
|
|
24
|
-
* paths / commands block.
|
|
25
|
-
*
|
|
26
|
-
* @param {object} manifest
|
|
27
|
-
* @param {{ config?: { project?: { paths?: { scriptsRoot?: string }, commands?: { validate?: string, test?: string } } } }} [opts]
|
|
28
|
-
* @returns {string}
|
|
29
|
-
*/
|
|
30
|
-
export function formatStoryManifestMarkdown(manifest, opts = {}) {
|
|
31
|
-
const project = opts.config?.project ?? {};
|
|
32
|
-
const scriptsRoot = project.paths?.scriptsRoot ?? '.agents/scripts';
|
|
33
|
-
const commands = project.commands ?? {};
|
|
34
|
-
const validateCmd = commands.validate ?? 'npm run lint';
|
|
35
|
-
const testCmd = commands.test ?? 'npm test';
|
|
36
|
-
|
|
37
|
-
const lines = [];
|
|
38
|
-
lines.push(`# š Story Execution Manifest`);
|
|
39
|
-
lines.push('');
|
|
40
|
-
lines.push(`> **Generated:** ${manifest.generatedAt}`);
|
|
41
|
-
lines.push('');
|
|
42
|
-
|
|
43
|
-
for (const story of manifest.stories) {
|
|
44
|
-
lines.push(`## Story #${story.storyId}: ${story.storyTitle}`);
|
|
45
|
-
lines.push(`- **Epic Branch:** \`${story.epicBranch}\``);
|
|
46
|
-
lines.push(`- **Story Branch:** \`${story.branchName}\``);
|
|
47
|
-
lines.push('');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
lines.push('---');
|
|
51
|
-
lines.push('');
|
|
52
|
-
lines.push('## Execution Steps');
|
|
53
|
-
lines.push('');
|
|
54
|
-
|
|
55
|
-
const initPath = `${scriptsRoot}/story-init.js`;
|
|
56
|
-
const closePath = `${scriptsRoot}/story-close.js`;
|
|
57
|
-
|
|
58
|
-
lines.push(
|
|
59
|
-
`1. \`node ${initPath} --story <storyId>\` (bootstraps branch, transitions Story)`,
|
|
60
|
-
);
|
|
61
|
-
lines.push(
|
|
62
|
-
'2. Implement the Story body acceptance criteria and commit on the Story branch.',
|
|
63
|
-
);
|
|
64
|
-
lines.push(`3. Run \`${validateCmd}\` and \`${testCmd}\` to validate.`);
|
|
65
|
-
lines.push(
|
|
66
|
-
`4. \`node <main-repo>/${closePath} --story <storyId> --cwd <main-repo>\` (merges, cleans up, closes tickets)`,
|
|
67
|
-
);
|
|
68
|
-
lines.push('');
|
|
69
|
-
|
|
70
|
-
return lines.join('\n');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Print the CLI Story Dispatch Table. Writes to the supplied `logger.log`
|
|
75
|
-
* channel (defaults to `Logger.info`). Keeping the sink injectable makes
|
|
76
|
-
* the function testable without capturing stdout.
|
|
77
|
-
*
|
|
78
|
-
* @param {object[]} storyManifest
|
|
79
|
-
* @param {{ logger?: { log: (line: string) => void } }} [opts]
|
|
80
|
-
*/
|
|
81
|
-
/* node:coverage ignore next */
|
|
82
|
-
export function printStoryDispatchTable(storyManifest, opts = {}) {
|
|
83
|
-
const log = opts.logger?.log ?? ((line) => Logger.info(line));
|
|
84
|
-
if (!storyManifest || storyManifest.length === 0) return;
|
|
85
|
-
|
|
86
|
-
const stories = storyManifest;
|
|
87
|
-
|
|
88
|
-
log('\nāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāā');
|
|
89
|
-
log('ā š STORY DISPATCH TABLE ā');
|
|
90
|
-
log('āāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāā¤');
|
|
91
|
-
log('ā Story ā Title ā Wave ā');
|
|
92
|
-
log('āāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāā¤');
|
|
93
|
-
|
|
94
|
-
for (const story of stories) {
|
|
95
|
-
const id =
|
|
96
|
-
story.storyId === '__ungrouped__' ? '(none)' : `#${story.storyId}`;
|
|
97
|
-
const title = (story.storySlug ?? '').substring(0, 36).padEnd(36);
|
|
98
|
-
const wave = (
|
|
99
|
-
story.earliestWave === -1 ? '-' : String(story.earliestWave)
|
|
100
|
-
).padEnd(4);
|
|
101
|
-
log(`ā ${id.padEnd(7)} ā ${title} ā ${wave} ā`);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
log('āāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāā');
|
|
105
|
-
log('');
|
|
106
|
-
log(' š” Stories in the same [Wave] can be executed in parallel.');
|
|
107
|
-
log(' š” Use /deliver #[Story ID] to execute a Story.');
|
|
108
|
-
|
|
109
|
-
log('');
|
|
110
|
-
}
|