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
@@ -2,30 +2,37 @@
2
2
  /* node:coverage ignore file */
3
3
 
4
4
  /**
5
- * check-lifecycle-lint.js — enforce the three Tech Spec lint rules for
6
- * the lifecycle bus surface that biome's stock ruleset cannot express.
5
+ * check-lifecycle-lint.js — enforce the lifecycle lint rules that biome's
6
+ * stock ruleset cannot express.
7
7
  *
8
- * Rule 1 — "No Promise.all over listener arrays".
9
- * Files under `.agents/scripts/lib/orchestration/lifecycle/**` (the bus
10
- * + listeners surface) MUST NOT contain `Promise.all(`. The bus is a
11
- * strictly sequential mediator; parallelizing listeners breaks
12
- * repeatability and idempotency by definition. Tests under
13
- * `tests/lifecycle/**` are exempt — fixtures that prove the rule
8
+ * Rule 1 — "No Promise.all over the lifecycle surface".
9
+ * Files under `.agents/scripts/lib/orchestration/lifecycle/**` MUST NOT
10
+ * contain `Promise.all(`. The surface is the append-only ledger writer, and
11
+ * record ordering is the whole point of an append-only trail: a parallel
12
+ * write interleaves records and breaks the ordering a reader relies on.
13
+ * Tests under `tests/lifecycle/**` are exempt — fixtures that prove the rule
14
14
  * bites need to carry the pattern.
15
15
  *
16
- * Rule 2 "Wildcard-observer firewall".
17
- * Any module under `.agents/scripts/lib/orchestration/lifecycle/listeners/**`
18
- * that calls `bus.on('*', …)` MUST NOT import a side-effecting module.
19
- * The static blocklist is small (the modules that mutate GitHub state,
20
- * the worktree, or write outside `temp/run-<id>/`); we match by module
21
- * specifier suffix to keep the rule simple and stable.
16
+ * (Story #5024 narrowed the rationale. It was "the bus is a strictly
17
+ * sequential mediator; parallelizing listeners breaks repeatability", which
18
+ * stopped being the reason when the bus was deleted. The rule still guards a
19
+ * real property of what remains.)
20
+ *
21
+ * The old Rule 2 "wildcard-observer firewall", gating any module under
22
+ * `lifecycle/listeners/**` that called `bus.on('*', …)` — was deleted by
23
+ * Story #5024 along with the bus. Both halves of its predicate became
24
+ * unsatisfiable in the same commit (the directory is gone and there is no
25
+ * `bus` to call `.on` on), so it returned zero violations by construction
26
+ * rather than by verification: a gate that cannot fire, of exactly the class
27
+ * Story #5004 retired `check-gherkin-placeholders.js` for.
22
28
  *
23
29
  * Rule 3 — "Auto-merge lockout" (Story #2253 / Task #2255, Epic #2172
24
30
  * review High-1).
25
31
  * String literals containing the substring `gh pr merge` MUST NOT
26
32
  * appear in any file under `.agents/scripts/**` EXCEPT
27
- * `.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js`
28
- * (Wave 7, Story #2256). The original safety hole was an
33
+ * `lib/orchestration/single-story-close/phases/auto-merge.js` — the v2
34
+ * close path that replaced the Epic-era `AutomergeArmer` listener the rule
35
+ * was originally written against. The original safety hole was an
29
36
  * unconditional `gh pr merge <pr> --auto --squash --delete-branch`
30
37
  * call in `epic-deliver-finalize.js` that armed GitHub's native
31
38
  * auto-merge BEFORE the framework's automerge predicate evaluated
@@ -48,11 +55,12 @@
48
55
  * biome + markdownlint; a custom rule fits cleanly alongside.
49
56
  */
50
57
 
51
- import { readdirSync, readFileSync } from 'node:fs';
58
+ import { readFileSync } from 'node:fs';
52
59
  import path from 'node:path';
53
60
  import { fileURLToPath } from 'node:url';
54
61
 
55
62
  import { runAsCli } from './lib/cli-utils.js';
63
+ import { walkFilesByExtension } from './lib/fs-walk.js';
56
64
 
57
65
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
58
66
  const REPO_ROOT = path.resolve(__dirname, '..', '..');
@@ -65,7 +73,6 @@ const LIFECYCLE_DIR = path.join(
65
73
  'orchestration',
66
74
  'lifecycle',
67
75
  );
68
- const LISTENERS_SUBDIR = path.join(LIFECYCLE_DIR, 'listeners');
69
76
  const SCRIPTS_DIR = path.join(REPO_ROOT, '.agents', 'scripts');
70
77
 
