mandrel 2.31.0 → 2.33.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.
Files changed (267) hide show
  1. package/.agents/README.md +13 -17
  2. package/.agents/agents/acceptance-critic.md +1 -2
  3. package/.agents/docs/SDLC.md +12 -9
  4. package/.agents/docs/agentrc-reference.json +63 -58
  5. package/.agents/docs/configuration.md +275 -227
  6. package/.agents/docs/execution-reference.md +13 -14
  7. package/.agents/docs/quality-gates.md +195 -23
  8. package/.agents/instructions.md +2 -5
  9. package/.agents/rules/git-conventions-reference.md +27 -27
  10. package/.agents/rules/git-conventions.md +4 -2
  11. package/.agents/rules/known-tooling-behavior.md +66 -30
  12. package/.agents/rules/testing-standards.md +35 -71
  13. package/.agents/runtime-deps.json +2 -2
  14. package/.agents/schemas/agentrc.schema.json +1955 -1410
  15. package/.agents/schemas/lifecycle/README.md +21 -14
  16. package/.agents/schemas/lifecycle/ledger-record.schema.json +76 -22
  17. package/.agents/schemas/story-deliver-terminal.schema.json +2 -2
  18. package/.agents/scripts/README.md +16 -29
  19. package/.agents/scripts/apply-quality-bootstrap.js +27 -34
  20. package/.agents/scripts/audit-to-stories.js +160 -41
  21. package/.agents/scripts/bootstrap.js +28 -26
  22. package/.agents/scripts/check-baseline-drift.js +73 -13
  23. package/.agents/scripts/check-baseline-scope.js +362 -0
  24. package/.agents/scripts/check-dead-exports.js +9 -1
  25. package/.agents/scripts/check-gherkin-corpus.js +508 -0
  26. package/.agents/scripts/check-knip-entries.js +159 -0
  27. package/.agents/scripts/check-lifecycle-lint.js +108 -124
  28. package/.agents/scripts/check-schema-references.js +1 -1
  29. package/.agents/scripts/diagnose-friction.js +7 -4
  30. package/.agents/scripts/generate-config-docs.js +263 -171
  31. package/.agents/scripts/install-matrix-assert.js +0 -1
  32. package/.agents/scripts/lib/ITicketingProvider.js +0 -58
  33. package/.agents/scripts/lib/audit-baselines/staleness.js +6 -6
  34. package/.agents/scripts/lib/audit-baselines/trend.js +7 -8
  35. package/.agents/scripts/lib/audit-baselines/weights.js +4 -5
  36. package/.agents/scripts/lib/audit-suite/checklist-threading.js +1 -1
  37. package/.agents/scripts/lib/audit-to-stories/build-story-body.js +81 -35
  38. package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +185 -0
  39. package/.agents/scripts/lib/baselines/envelope.js +41 -60
  40. package/.agents/scripts/lib/baselines/git-base.js +30 -37
  41. package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +103 -0
  42. package/.agents/scripts/lib/baselines/kinds/_crap-read.js +150 -0
  43. package/.agents/scripts/lib/baselines/kinds/crap.js +25 -65
  44. package/.agents/scripts/lib/baselines/orphan-pruner.js +233 -0
  45. package/.agents/scripts/lib/baselines/refresh-service.js +6 -8
  46. package/.agents/scripts/lib/baselines/scope-assert.js +223 -0
  47. package/.agents/scripts/lib/baselines/scope-inventory.js +314 -0
  48. package/.agents/scripts/lib/bdd-step-index.js +326 -0
  49. package/.agents/scripts/lib/bootstrap/install-ledger.js +5 -3
  50. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +4 -6
  51. package/.agents/scripts/lib/bootstrap/manifest.js +17 -40
  52. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +12 -59
  53. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +62 -2
  54. package/.agents/scripts/lib/checks/loop-health.js +9 -37
  55. package/.agents/scripts/lib/child-exec.js +193 -0
  56. package/.agents/scripts/lib/cli/standard-args.js +1 -1
  57. package/.agents/scripts/lib/cli-args.js +64 -0
  58. package/.agents/scripts/lib/close-validation/gates.js +2 -2
  59. package/.agents/scripts/lib/close-validation/runner.js +3 -3
  60. package/.agents/scripts/lib/config/acceptance-eval.js +5 -52
  61. package/.agents/scripts/lib/config/commands.js +3 -5
  62. package/.agents/scripts/lib/config/explain.js +5 -7
  63. package/.agents/scripts/lib/config/gates/bundle-size.schema.js +32 -6
  64. package/.agents/scripts/lib/config/gates/coverage.schema.js +25 -5
  65. package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +12 -2
  66. package/.agents/scripts/lib/config/gates/crap.schema.js +68 -23
  67. package/.agents/scripts/lib/config/gates/duplication.schema.js +29 -17
  68. package/.agents/scripts/lib/config/gates/index.js +5 -2
  69. package/.agents/scripts/lib/config/gates/lighthouse.schema.js +34 -6
  70. package/.agents/scripts/lib/config/gates/lint.schema.js +11 -2
  71. package/.agents/scripts/lib/config/gates/maintainability.schema.js +37 -15
  72. package/.agents/scripts/lib/config/gates/mutation.schema.js +15 -3
  73. package/.agents/scripts/lib/config/gates/shared.js +58 -9
  74. package/.agents/scripts/lib/config/github.js +0 -1
  75. package/.agents/scripts/lib/config/limits.js +3 -48
  76. package/.agents/scripts/lib/config/qa.js +105 -0
  77. package/.agents/scripts/lib/config/runners.js +38 -16
  78. package/.agents/scripts/lib/config/temp-paths.js +6 -5
  79. package/.agents/scripts/lib/config-settings-schema-delivery.js +245 -56
  80. package/.agents/scripts/lib/config-settings-schema-quality.js +209 -29
  81. package/.agents/scripts/lib/config-settings-schema.js +386 -39
  82. package/.agents/scripts/lib/crap-baseline-join.js +126 -9
  83. package/.agents/scripts/lib/crap-utils.js +84 -520
  84. package/.agents/scripts/lib/dead-exports-knip.js +79 -10
  85. package/.agents/scripts/lib/degraded-mode.js +2 -2
  86. package/.agents/scripts/lib/dependency-parser.js +20 -7
  87. package/.agents/scripts/lib/doc-tiers.js +3 -3
  88. package/.agents/scripts/lib/feedback-loop/graduator-core.js +46 -104
  89. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +10 -8
  90. package/.agents/scripts/lib/findings/provenance-field.js +135 -0
  91. package/.agents/scripts/lib/findings/route-finding.js +57 -8
  92. package/.agents/scripts/lib/fs-walk.js +52 -0
  93. package/.agents/scripts/lib/git-branch-lifecycle.js +2 -2
  94. package/.agents/scripts/lib/git-utils.js +16 -36
  95. package/.agents/scripts/lib/knip-config-resolver.js +181 -0
  96. package/.agents/scripts/lib/knip-entry-sync.js +508 -0
  97. package/.agents/scripts/lib/observability/metrics-ledger.js +1 -1
  98. package/.agents/scripts/lib/observability/runtime-friction.js +10 -0
  99. package/.agents/scripts/lib/observability/signal-validator.js +5 -85
  100. package/.agents/scripts/lib/observability/signals-writer.js +19 -62
  101. package/.agents/scripts/lib/observability/source-classifier.js +5 -7
  102. package/.agents/scripts/lib/observability/terse-result.js +3 -3
  103. package/.agents/scripts/lib/orchestration/behind-recovery.js +114 -0
  104. package/.agents/scripts/lib/orchestration/ceremony-routing.js +7 -8
  105. package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +34 -33
  106. package/.agents/scripts/lib/orchestration/code-review.js +2 -2
  107. package/.agents/scripts/lib/orchestration/complexity-gate.js +43 -161
  108. package/.agents/scripts/lib/orchestration/diff-magnitude.js +4 -4
  109. package/.agents/scripts/lib/orchestration/label-transitions.js +3 -2
  110. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +12 -38
  111. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +5 -6
  112. package/.agents/scripts/lib/orchestration/plan-metrics.js +2 -3
  113. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +7 -26
  114. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +69 -5
  115. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +69 -13
  116. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +49 -0
  117. package/.agents/scripts/lib/orchestration/{lifecycle/listeners/watcher.js → pr-watch.js} +58 -208
  118. package/.agents/scripts/lib/orchestration/resolve-stories.js +77 -50
  119. package/.agents/scripts/lib/orchestration/review-providers/codex.js +1 -1
  120. package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +130 -0
  121. package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -16
  122. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +1 -1
  123. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +37 -26
  124. package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +376 -0
  125. package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +161 -151
  126. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +15 -3
  127. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +10 -15
  128. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +5 -0
  129. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +157 -0
  130. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +0 -14
  131. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +59 -25
  132. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +20 -31
  133. package/.agents/scripts/lib/orchestration/spec-spill.js +17 -3
  134. package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +7 -6
  135. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +2 -1
  136. package/.agents/scripts/lib/orchestration/task-body-validator.js +4 -1
  137. package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -127
  138. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +116 -1
  139. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +1 -1
  140. package/.agents/scripts/lib/orchestration/ticket-validator.js +38 -0
  141. package/.agents/scripts/lib/orchestration/ticketing/reads.js +5 -5
  142. package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -4
  143. package/.agents/scripts/lib/orchestration/verify-tier-repair.js +107 -0
  144. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -87
  145. package/.agents/scripts/lib/signals/detectors/common.js +1 -1
  146. package/.agents/scripts/lib/signals/index.js +8 -6
  147. package/.agents/scripts/lib/signals/schema.js +20 -25
  148. package/.agents/scripts/lib/signals/write.js +8 -8
  149. package/.agents/scripts/lib/story-body/footer-block.js +97 -0
  150. package/.agents/scripts/lib/story-body/story-body.js +18 -81
  151. package/.agents/scripts/lib/temp-retention.js +1 -1
  152. package/.agents/scripts/lib/templates/decomposer-prompts.js +16 -14
  153. package/.agents/scripts/lib/ticket-body-sections.js +4 -5
  154. package/.agents/scripts/lib/wave-runner/footprint.js +306 -0
  155. package/.agents/scripts/lib/wave-runner/ready-set.js +198 -181
  156. package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +13 -45
  157. package/.agents/scripts/lib/worktree/lifecycle/reap.js +4 -5
  158. package/.agents/scripts/lib/worktree-manager.js +2 -3
  159. package/.agents/scripts/lint-label-vocabulary.js +2 -24
  160. package/.agents/scripts/pr-watch-with-update.js +7 -5
  161. package/.agents/scripts/providers/github/blocked-by-add.js +25 -10
  162. package/.agents/scripts/providers/github/cache.js +2 -2
  163. package/.agents/scripts/providers/github/comments.js +6 -28
  164. package/.agents/scripts/providers/github/compose.js +0 -15
  165. package/.agents/scripts/providers/github/errors.js +10 -27
  166. package/.agents/scripts/providers/github/request-helpers.js +1 -2
  167. package/.agents/scripts/providers/github/sub-issues.js +10 -218
  168. package/.agents/scripts/providers/github.js +4 -7
  169. package/.agents/scripts/prune-baseline-orphans.js +181 -0
  170. package/.agents/scripts/resolve-stories.js +21 -7
  171. package/.agents/scripts/run-lint.js +61 -61
  172. package/.agents/scripts/run-test-profile.js +6 -6
  173. package/.agents/scripts/run-verify.js +48 -30
  174. package/.agents/scripts/single-story-close.js +20 -0
  175. package/.agents/scripts/single-story-init.js +12 -35
  176. package/.agents/scripts/stories-wave-tick.js +192 -9
  177. package/.agents/scripts/update-dead-exports-baseline.js +321 -0
  178. package/.agents/skills/core/gates-and-baselines/SKILL.md +2 -2
  179. package/.agents/skills/skills.index.json +1 -11
  180. package/.agents/workflows/audit-documentation.md +5 -6
  181. package/.agents/workflows/audit-to-stories.md +28 -2
  182. package/.agents/workflows/helpers/audit-lens-core.md +11 -12
  183. package/.agents/workflows/helpers/code-quality-guardrails.md +15 -14
  184. package/.agents/workflows/helpers/code-review.md +3 -8
  185. package/.agents/workflows/helpers/deliver-reference.md +30 -2
  186. package/.agents/workflows/helpers/deliver-story-reference.md +84 -16
  187. package/.agents/workflows/helpers/plan-reference.md +76 -0
  188. package/.agents/workflows/helpers/worktree-lifecycle.md +1 -2
  189. package/.agents/workflows/mandrel-update.md +10 -10
  190. package/.agents/workflows/qa-assist.md +15 -20
  191. package/.agents/workflows/qa-explore.md +9 -8
  192. package/README.md +1 -1
  193. package/docs/CHANGELOG.md +58 -0
  194. package/lib/migrations/index.js +2 -0
  195. package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +127 -0
  196. package/package.json +14 -5
  197. package/.agents/schemas/lifecycle/checkpoint.written.schema.json +0 -13
  198. package/.agents/schemas/lifecycle/close-validate.end.schema.json +0 -18
  199. package/.agents/schemas/lifecycle/close-validate.start.schema.json +0 -13
  200. package/.agents/schemas/lifecycle/code-review.end.schema.json +0 -30
  201. package/.agents/schemas/lifecycle/code-review.start.schema.json +0 -12
  202. package/.agents/schemas/lifecycle/intervention.recorded.schema.json +0 -15
  203. package/.agents/schemas/lifecycle/loop.tick.schema.json +0 -20
  204. package/.agents/schemas/lifecycle/notification.emitted.schema.json +0 -18
  205. package/.agents/schemas/lifecycle/pr.created.schema.json +0 -14
  206. package/.agents/schemas/lifecycle/retro.end.schema.json +0 -16
  207. package/.agents/schemas/lifecycle/retro.start.schema.json +0 -12
  208. package/.agents/schemas/lifecycle/story.blocked.schema.json +0 -13
  209. package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +0 -17
  210. package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +0 -15
  211. package/.agents/schemas/lifecycle/story.merged.schema.json +0 -13
  212. package/.agents/scripts/check-gherkin-placeholders.js +0 -663
  213. package/.agents/scripts/check-lifecycle-doc-drift.js +0 -411
  214. package/.agents/scripts/lib/audit-suite/cli.js +0 -64
  215. package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +0 -202
  216. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +0 -212
  217. package/.agents/scripts/lib/checks/baseline-drift-main-checkout.js +0 -104
  218. package/.agents/scripts/lib/checks/push-hook-parity.js +0 -106
  219. package/.agents/scripts/lib/checks/windows-coverage-noise-floor.js +0 -92
  220. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +0 -81
  221. package/.agents/scripts/lib/checks/worktree-residue-biome.js +0 -55
  222. package/.agents/scripts/lib/crap-baseline-index.js +0 -46
  223. package/.agents/scripts/lib/crap-utils-incremental.js +0 -113
  224. package/.agents/scripts/lib/dynamic-workflow/capability.js +0 -396
  225. package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +0 -335
  226. package/.agents/scripts/lib/mutation/baseline-snapshot.js +0 -239
  227. package/.agents/scripts/lib/mutation/config-detector.js +0 -119
  228. package/.agents/scripts/lib/mutation/stryker-runner.js +0 -306
  229. package/.agents/scripts/lib/mutation/survivor-report.js +0 -160
  230. package/.agents/scripts/lib/observability/active-story-env.js +0 -170
  231. package/.agents/scripts/lib/observability/tool-trace-hook.js +0 -456
  232. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +0 -111
  233. package/.agents/scripts/lib/orchestration/context-envelope.js +0 -277
  234. package/.agents/scripts/lib/orchestration/detectors-phase.js +0 -194
  235. package/.agents/scripts/lib/orchestration/lifecycle/bus.js +0 -309
  236. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +0 -181
  237. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +0 -229
  238. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +0 -54
  239. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +0 -344
  240. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +0 -114
  241. package/.agents/scripts/lib/orchestration/pr-base-guard.js +0 -37
  242. package/.agents/scripts/lib/orchestration/resolves-token.js +0 -127
  243. package/.agents/scripts/lib/orchestration/spec-section-validator.js +0 -130
  244. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +0 -55
  245. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +0 -211
  246. package/.agents/scripts/lib/planning-corpus.js +0 -37
  247. package/.agents/scripts/lib/qa/coverage-report.js +0 -181
  248. package/.agents/scripts/lib/qa/propose-missing-test.js +0 -95
  249. package/.agents/scripts/lib/qa/qa-context-hydrator.js +0 -217
  250. package/.agents/scripts/lib/signals/detectors/index.js +0 -14
  251. package/.agents/scripts/lib/signals/detectors/retry.js +0 -253
  252. package/.agents/scripts/lib/signals/detectors/rework.js +0 -167
  253. package/.agents/scripts/lib/signals/read.js +0 -268
  254. package/.agents/scripts/lib/signals/span-tree.js +0 -291
  255. package/.agents/scripts/lib/story-lifecycle.js +0 -194
  256. package/.agents/scripts/lib/story-plan.js +0 -379
  257. package/.agents/scripts/lib/util/phase-timer-state.js +0 -72
  258. package/.agents/scripts/lib/util/phase-timer.js +0 -163
  259. package/.agents/scripts/lib/workers/combined-mi-crap-worker.js +0 -169
  260. package/.agents/scripts/lint-baseline.js +0 -507
  261. package/.agents/scripts/providers/github/prs.js +0 -103
  262. package/.agents/scripts/signals-view.js +0 -309
  263. package/.agents/scripts/story-plan.js +0 -370
  264. package/.agents/scripts/sync-branch-from-base.js +0 -149
  265. package/.agents/scripts/validate-docs-freshness.js +0 -314
  266. package/.agents/skills/core/diagnose-friction/SKILL.md +0 -78
  267. package/.agents/workflows/helpers/signals.md +0 -112
