mandrel 2.30.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 (253) 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/ci-remediation.md +44 -1
  10. package/.agents/rules/git-conventions-reference.md +27 -27
  11. package/.agents/rules/git-conventions.md +4 -2
  12. package/.agents/rules/known-tooling-behavior.md +66 -30
  13. package/.agents/rules/testing-standards.md +35 -71
  14. package/.agents/runtime-deps.json +0 -1
  15. package/.agents/schemas/agentrc.schema.json +1939 -1400
  16. package/.agents/schemas/lifecycle/README.md +21 -14
  17. package/.agents/schemas/lifecycle/ledger-record.schema.json +76 -22
  18. package/.agents/schemas/story-deliver-terminal.schema.json +2 -2
  19. package/.agents/scripts/README.md +7 -29
  20. package/.agents/scripts/apply-quality-bootstrap.js +27 -34
  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 +136 -0
  27. package/.agents/scripts/check-lifecycle-lint.js +36 -112
  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 +0 -1
  38. package/.agents/scripts/lib/baselines/envelope.js +41 -60
  39. package/.agents/scripts/lib/baselines/git-base.js +30 -37
  40. package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +103 -0
  41. package/.agents/scripts/lib/baselines/kinds/_crap-read.js +150 -0
  42. package/.agents/scripts/lib/baselines/kinds/crap.js +25 -65
  43. package/.agents/scripts/lib/baselines/orphan-pruner.js +233 -0
  44. package/.agents/scripts/lib/baselines/refresh-service.js +6 -8
  45. package/.agents/scripts/lib/baselines/scope-assert.js +223 -0
  46. package/.agents/scripts/lib/baselines/scope-inventory.js +314 -0
  47. package/.agents/scripts/lib/bdd-step-index.js +326 -0
  48. package/.agents/scripts/lib/bootstrap/install-ledger.js +5 -3
  49. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +4 -6
  50. package/.agents/scripts/lib/bootstrap/manifest.js +17 -40
  51. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +12 -59
  52. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +62 -2
  53. package/.agents/scripts/lib/checks/loop-health.js +9 -37
  54. package/.agents/scripts/lib/child-exec.js +193 -0
  55. package/.agents/scripts/lib/cli/standard-args.js +1 -1
  56. package/.agents/scripts/lib/cli-args.js +64 -0
  57. package/.agents/scripts/lib/close-validation/gates.js +2 -2
  58. package/.agents/scripts/lib/close-validation/runner.js +3 -3
  59. package/.agents/scripts/lib/config/acceptance-eval.js +5 -52
  60. package/.agents/scripts/lib/config/commands.js +3 -5
  61. package/.agents/scripts/lib/config/explain.js +5 -7
  62. package/.agents/scripts/lib/config/gates/bundle-size.schema.js +32 -6
  63. package/.agents/scripts/lib/config/gates/coverage.schema.js +25 -5
  64. package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +12 -2
  65. package/.agents/scripts/lib/config/gates/crap.schema.js +68 -23
  66. package/.agents/scripts/lib/config/gates/duplication.schema.js +29 -17
  67. package/.agents/scripts/lib/config/gates/index.js +5 -2
  68. package/.agents/scripts/lib/config/gates/lighthouse.schema.js +34 -6
  69. package/.agents/scripts/lib/config/gates/lint.schema.js +11 -2
  70. package/.agents/scripts/lib/config/gates/maintainability.schema.js +37 -15
  71. package/.agents/scripts/lib/config/gates/mutation.schema.js +15 -3
  72. package/.agents/scripts/lib/config/gates/shared.js +58 -9
  73. package/.agents/scripts/lib/config/github.js +0 -1
  74. package/.agents/scripts/lib/config/limits.js +3 -48
  75. package/.agents/scripts/lib/config/qa.js +105 -0
  76. package/.agents/scripts/lib/config/temp-paths.js +6 -5
  77. package/.agents/scripts/lib/config-settings-schema-delivery.js +237 -56
  78. package/.agents/scripts/lib/config-settings-schema-quality.js +209 -29
  79. package/.agents/scripts/lib/config-settings-schema.js +386 -39
  80. package/.agents/scripts/lib/crap-baseline-join.js +126 -9
  81. package/.agents/scripts/lib/crap-utils.js +84 -520
  82. package/.agents/scripts/lib/dead-exports-knip.js +79 -10
  83. package/.agents/scripts/lib/degraded-mode.js +2 -2
  84. package/.agents/scripts/lib/doc-tiers.js +3 -3
  85. package/.agents/scripts/lib/feedback-loop/graduator-core.js +46 -104
  86. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +10 -8
  87. package/.agents/scripts/lib/fs-walk.js +52 -0
  88. package/.agents/scripts/lib/git-branch-lifecycle.js +2 -2
  89. package/.agents/scripts/lib/git-utils.js +16 -36
  90. package/.agents/scripts/lib/knip-entry-sync.js +469 -0
  91. package/.agents/scripts/lib/observability/metrics-ledger.js +1 -1
  92. package/.agents/scripts/lib/observability/runtime-friction.js +10 -0
  93. package/.agents/scripts/lib/observability/signal-validator.js +5 -85
  94. package/.agents/scripts/lib/observability/signals-writer.js +19 -62
  95. package/.agents/scripts/lib/observability/source-classifier.js +5 -7
  96. package/.agents/scripts/lib/observability/terse-result.js +3 -3
  97. package/.agents/scripts/lib/orchestration/behind-recovery.js +114 -0
  98. package/.agents/scripts/lib/orchestration/ceremony-routing.js +7 -8
  99. package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +34 -33
  100. package/.agents/scripts/lib/orchestration/code-review.js +2 -2
  101. package/.agents/scripts/lib/orchestration/complexity-gate.js +43 -161
  102. package/.agents/scripts/lib/orchestration/diff-magnitude.js +4 -4
  103. package/.agents/scripts/lib/orchestration/label-transitions.js +3 -2
  104. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +12 -38
  105. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +5 -6
  106. package/.agents/scripts/lib/orchestration/plan-metrics.js +2 -3
  107. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +6 -0
  108. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +0 -1
  109. package/.agents/scripts/lib/orchestration/{lifecycle/listeners/watcher.js → pr-watch.js} +58 -208
  110. package/.agents/scripts/lib/orchestration/resolve-stories.js +5 -15
  111. package/.agents/scripts/lib/orchestration/review-providers/codex.js +1 -1
  112. package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +130 -0
  113. package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -16
  114. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +1 -1
  115. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +37 -26
  116. package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +376 -0
  117. package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +161 -151
  118. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +15 -3
  119. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +10 -15
  120. package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +17 -2
  121. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +5 -0
  122. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +157 -0
  123. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +0 -14
  124. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +65 -25
  125. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +20 -31
  126. package/.agents/scripts/lib/orchestration/spec-spill.js +17 -3
  127. package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +7 -6
  128. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +2 -1
  129. package/.agents/scripts/lib/orchestration/task-body-validator.js +4 -1
  130. package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -127
  131. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +1 -1
  132. package/.agents/scripts/lib/orchestration/ticketing/reads.js +5 -5
  133. package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -4
  134. package/.agents/scripts/lib/orchestration/verify-tier-repair.js +107 -0
  135. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -87
  136. package/.agents/scripts/lib/signals/detectors/common.js +1 -1
  137. package/.agents/scripts/lib/signals/index.js +8 -6
  138. package/.agents/scripts/lib/signals/schema.js +20 -25
  139. package/.agents/scripts/lib/signals/write.js +8 -8
  140. package/.agents/scripts/lib/story-body/story-body.js +12 -59
  141. package/.agents/scripts/lib/temp-retention.js +1 -1
  142. package/.agents/scripts/lib/templates/decomposer-prompts.js +16 -14
  143. package/.agents/scripts/lib/ticket-body-sections.js +4 -5
  144. package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +13 -45
  145. package/.agents/scripts/lib/worktree/lifecycle/reap.js +4 -5
  146. package/.agents/scripts/lib/worktree-manager.js +2 -3
  147. package/.agents/scripts/lint-label-vocabulary.js +2 -24
  148. package/.agents/scripts/pr-watch-with-update.js +7 -5
  149. package/.agents/scripts/providers/github/cache.js +2 -2
  150. package/.agents/scripts/providers/github/comments.js +6 -28
  151. package/.agents/scripts/providers/github/compose.js +0 -15
  152. package/.agents/scripts/providers/github/errors.js +10 -27
  153. package/.agents/scripts/providers/github/request-helpers.js +1 -2
  154. package/.agents/scripts/providers/github/sub-issues.js +10 -218
  155. package/.agents/scripts/providers/github.js +4 -7
  156. package/.agents/scripts/prune-baseline-orphans.js +181 -0
  157. package/.agents/scripts/resolve-stories.js +0 -2
  158. package/.agents/scripts/run-lint.js +61 -61
  159. package/.agents/scripts/run-test-profile.js +6 -6
  160. package/.agents/scripts/run-verify.js +48 -30
  161. package/.agents/scripts/single-story-close.js +20 -0
  162. package/.agents/scripts/single-story-init.js +12 -35
  163. package/.agents/scripts/update-dead-exports-baseline.js +321 -0
  164. package/.agents/skills/core/gates-and-baselines/SKILL.md +2 -2
  165. package/.agents/skills/skills.index.json +2 -12
  166. package/.agents/skills/stack/qa/playwright/SKILL.md +48 -0
  167. package/.agents/workflows/audit-documentation.md +5 -6
  168. package/.agents/workflows/audit-to-stories.md +2 -2
  169. package/.agents/workflows/helpers/audit-lens-core.md +11 -12
  170. package/.agents/workflows/helpers/code-quality-guardrails.md +15 -14
  171. package/.agents/workflows/helpers/code-review.md +3 -8
  172. package/.agents/workflows/helpers/deliver-reference.md +2 -1
  173. package/.agents/workflows/helpers/deliver-story-reference.md +27 -16
  174. package/.agents/workflows/helpers/worktree-lifecycle.md +1 -2
  175. package/.agents/workflows/mandrel-update.md +10 -10
  176. package/.agents/workflows/qa-assist.md +15 -20
  177. package/.agents/workflows/qa-explore.md +9 -8
  178. package/README.md +1 -1
  179. package/docs/CHANGELOG.md +49 -0
  180. package/lib/migrations/index.js +2 -0
  181. package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +127 -0
  182. package/package.json +12 -3
  183. package/.agents/schemas/lifecycle/checkpoint.written.schema.json +0 -13
  184. package/.agents/schemas/lifecycle/close-validate.end.schema.json +0 -18
  185. package/.agents/schemas/lifecycle/close-validate.start.schema.json +0 -13
  186. package/.agents/schemas/lifecycle/code-review.end.schema.json +0 -30
  187. package/.agents/schemas/lifecycle/code-review.start.schema.json +0 -12
  188. package/.agents/schemas/lifecycle/intervention.recorded.schema.json +0 -15
  189. package/.agents/schemas/lifecycle/loop.tick.schema.json +0 -20
  190. package/.agents/schemas/lifecycle/notification.emitted.schema.json +0 -18
  191. package/.agents/schemas/lifecycle/pr.created.schema.json +0 -14
  192. package/.agents/schemas/lifecycle/retro.end.schema.json +0 -16
  193. package/.agents/schemas/lifecycle/retro.start.schema.json +0 -12
  194. package/.agents/schemas/lifecycle/story.blocked.schema.json +0 -13
  195. package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +0 -17
  196. package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +0 -15
  197. package/.agents/schemas/lifecycle/story.merged.schema.json +0 -13
  198. package/.agents/scripts/check-gherkin-placeholders.js +0 -663
  199. package/.agents/scripts/check-lifecycle-doc-drift.js +0 -411
  200. package/.agents/scripts/lib/audit-suite/cli.js +0 -64
  201. package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +0 -202
  202. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +0 -212
  203. package/.agents/scripts/lib/checks/baseline-drift-main-checkout.js +0 -104
  204. package/.agents/scripts/lib/checks/push-hook-parity.js +0 -106
  205. package/.agents/scripts/lib/checks/windows-coverage-noise-floor.js +0 -92
  206. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +0 -81
  207. package/.agents/scripts/lib/checks/worktree-residue-biome.js +0 -55
  208. package/.agents/scripts/lib/crap-baseline-index.js +0 -46
  209. package/.agents/scripts/lib/crap-utils-incremental.js +0 -113
  210. package/.agents/scripts/lib/dynamic-workflow/capability.js +0 -396
  211. package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +0 -335
  212. package/.agents/scripts/lib/mutation/baseline-snapshot.js +0 -239
  213. package/.agents/scripts/lib/mutation/config-detector.js +0 -119
  214. package/.agents/scripts/lib/mutation/stryker-runner.js +0 -306
  215. package/.agents/scripts/lib/mutation/survivor-report.js +0 -160
  216. package/.agents/scripts/lib/observability/active-story-env.js +0 -170
  217. package/.agents/scripts/lib/observability/tool-trace-hook.js +0 -456
  218. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +0 -111
  219. package/.agents/scripts/lib/orchestration/context-envelope.js +0 -277
  220. package/.agents/scripts/lib/orchestration/detectors-phase.js +0 -194
  221. package/.agents/scripts/lib/orchestration/lifecycle/bus.js +0 -309
  222. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +0 -181
  223. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +0 -229
  224. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +0 -54
  225. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +0 -344
  226. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +0 -114
  227. package/.agents/scripts/lib/orchestration/pr-base-guard.js +0 -37
  228. package/.agents/scripts/lib/orchestration/resolves-token.js +0 -127
  229. package/.agents/scripts/lib/orchestration/spec-section-validator.js +0 -130
  230. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +0 -55
  231. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +0 -211
  232. package/.agents/scripts/lib/planning-corpus.js +0 -37
  233. package/.agents/scripts/lib/qa/coverage-report.js +0 -181
  234. package/.agents/scripts/lib/qa/propose-missing-test.js +0 -95
  235. package/.agents/scripts/lib/qa/qa-context-hydrator.js +0 -217
  236. package/.agents/scripts/lib/signals/detectors/index.js +0 -14
  237. package/.agents/scripts/lib/signals/detectors/retry.js +0 -253
  238. package/.agents/scripts/lib/signals/detectors/rework.js +0 -167
  239. package/.agents/scripts/lib/signals/read.js +0 -268
  240. package/.agents/scripts/lib/signals/span-tree.js +0 -291
  241. package/.agents/scripts/lib/story-lifecycle.js +0 -194
  242. package/.agents/scripts/lib/story-plan.js +0 -379
  243. package/.agents/scripts/lib/util/phase-timer-state.js +0 -72
  244. package/.agents/scripts/lib/util/phase-timer.js +0 -163
  245. package/.agents/scripts/lib/workers/combined-mi-crap-worker.js +0 -169
  246. package/.agents/scripts/lint-baseline.js +0 -507
  247. package/.agents/scripts/providers/github/prs.js +0 -103
  248. package/.agents/scripts/signals-view.js +0 -309
  249. package/.agents/scripts/story-plan.js +0 -370
  250. package/.agents/scripts/sync-branch-from-base.js +0 -149
  251. package/.agents/scripts/validate-docs-freshness.js +0 -314
  252. package/.agents/skills/core/diagnose-friction/SKILL.md +0 -78
  253. package/.agents/workflows/helpers/signals.md +0 -112
