mandrel 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/README.md +59 -28
- package/.agents/agents/acceptance-critic.md +9 -7
- package/.agents/agents/story-worker.md +41 -46
- package/.agents/audit-checklists/performance.md +1 -1
- package/.agents/docs/SDLC.md +51 -44
- package/.agents/docs/agentrc-reference.json +8 -13
- package/.agents/docs/configuration.md +32 -56
- package/.agents/docs/execution-reference.md +39 -10
- package/.agents/docs/quality-gates.md +14 -16
- package/.agents/docs/workflows.md +6 -6
- package/.agents/instructions.md +64 -79
- package/.agents/rules/ci-remediation.md +3 -3
- package/.agents/rules/git-conventions-reference.md +42 -51
- package/.agents/schemas/agentrc.schema.json +34 -45
- package/.agents/schemas/audit-rules.json +59 -1
- package/.agents/schemas/audit-rules.schema.json +33 -1
- package/.agents/schemas/lifecycle/README.md +1 -2
- package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
- package/.agents/schemas/lifecycle/merge.flip-failed.schema.json +33 -0
- package/.agents/schemas/lifecycle/merge.unlanded.schema.json +1 -0
- package/.agents/schemas/lifecycle/story.merged.schema.json +1 -1
- package/.agents/schemas/signal-event.schema.json +3 -3
- package/.agents/schemas/story-deliver-terminal.schema.json +152 -0
- package/.agents/schemas/validation-evidence.schema.json +1 -1
- package/.agents/scripts/acceptance-eval.js +22 -66
- package/.agents/scripts/agents-bootstrap-github.js +1 -1
- package/.agents/scripts/bootstrap.js +3 -3
- package/.agents/scripts/check-dead-exports.js +43 -104
- package/.agents/scripts/check-doc-links.js +2 -2
- package/.agents/scripts/check-lifecycle-lint.js +1 -1
- package/.agents/scripts/check-workflow-cli-lint.js +91 -0
- package/.agents/scripts/deliver-recover.js +122 -0
- package/.agents/scripts/drain-pending-cleanup.js +1 -1
- package/.agents/scripts/evidence-gate.js +20 -50
- package/.agents/scripts/generate-skills-index.js +17 -1
- package/.agents/scripts/generate-workflows-doc.js +4 -4
- package/.agents/scripts/lib/ITicketingProvider.js +1 -19
- package/.agents/scripts/lib/audit-suite/selector.js +323 -23
- package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -11
- package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +28 -33
- package/.agents/scripts/lib/bootstrap/manifest.js +8 -11
- package/.agents/scripts/lib/bootstrap/project-bootstrap.js +30 -53
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +0 -2
- package/.agents/scripts/lib/checks/core-bare-clean.js +4 -1
- package/.agents/scripts/lib/checks/index.js +1 -1
- package/.agents/scripts/lib/checks/loop-health.js +12 -11
- package/.agents/scripts/lib/checks/state.js +17 -248
- package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +3 -3
- package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +3 -4
- package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +2 -2
- package/.agents/scripts/lib/checks/worktree-residue-biome.js +3 -3
- package/.agents/scripts/lib/cli-args.js +23 -2
- package/.agents/scripts/lib/close-validation/gates.js +13 -13
- package/.agents/scripts/lib/close-validation/projections/inputs.js +7 -7
- package/.agents/scripts/lib/close-validation/projections/maintainability.js +12 -12
- package/.agents/scripts/lib/close-validation/runner.js +13 -21
- package/.agents/scripts/lib/close-validation/telemetry.js +17 -8
- package/.agents/scripts/lib/config/delivery-routing.js +7 -6
- package/.agents/scripts/lib/config/explain.js +10 -16
- package/.agents/scripts/lib/config/github.js +7 -5
- package/.agents/scripts/lib/config/limits.js +15 -25
- package/.agents/scripts/lib/config/quality.js +11 -14
- package/.agents/scripts/lib/config/runners.js +8 -21
- package/.agents/scripts/lib/config/temp-paths.js +18 -56
- package/.agents/scripts/lib/config-settings-schema-delivery.js +31 -13
- package/.agents/scripts/lib/config-settings-schema-quality.js +9 -2
- package/.agents/scripts/lib/config-settings-schema.js +48 -22
- package/.agents/scripts/lib/dead-exports-knip.js +105 -0
- package/.agents/scripts/lib/dead-exports-mode.js +51 -0
- package/.agents/scripts/lib/duplicate-search.js +38 -7
- package/.agents/scripts/lib/findings/promote-finding.js +23 -14
- package/.agents/scripts/lib/format-generated-json.js +97 -0
- package/.agents/scripts/lib/framework-version.js +19 -189
- package/.agents/scripts/lib/gh-exec.js +8 -0
- package/.agents/scripts/lib/git-branch-lifecycle.js +0 -158
- package/.agents/scripts/lib/git-utils.js +0 -14
- package/.agents/scripts/lib/json-utils.js +1 -2
- package/.agents/scripts/lib/label-constants.js +0 -15
- package/.agents/scripts/lib/label-taxonomy.js +1 -12
- package/.agents/scripts/lib/observability/active-story-env.js +42 -163
- package/.agents/scripts/lib/observability/runtime-friction.js +243 -0
- package/.agents/scripts/lib/observability/signal-validator.js +4 -4
- package/.agents/scripts/lib/observability/signals-writer.js +6 -82
- package/.agents/scripts/lib/observability/source-classifier.js +2 -2
- package/.agents/scripts/lib/observability/tool-trace-hook.js +2 -12
- package/.agents/scripts/lib/orchestration/acceptance-clusters.js +1 -1
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +2 -2
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +43 -45
- package/.agents/scripts/lib/orchestration/code-review.js +58 -168
- package/.agents/scripts/lib/orchestration/consolidation-precondition.js +3 -3
- package/.agents/scripts/lib/orchestration/deliver-recover.js +328 -0
- package/.agents/scripts/lib/orchestration/detectors-phase.js +12 -6
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +34 -0
- package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -2
- package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +142 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +9 -11
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +86 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +37 -103
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +7 -3
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +50 -85
- package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +3 -14
- package/.agents/scripts/lib/orchestration/merge-block-class.js +76 -20
- package/.agents/scripts/lib/orchestration/merge-poll.js +104 -0
- package/.agents/scripts/lib/orchestration/plan-context.js +114 -24
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +11 -22
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +3 -7
- package/.agents/scripts/lib/orchestration/plan-metrics.js +38 -6
- package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +16 -6
- package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +173 -25
- package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +116 -0
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +280 -75
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +472 -55
- package/.agents/scripts/lib/orchestration/plan-persist/summary.js +21 -16
- package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +509 -0
- package/.agents/scripts/lib/orchestration/planning/authoring-context.js +41 -40
- package/.agents/scripts/lib/orchestration/planning/spec-authoring-grounding.js +1 -1
- package/.agents/scripts/lib/orchestration/resolve-stories.js +344 -0
- package/.agents/scripts/lib/orchestration/retro-proposals.js +7 -7
- package/.agents/scripts/lib/orchestration/review-depth.js +105 -40
- package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +3 -13
- package/.agents/scripts/lib/orchestration/review-providers/native.js +1 -154
- package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +3 -2
- package/.agents/scripts/lib/orchestration/review-providers/security-review.js +1 -1
- package/.agents/scripts/lib/orchestration/review-providers/types.js +5 -4
- package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +1 -1
- package/.agents/scripts/lib/orchestration/run-epilogue.js +374 -16
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +24 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +11 -9
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +4 -4
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +3 -12
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +608 -152
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +72 -30
- package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +305 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +1 -1
- package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +12 -8
- package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +37 -4
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +2 -2
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +264 -43
- package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
- package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +10 -10
- package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -32
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +360 -0
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +75 -14
- package/.agents/scripts/lib/orchestration/story-init-remote.js +12 -8
- package/.agents/scripts/lib/orchestration/story-plan-state.js +14 -29
- package/.agents/scripts/lib/orchestration/task-body-validator.js +52 -7
- package/.agents/scripts/lib/orchestration/ticket-lease.js +27 -74
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +119 -14
- package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +3 -4
- package/.agents/scripts/lib/orchestration/ticket-validator.js +121 -18
- package/.agents/scripts/lib/orchestration/ticketing/bulk.js +14 -47
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +19 -32
- package/.agents/scripts/lib/orchestration/ticketing/transition.js +61 -1
- package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
- package/.agents/scripts/lib/plan-phase-cleanup.js +12 -14
- package/.agents/scripts/lib/planning-corpus.js +12 -286
- package/.agents/scripts/lib/preflight-runner.js +2 -2
- package/.agents/scripts/lib/qa/qa-context-hydrator.js +5 -5
- package/.agents/scripts/lib/signals/index.js +4 -17
- package/.agents/scripts/lib/signals/read.js +35 -35
- package/.agents/scripts/lib/signals/schema.js +8 -11
- package/.agents/scripts/lib/signals/span-tree.js +7 -7
- package/.agents/scripts/lib/signals/write.js +0 -1
- package/.agents/scripts/lib/single-story/story-merged-notify.js +13 -2
- package/.agents/scripts/lib/skills/parse-skill.js +16 -3
- package/.agents/scripts/lib/story-adjacency.js +8 -7
- package/.agents/scripts/lib/story-body/story-body.js +6 -5
- package/.agents/scripts/lib/templates/decomposer-prompts.js +7 -3
- package/.agents/scripts/lib/test-env.js +14 -1
- package/.agents/scripts/lib/test-tiers.js +0 -3
- package/.agents/scripts/lib/ticket-body-sections.js +0 -14
- package/.agents/scripts/lib/validation-evidence.js +31 -59
- package/.agents/scripts/lib/wave-runner/ready-set.js +32 -6
- package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +1 -1
- package/.agents/scripts/lib/worktree/lifecycle/reap.js +68 -19
- package/.agents/scripts/lib/worktree/lifecycle-manager.js +1 -2
- package/.agents/scripts/plan-context.js +38 -6
- package/.agents/scripts/plan-persist.js +145 -35
- package/.agents/scripts/plan-run-epilogue.js +83 -38
- package/.agents/scripts/post-structured-comment.js +0 -38
- package/.agents/scripts/pr-watch-with-update.js +43 -22
- package/.agents/scripts/providers/github/compose.js +0 -1
- package/.agents/scripts/providers/github/errors.js +0 -19
- package/.agents/scripts/providers/github/issues.js +1 -11
- package/.agents/scripts/providers/github/mappers.js +5 -0
- package/.agents/scripts/providers/github/sub-issues.js +0 -47
- package/.agents/scripts/providers/github/tickets.js +33 -153
- package/.agents/scripts/providers/github.js +17 -6
- package/.agents/scripts/resolve-stories.js +236 -0
- package/.agents/scripts/run-coverage.js +4 -1
- package/.agents/scripts/run-lint.js +2 -2
- package/.agents/scripts/run-verify.js +31 -2
- package/.agents/scripts/signals-view.js +9 -10
- package/.agents/scripts/single-story-close.js +173 -18
- package/.agents/scripts/single-story-confirm-merge.js +288 -15
- package/.agents/scripts/single-story-init.js +6 -10
- package/.agents/scripts/stories-wave-tick.js +79 -4
- package/.agents/scripts/story-plan.js +3 -3
- package/.agents/scripts/update-ticket-state.js +8 -50
- package/.agents/skills/core/code-review-and-quality/SKILL.md +28 -450
- package/.agents/skills/core/code-review-and-quality/reference.md +458 -0
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +22 -315
- package/.agents/skills/core/debugging-and-error-recovery/reference.md +323 -0
- package/.agents/skills/core/diagnose-friction/SKILL.md +14 -18
- package/.agents/skills/core/documentation-and-adrs/SKILL.md +25 -397
- package/.agents/skills/core/documentation-and-adrs/reference.md +403 -0
- package/.agents/skills/core/gates-and-baselines/SKILL.md +12 -12
- package/.agents/skills/core/idea-refinement/SKILL.md +3 -3
- package/.agents/skills/core/scope-triage/SKILL.md +3 -0
- package/.agents/skills/core/security-and-hardening/SKILL.md +22 -367
- package/.agents/skills/core/security-and-hardening/reference.md +375 -0
- package/.agents/skills/skills.index.json +2 -12
- package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +2 -4
- package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +1 -1
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -3
- package/.agents/workflows/audit-architecture.md +3 -4
- package/.agents/workflows/audit-clean-code.md +4 -4
- package/.agents/workflows/audit-documentation.md +4 -5
- package/.agents/workflows/audit-lighthouse.md +8 -0
- package/.agents/workflows/audit-navigability.md +10 -0
- package/.agents/workflows/audit-performance.md +2 -3
- package/.agents/workflows/audit-quality.md +8 -9
- package/.agents/workflows/audit-security.md +1 -2
- package/.agents/workflows/audit-seo.md +10 -0
- package/.agents/workflows/audit-ux-ui.md +7 -0
- package/.agents/workflows/deliver.md +98 -45
- package/.agents/workflows/git-cleanup.md +2 -2
- package/.agents/workflows/git-deliver.md +1 -1
- package/.agents/workflows/helpers/acceptance-self-eval.md +21 -13
- package/.agents/workflows/helpers/code-quality-guardrails.md +7 -7
- package/.agents/workflows/helpers/code-review.md +12 -10
- package/.agents/workflows/helpers/deliver-story-reference.md +73 -32
- package/.agents/workflows/helpers/deliver-story.md +193 -118
- package/.agents/workflows/helpers/parallel-tooling.md +2 -2
- package/.agents/workflows/helpers/worktree-lifecycle.md +28 -32
- package/.agents/workflows/plan.md +184 -19
- package/.agents/workflows/qa-assist.md +6 -6
- package/.agents/workflows/qa-explore.md +3 -3
- package/.agents/workflows/qa-run.md +1 -5
- package/bin/mandrel.js +12 -1
- package/docs/CHANGELOG.md +40 -0
- package/lib/cli/registry.js +262 -19
- package/lib/cli/sync-agents.js +157 -0
- package/lib/cli/sync-commands.js +115 -6
- package/lib/cli/sync.js +168 -6
- package/lib/cli/update.js +105 -8
- package/lib/cli/version-helpers.js +131 -0
- package/lib/migrations/README.md +7 -5
- package/lib/migrations/index.js +12 -9
- package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +100 -0
- package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +101 -0
- package/package.json +1 -1
- package/.agents/schemas/epic-perf-report.schema.json +0 -89
- package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +0 -13
- package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +0 -13
- package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +0 -13
- package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +0 -15
- package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.blocked.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.close.end.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.complete.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +0 -13
- package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +0 -14
- package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +0 -17
- package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +0 -15
- package/.agents/schemas/lifecycle/epic.plan.end.schema.json +0 -18
- package/.agents/schemas/lifecycle/epic.plan.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +0 -16
- package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +0 -12
- package/.agents/schemas/lifecycle/epic.watch.end.schema.json +0 -29
- package/.agents/schemas/lifecycle/epic.watch.start.schema.json +0 -16
- package/.agents/schemas/lifecycle/story.heartbeat.schema.json +0 -20
- package/.agents/schemas/risk-verdict.schema.json +0 -53
- package/.agents/schemas/story-perf-summary.schema.json +0 -73
- package/.agents/scripts/analyze-execution.js +0 -444
- package/.agents/scripts/check-prepush-recovery.js +0 -90
- package/.agents/scripts/lib/git-merge-orchestrator.js +0 -261
- package/.agents/scripts/lib/observability/baseline-refresh-rate.js +0 -221
- package/.agents/scripts/lib/observability/hook-heartbeat.js +0 -187
- package/.agents/scripts/lib/observability/perf-aggregator.js +0 -813
- package/.agents/scripts/lib/observability/perf-report-readers.js +0 -328
- package/.agents/scripts/lib/observability/perf-report-render.js +0 -182
- package/.agents/scripts/lib/orchestration/audit-lens-routing.js +0 -128
- package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +0 -273
- package/.agents/scripts/lib/orchestration/error-journal.js +0 -139
- package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +0 -155
- package/.agents/scripts/lib/orchestration/lifecycle/ledger-diff.js +0 -140
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +0 -665
- package/.agents/scripts/lib/orchestration/plan-review-routing.js +0 -63
- package/.agents/scripts/lib/orchestration/planning/risk-verdict.js +0 -104
- package/.agents/scripts/lib/orchestration/planning-context-budget.js +0 -213
- package/.agents/scripts/lib/orchestration/planning-risk.js +0 -194
- package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +0 -56
- package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +0 -21
- package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +0 -78
- package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +0 -68
- package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +0 -118
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +0 -397
- package/.agents/scripts/lib/orchestration/preflight-cache.js +0 -187
- package/.agents/scripts/lib/orchestration/resolve-plan-run.js +0 -155
- package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +0 -275
- package/.agents/scripts/lib/orchestration/story-progress/story-run-progress-writer.js +0 -400
- package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +0 -36
- package/.agents/scripts/resolve-plan-run.js +0 -117
- package/.agents/skills/core/analyze-execution/SKILL.md +0 -101
package/.agents/README.md
CHANGED
|
@@ -96,17 +96,17 @@ The bootstrap pipeline, in order:
|
|
|
96
96
|
3. **Project-side mutations.** Seeds `.agentrc.json` from
|
|
97
97
|
[`starter-agentrc.json`](starter-agentrc.json), merges the framework's
|
|
98
98
|
runtime dependencies into `package.json`, runs the install, wires the
|
|
99
|
-
|
|
100
|
-
`.claude/commands/` tree
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
system prompt (see below), gitignores derived artefacts, and runs the
|
|
100
|
+
quality-gates installer. The flat `.claude/commands/` tree is generated
|
|
101
|
+
at install time (via `prepare`) and on every `mandrel sync`/`update` —
|
|
102
|
+
see [`mandrel sync-commands`](#mandrel-sync-commands) below.
|
|
103
103
|
4. **GitHub-side mutations.** Creates the label taxonomy, branch protection,
|
|
104
104
|
and merge-method settings. Skipped with `--skip-github`. Two additional
|
|
105
105
|
mutations are **opt-in** (prompted y/N, defaulting No, or passed as flags):
|
|
106
106
|
- `--with-project-board` — provision the Projects V2 Status field and
|
|
107
107
|
custom fields on an existing board.
|
|
108
|
-
- `--with-issue-forms` — generate `.github/ISSUE_TEMPLATE/story.yml`
|
|
109
|
-
|
|
108
|
+
- `--with-issue-forms` — generate `.github/ISSUE_TEMPLATE/story.yml`
|
|
109
|
+
from the ticket-body schema.
|
|
110
110
|
|
|
111
111
|
The bootstrap is idempotent — safe to re-run; an already-configured
|
|
112
112
|
clone produces zero file mutations.
|
|
@@ -154,6 +154,7 @@ Run `mandrel --help` for a subcommand list. Each subcommand supports
|
|
|
154
154
|
| `init` | Install + configure mandrel in the current project (cold-start). | `--assume-yes`, `--skip-github`, `--dry-run` |
|
|
155
155
|
| `sync` | Re-materialize `.agents/` from the installed package payload. | `--dry-run` |
|
|
156
156
|
| `sync-commands` | Regenerate `.claude/commands/` from `.agents/workflows/`. | — |
|
|
157
|
+
| `sync-agents` | Regenerate `.claude/agents/` from `.agents/agents/`. | — |
|
|
157
158
|
| `doctor` | Run readiness checks and print per-check remedies. | — |
|
|
158
159
|
| `update` | Upgrade mandrel to the newest published version. | `--dry-run`, `--install-cmd` |
|
|
159
160
|
| `migrate` | Apply version-keyed migrations for a version range. | `--from`, `--to`, `--dry-run` |
|
|
@@ -175,13 +176,27 @@ mandrel explain --json # same report as JSON
|
|
|
175
176
|
### `mandrel sync-commands`
|
|
176
177
|
|
|
177
178
|
Regenerates the flat `.claude/commands/` projection from `.agents/workflows/`.
|
|
178
|
-
|
|
179
|
-
|
|
179
|
+
Runs automatically at install time (via the `prepare` script) and as part of
|
|
180
|
+
`mandrel sync` / `mandrel update`; doctor's `commands-in-sync` check flags a
|
|
181
|
+
hand-edited or stale tree. Refuses to project when the materialized `.agents/`
|
|
182
|
+
tree doesn't match the running CLI's own version — run `mandrel sync` first.
|
|
180
183
|
|
|
181
184
|
```bash
|
|
182
185
|
mandrel sync-commands # rebuild .claude/commands/
|
|
183
186
|
```
|
|
184
187
|
|
|
188
|
+
### `mandrel sync-agents`
|
|
189
|
+
|
|
190
|
+
Regenerates the flat `.claude/agents/` projection from `.agents/agents/` —
|
|
191
|
+
the role-scoped boot contexts (`story-worker`, `acceptance-critic`) that
|
|
192
|
+
`delivery.routing.roleScopedAgents` (default `true`) dispatches spawns
|
|
193
|
+
against. Same delegation shape, wiring, and version-match refusal as
|
|
194
|
+
`sync-commands` above.
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
mandrel sync-agents # rebuild .claude/agents/
|
|
198
|
+
```
|
|
199
|
+
|
|
185
200
|
### `mandrel uninstall`
|
|
186
201
|
|
|
187
202
|
Reverses a recorded install using the install ledger
|
|
@@ -247,6 +262,13 @@ read-when-relevant pattern skills use).
|
|
|
247
262
|
[`rules/test-seams.md`](rules/test-seams.md)) — when the task is in that
|
|
248
263
|
domain.
|
|
249
264
|
- Every `SKILL.md` under [`skills/`](skills/) — when the task hits its trigger.
|
|
265
|
+
A `SKILL.md` is itself split the same way: it leads with its **Policy
|
|
266
|
+
Capsule** (the contract, and the whole cost of activating the skill) plus
|
|
267
|
+
pointers into an on-demand `reference.md` sibling carrying the long-form
|
|
268
|
+
material. Activating a skill costs the capsule, not the essay — open a
|
|
269
|
+
`reference.md` section only when the task engages it. Routing does not
|
|
270
|
+
depend on the long-form being inline: skill descriptions live in the
|
|
271
|
+
generated [`skills/skills.index.json`](skills/skills.index.json).
|
|
250
272
|
- [`docs/execution-reference.md`](docs/execution-reference.md) — log-level and
|
|
251
273
|
token-budget reference detail lifted out of `instructions.md`.
|
|
252
274
|
|
|
@@ -280,10 +302,10 @@ For non-interactive (CI) installs, pass `--owner`, `--repo`, and
|
|
|
280
302
|
`--assume-yes`; pass `--skip-github` to defer the remote half.
|
|
281
303
|
|
|
282
304
|
After bootstrap, every Mandrel command is generated into a flat
|
|
283
|
-
`.claude/commands/` tree by `npm run sync:commands` (
|
|
284
|
-
|
|
285
|
-
`/plan`, `/deliver`, `/audit-security`. The commands load
|
|
286
|
-
environment. The [SDLC guide](docs/SDLC.md) walks end-to-end planning and
|
|
305
|
+
`.claude/commands/` tree by `npm run sync:commands` (kept current at install
|
|
306
|
+
time and on every `mandrel sync`/`update`) and loads as a bare `/<command>`
|
|
307
|
+
slash command — e.g. `/plan`, `/deliver`, `/audit-security`. The commands load
|
|
308
|
+
in every Claude Code environment. The [SDLC guide](docs/SDLC.md) walks end-to-end planning and
|
|
287
309
|
delivery; Stories pair [`/plan`](workflows/plan.md) (idea → drafted Story Issue)
|
|
288
310
|
with [`/deliver`](workflows/deliver.md) (Story Issue → merged
|
|
289
311
|
PR).
|
|
@@ -408,9 +430,9 @@ rule:
|
|
|
408
430
|
> GitHub I/O, label transitions, JSON validators, NDJSON readers,
|
|
409
431
|
> diff-vs-baseline gates, template renderers.
|
|
410
432
|
>
|
|
411
|
-
> **Prompt + judgment → make it a Skill.** Examples: composing a
|
|
412
|
-
> Spec from
|
|
413
|
-
> command, decomposing a
|
|
433
|
+
> **Prompt + judgment → make it a Skill.** Examples: composing a Story's
|
|
434
|
+
> `## Spec` from planning context, classifying friction signals from a
|
|
435
|
+
> failed shell command, decomposing a Spec into Stories.
|
|
414
436
|
|
|
415
437
|
The rule is two-sided on purpose. "Has an LLM step adjacent" is *not*
|
|
416
438
|
the signal — many deterministic scripts emit a JSON envelope that a host
|
|
@@ -424,17 +446,18 @@ The collapsed plan pipeline (`plan-context.js` → author → `plan-persist.js`,
|
|
|
424
446
|
Epic #4474) is a **split**: the deterministic halves stay as scripts, the
|
|
425
447
|
judgment middle moves to a Skill.
|
|
426
448
|
|
|
427
|
-
- **`--emit-context`** (script half) — fetches the
|
|
428
|
-
|
|
429
|
-
|
|
449
|
+
- **`--emit-context`** (script half) — fetches the seed/source tickets
|
|
450
|
+
and scrapes project docs, emits a JSON envelope. Parseable in,
|
|
451
|
+
parseable out. Stays a script.
|
|
430
452
|
- **Authoring middle** (Skill half) — given the envelope, author the
|
|
431
|
-
|
|
453
|
+
Story JSON. Pure prompt + judgment. Migrates to a Skill
|
|
432
454
|
under `.agents/skills/core/` so it ships with declarative
|
|
433
455
|
`allowed_tools` and a smoke test rather than bespoke prompt-template
|
|
434
456
|
plumbing inside a Node module.
|
|
435
457
|
- **Persist half** (script half) — given the author-provided tickets
|
|
436
|
-
JSON, validate against the schema, create
|
|
437
|
-
label
|
|
458
|
+
JSON, validate against the schema, create the `type::story` issue(s)
|
|
459
|
+
and label them `agent::ready`. Deterministic GitHub I/O + schema
|
|
460
|
+
validation. Stays a script.
|
|
438
461
|
|
|
439
462
|
The split codifies the "host LLM authors directly" pattern explicitly:
|
|
440
463
|
the prompt+judgment step gets a `description`, an
|
|
@@ -524,8 +547,8 @@ comment) is the cross-runtime contract.
|
|
|
524
547
|
The SDK barrel is `scripts/lib/orchestration/index.js`; its exports are
|
|
525
548
|
the source of truth for the public in-process surface. Key families
|
|
526
549
|
include dispatch (`dispatch-engine.js`, `manifest-builder.js`), context
|
|
527
|
-
hydration, planning state, label transitions,
|
|
528
|
-
|
|
550
|
+
hydration, planning state, label transitions, Story-close internals,
|
|
551
|
+
retro proposals, and structured error capture.
|
|
529
552
|
|
|
530
553
|
### GitHub authentication
|
|
531
554
|
|
|
@@ -578,7 +601,7 @@ environment inside the check. A finding includes `id`, `severity`,
|
|
|
578
601
|
`autoCorrectable`.
|
|
579
602
|
|
|
580
603
|
`autoCorrect: 'auto'` means the fix is local, bounded, and reversible.
|
|
581
|
-
Auto-fixes must not push to remotes, commit to `
|
|
604
|
+
Auto-fixes must not push to remotes, commit to `main`, amend
|
|
582
605
|
history, recursively delete outside `.worktrees/<id>/`, write GitHub
|
|
583
606
|
state, or read secret values. Anything requiring those operations must be
|
|
584
607
|
`refuse-and-print` with a human-run `fixCommand`.
|
|
@@ -828,7 +851,7 @@ Two operators can drive the same repository at once — for example, two
|
|
|
828
851
|
runs from clobbering one another with **two distinct coordination layers**.
|
|
829
852
|
They solve different problems and must not be confused:
|
|
830
853
|
|
|
831
|
-
- **Filesystem locks** (`
|
|
854
|
+
- **Filesystem locks** (`sweep-lock`) serialise work
|
|
832
855
|
**within a single machine/clone**. They are keyed on local process PIDs
|
|
833
856
|
and live under `.git/` (or a local lockfile path), so they do **not**
|
|
834
857
|
coordinate across clones. See
|
|
@@ -844,8 +867,16 @@ The lease primitive lives in
|
|
|
844
867
|
[`scripts/lib/orchestration/ticket-lease.js`](scripts/lib/orchestration/ticket-lease.js).
|
|
845
868
|
Rather than inventing a new state column, the lease rides the ticket's
|
|
846
869
|
existing **assignees** field: the single assignee *is* the lease owner.
|
|
847
|
-
Liveness is decided by the owner's
|
|
848
|
-
|
|
870
|
+
Liveness is decided by the owner's last-heartbeat timestamp compared against
|
|
871
|
+
a configurable TTL (`delivery.lease.ttlMs`).
|
|
872
|
+
|
|
873
|
+
> **In practice the lease always fails closed.** There is no live heartbeat
|
|
874
|
+
> source — the `story.heartbeat` emitter was structurally inert and has been
|
|
875
|
+
> deleted (A22) — so every guard anchors the owner's heartbeat to *now*,
|
|
876
|
+
> making **any** foreign claim read as live. The **stale-claim reclaim** row
|
|
877
|
+
> below is therefore unreachable in normal operation: a stranded claim is
|
|
878
|
+
> cleared with `--steal`, never by TTL expiry. The TTL and the reclaim branch
|
|
879
|
+
> remain as a seam for a caller that supplies its own `heartbeatAt`.
|
|
849
880
|
|
|
850
881
|
The model has five behaviours, all expressed through `acquireLease` /
|
|
851
882
|
`releaseLease`:
|
|
@@ -855,7 +886,7 @@ The model has five behaviours, all expressed through `acquireLease` /
|
|
|
855
886
|
| **Acquire by self-assign** | The ticket is unassigned. | The operator is written to `assignees`; the run proceeds (`reason: 'unclaimed'`). |
|
|
856
887
|
| **Re-affirm a self-held claim** | The operator already holds the lease. | No write; the run proceeds (`reason: 'already-held'`). |
|
|
857
888
|
| **Refuse-if-foreign** | A *different* operator holds the lease and their heartbeat is within the TTL (the claim is **live**). | The acquire **fails closed** — the run refuses to start and names the current owner so you know who to coordinate with (`reason: 'held'`). |
|
|
858
|
-
| **Stale-claim reclaim** | A foreign claim exists but
|
|
889
|
+
| **Stale-claim reclaim** *(unreachable — see above)* | A foreign claim exists but the caller supplied a `heartbeatAt` older than the TTL. | The lease is reassigned to the operator (`reason: 'reclaimed'`). No shipped caller supplies one, so this never fires today. |
|
|
859
890
|
| **`--steal` override** | A foreign claim is *live* and the operator passes `--steal`. | The live claim is forcibly transferred (`reason: 'stolen'`). This is the **only** way past a live foreign claim. |
|
|
860
891
|
|
|
861
892
|
On a clean completion the holder **releases** the lease (clears the
|
|
@@ -4,8 +4,9 @@ description: >-
|
|
|
4
4
|
Role-scoped boot context for a maker-blind acceptance critic. Booted on its
|
|
5
5
|
own system prompt (no CLAUDE.md / instructions.md closure). Scores a delivered
|
|
6
6
|
diff against the Story's acceptance-criteria cluster and emits the verdict
|
|
7
|
-
schema — without seeing the maker's self-assessment.
|
|
8
|
-
|
|
7
|
+
schema — without seeing the maker's self-assessment. Live under M7-B —
|
|
8
|
+
helpers/deliver-story Step 1a dispatches subagent_type: acceptance-critic
|
|
9
|
+
on the default risk-routed path.
|
|
9
10
|
---
|
|
10
11
|
|
|
11
12
|
# acceptance-critic — maker-blind acceptance evaluation
|
|
@@ -34,8 +35,11 @@ file they authored. You grade the **work product**, not the homework the maker
|
|
|
34
35
|
turned in about it. Your only trusted inputs are:
|
|
35
36
|
|
|
36
37
|
- the working **diff** (`git diff origin/<baseBranch>...HEAD`),
|
|
37
|
-
- the Story's inline `acceptance[]` and `verify[]` arrays
|
|
38
|
-
|
|
38
|
+
- the Story's inline `acceptance[]` and `verify[]` arrays, read from the
|
|
39
|
+
**Story body itself** (`gh issue view <storyId> --json body`) — its `##
|
|
40
|
+
Acceptance` / `## Verify` sections are the SSOT. The `story-init` structured
|
|
41
|
+
comment does not carry them: it reports init state (`workCwd`,
|
|
42
|
+
`dependenciesInstalled`, `remoteVerified`, …) and nothing else.
|
|
39
43
|
- the **actual output** of the `verify[]` commands you run yourself.
|
|
40
44
|
|
|
41
45
|
Treat the implementation reasoning as untrusted. Score each criterion afresh
|
|
@@ -66,12 +70,10 @@ For each acceptance item in your cluster:
|
|
|
66
70
|
a passing run records an evidence entry in the keyspace close consults:
|
|
67
71
|
|
|
68
72
|
```bash
|
|
69
|
-
# Epic-attached Story:
|
|
70
73
|
node <main-repo>/.agents/scripts/evidence-gate.js \
|
|
71
|
-
--
|
|
74
|
+
--standalone --scope-id <storyId> --gate lint \
|
|
72
75
|
--worktree <worktree> -- npm run lint
|
|
73
76
|
|
|
74
|
-
# Standalone Story (no parent Epic): use --standalone, omit --epic-id.
|
|
75
77
|
node <main-repo>/.agents/scripts/evidence-gate.js \
|
|
76
78
|
--standalone --scope-id <storyId> --gate typecheck \
|
|
77
79
|
--worktree <worktree> -- <resolved typecheck command>
|
|
@@ -3,8 +3,8 @@ name: story-worker
|
|
|
3
3
|
description: >-
|
|
4
4
|
Role-scoped boot context for a single Story delivery child, booted on its own
|
|
5
5
|
system prompt (no CLAUDE.md / instructions.md closure). Carries the
|
|
6
|
-
load-bearing delivery MUSTs standalone.
|
|
7
|
-
|
|
6
|
+
load-bearing delivery MUSTs standalone. Dispatched by helpers/deliver-story
|
|
7
|
+
when delivery.routing.roleScopedAgents is enabled (the default).
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# story-worker — Story delivery boot context
|
|
@@ -44,10 +44,10 @@ You run as a sub-agent with **no input channel** mid-run.
|
|
|
44
44
|
the **main checkout** (the worktree does not exist yet). Invoke it
|
|
45
45
|
**synchronously** with the Bash maximum timeout — a per-worktree install can
|
|
46
46
|
take several minutes; do not background it.
|
|
47
|
-
2. Capture `workCwd
|
|
48
|
-
|
|
49
|
-
**absolute** `workCwd` before doing any implementation
|
|
50
|
-
checkout's HEAD is never moved by you.
|
|
47
|
+
2. Capture `workCwd` and `dependenciesInstalled` from the init envelope (it
|
|
48
|
+
is flat — there is no `context` block). When worktree isolation is on, `cd`
|
|
49
|
+
into the printed **absolute** `workCwd` before doing any implementation
|
|
50
|
+
work. The main checkout's HEAD is never moved by you.
|
|
51
51
|
3. Every subsequent command runs against that worktree path. Because cwd may
|
|
52
52
|
reset between calls, prefer absolute paths anchored at `workCwd`.
|
|
53
53
|
|
|
@@ -60,8 +60,7 @@ git -C "<workCwd>" branch --show-current # MUST print story-<storyId>
|
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
If it does **not** report `story-<storyId>`, **STOP** — do not commit. Never
|
|
63
|
-
commit Story work to `main
|
|
64
|
-
worktree/branch. Re-run `single-story-init.js` (it is idempotent on partial state) to
|
|
63
|
+
commit Story work to `main` or outside the worktree/branch. Re-run `single-story-init.js` (it is idempotent on partial state) to
|
|
65
64
|
restore the branch before proceeding.
|
|
66
65
|
|
|
67
66
|
## Commit discipline
|
|
@@ -79,7 +78,7 @@ Author commits directly on `story-<storyId>` following the always-on git core
|
|
|
79
78
|
## Docs context — digest first
|
|
80
79
|
|
|
81
80
|
Do **not** re-read every file in `project.docsContextFiles`. Your caller passes
|
|
82
|
-
a `docsDigestPath` (the per-
|
|
81
|
+
a `docsDigestPath` (the per-run docs digest — a compact per-file outline:
|
|
83
82
|
path, size, heading outline with line numbers, first paragraph under each
|
|
84
83
|
`##`). Read that digest, decide which docs bear on this Story, then **pull the
|
|
85
84
|
full file on demand** (jump to the section at the line number the digest names)
|
|
@@ -89,9 +88,9 @@ mandate — read a full doc only if the Story's own context points you at one.
|
|
|
89
88
|
|
|
90
89
|
## Close gates — do not pre-run
|
|
91
90
|
|
|
92
|
-
`story-close.js` runs the canonical close-validation chain (**typecheck,
|
|
93
|
-
test, format, maintainability, coverage, crap**) before it merges. Do
|
|
94
|
-
pre-run those gates as a matter of course — running `npm run typecheck &&
|
|
91
|
+
`single-story-close.js` runs the canonical close-validation chain (**typecheck,
|
|
92
|
+
lint, test, format, maintainability, coverage, crap**) before it merges. Do
|
|
93
|
+
**not** pre-run those gates as a matter of course — running `npm run typecheck &&
|
|
95
94
|
npm run lint && npm test` as advisory pre-flight while iterating on a fix is
|
|
96
95
|
fine, but the close pipeline is the authoritative gate. The bounded acceptance
|
|
97
96
|
self-eval loop (below) may share `lint` / `typecheck` evidence with close via
|
|
@@ -110,21 +109,16 @@ scores the working diff against **each** `acceptance[]` item and consumes the
|
|
|
110
109
|
- **`block`** (round cap reached, criteria still unmet) → take the blocked path.
|
|
111
110
|
Never silently proceed to close.
|
|
112
111
|
|
|
113
|
-
## Lifecycle:
|
|
114
|
-
|
|
115
|
-
- **
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
`post
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
transition the Story to `agent::blocked`, post a `friction` comment naming
|
|
124
|
-
the decision needed (or the unmet criteria and their evidence), and **exit
|
|
125
|
-
non-zero**. **Never fall silent** — a child with no heartbeat, no commit, and
|
|
126
|
-
no `agent::blocked` label is exactly the dead-child failure the watchdog is
|
|
127
|
-
built to catch.
|
|
112
|
+
## Lifecycle: progress & blocked (MUST)
|
|
113
|
+
|
|
114
|
+
- **Progress.** Relay one terse line per phase transition (e.g.
|
|
115
|
+
`Story #<id>: implementing → closing`), not a full body. Your commits on
|
|
116
|
+
`story-<id>` and these lines are the progress surface.
|
|
117
|
+
- **Blocked.** If you genuinely cannot proceed, transition the Story to
|
|
118
|
+
`agent::blocked`, post a `friction` comment naming the decision needed (or
|
|
119
|
+
the unmet criteria and their evidence), and **exit non-zero**.
|
|
120
|
+
**Never fall silent** — a child that stalls without an `agent::blocked`
|
|
121
|
+
label and no commit is indistinguishable from a dead one.
|
|
128
122
|
- **Anti-thrashing.** If you hit the same error class twice with the same fix,
|
|
129
123
|
or drift through reads without narrowing the problem, STOP: summarize what
|
|
130
124
|
recurred and either re-plan or take the blocked path. Do not paper over a
|
|
@@ -136,26 +130,27 @@ The Story's init envelope carries `remoteVerified` + `remoteProbe`. When
|
|
|
136
130
|
`remoteVerified` is `false`, transition the Story to `agent::blocked` quoting
|
|
137
131
|
`remoteProbe.detail` and stop. Implementing the Story inline outside the
|
|
138
132
|
worktree / branch / PR path — or committing it to local `main` — is expressly
|
|
139
|
-
**forbidden**. The close pipeline's push (`story-close.js`) is the only
|
|
133
|
+
**forbidden**. The close pipeline's push (`single-story-close.js`) is the only
|
|
140
134
|
sanctioned way the work lands.
|
|
141
135
|
|
|
142
136
|
## Return schema
|
|
143
137
|
|
|
144
|
-
Your
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
138
|
+
Your return contract is
|
|
139
|
+
[`story-deliver-terminal.schema.json`](../schemas/story-deliver-terminal.schema.json)
|
|
140
|
+
— the SSOT for every field (Story #4543). Fields are deliberately not
|
|
141
|
+
restated here; that duplication is what drifted.
|
|
142
|
+
|
|
143
|
+
`single-story-close.js` emits a validated envelope between its
|
|
144
|
+
`--- STORY DELIVER TERMINAL ---` markers. **Relay it**; never hand-compose
|
|
145
|
+
one. Its `status` is one of four; your exit code mirrors it:
|
|
146
|
+
|
|
147
|
+
- `landed` → 0. Merged, `agent::done`, tail attempted (a `false` in `tail.*`
|
|
148
|
+
degrades the report, not the land).
|
|
149
|
+
- `pending` → 3. **Resumable, not a failure** — the bounded merge wait
|
|
150
|
+
expired with the PR healthy, or a human owns the merge. Nothing was
|
|
151
|
+
mutated; `nextCommand` resumes it. The only sanctioned no-merge ending.
|
|
152
|
+
- `blocked` / `failed` → exit non-zero. Take the blocked path above.
|
|
153
|
+
|
|
154
|
+
Stranded? Probe, don't guess:
|
|
155
|
+
`node .agents/scripts/deliver-recover.js --story <id>` (read-only, prints
|
|
156
|
+
one next command).
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
# Performance & Bottleneck Audit — authoring checklist
|
|
8
8
|
|
|
9
|
-
> Audit hot paths, algorithmic complexity, and I/O bottlenecks in the tooling surface (`
|
|
9
|
+
> Audit hot paths, algorithmic complexity, and I/O bottlenecks in the tooling surface (`single-story-close`, dispatcher, gates); propose remediations.
|
|
10
10
|
|
|
11
11
|
Self-check your change against this lens's concerns before you ship:
|
|
12
12
|
|
package/.agents/docs/SDLC.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Mandrel uses **Story-centric GitHub orchestration** — GitHub Issues,
|
|
4
4
|
Labels, and Projects V2 are the Single Source of Truth. Plans persist as
|
|
5
|
-
`type::story` tickets
|
|
5
|
+
`type::story` tickets ordered by `depends_on` edges;
|
|
6
6
|
each Story is delivered on its own `story-<id>` branch and reaches `main`
|
|
7
7
|
through its own PR.
|
|
8
8
|
|
|
@@ -49,19 +49,23 @@ From zero to shipped:
|
|
|
49
49
|
probe, risk heuristics, `systemPrompts.story`). Duplicate review
|
|
50
50
|
folds into **gate #1**.
|
|
51
51
|
2. **Author** — write `stories.json` (**one Story by default**) with a
|
|
52
|
-
folded Tech Spec in `## Spec` / `## Slicing
|
|
53
|
-
|
|
52
|
+
folded Tech Spec in `## Spec` / `## Slicing`. There is no risk artifact
|
|
53
|
+
to author (Story #4542).
|
|
54
54
|
Binding criteria live in top-level `acceptance[]` / `verify[]`;
|
|
55
55
|
changes/references are `{ path, assumption }` objects. Split into
|
|
56
56
|
N>1 only under the default-single split policy.
|
|
57
|
-
3. **Persist** — **gate #2** (
|
|
58
|
-
|
|
59
|
-
creates Story issue(s) with `type::story` + `agent::ready
|
|
60
|
-
|
|
57
|
+
3. **Persist** — **gate #2** (raised only by an explicit `--force-review`)
|
|
58
|
+
then `plan-persist.js` runs every deterministic gate and
|
|
59
|
+
creates Story issue(s) with `type::story` + `agent::ready`, writing
|
|
60
|
+
each authored `depends_on` edge into the sibling body as a
|
|
61
|
+
`blocked by #<id>` footer when N>1.
|
|
61
62
|
|
|
62
63
|
2. **Deliver the Story.** Run [`/deliver <storyId>`](../workflows/deliver.md)
|
|
63
|
-
(or `/deliver <a> <b>
|
|
64
|
-
|
|
64
|
+
(or `/deliver <a> <b> …` for several) in your IDE. `/deliver` takes
|
|
65
|
+
only Story ids and resolves their dependency graph from live state —
|
|
66
|
+
body edges union native GitHub `blocked_by` edges, with every blocker
|
|
67
|
+
checked against its real issue state, so a Story whose blocker landed in
|
|
68
|
+
an earlier plan run is simply ready. `/deliver` owns input resolution and
|
|
65
69
|
`depends_on` sequencing only — every Story runs through
|
|
66
70
|
[`helpers/deliver-story`](../workflows/helpers/deliver-story.md), the
|
|
67
71
|
single v2 delivery engine. Per-Story it:
|
|
@@ -72,11 +76,12 @@ From zero to shipped:
|
|
|
72
76
|
2. **Implement** — the agent delivers the Story in one guarded session
|
|
73
77
|
against its inline `acceptance[]` / `verify[]` contract (optional
|
|
74
78
|
`## Slicing` intra-session checkpoints).
|
|
75
|
-
3. **Acceptance self-eval** — a bounded
|
|
76
|
-
|
|
79
|
+
3. **Acceptance self-eval** — a bounded critic loop scores the working
|
|
80
|
+
diff against each acceptance item before close (see
|
|
77
81
|
[`helpers/acceptance-self-eval`](../workflows/helpers/acceptance-self-eval.md)).
|
|
78
|
-
4. **Ceremony** —
|
|
79
|
-
|
|
82
|
+
4. **Ceremony** — acceptance critic mode and review depth, both routed off
|
|
83
|
+
the change level derived from the Story's own diff
|
|
84
|
+
(`review-depth.js#deriveChangeLevel` → `ceremony-routing.js`).
|
|
80
85
|
5. **Close** (`single-story-close.js`) — runs close-validation gates,
|
|
81
86
|
the maker-blind Story-scope code review, pushes `story-<id>`, opens
|
|
82
87
|
a PR to `main`, and (under the default `delivery.ci.autoMerge:
|
|
@@ -88,7 +93,7 @@ From zero to shipped:
|
|
|
88
93
|
`MERGED` PR the Story flips to `agent::done`; local branch cleanup
|
|
89
94
|
and Projects-v2 Status re-assert run out-of-band.
|
|
90
95
|
|
|
91
|
-
For a multi-Story
|
|
96
|
+
For a multi-Story run, `/deliver` sequences ready Stories by
|
|
92
97
|
`depends_on` and runs the per-run epilogue (audit roster · follow-up
|
|
93
98
|
roll-up · sibling coherence) once after the last Story lands.
|
|
94
99
|
|
|
@@ -105,8 +110,8 @@ rather than re-documenting the ceremony they own.
|
|
|
105
110
|
- **Layered state stores with explicit precedence.** Ticket status lives
|
|
106
111
|
in GitHub Issues and Labels; the lifecycle bus
|
|
107
112
|
(`temp/run-<id>/lifecycle.ndjson`) is the canonical resume target for
|
|
108
|
-
in-flight runs; structured comments (`
|
|
109
|
-
|
|
113
|
+
in-flight runs; structured comments (`verification-results`, retro) are
|
|
114
|
+
the operator-visible rollup. The
|
|
110
115
|
stores, their owners, and their conflict-resolution rules are listed in
|
|
111
116
|
[§ State stores](#state-stores) — that matrix is the single source of
|
|
112
117
|
truth for "who owns which write."
|
|
@@ -149,9 +154,8 @@ on-disk layout resolved by
|
|
|
149
154
|
| State Store | Owner (canonical writer) | Mutation API | Idempotency key | Conflict resolution |
|
|
150
155
|
| --- | --- | --- | --- | --- |
|
|
151
156
|
| GitHub labels | `transitionTicketState` via `ticketing.js` | `gh issue edit --add-label / --remove-label`, wrapped in `update-ticket-state.js` | `(ticketId, label-set)` — set-equality before write | Authoritative for current ticket lifecycle state; if a label disagrees with the lifecycle ledger, the **ledger wins on resume** and the label is re-derived. |
|
|
152
|
-
| `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. |
|
|
153
157
|
| `verification-results` comment | `lib/orchestration/code-review.js` | `post-structured-comment.js` (upsert by `kind`) | `(storyId, kind='verification-results')` | Authoritative for the Story-scope review + lens findings; critical findings block close. |
|
|
154
|
-
| Lifecycle ledger NDJSON | `lifecycle-
|
|
158
|
+
| Lifecycle ledger NDJSON | `LedgerWriter` (`lib/orchestration/lifecycle/ledger-writer.js`, registered as the first listener on every bus event — single append-only writer per run) | Append-only line write to `temp/run-<id>/lifecycle.ndjson` | `(runId, 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. |
|
|
155
159
|
| Validation evidence cache | `evidence-gate.js` | JSON cache file under the run temp tree, keyed by HEAD SHA | `(gate, git rev-parse HEAD)` | Pure cache: a missing entry triggers a re-run; presence is a fast-path skip. Cache eviction is safe. |
|
|
156
160
|
| PR / auto-merge state | `single-story-close.js` (sole authorized caller of `gh pr merge`) | `gh pr merge --auto --squash --delete-branch`; PR open via the close pipeline's `gh pr create` | `(prNumber, head-branch SHA)` — `gh pr list --head` probes before create | GitHub is authoritative for PR + auto-merge arming state; the ledger records the *intent* to arm, GitHub records the outcome. |
|
|
157
161
|
| Worktree cleanup state | `WorktreeManager.reap` (via `single-story-close.js` / `git-cleanup.js`) | `git worktree remove` + on-disk pending-cleanup JSON under the run temp tree | `(storyId, worktree-path)` | Filesystem is authoritative for "is the worktree gone?"; the pending-cleanup JSON only tracks stale-registry entries needing a follow-up sweep. |
|
|
@@ -180,12 +184,12 @@ graph LR
|
|
|
180
184
|
A["👤 /plan --seed | --seed-file | --tickets"]:::manual
|
|
181
185
|
B["🤖 interrogate → author → persist"]:::agentic
|
|
182
186
|
A --> B
|
|
183
|
-
B -.-> B_Art["📄 type::story issue(s)<br/>(+
|
|
187
|
+
B -.-> B_Art["📄 type::story issue(s)<br/>(+ depends_on edges)"]:::artifact
|
|
184
188
|
end
|
|
185
189
|
|
|
186
190
|
subgraph Phase2 ["Phase 2: Deliver"]
|
|
187
191
|
direction TB
|
|
188
|
-
E["👤 /deliver <storyId>
|
|
192
|
+
E["👤 /deliver <storyId> [<storyId>…]"]:::manual
|
|
189
193
|
F["🤖 deliver-story: story-<id> from main<br/>implement → self-eval → ceremony → close"]:::agentic
|
|
190
194
|
G["🤖 close-validation → code-review → open PR"]:::agentic
|
|
191
195
|
E --> F --> G
|
|
@@ -267,7 +271,7 @@ the SDLC depends on:
|
|
|
267
271
|
- **One Story by default.** `/plan` authors a single `type::story` issue
|
|
268
272
|
whose body carries a folded `## Spec` (inline only — never spilled to
|
|
269
273
|
`docs/`) plus top-level `acceptance[]` / `verify[]`. It splits into N>1
|
|
270
|
-
siblings (
|
|
274
|
+
siblings (ordered by `depends_on` edges) **only**
|
|
271
275
|
under the default-single split policy: near-zero overlap or a genuine
|
|
272
276
|
architectural seam. Coupled work stays one Story and is decomposed inside
|
|
273
277
|
`## Slicing` as intra-session checkpoints, not sibling tickets.
|
|
@@ -278,8 +282,7 @@ the SDLC depends on:
|
|
|
278
282
|
`assertAcceptancePartition` so every acceptance criterion belongs to
|
|
279
283
|
exactly one Story.
|
|
280
284
|
- **Handoff.** Persist creates the Story issue(s) at `agent::ready` and
|
|
281
|
-
names the delivery command: `/deliver <storyId
|
|
282
|
-
<planRunId>`).
|
|
285
|
+
names the delivery command: `/deliver <storyId> [<storyId> ...]`.
|
|
283
286
|
|
|
284
287
|
Optional split advisory notes come from
|
|
285
288
|
[`core/scope-triage`](../skills/core/scope-triage/SKILL.md); there is no
|
|
@@ -308,8 +311,7 @@ self-eval, ceremony, close, CI watch, confirm-merge, cleanup) lives in the
|
|
|
308
311
|
| Mode | Entry point | When to use |
|
|
309
312
|
| --- | --- | --- |
|
|
310
313
|
| **Single Story** | `/deliver <storyId>` | Deliver one Story end-to-end; ends with a PR open to `main`. |
|
|
311
|
-
| **Story set** | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (default concurrency **3**); each lands through its own PR. |
|
|
312
|
-
| **Plan-run** | `/deliver --run <planRunId>` | Resolve Stories labeled `plan-run::<id>`, sequence them, and run the per-run epilogue after the set lands. |
|
|
314
|
+
| **Story set** | `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (default concurrency **3**), resolved from live state so edges may point at Stories from earlier plan runs; each lands through its own PR, and the per-run epilogue runs after the set lands. |
|
|
313
315
|
| **Story worker (internal)** | *helper* `helpers/deliver-story <storyId>` | Per-Story engine invoked internally by `/deliver`; not an operator slash command. |
|
|
314
316
|
|
|
315
317
|
The single operator-facing entry point is `/deliver`. It performs no
|
|
@@ -374,14 +376,14 @@ Concurrent runs are serialised by **two distinct layers**:
|
|
|
374
376
|
assignee; `--steal` is the only override. See
|
|
375
377
|
[`README.md` § Multi-developer coordination](../README.md#multi-developer-coordination).
|
|
376
378
|
|
|
377
|
-
### Concurrent close
|
|
379
|
+
### Concurrent close
|
|
378
380
|
|
|
379
381
|
`single-story-close.js` syncs the Story branch from `origin/main` before
|
|
380
|
-
pushing and opening/locating the PR
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
382
|
+
pushing and opening/locating the PR, so concurrent closes serialize through
|
|
383
|
+
their own worktrees rather than racing one shared branch. The push does not
|
|
384
|
+
retry: a rejected push, or a real content conflict at base-sync, aborts with
|
|
385
|
+
a clear error, leaves the tree clean, and exits non-zero for manual
|
|
386
|
+
resolution.
|
|
385
387
|
|
|
386
388
|
---
|
|
387
389
|
|
|
@@ -486,14 +488,18 @@ pass — the tiers below *are* the audit machinery.
|
|
|
486
488
|
| --- | --- | --- | --- |
|
|
487
489
|
| Tier 1 — write-time | During Story implementation | Footprint-matched **local**-lens authoring checklists threaded into the Story prompt (`checklistPath`) | advisory |
|
|
488
490
|
| Tier 2 — Story-scope | `single-story-close.js` (maker-blind subprocess) | Local-tier lens roster over the Story diff (`selectLocalLenses`) + review pillars, posted as `verification-results` | blocking on 🔴 |
|
|
489
|
-
| Tier 3 — run closeout | `/deliver` per-run epilogue (`plan-run-epilogue.js`, N>1 only) | Cumulative + global
|
|
491
|
+
| Tier 3 — run closeout | `/deliver` per-run epilogue (`plan-run-epilogue.js`, N>1 only) | Cumulative + global lenses (`selectAudits`) over the combined landed tip | blocking |
|
|
490
492
|
|
|
491
493
|
- **`local`** lenses (decidable from a single Story's diff) are verified at
|
|
492
494
|
Tiers 1–2 and are **not** re-run at run closeout.
|
|
493
|
-
- **`cumulative`** lenses (only decidable across a
|
|
495
|
+
- **`cumulative`** lenses (only decidable across a run's combined diff)
|
|
494
496
|
and **`global`** lenses (whole-product properties) are verified at Tier 3.
|
|
495
|
-
|
|
496
|
-
|
|
497
|
+
|
|
498
|
+
There is no risk-routed lens tier. Story #4542 deleted the risk→lens router:
|
|
499
|
+
it had zero callers while this document claimed it ran inside close. Lens
|
|
500
|
+
selection is change-set-matched (`selectAudits` / `selectLocalLenses`); the
|
|
501
|
+
`sensitivePaths` classes in `audit-rules.json` route review **depth**, not
|
|
502
|
+
lenses.
|
|
497
503
|
|
|
498
504
|
The run-closeout roster is deliberately **slim**: it excludes every
|
|
499
505
|
local-tier change-set lens so the outermost tier — where a fix is most
|
|
@@ -504,8 +510,8 @@ expensive — does not re-verify a concern already covered shift-left.
|
|
|
504
510
|
The Story-scope code review runs **outside the maker's context**, inside
|
|
505
511
|
the `single-story-close.js` close subprocess, over `main...story-<id>`
|
|
506
512
|
(see [`helpers/code-review.md`](../workflows/helpers/code-review.md)). It
|
|
507
|
-
walks the Story diff once, executing the
|
|
508
|
-
dimensions alongside the review pillars, and posts the unified
|
|
513
|
+
walks the Story diff once, executing the change-set-matched local lens roster
|
|
514
|
+
as review dimensions alongside the review pillars, and posts the unified
|
|
509
515
|
`verification-results` comment. Remediation is tier-aware and split by
|
|
510
516
|
finding class off `delivery.codeReview.autoFixSeverity` (default `medium`);
|
|
511
517
|
surviving 🔴 Critical findings halt the run. The legacy `scope: epic`
|
|
@@ -513,12 +519,14 @@ Epic-branch review path was removed with the v2 cutover.
|
|
|
513
519
|
|
|
514
520
|
### Quality ratchets
|
|
515
521
|
|
|
516
|
-
- **Maintainability ratchet** (`check-
|
|
522
|
+
- **Maintainability ratchet** (`check-baselines.js` via
|
|
523
|
+
`lib/baselines/kinds/maintainability.js`) — fails if the
|
|
517
524
|
composite score drops below the established baseline.
|
|
518
|
-
- **CRAP gate** (`check-crap.js`) —
|
|
525
|
+
- **CRAP gate** (`check-baselines.js` via `lib/baselines/kinds/crap.js`) —
|
|
526
|
+
per-method complexity × coverage risk
|
|
519
527
|
against `baselines/crap.json`, wired into close-validation, `ci.yml`, and
|
|
520
|
-
`.husky/pre-push`. The `baseline-refresh
|
|
521
|
-
project standard for baseline edits (see
|
|
528
|
+
`.husky/pre-push`. The `baseline-refresh: true` commit-trailer convention
|
|
529
|
+
is the project standard for baseline edits (see
|
|
522
530
|
[`core/gates-and-baselines`](../skills/core/gates-and-baselines/SKILL.md)).
|
|
523
531
|
|
|
524
532
|
### Audits → Stories
|
|
@@ -552,7 +560,7 @@ Severity vocabulary (`eventSeverity()` derives it for state transitions):
|
|
|
552
560
|
|
|
553
561
|
| Severity | Used for | Webhook prefix |
|
|
554
562
|
| --- | --- | --- |
|
|
555
|
-
| `low` |
|
|
563
|
+
| `low` | Intermediate transitions, audit reports. | `[low]` |
|
|
556
564
|
| `medium` | Operator-visible milestones: Story state transitions, story merged, run complete. | `[medium]` |
|
|
557
565
|
| `high` | Operator must act (HITL gates, Story blockers, autonomous-chain failures); body leads with `🚨 Action Required:`. | `[Action Required]` |
|
|
558
566
|
|
|
@@ -650,8 +658,7 @@ the ticket or re-plan the work as a v2 Story via `/plan --tickets <id>`.
|
|
|
650
658
|
| `/plan --seed-file <path>` | Plan from on-disk notes / a plan seed (the `/audit-to-stories` handoff). |
|
|
651
659
|
| `/plan --tickets <ids>` | Analyze existing issue(s) into proper Stories (prefer an N=1 rewrite). |
|
|
652
660
|
| `/deliver <storyId>` | Deliver one Story via `helpers/deliver-story` — `story-<id>` → PR → `main`. |
|
|
653
|
-
| `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order
|
|
654
|
-
| `/deliver --run <planRunId>` | Resolve Stories labeled `plan-run::<id>`, sequence them, and run the per-run epilogue. |
|
|
661
|
+
| `/deliver <storyId> [<storyId>…]` | Deliver multiple Stories in `depends_on` order (resolved from live state), then run the per-run epilogue. |
|
|
655
662
|
| *helper* `helpers/deliver-story` | Per-Story engine invoked by `/deliver`; not an operator slash command. See [`deliver-story.md`](../workflows/helpers/deliver-story.md). |
|
|
656
663
|
| `/audit-to-stories` | Convert audit findings into a plan seed / Stories → `/plan --seed-file`. |
|
|
657
664
|
| `/qa-explore` · `/qa-assist` · `/qa-run` | Agent-led / human-led exploratory QA and the automated Gherkin harness. |
|