mandrel 1.57.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 +954 -0
- package/.agents/docs/SDLC.md +1420 -0
- package/.agents/docs/agentrc-reference.json +278 -0
- package/.agents/docs/configuration.md +1040 -0
- package/.agents/docs/workflows.md +59 -0
- package/.agents/instructions.md +384 -0
- package/.agents/personas/architect.md +107 -0
- package/.agents/personas/devops-engineer.md +36 -0
- package/.agents/personas/engineer-mobile.md +119 -0
- package/.agents/personas/engineer-web.md +110 -0
- package/.agents/personas/engineer.md +90 -0
- package/.agents/personas/product.md +88 -0
- package/.agents/personas/project-manager.md +110 -0
- package/.agents/personas/qa-engineer.md +91 -0
- package/.agents/personas/refactorer.md +110 -0
- package/.agents/personas/security-engineer.md +112 -0
- package/.agents/personas/sre.md +86 -0
- package/.agents/personas/technical-writer.md +100 -0
- package/.agents/personas/ux-designer.md +95 -0
- package/.agents/rules/api-conventions.md +75 -0
- package/.agents/rules/changelog-style.md +238 -0
- package/.agents/rules/gherkin-standards.md +146 -0
- package/.agents/rules/git-conventions.md +146 -0
- package/.agents/rules/orchestration-error-handling.md +35 -0
- package/.agents/rules/security-baseline.md +92 -0
- package/.agents/rules/shell-conventions.md +70 -0
- package/.agents/rules/test-seams.md +59 -0
- package/.agents/rules/testing-standards.md +177 -0
- package/.agents/runtime-deps.json +18 -0
- package/.agents/schemas/acceptance-eval-verdict.schema.json +93 -0
- package/.agents/schemas/agentrc.schema.json +1583 -0
- package/.agents/schemas/audit-results.schema.json +69 -0
- package/.agents/schemas/audit-rules.json +134 -0
- package/.agents/schemas/audit-rules.schema.json +69 -0
- package/.agents/schemas/baselines/baseline-envelope.schema.json +44 -0
- package/.agents/schemas/baselines/bundle-size.schema.json +47 -0
- package/.agents/schemas/baselines/coverage.schema.json +50 -0
- package/.agents/schemas/baselines/crap.schema.json +52 -0
- package/.agents/schemas/baselines/duplication.schema.json +62 -0
- package/.agents/schemas/baselines/lighthouse.schema.json +59 -0
- package/.agents/schemas/baselines/lint.schema.json +47 -0
- package/.agents/schemas/baselines/maintainability.schema.json +71 -0
- package/.agents/schemas/baselines/mutation.schema.json +52 -0
- package/.agents/schemas/crap-baseline.schema.json +57 -0
- package/.agents/schemas/crap-report.schema.json +102 -0
- package/.agents/schemas/dispatch-manifest.json +232 -0
- package/.agents/schemas/epic-perf-report.schema.json +89 -0
- package/.agents/schemas/epic-spec.schema.json +183 -0
- package/.agents/schemas/friction-event.schema.json +56 -0
- package/.agents/schemas/lifecycle/README.md +18 -0
- package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +13 -0
- package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +13 -0
- package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +13 -0
- package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +13 -0
- package/.agents/schemas/lifecycle/checkpoint.written.schema.json +13 -0
- package/.agents/schemas/lifecycle/close-validate.end.schema.json +18 -0
- package/.agents/schemas/lifecycle/close-validate.start.schema.json +13 -0
- package/.agents/schemas/lifecycle/code-review.end.schema.json +30 -0
- package/.agents/schemas/lifecycle/code-review.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +14 -0
- package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +13 -0
- package/.agents/schemas/lifecycle/epic.blocked.schema.json +13 -0
- package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.close.end.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.complete.schema.json +13 -0
- package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +13 -0
- package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +13 -0
- package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +14 -0
- package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +17 -0
- package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +15 -0
- package/.agents/schemas/lifecycle/epic.plan.end.schema.json +18 -0
- package/.agents/schemas/lifecycle/epic.plan.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +16 -0
- package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/epic.watch.end.schema.json +28 -0
- package/.agents/schemas/lifecycle/epic.watch.start.schema.json +16 -0
- package/.agents/schemas/lifecycle/intervention.recorded.schema.json +15 -0
- package/.agents/schemas/lifecycle/ledger-record.schema.json +59 -0
- package/.agents/schemas/lifecycle/notification.emitted.schema.json +18 -0
- package/.agents/schemas/lifecycle/pr.created.schema.json +14 -0
- package/.agents/schemas/lifecycle/retro.end.schema.json +16 -0
- package/.agents/schemas/lifecycle/retro.start.schema.json +12 -0
- package/.agents/schemas/lifecycle/story.blocked.schema.json +13 -0
- package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +17 -0
- package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +15 -0
- package/.agents/schemas/lifecycle/story.heartbeat.schema.json +20 -0
- package/.agents/schemas/lifecycle/story.merged.schema.json +13 -0
- package/.agents/schemas/mi-report.schema.json +58 -0
- package/.agents/schemas/model-attribution.schema.json +49 -0
- package/.agents/schemas/qa-finding.schema.json +133 -0
- package/.agents/schemas/qa-ledger.schema.json +89 -0
- package/.agents/schemas/risk-verdict.schema.json +53 -0
- package/.agents/schemas/signal-event.schema.json +58 -0
- package/.agents/schemas/skill.schema.json +31 -0
- package/.agents/schemas/skills-index.schema.json +81 -0
- package/.agents/schemas/story-perf-summary.schema.json +73 -0
- package/.agents/schemas/validation-evidence.schema.json +78 -0
- package/.agents/scripts/README.md +93 -0
- package/.agents/scripts/acceptance-eval.js +284 -0
- package/.agents/scripts/acceptance-spec-reconciler.js +556 -0
- package/.agents/scripts/agents-bootstrap-github.js +634 -0
- package/.agents/scripts/analyze-execution.js +369 -0
- package/.agents/scripts/assert-branch.js +83 -0
- package/.agents/scripts/audit-labels-bootstrap.js +253 -0
- package/.agents/scripts/audit-to-stories.js +257 -0
- package/.agents/scripts/bootstrap.js +1378 -0
- package/.agents/scripts/check-baselines.js +81 -0
- package/.agents/scripts/check-dead-exports.js +311 -0
- package/.agents/scripts/check-doc-links.js +401 -0
- package/.agents/scripts/check-gherkin-placeholders.js +663 -0
- package/.agents/scripts/check-lifecycle-doc-drift.js +402 -0
- package/.agents/scripts/check-lifecycle-lint.js +379 -0
- package/.agents/scripts/check-prepush-recovery.js +90 -0
- package/.agents/scripts/check-windows-git-perf.js +138 -0
- package/.agents/scripts/cleanup-repo-test-temp.js +67 -0
- package/.agents/scripts/coverage-capture.js +112 -0
- package/.agents/scripts/detect-merges.js +111 -0
- package/.agents/scripts/diagnose-friction.js +257 -0
- package/.agents/scripts/diagnose.js +240 -0
- package/.agents/scripts/dispatcher.js +295 -0
- package/.agents/scripts/drain-pending-cleanup.js +147 -0
- package/.agents/scripts/epic-audit-prepare.js +419 -0
- package/.agents/scripts/epic-audit-recheck.js +241 -0
- package/.agents/scripts/epic-deliver-note-intervention.js +192 -0
- package/.agents/scripts/epic-deliver-preflight.js +407 -0
- package/.agents/scripts/epic-deliver-prepare.js +383 -0
- package/.agents/scripts/epic-execute-record-wave.js +463 -0
- package/.agents/scripts/epic-plan-clarity.js +201 -0
- package/.agents/scripts/epic-plan-decompose.js +79 -0
- package/.agents/scripts/epic-plan-healthcheck.js +363 -0
- package/.agents/scripts/epic-plan-spec-validate.js +111 -0
- package/.agents/scripts/epic-plan-spec.js +198 -0
- package/.agents/scripts/epic-reconcile.js +637 -0
- package/.agents/scripts/evidence-gate.js +235 -0
- package/.agents/scripts/generate-config-docs.js +516 -0
- package/.agents/scripts/generate-lifecycle-docs.js +224 -0
- package/.agents/scripts/generate-skills-index.js +252 -0
- package/.agents/scripts/generate-workflows-doc.js +168 -0
- package/.agents/scripts/git-cleanup.js +124 -0
- package/.agents/scripts/git-pr-quality-gate.js +203 -0
- package/.agents/scripts/git-rebase-and-resolve.js +234 -0
- package/.agents/scripts/hierarchy-gate.js +176 -0
- package/.agents/scripts/hydrate-context.js +179 -0
- package/.agents/scripts/install-matrix-assert.js +282 -0
- package/.agents/scripts/lib/Graph.js +326 -0
- package/.agents/scripts/lib/ITicketingProvider.js +349 -0
- package/.agents/scripts/lib/Logger.js +194 -0
- package/.agents/scripts/lib/audit-suite/cli.js +64 -0
- package/.agents/scripts/lib/audit-suite/findings.js +164 -0
- package/.agents/scripts/lib/audit-suite/frontmatter-lint.js +32 -0
- package/.agents/scripts/lib/audit-suite/frontmatter.js +110 -0
- package/.agents/scripts/lib/audit-suite/index.js +22 -0
- package/.agents/scripts/lib/audit-suite/runner.js +233 -0
- package/.agents/scripts/lib/audit-suite/selector.js +235 -0
- package/.agents/scripts/lib/audit-suite/substitutions.js +124 -0
- package/.agents/scripts/lib/audit-suite/workflow-loader.js +49 -0
- package/.agents/scripts/lib/audit-to-stories/build-story-body.js +130 -0
- package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +114 -0
- package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +93 -0
- package/.agents/scripts/lib/audit-to-stories/group-findings.js +265 -0
- package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +246 -0
- package/.agents/scripts/lib/audit-to-stories/seed-epic-from-findings.js +160 -0
- package/.agents/scripts/lib/auto-refresh-baselines.js +308 -0
- package/.agents/scripts/lib/baseline-loader.js +0 -0
- package/.agents/scripts/lib/baseline-schema-registry.js +69 -0
- package/.agents/scripts/lib/baseline-snapshot.js +716 -0
- package/.agents/scripts/lib/baselines/component-matcher.js +21 -0
- package/.agents/scripts/lib/baselines/components.js +126 -0
- package/.agents/scripts/lib/baselines/diff-scope-cli.js +203 -0
- package/.agents/scripts/lib/baselines/duplication-scanner.js +220 -0
- package/.agents/scripts/lib/baselines/env-overrides.js +129 -0
- package/.agents/scripts/lib/baselines/envelope.js +368 -0
- package/.agents/scripts/lib/baselines/exit-codes.js +89 -0
- package/.agents/scripts/lib/baselines/git-base.js +0 -0
- package/.agents/scripts/lib/baselines/kernel.js +111 -0
- package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +220 -0
- package/.agents/scripts/lib/baselines/kinds/bundle-size.js +157 -0
- package/.agents/scripts/lib/baselines/kinds/coverage.js +194 -0
- package/.agents/scripts/lib/baselines/kinds/crap.js +555 -0
- package/.agents/scripts/lib/baselines/kinds/duplication.js +197 -0
- package/.agents/scripts/lib/baselines/kinds/lighthouse.js +185 -0
- package/.agents/scripts/lib/baselines/kinds/lint.js +172 -0
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +340 -0
- package/.agents/scripts/lib/baselines/kinds/mutation.js +153 -0
- package/.agents/scripts/lib/baselines/path-canon.js +279 -0
- package/.agents/scripts/lib/baselines/preview-gates.js +298 -0
- package/.agents/scripts/lib/baselines/reader.js +321 -0
- package/.agents/scripts/lib/baselines/refresh-service.js +733 -0
- package/.agents/scripts/lib/baselines/scope.js +291 -0
- package/.agents/scripts/lib/baselines/writer.js +312 -0
- package/.agents/scripts/lib/bdd-runner-detect.js +417 -0
- package/.agents/scripts/lib/bdd-scenario-scanner.js +310 -0
- package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +202 -0
- package/.agents/scripts/lib/bootstrap/branch-protection.js +222 -0
- package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +171 -0
- package/.agents/scripts/lib/bootstrap/commit-push.js +146 -0
- package/.agents/scripts/lib/bootstrap/gh-list.js +153 -0
- package/.agents/scripts/lib/bootstrap/gh-preflight.js +306 -0
- package/.agents/scripts/lib/bootstrap/hitl-confirm.js +89 -0
- package/.agents/scripts/lib/bootstrap/install-ledger.js +174 -0
- package/.agents/scripts/lib/bootstrap/manifest.js +272 -0
- package/.agents/scripts/lib/bootstrap/merge-methods.js +108 -0
- package/.agents/scripts/lib/bootstrap/preflight.js +195 -0
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +801 -0
- package/.agents/scripts/lib/bootstrap/prompt.js +480 -0
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +370 -0
- package/.agents/scripts/lib/bootstrap/summary.js +75 -0
- package/.agents/scripts/lib/bootstrap/workflow-audit.js +256 -0
- package/.agents/scripts/lib/branch-name-guard.js +98 -0
- package/.agents/scripts/lib/c8-cli-path.js +21 -0
- package/.agents/scripts/lib/changed-files.js +184 -0
- package/.agents/scripts/lib/checks/baseline-drift-main-checkout.js +104 -0
- package/.agents/scripts/lib/checks/core-bare-clean.js +48 -0
- package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +54 -0
- package/.agents/scripts/lib/checks/index.js +288 -0
- package/.agents/scripts/lib/checks/push-hook-parity.js +106 -0
- package/.agents/scripts/lib/checks/stale-origin-epic.js +49 -0
- package/.agents/scripts/lib/checks/state.js +558 -0
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +186 -0
- package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +182 -0
- package/.agents/scripts/lib/checks/windows-coverage-noise-floor.js +92 -0
- package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +81 -0
- package/.agents/scripts/lib/checks/worktree-residue-biome.js +55 -0
- package/.agents/scripts/lib/cli/parse-numeric.js +60 -0
- package/.agents/scripts/lib/cli/standard-args.js +351 -0
- package/.agents/scripts/lib/cli-args.js +286 -0
- package/.agents/scripts/lib/cli-utils.js +69 -0
- package/.agents/scripts/lib/close-validation/projections/head-sha.js +44 -0
- package/.agents/scripts/lib/close-validation/projections/inputs.js +86 -0
- package/.agents/scripts/lib/close-validation/projections/maintainability.js +286 -0
- package/.agents/scripts/lib/close-validation.js +897 -0
- package/.agents/scripts/lib/codebase-snapshot.js +513 -0
- package/.agents/scripts/lib/command-header.js +33 -0
- package/.agents/scripts/lib/config/acceptance-eval.js +95 -0
- package/.agents/scripts/lib/config/baselines.js +60 -0
- package/.agents/scripts/lib/config/ci.js +30 -0
- package/.agents/scripts/lib/config/commands.js +36 -0
- package/.agents/scripts/lib/config/defaults.js +119 -0
- package/.agents/scripts/lib/config/explain.js +348 -0
- package/.agents/scripts/lib/config/gates/bundle-size.schema.js +23 -0
- package/.agents/scripts/lib/config/gates/coverage.schema.js +18 -0
- package/.agents/scripts/lib/config/gates/crap.schema.js +33 -0
- package/.agents/scripts/lib/config/gates/duplication.schema.js +26 -0
- package/.agents/scripts/lib/config/gates/index.js +36 -0
- package/.agents/scripts/lib/config/gates/lighthouse.schema.js +23 -0
- package/.agents/scripts/lib/config/gates/lint.schema.js +9 -0
- package/.agents/scripts/lib/config/gates/maintainability.schema.js +20 -0
- package/.agents/scripts/lib/config/gates/mutation.schema.js +12 -0
- package/.agents/scripts/lib/config/gates/shared.js +117 -0
- package/.agents/scripts/lib/config/github.js +122 -0
- package/.agents/scripts/lib/config/lifecycle.js +40 -0
- package/.agents/scripts/lib/config/limits.js +211 -0
- package/.agents/scripts/lib/config/paths.js +73 -0
- package/.agents/scripts/lib/config/preflight.js +58 -0
- package/.agents/scripts/lib/config/quality.js +665 -0
- package/.agents/scripts/lib/config/retro.js +77 -0
- package/.agents/scripts/lib/config/runners.js +105 -0
- package/.agents/scripts/lib/config/runtime.js +167 -0
- package/.agents/scripts/lib/config/shared.js +46 -0
- package/.agents/scripts/lib/config/sync-agentrc.js +243 -0
- package/.agents/scripts/lib/config/temp-paths.js +373 -0
- package/.agents/scripts/lib/config/validate-orchestration.js +81 -0
- package/.agents/scripts/lib/config/worktree-isolation.js +80 -0
- package/.agents/scripts/lib/config-resolver.js +298 -0
- package/.agents/scripts/lib/config-schema-shared.js +32 -0
- package/.agents/scripts/lib/config-schema.js +20 -0
- package/.agents/scripts/lib/config-settings-schema-delivery.js +332 -0
- package/.agents/scripts/lib/config-settings-schema-quality.js +165 -0
- package/.agents/scripts/lib/config-settings-schema.js +420 -0
- package/.agents/scripts/lib/coverage-baseline.js +352 -0
- package/.agents/scripts/lib/coverage-capture.js +195 -0
- package/.agents/scripts/lib/coverage-utils.js +239 -0
- package/.agents/scripts/lib/cpu-pool.js +223 -0
- package/.agents/scripts/lib/crap-engine.js +119 -0
- package/.agents/scripts/lib/crap-utils.js +479 -0
- package/.agents/scripts/lib/degraded-mode.js +69 -0
- package/.agents/scripts/lib/dependency-parser.js +129 -0
- package/.agents/scripts/lib/duplicate-search.js +189 -0
- package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +70 -0
- package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +197 -0
- package/.agents/scripts/lib/dynamic-workflow/capability.js +396 -0
- package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +80 -0
- package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +72 -0
- package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +90 -0
- package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +43 -0
- package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +83 -0
- package/.agents/scripts/lib/env-loader.js +52 -0
- package/.agents/scripts/lib/epic-merge-lock.js +239 -0
- package/.agents/scripts/lib/epic-plan-clarity.js +142 -0
- package/.agents/scripts/lib/epic-plan-ideation.js +228 -0
- package/.agents/scripts/lib/error-redactor.js +125 -0
- package/.agents/scripts/lib/errors/index.js +67 -0
- package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +230 -0
- package/.agents/scripts/lib/feedback-loop/code-review-graduator.js +207 -0
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +421 -0
- package/.agents/scripts/lib/feedback-loop/memory-freshness.js +480 -0
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +229 -0
- package/.agents/scripts/lib/findings/classify-finding.js +195 -0
- package/.agents/scripts/lib/findings/promote-finding.js +353 -0
- package/.agents/scripts/lib/findings/route-finding.js +283 -0
- package/.agents/scripts/lib/findings/semantic-issue-search.js +179 -0
- package/.agents/scripts/lib/findings/severity.js +102 -0
- package/.agents/scripts/lib/gates/baseline-store.js +106 -0
- package/.agents/scripts/lib/gates/friction.js +43 -0
- package/.agents/scripts/lib/gh-exec.js +553 -0
- package/.agents/scripts/lib/git/cached-fetch.js +0 -0
- package/.agents/scripts/lib/git/sync-from-base.js +162 -0
- package/.agents/scripts/lib/git-branch-cleanup.js +213 -0
- package/.agents/scripts/lib/git-branch-lifecycle.js +353 -0
- package/.agents/scripts/lib/git-merge-orchestrator.js +261 -0
- package/.agents/scripts/lib/git-utils.js +363 -0
- package/.agents/scripts/lib/github-url.js +29 -0
- package/.agents/scripts/lib/install-cmd-parser.js +51 -0
- package/.agents/scripts/lib/issue-link-parser.js +74 -0
- package/.agents/scripts/lib/json-utils.js +60 -0
- package/.agents/scripts/lib/label-constants.js +169 -0
- package/.agents/scripts/lib/label-taxonomy.js +200 -0
- package/.agents/scripts/lib/maintainability-engine.js +164 -0
- package/.agents/scripts/lib/maintainability-utils.js +343 -0
- package/.agents/scripts/lib/mandrel-catalog.js +170 -0
- package/.agents/scripts/lib/mutation/baseline-snapshot.js +238 -0
- package/.agents/scripts/lib/mutation/config-detector.js +119 -0
- package/.agents/scripts/lib/mutation/stryker-runner.js +306 -0
- package/.agents/scripts/lib/mutation/survivor-report.js +160 -0
- package/.agents/scripts/lib/notifications/notifier.js +75 -0
- package/.agents/scripts/lib/observability/active-story-env.js +182 -0
- package/.agents/scripts/lib/observability/baseline-refresh-rate.js +221 -0
- package/.agents/scripts/lib/observability/perf-aggregator.js +887 -0
- package/.agents/scripts/lib/observability/perf-report-readers.js +319 -0
- package/.agents/scripts/lib/observability/perf-report-render.js +182 -0
- package/.agents/scripts/lib/observability/signals-writer.js +296 -0
- package/.agents/scripts/lib/observability/source-classifier.js +103 -0
- package/.agents/scripts/lib/observability/tool-trace-hook.js +417 -0
- package/.agents/scripts/lib/onboard/detect-stack.js +300 -0
- package/.agents/scripts/lib/onboard/scaffold-docs.js +128 -0
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +173 -0
- package/.agents/scripts/lib/orchestration/cascade-grouping.js +275 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +131 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +80 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +132 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +142 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +149 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +158 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +56 -0
- package/.agents/scripts/lib/orchestration/code-review.js +652 -0
- package/.agents/scripts/lib/orchestration/column-sync.js +286 -0
- package/.agents/scripts/lib/orchestration/context-envelope.js +280 -0
- package/.agents/scripts/lib/orchestration/context-hydration-engine.js +581 -0
- package/.agents/scripts/lib/orchestration/dependency-analyzer.js +88 -0
- package/.agents/scripts/lib/orchestration/detectors-phase.js +188 -0
- package/.agents/scripts/lib/orchestration/dispatch-engine.js +144 -0
- package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +206 -0
- package/.agents/scripts/lib/orchestration/doc-reader.js +94 -0
- package/.agents/scripts/lib/orchestration/epic-cleanup.js +473 -0
- package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +310 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/cli.js +167 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +151 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +74 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +78 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +72 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +155 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +321 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +75 -0
- package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +86 -0
- package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +235 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +197 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/cli-args.js +48 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +94 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +414 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +55 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/risk-verdict.js +105 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +235 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +120 -0
- package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +118 -0
- package/.agents/scripts/lib/orchestration/epic-run-state-store.js +295 -0
- package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +186 -0
- package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +50 -0
- package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +146 -0
- package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +110 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +392 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +217 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +235 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter.js +69 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +32 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +291 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +175 -0
- package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +37 -0
- package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +127 -0
- package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +400 -0
- package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +285 -0
- package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +66 -0
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +797 -0
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +619 -0
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +335 -0
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +230 -0
- package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +363 -0
- package/.agents/scripts/lib/orchestration/error-journal.js +139 -0
- package/.agents/scripts/lib/orchestration/file-assumption-enum.js +31 -0
- package/.agents/scripts/lib/orchestration/file-assumptions.js +506 -0
- package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +116 -0
- package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +241 -0
- package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +489 -0
- package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +88 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +219 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +309 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +99 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +123 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +57 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +114 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +426 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +84 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +365 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +72 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +69 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +214 -0
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +137 -0
- package/.agents/scripts/lib/orchestration/label-transitions.js +43 -0
- package/.agents/scripts/lib/orchestration/lifecycle/bus.js +309 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +147 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +155 -0
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +226 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +69 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +378 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +248 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +527 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +259 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +278 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +355 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +647 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +331 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +140 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +421 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +168 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +668 -0
- package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +322 -0
- package/.agents/scripts/lib/orchestration/lint-baseline-service.js +114 -0
- package/.agents/scripts/lib/orchestration/manifest-builder.js +216 -0
- package/.agents/scripts/lib/orchestration/model-attribution.js +390 -0
- package/.agents/scripts/lib/orchestration/parked-follow-ons.js +147 -0
- package/.agents/scripts/lib/orchestration/phase-runner.js +87 -0
- package/.agents/scripts/lib/orchestration/plan-review-routing.js +63 -0
- package/.agents/scripts/lib/orchestration/plan-runner/plan-router.js +86 -0
- package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +212 -0
- package/.agents/scripts/lib/orchestration/planning-context-budget.js +213 -0
- package/.agents/scripts/lib/orchestration/planning-risk.js +155 -0
- package/.agents/scripts/lib/orchestration/planning-state-manager.js +318 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +56 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +33 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +78 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +68 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +118 -0
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +396 -0
- package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +205 -0
- package/.agents/scripts/lib/orchestration/pr-base-guard.js +47 -0
- package/.agents/scripts/lib/orchestration/preflight-cache.js +164 -0
- package/.agents/scripts/lib/orchestration/reassert-status-column.js +202 -0
- package/.agents/scripts/lib/orchestration/reconciler.js +137 -0
- package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +152 -0
- package/.agents/scripts/lib/orchestration/recut.js +56 -0
- package/.agents/scripts/lib/orchestration/resolves-token.js +127 -0
- package/.agents/scripts/lib/orchestration/retro/phases/checks.js +94 -0
- package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +448 -0
- package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +335 -0
- package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +133 -0
- package/.agents/scripts/lib/orchestration/retro-heuristics.js +57 -0
- package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +275 -0
- package/.agents/scripts/lib/orchestration/retro-proposals.js +395 -0
- package/.agents/scripts/lib/orchestration/retro-runner.js +171 -0
- package/.agents/scripts/lib/orchestration/review-depth.js +93 -0
- package/.agents/scripts/lib/orchestration/review-providers/codex.js +363 -0
- package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +205 -0
- package/.agents/scripts/lib/orchestration/review-providers/native.js +805 -0
- package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +73 -0
- package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +396 -0
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +373 -0
- package/.agents/scripts/lib/orchestration/review-providers/types.js +89 -0
- package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +107 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +159 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +194 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +81 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +190 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +70 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +106 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +42 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +73 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +225 -0
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +315 -0
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +149 -0
- package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +110 -0
- package/.agents/scripts/lib/orchestration/spec-freshness.js +320 -0
- package/.agents/scripts/lib/orchestration/spec-renderer.js +456 -0
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +80 -0
- package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +797 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +163 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +152 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +387 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +266 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +48 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +67 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +161 -0
- package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +117 -0
- package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +86 -0
- package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +147 -0
- package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +142 -0
- package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +62 -0
- package/.agents/scripts/lib/orchestration/story-close/format-autofix-scoped.js +221 -0
- package/.agents/scripts/lib/orchestration/story-close/format-autofix-shared.js +123 -0
- package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +216 -0
- package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +636 -0
- package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +198 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +105 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/close.js +222 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +220 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +291 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +234 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +110 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +86 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +112 -0
- package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +157 -0
- package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +434 -0
- package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +290 -0
- package/.agents/scripts/lib/orchestration/story-close-recovery.js +643 -0
- package/.agents/scripts/lib/orchestration/structured-comment-parser.js +67 -0
- package/.agents/scripts/lib/orchestration/task-body-validator.js +391 -0
- package/.agents/scripts/lib/orchestration/ticket-lease.js +358 -0
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +783 -0
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +367 -0
- package/.agents/scripts/lib/orchestration/ticket-validator.js +691 -0
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +723 -0
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +474 -0
- package/.agents/scripts/lib/orchestration/ticketing/state.js +559 -0
- package/.agents/scripts/lib/orchestration/ticketing.js +55 -0
- package/.agents/scripts/lib/orchestration/wave-marker.js +28 -0
- package/.agents/scripts/lib/orchestration/wave-record-io.js +277 -0
- package/.agents/scripts/lib/orchestration/wave-record-notifications.js +189 -0
- package/.agents/scripts/lib/orchestration/wave-record-projection.js +423 -0
- package/.agents/scripts/lib/path-security.js +25 -0
- package/.agents/scripts/lib/plan-phase-cleanup.js +125 -0
- package/.agents/scripts/lib/preflight-runner.js +196 -0
- package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +95 -0
- package/.agents/scripts/lib/presentation/manifest-builder.js +245 -0
- package/.agents/scripts/lib/presentation/manifest-formatter.js +243 -0
- package/.agents/scripts/lib/presentation/manifest-helpers.js +213 -0
- package/.agents/scripts/lib/presentation/manifest-persistence.js +262 -0
- package/.agents/scripts/lib/presentation/manifest-procedures.js +55 -0
- package/.agents/scripts/lib/presentation/manifest-render-waves.js +252 -0
- package/.agents/scripts/lib/presentation/manifest-renderer.js +188 -0
- package/.agents/scripts/lib/presentation/manifest-story-views.js +119 -0
- package/.agents/scripts/lib/provider-factory.js +80 -0
- package/.agents/scripts/lib/push-epic-retry.js +209 -0
- package/.agents/scripts/lib/qa/console-allowlist.js +151 -0
- package/.agents/scripts/lib/qa/coverage-report.js +181 -0
- package/.agents/scripts/lib/qa/coverage-verdict.js +296 -0
- package/.agents/scripts/lib/qa/propose-missing-test.js +95 -0
- package/.agents/scripts/lib/qa/qa-context-hydrator.js +296 -0
- package/.agents/scripts/lib/qa/qa-session.js +197 -0
- package/.agents/scripts/lib/qa/redact-evidence.js +245 -0
- package/.agents/scripts/lib/qa/resolve-qa-contract.js +190 -0
- package/.agents/scripts/lib/qa/resolve-selection.js +373 -0
- package/.agents/scripts/lib/runtime-deps/ensure-installed.js +100 -0
- package/.agents/scripts/lib/runtime-deps/manifest.js +96 -0
- package/.agents/scripts/lib/runtime-deps/preflight.js +78 -0
- package/.agents/scripts/lib/runtime-deps/scan-imports.js +202 -0
- package/.agents/scripts/lib/signals/detectors/common.js +36 -0
- package/.agents/scripts/lib/signals/detectors/hotspot.js +298 -0
- package/.agents/scripts/lib/signals/detectors/index.js +14 -0
- package/.agents/scripts/lib/signals/detectors/retry.js +289 -0
- package/.agents/scripts/lib/signals/detectors/rework.js +204 -0
- package/.agents/scripts/lib/signals/index.js +39 -0
- package/.agents/scripts/lib/signals/read.js +268 -0
- package/.agents/scripts/lib/signals/schema.js +225 -0
- package/.agents/scripts/lib/signals/span-tree.js +290 -0
- package/.agents/scripts/lib/signals/write.js +19 -0
- package/.agents/scripts/lib/single-story/confirm-merge.js +201 -0
- package/.agents/scripts/lib/single-story/story-merged-notify.js +126 -0
- package/.agents/scripts/lib/single-story-sweep/protection.js +274 -0
- package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +169 -0
- package/.agents/scripts/lib/single-story-sweep.js +329 -0
- package/.agents/scripts/lib/skills/parse-skill.js +202 -0
- package/.agents/scripts/lib/skills/walk-skill-files.js +56 -0
- package/.agents/scripts/lib/spec/index.js +36 -0
- package/.agents/scripts/lib/spec/loader.js +425 -0
- package/.agents/scripts/lib/spec/state.js +217 -0
- package/.agents/scripts/lib/story-body/story-body.js +743 -0
- package/.agents/scripts/lib/story-init/blocker-validator.js +68 -0
- package/.agents/scripts/lib/story-init/branch-initializer.js +422 -0
- package/.agents/scripts/lib/story-init/context-resolver.js +92 -0
- package/.agents/scripts/lib/story-init/donor-precheck.js +207 -0
- package/.agents/scripts/lib/story-init/hierarchy-tracer.js +36 -0
- package/.agents/scripts/lib/story-init/state-transitioner.js +80 -0
- package/.agents/scripts/lib/story-init/task-graph-builder.js +114 -0
- package/.agents/scripts/lib/story-init/transition-summary.js +34 -0
- package/.agents/scripts/lib/story-lifecycle.js +186 -0
- package/.agents/scripts/lib/story-plan.js +246 -0
- package/.agents/scripts/lib/task-utils.js +26 -0
- package/.agents/scripts/lib/templates/decomposer-prompts.js +168 -0
- package/.agents/scripts/lib/test-env.js +30 -0
- package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +52 -0
- package/.agents/scripts/lib/test-isolate/list-files.js +90 -0
- package/.agents/scripts/lib/test-isolate/parse-tap.js +75 -0
- package/.agents/scripts/lib/test-isolate/runner.js +483 -0
- package/.agents/scripts/lib/test-profile/parse-tap.js +136 -0
- package/.agents/scripts/lib/test-profile/render-report.js +45 -0
- package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +35 -0
- package/.agents/scripts/lib/test-tiers.js +94 -0
- package/.agents/scripts/lib/util/concurrent-map.js +59 -0
- package/.agents/scripts/lib/util/phase-timer-state.js +72 -0
- package/.agents/scripts/lib/util/phase-timer.js +163 -0
- package/.agents/scripts/lib/util/poll-loop.js +86 -0
- package/.agents/scripts/lib/util/with-timeout.js +32 -0
- package/.agents/scripts/lib/validation-evidence.js +323 -0
- package/.agents/scripts/lib/wave-runner/tick.js +665 -0
- package/.agents/scripts/lib/wave-runner/wave-checkpoint.js +91 -0
- package/.agents/scripts/lib/wave-runner/wave-runner-error.js +19 -0
- package/.agents/scripts/lib/workers/crap-worker.js +197 -0
- package/.agents/scripts/lib/workers/maintainability-report-worker.js +137 -0
- package/.agents/scripts/lib/workers/maintainability-worker.js +79 -0
- package/.agents/scripts/lib/workspace-provisioner.js +189 -0
- package/.agents/scripts/lib/worktree/bootstrapper.js +48 -0
- package/.agents/scripts/lib/worktree/inspector.js +140 -0
- package/.agents/scripts/lib/worktree/lifecycle/creation.js +118 -0
- package/.agents/scripts/lib/worktree/lifecycle/drift-detection.js +62 -0
- package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +276 -0
- package/.agents/scripts/lib/worktree/lifecycle/gc.js +49 -0
- package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +178 -0
- package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +264 -0
- package/.agents/scripts/lib/worktree/lifecycle/precheck.js +100 -0
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +588 -0
- package/.agents/scripts/lib/worktree/lifecycle/registry-sync.js +124 -0
- package/.agents/scripts/lib/worktree/lifecycle/shared.js +26 -0
- package/.agents/scripts/lib/worktree/lifecycle-manager.js +40 -0
- package/.agents/scripts/lib/worktree/node-modules-strategy.js +349 -0
- package/.agents/scripts/lib/worktree-manager.js +243 -0
- package/.agents/scripts/lifecycle-diff.js +206 -0
- package/.agents/scripts/lifecycle-emit-story-dispatch.js +194 -0
- package/.agents/scripts/lifecycle-emit.js +479 -0
- package/.agents/scripts/lint-baseline.js +507 -0
- package/.agents/scripts/lint-label-vocabulary.js +237 -0
- package/.agents/scripts/loc-delta.js +205 -0
- package/.agents/scripts/notify.js +307 -0
- package/.agents/scripts/package.json +3 -0
- package/.agents/scripts/post-structured-comment.js +127 -0
- package/.agents/scripts/pr-watch-with-update.js +152 -0
- package/.agents/scripts/providers/github/auth.js +65 -0
- package/.agents/scripts/providers/github/board-add.js +63 -0
- package/.agents/scripts/providers/github/branch-protection.js +186 -0
- package/.agents/scripts/providers/github/cache.js +72 -0
- package/.agents/scripts/providers/github/comments.js +131 -0
- package/.agents/scripts/providers/github/compose.js +111 -0
- package/.agents/scripts/providers/github/errors.js +242 -0
- package/.agents/scripts/providers/github/issues.js +242 -0
- package/.agents/scripts/providers/github/labels.js +179 -0
- package/.agents/scripts/providers/github/mappers.js +126 -0
- package/.agents/scripts/providers/github/merge-methods.js +82 -0
- package/.agents/scripts/providers/github/project-board.js +47 -0
- package/.agents/scripts/providers/github/projects-v2-graphql.js +472 -0
- package/.agents/scripts/providers/github/prs.js +103 -0
- package/.agents/scripts/providers/github/request-helpers.js +110 -0
- package/.agents/scripts/providers/github/sub-issues.js +369 -0
- package/.agents/scripts/providers/github/tickets.js +381 -0
- package/.agents/scripts/providers/github/transient-retry.js +62 -0
- package/.agents/scripts/providers/github.js +157 -0
- package/.agents/scripts/quality-preview.js +327 -0
- package/.agents/scripts/quality-watch.js +223 -0
- package/.agents/scripts/render-manifest.js +143 -0
- package/.agents/scripts/resync-status-column.js +176 -0
- package/.agents/scripts/retro-run.js +167 -0
- package/.agents/scripts/run-audit-suite.js +97 -0
- package/.agents/scripts/run-coverage.js +103 -0
- package/.agents/scripts/run-lint.js +94 -0
- package/.agents/scripts/run-test-profile.js +126 -0
- package/.agents/scripts/run-tests.js +185 -0
- package/.agents/scripts/run-verify.js +56 -0
- package/.agents/scripts/select-audits.js +155 -0
- package/.agents/scripts/signals-view.js +294 -0
- package/.agents/scripts/single-story-close.js +83 -0
- package/.agents/scripts/single-story-confirm-merge.js +183 -0
- package/.agents/scripts/single-story-init.js +692 -0
- package/.agents/scripts/stories-wave-tick.js +415 -0
- package/.agents/scripts/story-close.js +246 -0
- package/.agents/scripts/story-deliver-prepare.js +267 -0
- package/.agents/scripts/story-init.js +516 -0
- package/.agents/scripts/story-phase.js +327 -0
- package/.agents/scripts/story-plan.js +284 -0
- package/.agents/scripts/sync-agentrc.js +71 -0
- package/.agents/scripts/sync-branch-from-base.js +138 -0
- package/.agents/scripts/sync-claude-commands.js +151 -0
- package/.agents/scripts/test-isolate.js +222 -0
- package/.agents/scripts/test-wrapper.js +108 -0
- package/.agents/scripts/update-coverage-baseline.js +129 -0
- package/.agents/scripts/update-crap-baseline.js +177 -0
- package/.agents/scripts/update-duplication-baseline.js +134 -0
- package/.agents/scripts/update-maintainability-baseline.js +183 -0
- package/.agents/scripts/update-mutation-baseline.js +189 -0
- package/.agents/scripts/update-ticket-state.js +107 -0
- package/.agents/scripts/validate-docs-freshness.js +259 -0
- package/.agents/scripts/validate-skills.js +278 -0
- package/.agents/scripts/wave-tick.js +335 -0
- package/.agents/skills/core/analyze-execution/SKILL.md +98 -0
- package/.agents/skills/core/api-and-interface-design/SKILL.md +327 -0
- package/.agents/skills/core/baseline-refresh/SKILL.md +181 -0
- package/.agents/skills/core/browser-testing-with-devtools/SKILL.md +352 -0
- package/.agents/skills/core/ci-cd-and-automation/SKILL.md +274 -0
- package/.agents/skills/core/ci-cd-and-automation/examples.md +211 -0
- package/.agents/skills/core/code-review-and-quality/SKILL.md +421 -0
- package/.agents/skills/core/code-simplification/SKILL.md +389 -0
- package/.agents/skills/core/context-engineering/SKILL.md +309 -0
- package/.agents/skills/core/context-engineering/examples.md +58 -0
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +338 -0
- package/.agents/skills/core/deprecation-and-migration/SKILL.md +250 -0
- package/.agents/skills/core/diagnose-friction/SKILL.md +79 -0
- package/.agents/skills/core/documentation-and-adrs/SKILL.md +323 -0
- package/.agents/skills/core/epic-plan-consolidate/SKILL.md +145 -0
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +425 -0
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +393 -0
- package/.agents/skills/core/frontend-ui-engineering/SKILL.md +357 -0
- package/.agents/skills/core/git-workflow-and-versioning/SKILL.md +352 -0
- package/.agents/skills/core/hydrate-context/SKILL.md +118 -0
- package/.agents/skills/core/idea-refinement/SKILL.md +317 -0
- package/.agents/skills/core/idea-refinement/examples.md +437 -0
- package/.agents/skills/core/idea-refinement/frameworks.md +135 -0
- package/.agents/skills/core/idea-refinement/refinement-criteria.md +155 -0
- package/.agents/skills/core/idea-refinement/scripts/idea-refine.sh +15 -0
- package/.agents/skills/core/incremental-implementation/SKILL.md +271 -0
- package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +213 -0
- package/.agents/skills/core/knowledge-transfer/SKILL.md +175 -0
- package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +117 -0
- package/.agents/skills/core/performance-optimization/SKILL.md +314 -0
- package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +277 -0
- package/.agents/skills/core/property-based-testing/SKILL.md +148 -0
- package/.agents/skills/core/qa-coverage-mapping/SKILL.md +105 -0
- package/.agents/skills/core/refactoring-discipline/SKILL.md +111 -0
- package/.agents/skills/core/scope-triage/SKILL.md +127 -0
- package/.agents/skills/core/security-and-hardening/SKILL.md +400 -0
- package/.agents/skills/core/shipping-and-launch/SKILL.md +328 -0
- package/.agents/skills/core/spec-driven-development/SKILL.md +252 -0
- package/.agents/skills/core/test-driven-development/SKILL.md +475 -0
- package/.agents/skills/core/using-agent-skills/SKILL.md +232 -0
- package/.agents/skills/skills.index.json +596 -0
- package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +31 -0
- package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +51 -0
- package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +48 -0
- package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +31 -0
- package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +33 -0
- package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +31 -0
- package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +51 -0
- package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +54 -0
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +29 -0
- package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +30 -0
- package/.agents/skills/stack/backend/stripe-integration/SKILL.md +57 -0
- package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +9 -0
- package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +48 -0
- package/.agents/skills/stack/frontend/astro/SKILL.md +62 -0
- package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +30 -0
- package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +29 -0
- package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +50 -0
- package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +58 -0
- package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +34 -0
- package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +51 -0
- package/.agents/skills/stack/qa/gherkin-authoring/SKILL.md +257 -0
- package/.agents/skills/stack/qa/gherkin-authoring/examples/invoice-issue.feature +41 -0
- package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +199 -0
- package/.agents/skills/stack/qa/playwright/SKILL.md +50 -0
- package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +188 -0
- package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +142 -0
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +220 -0
- package/.agents/skills/stack/qa/vitest/SKILL.md +51 -0
- package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +68 -0
- package/.agents/starter-agentrc.json +22 -0
- package/.agents/templates/agent-protocol.md +72 -0
- package/.agents/templates/docs/architecture.md +30 -0
- package/.agents/templates/docs/decisions.md +24 -0
- package/.agents/templates/epic-from-idea.md +21 -0
- package/.agents/templates/single-story-body.md +17 -0
- package/.agents/workflows/agents-update.md +415 -0
- package/.agents/workflows/audit-architecture.md +312 -0
- package/.agents/workflows/audit-clean-code.md +179 -0
- package/.agents/workflows/audit-dependencies.md +91 -0
- package/.agents/workflows/audit-devops.md +110 -0
- package/.agents/workflows/audit-lighthouse.md +260 -0
- package/.agents/workflows/audit-performance.md +161 -0
- package/.agents/workflows/audit-privacy.md +104 -0
- package/.agents/workflows/audit-quality.md +191 -0
- package/.agents/workflows/audit-security.md +156 -0
- package/.agents/workflows/audit-seo.md +118 -0
- package/.agents/workflows/audit-sre.md +139 -0
- package/.agents/workflows/audit-to-stories.md +257 -0
- package/.agents/workflows/audit-ux-ui.md +102 -0
- package/.agents/workflows/epic-deliver.md +864 -0
- package/.agents/workflows/epic-plan.md +998 -0
- package/.agents/workflows/explain.md +118 -0
- package/.agents/workflows/git-cleanup.md +250 -0
- package/.agents/workflows/git-commit-all.md +15 -0
- package/.agents/workflows/git-merge-pr.md +377 -0
- package/.agents/workflows/git-pr-all.md +278 -0
- package/.agents/workflows/git-push.md +60 -0
- package/.agents/workflows/helpers/_merge-conflict-template.md +54 -0
- package/.agents/workflows/helpers/acceptance-self-eval.md +74 -0
- package/.agents/workflows/helpers/agents-sync-config.md +129 -0
- package/.agents/workflows/helpers/code-quality-guardrails.md +101 -0
- package/.agents/workflows/helpers/code-review.md +370 -0
- package/.agents/workflows/helpers/diagnose.md +117 -0
- package/.agents/workflows/helpers/epic-audit.md +295 -0
- package/.agents/workflows/helpers/epic-deliver-story.md +370 -0
- package/.agents/workflows/helpers/epic-plan-decompose.md +199 -0
- package/.agents/workflows/helpers/epic-plan-spec.md +184 -0
- package/.agents/workflows/helpers/epic-testing.md +125 -0
- package/.agents/workflows/helpers/parallel-tooling.md +88 -0
- package/.agents/workflows/helpers/signals.md +112 -0
- package/.agents/workflows/helpers/single-story-deliver.md +636 -0
- package/.agents/workflows/helpers/worktree-lifecycle.md +317 -0
- package/.agents/workflows/onboard.md +207 -0
- package/.agents/workflows/qa-assist.md +293 -0
- package/.agents/workflows/qa-explore.md +350 -0
- package/.agents/workflows/qa-run-harness.md +288 -0
- package/.agents/workflows/story-deliver.md +327 -0
- package/.agents/workflows/story-plan.md +233 -0
- package/LICENSE +21 -0
- package/README.md +193 -0
- package/bin/mandrel.js +56 -0
- package/bin/postinstall.js +195 -0
- package/lib/cli/__tests__/migrate.test.js +268 -0
- package/lib/cli/__tests__/sync-local-zone.test.js +247 -0
- package/lib/cli/__tests__/sync.test.js +372 -0
- package/lib/cli/__tests__/update-major.test.js +217 -0
- package/lib/cli/__tests__/update.test.js +696 -0
- package/lib/cli/__tests__/version-check.test.js +398 -0
- package/lib/cli/doctor.js +124 -0
- package/lib/cli/explain.js +107 -0
- package/lib/cli/migrate.js +260 -0
- package/lib/cli/registry.js +830 -0
- package/lib/cli/sync-commands.js +50 -0
- package/lib/cli/sync.js +200 -0
- package/lib/cli/uninstall.js +795 -0
- package/lib/cli/update.js +854 -0
- package/lib/cli/version-check.js +206 -0
- package/lib/migrations/README.md +69 -0
- package/lib/migrations/__tests__/index.test.js +216 -0
- package/lib/migrations/index.js +164 -0
- package/package.json +105 -0
|
@@ -0,0 +1,1420 @@
|
|
|
1
|
+
# Software Development Life Cycle (SDLC) Workflow
|
|
2
|
+
|
|
3
|
+
Mandrel uses **Epic-Centric GitHub Orchestration** — GitHub Issues,
|
|
4
|
+
Labels, and Projects V2 are the Single Source of Truth, fronted by a
|
|
5
|
+
declarative `epic.yaml` artifact that makes plans diff-able and
|
|
6
|
+
reconcilable. No per-iteration directories, no JSON state files for
|
|
7
|
+
ticket data.
|
|
8
|
+
|
|
9
|
+
The framework is **Claude Code-first**: `.claude/`, hooks, skills, and
|
|
10
|
+
the slash-command surface lean in on Claude Code as the reference
|
|
11
|
+
runtime, and the dispatcher (`.agents/scripts/`) treats the dispatch
|
|
12
|
+
manifest (md + structured comment) as the cross-runtime contract. See
|
|
13
|
+
ADR 20260512-coupling-stance in [`../docs/decisions.md`](../../docs/decisions.md).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## The simple flow
|
|
18
|
+
|
|
19
|
+
From zero to shipped:
|
|
20
|
+
|
|
21
|
+
1. **Plan the work.** Run `/epic-plan` in your agentic IDE. The framework
|
|
22
|
+
generates a PRD, a Tech Spec, and an Acceptance Spec, decomposes the
|
|
23
|
+
work into the full Feature → Story hierarchy under the Epic, and
|
|
24
|
+
transitions the Epic to `agent::ready`.
|
|
25
|
+
|
|
26
|
+
The entry point you use selects where the run begins:
|
|
27
|
+
- With **no arguments** (or `--idea "<seed>"`), the workflow enters at
|
|
28
|
+
Phase 1 and runs the ideation phases (1–4) to open a fresh
|
|
29
|
+
`type::epic` Issue before authoring.
|
|
30
|
+
- With **`<epicId>`**, the workflow skips ideation and enters at
|
|
31
|
+
Phase 5 for an Epic Issue you have already opened.
|
|
32
|
+
|
|
33
|
+
> **Phase numbering note.** The numbered phases below are
|
|
34
|
+
> `/epic-plan`'s **internal** phases (1–11), not the SDLC-level
|
|
35
|
+
> Phase 0–4 used by the Mermaid diagram in [§ End-to-End
|
|
36
|
+
> Process](#end-to-end-process). Phases 1–4 run **only** on the
|
|
37
|
+
> ideation entry; an existing-Epic invocation starts at Phase 5.
|
|
38
|
+
|
|
39
|
+
1. **Phase 1 — idea refinement** *(ideation entry only)* — the
|
|
40
|
+
`idea-refinement` skill drives a divergent → convergent → sharpen
|
|
41
|
+
loop and emits a one-pager with the five canonical Epic sections.
|
|
42
|
+
Stops for operator confirmation of the one-pager.
|
|
43
|
+
2. **Phase 2 — cross-Epic duplicate search** *(ideation entry only)*
|
|
44
|
+
— `lib/duplicate-search.js` ranks open Epics whose scope overlaps
|
|
45
|
+
the one-pager; the operator confirms the idea is distinct or folds
|
|
46
|
+
it into an existing Epic (in which case `/epic-plan` exits).
|
|
47
|
+
3. **Phase 3 — render Epic body** *(ideation entry only)* — renders
|
|
48
|
+
the confirmed one-pager into the canonical Epic-from-idea template
|
|
49
|
+
and stops for a final wording confirmation.
|
|
50
|
+
4. **Phase 4 — open the Epic Issue** *(ideation entry only)* — opens
|
|
51
|
+
the GitHub Issue with **only** the `type::epic` label; the captured
|
|
52
|
+
id flows into the rest of the pipeline.
|
|
53
|
+
5. **Phase 5 — re-plan detection** — checks whether the Epic already
|
|
54
|
+
carries planning artifacts and, if so, prompts before overwriting
|
|
55
|
+
the PRD / Tech Spec / Acceptance Spec in place and recreating the
|
|
56
|
+
Feature/Story tickets.
|
|
57
|
+
6. **Phase 6 — Epic clarity gate** — scores the Epic body against the
|
|
58
|
+
five canonical sections. A `clear` verdict requires ≥ 4 of 5
|
|
59
|
+
sections present **and** the Acceptance Criteria section present (AC
|
|
60
|
+
is required, not optional). A `clear` verdict proceeds silently;
|
|
61
|
+
`needs-refinement` drops into a one-shot refinement loop with a HITL
|
|
62
|
+
diff before persisting the sharpened body.
|
|
63
|
+
7. **Phase 7 — PRD, Tech Spec & Acceptance Spec** — the
|
|
64
|
+
`epic-plan-spec-author` skill authors all three planning artifacts
|
|
65
|
+
as linked context tickets, flips the Epic to `agent::review-spec`,
|
|
66
|
+
and routes high-risk Epics to a HITL review stop (low-risk Epics
|
|
67
|
+
auto-proceed).
|
|
68
|
+
8. **Phase 8 — work-breakdown decomposition** — the
|
|
69
|
+
`epic-plan-decompose-author` skill emits the Epic → Feature → Story
|
|
70
|
+
tree (with inline `acceptance[]` / `verify[]` per Story); the
|
|
71
|
+
validator enforces hierarchy, DAG acyclicity, and file-assumption
|
|
72
|
+
invariants.
|
|
73
|
+
9. **Phase 9 — execution roadmap** — runs the dispatcher in dry-run to
|
|
74
|
+
compute waves and posts the `dispatch-manifest` structured comment
|
|
75
|
+
that `/epic-deliver` consumes.
|
|
76
|
+
10. **Phase 10 — readiness health check** — `epic-plan-healthcheck.js`
|
|
77
|
+
runs the default config + git-remote checks; a non-OK result is a
|
|
78
|
+
**blocking** exit condition for the `agent::ready` flip (overridable
|
|
79
|
+
only via the `planning::healthcheck-waived` label).
|
|
80
|
+
11. **Phase 11 — plan comprehension gate** — an opt-in, advisory
|
|
81
|
+
walkthrough of the planned backlog driven by the
|
|
82
|
+
`core/knowledge-transfer` skill. Offered by LM judgment only on
|
|
83
|
+
non-trivial plans, runs **after** the `agent::ready` flip, and is
|
|
84
|
+
interruptible at every checkpoint — it never blocks the hand-off.
|
|
85
|
+
12. **Phase 12 — notification & hand-off** — posts the backlog summary
|
|
86
|
+
comment, @mentions the operator, and names `/epic-deliver` as the
|
|
87
|
+
next step.
|
|
88
|
+
|
|
89
|
+
2. **Deliver the Epic.** Run `/epic-deliver <epicId>` in your IDE. The
|
|
90
|
+
skill drives the merged execute + close flow end-to-end.
|
|
91
|
+
|
|
92
|
+
> **Phase numbering note.** The numbered phases below refer to
|
|
93
|
+
> `/epic-deliver`'s **internal** phases (1–9), not the SDLC-level
|
|
94
|
+
> Phase 0–4 used by the Mermaid diagram in [§ End-to-End
|
|
95
|
+
> Process](#end-to-end-process). When prose elsewhere in this
|
|
96
|
+
> document says "Phase 7", it always means the internal
|
|
97
|
+
> `/epic-deliver` phase unless explicitly prefixed with "SDLC".
|
|
98
|
+
|
|
99
|
+
1. **Phase 1 — prepare** — snapshot the Epic, build the wave DAG,
|
|
100
|
+
initialise the `epic-run-state` checkpoint.
|
|
101
|
+
2. **Phase 2 — wave loop** — fan one `/story-deliver` Agent-tool
|
|
102
|
+
sub-agent out per Story per wave (capped at `concurrencyCap`).
|
|
103
|
+
Stories run in parallel inside the operator's Claude session
|
|
104
|
+
against your Max subscription quota; no subprocess worker sessions
|
|
105
|
+
for Story execution, no GitHub Actions minutes. Deterministic
|
|
106
|
+
Node CLIs remain the state-mutation contract.
|
|
107
|
+
3. **Phase 3 — close-validation** — lint, test, and the project's
|
|
108
|
+
ratcheted baselines run against the Epic branch. Evidence is
|
|
109
|
+
cached by HEAD SHA so re-runs short-circuit.
|
|
110
|
+
4. **Phase 4 — audit** — runs the change-set audit lenses against
|
|
111
|
+
the Epic diff; findings flow through as advisory signal.
|
|
112
|
+
5. **Phase 5 — code-review** — auto-invokes the in-process
|
|
113
|
+
`lib/orchestration/code-review.js` (extracted from the old
|
|
114
|
+
`helpers/code-review.md` helper); findings persist as a
|
|
115
|
+
`code-review` structured comment on the Epic. Critical findings
|
|
116
|
+
halt the run.
|
|
117
|
+
6. **Phase 6 — retro** — auto-invokes the in-process
|
|
118
|
+
`lib/orchestration/retro-runner.js` (extracted from the old
|
|
119
|
+
retro helper) and posts the structured retro comment on the
|
|
120
|
+
Epic. The retro fires **before** the PR is opened so it has
|
|
121
|
+
full env access in the operator's local session.
|
|
122
|
+
7. **Phase 7 — finalize** — pushes `epic/<epicId>` to `origin`,
|
|
123
|
+
opens a pull request to `main`, sets the required-checks
|
|
124
|
+
expectation from `github.branchProtection.requiredChecks`, and
|
|
125
|
+
posts the hand-off comment naming the PR URL. The Epic stays
|
|
126
|
+
at `agent::executing` until the PR merges; the standard
|
|
127
|
+
label-transition pathway flips it to `agent::done` on merge.
|
|
128
|
+
Finalize hands off to the watch / auto-merge / cleanup tail
|
|
129
|
+
below — it does **not** stop the run.
|
|
130
|
+
8. **Phase 8 — watch-and-iterate** — watches CI on the open PR
|
|
131
|
+
until checks turn green (or a failure surfaces for human
|
|
132
|
+
remediation).
|
|
133
|
+
9. **Phase 8.5 — auto-merge** — arms GitHub native auto-merge
|
|
134
|
+
(`gh pr merge --auto --squash --delete-branch`) once the
|
|
135
|
+
required checks have passed so the PR lands without a second
|
|
136
|
+
operator visit. The operator can disarm auto-merge in the
|
|
137
|
+
GitHub UI if they want to gate the merge manually.
|
|
138
|
+
10. **Phase 9 — cleanup** — reaps local Story/Epic branch refs and
|
|
139
|
+
worktrees after the PR merges so the workspace returns to a
|
|
140
|
+
clean state for the next Epic.
|
|
141
|
+
|
|
142
|
+
For a single Epic-attached Story (re-driving a hotfix, resuming after
|
|
143
|
+
a halt), re-run `/epic-deliver <epicId>` — the wave loop picks up
|
|
144
|
+
incomplete Stories from the dispatch manifest automatically. Standalone
|
|
145
|
+
Stories (no `Epic: #N` reference) use `/story-deliver <storyId>` instead.
|
|
146
|
+
|
|
147
|
+
That is the whole happy path. Everything below is **detail** — branching
|
|
148
|
+
conventions, HITL escalation, audit gates — that you only need when the
|
|
149
|
+
default flow requires adjustment.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Core Principles
|
|
154
|
+
|
|
155
|
+
- **Layered state stores with explicit precedence.** Project logic, work
|
|
156
|
+
breakdown, and ticket status live in GitHub Issues and Labels; the
|
|
157
|
+
lifecycle bus (`temp/epic-<id>/lifecycle.ndjson`) is the canonical
|
|
158
|
+
resume target for in-flight runs; structured comments
|
|
159
|
+
(`epic-run-state`, `story-run-progress`) are the operator-visible
|
|
160
|
+
rollup. The seven stores, their owners, and their conflict-resolution
|
|
161
|
+
rules are listed in [§ State stores](#state-stores) — that matrix is
|
|
162
|
+
the single source of truth for "who owns which write" and supersedes
|
|
163
|
+
the earlier "GitHub as SSOT" / "lifecycle ledger canonical" prose.
|
|
164
|
+
- **Provider Abstraction.** Orchestration flows through `ITicketingProvider`, an
|
|
165
|
+
abstract interface with a shipped GitHub implementation.
|
|
166
|
+
- **Story-Level Branching.** All work for a Story lands on the shared
|
|
167
|
+
`story-<id>` branch. Stories merge into `epic/<epicId>`; the Epic
|
|
168
|
+
branch reaches `main` only via a pull request the operator merges
|
|
169
|
+
through the GitHub UI.
|
|
170
|
+
- **Hierarchy-aligned skills.** Execution is split along the ticket
|
|
171
|
+
hierarchy: `/epic-plan` builds the backlog (with optional ideation
|
|
172
|
+
entry), `/epic-deliver` owns the merged wave-loop + close-tail, and
|
|
173
|
+
`/story-deliver` delivers one or more standalone Stories end-to-end.
|
|
174
|
+
`helpers/epic-deliver-story` and `helpers/single-story-deliver` are the
|
|
175
|
+
per-Story workers called by those two commands respectively. All share
|
|
176
|
+
the same primitives (`Graph.computeWaves`, `cascadeCompletion`,
|
|
177
|
+
`ticketing.js`, `WorktreeManager`).
|
|
178
|
+
- **Single-session fan-out.** `/epic-deliver` launches Story sub-agents via
|
|
179
|
+
the Agent tool — every Story runs inside the operator's Claude session,
|
|
180
|
+
with no subprocess boundary. Worktree filesystem isolation is preserved;
|
|
181
|
+
only the process boundary is gone.
|
|
182
|
+
- **PR is the sole promotion gate.** `/epic-deliver` ends with a PR open
|
|
183
|
+
against `main` and (by default) GitHub native auto-merge armed; the
|
|
184
|
+
workflow itself never executes `git merge` against `main`. Branch
|
|
185
|
+
protection on `main` enforces required-checks before the merge button
|
|
186
|
+
(auto or manual) fires. The operator can disarm auto-merge in the
|
|
187
|
+
GitHub UI to make the merge an explicit human action.
|
|
188
|
+
- **HITL-minimal by default.** Exactly one mandatory operator touchpoint on
|
|
189
|
+
the happy path — blocker resolution mid-run. PR merge is autonomous via
|
|
190
|
+
the armed auto-merge; the operator becomes a second touchpoint only when
|
|
191
|
+
they disarm auto-merge or when required checks fail and need
|
|
192
|
+
remediation.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## State stores
|
|
197
|
+
|
|
198
|
+
Mandrel writes orchestration state across seven distinct stores. Each
|
|
199
|
+
store has exactly one canonical writer and one well-defined idempotency
|
|
200
|
+
key; conflicts between stores are resolved in the **Conflict
|
|
201
|
+
resolution** column. When the same fact appears in more than one store
|
|
202
|
+
(common during a run — labels mirror lifecycle events, comments mirror
|
|
203
|
+
ledger entries) the entry below names the authoritative reader for that
|
|
204
|
+
fact so downstream code does not have to guess.
|
|
205
|
+
|
|
206
|
+
| State Store | Owner (canonical writer) | Mutation API | Idempotency key | Conflict resolution |
|
|
207
|
+
| --------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
208
|
+
| GitHub labels | `transitionTicketState` via `ticketing.js` | `gh issue edit --add-label / --remove-label`, wrapped in `update-ticket-state.js` | `(ticketId, label-set)` — set-equality check before write | Authoritative for current ticket lifecycle state; if the label disagrees with the lifecycle ledger, the **ledger wins on resume** and the label is re-derived. |
|
|
209
|
+
| `epic-run-state` comment | `checkpointer` submodule in the Epic Deliver Runner | `post-structured-comment.js` (upsert by `kind`) | `(epicId, kind='epic-run-state')` | Operator-visible rollup of phase progress; on conflict with the lifecycle ledger, the ledger is authoritative and the comment is re-rendered. |
|
|
210
|
+
| `story-run-progress` comment | `story-phase.js` (per Story, per phase transition) | `post-structured-comment.js` (upsert by `kind`) | `(storyId, kind='story-run-progress')` | Authoritative for Story-level phase progress; the wave aggregator reads this comment, not labels. |
|
|
211
|
+
| Lifecycle ledger NDJSON | `lifecycle-emit.js` (single append-only writer per Epic run) | Append-only line write to `temp/epic-<id>/lifecycle.ndjson` | `(epicId, eventId)` — `eventId` is a content hash of `{type, ts, payload}` | **Canonical resume target.** When labels / comments disagree with the ledger, the ledger wins and the others are re-derived from it. |
|
|
212
|
+
| Validation evidence cache | `evidence-gate.js` | JSON cache file under `temp/epic-<id>/evidence/<gate>/<sha>.json` | `(gate, git rev-parse HEAD)` | Pure cache: a missing entry triggers a re-run; presence is a fast-path skip. Cache eviction is safe. |
|
|
213
|
+
| PR / auto-merge state | `AutomergeArmer` listener (sole authorized caller of `gh pr merge`) | `gh pr merge --auto --squash --delete-branch`; PR open via `openOrLocatePr` in `Finalizer` | `(prNumber, head-branch SHA)` — `gh pr view` probes existing PR before create | GitHub is authoritative for PR + auto-merge arming state; the lifecycle ledger records the *intent* to arm, GitHub records the outcome. |
|
|
214
|
+
| Worktree cleanup state | `WorktreeManager.reap` (via `story-close.js` / cleanup state) | `git worktree remove` + on-disk pending-cleanup JSON under `temp/epic-<id>/worktree-cleanup.json` | `(storyId, worktree-path)` | Filesystem is authoritative for "is the worktree gone?"; the pending-cleanup JSON only tracks Windows stale-registry entries that need a follow-up sweep. |
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## End-to-End Process
|
|
219
|
+
|
|
220
|
+
```mermaid
|
|
221
|
+
graph LR
|
|
222
|
+
classDef manual fill:#f9d0c4,stroke:#333,stroke-width:2px,color:#000;
|
|
223
|
+
classDef agentic fill:#c4f9d0,stroke:#333,stroke-width:2px,color:#000;
|
|
224
|
+
classDef artifact fill:#ececec,stroke:#333,stroke-width:1px,stroke-dasharray: 5 5,color:#000;
|
|
225
|
+
|
|
226
|
+
subgraph Phase0 ["Phase 0: Bootstrap"]
|
|
227
|
+
direction TB
|
|
228
|
+
Z["👤 npx create-mandrel<br/>(install → sync → bootstrap.js)"]:::manual
|
|
229
|
+
Z2["👤 /onboard (guided first run)"]:::manual
|
|
230
|
+
Z --> Z2
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
subgraph Phase1 ["Phase 1: Initiation"]
|
|
234
|
+
direction TB
|
|
235
|
+
A["👤 /epic-plan (ideation)<br/>or 👤 Create GitHub Epic + /epic-plan <id>"]:::manual
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
subgraph Phase2 ["Phase 2: Planning"]
|
|
239
|
+
direction TB
|
|
240
|
+
C["🤖 PRD + Tech Spec authoring"]:::agentic
|
|
241
|
+
D["🤖 Ticket Decomposer"]:::agentic
|
|
242
|
+
C --> D
|
|
243
|
+
D -.-> D_Art["📄 GitHub Issue Hierarchy"]:::artifact
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
subgraph Phase3 ["Phase 3: Delivery"]
|
|
247
|
+
direction TB
|
|
248
|
+
E["👤 /epic-deliver <epicId>"]:::manual
|
|
249
|
+
F["🤖 wave loop (one /story-deliver sub-agent per Story per wave)"]:::agentic
|
|
250
|
+
G["🤖 close-validation → code-review → retro → open PR"]:::agentic
|
|
251
|
+
E --> F --> G
|
|
252
|
+
G -.-> G_Art["📄 PR open against main"]:::artifact
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
subgraph Phase4 ["Phase 4: PR merge (auto by default)"]
|
|
256
|
+
direction TB
|
|
257
|
+
H["🤖 Auto-merge armed → PR lands when checks pass<br/>(👤 operator may disarm to merge manually)"]:::agentic
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
Z2 --> A
|
|
261
|
+
A --> C
|
|
262
|
+
D --> E
|
|
263
|
+
G --> H
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Phase 0: Bootstrap (One-Time Setup)
|
|
269
|
+
|
|
270
|
+
Before any Epic workflow, bootstrap your project to seed `.agentrc.json`,
|
|
271
|
+
wire the framework system prompt, and create the GitHub labels, Projects V2
|
|
272
|
+
fields, and (when enabled) main-branch protection the orchestration engine
|
|
273
|
+
depends on.
|
|
274
|
+
|
|
275
|
+
The canonical cold-start path is a single launcher command:
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
npx create-mandrel
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
`create-mandrel` installs `mandrel`, materializes `./.agents/` via
|
|
282
|
+
`mandrel sync`, and runs `node .agents/scripts/bootstrap.js`, forwarding any
|
|
283
|
+
flags you pass. `bootstrap.js`:
|
|
284
|
+
|
|
285
|
+
1. **Provisions a cold start.** Initializes the local git repo (with a first
|
|
286
|
+
commit) when absent, creates the GitHub repo (`gh repo create --source=.
|
|
287
|
+
--push`; choose visibility with `--visibility private|public|internal`,
|
|
288
|
+
default `private`), and creates the Projects V2 board (`gh project
|
|
289
|
+
create`) when it doesn't exist. No pre-created repo or remote is required.
|
|
290
|
+
2. **Seeds `.agentrc.json`** from `.agents/starter-agentrc.json` (the `github`
|
|
291
|
+
section carries owner, repo, base branch, operator handle, and project
|
|
292
|
+
number — inferred from your local `git` config where possible). See
|
|
293
|
+
`.agents/docs/agentrc-reference.json` for the exhaustive reference of every
|
|
294
|
+
available key.
|
|
295
|
+
3. **Creates the label taxonomy and Projects V2 fields**, and — when
|
|
296
|
+
`github.branchProtection.enforce` is `true` (default) — creates or merges
|
|
297
|
+
branch protection on `main` with the project's
|
|
298
|
+
`github.branchProtection.requiredChecks` as required status checks. This
|
|
299
|
+
step is load-bearing for the SDL because PR merges to `main` are the sole
|
|
300
|
+
promotion gate.
|
|
301
|
+
|
|
302
|
+
When `.agents/` is already materialized you can run the bootstrap directly
|
|
303
|
+
(`node .agents/scripts/bootstrap.js`). After bootstrap, run **`/onboard`**
|
|
304
|
+
inside Claude Code for the guided first run — stack detection, docs
|
|
305
|
+
scaffolding, a `mandrel doctor` readiness gate, and a started `/epic-plan`.
|
|
306
|
+
|
|
307
|
+
> [!NOTE] Bootstrap runs once per repository. It is safe to re-run — existing
|
|
308
|
+
> labels, fields, and branch-protection entries are preserved; missing ones
|
|
309
|
+
> are added.
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Phase 1: Initiation
|
|
314
|
+
|
|
315
|
+
The product lead defines the objective and triggers planning.
|
|
316
|
+
|
|
317
|
+
### 1a. Ideation entry (optional)
|
|
318
|
+
|
|
319
|
+
Run `/epic-plan` with no arguments (or `--idea "<seed>"`) to enter ideation
|
|
320
|
+
mode:
|
|
321
|
+
|
|
322
|
+
1. **Sharpen the idea.** The `idea-refinement` skill drives a divergent →
|
|
323
|
+
convergent → sharpen loop and emits a markdown one-pager with the
|
|
324
|
+
five canonical Epic sections (Context, Goal, Non-Goals, Scope,
|
|
325
|
+
Acceptance Criteria).
|
|
326
|
+
2. **Scope triage (Phase 1.5).** Before the ceremony is paid for, the
|
|
327
|
+
one-pager is judged against the story-vs-epic rubric (see the
|
|
328
|
+
subsection below). On a `story` / `borderline` verdict the operator may
|
|
329
|
+
route the work to `/story-plan` instead of opening an Epic.
|
|
330
|
+
3. **Cross-Epic duplicate search.** `lib/duplicate-search.js` queries the
|
|
331
|
+
open Epics in the repo, scores by title + body keyword overlap, and
|
|
332
|
+
surfaces matches above a threshold. The operator either confirms the
|
|
333
|
+
new idea is genuinely distinct or folds it into an existing Epic
|
|
334
|
+
(`/epic-plan` exits and the operator resumes work on the existing
|
|
335
|
+
id).
|
|
336
|
+
4. **Render and confirm the Epic body.** The one-pager is rendered into
|
|
337
|
+
the canonical Epic-from-idea template; the operator confirms before
|
|
338
|
+
the GitHub Issue is opened.
|
|
339
|
+
5. **Open the Epic.** The Issue is opened with **only** the `type::epic`
|
|
340
|
+
label — no `state::*` label is applied at creation. PRD authoring in
|
|
341
|
+
Phase 1b advances it to `agent::review-spec`.
|
|
342
|
+
|
|
343
|
+
#### Scope triage
|
|
344
|
+
|
|
345
|
+
`/epic-plan` Phase 1.5 runs the
|
|
346
|
+
[`core/scope-triage`](../skills/core/scope-triage/SKILL.md) rubric over the
|
|
347
|
+
sharpened one-pager so a story-sized scope is not pushed through the full Epic
|
|
348
|
+
ceremony (PRD + Tech Spec + Acceptance Spec + Feature/Story tree +
|
|
349
|
+
`epic/<id>` integration branch) only to land as a degenerate one-Feature,
|
|
350
|
+
one-Story output. The rubric anchors its sizing judgment **by reference** to
|
|
351
|
+
the existing sizing SSOT (`DELIVERABLE_GRANULARITY_GUIDANCE` /
|
|
352
|
+
`DEFAULT_TASK_SIZING` in `ticket-validator-sizing.js`) and emits one of three
|
|
353
|
+
verdicts — `epic` | `story` | `borderline`.
|
|
354
|
+
|
|
355
|
+
The verdict is **host-LLM judgment** (no scorer, no schema, no label
|
|
356
|
+
transition) and **advisory** — the operator always decides. It folds into the
|
|
357
|
+
existing Phase 1 HITL confirmation rather than adding a second stop: an `epic`
|
|
358
|
+
verdict proceeds with a plain confirm, while a `story` / `borderline` verdict
|
|
359
|
+
offers a three-way choice (single Story / plan as Epic anyway / abort). On an
|
|
360
|
+
accepted `story`, `/epic-plan` hands the one-pager off to
|
|
361
|
+
`/story-plan --from-notes` as a scope-triage handoff and exits. Phase 1.5 is
|
|
362
|
+
skipped when `/epic-plan` is itself entered via a scope-triage handoff, so the
|
|
363
|
+
two workflows never ping-pong a settled decision.
|
|
364
|
+
|
|
365
|
+
The same rubric also guards the **existing-Epic entry** (1b) as the
|
|
366
|
+
**Phase 5.5 story-sized advisory**, which catches a story-sized scope that was
|
|
367
|
+
hand-opened directly as a `type::epic` issue (the Phase 6 Epic Clarity Gate
|
|
368
|
+
scores section *presence*, not scope *size*, so a clear-but-thin Epic would
|
|
369
|
+
otherwise sail through). The advisory fires **only** when Phase 5 found no
|
|
370
|
+
linked PRD / Tech Spec **and** the Epic has no open Feature/Story children, so
|
|
371
|
+
it never re-triages an Epic that is being re-planned. An `epic` verdict
|
|
372
|
+
proceeds silently; a `story` / `borderline` verdict STOPs with the same
|
|
373
|
+
three-way choice (convert to a standalone Story / proceed as Epic anyway /
|
|
374
|
+
abort). Converting is **close-and-recreate** — a `type::epic` body cannot
|
|
375
|
+
satisfy `validateStoryBody`, and editing the issue in place would violate the
|
|
376
|
+
"do not modify existing issues without explicit permission" rule — so, only
|
|
377
|
+
after the operator confirms, the Epic body seeds a notes file,
|
|
378
|
+
`/story-plan --from-notes` opens a replacement Story (identified as a
|
|
379
|
+
scope-triage handoff so it skips its own gate, with a `## Notes` back-link to
|
|
380
|
+
the Epic), and the Epic is closed with `gh issue close --comment` cross-linking
|
|
381
|
+
the replacement. No deterministic scorer, no schema, and no label transition
|
|
382
|
+
sit behind either gate.
|
|
383
|
+
|
|
384
|
+
The rubric also runs in the **escalation direction** — the symmetric
|
|
385
|
+
counterpart in [`/story-plan`](../workflows/story-plan.md). After `/story-plan`
|
|
386
|
+
Phase 2 drafts a standalone Story body (the draft, not the seed, is the honest
|
|
387
|
+
basis for the judgment), the same `core/scope-triage` rubric judges whether the
|
|
388
|
+
scope is actually Epic-sized. The verdict folds into the existing Phase 2
|
|
389
|
+
draft-confirmation HITL stop with no extra stop on a `story` verdict; an `epic`
|
|
390
|
+
verdict offers a three-way choice (escalate to `/epic-plan --idea` as a
|
|
391
|
+
scope-triage handoff / persist as a standalone Story anyway / abort). On an
|
|
392
|
+
accepted escalation, `/story-plan` abandons the draft and hands the notes off to
|
|
393
|
+
`/epic-plan --idea`, marked as a handoff so `/epic-plan` skips its own Phase 1.5
|
|
394
|
+
gate. This gate is itself skipped when `/story-plan` was entered via a
|
|
395
|
+
scope-triage handoff (from `/epic-plan` Phase 1.5 or the Phase 5.5 conversion
|
|
396
|
+
path), so the two workflows never ping-pong a settled decision. As with the
|
|
397
|
+
inbound gates, the verdict is advisory and host-LLM judgment — no auto-routing,
|
|
398
|
+
no scorer, no schema, and no label transition.
|
|
399
|
+
|
|
400
|
+
### 1b. Existing-Epic entry
|
|
401
|
+
|
|
402
|
+
Run `/epic-plan <epicId>` directly when the Epic Issue already exists. The
|
|
403
|
+
ideation phases (1a) are skipped.
|
|
404
|
+
|
|
405
|
+
In both modes the planning flow continues into Phase 2 with the captured
|
|
406
|
+
Epic id.
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## Phase 2: Planning (Autonomous)
|
|
411
|
+
|
|
412
|
+
The framework reads the Epic and autonomously builds the entire work breakdown.
|
|
413
|
+
|
|
414
|
+
> **Epic Clarity Gate (`/epic-plan` `planning.clarity-gate` state).** Before PRD / Tech Spec /
|
|
415
|
+
> Acceptance Spec authoring kicks off, `/epic-plan` scores the Epic body
|
|
416
|
+
> against the five canonical sections from
|
|
417
|
+
> [`templates/epic-from-idea.md`](../templates/epic-from-idea.md) (Context,
|
|
418
|
+
> Goal, Non-Goals, Scope, Acceptance Criteria). Common legacy heading
|
|
419
|
+
> variants (`Problem`, `Direction`, `MVP Scope`, `Not Doing`,
|
|
420
|
+
> `Out of Scope`) are accepted by the scorer's regex for back-compat.
|
|
421
|
+
> The rubric is deterministic (section-presence): `clear` requires ≥ 4 of 5
|
|
422
|
+
> sections present **and** the Acceptance Criteria section present (AC is
|
|
423
|
+
> required). A
|
|
424
|
+
> `clear` verdict
|
|
425
|
+
> skips fast with no prompt; a `needs-refinement` verdict drops into the
|
|
426
|
+
> `idea-refinement` skill seeded from the current Epic body, surfaces a
|
|
427
|
+
> HITL diff, and on approval persists the sharpened body via
|
|
428
|
+
> `gh issue edit` before the `planning.spec-authoring` state begins.
|
|
429
|
+
> The gate honours the
|
|
430
|
+
> "do not modify existing issues without permission" Constraint — every
|
|
431
|
+
> body rewrite is operator-confirmed.
|
|
432
|
+
|
|
433
|
+
1. **Epic Planner** (`epic-plan-spec.js`):
|
|
434
|
+
- Synthesizes the Epic body with project documentation.
|
|
435
|
+
- Generates a **PRD** (`context::prd`), **Tech Spec**
|
|
436
|
+
(`context::tech-spec`), and **Acceptance Spec**
|
|
437
|
+
(`context::acceptance-spec`) as linked GitHub Issues.
|
|
438
|
+
|
|
439
|
+
> [!TIP] **PRD authoring — acceptance criteria phrasing.** Write acceptance
|
|
440
|
+
> criteria in Gherkin-compatible `Given / When / Then` form so the QA
|
|
441
|
+
> acceptance suite can lift them directly into executable `.feature` files. See
|
|
442
|
+
> [`rules/gherkin-standards.md`](../rules/gherkin-standards.md) for the canonical
|
|
443
|
+
> clause grammar, tag taxonomy, and forbidden patterns.
|
|
444
|
+
|
|
445
|
+
### Acceptance Spec — the third planning context ticket
|
|
446
|
+
|
|
447
|
+
Every Epic carries **three** planning context tickets, not two:
|
|
448
|
+
|
|
449
|
+
| Label | Artifact | Authored by | Drives |
|
|
450
|
+
| --------------------------- | ---------------- | --------------------------------------------------- | -------------------------------------------------------- |
|
|
451
|
+
| `context::prd` | PRD | `epic-plan-spec-author` skill (PRD persona) | What we're shipping and why. |
|
|
452
|
+
| `context::tech-spec` | Tech Spec | `epic-plan-spec-author` skill (Architect persona) | How we're shipping it. |
|
|
453
|
+
| `context::acceptance-spec` | Acceptance Spec | `epic-plan-spec-author` skill (Acceptance Engineer) | The AC ID table that gates close-time reconciliation. |
|
|
454
|
+
|
|
455
|
+
The Acceptance Spec body is a single Markdown table —
|
|
456
|
+
`| AC ID | Outcome | Feature File | Scenario | Disposition |` — with
|
|
457
|
+
stable `AC-<n>` IDs assigned in document order. IDs are reused across
|
|
458
|
+
re-plans when an Outcome is materially unchanged so scenario tags
|
|
459
|
+
(`@ac-N`) stay aligned with the spec. Each row's `Disposition` is one
|
|
460
|
+
of `new | updated | unchanged`. The skill also renders a **Runner
|
|
461
|
+
Verification** line directly under the table that records the verified
|
|
462
|
+
BDD runner + pending-tag (e.g. `playwright-bdd supports @skip`) for the
|
|
463
|
+
features-first Story to consume.
|
|
464
|
+
|
|
465
|
+
The spec is persisted by
|
|
466
|
+
`epic-plan-spec.js --epic [Epic_ID] --prd ... --techspec ... --acceptance-spec ...`
|
|
467
|
+
— the persist half writes all three artifacts in one atomic step and
|
|
468
|
+
fails loudly if any is missing or empty.
|
|
469
|
+
|
|
470
|
+
#### Adaptive planning risk routing
|
|
471
|
+
|
|
472
|
+
`/epic-plan`'s `planning.spec-authoring` state derives a deterministic
|
|
473
|
+
**`planningRisk`** envelope from a **planner-authored risk verdict**
|
|
474
|
+
(`risk-verdict.json`, the fourth planning artifact the
|
|
475
|
+
`epic-plan-spec-author` Skill writes from the PRD / Tech Spec it just
|
|
476
|
+
authored). The persist half of `epic-plan-spec.js` validates the verdict
|
|
477
|
+
against `risk-verdict.schema.json` — a malformed verdict fails closed —
|
|
478
|
+
then derives the envelope via `deriveRiskEnvelope`
|
|
479
|
+
(`lib/orchestration/planning-risk.js`). The verdict is recorded as a
|
|
480
|
+
`risk-verdict` structured comment on the Epic, and both the verdict and
|
|
481
|
+
the envelope land in the `epic-plan-state` checkpoint, consumed by two
|
|
482
|
+
downstream decisions:
|
|
483
|
+
|
|
484
|
+
- **Acceptance disposition** — `acceptanceDisposition` is one of
|
|
485
|
+
`required`, `recommended`, or `not-applicable`. The `not-applicable`
|
|
486
|
+
case is the planner-selected route to the `acceptance::n-a` waiver
|
|
487
|
+
(see the section below); the other two cause the Acceptance Spec to
|
|
488
|
+
be authored normally.
|
|
489
|
+
- **Gate routing** — `gateDecision` is either `review-required`
|
|
490
|
+
(paired with `requiresReview: true`) or `auto-proceed`. High-risk
|
|
491
|
+
Epics (visible behavior, public API, security, billing, data
|
|
492
|
+
migration, destructive mutation, critical workflow) trigger a HITL
|
|
493
|
+
stop after `planning.spec-authoring` so the operator can read the
|
|
494
|
+
PRD / Tech Spec / Acceptance Spec on GitHub before decomposition
|
|
495
|
+
starts. Low-risk Epics (docs-only, internal refactor, pure test
|
|
496
|
+
harness, cleanup) print the auto-proceed message from
|
|
497
|
+
`reviewRouting.operatorMessage` and chain directly into the
|
|
498
|
+
`planning.decompose` state. The operator can force the review
|
|
499
|
+
stop on low-risk work by passing `--force-review` to `/epic-plan`.
|
|
500
|
+
|
|
501
|
+
The risk envelope is also threaded into the `planning.decompose` state's decomposer context
|
|
502
|
+
so the ticket array can cite the relevant axes when assigning
|
|
503
|
+
`risk::high` labels to Stories. The split is "judgment proposes, harness
|
|
504
|
+
gates": the planner supplies the axes (with per-axis rationale), and the
|
|
505
|
+
envelope derivation — overall level, review requirement, acceptance
|
|
506
|
+
disposition, gate decision — is local and deterministic.
|
|
507
|
+
|
|
508
|
+
#### Opting out — the `acceptance::n-a` waiver
|
|
509
|
+
|
|
510
|
+
Not every Epic warrants a formal Acceptance Spec (pure refactors,
|
|
511
|
+
framework maintenance, docs-only churn). The **`acceptance::n-a`** label
|
|
512
|
+
on the Epic ticket records the waiver. There are two routes to the label:
|
|
513
|
+
|
|
514
|
+
- **Operator-applied** — the operator labels the Epic before or during
|
|
515
|
+
`/epic-plan`'s `planning.spec-authoring` state when they already
|
|
516
|
+
know the work does not need a spec.
|
|
517
|
+
- **Planner-selected** — `/epic-plan`'s `planning.spec-authoring` state derives a
|
|
518
|
+
`planningRisk` envelope from the planner-authored risk verdict
|
|
519
|
+
(see § Adaptive planning risk routing) and,
|
|
520
|
+
when `acceptanceDisposition === 'not-applicable'`, the persist half
|
|
521
|
+
of `epic-plan-spec.js` applies `acceptance::n-a` on the Epic and skips
|
|
522
|
+
the Acceptance Spec artifact for that run. The disposition is also
|
|
523
|
+
recorded in the `epic-plan-state` checkpoint so the decision is
|
|
524
|
+
auditable.
|
|
525
|
+
|
|
526
|
+
Either route produces the same runtime behavior. The waiver is respected
|
|
527
|
+
by both runtime gates:
|
|
528
|
+
|
|
529
|
+
- The `/epic-deliver` **start gate** (`delivery.snapshot` state) skips
|
|
530
|
+
the acceptance-spec presence check when the label is set.
|
|
531
|
+
- The finalize-time **acceptance-spec reconciler** returns
|
|
532
|
+
`status: 'waived'` without scanning `tests/features/**` and the
|
|
533
|
+
finalize step proceeds.
|
|
534
|
+
|
|
535
|
+
The waiver is binary — there is no partial opt-out. If an Epic later
|
|
536
|
+
warrants spec coverage, remove the label and run `/epic-plan`'s
|
|
537
|
+
`planning.spec-authoring` state to author the spec.
|
|
538
|
+
|
|
539
|
+
1. **Ticket Decomposer** (`epic-plan-decompose.js`):
|
|
540
|
+
- Recursively decomposes specs into the **3-tier hierarchy**
|
|
541
|
+
(Epic → Feature → Story):
|
|
542
|
+
|
|
543
|
+
```text
|
|
544
|
+
Epic (type::epic)
|
|
545
|
+
├── PRD (context::prd)
|
|
546
|
+
├── Tech Spec (context::tech-spec)
|
|
547
|
+
├── Feature (type::feature)
|
|
548
|
+
│ ├── Story (type::story)
|
|
549
|
+
│ │ ├── acceptance[] ← inline on Story body
|
|
550
|
+
│ │ └── verify[] ← inline on Story body
|
|
551
|
+
│ └── Story (type::story)
|
|
552
|
+
└── Feature (type::feature)
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
- **Wiring.** Each ticket is linked using `blocked by #NNN` syntax and
|
|
556
|
+
GitHub's native sub-issues API.
|
|
557
|
+
- **Metadata.** Each Story is stamped with persona, estimated files,
|
|
558
|
+
and agent prompts, plus the inline `acceptance[]` / `verify[]`
|
|
559
|
+
arrays the executing sub-agent reads.
|
|
560
|
+
|
|
561
|
+
`/story-deliver` runs a **single** Story-implementation phase per
|
|
562
|
+
Story. The wave-loop fan-out in `/epic-deliver`, the Epic → Feature
|
|
563
|
+
thematic frame, and the Story-branch → Epic-branch merge model are
|
|
564
|
+
unchanged from the prior 4-tier shape; only the Task layer is gone.
|
|
565
|
+
|
|
566
|
+
When decomposition completes the Epic flips to `agent::ready` and the
|
|
567
|
+
dispatch manifest is posted as a structured comment on the Epic. That
|
|
568
|
+
manifest is the source of truth for the wave layout `/epic-deliver`
|
|
569
|
+
consumes in the `delivery.snapshot` state.
|
|
570
|
+
|
|
571
|
+
### `agent::ready` exit conditions
|
|
572
|
+
|
|
573
|
+
The planning → delivery handoff is governed by an explicit checklist.
|
|
574
|
+
The persist half of `epic-plan-decompose.js` refuses to flip the Epic
|
|
575
|
+
to `agent::ready` unless **every** condition below is true. The
|
|
576
|
+
contract is enforced at the planner boundary so `/epic-deliver` can
|
|
577
|
+
treat `agent::ready` as a load-bearing precondition rather than a
|
|
578
|
+
hopeful signal.
|
|
579
|
+
|
|
580
|
+
- **Planning artifacts linked or waived.** The Epic body lists a
|
|
581
|
+
linked `context::prd` and `context::tech-spec` ticket, and either a
|
|
582
|
+
linked `context::acceptance-spec` ticket **or** the
|
|
583
|
+
`acceptance::n-a` waiver label. Missing-without-waiver fails the
|
|
584
|
+
handoff.
|
|
585
|
+
- **Decomposition persisted.** The structural reconciler has applied
|
|
586
|
+
the Feature/Story/Task hierarchy and written the spec to
|
|
587
|
+
`.agents/epics/<epicId>.yaml`. The `epic-plan-state` checkpoint
|
|
588
|
+
comment records `phase: ready`.
|
|
589
|
+
- **Dispatch manifest posted.** A single `epic-dispatch` structured
|
|
590
|
+
comment exists on the Epic and validates against
|
|
591
|
+
`.agents/schemas/dispatch-manifest.json`. The dispatch manifest is
|
|
592
|
+
the source of truth `/epic-deliver` reads during
|
|
593
|
+
`delivery.snapshot`.
|
|
594
|
+
- **Healthcheck green.** `epic-plan-healthcheck.js` (run during
|
|
595
|
+
`/epic-plan` Phase 10) returned `ok: true`. A failing healthcheck
|
|
596
|
+
blocks the handoff — there is no advisory degrade-mode for
|
|
597
|
+
`agent::ready`.
|
|
598
|
+
- **Notification posted.** The planner has posted the
|
|
599
|
+
`planning.handoff` notification on the Epic so the operator and any
|
|
600
|
+
subscribed listeners know the Epic is ready to fan out.
|
|
601
|
+
|
|
602
|
+
**Operator override.** The `planning::healthcheck-waived` label, applied
|
|
603
|
+
to the Epic by the operator, is the documented escape hatch for cases
|
|
604
|
+
where the healthcheck reports `ok: false` for an environmental reason
|
|
605
|
+
the operator has triaged and accepted (for example: a transient
|
|
606
|
+
`origin` outage during a known maintenance window). When the label is
|
|
607
|
+
present, the persist half allows the `agent::ready` flip even though
|
|
608
|
+
the healthcheck failed. Every other exit condition above still
|
|
609
|
+
applies — the waiver scopes to the healthcheck check alone. Remove
|
|
610
|
+
the label to re-arm the gate.
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
## Phase 3: Delivery (Agentic)
|
|
615
|
+
|
|
616
|
+
Delivery is driven by the **`/epic-deliver`** slash command for whole-Epic
|
|
617
|
+
flows and the **Story Init/Close** scripts for individual Stories. All entry
|
|
618
|
+
points share the same primitives — DAG computation, context hydration,
|
|
619
|
+
worktree isolation, and cascade closure. The lifecycle bus listener
|
|
620
|
+
chain inside the session is the single runtime; it owns wave fan-out,
|
|
621
|
+
finalize, automerge, and cleanup. The `delivery.finalize`,
|
|
622
|
+
`delivery.automerge`, and `delivery.complete` states each fire one
|
|
623
|
+
typed event via `lifecycle-emit.js` (`epic.close.end`,
|
|
624
|
+
`epic.automerge.start`, `epic.merge.armed`); the matching listeners run
|
|
625
|
+
the side effects. See
|
|
626
|
+
[`docs/LIFECYCLE.md`](../../docs/LIFECYCLE.md) for the bus contract,
|
|
627
|
+
event taxonomy, ledger format, and listener model — every phase
|
|
628
|
+
transition, ticket-state flip, and webhook fan-out now flows through
|
|
629
|
+
that bus, and the on-disk ledger at `temp/epic-<id>/lifecycle.ndjson`
|
|
630
|
+
is the canonical resume target. Safety gates (auto-merge arming,
|
|
631
|
+
acceptance-spec reconciliation, blocker handling) are listener
|
|
632
|
+
side-effects rather than inline calls at phase boundaries; the
|
|
633
|
+
"merge-lockout" lint rule keeps `gh pr merge` confined to the
|
|
634
|
+
`AutomergeArmer` listener.
|
|
635
|
+
|
|
636
|
+
> **Acceptance-spec start gate.** Before a single wave fans out,
|
|
637
|
+
> `/epic-deliver`'s `delivery.snapshot` state
|
|
638
|
+
> ([`lib/orchestration/epic-runner/phases/snapshot.js`](../scripts/lib/orchestration/epic-runner/phases/snapshot.js))
|
|
639
|
+
> asserts that the Epic either (a) carries the `acceptance::n-a`
|
|
640
|
+
> waiver label, or (b) has a linked `context::acceptance-spec`
|
|
641
|
+
> ticket. The ticket's GitHub state (open / closed) is not checked
|
|
642
|
+
> — presence is sufficient, matching the PRD and Tech Spec contract.
|
|
643
|
+
> The reviewer's OK during `/epic-plan`'s `planning.spec-authoring`
|
|
644
|
+
> state is the approval
|
|
645
|
+
> signal, not a manual ticket-close action; the three planning
|
|
646
|
+
> context tickets are closed automatically by the
|
|
647
|
+
> `Finalizer` listener subscribed to `epic.close.end` once the
|
|
648
|
+
> Epic PR opens. Neither
|
|
649
|
+
> condition met → the snapshot throws a clear error naming the
|
|
650
|
+
> missing precondition and `runAsCli` maps it to `process.exit(1)`.
|
|
651
|
+
> This refuses to launch Epics that skipped acceptance-spec
|
|
652
|
+
> authoring, surfacing the gap at delivery time rather than letting
|
|
653
|
+
> Story dispatch race ahead.
|
|
654
|
+
|
|
655
|
+
### Invocation modes
|
|
656
|
+
|
|
657
|
+
| Mode | Entry point | When to use |
|
|
658
|
+
| -------------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
659
|
+
| **Whole Epic** | `/epic-deliver <epicId>` | Drive an Epic end-to-end. Owns the wave loop and the close-tail; ends with a PR open to main. |
|
|
660
|
+
| **Epic-attached Story (worker)** | *helper* `helpers/epic-deliver-story <storyId>` | Per-Story sub-agent called internally by `/epic-deliver`'s wave fan-out; not an operator slash command. |
|
|
661
|
+
| **Standalone Story — plan** | `/story-plan` | Plan a one-off Story that does not belong to an Epic backlog. |
|
|
662
|
+
| **Standalone Story — deliver** | `/story-deliver <storyId> [<storyId>...]` | Deliver one or more standalone Stories authored by `/story-plan`. |
|
|
663
|
+
| **Standalone Story (worker)** | *helper* `helpers/single-story-deliver <storyId>` | Per-Story sub-agent called internally by `/story-deliver`; not an operator slash command. |
|
|
664
|
+
|
|
665
|
+
The operator-facing entry points are `/epic-deliver` (for Epics) and
|
|
666
|
+
`/story-deliver` (for standalone Stories). The `helpers/` layer sits below
|
|
667
|
+
both and is never invoked directly by the operator.
|
|
668
|
+
|
|
669
|
+
### Story-centric branching
|
|
670
|
+
|
|
671
|
+
- **Format**: `story-<storyId>` (merges into `epic/<epicId>`).
|
|
672
|
+
- **Goal**: minimize merge conflicts and consolidation waves by grouping
|
|
673
|
+
related work on one context slice.
|
|
674
|
+
|
|
675
|
+
### Story execution lifecycle
|
|
676
|
+
|
|
677
|
+
Whether the Story is launched directly by the operator or fanned out by
|
|
678
|
+
`/epic-deliver`'s wave loop, the same three phases run:
|
|
679
|
+
|
|
680
|
+
1. **Initialization** (`story-init.js`):
|
|
681
|
+
- Verifies all upstream dependencies are satisfied.
|
|
682
|
+
- Syncs the Epic base branch with `main`.
|
|
683
|
+
- Creates or seeds the Story branch (in a worktree when
|
|
684
|
+
`delivery.worktreeIsolation.enabled: true`).
|
|
685
|
+
- Transitions the Story to `agent::executing`. `story-phase.js`
|
|
686
|
+
upserts the initial `story-run-progress` snapshot at the `init`
|
|
687
|
+
phase.
|
|
688
|
+
2. **Story implementation.** The agent executes the Story's inline
|
|
689
|
+
`acceptance[]` / `verify[]` contract on the shared Story branch,
|
|
690
|
+
authoring one or more commits referencing the parent Story via
|
|
691
|
+
`(refs #<storyId>)`. Each phase transition (`implementing`,
|
|
692
|
+
`closing`, `done`, `blocked`) is recorded via `story-phase.js`.
|
|
693
|
+
|
|
694
|
+
After the implementation commits land and **before** the phase flips
|
|
695
|
+
to `closing`, a **bounded acceptance self-eval loop** runs (Story
|
|
696
|
+
#3819). An independent, fresh-context critic pass scores the working
|
|
697
|
+
diff against **each** `acceptance[]` item — `met | partial | unmet`
|
|
698
|
+
plus a short evidence string, consuming the Story's `verify[]`
|
|
699
|
+
commands as **required evidence** (the `verify[]` commands are no
|
|
700
|
+
longer optional advisory pre-flight). The critic writes its verdict to
|
|
701
|
+
a verdict file
|
|
702
|
+
(`.agents/schemas/acceptance-eval-verdict.schema.json`); the
|
|
703
|
+
`acceptance-eval.js` gate validates it, enforces the bounded round
|
|
704
|
+
cap, and decides the next action:
|
|
705
|
+
- **all `met`** → the phase flips to `closing`.
|
|
706
|
+
- **any `partial`/`unmet`, rounds remaining** → the agent redrafts
|
|
707
|
+
the flagged criteria and re-runs the critic pass for the next round.
|
|
708
|
+
- **round cap reached, criteria still unmet** → the Story transitions
|
|
709
|
+
to `agent::blocked` (not `closing`), posts a `friction` comment
|
|
710
|
+
naming the unmet criteria and their evidence, and exits non-zero. It
|
|
711
|
+
never silently proceeds to close.
|
|
712
|
+
|
|
713
|
+
The loop is **always on** (a hard cutover — there is no flag toggling
|
|
714
|
+
it off) and **bounded**: the redraft ceiling is
|
|
715
|
+
`delivery.acceptanceEval.maxRounds` (default 2), clamped by the
|
|
716
|
+
resolver into `[1, hard ceiling]` so no configuration can disable the
|
|
717
|
+
cap or let the loop spin unbounded. Each terminus emits a
|
|
718
|
+
per-criterion `acceptance-eval` signal into the retro / feedback
|
|
719
|
+
substrate so the retro and `/epic-plan` Phase 0 feedback fetch see
|
|
720
|
+
which acceptance items needed rework and the round count. The loop is
|
|
721
|
+
**additive** and sits below the Epic-level acceptance-spec
|
|
722
|
+
reconciliation (`/epic-deliver` Phase 7.1) — it evaluates the actual
|
|
723
|
+
work product per Story mid-delivery, not test-tag presence at
|
|
724
|
+
finalize.
|
|
725
|
+
3. **Closure** (`story-close.js`):
|
|
726
|
+
- Runs shift-left validation (lint, format, test).
|
|
727
|
+
- Merges the Story branch into `epic/<epicId>`.
|
|
728
|
+
- Transitions the Story → `agent::done`; cascades up Story → Feature
|
|
729
|
+
(Epics and context tickets are excluded from auto-cascade).
|
|
730
|
+
- Reaps the Story worktree and cleans up the merged Story branch.
|
|
731
|
+
|
|
732
|
+
### Context hydration
|
|
733
|
+
|
|
734
|
+
When a sub-agent runs `helpers/epic-deliver-story <storyId>` (for
|
|
735
|
+
Epic-attached Stories) or `helpers/single-story-deliver <storyId>` (for
|
|
736
|
+
standalone Stories), the Context Hydrator assembles a self-contained prompt:
|
|
737
|
+
|
|
738
|
+
1. `agent-protocol.md` (universal rules).
|
|
739
|
+
2. Persona and skill directives (from Task labels).
|
|
740
|
+
3. Hierarchy context (Story → Feature → Epic → PRD → Tech Spec).
|
|
741
|
+
4. **Story branch context.** Automatic checkouts to the Story branch. Under
|
|
742
|
+
worktree isolation, each Story runs in its own `.worktrees/story-<id>/` so
|
|
743
|
+
branch swaps, staging, and reflog activity are isolated per-story. See
|
|
744
|
+
[`workflows/helpers/worktree-lifecycle.md`](../workflows/helpers/worktree-lifecycle.md).
|
|
745
|
+
5. Task-specific instructions and subtask checklist.
|
|
746
|
+
|
|
747
|
+
### State sync
|
|
748
|
+
|
|
749
|
+
Agents update their state in real-time on GitHub:
|
|
750
|
+
|
|
751
|
+
- **Labels**: `agent::ready` → `agent::executing` → `agent::done`. The
|
|
752
|
+
intermediate review label is not part of the label taxonomy; the
|
|
753
|
+
PR opened by `/epic-deliver`'s `delivery.finalize` state is the equivalent "ready to merge"
|
|
754
|
+
signal at the Epic level. The `WaveObserver` submodule additionally
|
|
755
|
+
syncs a GitHub Projects v2 Status column on each transition when a
|
|
756
|
+
`projectNumber` is configured.
|
|
757
|
+
- **Tasklists**: subtasks are checked off in the ticket body (`- [ ]` →
|
|
758
|
+
`- [x]`).
|
|
759
|
+
- **Friction**: friction logs are posted as structured comments on the Task.
|
|
760
|
+
- **Wave transitions**: the Epic Deliver Runner emits `wave-N-start` and
|
|
761
|
+
`wave-N-end` structured comments on the Epic, each carrying the wave
|
|
762
|
+
manifest, story outcomes, and timing.
|
|
763
|
+
|
|
764
|
+
### Dependency unblocking
|
|
765
|
+
|
|
766
|
+
When a Task reaches `agent::done`, the runner re-evaluates the DAG and
|
|
767
|
+
dispatches any newly-unblocked Tasks. This continues until all waves complete.
|
|
768
|
+
|
|
769
|
+
### Story assignment (deterministic)
|
|
770
|
+
|
|
771
|
+
`helpers/epic-deliver-story` requires an explicit Story id. The parent
|
|
772
|
+
`/epic-deliver` wave loop picks Story ids off the frozen dispatch manifest
|
|
773
|
+
deterministically and launches one Agent-tool sub-agent (calling
|
|
774
|
+
`helpers/epic-deliver-story`) per id per wave; sibling sub-agents never
|
|
775
|
+
race on the same Story.
|
|
776
|
+
|
|
777
|
+
`runtime.sessionId` survives as a stable per-process identity surfaced in
|
|
778
|
+
the startup `[ENV]` log line for operator correlation. It is a 12-char
|
|
779
|
+
short-id derived from hostname+pid+random.
|
|
780
|
+
|
|
781
|
+
### Launch-time dependency guard
|
|
782
|
+
|
|
783
|
+
Before any branch operation, `story-init.js` reads the Epic's
|
|
784
|
+
dispatch manifest and verifies the target story's blockers are all merged.
|
|
785
|
+
Unmerged blockers print each blocker's id, state, and URL; the session exits
|
|
786
|
+
0 (operator-error, not a system error) without touching any branches. A
|
|
787
|
+
missing or stale-format manifest emits a warning and proceeds — the guard is
|
|
788
|
+
a footgun-prevention layer, not a strict gate.
|
|
789
|
+
|
|
790
|
+
The guard runs identically on web and local.
|
|
791
|
+
|
|
792
|
+
### Concurrent close — push retry
|
|
793
|
+
|
|
794
|
+
`story-close.js` merges the Story branch into `epic/<epicId>` locally
|
|
795
|
+
and pushes. With multiple sessions closing into the same Epic branch from
|
|
796
|
+
separate clones, a non-fast-forward rejection is expected. The push step is
|
|
797
|
+
wrapped in a bounded retry: on rejection the script fetches
|
|
798
|
+
`origin/epic/<id>`, replays the Story merge on top of the new remote tip,
|
|
799
|
+
and pushes again. Bounds:
|
|
800
|
+
|
|
801
|
+
- `DEFAULT_STORY_MERGE_RETRY.maxAttempts` (framework-internal constant in
|
|
802
|
+
`.agents/scripts/lib/config/runners.js`) — 3.
|
|
803
|
+
- `DEFAULT_STORY_MERGE_RETRY.backoffMs` (same module) — `[250, 500, 1000]`.
|
|
804
|
+
|
|
805
|
+
A real content conflict (both stories touched the same lines) aborts the
|
|
806
|
+
loop with a clear error, leaves the local tree clean, and exits non-zero for
|
|
807
|
+
manual resolution. The retry path is a wrapper around the existing happy path.
|
|
808
|
+
|
|
809
|
+
### Cross-clone coordination
|
|
810
|
+
|
|
811
|
+
Concurrent runs are serialised by **two distinct layers**, and the
|
|
812
|
+
distinction matters: getting it wrong leaves two clones racing on the same
|
|
813
|
+
Epic with no guard between them.
|
|
814
|
+
|
|
815
|
+
**Filesystem locks are same-machine-only.** The Epic merge lock
|
|
816
|
+
(`.agents/scripts/lib/epic-merge-lock.js`) lives at
|
|
817
|
+
`<gitCommonDir>/epic-<epicId>.merge.lock` inside `.git/`, and the
|
|
818
|
+
single-story sweep lock (`.agents/scripts/lib/single-story-sweep/sweep-lock.js`)
|
|
819
|
+
is a single-file rendezvous on the local filesystem. Both decide staleness
|
|
820
|
+
by probing a recorded **process PID** with `process.kill(pid, 0)` and by
|
|
821
|
+
comparing a local-filesystem mtime against a TTL. Because a PID is only
|
|
822
|
+
meaningful on the machine that owns it and `.git/` is never committed,
|
|
823
|
+
**these locks coordinate only the worktrees and sessions on a single
|
|
824
|
+
machine/clone. They do NOT coordinate across clones.** Two operators on
|
|
825
|
+
two separate clones (or two CI runners) will each acquire their *own*
|
|
826
|
+
merge lock and never see the other's — the locks are invisible to each
|
|
827
|
+
other. The only cross-clone safety the merge step itself has is the
|
|
828
|
+
bounded push-retry described above, which recovers from the
|
|
829
|
+
non-fast-forward rejection *after* the race has already happened.
|
|
830
|
+
|
|
831
|
+
**The assignee-as-lease is the cross-clone layer.** To stop two clones
|
|
832
|
+
from both *starting* to drive the same Epic or Story, the framework takes
|
|
833
|
+
an exclusive, time-bounded claim on the ticket via
|
|
834
|
+
[`ticket-lease.js`](../scripts/lib/orchestration/ticket-lease.js). The lease
|
|
835
|
+
rides the ticket's GitHub `assignees` field — a substrate every clone can
|
|
836
|
+
read — so a live foreign claim is visible to, and refuses, a second
|
|
837
|
+
operator regardless of which machine they are on. All three delivery and
|
|
838
|
+
planning entry points take the claim: `/epic-plan` acquires the Epic lease
|
|
839
|
+
before Phase 7 (spec) and releases it after Phase 8 (decompose),
|
|
840
|
+
`/epic-deliver` acquires the Epic lease in its prepare guard, and
|
|
841
|
+
`/single-story-deliver` acquires the Story lease at init. For
|
|
842
|
+
`/epic-deliver` and `/single-story-deliver`, liveness is decided by the
|
|
843
|
+
owner's most-recent `story.heartbeat` against `delivery.lease.ttlMs`;
|
|
844
|
+
because planning emits no `story.heartbeat`, `/epic-plan` has no
|
|
845
|
+
live-heartbeat source and treats **any** foreign assignee as a live claim.
|
|
846
|
+
A live foreign claim fails the preflight closed (refuse-and-exit, naming
|
|
847
|
+
the owner); `--steal` is the only override. See
|
|
848
|
+
[`README.md` § Multi-developer coordination](../README.md#multi-developer-coordination)
|
|
849
|
+
for the full lease behaviour table.
|
|
850
|
+
|
|
851
|
+
The two layers are complementary, not redundant: the lease prevents two
|
|
852
|
+
clones from racing in the first place, while the same-machine merge lock
|
|
853
|
+
serialises the parallel-wave story closures *within* the one clone that
|
|
854
|
+
holds the lease.
|
|
855
|
+
|
|
856
|
+
### Close-tail (`delivery.close-validation` through `delivery.complete` of `/epic-deliver`)
|
|
857
|
+
|
|
858
|
+
After the wave loop returns `complete`, `/epic-deliver` runs the
|
|
859
|
+
remaining phases against the Epic branch — close-validation, audit,
|
|
860
|
+
code-review, retro, and finalize — before handing off to the
|
|
861
|
+
watch / auto-merge / cleanup tail that drives the PR to merge:
|
|
862
|
+
|
|
863
|
+
1. **Close-validation (Phase 3).** Lint + test + project-extended ratchets
|
|
864
|
+
(maintainability, CRAP, lint baseline) run via `evidence-gate.js` keyed
|
|
865
|
+
on `git rev-parse HEAD`. A clean tree on a re-run short-circuits in
|
|
866
|
+
milliseconds. A failing gate halts the workflow until the regression is
|
|
867
|
+
fixed on a hotfix branch and re-merged into the Epic.
|
|
868
|
+
2. **Audit (Phase 4).** The change-set audit lenses run against the Epic
|
|
869
|
+
diff; findings flow through as advisory signal to inform the code
|
|
870
|
+
review that follows.
|
|
871
|
+
3. **Code-review (Phase 5).** `lib/orchestration/code-review.js` (extracted
|
|
872
|
+
from the `code-review.md` helper) audits the diff and posts the
|
|
873
|
+
findings as a `code-review` structured comment on the Epic. 🔴 Critical
|
|
874
|
+
findings halt the run; 🟠/🟡/🟢 findings flow through as non-blocking.
|
|
875
|
+
4. **Retro (Phase 6).** `lib/orchestration/retro-runner.js` (extracted from the old
|
|
876
|
+
retro helper) aggregates perf signals, friction counts, hotfix counts,
|
|
877
|
+
recut counts, parked counts, and HITL count using
|
|
878
|
+
`retro-heuristics.js`. The structured retro comment is posted on the
|
|
879
|
+
Epic. The retro fires **before** the PR opens — this keeps it inside
|
|
880
|
+
the operator's local session with full env access (env vars,
|
|
881
|
+
credentials, MCP servers); pushing it after PR-open would deny it
|
|
882
|
+
that access. After the GitHub upsert succeeds, the retro body is
|
|
883
|
+
also **mirrored locally** to the per-Epic temp tree at
|
|
884
|
+
`temp/epic-<id>/retro.md` (path resolved via
|
|
885
|
+
[`lib/config/temp-paths.js`](../scripts/lib/config/temp-paths.js)'s
|
|
886
|
+
`epicRetroMirrorPath`) so operators can read the retro without
|
|
887
|
+
re-fetching from GitHub. GitHub remains the source of truth; the
|
|
888
|
+
mirror write is best-effort and a failure only logs a warn.
|
|
889
|
+
5. **Finalize (Phase 7).** `/epic-deliver` fires `epic.close.end` via
|
|
890
|
+
`lifecycle-emit.js`; the `AcceptanceReconciler` → `Finalizer`
|
|
891
|
+
listener chain owns every close-time side effect end to end
|
|
892
|
+
(Story #2894 — bus-owned finalize). The chain runs three
|
|
893
|
+
responsibilities in order:
|
|
894
|
+
1. **Acceptance-spec reconciliation.** Invokes
|
|
895
|
+
`acceptance-spec-reconciler.js` to diff the AC IDs declared in
|
|
896
|
+
the linked `context::acceptance-spec` body against `@ac-*` /
|
|
897
|
+
`@pending` tags in `tests/features/**`. A non-OK reconciliation
|
|
898
|
+
throws (per `.agents/rules/orchestration-error-handling.md`),
|
|
899
|
+
aborting finalize **before** the planning artifacts are closed —
|
|
900
|
+
so the PRD / Tech Spec / Acceptance Spec stay open until the AC
|
|
901
|
+
coverage gap is fixed. Skipped (`status: 'waived'`) when the Epic
|
|
902
|
+
carries `acceptance::n-a`.
|
|
903
|
+
2. **PR open (bus-owned, Story #2894).** On
|
|
904
|
+
`acceptance.reconcile.ok`, the `Finalizer` listener invokes
|
|
905
|
+
`openOrLocatePr({ epicId, headBranch: 'epic/<id>', baseBranch:
|
|
906
|
+
'main' })`. The helper probes for an existing open PR on the
|
|
907
|
+
head branch first (idempotent locate path) and only runs
|
|
908
|
+
`gh pr create` when the head branch has no open PR. The
|
|
909
|
+
Finalizer does **not** arm auto-merge — it emits
|
|
910
|
+
`epic.merge.ready` carrying `{ prNumber, epicId, prUrl }` and
|
|
911
|
+
hands off to the auto-merge gate. The sole production caller
|
|
912
|
+
authorised to shell `gh pr merge` in the entire codebase is
|
|
913
|
+
the `AutomergeArmer` listener at the `delivery.automerge` state
|
|
914
|
+
(enforced by the merge-lockout rule in
|
|
915
|
+
`.agents/scripts/check-lifecycle-lint.js`); the
|
|
916
|
+
`delivery.finalize` state never shells the merge command.
|
|
917
|
+
3. **Planning-artifact close + hand-off (bus-owned, Story #2894).**
|
|
918
|
+
The `Finalizer` chains `closePlanningTickets({ epicId,
|
|
919
|
+
provider })` to close the three planning context tickets
|
|
920
|
+
(`context::prd`, `context::tech-spec`,
|
|
921
|
+
`context::acceptance-spec`) so the Epic's `Closes #<id>`
|
|
922
|
+
auto-close path is not blocked by open sub-issues, then
|
|
923
|
+
`postHandoffComment({ epicId, prNumber, prUrl, provider })` to
|
|
924
|
+
upsert the canonical `epic-handoff` structured comment naming
|
|
925
|
+
the PR. Both helpers are idempotent — re-running finalize
|
|
926
|
+
after a crash counts already-closed tickets under
|
|
927
|
+
`alreadyClosed` and edits the existing handoff comment in
|
|
928
|
+
place rather than appending a duplicate. The Epic stays at
|
|
929
|
+
`agent::executing` until the PR merges.
|
|
930
|
+
6. **Watch-and-iterate (Phase 8).** `/epic-deliver` watches the open PR's
|
|
931
|
+
required checks until they turn green. Transient failures trigger an
|
|
932
|
+
automated re-run loop; durable failures surface for human remediation
|
|
933
|
+
on the Epic branch.
|
|
934
|
+
7. **Auto-merge (Phase 8.5).** Once the watch loop reports all required
|
|
935
|
+
checks passing, the auto-merge gate arms GitHub native auto-merge via
|
|
936
|
+
`gh pr merge --auto --squash --delete-branch` so the PR lands without
|
|
937
|
+
a second operator visit.
|
|
938
|
+
8. **Cleanup (Phase 9).** After the PR merges, the cleanup phase reaps
|
|
939
|
+
local Story/Epic branch refs and any lingering worktrees so the
|
|
940
|
+
workspace returns to a clean state for the next Epic.
|
|
941
|
+
|
|
942
|
+
`/epic-deliver` exits cleanly once auto-merge is armed (or sooner if the
|
|
943
|
+
operator declines auto-merge). The operator can merge through the GitHub UI
|
|
944
|
+
at any time; the `delivery.complete` state handles the post-merge branch reap.
|
|
945
|
+
|
|
946
|
+
---
|
|
947
|
+
|
|
948
|
+
## HITL (Human-in-the-Loop) model
|
|
949
|
+
|
|
950
|
+
On the happy path there is exactly **one** mandatory operator touchpoint
|
|
951
|
+
after `/epic-deliver` fires (blocker resolution). PR merge is autonomous
|
|
952
|
+
via armed auto-merge; the operator can opt in as a second touchpoint by
|
|
953
|
+
disarming auto-merge in the GitHub UI, or is pulled in by exception when
|
|
954
|
+
required checks fail.
|
|
955
|
+
|
|
956
|
+
1. **Blocker resolution (mandatory when triggered).** If the orchestrator
|
|
957
|
+
hits an unresolvable condition, `BlockerHandler` flips the Epic to
|
|
958
|
+
`agent::blocked`, posts a structured friction comment, fires the
|
|
959
|
+
notification webhook (fire-and-forget), and halts wave N+1 (letting
|
|
960
|
+
wave N's in-flight stories finish naturally). The operator resolves
|
|
961
|
+
the underlying issue (e.g. a hand-fix commit on the Story branch or a
|
|
962
|
+
scope edit on the blocking ticket), then flips the Epic back to
|
|
963
|
+
`agent::executing` to resume.
|
|
964
|
+
2. **PR merge (autonomous by default; operator-gated by exception).** At
|
|
965
|
+
the end of `/epic-deliver`, the workflow opens a PR to `main` and
|
|
966
|
+
arms GitHub native auto-merge (the `delivery.automerge` state). When required checks pass,
|
|
967
|
+
the PR lands without a second operator visit; the standard
|
|
968
|
+
label-transition pathway flips the Epic to `agent::done` on merge.
|
|
969
|
+
The operator becomes a touchpoint here only when they (a) disarm
|
|
970
|
+
auto-merge in the GitHub UI to inspect required-checks, the
|
|
971
|
+
`code-review` comment, and the retro before merging by hand, or
|
|
972
|
+
(b) checks fail and need remediation on the Epic branch. There is
|
|
973
|
+
no separate close command — the close-out side effects (PR open,
|
|
974
|
+
planning-ticket close, handoff comment) are owned by `/epic-deliver`'s
|
|
975
|
+
`delivery.finalize` state (the lifecycle Finalizer listener), whose
|
|
976
|
+
replay is idempotent.
|
|
977
|
+
|
|
978
|
+
### What triggers `agent::blocked`
|
|
979
|
+
|
|
980
|
+
- Unresolvable merge conflict that automated strategies cannot reconcile.
|
|
981
|
+
- Test failures that persist after one automated remediation attempt.
|
|
982
|
+
- Ambiguity in a ticket requiring a product/scope decision the orchestrator
|
|
983
|
+
cannot make from ticket context alone.
|
|
984
|
+
- A destructive action not pre-authorized by the ticket body (e.g. dropping a
|
|
985
|
+
table, deleting user data, force-pushing to a protected branch).
|
|
986
|
+
- External service failure preventing progress (GitHub API 5xx loop, npm
|
|
987
|
+
registry down).
|
|
988
|
+
- Wave concurrency exhausted for an unbounded time (possible deadlock).
|
|
989
|
+
|
|
990
|
+
### What is *not* gated at runtime
|
|
991
|
+
|
|
992
|
+
- `risk::high` tasks **run without pause.** The label remains as planning
|
|
993
|
+
metadata and retro telemetry, but it does **not** halt the dispatcher
|
|
994
|
+
or `/epic-deliver`. Branch protection on `main` and
|
|
995
|
+
`BlockerHandler`-driven escalation are the runtime defenses for
|
|
996
|
+
destructive actions.
|
|
997
|
+
- Wave boundaries — the runner advances as soon as wave N completes.
|
|
998
|
+
- Individual story completion — no per-story approval prompt.
|
|
999
|
+
|
|
1000
|
+
> [!NOTE] Legacy `risk::high` runtime gating has been retired. `risk::high`
|
|
1001
|
+
> remains planning/audit metadata only; the sole runtime pause point is
|
|
1002
|
+
> `agent::blocked`.
|
|
1003
|
+
|
|
1004
|
+
---
|
|
1005
|
+
|
|
1006
|
+
## Epic Deliver Runner internals
|
|
1007
|
+
|
|
1008
|
+
`/epic-deliver` drives the long-running coordinator inside the operator's
|
|
1009
|
+
Claude session. The slash command composes the submodules listed below;
|
|
1010
|
+
`helpers/epic-deliver-story` is launched as an Agent-tool sub-agent of
|
|
1011
|
+
`/epic-deliver`'s wave loop — no subprocess worker sessions for Story
|
|
1012
|
+
execution, no GitHub Actions runner. Deterministic Node CLIs remain the
|
|
1013
|
+
state-mutation contract.
|
|
1014
|
+
|
|
1015
|
+
| Submodule | Role |
|
|
1016
|
+
| ------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
1017
|
+
| `wave-scheduler` | Iterates waves from `Graph.computeWaves()`. |
|
|
1018
|
+
| `story-launcher` | Fans out up to `concurrencyCap` Agent-tool Story sub-agents per wave. |
|
|
1019
|
+
| `checkpointer` | Upserts the `epic-run-state` structured comment; handles phase-granular resume across all six phases. |
|
|
1020
|
+
| `blocker-handler` | The sole runtime pause point — halts on `agent::blocked`. |
|
|
1021
|
+
| `notification-hook` | Fire-and-forget webhook for blocker / wave-transition events. |
|
|
1022
|
+
| `wave-observer` | Emits `wave-N-start` / `wave-N-end` comments and reads each Story's `story-run-progress` snapshot. |
|
|
1023
|
+
| `column-sync` | Syncs the Projects v2 Status column from `agent::` labels. |
|
|
1024
|
+
| `code-review` | `lib/orchestration/code-review.js` — `delivery.code-review` inline audit; halts on critical findings. |
|
|
1025
|
+
| `retro-runner` | `lib/orchestration/retro-runner.js` — `delivery.retro` authoring; posts structured retro comment. |
|
|
1026
|
+
|
|
1027
|
+
### Claude Max quota
|
|
1028
|
+
|
|
1029
|
+
`/epic-deliver` consumes Max subscription quota (5-hour rolling window with
|
|
1030
|
+
overage disabled at the org level by default). If a long Epic exceeds the
|
|
1031
|
+
5-hour window, `BlockerHandler` surfaces the rate-limit error as
|
|
1032
|
+
`agent::blocked` so you can resume after the quota rolls.
|
|
1033
|
+
|
|
1034
|
+
### Skipping CI/CD on orchestrator commits
|
|
1035
|
+
|
|
1036
|
+
The orchestrator pushes many commits during a run, each potentially triggering
|
|
1037
|
+
the project's `CI / CD` workflow. Two mitigations:
|
|
1038
|
+
|
|
1039
|
+
- Add `[skip ci]` to orchestrator commit messages (requires a small tweak in
|
|
1040
|
+
`story-close.js`), OR
|
|
1041
|
+
- Add a `paths-ignore` or branch filter to `ci.yml` that excludes `epic/*` and
|
|
1042
|
+
`story-*` branches. Only `main` pushes trigger CI.
|
|
1043
|
+
|
|
1044
|
+
---
|
|
1045
|
+
|
|
1046
|
+
## Phase 4: PR merge (auto by default)
|
|
1047
|
+
|
|
1048
|
+
Once the wave loop, close-validation, code-review, and retro have all
|
|
1049
|
+
completed, `/epic-deliver` opens a pull request from `epic/<epicId>` to
|
|
1050
|
+
`main` and arms GitHub native auto-merge. When the required checks pass
|
|
1051
|
+
the PR lands without further intervention; the operator can disarm
|
|
1052
|
+
auto-merge in the GitHub UI to make the final merge an explicit human
|
|
1053
|
+
action.
|
|
1054
|
+
|
|
1055
|
+
1. **Story merging.** Stories merge into `epic/<epicId>` automatically
|
|
1056
|
+
during Story closure (`story-close.js`). The Epic branch is the rolling
|
|
1057
|
+
integration target.
|
|
1058
|
+
2. **Completion cascade.** When the last Task in a Story reaches
|
|
1059
|
+
`agent::done`, status cascades upward:
|
|
1060
|
+
|
|
1061
|
+
```text
|
|
1062
|
+
Task Done → Story Done → Feature Done
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
Epics, PRDs, and Tech Specs are explicitly excluded from auto-cascade —
|
|
1066
|
+
the Epic only flips to `agent::done` when the operator merges the PR
|
|
1067
|
+
to `main`.
|
|
1068
|
+
|
|
1069
|
+
3. **PR merge — the sole promotion gate.** When the PR merges (auto or
|
|
1070
|
+
manual):
|
|
1071
|
+
- the Epic-to-`main` merge lands as a real PR merge with a real
|
|
1072
|
+
reviewer-trail and required-checks history;
|
|
1073
|
+
- the standard label-transition pathway flips the Epic to
|
|
1074
|
+
`agent::done`;
|
|
1075
|
+
- branch cleanup runs out-of-band: the `delivery.complete` state of
|
|
1076
|
+
`/epic-deliver` reaps local refs after the merge; the rare "scrap
|
|
1077
|
+
and reset" case for an unmerged Epic is handled manually.
|
|
1078
|
+
|
|
1079
|
+
If the operator chooses not to merge (rolling back, deferring, re-scoping),
|
|
1080
|
+
`/epic-deliver` has not poisoned `main`. The Epic branch can be amended
|
|
1081
|
+
in place; re-running `/epic-deliver <epicId>` re-runs the
|
|
1082
|
+
`delivery.close-validation` / `delivery.audit` / `delivery.code-review`
|
|
1083
|
+
states against the new HEAD (the evidence wrapper picks up the new SHA) and
|
|
1084
|
+
updates the same PR — no duplicate PRs are opened against the same Epic
|
|
1085
|
+
branch.
|
|
1086
|
+
|
|
1087
|
+
---
|
|
1088
|
+
|
|
1089
|
+
## Testing strategy
|
|
1090
|
+
|
|
1091
|
+
Tests are **pyramid-aware**. Every test written during Story delivery
|
|
1092
|
+
belongs to exactly one tier — **unit**, **contract**, or **e2e / acceptance** —
|
|
1093
|
+
and each tier has distinct scope, dependency, and assertion rules. The canonical
|
|
1094
|
+
tier definitions, assertion-placement rules, and coverage thresholds live in
|
|
1095
|
+
[`rules/testing-standards.md`](../rules/testing-standards.md); Gherkin authoring
|
|
1096
|
+
for the acceptance tier is governed by
|
|
1097
|
+
[`rules/gherkin-standards.md`](../rules/gherkin-standards.md).
|
|
1098
|
+
|
|
1099
|
+
The acceptance tier is executed and reported via
|
|
1100
|
+
[`workflows/qa-run-harness.md`](../workflows/qa-run-harness.md) and consumed as
|
|
1101
|
+
epic evidence by
|
|
1102
|
+
[`workflows/helpers/epic-testing.md`](../workflows/helpers/epic-testing.md).
|
|
1103
|
+
|
|
1104
|
+
### QA workflows: explore, assist, and run-harness
|
|
1105
|
+
|
|
1106
|
+
Three complementary QA workflows sit alongside the automated test pyramid, all
|
|
1107
|
+
adopting the `qa-engineer` persona and all reading the consumer's `qa.*`
|
|
1108
|
+
project contract from `.agentrc.json`. The first two are exploratory siblings
|
|
1109
|
+
that differ on **who drives** the session; the third steps a known scenario
|
|
1110
|
+
set:
|
|
1111
|
+
|
|
1112
|
+
- **[`workflows/qa-explore.md`](../workflows/qa-explore.md)** (`/qa-explore`) — an
|
|
1113
|
+
**agent-led**, open-ended **Plan → Capture → Triage** exploratory sweep.
|
|
1114
|
+
The operator names a surface; the **agent drives** it (through the browser
|
|
1115
|
+
MCP by default, or statically as a documented interim), probing for product
|
|
1116
|
+
bugs, environment-setup friction, tooling/DX gaps, missing tests, and
|
|
1117
|
+
enhancement ideas. Each observation is recorded as a `QaLedgerItem` against
|
|
1118
|
+
[`schemas/qa-ledger.schema.json`](../schemas/qa-ledger.schema.json) and appended
|
|
1119
|
+
to a **session ledger** at `temp/qa/<sessionId>.ndjson` (one item per ndjson
|
|
1120
|
+
line, under `project.paths.tempRoot`, gitignored, never committed). Capture
|
|
1121
|
+
is strictly **read-only** — the ledger append is its only write — so every
|
|
1122
|
+
state-changing action (filing a follow-up ticket, mutating a label) lands in
|
|
1123
|
+
Triage, and only after explicit operator confirmation. The session is
|
|
1124
|
+
HITL-gated: every phase transition is operator-gated. Deterministic Node
|
|
1125
|
+
helpers under `scripts/lib/qa/` (session resolution, evidence redaction,
|
|
1126
|
+
coverage verdict, missing-test proposal) and `scripts/lib/findings/`
|
|
1127
|
+
(classification, dedup/route — the same dedup implementation shared with
|
|
1128
|
+
`audit-to-stories`) make the decisions; the agent never re-derives them in
|
|
1129
|
+
prose. A resumed session appends and carries its un-triaged backlog forward
|
|
1130
|
+
as a rolling backlog.
|
|
1131
|
+
- **[`workflows/qa-assist.md`](../workflows/qa-assist.md)** (`/qa-assist`) — the
|
|
1132
|
+
**human-led** sibling of `/qa-explore`: a single-observation
|
|
1133
|
+
**Intake → Enrich → Record** loop. Here the **human drives** — the operator
|
|
1134
|
+
reports one observation they hit (a bug, a flaky behavior, a "this feels
|
|
1135
|
+
off") and the agent enriches it into a triage-ready `QaLedgerItem` (a clean
|
|
1136
|
+
repro, a `file:line` root-cause locus, a coverage verdict), asking clarifying
|
|
1137
|
+
questions when the observation is ambiguous, then appends it — after explicit
|
|
1138
|
+
operator confirmation — to a persistent, resumable rolling session under
|
|
1139
|
+
`temp/qa/`. It produces the **same** ledger contract `/qa-explore` writes
|
|
1140
|
+
(`qa-ledger.schema.json`) and reuses the same `scripts/lib/qa/` and
|
|
1141
|
+
`scripts/lib/findings/` decision seams, so a `/qa-assist` item flows through
|
|
1142
|
+
the identical dedup, classification, and promotion machinery later.
|
|
1143
|
+
- **[`workflows/qa-run-harness.md`](../workflows/qa-run-harness.md)**
|
|
1144
|
+
(`/qa-run-harness`) — the **automated complement**: it steps a *known* set of
|
|
1145
|
+
Gherkin `.feature` scenarios through a real browser, asserting `Then`
|
|
1146
|
+
outcomes semantically against the accessibility snapshot and bundling
|
|
1147
|
+
console/network problems into structured `F#` findings for operator sign-off.
|
|
1148
|
+
|
|
1149
|
+
All three workflows resolve the `qa.*` contract through the single seam
|
|
1150
|
+
[`scripts/lib/qa/resolve-qa-contract.js`](../scripts/lib/qa/resolve-qa-contract.js).
|
|
1151
|
+
The block is **optional in the schema** (so config validation never breaks a
|
|
1152
|
+
non-QA consumer) but enforced at run time: the resolver fails **loudly** with
|
|
1153
|
+
"this project has not bound the QA harness" when no `qa` block is present —
|
|
1154
|
+
there is no silent fallback. The contract's four required keys are
|
|
1155
|
+
`qa.featureRoot` (the `.feature` discovery root), `qa.fixturesManifest`
|
|
1156
|
+
(persona → seed-data binding), `qa.signInSeam` (the dev-only sign-in seam,
|
|
1157
|
+
either `{ urlTemplate }` or `{ skill }`), and `qa.personas` (the persona set,
|
|
1158
|
+
authored as a name-only array under a url-template seam or as a per-persona
|
|
1159
|
+
credential/skill map under a skill seam); the two optional keys
|
|
1160
|
+
`qa.consoleAllowlist` and `qa.designTokens` default to `[]` and `null`.
|
|
1161
|
+
Consumer adoption steps are in
|
|
1162
|
+
[`README.md` § Adopting the QA harness](../README.md#adopting-the-qa-harness).
|
|
1163
|
+
|
|
1164
|
+
---
|
|
1165
|
+
|
|
1166
|
+
## Static analysis & audit orchestration
|
|
1167
|
+
|
|
1168
|
+
An automated, gate-based static-analysis and audit orchestration pipeline
|
|
1169
|
+
replaces manual auditing with a CLI-driven system.
|
|
1170
|
+
|
|
1171
|
+
### Audit triggering
|
|
1172
|
+
|
|
1173
|
+
Audits are selectively invoked by the orchestrator at four Epic lifecycle
|
|
1174
|
+
gates (`gate1` through `gate4`). The audit orchestrator
|
|
1175
|
+
(`lib/dynamic-workflow/audit-orchestrator.js`) evaluates rules
|
|
1176
|
+
defined in `.agents/schemas/audit-rules.json` (schema:
|
|
1177
|
+
`.agents/schemas/audit-rules.schema.json`) based on:
|
|
1178
|
+
|
|
1179
|
+
1. **Gate configuration** — which gate is currently firing.
|
|
1180
|
+
2. **Contextual keywords** — the Epic or Task body contents (e.g., `auth` or
|
|
1181
|
+
`encrypt` triggers security audits).
|
|
1182
|
+
3. **File patterns** — which files changed compared to the base branch (e.g.,
|
|
1183
|
+
`user-profile` files trigger privacy audits).
|
|
1184
|
+
|
|
1185
|
+
### Epic lifecycle gates
|
|
1186
|
+
|
|
1187
|
+
The matrix lists every quality gate the framework fires during an Epic
|
|
1188
|
+
run. **Blocking?** is `blocking` when a non-OK result aborts the
|
|
1189
|
+
workflow, `advisory` when findings are surfaced but execution proceeds.
|
|
1190
|
+
**Idempotency key** names the on-disk or in-ticket marker the gate keys
|
|
1191
|
+
on so re-runs short-circuit when state has not changed.
|
|
1192
|
+
|
|
1193
|
+
| Gate | When | What Runs | Blocking? | Idempotency key |
|
|
1194
|
+
| ------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------ |
|
|
1195
|
+
| Gate 1 | After Story completion | Content-triggered audits (clean-code, etc.) | advisory | Audit-report comment per Story (`audit-<lens>` structured comment) |
|
|
1196
|
+
| Gate 2 | Pre-integration | Dependency + DevOps audits | advisory | Audit-report comment per Epic (`audit-<lens>` structured comment) |
|
|
1197
|
+
| Gate 3 | `/epic-deliver` `delivery.code-review` state | Full automated audit pass | blocking | `code-review` structured comment on Epic, keyed by Epic HEAD SHA |
|
|
1198
|
+
| Gate 4 | `/epic-deliver` `delivery.finalize` state (pre-PR) | `audit-sre` production readiness gate | blocking | `audit-sre` structured comment on Epic, keyed by Epic HEAD SHA |
|
|
1199
|
+
| Close-validation | `/epic-deliver` `delivery.close-validation` state | lint + test + maintainability + CRAP + coverage ratchets via `evidence-gate.js` | blocking | `evidence-gate` cache entry keyed by `git rev-parse HEAD` |
|
|
1200
|
+
| Pre-push | Local `.husky/pre-push` hook on every push | Diff-scoped quality preview + coverage/CRAP ratchet | blocking | Working-tree SHA + staged-diff hash (per push) |
|
|
1201
|
+
| Acceptance reconciliation | `/epic-deliver` `delivery.finalize` state | `acceptance-spec-reconciler.js` diffs AC IDs against `@ac-*` / `@pending` feature tags | blocking | `acceptance-reconcile` structured comment on Epic, keyed by spec-body SHA |
|
|
1202
|
+
| Spec freshness | `/epic-plan` `planning.spec-authoring` state | Re-derives PRD / Tech Spec / Acceptance Spec staleness against Epic body checksum | advisory | `epic-plan-state` checkpoint entry per spec artifact body SHA |
|
|
1203
|
+
|
|
1204
|
+
### Review & feedback loop
|
|
1205
|
+
|
|
1206
|
+
When audits produce findings, the orchestrator compiles a structured Markdown
|
|
1207
|
+
report and posts it as a ticket comment via the `ITicketingProvider`.
|
|
1208
|
+
|
|
1209
|
+
- **Maintainability ratchet.** The orchestrator enforces code quality by relying
|
|
1210
|
+
on maintainability checks (`check-maintainability.js`), which fail if the
|
|
1211
|
+
composite score drops below the established baseline.
|
|
1212
|
+
- **CRAP gate.** Sibling per-method gate (`check-crap.js`) wired
|
|
1213
|
+
into `close-validation` after `check-maintainability`, the `ci.yml` step
|
|
1214
|
+
after `test:coverage`, and `.husky/pre-push`. Tracks complexity × coverage
|
|
1215
|
+
risk per method against `baselines/crap.json`. Self-skips when
|
|
1216
|
+
`delivery.quality.gates.crap.enabled` is `false`. The
|
|
1217
|
+
`baseline-refresh:`-tagged commit convention for baseline edits is the
|
|
1218
|
+
project standard; the operator is the gate during `/epic-deliver`
|
|
1219
|
+
`delivery.finalize` state (the prior CI guardrail that enforced the tag was removed).
|
|
1220
|
+
- **Human review on High/Critical.** If High or Critical findings are detected,
|
|
1221
|
+
the workflow halts for human review at the corresponding `/epic-deliver`
|
|
1222
|
+
phase. Approval is given by the operator advancing the phase (the
|
|
1223
|
+
auto-approve webhook listener was never wired into CI and was removed during the rebrand).
|
|
1224
|
+
- **Implementation.** Once the operator approves the fixes, the ticket
|
|
1225
|
+
transitions to `agent::executing` and `/epic-deliver` dispatches an agent to
|
|
1226
|
+
implement and verify them.
|
|
1227
|
+
|
|
1228
|
+
---
|
|
1229
|
+
|
|
1230
|
+
## Notification system
|
|
1231
|
+
|
|
1232
|
+
Two independent notification surfaces, both living in `.agents/` so they ship to
|
|
1233
|
+
consuming projects:
|
|
1234
|
+
|
|
1235
|
+
### 1. Unified `notify()` dispatcher
|
|
1236
|
+
|
|
1237
|
+
Every notification — whether a manual orchestration milestone (story merged,
|
|
1238
|
+
HITL gate triggered) or an auto-fired ticket-state transition — routes through
|
|
1239
|
+
[`notify.js`](../scripts/notify.js). Two delivery channels:
|
|
1240
|
+
|
|
1241
|
+
| Channel | What it does |
|
|
1242
|
+
| ----------------- | ------------------------------------------------------------------------- |
|
|
1243
|
+
| GitHub comment | Posts to the targeted ticket; @mentions operator for `medium`/`high`. |
|
|
1244
|
+
| Webhook | Fire-and-forget POST to the configured URL (Make.com / Slack / Discord). |
|
|
1245
|
+
|
|
1246
|
+
Severity vocabulary (assigned by callers; `eventSeverity()` in
|
|
1247
|
+
`lib/notifications/notifier.js` derives it for state transitions):
|
|
1248
|
+
|
|
1249
|
+
| Severity | Used for | Webhook prefix |
|
|
1250
|
+
| -------- | --------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
1251
|
+
| `low` | Task transitions, `story-run-progress` upserts, intermediate state transitions, audit reports. | `[low]` |
|
|
1252
|
+
| `medium` | Operator-visible milestones: Story state transitions, `wave-run-progress`, `epic-run-progress`, story merged, epic complete. | `[medium]` |
|
|
1253
|
+
| `high` | Operator must act (HITL gates, epic blockers, autonomous-chain failures). Message body should also lead with `🚨 Action Required:`. | `[Action Required]` |
|
|
1254
|
+
|
|
1255
|
+
Two independent event-allowlist knobs in `github.notifications`
|
|
1256
|
+
(both mandatory):
|
|
1257
|
+
|
|
1258
|
+
- `commentEvents` — event-name allowlist for GitHub-ticket comment
|
|
1259
|
+
posting. Default:
|
|
1260
|
+
`["state-transition", "story-merged", "operator-message"]`.
|
|
1261
|
+
- `webhookEvents` — event-name allowlist for `NOTIFICATION_WEBHOOK_URL`
|
|
1262
|
+
deliveries. Default:
|
|
1263
|
+
`["epic-started", "epic-progress", "epic-blocked", "epic-unblocked", "epic-complete"]`.
|
|
1264
|
+
|
|
1265
|
+
Each channel filters independently; there is no fallback chain.
|
|
1266
|
+
Severity is carried as envelope metadata (and still drives `@mention`
|
|
1267
|
+
behavior on the comment channel — high always @mentions, medium
|
|
1268
|
+
@mentions when `mentionOperator: true`) but is no longer a routing
|
|
1269
|
+
factor for either channel. `transitionTicketState` suppresses the
|
|
1270
|
+
`notify()` dispatch entirely for low-severity transitions (task-level,
|
|
1271
|
+
non-terminal story / epic flips) so the comment channel sees only the
|
|
1272
|
+
medium-severity story-level events operators expect on the ticket
|
|
1273
|
+
timeline. To suppress either channel entirely, set its array to `[]`.
|
|
1274
|
+
The schema enums pin closed vocabularies — adding custom event names
|
|
1275
|
+
requires loosening the enum in `.agents/scripts/lib/config-schema.js`.
|
|
1276
|
+
|
|
1277
|
+
Webhook URL resolution:
|
|
1278
|
+
|
|
1279
|
+
- `NOTIFICATION_WEBHOOK_URL` process env var only — loaded from `.env` at the
|
|
1280
|
+
project root. The webhook URL is **not** sourced from `.agentrc.json`, and
|
|
1281
|
+
(as of Epic #702) is no longer sourced from `.mcp.json`.
|
|
1282
|
+
|
|
1283
|
+
Because `notify()` is called in-band from the orchestration SDK, it captures
|
|
1284
|
+
changes from:
|
|
1285
|
+
|
|
1286
|
+
- The Epic Deliver Runner (coordinator-driven state flips).
|
|
1287
|
+
- Per-story scripts (`story-init.js`, `story-close.js`).
|
|
1288
|
+
- Any script that routes state changes through `transitionTicketState`.
|
|
1289
|
+
|
|
1290
|
+
It does **not** capture manual label clicks in the GitHub UI (no webhook
|
|
1291
|
+
receiver). For programmatic orchestration workflows this covers >95% of
|
|
1292
|
+
lifecycle transitions.
|
|
1293
|
+
|
|
1294
|
+
### 2. Deliver-runner blocker / HITL notifications
|
|
1295
|
+
|
|
1296
|
+
The `NotificationHook` inside the Epic Deliver Runner fires on
|
|
1297
|
+
blocker-escalation events (`agent::blocked`) and operator-attention events
|
|
1298
|
+
(PR-open hand-off, run cancellation). Fire-and-forget by design; webhook
|
|
1299
|
+
failures never block execution.
|
|
1300
|
+
|
|
1301
|
+
| Event | Type | Channel | Operator Action |
|
|
1302
|
+
| ------------------ | ---------- | ------------------ | ---------------------- |
|
|
1303
|
+
| `task-complete` | **INFO** | @mention | Review when convenient |
|
|
1304
|
+
| `feature-complete` | **INFO** | @mention | Informational only |
|
|
1305
|
+
| `epic-complete` | **INFO** | @mention + webhook | Final review |
|
|
1306
|
+
| `pr-opened` | **ACTION** | @mention + webhook | Inspect checks + merge |
|
|
1307
|
+
| `epic-blocked` | **ACTION** | webhook | Resolve and re-flip |
|
|
1308
|
+
| `wave-transition` | **INFO** | webhook | Informational only |
|
|
1309
|
+
|
|
1310
|
+
---
|
|
1311
|
+
|
|
1312
|
+
## Troubleshooting
|
|
1313
|
+
|
|
1314
|
+
### Sub-agent CI workflow editing
|
|
1315
|
+
|
|
1316
|
+
Sub-agents (any agent operating under the framework's default
|
|
1317
|
+
`GITHUB_TOKEN`) **cannot edit files under `.github/workflows/**`**. The
|
|
1318
|
+
framework's token does not carry the `workflows` permission scope by
|
|
1319
|
+
default, so a push that touches a workflow file is rejected by GitHub
|
|
1320
|
+
with an error of the shape:
|
|
1321
|
+
|
|
1322
|
+
> refusing to allow a GitHub App to create or update workflow
|
|
1323
|
+
> `.github/workflows/<file>.yml` without `workflows` permission
|
|
1324
|
+
|
|
1325
|
+
This is a hard constraint, not a transient failure. Re-running the same
|
|
1326
|
+
push will not succeed.
|
|
1327
|
+
|
|
1328
|
+
**When a Story plans a new CI gate**, route the check through a
|
|
1329
|
+
`package.json` script rather than adding it directly to the workflow
|
|
1330
|
+
YAML. Examples:
|
|
1331
|
+
|
|
1332
|
+
- Add the new check to `npm run lint`, `npm run docs:check`, or
|
|
1333
|
+
`npm test` so an existing CI job picks it up by transitivity.
|
|
1334
|
+
- Wire a new `package.json` script and chain it from one of the
|
|
1335
|
+
existing scripts the workflow already invokes.
|
|
1336
|
+
- For a check that genuinely cannot be expressed as an npm script,
|
|
1337
|
+
surface it as a script anyway (e.g. `npm run check:<name>` →
|
|
1338
|
+
`node .agents/scripts/<name>.js`) and call the script from the
|
|
1339
|
+
existing `Validate and Test` job's `run:` block — but the YAML edit
|
|
1340
|
+
itself must be made by an operator.
|
|
1341
|
+
|
|
1342
|
+
Precedent: Epic #2880 Story #2895 Task #2916 intended to add
|
|
1343
|
+
`check-lifecycle-doc-drift.js` directly to `.github/workflows/ci.yml`,
|
|
1344
|
+
hit this constraint, and worked around it by chaining the check into
|
|
1345
|
+
`npm run docs:check`. The functional outcome is identical; the
|
|
1346
|
+
workaround is the canonical pattern.
|
|
1347
|
+
|
|
1348
|
+
**When a workflow file genuinely must change** (a new top-level job, a
|
|
1349
|
+
trigger change, a runner-image bump, etc.), the edit must be made by an
|
|
1350
|
+
operator with `Workflows: Read and write` PAT permissions. See
|
|
1351
|
+
[§ One-time PAT setup](../../AGENTS.md#one-time-pat-setup) in the root
|
|
1352
|
+
`AGENTS.md` for how to provision a PAT with the required scope. The same
|
|
1353
|
+
operator surface that release-please relies on is the one that authorizes
|
|
1354
|
+
workflow edits.
|
|
1355
|
+
|
|
1356
|
+
### Worktree config shadow
|
|
1357
|
+
|
|
1358
|
+
`helpers/epic-deliver-story` and `helpers/single-story-deliver` run inside
|
|
1359
|
+
per-Story worktrees under `.worktrees/story-<id>/`. A git worktree checks out the
|
|
1360
|
+
**Story branch's own copy** of every repo-tracked file — including
|
|
1361
|
+
`.agentrc.json`, `package.json`, `release-please-config.json`, and any
|
|
1362
|
+
other config under version control. **Operator edits made in the main
|
|
1363
|
+
checkout do NOT propagate to an already-active worktree.** The worktree
|
|
1364
|
+
sees the branch's committed contents until the operator either re-edits
|
|
1365
|
+
inside the worktree or merges the change into the Story branch.
|
|
1366
|
+
|
|
1367
|
+
Symptom: you bump a runtime knob in `<main-repo>/.agentrc.json` (e.g.
|
|
1368
|
+
raise `delivery.quality.gates.coverage.timeoutMs`), re-run
|
|
1369
|
+
`story-close.js --cwd <worktree>`, and the script still uses the old
|
|
1370
|
+
value. The script resolved config from the worktree's stale
|
|
1371
|
+
`.agentrc.json`, not the main checkout's edited one. Precedent: Epic
|
|
1372
|
+
\#2880 friction note F-W0-6 (Story \#2896 recovery debugging time).
|
|
1373
|
+
|
|
1374
|
+
When tuning runtime knobs **mid-Story**:
|
|
1375
|
+
|
|
1376
|
+
1. **Prefer an env-var override** when the knob exposes one (e.g.
|
|
1377
|
+
timeouts, log level via `AGENT_LOG_LEVEL`, concurrency caps). Env
|
|
1378
|
+
vars are read from the operator's actual shell, not from the
|
|
1379
|
+
checked-out config, so they bypass worktree shadow entirely.
|
|
1380
|
+
2. **Edit the file inside the worktree** —
|
|
1381
|
+
`.worktrees/<story-id>/.agentrc.json` — so the script sees the bump
|
|
1382
|
+
on its next read. Either commit the change on the Story branch (if
|
|
1383
|
+
the bump is project-wide and should land with the Story) or leave
|
|
1384
|
+
it uncommitted as a scratch tweak that gets discarded when the
|
|
1385
|
+
worktree is reaped.
|
|
1386
|
+
3. **Use `.agentrc.local.json`** for per-machine tuning you never want
|
|
1387
|
+
to commit. The file is gitignored and layered on top of
|
|
1388
|
+
`.agentrc.json` by the config resolver
|
|
1389
|
+
(see [`.agents/docs/configuration.md`](configuration.md#per-machine-local-overrides)).
|
|
1390
|
+
Note: the local override is still read relative to the script's
|
|
1391
|
+
cwd, so for worktree-bound scripts you must place
|
|
1392
|
+
`.agentrc.local.json` inside the worktree directory — or invoke the
|
|
1393
|
+
script with `--cwd <main-repo>` so the resolver reads from the main
|
|
1394
|
+
checkout's local override.
|
|
1395
|
+
|
|
1396
|
+
Editing the main checkout's `.agentrc.json` only affects **the next**
|
|
1397
|
+
`story-init.js` invocation, because new Story branches fork from
|
|
1398
|
+
`main`'s current tip and therefore see the new config from the start.
|
|
1399
|
+
For Stories already in flight, use one of the three options above.
|
|
1400
|
+
|
|
1401
|
+
---
|
|
1402
|
+
|
|
1403
|
+
## Quick reference
|
|
1404
|
+
|
|
1405
|
+
| Command | Purpose |
|
|
1406
|
+
| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1407
|
+
| `npx create-mandrel` | Cold-start launcher — install `mandrel`, `mandrel sync`, then run `bootstrap.js` (provisions repo + Projects V2 board, labels, branch protection). |
|
|
1408
|
+
| `/onboard` | Guided first run after bootstrap — stack detection, docs scaffolding, `mandrel doctor` readiness gate, started `/epic-plan` handoff. |
|
|
1409
|
+
| `/epic-plan` | Ideation entry — sharpen idea, search duplicates, open Epic, then PRD + Tech Spec + decomposition. |
|
|
1410
|
+
| `/epic-plan --idea "<seed>"` | Same ideation entry with pre-supplied seed. |
|
|
1411
|
+
| `/epic-plan <epicId>` | Existing-Epic mode — PRD + Tech Spec + decomposition for an Epic Issue already opened. |
|
|
1412
|
+
| `/epic-deliver <epicId>` | Drive an Epic end-to-end. Wave loop → close-validation → code-review → retro → opens PR to `main` with auto-merge armed. |
|
|
1413
|
+
| `/story-deliver <storyId> [<storyId>...]` | Deliver one or more standalone Stories (no `Epic: #N` reference). Builds a dependency-aware wave plan and fans out one worker per Story per wave. |
|
|
1414
|
+
| `/story-plan` | Plan a one-off Story outside an Epic backlog. |
|
|
1415
|
+
| *helper* `workflows/helpers/epic-deliver-story` | Per-Story worker called by `/epic-deliver`'s wave loop; not an operator slash command. See [`helpers/epic-deliver-story.md`](../workflows/helpers/epic-deliver-story.md). |
|
|
1416
|
+
| *helper* `workflows/helpers/single-story-deliver` | Per-Story worker called by `/story-deliver`; not an operator slash command. See [`helpers/single-story-deliver.md`](../workflows/helpers/single-story-deliver.md). |
|
|
1417
|
+
| *helper* `workflows/helpers/code-review.md` | Auto-invoked by `/epic-deliver`'s `delivery.code-review` state (scope: epic); not a slash command. |
|
|
1418
|
+
| `/git-commit-all` | Stage and commit all changes |
|
|
1419
|
+
| `/git-push` | Stage, commit, and push to remote |
|
|
1420
|
+
| `epic-reconcile.js --explicit-delete` | Hard reset — close orphaned Epic-scoped issues per `.agents/epics/<id>.yaml` |
|