package/.agents/README.md CHANGED
@@ -293,7 +293,7 @@ a single vendored manifest that ships inside the bundle:
293
293
 
294
294
  - **[`runtime-deps.json`](runtime-deps.json)** — the single source of
295
295
  truth. Its `dependencies` block lists the **required** packages (`ajv`,
296
- `ajv-formats`, `js-yaml`, `minimatch`, `picomatch`, `string-argv`,
296
+ `ajv-formats`, `js-yaml`, `minimatch`, `picomatch`,
297
297
  `typhonjs-escomplex`); its `optionalDependencies` block lists packages
298
298
  used behind graceful-degradation paths (`typescript` for TS-source
299
299
  scoring in the maintainability engine, `chokidar` for `quality:watch`,
@@ -360,7 +360,6 @@ refused by `/deliver`. The execution-model contract is owned by
360
360
  | Every `.agentrc.json` key, default, and override | [`docs/configuration.md`](docs/configuration.md) (under `.agents/`) |
361
361
  | Quality-gate runbooks (CRAP, MI, lint, friction) plus the baseline envelope, component model, and writer/reader contract | [`.agents/docs/quality-gates.md`](docs/quality-gates.md) |
362
362
  | Slash-command workflow definitions | [`workflows/`](workflows/) |
363
- | Render the signals span-tree (debug helper) | [`workflows/helpers/signals.md`](workflows/helpers/signals.md) |
364
363
  | Role-scoped spawn boot contexts | [`agents/`](agents/) |
365
364
  | Domain-agnostic baseline rules | [`rules/`](rules/) |
366
365
  | Skill library (core process + stack guardrails) | [`skills/core/`](skills/core/) · [`skills/stack/`](skills/stack/) |
@@ -687,27 +686,24 @@ The lease primitive lives in
687
686
  [`scripts/lib/orchestration/ticket-lease.js`](scripts/lib/orchestration/ticket-lease.js).
688
687
  Rather than inventing a new state column, the lease rides the ticket's
689
688
  existing **assignees** field: the single assignee *is* the lease owner.
690
- Liveness is decided by the owner's last-heartbeat timestamp compared against
691
- a configurable TTL (`delivery.lease.ttlMs`).
692
-
693
- > **In practice the lease always fails closed.** There is no live heartbeat
694
- > source the `story.heartbeat` emitter was structurally inert and has been
695
- > deleted (A22) so every guard anchors the owner's heartbeat to *now*,
696
- > making **any** foreign claim read as live. The **stale-claim reclaim** row
697
- > below is therefore unreachable in normal operation: a stranded claim is
698
- > cleared with `--steal`, never by TTL expiry. The TTL and the reclaim branch
699
- > remain as a seam for a caller that supplies its own `heartbeatAt`.
700
-
701
- The model has five behaviours, all expressed through `acquireLease` /
689
+
690
+ > **The lease fails closed.** It shipped with a TTL (`delivery.lease.ttlMs`)
691
+ > that reclaimed a claim whose owner's heartbeat had gone stale — but the
692
+ > `story.heartbeat` emitter was structurally inert and was deleted (A22),
693
+ > after which every guard anchored the heartbeat to *now* so **any** foreign
694
+ > claim read as live. Story #5006 deleted the TTL, the heartbeat parameter
695
+ > and the reclaim branch: a foreign claim now refuses unconditionally, and a
696
+ > stranded one is cleared with `--steal`.
697
+
698
+ The model has four behaviours, all expressed through `acquireLease` /
702
699
  `releaseLease`:
703
700
 
704
701
  | Behaviour | When it fires | Outcome |
705
702
  | --------- | ------------- | ------- |
706
703
  | **Acquire by self-assign** | The ticket is unassigned. | The operator is written to `assignees`; the run proceeds (`reason: 'unclaimed'`). |
707
704
  | **Re-affirm a self-held claim** | The operator already holds the lease. | No write; the run proceeds (`reason: 'already-held'`). |
708
- | **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'`). |
709
- | **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. |
710
- | **`--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. |
705
+ | **Refuse-if-foreign** | A *different* operator holds the lease. | The acquire **fails closed** — the run refuses to start and names the current owner so you know who to coordinate with (`reason: 'held'`). |
706
+ | **`--steal` override** | A foreign claim exists and the operator passes `--steal`. | The claim is forcibly transferred (`reason: 'stolen'`). This is the **only** way past a foreign claim. |
711
707
 
712
708
  On a clean completion the holder **releases** the lease (clears the
713
709
  assignment), but only when it still holds it — a late release on a ticket
@@ -81,8 +81,7 @@ from the evidence.
81
81
  You are handed **one cluster** of acceptance criteria to score. You evaluate
82
82
  exactly the criteria in that cluster and emit one verdict record per criterion.
83
83
  You do **not** decide how many clusters exist, re-slice the criteria, or merge
84
- clusters — the caller owns clustering (`ceil(totalACs / clusterCeiling)` with
85
- its clamp).
84
+ clusters — the caller owns clustering.
86
85
 
87
86
  ## Per-criterion evaluation
88
87
 
@@ -44,14 +44,17 @@ From zero to shipped:
44
44
  resolves their dependency graph from live state — body edges union native
45
45
  GitHub `blocked_by` edges, every blocker checked against its real issue
46
46
  state, so a Story whose blocker landed in an earlier plan run is simply
47
- ready. `/deliver` owns input resolution and `depends_on` sequencing only;
47
+ ready. `/deliver` owns input resolution and dispatch order — the declared
48
+ `depends_on` edges plus a delivery-time file-overlap guard that withholds
49
+ two Stories whose footprints would race the same path (see
50
+ [`architecture.md` § Scheduler safety mechanics](../../docs/architecture.md));
48
51
  every Story runs through the single v2 delivery engine
49
52
  [`helpers/deliver-story`](../workflows/helpers/deliver-story.md) —
50
53
  init → implement → acceptance self-eval → ceremony → close → CI watch →
51
54
  confirm-merge — which owns its own per-step detail. For a multi-Story run,
52
- `/deliver` sequences ready Stories by `depends_on` and runs the per-run
53
- epilogue (audit roster · follow-up roll-up · sibling coherence) once after
54
- the last Story lands.
55
+ `/deliver` sequences ready Stories by `depends_on` plus that footprint
56
+ guard — and runs the per-run epilogue (audit roster · follow-up roll-up ·
57
+ sibling coherence) once after the last Story lands.
55
58
 
56
59
  That is the whole happy path. Everything below is **detail** — branching
57
60
  conventions, HITL escalation, audit lenses — that you only need when the
@@ -62,9 +65,9 @@ rather than re-documenting the ceremony they own.
62
65
  ## Core Principles
63
66
 
64
67
  - **Layered state stores with explicit precedence.** Ticket status lives
65
- in GitHub Issues and Labels; the lifecycle bus
66
- (`temp/run-<id>/lifecycle.ndjson`) is the canonical resume target for
67
- in-flight runs; structured comments (`verification-results`, retro) are
68
+ in GitHub Issues and Labels; the lifecycle ledger
69
+ (`lifecycle.ndjson`) records merge-terminal outcomes for post-hoc
70
+ attribution; structured comments (`verification-results`, retro) are
68
71
  the operator-visible rollup. The
69
72
  stores, their owners, and their conflict-resolution rules are listed in
70
73
  [§ State stores](#state-stores) — that matrix is the single source of
@@ -109,7 +112,7 @@ on-disk layout resolved by
109
112
  | --- | --- | --- | --- | --- |
110
113
  | 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. |
111
114
  | `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. |
112
- | 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. |
115
+ | Lifecycle ledger NDJSON | `appendLedgerEvent` (`lib/orchestration/lifecycle/emit-ledger-event.js`) a bare `appendFileSync` from the close path; Story #5024 retired the `LedgerWriter` listener that preceded it | Append-only line write to the scope-resolved `lifecycle.ndjson` | `(storyId, event)` — one record per merge-terminal outcome | Records the two merge-terminal outcomes (`merge.unlanded`, `merge.flip-failed`) for post-hoc attribution. Labels remain authoritative for current ticket state. |
113
116
  | 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. |
114
117
  | 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. |
115
118
  | 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. |
@@ -239,7 +242,7 @@ self-eval, ceremony, close, CI watch, confirm-merge, cleanup) lives in the
239
242
  | Mode | Entry point | When to use |
