mandrel 2.31.0 → 2.32.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 (250) hide show
  1. package/.agents/README.md +13 -17
  2. package/.agents/agents/acceptance-critic.md +1 -2
  3. package/.agents/docs/SDLC.md +4 -4
  4. package/.agents/docs/agentrc-reference.json +61 -57
  5. package/.agents/docs/configuration.md +274 -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 +0 -1
  14. package/.agents/schemas/agentrc.schema.json +1939 -1400
  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 +7 -29
  19. package/.agents/scripts/apply-quality-bootstrap.js +27 -34
  20. package/.agents/scripts/bootstrap.js +28 -26
  21. package/.agents/scripts/check-baseline-drift.js +73 -13
  22. package/.agents/scripts/check-baseline-scope.js +362 -0
  23. package/.agents/scripts/check-dead-exports.js +9 -1
  24. package/.agents/scripts/check-gherkin-corpus.js +508 -0
  25. package/.agents/scripts/check-knip-entries.js +136 -0
  26. package/.agents/scripts/check-lifecycle-lint.js +36 -112
  27. package/.agents/scripts/check-schema-references.js +1 -1
  28. package/.agents/scripts/diagnose-friction.js +7 -4
  29. package/.agents/scripts/generate-config-docs.js +263 -171
  30. package/.agents/scripts/install-matrix-assert.js +0 -1
  31. package/.agents/scripts/lib/ITicketingProvider.js +0 -58
  32. package/.agents/scripts/lib/audit-baselines/staleness.js +6 -6
  33. package/.agents/scripts/lib/audit-baselines/trend.js +7 -8
  34. package/.agents/scripts/lib/audit-baselines/weights.js +4 -5
  35. package/.agents/scripts/lib/audit-suite/checklist-threading.js +1 -1
  36. package/.agents/scripts/lib/audit-to-stories/build-story-body.js +0 -1
  37. package/.agents/scripts/lib/baselines/envelope.js +41 -60
  38. package/.agents/scripts/lib/baselines/git-base.js +30 -37
  39. package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +103 -0
  40. package/.agents/scripts/lib/baselines/kinds/_crap-read.js +150 -0
  41. package/.agents/scripts/lib/baselines/kinds/crap.js +25 -65
  42. package/.agents/scripts/lib/baselines/orphan-pruner.js +233 -0
  43. package/.agents/scripts/lib/baselines/refresh-service.js +6 -8
  44. package/.agents/scripts/lib/baselines/scope-assert.js +223 -0
  45. package/.agents/scripts/lib/baselines/scope-inventory.js +314 -0
  46. package/.agents/scripts/lib/bdd-step-index.js +326 -0
  47. package/.agents/scripts/lib/bootstrap/install-ledger.js +5 -3
  48. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +4 -6
  49. package/.agents/scripts/lib/bootstrap/manifest.js +17 -40
  50. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +12 -59
  51. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +62 -2
  52. package/.agents/scripts/lib/checks/loop-health.js +9 -37
  53. package/.agents/scripts/lib/child-exec.js +193 -0
  54. package/.agents/scripts/lib/cli/standard-args.js +1 -1
  55. package/.agents/scripts/lib/cli-args.js +64 -0
  56. package/.agents/scripts/lib/close-validation/gates.js +2 -2
  57. package/.agents/scripts/lib/close-validation/runner.js +3 -3
  58. package/.agents/scripts/lib/config/acceptance-eval.js +5 -52
  59. package/.agents/scripts/lib/config/commands.js +3 -5
  60. package/.agents/scripts/lib/config/explain.js +5 -7
  61. package/.agents/scripts/lib/config/gates/bundle-size.schema.js +32 -6
  62. package/.agents/scripts/lib/config/gates/coverage.schema.js +25 -5
  63. package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +12 -2
  64. package/.agents/scripts/lib/config/gates/crap.schema.js +68 -23
  65. package/.agents/scripts/lib/config/gates/duplication.schema.js +29 -17
  66. package/.agents/scripts/lib/config/gates/index.js +5 -2
  67. package/.agents/scripts/lib/config/gates/lighthouse.schema.js +34 -6
  68. package/.agents/scripts/lib/config/gates/lint.schema.js +11 -2
  69. package/.agents/scripts/lib/config/gates/maintainability.schema.js +37 -15
  70. package/.agents/scripts/lib/config/gates/mutation.schema.js +15 -3
  71. package/.agents/scripts/lib/config/gates/shared.js +58 -9
  72. package/.agents/scripts/lib/config/github.js +0 -1
  73. package/.agents/scripts/lib/config/limits.js +3 -48
  74. package/.agents/scripts/lib/config/qa.js +105 -0
  75. package/.agents/scripts/lib/config/temp-paths.js +6 -5
  76. package/.agents/scripts/lib/config-settings-schema-delivery.js +237 -56
  77. package/.agents/scripts/lib/config-settings-schema-quality.js +209 -29
  78. package/.agents/scripts/lib/config-settings-schema.js +386 -39
  79. package/.agents/scripts/lib/crap-baseline-join.js +126 -9
  80. package/.agents/scripts/lib/crap-utils.js +84 -520
  81. package/.agents/scripts/lib/dead-exports-knip.js +79 -10
  82. package/.agents/scripts/lib/degraded-mode.js +2 -2
  83. package/.agents/scripts/lib/doc-tiers.js +3 -3
  84. package/.agents/scripts/lib/feedback-loop/graduator-core.js +46 -104
  85. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +10 -8
  86. package/.agents/scripts/lib/fs-walk.js +52 -0
  87. package/.agents/scripts/lib/git-branch-lifecycle.js +2 -2
  88. package/.agents/scripts/lib/git-utils.js +16 -36
  89. package/.agents/scripts/lib/knip-entry-sync.js +469 -0
  90. package/.agents/scripts/lib/observability/metrics-ledger.js +1 -1
  91. package/.agents/scripts/lib/observability/runtime-friction.js +10 -0
  92. package/.agents/scripts/lib/observability/signal-validator.js +5 -85
  93. package/.agents/scripts/lib/observability/signals-writer.js +19 -62
  94. package/.agents/scripts/lib/observability/source-classifier.js +5 -7
  95. package/.agents/scripts/lib/observability/terse-result.js +3 -3
  96. package/.agents/scripts/lib/orchestration/behind-recovery.js +114 -0
  97. package/.agents/scripts/lib/orchestration/ceremony-routing.js +7 -8
  98. package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +34 -33
  99. package/.agents/scripts/lib/orchestration/code-review.js +2 -2
  100. package/.agents/scripts/lib/orchestration/complexity-gate.js +43 -161
  101. package/.agents/scripts/lib/orchestration/diff-magnitude.js +4 -4
  102. package/.agents/scripts/lib/orchestration/label-transitions.js +3 -2
  103. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +12 -38
  104. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +5 -6
  105. package/.agents/scripts/lib/orchestration/plan-metrics.js +2 -3
  106. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +6 -0
  107. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +0 -1
  108. package/.agents/scripts/lib/orchestration/{lifecycle/listeners/watcher.js → pr-watch.js} +58 -208
  109. package/.agents/scripts/lib/orchestration/resolve-stories.js +5 -15
  110. package/.agents/scripts/lib/orchestration/review-providers/codex.js +1 -1
  111. package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +130 -0
  112. package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -16
  113. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +1 -1
  114. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +37 -26
  115. package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +376 -0
  116. package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +161 -151
  117. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +15 -3
  118. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +10 -15
  119. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +5 -0
  120. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +157 -0
  121. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +0 -14
  122. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +59 -25
  123. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +20 -31
  124. package/.agents/scripts/lib/orchestration/spec-spill.js +17 -3
  125. package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +7 -6
  126. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +2 -1
  127. package/.agents/scripts/lib/orchestration/task-body-validator.js +4 -1
  128. package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -127
  129. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +1 -1
  130. package/.agents/scripts/lib/orchestration/ticketing/reads.js +5 -5
  131. package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -4
  132. package/.agents/scripts/lib/orchestration/verify-tier-repair.js +107 -0
  133. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -87
  134. package/.agents/scripts/lib/signals/detectors/common.js +1 -1
  135. package/.agents/scripts/lib/signals/index.js +8 -6
  136. package/.agents/scripts/lib/signals/schema.js +20 -25
  137. package/.agents/scripts/lib/signals/write.js +8 -8
  138. package/.agents/scripts/lib/story-body/story-body.js +12 -59
  139. package/.agents/scripts/lib/temp-retention.js +1 -1
  140. package/.agents/scripts/lib/templates/decomposer-prompts.js +16 -14
  141. package/.agents/scripts/lib/ticket-body-sections.js +4 -5
  142. package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +13 -45
  143. package/.agents/scripts/lib/worktree/lifecycle/reap.js +4 -5
  144. package/.agents/scripts/lib/worktree-manager.js +2 -3
  145. package/.agents/scripts/lint-label-vocabulary.js +2 -24
  146. package/.agents/scripts/pr-watch-with-update.js +7 -5
  147. package/.agents/scripts/providers/github/cache.js +2 -2
  148. package/.agents/scripts/providers/github/comments.js +6 -28
  149. package/.agents/scripts/providers/github/compose.js +0 -15
  150. package/.agents/scripts/providers/github/errors.js +10 -27
  151. package/.agents/scripts/providers/github/request-helpers.js +1 -2
  152. package/.agents/scripts/providers/github/sub-issues.js +10 -218
  153. package/.agents/scripts/providers/github.js +4 -7
  154. package/.agents/scripts/prune-baseline-orphans.js +181 -0
  155. package/.agents/scripts/resolve-stories.js +0 -2
  156. package/.agents/scripts/run-lint.js +61 -61
  157. package/.agents/scripts/run-test-profile.js +6 -6
  158. package/.agents/scripts/run-verify.js +48 -30
  159. package/.agents/scripts/single-story-close.js +20 -0
  160. package/.agents/scripts/single-story-init.js +12 -35
  161. package/.agents/scripts/update-dead-exports-baseline.js +321 -0
  162. package/.agents/skills/core/gates-and-baselines/SKILL.md +2 -2
  163. package/.agents/skills/skills.index.json +1 -11
  164. package/.agents/workflows/audit-documentation.md +5 -6
  165. package/.agents/workflows/audit-to-stories.md +2 -2
  166. package/.agents/workflows/helpers/audit-lens-core.md +11 -12
  167. package/.agents/workflows/helpers/code-quality-guardrails.md +15 -14
  168. package/.agents/workflows/helpers/code-review.md +3 -8
  169. package/.agents/workflows/helpers/deliver-reference.md +2 -1
  170. package/.agents/workflows/helpers/deliver-story-reference.md +27 -16
  171. package/.agents/workflows/helpers/worktree-lifecycle.md +1 -2
  172. package/.agents/workflows/mandrel-update.md +10 -10
  173. package/.agents/workflows/qa-assist.md +15 -20
  174. package/.agents/workflows/qa-explore.md +9 -8
  175. package/README.md +1 -1
  176. package/docs/CHANGELOG.md +42 -0
  177. package/lib/migrations/index.js +2 -0
  178. package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +127 -0
  179. package/package.json +12 -3
  180. package/.agents/schemas/lifecycle/checkpoint.written.schema.json +0 -13
  181. package/.agents/schemas/lifecycle/close-validate.end.schema.json +0 -18
  182. package/.agents/schemas/lifecycle/close-validate.start.schema.json +0 -13
  183. package/.agents/schemas/lifecycle/code-review.end.schema.json +0 -30
  184. package/.agents/schemas/lifecycle/code-review.start.schema.json +0 -12
  185. package/.agents/schemas/lifecycle/intervention.recorded.schema.json +0 -15
  186. package/.agents/schemas/lifecycle/loop.tick.schema.json +0 -20
  187. package/.agents/schemas/lifecycle/notification.emitted.schema.json +0 -18
  188. package/.agents/schemas/lifecycle/pr.created.schema.json +0 -14
  189. package/.agents/schemas/lifecycle/retro.end.schema.json +0 -16
  190. package/.agents/schemas/lifecycle/retro.start.schema.json +0 -12
  191. package/.agents/schemas/lifecycle/story.blocked.schema.json +0 -13
  192. package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +0 -17
  193. package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +0 -15
  194. package/.agents/schemas/lifecycle/story.merged.schema.json +0 -13
  195. package/.agents/scripts/check-gherkin-placeholders.js +0 -663
  196. package/.agents/scripts/check-lifecycle-doc-drift.js +0 -411
  197. package/.agents/scripts/lib/audit-suite/cli.js +0 -64
  198. package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +0 -202
  199. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +0 -212
  200. package/.agents/scripts/lib/checks/baseline-drift-main-checkout.js +0 -104
  201. package/.agents/scripts/lib/checks/push-hook-parity.js +0 -106
  202. package/.agents/scripts/lib/checks/windows-coverage-noise-floor.js +0 -92
  203. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +0 -81
  204. package/.agents/scripts/lib/checks/worktree-residue-biome.js +0 -55
  205. package/.agents/scripts/lib/crap-baseline-index.js +0 -46
  206. package/.agents/scripts/lib/crap-utils-incremental.js +0 -113
  207. package/.agents/scripts/lib/dynamic-workflow/capability.js +0 -396
  208. package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +0 -335
  209. package/.agents/scripts/lib/mutation/baseline-snapshot.js +0 -239
  210. package/.agents/scripts/lib/mutation/config-detector.js +0 -119
  211. package/.agents/scripts/lib/mutation/stryker-runner.js +0 -306
  212. package/.agents/scripts/lib/mutation/survivor-report.js +0 -160
  213. package/.agents/scripts/lib/observability/active-story-env.js +0 -170
  214. package/.agents/scripts/lib/observability/tool-trace-hook.js +0 -456
  215. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +0 -111
  216. package/.agents/scripts/lib/orchestration/context-envelope.js +0 -277
  217. package/.agents/scripts/lib/orchestration/detectors-phase.js +0 -194
  218. package/.agents/scripts/lib/orchestration/lifecycle/bus.js +0 -309
  219. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +0 -181
  220. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +0 -229
  221. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +0 -54
  222. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +0 -344
  223. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +0 -114
  224. package/.agents/scripts/lib/orchestration/pr-base-guard.js +0 -37
  225. package/.agents/scripts/lib/orchestration/resolves-token.js +0 -127
  226. package/.agents/scripts/lib/orchestration/spec-section-validator.js +0 -130
  227. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +0 -55
  228. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +0 -211
  229. package/.agents/scripts/lib/planning-corpus.js +0 -37
  230. package/.agents/scripts/lib/qa/coverage-report.js +0 -181
  231. package/.agents/scripts/lib/qa/propose-missing-test.js +0 -95
  232. package/.agents/scripts/lib/qa/qa-context-hydrator.js +0 -217
  233. package/.agents/scripts/lib/signals/detectors/index.js +0 -14
  234. package/.agents/scripts/lib/signals/detectors/retry.js +0 -253
  235. package/.agents/scripts/lib/signals/detectors/rework.js +0 -167
  236. package/.agents/scripts/lib/signals/read.js +0 -268
  237. package/.agents/scripts/lib/signals/span-tree.js +0 -291
  238. package/.agents/scripts/lib/story-lifecycle.js +0 -194
  239. package/.agents/scripts/lib/story-plan.js +0 -379
  240. package/.agents/scripts/lib/util/phase-timer-state.js +0 -72
  241. package/.agents/scripts/lib/util/phase-timer.js +0 -163
  242. package/.agents/scripts/lib/workers/combined-mi-crap-worker.js +0 -169
  243. package/.agents/scripts/lint-baseline.js +0 -507
  244. package/.agents/scripts/providers/github/prs.js +0 -103
  245. package/.agents/scripts/signals-view.js +0 -309
  246. package/.agents/scripts/story-plan.js +0 -370
  247. package/.agents/scripts/sync-branch-from-base.js +0 -149
  248. package/.agents/scripts/validate-docs-freshness.js +0 -314
  249. package/.agents/skills/core/diagnose-friction/SKILL.md +0 -78
  250. 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
 
