mandrel 1.59.0 → 1.60.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 +14 -14
- package/.agents/docs/SDLC.md +129 -134
- package/.agents/docs/configuration.md +16 -16
- package/.agents/docs/workflows.md +6 -8
- package/.agents/instructions.md +12 -11
- package/.agents/personas/architect.md +1 -1
- package/.agents/personas/product.md +1 -1
- package/.agents/personas/project-manager.md +14 -14
- package/.agents/personas/technical-writer.md +1 -1
- package/.agents/rules/changelog-style.md +5 -5
- package/.agents/rules/git-conventions.md +3 -3
- package/.agents/schemas/agentrc.schema.json +3 -3
- package/.agents/schemas/dispatch-manifest.json +4 -4
- package/.agents/schemas/epic-spec.schema.json +15 -45
- package/.agents/schemas/lifecycle/README.md +1 -1
- package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +1 -1
- package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +1 -1
- package/.agents/schemas/lifecycle/story.heartbeat.schema.json +1 -1
- package/.agents/schemas/validation-evidence.schema.json +1 -1
- package/.agents/scripts/README.md +1 -1
- package/.agents/scripts/acceptance-eval.js +1 -1
- package/.agents/scripts/acceptance-spec-reconciler.js +2 -2
- package/.agents/scripts/analyze-execution.js +2 -2
- package/.agents/scripts/audit-to-stories.js +1 -1
- package/.agents/scripts/check-doc-links.js +2 -3
- package/.agents/scripts/diagnose-friction.js +1 -1
- package/.agents/scripts/dispatcher.js +2 -2
- package/.agents/scripts/drain-pending-cleanup.js +1 -1
- package/.agents/scripts/epic-audit-prepare.js +3 -3
- package/.agents/scripts/epic-deliver-note-intervention.js +2 -2
- package/.agents/scripts/epic-deliver-preflight.js +6 -6
- package/.agents/scripts/epic-deliver-prepare.js +1 -1
- package/.agents/scripts/epic-execute-record-wave.js +4 -4
- package/.agents/scripts/epic-plan-healthcheck.js +6 -10
- package/.agents/scripts/epic-plan-spec-validate.js +1 -1
- package/.agents/scripts/epic-reconcile.js +11 -29
- package/.agents/scripts/evidence-gate.js +1 -1
- package/.agents/scripts/generate-workflows-doc.js +1 -1
- package/.agents/scripts/hierarchy-gate.js +7 -11
- package/.agents/scripts/lib/ITicketingProvider.js +1 -1
- package/.agents/scripts/lib/audit-suite/selector.js +1 -1
- package/.agents/scripts/lib/audit-to-stories/seed-epic-from-findings.js +2 -2
- package/.agents/scripts/lib/baseline-snapshot.js +7 -7
- package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
- package/.agents/scripts/lib/bdd-scenario-scanner.js +3 -3
- package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +1 -1
- package/.agents/scripts/lib/bootstrap/branch-protection.js +1 -1
- package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +1 -1
- package/.agents/scripts/lib/bootstrap/commit-push.js +2 -2
- package/.agents/scripts/lib/codebase-snapshot.js +1 -1
- package/.agents/scripts/lib/config/explain.js +1 -1
- package/.agents/scripts/lib/config/runners.js +2 -2
- package/.agents/scripts/lib/config/runtime.js +1 -1
- package/.agents/scripts/lib/config/temp-paths.js +2 -2
- package/.agents/scripts/lib/config-settings-schema-delivery.js +2 -2
- package/.agents/scripts/lib/config-settings-schema-quality.js +1 -1
- package/.agents/scripts/lib/config-settings-schema.js +3 -3
- package/.agents/scripts/lib/duplicate-search.js +1 -1
- package/.agents/scripts/lib/dynamic-workflow/capability.js +1 -1
- package/.agents/scripts/lib/epic-plan-clarity.js +1 -1
- package/.agents/scripts/lib/epic-plan-ideation.js +1 -1
- package/.agents/scripts/lib/feedback-loop/memory-freshness.js +1 -1
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +1 -1
- package/.agents/scripts/lib/findings/classify-finding.js +1 -1
- package/.agents/scripts/lib/findings/promote-finding.js +10 -10
- package/.agents/scripts/lib/label-constants.js +3 -4
- package/.agents/scripts/lib/label-taxonomy.js +3 -8
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +1 -1
- package/.agents/scripts/lib/orchestration/code-review.js +5 -5
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +8 -9
- package/.agents/scripts/lib/orchestration/dependency-analyzer.js +3 -3
- package/.agents/scripts/lib/orchestration/detectors-phase.js +2 -2
- package/.agents/scripts/lib/orchestration/dispatch-engine.js +30 -38
- package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +9 -25
- package/.agents/scripts/lib/orchestration/epic-cleanup.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +8 -8
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +7 -21
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +3 -3
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +26 -13
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +2 -2
- package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-run-state-store.js +3 -3
- package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +4 -4
- package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +3 -3
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +6 -21
- package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +7 -7
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +1 -1
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +2 -2
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +4 -4
- package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +4 -4
- package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +8 -8
- package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +4 -4
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +7 -15
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +72 -41
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +2 -4
- package/.agents/scripts/lib/orchestration/file-assumptions.js +2 -2
- package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +1 -1
- package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +2 -2
- package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +1 -1
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -3
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +1 -1
- package/.agents/scripts/lib/orchestration/manifest-builder.js +5 -5
- package/.agents/scripts/lib/orchestration/parked-follow-ons.js +2 -2
- package/.agents/scripts/lib/orchestration/plan-runner/plan-router.js +5 -5
- package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +3 -3
- package/.agents/scripts/lib/orchestration/preflight-cache.js +1 -1
- package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +1 -1
- package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +1 -1
- package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +2 -2
- package/.agents/scripts/lib/orchestration/retro-runner.js +3 -3
- package/.agents/scripts/lib/orchestration/review-depth.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +1 -1
- package/.agents/scripts/lib/orchestration/spec-freshness.js +1 -1
- package/.agents/scripts/lib/orchestration/spec-renderer.js +36 -73
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +1 -1
- package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +1 -1
- package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +2 -2
- package/.agents/scripts/lib/orchestration/task-body-validator.js +6 -6
- package/.agents/scripts/lib/orchestration/ticket-lease.js +1 -1
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +2 -2
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +1 -10
- package/.agents/scripts/lib/orchestration/ticket-validator.js +25 -70
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +5 -12
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +8 -8
- package/.agents/scripts/lib/orchestration/ticketing/state.js +3 -3
- package/.agents/scripts/lib/orchestration/wave-record-notifications.js +2 -2
- package/.agents/scripts/lib/orchestration/wave-record-projection.js +1 -1
- package/.agents/scripts/lib/plan-phase-cleanup.js +1 -1
- package/.agents/scripts/lib/preflight-runner.js +1 -1
- package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +4 -5
- package/.agents/scripts/lib/presentation/manifest-builder.js +28 -34
- package/.agents/scripts/lib/presentation/manifest-formatter.js +3 -4
- package/.agents/scripts/lib/presentation/manifest-helpers.js +1 -1
- package/.agents/scripts/lib/presentation/manifest-procedures.js +4 -4
- package/.agents/scripts/lib/presentation/manifest-render-waves.js +4 -23
- package/.agents/scripts/lib/presentation/manifest-renderer.js +1 -1
- package/.agents/scripts/lib/presentation/manifest-story-views.js +2 -11
- package/.agents/scripts/lib/signals/schema.js +1 -1
- package/.agents/scripts/lib/spec/index.js +1 -1
- package/.agents/scripts/lib/spec/loader.js +2 -2
- package/.agents/scripts/lib/spec/state.js +7 -16
- package/.agents/scripts/lib/story-init/context-resolver.js +3 -3
- package/.agents/scripts/lib/story-init/state-transitioner.js +2 -2
- package/.agents/scripts/lib/story-init/task-graph-builder.js +7 -7
- package/.agents/scripts/lib/story-lifecycle.js +8 -8
- package/.agents/scripts/lib/story-plan.js +1 -1
- package/.agents/scripts/lib/templates/decomposer-prompts.js +59 -52
- package/.agents/scripts/lib/wave-runner/tick.js +1 -1
- package/.agents/scripts/lifecycle-emit-story-dispatch.js +1 -1
- package/.agents/scripts/lifecycle-emit.js +1 -1
- package/.agents/scripts/providers/github/board-add.js +1 -1
- package/.agents/scripts/providers/github/errors.js +1 -1
- package/.agents/scripts/providers/github/mappers.js +2 -2
- package/.agents/scripts/providers/github/tickets.js +4 -4
- package/.agents/scripts/resync-status-column.js +1 -1
- package/.agents/scripts/retro-run.js +2 -2
- package/.agents/scripts/run-lint.js +1 -1
- package/.agents/scripts/single-story-init.js +1 -1
- package/.agents/scripts/stories-wave-tick.js +5 -5
- package/.agents/scripts/story-close.js +1 -1
- package/.agents/scripts/story-init.js +13 -16
- package/.agents/scripts/story-phase.js +5 -5
- package/.agents/scripts/story-plan.js +3 -3
- package/.agents/scripts/sync-branch-from-base.js +1 -1
- package/.agents/scripts/validate-docs-freshness.js +1 -1
- package/.agents/scripts/wave-tick.js +1 -1
- package/.agents/skills/core/analyze-execution/SKILL.md +2 -2
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +21 -26
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +23 -56
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +4 -4
- package/.agents/skills/core/hydrate-context/SKILL.md +2 -2
- package/.agents/skills/core/idea-refinement/SKILL.md +4 -4
- package/.agents/skills/core/knowledge-transfer/SKILL.md +2 -2
- package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +1 -1
- package/.agents/skills/core/scope-triage/SKILL.md +9 -10
- package/.agents/skills/core/using-agent-skills/SKILL.md +1 -1
- package/.agents/skills/skills.index.json +7 -7
- package/.agents/templates/agent-protocol.md +2 -2
- package/.agents/workflows/agents-update.md +2 -2
- package/.agents/workflows/audit-architecture.md +2 -2
- package/.agents/workflows/audit-clean-code.md +2 -2
- package/.agents/workflows/audit-dependencies.md +1 -1
- package/.agents/workflows/audit-devops.md +1 -1
- package/.agents/workflows/audit-documentation.md +2 -2
- package/.agents/workflows/audit-lighthouse.md +1 -1
- package/.agents/workflows/audit-performance.md +2 -2
- package/.agents/workflows/audit-privacy.md +1 -1
- package/.agents/workflows/audit-quality.md +2 -2
- package/.agents/workflows/audit-security.md +2 -2
- package/.agents/workflows/audit-seo.md +1 -1
- package/.agents/workflows/audit-sre.md +1 -1
- package/.agents/workflows/audit-to-stories.md +10 -10
- package/.agents/workflows/audit-ux-ui.md +1 -1
- package/.agents/workflows/deliver.md +85 -0
- package/.agents/workflows/explain.md +3 -3
- package/.agents/workflows/git-merge-pr.md +1 -1
- package/.agents/workflows/git-pr-all.md +13 -10
- package/.agents/workflows/git-push.md +6 -3
- package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
- package/.agents/workflows/helpers/acceptance-self-eval.md +1 -1
- package/.agents/workflows/helpers/code-review.md +5 -5
- package/.agents/workflows/{epic-deliver.md → helpers/deliver-epic.md} +43 -43
- package/.agents/workflows/{story-deliver.md → helpers/deliver-stories.md} +25 -25
- package/.agents/workflows/helpers/diagnose.md +1 -1
- package/.agents/workflows/helpers/epic-audit.md +6 -6
- package/.agents/workflows/helpers/epic-deliver-story.md +13 -13
- package/.agents/workflows/helpers/epic-plan-decompose.md +23 -23
- package/.agents/workflows/helpers/epic-plan-spec.md +6 -6
- package/.agents/workflows/helpers/epic-testing.md +3 -3
- package/.agents/workflows/helpers/parallel-tooling.md +1 -1
- package/.agents/workflows/{epic-plan.md → helpers/plan-epic.md} +84 -84
- package/.agents/workflows/{story-plan.md → helpers/plan-story.md} +43 -43
- package/.agents/workflows/helpers/signals.md +1 -1
- package/.agents/workflows/helpers/single-story-deliver.md +11 -11
- package/.agents/workflows/helpers/worktree-lifecycle.md +18 -18
- package/.agents/workflows/onboard.md +17 -17
- package/.agents/workflows/plan.md +89 -0
- package/.agents/workflows/qa-explore.md +1 -1
- package/.agents/workflows/qa-run-harness.md +1 -1
- package/README.md +4 -12
- package/docs/CHANGELOG.md +1149 -0
- package/lib/cli/__tests__/update-changelog-surface.test.js +357 -0
- package/lib/cli/__tests__/update-reexec.test.js +513 -0
- package/lib/cli/init.js +31 -29
- package/lib/cli/update.js +413 -52
- package/package.json +2 -1
- package/.agents/scripts/lib/orchestration/reconciler.js +0 -137
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/lifecycle/story.dispatch.end.schema.json",
|
|
4
4
|
"title": "story.dispatch.end",
|
|
5
|
-
"description": "Appended to the Epic ledger by emit-story-dispatch-end.js when a child story sub-agent returns, so /
|
|
5
|
+
"description": "Appended to the Epic ledger by emit-story-dispatch-end.js when a child story sub-agent returns, so /deliver's idle watchdog can subtract completed Stories from the in-flight set. Subscribed by CheckpointPointerWriter via SUBSCRIBED_END_EVENTS. Sibling ordering within a wave is not guaranteed; ordering between waves is.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["storyId", "outcome", "durationMs"],
|
|
8
8
|
"properties": {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/lifecycle/story.dispatch.start.schema.json",
|
|
4
4
|
"title": "story.dispatch.start",
|
|
5
|
-
"description": "Emitted before a story is handed to the host-LLM for Agent-tool fanout. lifecycle-emit-story-dispatch.js appends the {storyId, waveIndex, dispatchedAt, attempt} shape to the Epic ledger so /
|
|
5
|
+
"description": "Emitted before a story is handed to the host-LLM for Agent-tool fanout. lifecycle-emit-story-dispatch.js appends the {storyId, waveIndex, dispatchedAt, attempt} shape to the Epic ledger so /deliver's host loop can durably ledger every dispatch attempt for in-flight reconciliation (Story #2891).",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["storyId", "waveIndex"],
|
|
8
8
|
"properties": {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/dsj1984/mandrel/blob/main/.agents/schemas/lifecycle/story.heartbeat.schema.json",
|
|
4
4
|
"title": "story.heartbeat",
|
|
5
|
-
"description": "Emitted by story-phase.js inside a Story's implementation loop. Surfaces the in-progress Story as an inspectable ledger event so /
|
|
5
|
+
"description": "Emitted by story-phase.js inside a Story's implementation loop. Surfaces the in-progress Story as an inspectable ledger event so /deliver's host-loop reconciler can confirm a long Story is still making forward progress between dispatch and merge — distinct from story.dispatch.start (one per Story per attempt) and story.merged (one per Story per close). The 2-tier hierarchy has no child Task tickets, so the heartbeat carries phase info only. The optional operator field (Story #3480) records the handle holding the assignee-as-lease claim on the Story so the ticket-lease primitive can decide claim liveness from the most-recent heartbeat for a given owner.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["event", "storyId", "epicId", "phase", "timestamp"],
|
|
8
8
|
"properties": {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "validation-evidence",
|
|
4
4
|
"title": "Validation Evidence",
|
|
5
|
-
"description": "Per-scope record of which validation gates have passed against which commit SHA. Written by lib/validation-evidence.js under the per-Epic temp tree at temp/epic-<epicId>/validation-evidence.json (Epic-scoped) or temp/epic-<epicId>/stories/story-<storyId>/validation-evidence.json (Story-scoped); both are gitignored via temp/. Consumed by close-validation, epic-code-review, and /
|
|
5
|
+
"description": "Per-scope record of which validation gates have passed against which commit SHA. Written by lib/validation-evidence.js under the per-Epic temp tree at temp/epic-<epicId>/validation-evidence.json (Epic-scoped) or temp/epic-<epicId>/stories/story-<storyId>/validation-evidence.json (Story-scoped); both are gitignored via temp/. Consumed by close-validation, epic-code-review, and /deliver Phase 3 (close-validation) to skip identical re-runs against an already-validated tree. The `storyId` field carries the scope id and equals the epic id for Epic-scoped records.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": ["storyId", "schemaVersion", "records"],
|
|
8
8
|
"properties": {
|
|
@@ -49,7 +49,7 @@ that the file was meaningfully updated during this Epic's lifecycle
|
|
|
49
49
|
|
|
50
50
|
**When to run.** Optional. Useful as a pre-merge spot check when an
|
|
51
51
|
Epic should have produced documentation updates; the standard
|
|
52
|
-
`/
|
|
52
|
+
`/deliver` flow does **not** invoke this gate today.
|
|
53
53
|
|
|
54
54
|
**Usage.**
|
|
55
55
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* and the resolved, undisableable round cap
|
|
17
17
|
* (`delivery.acceptanceEval.maxRounds`, clamped to `[1, ceiling]`).
|
|
18
18
|
* 3. Emit one per-criterion `acceptance-eval` signal into the retro /
|
|
19
|
-
* feedback substrate so the retro and `/
|
|
19
|
+
* feedback substrate so the retro and `/plan` Phase 0 feedback
|
|
20
20
|
* fetch can see which acceptance items needed rework and the round
|
|
21
21
|
* count.
|
|
22
22
|
* 4. Print a single JSON envelope and exit:
|
|
@@ -301,7 +301,7 @@ export function renderBlockerMessage({
|
|
|
301
301
|
lines.push(` Pending (@pending-only coverage): ${pending.join(', ')}`);
|
|
302
302
|
}
|
|
303
303
|
lines.push(
|
|
304
|
-
`Author or de-pend scenarios under tests/features/** tagged @epic-${epicId}-ac-<n> so every AC ID is satisfied, then re-run /
|
|
304
|
+
`Author or de-pend scenarios under tests/features/** tagged @epic-${epicId}-ac-<n> so every AC ID is satisfied, then re-run /deliver.`,
|
|
305
305
|
);
|
|
306
306
|
return lines.join('\n');
|
|
307
307
|
}
|
|
@@ -420,7 +420,7 @@ export async function reconcileAcceptanceSpec({
|
|
|
420
420
|
}
|
|
421
421
|
// Defence in depth — the start gate would normally catch this.
|
|
422
422
|
throw new Error(
|
|
423
|
-
`[acceptance-spec-reconciler] Epic #${epicId} has no linked context::acceptance-spec ticket and no acceptance::n-a waiver label. Re-run /
|
|
423
|
+
`[acceptance-spec-reconciler] Epic #${epicId} has no linked context::acceptance-spec ticket and no acceptance::n-a waiver label. Re-run /plan Phase 7 or apply the waiver.`,
|
|
424
424
|
);
|
|
425
425
|
}
|
|
426
426
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* fetching each `story-perf-summary` structured comment from the
|
|
19
19
|
* ticketing provider. Posts the
|
|
20
20
|
* `<!-- structured:epic-perf-report -->` comment on the Epic ticket.
|
|
21
|
-
* Run from the retro composer / `/
|
|
21
|
+
* Run from the retro composer / `/deliver` Phase 6.0.
|
|
22
22
|
*
|
|
23
23
|
* Both modes are idempotent: `upsertStructuredComment` deletes the prior
|
|
24
24
|
* marker before posting the new one.
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* NDJSON for a Story, no children for an Epic) so the close pipelines
|
|
28
28
|
* never block on observability output. Hard failures (bad CLI args,
|
|
29
29
|
* provider error, schema-violating payload) exit non-zero — the call
|
|
30
|
-
* sites in post-merge-pipeline / `/
|
|
30
|
+
* sites in post-merge-pipeline / `/deliver` Phase 5 treat that
|
|
31
31
|
* as a non-fatal warning.
|
|
32
32
|
*
|
|
33
33
|
* This file is a thin CLI: it wires the I/O readers from
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* stdout when --json is set).
|
|
14
14
|
*
|
|
15
15
|
* --emit-epic-seed --plan <plan.json> --out <path>
|
|
16
|
-
* Read the plan envelope from disk, render the `/
|
|
16
|
+
* Read the plan envelope from disk, render the `/plan --idea`
|
|
17
17
|
* seed markdown, persist to --out.
|
|
18
18
|
*
|
|
19
19
|
* --emit-stories --plan <plan.json>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// Story #2662 — Internal-link and slash-command resolver for active docs.
|
|
6
6
|
//
|
|
7
7
|
// Scans every `*.md` under `docs/` and `.agents/` (excluding
|
|
8
|
-
// `docs/CHANGELOG.md`
|
|
8
|
+
// `docs/CHANGELOG.md`) and validates:
|
|
9
9
|
//
|
|
10
10
|
// 1. Every Markdown relative-path link `[text](relative/path[#anchor])`
|
|
11
11
|
// resolves to a real file on disk (anchors are not validated, only
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
//
|
|
20
20
|
// 3. No active doc mentions any retired slash command. The retired-command
|
|
21
21
|
// blocklist is seeded with `agents-bootstrap-github`,
|
|
22
|
-
// `single-story-plan` (renamed to `/
|
|
22
|
+
// `single-story-plan` (renamed to `/plan`), and `mandrel`
|
|
23
23
|
// (retired in favor of the generated `.agents/docs/workflows.md`
|
|
24
24
|
// catalog) and takes precedence over the workflow-resolution check —
|
|
25
25
|
// a retired token is always a non-zero exit even if a stale workflow
|
|
@@ -125,7 +125,6 @@ export const SLASH_ALLOWLIST = new Set([
|
|
|
125
125
|
|
|
126
126
|
function isExcludedRelPath(relPath) {
|
|
127
127
|
if (relPath === 'docs/CHANGELOG.md') return true;
|
|
128
|
-
if (relPath.startsWith('docs/archive/')) return true;
|
|
129
128
|
return false;
|
|
130
129
|
}
|
|
131
130
|
|
|
@@ -134,7 +134,7 @@ function buildFrictionSignal({
|
|
|
134
134
|
timestamp: new Date().toISOString(),
|
|
135
135
|
epicId: epicId ?? null,
|
|
136
136
|
storyId: storyId ?? null,
|
|
137
|
-
//
|
|
137
|
+
// 2-tier hierarchy (Epic #3163): no Task tier, so friction signals
|
|
138
138
|
// carry no Task id. The field is retained for schema compatibility
|
|
139
139
|
// and always null.
|
|
140
140
|
taskId: null,
|
|
@@ -72,12 +72,12 @@ import { loadSpec, loadState } from './lib/spec/index.js';
|
|
|
72
72
|
* loaded state mapping. The spec-aware renderer (`buildManifestFromSpec`)
|
|
73
73
|
* looks up each Story's status via `state.mapping[slug].lastObservedAgentState`;
|
|
74
74
|
* that field is only refreshed by the structural reconciler, so during
|
|
75
|
-
* `/
|
|
75
|
+
* `/deliver` execution it stays `null` and every Story renders as ⬜
|
|
76
76
|
* pending even after the Story merges. The wave-runner replaced the
|
|
77
77
|
* dispatcher-per-wave refresh loop and the local state.json never sees
|
|
78
78
|
* the progress signal.
|
|
79
79
|
*
|
|
80
|
-
* Under the
|
|
80
|
+
* Under the 2-tier hierarchy (Epic #3163) the runtime manifest's wave
|
|
81
81
|
* records carry `stories[]` (each with the live `storyId` + `status` from
|
|
82
82
|
* `fetchEpicContext`'s GH query), not the retired `tasks[]` shape. The
|
|
83
83
|
* overlay walks `manifest.waves[].stories[]` and copies each Story's
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* any still-stuck entries by enumerating the processes holding handles
|
|
9
9
|
* inside the worktree path and terminating them.
|
|
10
10
|
*
|
|
11
|
-
* Invoked by `/
|
|
11
|
+
* Invoked by `/deliver`, `/epic-plan-spec` / `/epic-plan-decompose`
|
|
12
12
|
* (via `drainPendingCleanupAtBoot` → `worktree-sweep.js`), and
|
|
13
13
|
* `story-close` so the pending-cleanup ledger drains automatically
|
|
14
14
|
* across the sprint lifecycle. Operators can also run it standalone:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* node:coverage ignore file */
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* epic-audit-prepare.js — Phase 4 prepare CLI for `/
|
|
5
|
+
* epic-audit-prepare.js — Phase 4 prepare CLI for `/deliver`.
|
|
6
6
|
*
|
|
7
7
|
* Thin glue around the audit-suite `selectAudits` SDK. Reads the Epic
|
|
8
8
|
* ticket, runs the change-set selector against the Epic branch diff
|
|
@@ -193,7 +193,7 @@ function resolveTaskSizing(config) {
|
|
|
193
193
|
* Best-effort and total, mirroring `resolveRiskRoutedLenses`: a
|
|
194
194
|
* missing/unparseable checkpoint, an absent `planningRisk` field, or a
|
|
195
195
|
* provider read failure all degrade to `standard` — the neutral default that
|
|
196
|
-
* preserves today's behavior — so an Epic that skipped `/
|
|
196
|
+
* preserves today's behavior — so an Epic that skipped `/plan` (no
|
|
197
197
|
* checkpoint) still gets a passing `standard` pass with no new failure mode.
|
|
198
198
|
* The changed-file count can only escalate a low-risk Epic to `deep` (a wide
|
|
199
199
|
* diff) and never downgrades a high-risk one; an unknown/absent count is the
|
|
@@ -295,7 +295,7 @@ export async function runEpicAuditPrepare(values, deps = {}) {
|
|
|
295
295
|
const runner = deps.selectAudits ?? selectAudits;
|
|
296
296
|
|
|
297
297
|
// Pin the change set to the requested Epic's own branch rather than the
|
|
298
|
-
// shared checkout's HEAD (Story #3362). Under two concurrent /
|
|
298
|
+
// shared checkout's HEAD (Story #3362). Under two concurrent /deliver
|
|
299
299
|
// runs sharing one working copy, a HEAD-relative diff silently reports the
|
|
300
300
|
// *other* Epic's change set; `refs/heads/epic/<id>` is unambiguous.
|
|
301
301
|
const epicBranch = `epic/${epicId}`;
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* epic-deliver-note-intervention.js — record a manual-intervention event
|
|
6
|
-
* against the active `/
|
|
6
|
+
* against the active `/deliver` run-state checkpoint.
|
|
7
7
|
*
|
|
8
|
-
* The host LLM driving `/
|
|
8
|
+
* The host LLM driving `/deliver` invokes this CLI whenever it does
|
|
9
9
|
* something out-of-band that disqualifies the Epic from auto-merge:
|
|
10
10
|
*
|
|
11
11
|
* - `AskUserQuestion` to the operator mid-run
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* epic-deliver-preflight.js — Story #2899 (Epic #2880, F13).
|
|
6
6
|
*
|
|
7
|
-
* Estimates the cost of an upcoming `/
|
|
7
|
+
* Estimates the cost of an upcoming `/deliver` run *before* Story
|
|
8
8
|
* fan-out and surfaces the result to the operator on two channels:
|
|
9
9
|
*
|
|
10
10
|
* 1. A JSON envelope on stdout (always) with the keys
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
* The CLI is intentionally side-effect-light when `--dry-run` is set: no
|
|
21
21
|
* comment write, no lifecycle emit. The slash-command workflow
|
|
22
|
-
* (`/
|
|
22
|
+
* (`/deliver` Phase 1) calls the CLI without `--dry-run` so the
|
|
23
23
|
* comment is upserted; if any threshold is breached, the workflow flips
|
|
24
24
|
* the Epic to `agent::blocked` and surfaces the envelope in chat for
|
|
25
25
|
* operator review. The CLI itself does NOT flip labels — the workflow
|
|
@@ -70,7 +70,7 @@ const HELP = `Usage: node .agents/scripts/epic-deliver-preflight.js \\
|
|
|
70
70
|
[--per-story-claude-tokens <n>]
|
|
71
71
|
|
|
72
72
|
Estimates Story count, install cost, wave count, GitHub API request volume,
|
|
73
|
-
and Claude Max quota burn for an Epic *before* /
|
|
73
|
+
and Claude Max quota burn for an Epic *before* /deliver fan-out.
|
|
74
74
|
|
|
75
75
|
Flags:
|
|
76
76
|
--dry-run Compute the estimate and print the JSON
|
|
@@ -103,7 +103,7 @@ const DEFAULTS = Object.freeze({
|
|
|
103
103
|
perStoryApiRequests: 25,
|
|
104
104
|
perStoryClaudeTokens: 200_000,
|
|
105
105
|
// Base GH API budget: snapshot getTicket + getSubTickets + plan/manifest
|
|
106
|
-
// reads/writes that happen once per /
|
|
106
|
+
// reads/writes that happen once per /deliver run regardless of
|
|
107
107
|
// Story count. Empirical observation from a 5-Story Epic shows ~30
|
|
108
108
|
// requests for the non-per-Story floor.
|
|
109
109
|
baseApiRequests: 30,
|
|
@@ -240,7 +240,7 @@ export function renderPreflightBody({
|
|
|
240
240
|
);
|
|
241
241
|
} else {
|
|
242
242
|
lines.push(
|
|
243
|
-
'⛔ **Threshold breaches** — `/
|
|
243
|
+
'⛔ **Threshold breaches** — `/deliver` will flip the Epic to `agent::blocked` for operator review:',
|
|
244
244
|
);
|
|
245
245
|
for (const b of breaches) {
|
|
246
246
|
lines.push(`- \`${b.key}\` = ${b.observed} (max ${b.max})`);
|
|
@@ -284,7 +284,7 @@ export async function runPreflight({
|
|
|
284
284
|
const provider = injectedProvider ?? createProvider(config);
|
|
285
285
|
const thresholds = getPreflight(config);
|
|
286
286
|
|
|
287
|
-
// Compose the same two phases /
|
|
287
|
+
// Compose the same two phases /deliver Phase 1 runs so the
|
|
288
288
|
// preflight numbers match the actual dispatch plan.
|
|
289
289
|
const ctx = { epicId, provider };
|
|
290
290
|
let state = {};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* node:coverage ignore file */
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* epic-deliver-prepare.js — Step 0/1 of the operator-driven `/
|
|
5
|
+
* epic-deliver-prepare.js — Step 0/1 of the operator-driven `/deliver`.
|
|
6
6
|
*
|
|
7
7
|
* Composes the existing engine phases that the in-process epic-runner used to
|
|
8
8
|
* call sequentially, but does NOT dispatch any waves. The CLI is the single
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* advance the `epic-run-state` checkpoint, and re-render the unified
|
|
7
7
|
* `epic-run-progress` rollup on the Epic.
|
|
8
8
|
*
|
|
9
|
-
* The slash-command (`/
|
|
9
|
+
* The slash-command (`/deliver`) calls this CLI once per wave, after
|
|
10
10
|
* its host-level Agent-tool fan-out drains. It is the only writer of the
|
|
11
11
|
* `epic-run-progress` structured comment for the wave-completion path —
|
|
12
12
|
* there is no separate `/wave-execute` skill, no `wave-run-progress`
|
|
@@ -95,7 +95,7 @@ const HELP = `Usage: node .agents/scripts/epic-execute-record-wave.js \\
|
|
|
95
95
|
|
|
96
96
|
Records the wave's per-Story outcomes, advances the epic-run-state
|
|
97
97
|
checkpoint, and upserts the unified epic-run-progress rollup on the Epic.
|
|
98
|
-
Prints the next action for the /
|
|
98
|
+
Prints the next action for the /deliver slash command.
|
|
99
99
|
`;
|
|
100
100
|
|
|
101
101
|
/**
|
|
@@ -237,7 +237,7 @@ export async function runEpicExecuteRecordWave({
|
|
|
237
237
|
// Closes the start/end pairing the wave-tick reconciler and the
|
|
238
238
|
// `--check-idle` watchdog use to derive in-flight Stories. Before this
|
|
239
239
|
// the only producer was `wave-session.js`, which the host-LLM driven
|
|
240
|
-
// /
|
|
240
|
+
// /deliver path never imports — so every dispatched Story stayed
|
|
241
241
|
// "in-flight" forever and completed Stories tripped the watchdog.
|
|
242
242
|
// Best-effort: a failed append must not block the wave loop.
|
|
243
243
|
emitWaveDispatchEnds({ epicId, verified, config });
|
|
@@ -257,7 +257,7 @@ export async function runEpicExecuteRecordWave({
|
|
|
257
257
|
|
|
258
258
|
// 7. Fire the curated webhook events for this wave boundary. Mirrors the
|
|
259
259
|
// wave-loop emits in `lib/orchestration/epic-runner/phases/iterate-waves.js`
|
|
260
|
-
// for the host-LLM driven /
|
|
260
|
+
// for the host-LLM driven /deliver path (which does not pass
|
|
261
261
|
// through `runEpic`). Each helper is fire-and-forget — webhook
|
|
262
262
|
// misconfig or a transient Slack outage must not block the wave loop.
|
|
263
263
|
await emitWaveBoundaryNotifications({
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* epic-plan-healthcheck.js — Post-Plan Readiness Check
|
|
7
7
|
*
|
|
8
|
-
* Runs at the end of /
|
|
8
|
+
* Runs at the end of /plan (Phase 10) to validate the backlog and
|
|
9
9
|
* optionally prime the execution environment before handing off to
|
|
10
10
|
* /epic-deliver.
|
|
11
11
|
*
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* node epic-plan-healthcheck.js --epic <EPIC_ID> \
|
|
28
28
|
* [--paranoid] [--prime-install] [--dry-run]
|
|
29
29
|
*
|
|
30
|
-
* @see .agents/workflows/epic
|
|
30
|
+
* @see .agents/workflows/helpers/plan-epic.md Phase 10
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
33
|
import { spawnSync } from 'node:child_process';
|
|
@@ -131,7 +131,7 @@ function checkGitRemote(baseBranch, cwd) {
|
|
|
131
131
|
|
|
132
132
|
/**
|
|
133
133
|
* Detect whether a Story body carries an inline `## Acceptance` section with
|
|
134
|
-
* at least one checklist item. Epic #3078 — under
|
|
134
|
+
* at least one checklist item. Epic #3078 — under 2-tier hierarchy, Stories
|
|
135
135
|
* carry acceptance inline, so the hierarchy check uses this signal as the
|
|
136
136
|
* mark of a complete, executable Story.
|
|
137
137
|
*
|
|
@@ -152,7 +152,7 @@ function hasInlineAcceptance(body) {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
|
-
* Validate Epic ticket hierarchy.
|
|
155
|
+
* Validate Epic ticket hierarchy. 2-tier is the only supported hierarchy
|
|
156
156
|
* after Task #3154 deleted `planning.hierarchy`: every Story must carry an
|
|
157
157
|
* inline `## Acceptance` checklist; there is no Task layer to graph.
|
|
158
158
|
*
|
|
@@ -181,13 +181,9 @@ async function checkTickets(provider, epicId) {
|
|
|
181
181
|
return { ok: false, detail: `Epic #${epicId} has no child tickets.` };
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
const features = tickets.filter((t) =>
|
|
185
|
-
t.labels.includes(TYPE_LABELS.FEATURE),
|
|
186
|
-
);
|
|
187
184
|
const stories = tickets.filter((t) => t.labels.includes(TYPE_LABELS.STORY));
|
|
188
185
|
|
|
189
186
|
const errors = [];
|
|
190
|
-
if (features.length === 0) errors.push('no type::feature tickets');
|
|
191
187
|
if (stories.length === 0) errors.push('no type::story tickets');
|
|
192
188
|
|
|
193
189
|
const missingAcceptance = stories.filter(
|
|
@@ -214,7 +210,7 @@ async function checkTickets(provider, epicId) {
|
|
|
214
210
|
|
|
215
211
|
return {
|
|
216
212
|
ok: true,
|
|
217
|
-
detail: `${
|
|
213
|
+
detail: `${stories.length} stories (2-tier, inline acceptance) — hierarchy valid${advisory}.`,
|
|
218
214
|
};
|
|
219
215
|
}
|
|
220
216
|
|
|
@@ -313,7 +309,7 @@ export async function runPlanHealthcheck(opts = {}) {
|
|
|
313
309
|
await timed('git-remote', async () => checkGitRemote(baseBranch, cwd)),
|
|
314
310
|
);
|
|
315
311
|
|
|
316
|
-
// Paranoid lane: ticket-hierarchy revalidation (
|
|
312
|
+
// Paranoid lane: ticket-hierarchy revalidation (2-tier only).
|
|
317
313
|
if (paranoid) {
|
|
318
314
|
const provider = opts.injectedProvider || createProvider(config);
|
|
319
315
|
progress('CHECK', 'Validating ticket hierarchy...');
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* epic-plan-spec-validate.js — Phase 7.5 Tech Spec post-authoring gate CLI.
|
|
5
5
|
*
|
|
6
|
-
* `/
|
|
6
|
+
* `/plan` Phase 7 authors the Tech Spec; Phase 8.3 (Holistic
|
|
7
7
|
* Consolidation) reconciles the draft ticket array against the Tech Spec's
|
|
8
8
|
* `## Delivery Slicing` section, which the decompose-author skill uses as the
|
|
9
9
|
* capability-boundary anchor. When that section is absent the consolidation
|
|
@@ -195,11 +195,11 @@ export async function fetchGhState(provider, epicId) {
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
/**
|
|
198
|
-
* Walk the spec
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
198
|
+
* Walk the spec and yield one `{ slug, entity, title, parentSlug,
|
|
199
|
+
* dependsOn }` record per logical entity (epic → story), mirroring the
|
|
200
|
+
* diff engine's `flattenSpec`. Local to the CLI so the reseed pass
|
|
201
|
+
* (below) can map spec slugs onto live GH issues without importing the
|
|
202
|
+
* diff engine's private walker. Pure.
|
|
203
203
|
*
|
|
204
204
|
* @param {object} spec
|
|
205
205
|
* @returns {Array<{slug: string, entity: string, title: string, parentSlug: string|null, dependsOn: string[]}>}
|
|
@@ -216,32 +216,14 @@ export function flattenSpecForReseed(spec) {
|
|
|
216
216
|
dependsOn: [],
|
|
217
217
|
});
|
|
218
218
|
}
|
|
219
|
-
for (const
|
|
219
|
+
for (const story of spec.stories ?? []) {
|
|
220
220
|
out.push({
|
|
221
|
-
slug:
|
|
222
|
-
entity: '
|
|
223
|
-
title: String(
|
|
221
|
+
slug: story.slug,
|
|
222
|
+
entity: 'story',
|
|
223
|
+
title: String(story.title ?? ''),
|
|
224
224
|
parentSlug: 'epic',
|
|
225
|
-
dependsOn: [],
|
|
225
|
+
dependsOn: story.dependsOn ?? [],
|
|
226
226
|
});
|
|
227
|
-
for (const story of feature.stories ?? []) {
|
|
228
|
-
out.push({
|
|
229
|
-
slug: story.slug,
|
|
230
|
-
entity: 'story',
|
|
231
|
-
title: String(story.title ?? ''),
|
|
232
|
-
parentSlug: feature.slug,
|
|
233
|
-
dependsOn: story.dependsOn ?? [],
|
|
234
|
-
});
|
|
235
|
-
for (const task of story.tasks ?? []) {
|
|
236
|
-
out.push({
|
|
237
|
-
slug: task.slug,
|
|
238
|
-
entity: 'task',
|
|
239
|
-
title: String(task.title ?? ''),
|
|
240
|
-
parentSlug: story.slug,
|
|
241
|
-
dependsOn: [],
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
227
|
}
|
|
246
228
|
return out;
|
|
247
229
|
}
|
|
@@ -255,7 +237,7 @@ export function flattenSpecForReseed(spec) {
|
|
|
255
237
|
* file is absent (a fresh checkout, a reaped temp dir, the exact
|
|
256
238
|
* situation `--resume` exists to recover from), `loadState` returns an
|
|
257
239
|
* empty mapping, the diff engine sees every spec slug as unmapped, and
|
|
258
|
-
* `apply` recreates the entire
|
|
240
|
+
* `apply` recreates the entire Story set on top of the existing
|
|
259
241
|
* one — duplicating every child. This is precisely the failure `--resume`
|
|
260
242
|
* is meant to prevent.
|
|
261
243
|
*
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* evidence-gate.js — evidence-aware wrapper around a single shell gate.
|
|
5
5
|
*
|
|
6
|
-
* Tech Spec #819 §"Evidence record (Story 7)" — `/
|
|
6
|
+
* Tech Spec #819 §"Evidence record (Story 7)" — `/deliver` Phase 3
|
|
7
7
|
* (close-validation) runs `npm run lint` and `npm test` against the Epic
|
|
8
8
|
* branch before opening the PR.
|
|
9
9
|
* If the same gate has already passed against the current `git rev-parse
|
|
@@ -91,7 +91,7 @@ export function renderWorkflowsDoc(catalog) {
|
|
|
91
91
|
'Every command file lives at `.agents/workflows/<name>.md` and is projected',
|
|
92
92
|
'into a flat `.claude/commands/` tree by `npm run sync:commands` (the',
|
|
93
93
|
'UserPromptSubmit hook keeps it current) so it shows up as a bare `/<name>`',
|
|
94
|
-
'slash command (e.g. `/
|
|
94
|
+
'slash command (e.g. `/deliver`). The projection writes only',
|
|
95
95
|
'`.claude/commands/<name>.md` — there is no plugin manifest and no',
|
|
96
96
|
'marketplace listing. The commands load in every Claude Code environment.',
|
|
97
97
|
'',
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* .agents/scripts/hierarchy-gate.js — Hierarchy Completeness Gate
|
|
5
5
|
*
|
|
6
|
-
* Walks the Epic's full sub-issue graph (
|
|
6
|
+
* Walks the Epic's full sub-issue graph (Stories) and verifies
|
|
7
7
|
* every descendant is closed. Where the wave gate asks "did the sprint
|
|
8
8
|
* complete what it committed to?" (manifest view), this gate asks "is
|
|
9
9
|
* anything still open under this Epic?" (live GitHub graph view).
|
|
@@ -16,14 +16,13 @@
|
|
|
16
16
|
* top-level Stories outside the Epic's sub-issue graph.
|
|
17
17
|
*
|
|
18
18
|
* Per ticket type the rule is:
|
|
19
|
-
* - Features — must be closed.
|
|
20
19
|
* - Stories — must be closed.
|
|
21
20
|
* - Auxiliary (context::prd, context::tech-spec) — ignored.
|
|
22
21
|
* These are closed by the operator after the Epic PR merges, so
|
|
23
22
|
* requiring them closed here would block every Epic.
|
|
24
23
|
*
|
|
25
|
-
* **
|
|
26
|
-
*
|
|
24
|
+
* **2-tier hierarchy (Story #4041).** Mandrel ships only Epic / Story
|
|
25
|
+
* tickets. `getSubTickets(<storyId>)` returns `[]`; the walk
|
|
27
26
|
* terminates at the Story. Acceptance criteria live inline on the
|
|
28
27
|
* Story body.
|
|
29
28
|
*
|
|
@@ -53,7 +52,6 @@ const SUB_TICKET_FETCH_CONCURRENCY = 4;
|
|
|
53
52
|
function classify(ticket) {
|
|
54
53
|
const labels = ticket.labels ?? [];
|
|
55
54
|
if (labels.includes(TYPE_LABELS.STORY)) return 'story';
|
|
56
|
-
if (labels.includes(TYPE_LABELS.FEATURE)) return 'feature';
|
|
57
55
|
if (
|
|
58
56
|
labels.includes(CONTEXT_LABELS.PRD) ||
|
|
59
57
|
labels.includes(CONTEXT_LABELS.TECH_SPEC)
|
|
@@ -80,7 +78,7 @@ async function collectDescendants(provider, epicId) {
|
|
|
80
78
|
const out = [];
|
|
81
79
|
// Level-order BFS: each round fetches the whole frontier's children with a
|
|
82
80
|
// bounded-parallel map instead of one awaited round-trip per node. Stories
|
|
83
|
-
// are
|
|
81
|
+
// are leaves (no sub-issues by contract), so they are never expanded
|
|
84
82
|
// — that skip alone removes the largest class of wasted GraphQL calls.
|
|
85
83
|
let frontier = [epicId];
|
|
86
84
|
while (frontier.length > 0) {
|
|
@@ -126,7 +124,7 @@ export async function runHierarchyGate({ epicId, injectedProvider } = {}) {
|
|
|
126
124
|
process.exit(2);
|
|
127
125
|
}
|
|
128
126
|
|
|
129
|
-
const failures = {
|
|
127
|
+
const failures = { story: [], other: [] };
|
|
130
128
|
let auxiliaryDeferred = 0;
|
|
131
129
|
for (const ticket of descendants) {
|
|
132
130
|
const kind = classify(ticket);
|
|
@@ -144,15 +142,13 @@ export async function runHierarchyGate({ epicId, injectedProvider } = {}) {
|
|
|
144
142
|
}
|
|
145
143
|
}
|
|
146
144
|
|
|
147
|
-
const totalOpen =
|
|
148
|
-
failures.feature.length + failures.story.length + failures.other.length;
|
|
145
|
+
const totalOpen = failures.story.length + failures.other.length;
|
|
149
146
|
|
|
150
147
|
if (totalOpen > 0) {
|
|
151
148
|
Logger.error(
|
|
152
149
|
`[hierarchy-gate] ❌ Hierarchy-completeness gate FAILED for Epic #${epicId}: ${totalOpen} descendant(s) incomplete.`,
|
|
153
150
|
);
|
|
154
151
|
const sections = [
|
|
155
|
-
['feature', 'Features'],
|
|
156
152
|
['story', 'Stories'],
|
|
157
153
|
['other', 'Untyped descendants'],
|
|
158
154
|
];
|
|
@@ -163,7 +159,7 @@ export async function runHierarchyGate({ epicId, injectedProvider } = {}) {
|
|
|
163
159
|
Logger.error(` - #${item.id} (${item.reason}) — ${item.title}`);
|
|
164
160
|
}
|
|
165
161
|
}
|
|
166
|
-
Logger.error('\nClose the open descendants and re-run `/
|
|
162
|
+
Logger.error('\nClose the open descendants and re-run `/deliver`.');
|
|
167
163
|
process.exit(1);
|
|
168
164
|
}
|
|
169
165
|
|
|
@@ -154,7 +154,7 @@ export class ITicketingProvider {
|
|
|
154
154
|
/**
|
|
155
155
|
* Create a child ticket within an Epic's structural hierarchy.
|
|
156
156
|
*
|
|
157
|
-
* @param {number} parentId - GitHub Issue number of the immediate structural parent (e.g. Epic
|
|
157
|
+
* @param {number} parentId - GitHub Issue number of the immediate structural parent (e.g. Epic or Story).
|
|
158
158
|
* @param {{
|
|
159
159
|
* epicId: number,
|
|
160
160
|
* title: string,
|
|
@@ -60,7 +60,7 @@ export function matchesAnyFilePattern(patterns, files) {
|
|
|
60
60
|
* callers MUST pass the requested Epic's own branch ref (e.g.
|
|
61
61
|
* `refs/heads/epic/<id>`) so the change set is pinned to that Epic's branch
|
|
62
62
|
* rather than whatever HEAD the shared checkout happens to sit on. Under two
|
|
63
|
-
* concurrent `/
|
|
63
|
+
* concurrent `/deliver` runs sharing one checkout, diffing against
|
|
64
64
|
* `HEAD` silently resolves the *other* Epic's change set (Story #3362). When
|
|
65
65
|
* `headRef` cannot be resolved in the repo, the selector returns a
|
|
66
66
|
* `degraded: true` envelope (or hard-fails in gate-mode) instead of diffing
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* lib/audit-to-stories/seed-epic-from-findings.js
|
|
3
3
|
*
|
|
4
|
-
* Build the `--idea`-shaped seed markdown that `/
|
|
4
|
+
* Build the `--idea`-shaped seed markdown that `/plan` Phase 1
|
|
5
5
|
* consumes when the operator picks the Single-Epic grouping mode.
|
|
6
6
|
*
|
|
7
7
|
* The seed renders the canonical one-pager sections so the idea-refinement
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - Recommended Direction (rollup of recommendations by dimension)
|
|
11
11
|
* - Key Assumptions (carries the source-report links forward)
|
|
12
12
|
* - MVP Scope (the proposed Stories, one bullet per group)
|
|
13
|
-
* - Key Files (explicit file paths so /
|
|
13
|
+
* - Key Files (explicit file paths so /plan Phase 7 decompose
|
|
14
14
|
* has concrete anchors)
|
|
15
15
|
* - Not Doing (out-of-scope items by convention)
|
|
16
16
|
*
|