240
243
  | --- | --- | --- |
241
244
  | **Single Story** | `/deliver <storyId>` | Deliver one Story end-to-end; ends with a PR open to `main`. |
242
- | **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. |
245
+ | **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; a delivery-time file-overlap guard additionally withholds two Stories whose footprints would race the same path (`delivery.deliverRunner.footprintGuard`). Each lands through its own PR, and the per-run epilogue runs after the set lands. |
243
246
  | **Story worker (internal)** | *helper* `helpers/deliver-story <storyId>` | Per-Story engine invoked internally by `/deliver`; not an operator slash command. |
244
247
 
245
248
  The single operator-facing entry point is `/deliver`. It performs no
@@ -14,7 +14,6 @@
14
14
  "patterns.md"
15
15
  ],
16
16
  "commands": {
17
- "lintBaseline": "npx eslint . --format json",
18
17
  "test": "npm test",
19
18
  "typecheck": null,
20
19
  "formatCheck": "npx biome format .",
@@ -61,8 +60,7 @@
61
60
  "story-closing",
62
61
  "operator-message",
63
62
  "merge.unlanded",
64
- "merge.flip-failed",
65
- "loop.tick"
63
+ "merge.flip-failed"
66
64
  ]
67
65
  }
68
66
  },
@@ -76,14 +74,14 @@
76
74
  ],