@@ -6,7 +6,6 @@
6
6
  * `planning.*` and `delivery.*`:
7
7
  *
8
8
  * - `delivery.execution.timeoutMs` (per-process execution timeout)
9
- * - `delivery.lease.ttlMs` (assignee-as-lease staleness window — Story #3480)
10
9
  * - `delivery.signals.{rework, retry}` (performance-signal detector
11
10
  * thresholds — `hotspot` retired with Epic #4406; `churn`/`idle` dropped)
12
11
  *
@@ -14,7 +13,9 @@
14
13
  * - `maxTickets` — decomposer reviewability budget (Story #4163)
15
14
  *
16
15
  * Dropped entirely: `maxInstructionSteps`, `friction.*`, `executionMaxBuffer`,
17
- * `signals.{churn, idle}`, `delivery.preflight`, `delivery.maxTokenBudget`
16
+ * `signals.{churn, idle}`, `delivery.preflight`, `delivery.lease.ttlMs`
17
+ * (Story #5006 deleted the lease TTL: with no heartbeat source every foreign
18
+ * claim read live, so the window decided nothing), `delivery.maxTokenBudget`
18
19
  * (planning no longer sizes against a token-budget envelope; session-mass
19
20
  * ceilings are absolute in `DEFAULT_MODEL_CAPACITY`), and
20
21
  * `planning.context.{maxBytes, summaryMode}` (Story #4541 — the `applyBudget`
@@ -39,26 +40,12 @@ export const SIGNALS_DEFAULTS = Object.freeze({
39
40
  retry: Object.freeze({ repeatCount: 3 }),
40
41
  });
41
42
 
42
- /**
43
- * Default TTL for the assignee-as-lease primitive (Story #3480). A claim
44
- * whose owner's last heartbeat is older than this window is considered stale
45
- * and may be reclaimed by another operator.
46
- *
47
- * Note: no shipped caller supplies a real heartbeat — the emitter was inert
48
- * and was deleted (A22), so the guards anchor liveness to `now` and every
49
- * foreign claim reads live (fail-closed; clear a stranded claim with
50
- * `--steal`). This value is therefore only consulted by a caller that threads
51
- * its own `heartbeatAt`, and is kept as the documented default for that seam.
52
- */
53
- export const LEASE_TTL_MS_DEFAULT = 900000;
54
-
55
43
  /**
56
44
  * Framework defaults for the surviving limits surface.
57
45
  */
58
46
  export const LIMITS_DEFAULTS = Object.freeze({
59
47
  maxTickets: 80,
60
48
  executionTimeoutMs: 600000,
61
- leaseTtlMs: LEASE_TTL_MS_DEFAULT,
62
49
  signals: SIGNALS_DEFAULTS,
63
50
  });
64
51
 
@@ -94,7 +81,6 @@ function mergeSignals(userSignals) {
94
81
  * @returns {{
95
82
  * maxTickets: number,
96
83
  * executionTimeoutMs: number,
97
- * leaseTtlMs: number,
98
84
  * signals: ReturnType<typeof mergeSignals>,
99
85
  * }}
100
86
  */
@@ -107,13 +93,10 @@ export function resolveLimits(config) {
107
93
  delivery.execution && typeof delivery.execution === 'object'
108
94
  ? delivery.execution
109
95
  : {};
110
- const lease =
111
- delivery.lease && typeof delivery.lease === 'object' ? delivery.lease : {};
112
96
  return {
113
97
  maxTickets: LIMITS_DEFAULTS.maxTickets,
114
98
  executionTimeoutMs:
115
99
  execution.timeoutMs ?? LIMITS_DEFAULTS.executionTimeoutMs,
116
- leaseTtlMs: lease.ttlMs ?? LIMITS_DEFAULTS.leaseTtlMs,
117
100
  signals: mergeSignals(delivery.signals),
118
101
  };
119
102
  }
@@ -141,31 +124,3 @@ export function getLimits(config) {
141
124
  export function getSignals(config) {
142
125
  return getLimits(config).signals;
143
126
  }
144
-
145
- /**
146
- * Resolve the assignee-as-lease TTL in milliseconds (Story #3480). Standalone
147
- * accessor so the `ticket-lease` module can import it without dragging the
148
- * whole limits surface into its bundle. Precedence:
149
- *
150
- * 1. An explicit `override` (a positive finite number) — lets a caller or
151
- * test pin the TTL directly.
152
- * 2. `delivery.lease.ttlMs` from the resolved config.
153
- * 3. `LEASE_TTL_MS_DEFAULT`.
154
- *
155
- * A non-positive or non-finite override is ignored (falls through to config /
156
- * default) so a stray `0` can never collapse every claim to instantly-stale.
157
- *
158
- * @param {object | null | undefined} config
159
- * @param {number} [override]
160
- * @returns {number}
161
- */
162
- export function resolveLeaseTtlMs(config, override) {
163
- if (
164
- typeof override === 'number' &&
165
- Number.isFinite(override) &&
166
- override > 0
167
- ) {
168
- return override;
169
- }
170
- return getLimits(config).leaseTtlMs;
171
- }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * `qa.gherkinLint` accessor — the static Gherkin corpus gate's contract.
3
+ *
4
+ * The gate is **opt-in**: absent this block, `check-gherkin-corpus.js` reports
5
+ * that it is not configured and exits 0. That is not politeness. `.agents/`
6
+ * reaches a consumer by plain file copy, so every framework upgrade lands this
7
+ * gate in every project at once; a default-on corpus lint would redden the
8
+ * `lint` required check of every repo that happens to own a `.feature` file it
9
+ * never asked the framework to police.
10
+ *
11
+ * Inside the opt-in the posture inverts and the gate fails **closed** — an
12
+ * unresolvable parser or a scope that resolves no step definitions is an
13
+ * error, never a quiet pass. Both are the same blackout the gate exists to
14
+ * catch, wearing a different costume.
15
+ *
16
+ * Scopes are the load-bearing shape. Pooling every step root into one matcher
17
+ * list makes a cross-app false bind possible: a step defined only in app B's
18
+ * suite silently vouches for app A's feature, and the gate reports green on a
19
+ * corpus that cannot generate. Resolving each feature against **its own**
20
+ * scope's step roots makes that structurally impossible rather than merely
21
+ * unlikely.
22
+ */
23
+
24
+ /**
25
+ * Framework defaults for the two escape hatches. `@skip` is the conventional
26
+ * "not meant to run" tag across cucumber-js and playwright-bdd, so it is the
27
+ * default exemption; the waiver list starts empty because every entry is a
28
+ * project-specific admission that the step index guessed wrong.
29
+ */
30
+ const GHERKIN_LINT_DEFAULTS = Object.freeze({
31
+ exemptionTags: Object.freeze(['@skip']),
32
+ stepWaivers: Object.freeze([]),
33
+ });
34
+
35
+ /** Coerce a value to an array of non-empty strings. */
36
+ function stringArray(value, fallback) {
37
+ if (!Array.isArray(value)) return [...fallback];
38
+ return value.filter((item) => typeof item === 'string' && item.length > 0);
39
+ }
40
+
41
+ /**
42
+ * Normalize one scope entry into `{ name, featureRoots, stepRoots }`.
43
+ *
44
+ * @param {string} name
45
+ * @param {object} raw
46
+ * @returns {{ name: string, featureRoots: string[], stepRoots: string[] }}
47
+ */
48
+ function normalizeScope(name, raw) {
49
+ return {
50
+ name,
51
+ featureRoots: stringArray(raw?.featureRoots, []),
52
+ stepRoots: stringArray(raw?.stepRoots, []),
53
+ };
54
+ }
55
+
56
+ /**
57
+ * Normalize a raw `qa.gherkinLint` block.
58
+ *
59
+ * @param {object | null | undefined} raw
60
+ * @returns {{
61
+ * scopes: Array<{ name: string, featureRoots: string[], stepRoots: string[] }>,
62
+ * exemptionTags: string[],
63
+ * stepWaivers: string[],
64
+ * } | null} `null` when the block is absent or not an object
65
+ */
66
+ function resolveGherkinLint(raw) {
67
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;
68
+ const scopesRaw =
69
+ raw.scopes && typeof raw.scopes === 'object' && !Array.isArray(raw.scopes)
70
+ ? raw.scopes
71
+ : {};
72
+ return {
73
+ scopes: Object.keys(scopesRaw)
74
+ .sort()
75
+ .map((name) => normalizeScope(name, scopesRaw[name])),
76
+ exemptionTags: stringArray(
77
+ raw.exemptionTags,
78
+ GHERKIN_LINT_DEFAULTS.exemptionTags,
79
+ ),
80
+ stepWaivers: stringArray(
81
+ raw.stepWaivers,
82
+ GHERKIN_LINT_DEFAULTS.stepWaivers,
83
+ ),
84
+ };
85
+ }
86
+
87
+ /**
88
+ * Read the normalized `qa.gherkinLint` contract off a resolved config.
89
+ *
90
+ * @param {object | null | undefined} config
91
+ * @returns {ReturnType<typeof resolveGherkinLint>}
92
+ */
93
+ export function getGherkinLint(config) {
94
+ return resolveGherkinLint(config?.qa?.gherkinLint);
95
+ }
96
+
97
+ /**
98
+ * Module-private surface the suite drives directly, bundled behind one export
99
+ * for the same reason as `bdd-step-index.js`: `getGherkinLint` is the whole
100
+ * public API, and the normalizer and its defaults are how it is built.
101
+ */
102
+ export const __testing = Object.freeze({
103
+ GHERKIN_LINT_DEFAULTS,
104
+ resolveGherkinLint,
105
+ });
@@ -13,7 +13,7 @@
13
13
  * ├─ techspec.md
14
14
  * ├─ manifest.md (dispatch manifest)
15
15
  * ├─ retro.md (mirror of GitHub retro at Epic close)
16
- * ├─ lifecycle.ndjson (lifecycle bus ledger)
16
+ * ├─ lifecycle.ndjson (lifecycle ledger)
17
17
  * ├─ checkpoints/... (pre-v2 epic-runner state store; retained layout)
18
18
  * ├─ <name> (runArtifactPath escape hatch)
19
19
  * └─ stories/
@@ -124,7 +124,7 @@ export function _clearMainCheckoutRootCache() {
124
124
  *
125
125
  * The shared test bootstrap (`lib/test-env.js`) sets this to a fresh
126
126
  * `os.tmpdir()` directory before spawning the test runner, so any test that
127
- * reaches a writer (`signals-writer`, the lifecycle `LedgerWriter`, etc.)
127
+ * reaches a writer (`signals-writer`, `appendLedgerEvent`, etc.)
128
128
  * *without* explicitly injecting an absolute tempRoot still resolves under
129
129
  * scratch instead of the repo's real `temp/` tree. This is the single
130
130
  * injection seam: because every path helper funnels a relative root through
@@ -573,9 +573,10 @@ function storyArtifactPath(eid, sid, name, config) {
573
573
  }
574
574
 
575
575
  /**
576
- * `temp/run-<eid>/lifecycle.ndjson` — append-only lifecycle bus ledger
577
- * (Story #2510). The LedgerWriter persists every emitted/completed/failed
578
- * record here; the TraceLogger renders the companion markdown from it.
576
+ * `temp/run-<eid>/lifecycle.ndjson` — append-only lifecycle ledger
577
+ * (Story #2510). `appendLedgerEvent` persists one `emitted` record here per
578
+ * merge-terminal outcome; Story #5024 retired the `LedgerWriter` listener and
579
+ * the `TraceLogger` markdown companion that preceded it.
579
580
  *
580
581
  * The path is also the canonical input the standalone `lifecycle-emit`
581
582
  * CLI feeds to `buildDefaultListenerChain` when assembling the default