71
78
  /**
@@ -102,52 +109,6 @@ const MERGE_LOCKOUT_INFRASTRUCTURE_SUFFIXES = Object.freeze([
102
109
  path.join('.agents', 'scripts', 'check-lifecycle-lint.js'),
103
110
  ]);
104
111
 
105
- /**
106
- * Static blocklist of modules that mutate state under orchestration.
107
- * Matched by `import … from '<spec>'` specifier suffix so both
108
- * relative and package imports are caught. The list is small by
109
- * intent — wildcard observers should not need ANY of these.
110
- *
111
- * Maintainers: when a future module joins the "mutates real state"
112
- * club, add it here. The lint rule is the wildcard-firewall contract;
113
- * the listeners SHOULD NOT bypass it.
114
- */
115
- const STATE_MUTATING_MODULES = Object.freeze([
116
- // GitHub state writers
117
- 'update-ticket-state.js',
118
- 'post-structured-comment.js',
119
- 'lib/orchestration/ticketing/state.js',
120
- 'lib/orchestration/ticketing/bulk.js',
121
- // git / worktree mutators
122
- 'lib/git-utils.js',
123
- 'lib/orchestration/worktree-manager.js',
124
- // notification writers
125
- 'notify.js',
126
- ]);
127
-
128
- /**
129
- * Walk a directory tree synchronously, yielding absolute paths of files
130
- * matching `.js`. The lifecycle surface is small (< 50 files in the
131
- * worst case); a streaming walker is unnecessary.
132
- */
133
- function* walkJs(dir) {
134
- let entries;
135
- try {
136
- entries = readdirSync(dir, { withFileTypes: true });
137
- } catch (err) {
138
- if (err.code === 'ENOENT') return;
139
- throw err;
140
- }
141
- for (const entry of entries) {
142
- const p = path.join(dir, entry.name);
143
- if (entry.isDirectory()) {
144
- yield* walkJs(p);
145
- } else if (entry.isFile() && entry.name.endsWith('.js')) {
146
- yield p;
147
- }
148
- }
149
- }
150
-
151
112
  /**
152
113
  * Rule 1 enforcement. Returns an array of `{ file, line, hint }`
153
114
  * violations. Inline disable comments (`// lint-lifecycle-disable`) on
@@ -158,7 +119,7 @@ export function findPromiseAllViolations(
158
119
  { read = readFileSync } = {},
159
120
  ) {
160
121
  const violations = [];
161
- for (const file of walkJs(rootDir)) {
122
+ for (const file of walkFilesByExtension(rootDir, '.js')) {
162
123
  const text = read(file, 'utf8');
163
124
  const lines = text.split('\n');
164
125
  for (let i = 0; i < lines.length; i += 1) {
@@ -169,7 +130,7 @@ export function findPromiseAllViolations(
169
130
  violations.push({
170
131
  file,
171
132
  line: i + 1,
172
- hint: 'Promise.all over listener arrays breaks bus repeatability. Listeners must run sequentially with await.',
133
+ hint: 'Promise.all on the lifecycle surface interleaves ledger writes. The ledger is append-only; writes must stay sequential.',
173
134
  });
174
135
  }
175
136
  }
@@ -177,45 +138,6 @@ export function findPromiseAllViolations(
177
138
  return violations;
178
139
  }
179
140
 
180
- /**
181
- * Rule 2 enforcement. Returns violations for any file under
182
- * `listenersDir` that BOTH (a) registers a wildcard observer
183
- * (`bus.on('*', …)`) AND (b) imports a state-mutating module.
184
- *
185
- * Files that don't register a wildcard observer are not gated; files
186
- * that wildcard-observe but only import safe modules are not gated.
187
- */
188
- export function findWildcardObserverFirewallViolations(
189
- listenersDir,
190
- { read = readFileSync, blocklist = STATE_MUTATING_MODULES } = {},
191
- ) {
192
- const violations = [];
193
- for (const file of walkJs(listenersDir)) {
194
- const text = read(file, 'utf8');
195
- const hasWildcard = /\bbus\s*\.\s*on\s*\(\s*['"`]\*['"`]/.test(text);
196
- if (!hasWildcard) continue;
197
- // Extract imported module specifiers — robust enough for ES module
198
- // imports without parsing the full AST.
199
- // `matchAll` returns an iterator of regex match arrays; using it
200
- // sidesteps the assignment-in-`while` pattern biome flags as
201
- // confusing.
202
- for (const match of text.matchAll(/\bfrom\s+['"]([^'"]+)['"]/g)) {
203
- const spec = match[1];
204
- for (const banned of blocklist) {
205
- if (spec === banned || spec.endsWith(`/${banned}`)) {
206
- violations.push({
207
- file,
208
- spec,
209
- hint: `Wildcard observers must not import state-mutating modules. Saw '${spec}'.`,
210
- });
211
- break;
212
- }
213
- }
214
- }
215
- }
216
- return violations;
217
- }
218
-
219
141
  /**
220
142
  * Strip block (`/* … *​/`) and line (`// …`) comments from a source
221
143
  * string. Pure — exported for tests so the comment-stripping contract
@@ -310,7 +232,7 @@ export function findMergeLockoutViolations(
310
232
  // CLI, only the space-delimited form is.
311
233
  const FORBIDDEN = 'gh pr merge';
312
234
  const lineRe = /(['"`])((?:\\.|(?!\1).)*)\1/g;
313
- for (const file of walkJs(rootDir)) {
235
+ for (const file of walkFilesByExtension(rootDir, '.js')) {
314
236
  // Skip the armer (intentional carrier) and the lint infrastructure.
315
237
  const allExempt = [...allowSuffixes, ...infrastructureSuffixes];
316
238
  if (allExempt.some((suffix) => file.endsWith(suffix))) continue;
@@ -350,22 +272,24 @@ export function findMergeLockoutViolations(
350
272
  async function main() {
351
273
  // Per-rule discovery.
352
274
  const v1 = findPromiseAllViolations(LIFECYCLE_DIR);
353
- const v2 = findWildcardObserverFirewallViolations(LISTENERS_SUBDIR);
354
275
  const v3 = findMergeLockoutViolations(SCRIPTS_DIR);
355
276
  const all = [
356
- ...v1.map((v) => ({ rule: 'no-promise-all-listeners', ...v })),
357
- ...v2.map((v) => ({ rule: 'wildcard-observer-firewall', ...v })),
277
+ ...v1.map((v) => ({ rule: 'no-promise-all-lifecycle', ...v })),
358
278
  ...v3.map((v) => ({ rule: 'merge-lockout', ...v })),
359
279
  ];
360
280
  if (all.length === 0) {
361
281
  process.stdout.write(
362
- '[lifecycle-lint] clean: no Promise.all over listeners; no wildcard-firewall breaches; no merge-lockout violations.\n',
282
+ '[lifecycle-lint] clean: no Promise.all on the lifecycle surface; no merge-lockout violations.\n',
363
283
  );
364
284
  return 0;
365
285
  }
366
286
  for (const v of all) {
367
- const loc = v.line ? `${v.file}:${v.line}` : v.file;
368
- process.stderr.write(`[lifecycle-lint][${v.rule}] ${loc}\n ${v.hint}\n`);
287
+ // Both finders always stamp a 1-based `line`, so there is no file-only
288
+ // fallback to render — the ternary that used to guard this was an
289
+ // unreachable branch (Story #5024).
290
+ process.stderr.write(
291
+ `[lifecycle-lint][${v.rule}] ${v.file}:${v.line}\n ${v.hint}\n`,
292
+ );
369
293
  }
370
294
  return 1;
371
295
  }
@@ -36,7 +36,7 @@
36
36
  * `` `${key}.schema.json` `` template), AND the
37
37
  * schema's stem appears literally in a JS source as the
38
38
  * key that would produce it. `lifecycle/` is loaded this
39
- * way by `lib/orchestration/lifecycle/bus.js`, and
39
+ * way by `lifecycle/emit-ledger-event.js`, and
40
40
  * `baselines/` by `lib/baselines/envelope.js`.
41
41
  *
42
42
  * BOTH halves are required. The directory evidence alone
@@ -36,6 +36,7 @@
36
36
  import { spawnSync } from 'node:child_process';
37
37
  import crypto from 'node:crypto';
38
38
  import { constants as osConstants } from 'node:os';
39
+ import { INTERCEPTOR_MAX_BUFFER_BYTES } from './lib/child-exec.js';
39
40
  import { getLimits, resolveConfig } from './lib/config-resolver.js';
40
41
  import { Logger } from './lib/Logger.js';
41
42
  import { appendSignal } from './lib/observability/signals-writer.js';
@@ -291,10 +292,12 @@ export async function main(args = process.argv.slice(2)) {
291
292
  const config = resolveConfig();
292
293
  const limits = getLimits(config);
293
294
  const executionTimeoutMs = limits.executionTimeoutMs;
294
- // Hardcoded post-reshape (Epic #1720 Story #1739). Node `spawnSync`
295
- // buffer ceiling 10 MiB is the framework-wide value used by every
296
- // child-process spawn site. An OOM symptom, not a domain knob.
297
- const executionMaxBuffer = 10485760;
295
+ // The interceptor's bound is deliberately *below* the framework-wide
296
+ // `MAX_BUFFER_BYTES` ceiling: it is a reported policy bound whose value the
297
+ // emitted friction row carries (`details.executionMaxBuffer`), not an
298
+ // overflow guard. Story #5009 moved its definition to the shared
299
+ // child-process surface so it is no longer a hand-copied literal here.
300
+ const executionMaxBuffer = INTERCEPTOR_MAX_BUFFER_BYTES;
298
301
 
299
302
  const commandStr = cmdArgs.join(' ');
300
303
  Logger.error(`[Diagnostic Interceptor] Executing: ${commandStr}`);