@@ -62,9 +62,9 @@ rather than re-documenting the ceremony they own.
62
62
  ## Core Principles
63
63
 
64
64
  - **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
65
+ in GitHub Issues and Labels; the lifecycle ledger
66
+ (`lifecycle.ndjson`) records merge-terminal outcomes for post-hoc
67
+ attribution; structured comments (`verification-results`, retro) are
68
68
  the operator-visible rollup. The
69
69
  stores, their owners, and their conflict-resolution rules are listed in
70
70
  [§ State stores](#state-stores) — that matrix is the single source of
@@ -109,7 +109,7 @@ on-disk layout resolved by
109
109
  | --- | --- | --- | --- | --- |
110
110
  | 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
111
  | `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. |
112
+ | 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
113
  | 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
114
  | 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
115
  | 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. |
@@ -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
  },
@@ -143,43 +129,6 @@
143
129
  "repeatCount": 3
144
130
  }
145
131
  },
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
132
  "quality": {
184
133
  "gateScoping": {
185
134
  "scope": "diff",
@@ -346,12 +295,57 @@
346
295
  "navRegistry": []
347
296
  }
348
297
  },
298
+ "mergeWatch": {
299
+ "intervalSeconds": 30,
300
+ "maxBudgetSeconds": 3600
301
+ },
302
+ "codeReview": {
303
+ "providers": [
304
+ {
305
+ "name": "native"
306
+ },
307
+ {
308
+ "name": "security-review",
309
+ "scopes": ["story"],
310
+ "optional": true
311
+ },
312
+ {
313
+ "name": "ultrareview",
314
+ "scopes": ["story"],
315
+ "manualPrompt": true,
316
+ "when": {
317
+ "label": "risk::high"
318
+ }
319
+ }
320
+ ],
321
+ "maxFixAttempts": 3,
322
+ "maxFixScopeFiles": 5,
323
+ "autoFixSeverity": "medium"
324
+ },
349
325
  "refactorStage": {
350
326
  "enabled": false
351
327
  },
352
328
  "acceptanceEval": {
353
- "maxRounds": 2,
354
- "clusterCeiling": 4
329
+ "maxRounds": 2
330
+ },
331
+ "feedbackLoop": {
332
+ "auditResultsAutoFile": true,
333
+ "retroProposals": true
334
+ },
335
+ "ci": {
336
+ "watch": {
337
+ "pollIntervalMs": 10000,
338
+ "maxPolls": 180,
339
+ "maxResumes": 3,
340
+ "attachWindowMs": 1200000
341
+ },
342
+ "autoMerge": "trust-ci"
343
+ },
344
+ "routing": {
345
+ "roleScopedAgents": true,
346
+ "freshCriticSampleRate": 0.2,
347
+ "ceremonyProfile": "standard",
348
+ "closeAndLand": true
355
349
  }
356
350
  },
357
351
  "qa": {
@@ -380,6 +374,16 @@
380
374
  "signInSkill": "stack/qa/sign-in-member"
381
375
  }
382
376
  },
377
+ "gherkinLint": {
378
+ "scopes": {
379
+ "web": {
380
+ "featureRoots": ["apps/web/tests/features"],
381
+ "stepRoots": ["apps/web/tests/steps"]
382
+ }
383
+ },
384
+ "exemptionTags": ["@skip"],
385
+ "stepWaivers": []
386
+ },
383
387
  "consoleAllowlist": ["Download the React DevTools", "[HMR]"],
384
388
  "designTokens": "src/styles/tokens.css"
385
389
  }