77
75
  "failOnSharedEditors": false,
78
76
  "requireExplicitCrossStoryDeps": false,
79
- "failOnRegistryConflicts": false,
80
- "failOnLargeFanOut": false,
81
- "largeFanOutThreshold": 10,
82
77
  "crossCuttingRegistries": [
83
78
  "lib/orchestration/lifecycle/listeners/index.js",
84
79
  "**/listeners/index.js",
85
80
  "**/handlers/index.js"
86
81
  ],
82
+ "failOnRegistryConflicts": false,
83
+ "failOnLargeFanOut": false,
84
+ "largeFanOutThreshold": 10,
87
85
  "navigation": {
88
86
  "routeGlobs": [],
89
87
  "navRegistry": []
@@ -93,18 +91,6 @@
93
91
  "execution": {
94
92
  "timeoutMs": 600000
95
93
  },
96
- "lease": {
97
- "ttlMs": 900000
98
- },
99
- "ci": {
100
- "watch": {
101
- "pollIntervalMs": 10000,
102
- "maxPolls": 180,
103
- "maxResumes": 3,
104
- "attachWindowMs": 1200000
105
- },
106
- "autoMerge": "trust-ci"
107
- },
108
94
  "docsFreshness": {
109
95
  "paths": ["README.md"]
110
96
  },
@@ -119,7 +105,8 @@
119
105
  }
120
106
  },
121
107
  "deliverRunner": {
122
- "concurrencyCap": 3
108
+ "concurrencyCap": 3,
109
+ "footprintGuard": "enforce"
123
110
  },
124
111
  "worktreeIsolation": {
125
112
  "enabled": true,
@@ -143,43 +130,6 @@
143
130
  "repeatCount": 3
144
131
  }
145
132
  },
146
- "mergeWatch": {
147
- "intervalSeconds": 30,
148
- "maxBudgetSeconds": 3600
149
- },
150
- "codeReview": {
151
- "providers": [
152
- {
153
- "name": "native"
154
- },
155
- {
156
- "name": "security-review",
157
- "scopes": ["story"],
158
- "optional": true
159
- },
160
- {
161
- "name": "ultrareview",
162
- "scopes": ["story"],
163
- "manualPrompt": true,
164
- "when": {
165
- "label": "risk::high"
166
- }
167
- }
168
- ],
169
- "maxFixAttempts": 3,
170
- "maxFixScopeFiles": 5,
171
- "autoFixSeverity": "medium"
172
- },
173
- "routing": {
174
- "roleScopedAgents": true,
175
- "freshCriticSampleRate": 0.2,
176
- "ceremonyProfile": "standard",
177
- "closeAndLand": true
178
- },
179
- "feedbackLoop": {
180
- "auditResultsAutoFile": true,
181
- "retroProposals": true
182
- },
183
133
  "quality": {
184
134
  "gateScoping": {
185
135
  "scope": "diff",
@@ -346,12 +296,57 @@
346
296
  "navRegistry": []
347
297
  }
348
298
  },
299
+ "mergeWatch": {
300
+ "intervalSeconds": 30,
301
+ "maxBudgetSeconds": 3600
302
+ },
303
+ "codeReview": {
304
+ "providers": [
305
+ {
306
+ "name": "native"
307
+ },
308
+ {
309
+ "name": "security-review",
310
+ "scopes": ["story"],
311
+ "optional": true
312
+ },
313
+ {
314
+ "name": "ultrareview",
315
+ "scopes": ["story"],
316
+ "manualPrompt": true,
317
+ "when": {
318
+ "label": "risk::high"
319
+ }
320
+ }
321
+ ],
322
+ "maxFixAttempts": 3,
323
+ "maxFixScopeFiles": 5,
324
+ "autoFixSeverity": "medium"
325
+ },
349
326
  "refactorStage": {
350
327
  "enabled": false
351
328
  },
352
329
  "acceptanceEval": {
353
- "maxRounds": 2,
354
- "clusterCeiling": 4
330
+ "maxRounds": 2
331
+ },
332
+ "feedbackLoop": {
333
+ "auditResultsAutoFile": true,
334
+ "retroProposals": true
335
+ },
336
+ "ci": {
337
+ "watch": {
338
+ "pollIntervalMs": 10000,
339
+ "maxPolls": 180,
340
+ "maxResumes": 3,
341
+ "attachWindowMs": 1200000
342
+ },
343
+ "autoMerge": "trust-ci"
344
+ },
345
+ "routing": {
346
+ "roleScopedAgents": true,
347
+ "freshCriticSampleRate": 0.2,
348
+ "ceremonyProfile": "standard",
349
+ "closeAndLand": true
355
350
  }
356
351
  },
357
352
  "qa": {
@@ -380,6 +375,16 @@
380
375
  "signInSkill": "stack/qa/sign-in-member"
381
376
  }
382
377
  },
378
+ "gherkinLint": {
379
+ "scopes": {
380
+ "web": {
381
+ "featureRoots": ["apps/web/tests/features"],
382
+ "stepRoots": ["apps/web/tests/steps"]
383
+ }
384
+ },
385
+ "exemptionTags": ["@skip"],
386
+ "stepWaivers": []
387
+ },
383
388
  "consoleAllowlist": ["Download the React DevTools", "[HMR]"],
384
389
  "designTokens": "src/styles/tokens.css"
385
390
  }