@lumenflow/cli 3.1.2 → 3.1.3

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 (389) hide show
  1. package/README.md +36 -35
  2. package/dist/agent-issues-query.js +13 -8
  3. package/dist/agent-log-issue.js +15 -4
  4. package/dist/agent-session-end.js +15 -4
  5. package/dist/agent-session.js +18 -6
  6. package/dist/backlog-prune.js +1 -1
  7. package/dist/commands/integrate.js +32 -18
  8. package/dist/config-get.js +27 -15
  9. package/dist/config-set.js +104 -37
  10. package/dist/delegation-list.js +1 -1
  11. package/dist/doctor.js +19 -13
  12. package/dist/file-delete.js +1 -1
  13. package/dist/file-edit.js +1 -1
  14. package/dist/file-read.js +1 -1
  15. package/dist/file-write.js +1 -1
  16. package/dist/flow-bottlenecks.js +1 -1
  17. package/dist/flow-report.js +10 -9
  18. package/dist/gates.js +3 -2
  19. package/dist/git-branch.js +1 -1
  20. package/dist/git-diff.js +1 -1
  21. package/dist/git-log.js +1 -1
  22. package/dist/init.js +238 -42
  23. package/dist/initiative-add-wu.js +1 -1
  24. package/dist/initiative-bulk-assign-wus.js +1 -1
  25. package/dist/initiative-create.js +2 -2
  26. package/dist/initiative-edit.js +1 -1
  27. package/dist/initiative-list.js +1 -1
  28. package/dist/initiative-plan.js +1 -3
  29. package/dist/initiative-status.js +47 -6
  30. package/dist/lane-edit.js +19 -10
  31. package/dist/lane-health.js +13 -24
  32. package/dist/lane-lock.js +4 -5
  33. package/dist/lane-setup.js +5 -5
  34. package/dist/lane-status.js +4 -5
  35. package/dist/lane-suggest.js +9 -7
  36. package/dist/lane-validate.js +4 -5
  37. package/dist/lumenflow-upgrade.js +17 -11
  38. package/dist/mem-checkpoint.js +1 -1
  39. package/dist/mem-cleanup.js +6 -23
  40. package/dist/mem-context.js +1 -1
  41. package/dist/mem-create.js +1 -1
  42. package/dist/mem-delete.js +1 -1
  43. package/dist/mem-export.js +1 -1
  44. package/dist/mem-inbox.js +1 -1
  45. package/dist/mem-init.js +1 -1
  46. package/dist/mem-ready.js +1 -1
  47. package/dist/mem-recover.js +1 -1
  48. package/dist/mem-signal.js +1 -1
  49. package/dist/mem-start.js +1 -1
  50. package/dist/mem-summarize.js +8 -7
  51. package/dist/mem-triage.js +7 -5
  52. package/dist/metrics-cli.js +1 -1
  53. package/dist/metrics-snapshot.js +1 -1
  54. package/dist/onboard.js +295 -120
  55. package/dist/orchestrate-init-status.js +12 -7
  56. package/dist/orchestrate-initiative.js +23 -12
  57. package/dist/orchestrate-monitor.js +20 -8
  58. package/dist/pack-scaffold.js +1 -1
  59. package/dist/plan-create.js +1 -3
  60. package/dist/plan-edit.js +1 -3
  61. package/dist/plan-link.js +1 -3
  62. package/dist/plan-promote.js +1 -3
  63. package/dist/release.js +1 -3
  64. package/dist/signal-cleanup.js +4 -18
  65. package/dist/state-bootstrap.js +11 -8
  66. package/dist/state-cleanup.js +5 -19
  67. package/dist/state-doctor.js +213 -9
  68. package/dist/task-claim.js +1 -1
  69. package/dist/validate.js +1 -1
  70. package/dist/workspace-init.js +61 -61
  71. package/dist/wu-block.js +1 -1
  72. package/dist/wu-brief.js +1 -1
  73. package/dist/wu-claim.js +1 -1
  74. package/dist/wu-cleanup.js +1 -1
  75. package/dist/wu-create.js +3 -3
  76. package/dist/wu-delegate.js +1 -1
  77. package/dist/wu-deps.js +1 -1
  78. package/dist/wu-done.js +66 -34
  79. package/dist/wu-edit.js +1 -1
  80. package/dist/wu-infer-lane.js +1 -1
  81. package/dist/wu-preflight.js +1 -1
  82. package/dist/wu-prep.js +1 -1
  83. package/dist/wu-proto.js +1 -1
  84. package/dist/wu-prune.js +1 -1
  85. package/dist/wu-recover.js +1 -1
  86. package/dist/wu-release.js +1 -1
  87. package/dist/wu-repair.js +1 -1
  88. package/dist/wu-sandbox.js +40 -27
  89. package/dist/wu-status.js +1 -1
  90. package/dist/wu-unblock.js +1 -1
  91. package/dist/wu-unlock-lane.js +1 -1
  92. package/dist/wu-validate.js +1 -1
  93. package/package.json +12 -8
  94. package/packs/software-delivery/constants.ts +10 -0
  95. package/packs/software-delivery/extensions.ts +140 -0
  96. package/packs/software-delivery/gate-policies.ts +134 -0
  97. package/packs/software-delivery/index.ts +8 -0
  98. package/packs/software-delivery/manifest-schema.ts +236 -0
  99. package/packs/software-delivery/manifest.ts +417 -0
  100. package/packs/software-delivery/manifest.yaml +711 -0
  101. package/packs/software-delivery/pack-registration.ts +113 -0
  102. package/packs/software-delivery/tool-impl/agent-tools.ts +263 -0
  103. package/packs/software-delivery/tool-impl/delegation-tools.ts +66 -0
  104. package/packs/software-delivery/tool-impl/flow-metrics-tools.ts +219 -0
  105. package/packs/software-delivery/tool-impl/git-runner.ts +113 -0
  106. package/packs/software-delivery/tool-impl/git-tools.ts +316 -0
  107. package/packs/software-delivery/tool-impl/index.ts +15 -0
  108. package/packs/software-delivery/tool-impl/initiative-orchestration-tools.ts +720 -0
  109. package/packs/software-delivery/tool-impl/lane-lock.ts +246 -0
  110. package/packs/software-delivery/tool-impl/memory-tools.ts +415 -0
  111. package/packs/software-delivery/tool-impl/pending-runtime-tools.ts +21 -0
  112. package/packs/software-delivery/tool-impl/runtime-cli-adapter.ts +328 -0
  113. package/packs/software-delivery/tool-impl/runtime-native-tools.ts +687 -0
  114. package/packs/software-delivery/tool-impl/worker-loader.ts +52 -0
  115. package/packs/software-delivery/tool-impl/worktree-tools.ts +46 -0
  116. package/packs/software-delivery/tool-impl/wu-lifecycle-tools.ts +759 -0
  117. package/packs/software-delivery/tools/delegation-tools.ts +23 -0
  118. package/packs/software-delivery/tools/git-tools.ts +55 -0
  119. package/packs/software-delivery/tools/index.ts +8 -0
  120. package/packs/software-delivery/tools/lane-lock-tool.ts +37 -0
  121. package/packs/software-delivery/tools/types.ts +71 -0
  122. package/packs/software-delivery/tools/worktree-tools.ts +49 -0
  123. package/templates/core/LUMENFLOW.md.template +3 -3
  124. package/templates/core/ai/onboarding/agent-invocation-guide.md.template +1 -1
  125. package/templates/core/ai/onboarding/lumenflow-force-usage.md.template +1 -1
  126. package/templates/core/ai/onboarding/quick-ref-commands.md.template +5 -5
  127. package/templates/core/ai/onboarding/starting-prompt.md.template +3 -3
  128. package/templates/core/ai/onboarding/vendor-support.md.template +1 -1
  129. package/templates/core/ai/onboarding/wu-create-checklist.md.template +1 -1
  130. package/dist/agent-issues-query.js.map +0 -1
  131. package/dist/agent-log-issue.js.map +0 -1
  132. package/dist/agent-session-end.js.map +0 -1
  133. package/dist/agent-session.js.map +0 -1
  134. package/dist/backlog-prune.js.map +0 -1
  135. package/dist/cli-entry-point.js +0 -149
  136. package/dist/cli-entry-point.js.map +0 -1
  137. package/dist/commands/integrate.js.map +0 -1
  138. package/dist/commands.js.map +0 -1
  139. package/dist/config-get.js.map +0 -1
  140. package/dist/config-set.js.map +0 -1
  141. package/dist/delegation-list.js.map +0 -1
  142. package/dist/deps-add.js +0 -259
  143. package/dist/deps-add.js.map +0 -1
  144. package/dist/deps-remove.js +0 -105
  145. package/dist/deps-remove.js.map +0 -1
  146. package/dist/docs-sync.js.map +0 -1
  147. package/dist/doctor.js.map +0 -1
  148. package/dist/file-delete.js.map +0 -1
  149. package/dist/file-edit.js.map +0 -1
  150. package/dist/file-read.js.map +0 -1
  151. package/dist/file-write.js.map +0 -1
  152. package/dist/flow-bottlenecks.js.map +0 -1
  153. package/dist/flow-report.js.map +0 -1
  154. package/dist/formatters.js +0 -151
  155. package/dist/formatters.js.map +0 -1
  156. package/dist/gate-defaults.js +0 -131
  157. package/dist/gate-defaults.js.map +0 -1
  158. package/dist/gate-registry.js +0 -73
  159. package/dist/gate-registry.js.map +0 -1
  160. package/dist/gates-graceful-degradation.js +0 -153
  161. package/dist/gates-graceful-degradation.js.map +0 -1
  162. package/dist/gates-plan-resolvers.js +0 -152
  163. package/dist/gates-plan-resolvers.js.map +0 -1
  164. package/dist/gates-runners.js +0 -509
  165. package/dist/gates-runners.js.map +0 -1
  166. package/dist/gates-types.js +0 -4
  167. package/dist/gates-types.js.map +0 -1
  168. package/dist/gates-utils.js +0 -323
  169. package/dist/gates-utils.js.map +0 -1
  170. package/dist/gates.js.map +0 -1
  171. package/dist/git-branch.js.map +0 -1
  172. package/dist/git-diff.js.map +0 -1
  173. package/dist/git-log.js.map +0 -1
  174. package/dist/git-status.js.map +0 -1
  175. package/dist/guard-locked.js +0 -172
  176. package/dist/guard-locked.js.map +0 -1
  177. package/dist/guard-main-branch.js +0 -217
  178. package/dist/guard-main-branch.js.map +0 -1
  179. package/dist/guard-worktree-commit.js +0 -163
  180. package/dist/guard-worktree-commit.js.map +0 -1
  181. package/dist/hooks/auto-checkpoint-utils.js +0 -54
  182. package/dist/hooks/auto-checkpoint-utils.js.map +0 -1
  183. package/dist/hooks/enforcement-checks.js +0 -399
  184. package/dist/hooks/enforcement-checks.js.map +0 -1
  185. package/dist/hooks/enforcement-generator.js +0 -139
  186. package/dist/hooks/enforcement-generator.js.map +0 -1
  187. package/dist/hooks/enforcement-sync.js +0 -385
  188. package/dist/hooks/enforcement-sync.js.map +0 -1
  189. package/dist/hooks/generators/auto-checkpoint.js +0 -125
  190. package/dist/hooks/generators/auto-checkpoint.js.map +0 -1
  191. package/dist/hooks/generators/enforce-worktree.js +0 -190
  192. package/dist/hooks/generators/enforce-worktree.js.map +0 -1
  193. package/dist/hooks/generators/index.js +0 -18
  194. package/dist/hooks/generators/index.js.map +0 -1
  195. package/dist/hooks/generators/pre-compact-checkpoint.js +0 -136
  196. package/dist/hooks/generators/pre-compact-checkpoint.js.map +0 -1
  197. package/dist/hooks/generators/require-wu.js +0 -117
  198. package/dist/hooks/generators/require-wu.js.map +0 -1
  199. package/dist/hooks/generators/session-start-recovery.js +0 -103
  200. package/dist/hooks/generators/session-start-recovery.js.map +0 -1
  201. package/dist/hooks/generators/signal-utils.js +0 -54
  202. package/dist/hooks/generators/signal-utils.js.map +0 -1
  203. package/dist/hooks/generators/warn-incomplete.js +0 -67
  204. package/dist/hooks/generators/warn-incomplete.js.map +0 -1
  205. package/dist/hooks/index.js +0 -10
  206. package/dist/hooks/index.js.map +0 -1
  207. package/dist/index.js.map +0 -1
  208. package/dist/init-detection.js +0 -232
  209. package/dist/init-detection.js.map +0 -1
  210. package/dist/init-lane-validation.js +0 -143
  211. package/dist/init-lane-validation.js.map +0 -1
  212. package/dist/init-scaffolding.js +0 -158
  213. package/dist/init-scaffolding.js.map +0 -1
  214. package/dist/init-templates.js +0 -1982
  215. package/dist/init-templates.js.map +0 -1
  216. package/dist/init.js.map +0 -1
  217. package/dist/initiative-add-wu.js.map +0 -1
  218. package/dist/initiative-bulk-assign-wus.js.map +0 -1
  219. package/dist/initiative-create.js.map +0 -1
  220. package/dist/initiative-edit.js.map +0 -1
  221. package/dist/initiative-list.js.map +0 -1
  222. package/dist/initiative-plan.js.map +0 -1
  223. package/dist/initiative-remove-wu.js.map +0 -1
  224. package/dist/initiative-status.js.map +0 -1
  225. package/dist/lane-edit.js.map +0 -1
  226. package/dist/lane-health.js.map +0 -1
  227. package/dist/lane-lifecycle-process.js +0 -366
  228. package/dist/lane-lifecycle-process.js.map +0 -1
  229. package/dist/lane-lock.js.map +0 -1
  230. package/dist/lane-setup.js.map +0 -1
  231. package/dist/lane-status.js.map +0 -1
  232. package/dist/lane-suggest.js.map +0 -1
  233. package/dist/lane-validate.js.map +0 -1
  234. package/dist/lifecycle-regression-harness.js +0 -181
  235. package/dist/lifecycle-regression-harness.js.map +0 -1
  236. package/dist/lumenflow-upgrade.js.map +0 -1
  237. package/dist/mem-checkpoint.js.map +0 -1
  238. package/dist/mem-cleanup.js.map +0 -1
  239. package/dist/mem-context.js.map +0 -1
  240. package/dist/mem-create.js.map +0 -1
  241. package/dist/mem-delete.js.map +0 -1
  242. package/dist/mem-export.js.map +0 -1
  243. package/dist/mem-inbox.js.map +0 -1
  244. package/dist/mem-index.js +0 -214
  245. package/dist/mem-index.js.map +0 -1
  246. package/dist/mem-init.js.map +0 -1
  247. package/dist/mem-profile.js +0 -210
  248. package/dist/mem-profile.js.map +0 -1
  249. package/dist/mem-promote.js +0 -257
  250. package/dist/mem-promote.js.map +0 -1
  251. package/dist/mem-ready.js.map +0 -1
  252. package/dist/mem-recover.js.map +0 -1
  253. package/dist/mem-signal.js.map +0 -1
  254. package/dist/mem-start.js.map +0 -1
  255. package/dist/mem-summarize.js.map +0 -1
  256. package/dist/mem-triage.js.map +0 -1
  257. package/dist/merge-block.js +0 -225
  258. package/dist/merge-block.js.map +0 -1
  259. package/dist/metrics-cli.js.map +0 -1
  260. package/dist/metrics-snapshot.js.map +0 -1
  261. package/dist/onboard.js.map +0 -1
  262. package/dist/onboarding-smoke-test.js +0 -418
  263. package/dist/onboarding-smoke-test.js.map +0 -1
  264. package/dist/orchestrate-init-status.js.map +0 -1
  265. package/dist/orchestrate-initiative.js.map +0 -1
  266. package/dist/orchestrate-monitor.js.map +0 -1
  267. package/dist/pack-author.js.map +0 -1
  268. package/dist/pack-hash.js.map +0 -1
  269. package/dist/pack-install.js.map +0 -1
  270. package/dist/pack-publish.js.map +0 -1
  271. package/dist/pack-scaffold.js.map +0 -1
  272. package/dist/pack-search.js.map +0 -1
  273. package/dist/pack-validate.js.map +0 -1
  274. package/dist/plan-create.js.map +0 -1
  275. package/dist/plan-edit.js.map +0 -1
  276. package/dist/plan-link.js.map +0 -1
  277. package/dist/plan-promote.js.map +0 -1
  278. package/dist/public-manifest.js +0 -920
  279. package/dist/public-manifest.js.map +0 -1
  280. package/dist/release.js.map +0 -1
  281. package/dist/rotate-progress.js +0 -253
  282. package/dist/rotate-progress.js.map +0 -1
  283. package/dist/session-coordinator.js +0 -303
  284. package/dist/session-coordinator.js.map +0 -1
  285. package/dist/shared-validators.js +0 -81
  286. package/dist/shared-validators.js.map +0 -1
  287. package/dist/signal-cleanup.js.map +0 -1
  288. package/dist/state-bootstrap.js.map +0 -1
  289. package/dist/state-cleanup.js.map +0 -1
  290. package/dist/state-doctor-fix.js +0 -226
  291. package/dist/state-doctor-fix.js.map +0 -1
  292. package/dist/state-doctor-stamps.js +0 -23
  293. package/dist/state-doctor-stamps.js.map +0 -1
  294. package/dist/state-doctor.js.map +0 -1
  295. package/dist/strict-progress.js +0 -255
  296. package/dist/strict-progress.js.map +0 -1
  297. package/dist/sync-templates.js.map +0 -1
  298. package/dist/task-claim.js.map +0 -1
  299. package/dist/trace-gen.js +0 -401
  300. package/dist/trace-gen.js.map +0 -1
  301. package/dist/validate-agent-skills.js +0 -223
  302. package/dist/validate-agent-skills.js.map +0 -1
  303. package/dist/validate-agent-sync.js +0 -151
  304. package/dist/validate-agent-sync.js.map +0 -1
  305. package/dist/validate-backlog-sync.js +0 -77
  306. package/dist/validate-backlog-sync.js.map +0 -1
  307. package/dist/validate-skills-spec.js +0 -211
  308. package/dist/validate-skills-spec.js.map +0 -1
  309. package/dist/validate.js.map +0 -1
  310. package/dist/validator-defaults.js +0 -107
  311. package/dist/validator-defaults.js.map +0 -1
  312. package/dist/validator-registry.js +0 -71
  313. package/dist/validator-registry.js.map +0 -1
  314. package/dist/workspace-init.js.map +0 -1
  315. package/dist/wu-block.js.map +0 -1
  316. package/dist/wu-brief.js.map +0 -1
  317. package/dist/wu-claim-branch.js +0 -123
  318. package/dist/wu-claim-branch.js.map +0 -1
  319. package/dist/wu-claim-cloud.js +0 -79
  320. package/dist/wu-claim-cloud.js.map +0 -1
  321. package/dist/wu-claim-mode.js +0 -82
  322. package/dist/wu-claim-mode.js.map +0 -1
  323. package/dist/wu-claim-output.js +0 -85
  324. package/dist/wu-claim-output.js.map +0 -1
  325. package/dist/wu-claim-repair-guidance.js +0 -12
  326. package/dist/wu-claim-repair-guidance.js.map +0 -1
  327. package/dist/wu-claim-resume-handler.js +0 -87
  328. package/dist/wu-claim-resume-handler.js.map +0 -1
  329. package/dist/wu-claim-state.js +0 -581
  330. package/dist/wu-claim-state.js.map +0 -1
  331. package/dist/wu-claim-validation.js +0 -457
  332. package/dist/wu-claim-validation.js.map +0 -1
  333. package/dist/wu-claim-worktree.js +0 -223
  334. package/dist/wu-claim-worktree.js.map +0 -1
  335. package/dist/wu-claim.js.map +0 -1
  336. package/dist/wu-cleanup-cloud.js +0 -78
  337. package/dist/wu-cleanup-cloud.js.map +0 -1
  338. package/dist/wu-cleanup.js.map +0 -1
  339. package/dist/wu-code-path-coverage.js +0 -83
  340. package/dist/wu-code-path-coverage.js.map +0 -1
  341. package/dist/wu-create-cloud.js +0 -30
  342. package/dist/wu-create-cloud.js.map +0 -1
  343. package/dist/wu-create-content.js +0 -264
  344. package/dist/wu-create-content.js.map +0 -1
  345. package/dist/wu-create-readiness.js +0 -59
  346. package/dist/wu-create-readiness.js.map +0 -1
  347. package/dist/wu-create-validation.js +0 -128
  348. package/dist/wu-create-validation.js.map +0 -1
  349. package/dist/wu-create.js.map +0 -1
  350. package/dist/wu-delegate.js.map +0 -1
  351. package/dist/wu-delete.js.map +0 -1
  352. package/dist/wu-deps.js.map +0 -1
  353. package/dist/wu-done-auto-cleanup.js +0 -203
  354. package/dist/wu-done-auto-cleanup.js.map +0 -1
  355. package/dist/wu-done-check.js +0 -38
  356. package/dist/wu-done-check.js.map +0 -1
  357. package/dist/wu-done-cloud.js +0 -48
  358. package/dist/wu-done-cloud.js.map +0 -1
  359. package/dist/wu-done-decay.js +0 -86
  360. package/dist/wu-done-decay.js.map +0 -1
  361. package/dist/wu-done.js.map +0 -1
  362. package/dist/wu-edit-operations.js +0 -399
  363. package/dist/wu-edit-operations.js.map +0 -1
  364. package/dist/wu-edit-validators.js +0 -282
  365. package/dist/wu-edit-validators.js.map +0 -1
  366. package/dist/wu-edit.js.map +0 -1
  367. package/dist/wu-infer-lane.js.map +0 -1
  368. package/dist/wu-preflight.js.map +0 -1
  369. package/dist/wu-prep.js.map +0 -1
  370. package/dist/wu-proto.js.map +0 -1
  371. package/dist/wu-prune.js.map +0 -1
  372. package/dist/wu-recover.js.map +0 -1
  373. package/dist/wu-release.js.map +0 -1
  374. package/dist/wu-repair.js.map +0 -1
  375. package/dist/wu-sandbox.js.map +0 -1
  376. package/dist/wu-spawn-completion.js +0 -33
  377. package/dist/wu-spawn-completion.js.map +0 -1
  378. package/dist/wu-spawn-prompt-builders.js +0 -1197
  379. package/dist/wu-spawn-prompt-builders.js.map +0 -1
  380. package/dist/wu-spawn-strategy-resolver.js +0 -322
  381. package/dist/wu-spawn-strategy-resolver.js.map +0 -1
  382. package/dist/wu-spawn.js +0 -59
  383. package/dist/wu-spawn.js.map +0 -1
  384. package/dist/wu-state-cloud.js +0 -41
  385. package/dist/wu-state-cloud.js.map +0 -1
  386. package/dist/wu-status.js.map +0 -1
  387. package/dist/wu-unblock.js.map +0 -1
  388. package/dist/wu-unlock-lane.js.map +0 -1
  389. package/dist/wu-validate.js.map +0 -1
@@ -1,152 +0,0 @@
1
- // Copyright (c) 2026 Hellmai Ltd
2
- // SPDX-License-Identifier: AGPL-3.0-only
3
- /**
4
- * Gates Plan Resolvers
5
- *
6
- * WU-1647: Extracted pure plan-resolution functions that decide
7
- * what mode (full/incremental/skip) each gate should use.
8
- *
9
- * These functions are side-effect-free and only depend on their inputs.
10
- *
11
- * @module gates-plan-resolvers
12
- */
13
- import { isLintableFile } from '@lumenflow/core/incremental-lint';
14
- import { getBasename, normalizePath, extractPackagesFromCodePaths } from './gates-utils.js';
15
- // ── Config file detection ──────────────────────────────────────────────
16
- const PRETTIER_CONFIG_FILES = new Set([
17
- '.prettierrc',
18
- '.prettierrc.json',
19
- '.prettierrc.yaml',
20
- '.prettierrc.yml',
21
- '.prettierrc.js',
22
- '.prettierrc.cjs',
23
- '.prettierrc.ts',
24
- 'prettier.config.js',
25
- 'prettier.config.cjs',
26
- 'prettier.config.ts',
27
- 'prettier.config.mjs',
28
- '.prettierignore',
29
- ]);
30
- // WU-1356: Extended to support multiple build tools and test runners
31
- const TEST_CONFIG_BASENAMES = new Set([
32
- 'turbo.json', // Turborepo
33
- 'nx.json', // Nx
34
- 'lerna.json', // Lerna
35
- 'pnpm-lock.yaml',
36
- 'package-lock.json',
37
- 'yarn.lock',
38
- 'bun.lockb',
39
- 'package.json',
40
- ]);
41
- // WU-1356: Extended to support vitest, jest, and mocha config patterns
42
- const TEST_CONFIG_PATTERNS = [
43
- /^vitest\.config\.(ts|mts|js|mjs|cjs)$/i,
44
- /^jest\.config\.(ts|js|mjs|cjs|json)$/i,
45
- /^\.mocharc\.(js|json|yaml|yml)$/i,
46
- // eslint-disable-next-line security/detect-unsafe-regex -- static tsconfig pattern; no backtracking risk
47
- /^tsconfig(\..+)?\.json$/i,
48
- ];
49
- export function isPrettierConfigFile(filePath) {
50
- if (!filePath)
51
- return false;
52
- const basename = getBasename(filePath);
53
- return PRETTIER_CONFIG_FILES.has(basename);
54
- }
55
- export function isTestConfigFile(filePath) {
56
- if (!filePath)
57
- return false;
58
- const basename = getBasename(filePath);
59
- if (TEST_CONFIG_BASENAMES.has(basename)) {
60
- return true;
61
- }
62
- return TEST_CONFIG_PATTERNS.some((pattern) => pattern.test(basename));
63
- }
64
- // ── Plan resolvers ─────────────────────────────────────────────────────
65
- /* eslint-disable sonarjs/no-duplicate-string -- Pre-existing: format check reasons are intentionally distinct string literals */
66
- export function resolveFormatCheckPlan({ changedFiles, fileListError = false, }) {
67
- if (fileListError) {
68
- return { mode: 'full', files: [], reason: 'file-list-error' };
69
- }
70
- if (changedFiles.some(isPrettierConfigFile)) {
71
- return { mode: 'full', files: [], reason: 'prettier-config' };
72
- }
73
- if (changedFiles.length === 0) {
74
- return { mode: 'skip', files: [] };
75
- }
76
- return { mode: 'incremental', files: changedFiles };
77
- }
78
- export function resolveLintPlan({ isMainBranch, changedFiles, }) {
79
- if (isMainBranch) {
80
- return { mode: 'full', files: [] };
81
- }
82
- const lintTargets = changedFiles.filter((filePath) => {
83
- const normalized = normalizePath(filePath);
84
- return ((normalized.startsWith('apps/') || normalized.startsWith('packages/')) &&
85
- isLintableFile(normalized));
86
- });
87
- if (lintTargets.length === 0) {
88
- return { mode: 'skip', files: [] };
89
- }
90
- return { mode: 'incremental', files: lintTargets };
91
- }
92
- /* eslint-enable sonarjs/no-duplicate-string */
93
- export function resolveTestPlan({ isMainBranch, hasUntrackedCode, hasConfigChange, fileListError, }) {
94
- if (fileListError) {
95
- return { mode: 'full', reason: 'file-list-error' };
96
- }
97
- if (hasUntrackedCode) {
98
- return { mode: 'full', reason: 'untracked-code' };
99
- }
100
- if (hasConfigChange) {
101
- return { mode: 'full', reason: 'test-config' };
102
- }
103
- if (isMainBranch) {
104
- return { mode: 'full' };
105
- }
106
- return { mode: 'incremental' };
107
- }
108
- /**
109
- * WU-1299: Resolve test plan for docs-only mode
110
- */
111
- export function resolveDocsOnlyTestPlan({ codePaths }) {
112
- const packages = extractPackagesFromCodePaths(codePaths);
113
- if (packages.length === 0) {
114
- return {
115
- mode: 'skip',
116
- packages: [],
117
- reason: 'no-code-packages',
118
- };
119
- }
120
- return {
121
- mode: 'filtered',
122
- packages,
123
- };
124
- }
125
- /**
126
- * WU-1299: Format message for docs-only test skipping/filtering
127
- */
128
- export function formatDocsOnlySkipMessage(plan) {
129
- if (plan.mode === 'skip') {
130
- return '\uD83D\uDCDD docs-only mode: skipping all tests (no code packages in code_paths)';
131
- }
132
- const packageList = plan.packages.join(', ');
133
- return `\uD83D\uDCDD docs-only mode: running tests only for packages in code_paths: ${packageList}`;
134
- }
135
- /**
136
- * Resolve spec-linter execution strategy.
137
- * If current WU is known, run scoped validation only.
138
- * If unknown, fall back to global validation.
139
- */
140
- export function resolveSpecLinterPlan(wuId) {
141
- if (wuId) {
142
- return {
143
- scopedWuId: wuId,
144
- runGlobal: false,
145
- };
146
- }
147
- return {
148
- scopedWuId: null,
149
- runGlobal: true,
150
- };
151
- }
152
- //# sourceMappingURL=gates-plan-resolvers.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gates-plan-resolvers.js","sourceRoot":"","sources":["../src/gates-plan-resolvers.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAEzC;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,kBAAkB,CAAC;AA8B5F,0EAA0E;AAE1E,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,aAAa;IACb,kBAAkB;IAClB,kBAAkB;IAClB,iBAAiB;IACjB,gBAAgB;IAChB,iBAAiB;IACjB,gBAAgB;IAChB,oBAAoB;IACpB,qBAAqB;IACrB,oBAAoB;IACpB,qBAAqB;IACrB,iBAAiB;CAClB,CAAC,CAAC;AAEH,qEAAqE;AACrE,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,YAAY,EAAE,YAAY;IAC1B,SAAS,EAAE,KAAK;IAChB,YAAY,EAAE,QAAQ;IACtB,gBAAgB;IAChB,mBAAmB;IACnB,WAAW;IACX,WAAW;IACX,cAAc;CACf,CAAC,CAAC;AACH,uEAAuE;AACvE,MAAM,oBAAoB,GAAG;IAC3B,wCAAwC;IACxC,uCAAuC;IACvC,kCAAkC;IAClC,yGAAyG;IACzG,0BAA0B;CAC3B,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACvC,OAAO,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,0EAA0E;AAE1E,iIAAiI;AACjI,MAAM,UAAU,sBAAsB,CAAC,EACrC,YAAY,EACZ,aAAa,GAAG,KAAK,GAItB;IACC,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAChE,CAAC;IACD,IAAI,YAAY,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC;QAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAChE,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAC9B,YAAY,EACZ,YAAY,GAIb;IACC,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;IAED,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE;QACnD,MAAM,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC3C,OAAO,CACL,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YACtE,cAAc,CAAC,UAAU,CAAC,CAC3B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;AACrD,CAAC;AACD,+CAA+C;AAE/C,MAAM,UAAU,eAAe,CAAC,EAC9B,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,aAAa,GAMd;IACC,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACrD,CAAC;IACD,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACpD,CAAC;IACD,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACjD,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,EAAE,SAAS,EAA2B;IAC5E,MAAM,QAAQ,GAAG,4BAA4B,CAAC,SAAS,CAAC,CAAC;IAEzD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,EAAE;YACZ,MAAM,EAAE,kBAAkB;SAC3B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAsB;IAC9D,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,OAAO,kFAAkF,CAAC;IAC5F,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,OAAO,+EAA+E,WAAW,EAAE,CAAC;AACtG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAmB;IAIvD,IAAI,IAAI,EAAE,CAAC;QACT,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,KAAK;SACjB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC"}
@@ -1,509 +0,0 @@
1
- // Copyright (c) 2026 Hellmai Ltd
2
- // SPDX-License-Identifier: AGPL-3.0-only
3
- /**
4
- * Gate Runner Functions
5
- *
6
- * WU-1647: Extracted gate runner functions that execute individual gates.
7
- * Each runner takes a GateLogContext and returns a result with ok/duration.
8
- *
9
- * @module gates-runners
10
- */
11
- import { spawnSync } from 'node:child_process';
12
- import { writeSync } from 'node:fs';
13
- import { access } from 'node:fs/promises';
14
- import path from 'node:path';
15
- import { getChangedLintableFiles } from '@lumenflow/core/incremental-lint';
16
- import { buildVitestChangedArgs, isCodeFilePath } from '@lumenflow/core/incremental-test';
17
- import { createGitForPath } from '@lumenflow/core/git-adapter';
18
- import { resolveGatesCommands, resolveTestRunner } from '@lumenflow/core/gates-config';
19
- import { validateBacklogSync } from '@lumenflow/core/validators/backlog-sync';
20
- import { runSupabaseDocsLinter } from '@lumenflow/core/validators/supabase-docs-linter';
21
- import { BRANCHES, PACKAGES, PKG_MANAGER, ESLINT_FLAGS, ESLINT_COMMANDS, ESLINT_DEFAULTS, SCRIPTS, CACHE_STRATEGIES, DIRECTORIES, EXIT_CODES, FILE_SYSTEM, } from '@lumenflow/core/wu-constants';
22
- import { runLaneHealthCheck } from './lane-health.js';
23
- import { pnpmCmd, pnpmRun, run, makeGateLogger, quoteShellArgs, filterExistingFiles, getChangedFilesForIncremental, detectCurrentWUForCwd, buildPrettierCheckCommand, } from './gates-utils.js';
24
- import { resolveFormatCheckPlan, resolveLintPlan, resolveTestPlan, resolveSpecLinterPlan, isTestConfigFile, } from './gates-plan-resolvers.js';
25
- // ── Format check gate ──────────────────────────────────────────────────
26
- export async function runFormatCheckGate({ agentLog, useAgentMode, cwd }) {
27
- const start = Date.now();
28
- const effectiveCwd = cwd ?? process.cwd();
29
- const logLine = makeGateLogger({ agentLog, useAgentMode });
30
- let git;
31
- let isMainBranch;
32
- try {
33
- git = createGitForPath(effectiveCwd);
34
- const currentBranch = await git.getCurrentBranch();
35
- isMainBranch = currentBranch === BRANCHES.MAIN || currentBranch === BRANCHES.MASTER;
36
- }
37
- catch (error) {
38
- logLine(`\u26A0\uFE0F Failed to determine branch for format check: ${error.message}`);
39
- const result = run(pnpmCmd(SCRIPTS.FORMAT_CHECK), { agentLog, cwd: effectiveCwd });
40
- return { ...result, duration: Date.now() - start, fileCount: -1 };
41
- }
42
- if (isMainBranch) {
43
- logLine('\uD83D\uDCCB On main branch - running full format check');
44
- const result = run(pnpmCmd(SCRIPTS.FORMAT_CHECK), { agentLog, cwd: effectiveCwd });
45
- return { ...result, duration: Date.now() - start, fileCount: -1 };
46
- }
47
- let changedFiles = [];
48
- let fileListError = false;
49
- try {
50
- changedFiles = await getChangedFilesForIncremental({ git });
51
- }
52
- catch (error) {
53
- fileListError = true;
54
- logLine(`\u26A0\uFE0F Failed to determine changed files for format check: ${error.message}`);
55
- }
56
- const plan = resolveFormatCheckPlan({ changedFiles, fileListError });
57
- if (plan.mode === 'skip') {
58
- logLine('\n> format:check (incremental)\n');
59
- logLine('\u2705 No files changed - skipping format check');
60
- return { ok: true, duration: Date.now() - start, fileCount: 0, filesChecked: [] };
61
- }
62
- if (plan.mode === 'full') {
63
- const reason = plan.reason === 'prettier-config'
64
- ? ' (prettier config changed)'
65
- : plan.reason === 'file-list-error'
66
- ? ' (file list unavailable)'
67
- : '';
68
- logLine(`\uD83D\uDCCB Running full format check${reason}`);
69
- const result = run(pnpmCmd(SCRIPTS.FORMAT_CHECK), { agentLog, cwd: effectiveCwd });
70
- return { ...result, duration: Date.now() - start, fileCount: -1 };
71
- }
72
- const existingFiles = await filterExistingFiles(plan.files);
73
- if (existingFiles.length === 0) {
74
- logLine('\n> format:check (incremental)\n');
75
- logLine('\u2705 All changed files were deleted - skipping format check');
76
- return { ok: true, duration: Date.now() - start, fileCount: 0, filesChecked: [] };
77
- }
78
- logLine(`\n> format:check (incremental: ${existingFiles.length} files)\n`);
79
- const result = run(buildPrettierCheckCommand(existingFiles), { agentLog, cwd: effectiveCwd });
80
- return {
81
- ...result,
82
- duration: Date.now() - start,
83
- fileCount: existingFiles.length,
84
- filesChecked: existingFiles,
85
- };
86
- }
87
- // ── Lint gate ──────────────────────────────────────────────────────────
88
- /**
89
- * Run incremental ESLint on changed files only
90
- * Falls back to full lint if on main branch or if incremental fails
91
- */
92
- export async function runIncrementalLint({ agentLog, cwd, }) {
93
- const start = Date.now();
94
- const logLine = (line) => {
95
- if (!agentLog) {
96
- console.log(line);
97
- return;
98
- }
99
- writeSync(agentLog.logFd, `${line}\n`);
100
- };
101
- try {
102
- // Check if we're on main branch
103
- const git = createGitForPath(cwd);
104
- const currentBranch = await git.getCurrentBranch();
105
- const isMainBranch = currentBranch === BRANCHES.MAIN || currentBranch === BRANCHES.MASTER;
106
- if (isMainBranch) {
107
- logLine('\uD83D\uDCCB On main branch - running full lint');
108
- const result = run(pnpmCmd(SCRIPTS.LINT), { agentLog, cwd });
109
- return { ...result, fileCount: -1 };
110
- }
111
- const changedFiles = await getChangedLintableFiles({ git });
112
- const plan = resolveLintPlan({ isMainBranch, changedFiles });
113
- if (plan.mode === 'skip') {
114
- logLine('\n> ESLint (incremental)\n');
115
- logLine('\u2705 No lintable files changed - skipping lint');
116
- return { ok: true, duration: Date.now() - start, fileCount: 0 };
117
- }
118
- if (plan.mode === 'full') {
119
- logLine('\uD83D\uDCCB Running full lint (incremental plan forced full)');
120
- const result = run(pnpmCmd(SCRIPTS.LINT), { agentLog, cwd });
121
- return { ...result, fileCount: -1 };
122
- }
123
- const existingFiles = await filterExistingFiles(plan.files);
124
- if (existingFiles.length === 0) {
125
- logLine('\n> ESLint (incremental)\n');
126
- logLine('\u2705 All changed files were deleted - skipping lint');
127
- return { ok: true, duration: Date.now() - start, fileCount: 0 };
128
- }
129
- logLine(`\n> ESLint (incremental: ${existingFiles.length} files)\n`);
130
- logLine(`Files to lint:\n ${existingFiles.join('\n ')}\n`);
131
- const result = spawnSync(PKG_MANAGER, [
132
- ESLINT_COMMANDS.ESLINT,
133
- ESLINT_FLAGS.MAX_WARNINGS,
134
- ESLINT_DEFAULTS.MAX_WARNINGS,
135
- ESLINT_FLAGS.NO_WARN_IGNORED,
136
- ESLINT_FLAGS.CACHE,
137
- ESLINT_FLAGS.CACHE_STRATEGY,
138
- CACHE_STRATEGIES.CONTENT,
139
- ESLINT_FLAGS.CACHE_LOCATION,
140
- '.eslintcache',
141
- ESLINT_FLAGS.PASS_ON_UNPRUNED,
142
- ...existingFiles,
143
- ], agentLog
144
- ? {
145
- stdio: ['ignore', agentLog.logFd, agentLog.logFd],
146
- encoding: FILE_SYSTEM.ENCODING,
147
- cwd,
148
- }
149
- : {
150
- stdio: 'inherit',
151
- encoding: FILE_SYSTEM.ENCODING,
152
- cwd,
153
- });
154
- const duration = Date.now() - start;
155
- return {
156
- ok: result.status === EXIT_CODES.SUCCESS,
157
- duration,
158
- fileCount: existingFiles.length,
159
- };
160
- }
161
- catch (error) {
162
- console.error('\u26A0\uFE0F Incremental lint failed, falling back to full lint:', error.message);
163
- const result = run(pnpmCmd(SCRIPTS.LINT), { agentLog, cwd });
164
- return { ...result, fileCount: -1 };
165
- }
166
- }
167
- // ── Test gates ─────────────────────────────────────────────────────────
168
- const DEFAULT_INCREMENTAL_BASE_BRANCH = 'origin/main';
169
- export function buildStableVitestIncrementalCommand(baseBranch = DEFAULT_INCREMENTAL_BASE_BRANCH) {
170
- return pnpmCmd('vitest', 'run', ...buildVitestChangedArgs({ baseBranch }));
171
- }
172
- export function resolveIncrementalTestCommand({ testRunner, configuredIncrementalCommand, baseBranch = DEFAULT_INCREMENTAL_BASE_BRANCH, }) {
173
- const normalizedConfiguredCommand = configuredIncrementalCommand?.trim();
174
- if (testRunner === 'vitest') {
175
- if (!normalizedConfiguredCommand) {
176
- return buildStableVitestIncrementalCommand(baseBranch);
177
- }
178
- const isVitestChangedCommand = normalizedConfiguredCommand.includes('vitest') &&
179
- normalizedConfiguredCommand.includes('--changed');
180
- if (isVitestChangedCommand) {
181
- return buildStableVitestIncrementalCommand(baseBranch);
182
- }
183
- }
184
- return normalizedConfiguredCommand ?? null;
185
- }
186
- /**
187
- * Run changed tests using configured test runner's incremental mode.
188
- * WU-1356: Updated to use configured commands from gates-config.
189
- */
190
- export async function runChangedTests({ agentLog, cwd, scopedTestPaths = [], }) {
191
- const start = Date.now();
192
- // eslint-disable-next-line sonarjs/no-identical-functions -- Pre-existing: logLine helper duplicated across gate runners
193
- const logLine = (line) => {
194
- if (!agentLog) {
195
- console.log(line);
196
- return;
197
- }
198
- writeSync(agentLog.logFd, `${line}\n`);
199
- };
200
- // WU-1356: Get configured commands
201
- const gatesCommands = resolveGatesCommands(cwd);
202
- const testRunner = resolveTestRunner(cwd);
203
- const normalizedScopedTestPaths = scopedTestPaths
204
- .filter((testPath) => typeof testPath === 'string')
205
- .map((testPath) => testPath.trim())
206
- .filter(Boolean);
207
- try {
208
- if (normalizedScopedTestPaths.length > 0) {
209
- const testPathsArg = quoteShellArgs(normalizedScopedTestPaths);
210
- logLine(`\n> Running scoped tests from WU tests.unit (${normalizedScopedTestPaths.length})\n`);
211
- const result = run(pnpmCmd('vitest', 'run', testPathsArg, '--passWithNoTests'), {
212
- agentLog,
213
- cwd,
214
- });
215
- return { ...result, duration: Date.now() - start, isIncremental: true };
216
- }
217
- const git = createGitForPath(cwd);
218
- const currentBranch = await git.getCurrentBranch();
219
- const isMainBranch = currentBranch === BRANCHES.MAIN || currentBranch === BRANCHES.MASTER;
220
- if (isMainBranch) {
221
- logLine('\uD83D\uDCCB On main branch - running full test suite');
222
- const result = run(gatesCommands.test_full, { agentLog, cwd });
223
- return { ...result, isIncremental: false };
224
- }
225
- let changedFiles = [];
226
- let fileListError = false;
227
- try {
228
- changedFiles = await getChangedFilesForIncremental({ git });
229
- }
230
- catch (error) {
231
- fileListError = true;
232
- logLine(`\u26A0\uFE0F Failed to determine changed files for tests: ${error.message}`);
233
- }
234
- const hasConfigChange = !fileListError && changedFiles.some(isTestConfigFile);
235
- const untrackedOutput = await git.raw(['ls-files', '--others', '--exclude-standard']);
236
- const untrackedFiles = untrackedOutput
237
- .split(/\r?\n/)
238
- .map((f) => f.trim())
239
- .filter(Boolean);
240
- const untrackedCodeFiles = untrackedFiles.filter(isCodeFilePath);
241
- const hasUntrackedCode = untrackedCodeFiles.length > 0;
242
- const plan = resolveTestPlan({
243
- isMainBranch,
244
- hasUntrackedCode,
245
- hasConfigChange,
246
- fileListError,
247
- });
248
- if (plan.mode === 'full') {
249
- if (plan.reason === 'untracked-code') {
250
- const preview = untrackedCodeFiles.slice(0, 5).join(', ');
251
- logLine(`\u26A0\uFE0F Untracked code files detected (${untrackedCodeFiles.length}): ${preview}${untrackedCodeFiles.length > 5 ? '...' : ''}`);
252
- }
253
- else if (plan.reason === 'test-config') {
254
- logLine('\u26A0\uFE0F Test config changes detected - running full test suite');
255
- }
256
- else if (plan.reason === 'file-list-error') {
257
- logLine('\u26A0\uFE0F Changed file list unavailable - running full test suite');
258
- }
259
- logLine('\uD83D\uDCCB Running full test suite to avoid missing coverage');
260
- const result = run(gatesCommands.test_full, { agentLog, cwd });
261
- return { ...result, duration: Date.now() - start, isIncremental: false };
262
- }
263
- // WU-1356: Use configured incremental test command
264
- logLine(`\n> Running tests (${testRunner} --changed)\n`);
265
- const incrementalCommand = resolveIncrementalTestCommand({
266
- testRunner,
267
- configuredIncrementalCommand: gatesCommands.test_incremental,
268
- });
269
- if (incrementalCommand) {
270
- if (testRunner === 'vitest' &&
271
- incrementalCommand !== gatesCommands.test_incremental?.trim()) {
272
- logLine('ℹ️ Using hardened vitest incremental command for worker stability');
273
- }
274
- const result = run(incrementalCommand, { agentLog, cwd });
275
- return { ...result, duration: Date.now() - start, isIncremental: true };
276
- }
277
- // For other runners without configured incremental, fall back to full
278
- logLine('\u26A0\uFE0F No incremental test command configured, running full suite');
279
- const result = run(gatesCommands.test_full, { agentLog, cwd });
280
- return { ...result, duration: Date.now() - start, isIncremental: false };
281
- }
282
- catch (error) {
283
- console.error('\u26A0\uFE0F Changed tests failed, falling back to full suite:', error.message);
284
- const result = run(gatesCommands.test_full, { agentLog, cwd });
285
- return { ...result, isIncremental: false };
286
- }
287
- }
288
- /**
289
- * Safety-critical test file patterns (relative to apps/web).
290
- */
291
- export const SAFETY_CRITICAL_TEST_FILES = [
292
- // Privacy detection tests
293
- 'src/lib/llm/__tests__/privacyDetector.test.ts',
294
- // Escalation trigger tests
295
- 'src/lib/llm/__tests__/escalationTrigger.test.ts',
296
- 'src/components/escalation/__tests__/EscalationHistory.test.tsx',
297
- // Constitutional enforcer tests
298
- 'src/lib/llm/__tests__/constitutionalEnforcer.test.ts',
299
- // Safe prompt wrapper tests
300
- 'src/lib/llm/__tests__/safePromptWrapper.test.ts',
301
- // Crisis/emergency handling tests
302
- 'src/lib/prompts/__tests__/golden-crisis.test.ts',
303
- ];
304
- /**
305
- * WU-2062: Run safety-critical tests
306
- * These tests ALWAYS run regardless of which files changed.
307
- */
308
- export async function runSafetyCriticalTests({ agentLog, cwd, }) {
309
- const start = Date.now();
310
- // eslint-disable-next-line sonarjs/no-identical-functions -- Pre-existing: logLine helper duplicated across gate runners
311
- const logLine = (line) => {
312
- if (!agentLog) {
313
- console.log(line);
314
- return;
315
- }
316
- writeSync(agentLog.logFd, `${line}\n`);
317
- };
318
- // WU-1006: Skip safety-critical tests if apps/web doesn't exist (repo-agnostic)
319
- const webDir = path.join(cwd, DIRECTORIES.APPS_WEB);
320
- try {
321
- await access(webDir);
322
- }
323
- catch {
324
- logLine('\n> Safety-critical tests skipped (apps/web not present)\n');
325
- return { ok: true, duration: Date.now() - start, testCount: 0 };
326
- }
327
- try {
328
- logLine('\n> Safety-critical tests (always run)\n');
329
- logLine(`Test files: ${SAFETY_CRITICAL_TEST_FILES.length} files\n`);
330
- const result = spawnSync(PKG_MANAGER, [
331
- 'vitest',
332
- 'run',
333
- '--project',
334
- PACKAGES.WEB,
335
- '--reporter=verbose',
336
- ...SAFETY_CRITICAL_TEST_FILES,
337
- '--passWithNoTests',
338
- ], agentLog
339
- ? {
340
- stdio: ['ignore', agentLog.logFd, agentLog.logFd],
341
- encoding: FILE_SYSTEM.ENCODING,
342
- cwd,
343
- }
344
- : {
345
- stdio: 'inherit',
346
- encoding: FILE_SYSTEM.ENCODING,
347
- cwd,
348
- });
349
- const duration = Date.now() - start;
350
- return {
351
- ok: result.status === EXIT_CODES.SUCCESS,
352
- duration,
353
- testCount: SAFETY_CRITICAL_TEST_FILES.length,
354
- };
355
- }
356
- catch (error) {
357
- console.error('\u26A0\uFE0F Safety-critical tests failed:', error.message);
358
- return { ok: false, duration: Date.now() - start, testCount: 0 };
359
- }
360
- }
361
- /**
362
- * WU-2062: Run integration tests for high-risk changes
363
- */
364
- export async function runIntegrationTests({ agentLog, cwd, }) {
365
- const start = Date.now();
366
- // eslint-disable-next-line sonarjs/no-identical-functions -- Pre-existing: logLine helper duplicated across gate runners
367
- const logLine = (line) => {
368
- if (!agentLog) {
369
- console.log(line);
370
- return;
371
- }
372
- writeSync(agentLog.logFd, `${line}\n`);
373
- };
374
- try {
375
- logLine('\n> Integration tests (high-risk changes detected)\n');
376
- // WU-1415: vitest doesn't support --include flag
377
- const result = run(`RUN_INTEGRATION_TESTS=1 ${pnpmCmd('vitest', 'run', "'**/*.integration.*'", "'**/golden-*.test.*'")}`, { agentLog, cwd });
378
- const duration = Date.now() - start;
379
- return {
380
- ok: result.ok,
381
- duration,
382
- };
383
- }
384
- catch (error) {
385
- console.error('\u26A0\uFE0F Integration tests failed:', error.message);
386
- return { ok: false, duration: Date.now() - start };
387
- }
388
- }
389
- // ── Spec linter gate ───────────────────────────────────────────────────
390
- export async function runSpecLinterGate({ agentLog, useAgentMode, cwd }) {
391
- const start = Date.now();
392
- const wuId = await detectCurrentWUForCwd(cwd);
393
- const plan = resolveSpecLinterPlan(wuId);
394
- if (plan.scopedWuId) {
395
- const scopedCmd = pnpmCmd('wu:validate', '--id', plan.scopedWuId);
396
- const scopedResult = run(scopedCmd, { agentLog, cwd });
397
- if (!scopedResult.ok) {
398
- return { ok: false, duration: Date.now() - start };
399
- }
400
- return { ok: true, duration: Date.now() - start };
401
- }
402
- if (!useAgentMode) {
403
- console.log('\u26A0\uFE0F Unable to detect current WU; skipping scoped validation.');
404
- }
405
- else if (agentLog) {
406
- writeSync(agentLog.logFd, '\u26A0\uFE0F Unable to detect current WU; skipping scoped validation.\n');
407
- }
408
- if (!plan.runGlobal) {
409
- return { ok: true, duration: Date.now() - start };
410
- }
411
- const fallbackResult = run(pnpmRun(SCRIPTS.SPEC_LINTER), { agentLog, cwd });
412
- return { ok: fallbackResult.ok, duration: Date.now() - start };
413
- }
414
- // ── Backlog sync gate ──────────────────────────────────────────────────
415
- export async function runBacklogSyncGate({ agentLog, useAgentMode, cwd }) {
416
- const start = Date.now();
417
- const logLine = makeGateLogger({ agentLog, useAgentMode });
418
- logLine('\n> Backlog sync\n');
419
- const result = await validateBacklogSync({ cwd });
420
- if (result.errors.length > 0) {
421
- logLine('\u274C Backlog sync errors:');
422
- result.errors.forEach((error) => logLine(` - ${error}`));
423
- }
424
- if (result.warnings.length > 0) {
425
- logLine('\u26A0\uFE0F Backlog sync warnings:');
426
- result.warnings.forEach((warning) => logLine(` - ${warning}`));
427
- }
428
- logLine(`Backlog sync summary: WU files=${result.wuCount}, Backlog refs=${result.backlogCount}`);
429
- return { ok: result.valid, duration: Date.now() - start };
430
- }
431
- // ── Supabase docs gate ─────────────────────────────────────────────────
432
- export async function runSupabaseDocsGate({ agentLog, useAgentMode, cwd }) {
433
- const start = Date.now();
434
- const logLine = makeGateLogger({ agentLog, useAgentMode });
435
- logLine('\n> Supabase docs linter\n');
436
- const result = await runSupabaseDocsLinter({ cwd, logger: { log: logLine } });
437
- if (result.skipped) {
438
- logLine(`\u26A0\uFE0F ${result.message ?? 'Supabase docs linter skipped.'}`);
439
- }
440
- else if (!result.ok) {
441
- logLine('\u274C Supabase docs linter failed.');
442
- (result.errors ?? []).forEach((error) => logLine(` - ${error}`));
443
- }
444
- else {
445
- logLine(result.message ?? 'Supabase docs linter passed.');
446
- }
447
- return { ok: result.ok, duration: Date.now() - start };
448
- }
449
- // ── Lane health gate ───────────────────────────────────────────────────
450
- /**
451
- * WU-1191: Run lane health check gate
452
- */
453
- export async function runLaneHealthGate({ agentLog, useAgentMode, mode, cwd, }) {
454
- const start = Date.now();
455
- const logLine = makeGateLogger({ agentLog, useAgentMode });
456
- if (mode === 'off') {
457
- logLine('\n> Lane health check (skipped - mode: off)\n');
458
- return { ok: true, duration: Date.now() - start };
459
- }
460
- logLine(`\n> Lane health check (mode: ${mode})\n`);
461
- const report = runLaneHealthCheck({ projectRoot: cwd });
462
- if (!report.healthy) {
463
- logLine('\u26A0\uFE0F Lane health issues detected:');
464
- if (report.overlaps.hasOverlaps) {
465
- logLine(` - ${report.overlaps.overlaps.length} overlapping code_paths`);
466
- }
467
- if (report.gaps.hasGaps) {
468
- logLine(` - ${report.gaps.uncoveredFiles.length} uncovered files`);
469
- }
470
- logLine(` Run 'pnpm lane:health' for full report.`);
471
- if (mode === 'error') {
472
- return { ok: false, duration: Date.now() - start };
473
- }
474
- // mode === 'warn': report but don't fail
475
- logLine(' (mode: warn - not blocking)');
476
- }
477
- else {
478
- logLine('Lane health check passed.');
479
- }
480
- return { ok: true, duration: Date.now() - start };
481
- }
482
- // ── Docs-only filtered tests ───────────────────────────────────────────
483
- /**
484
- * WU-1299: Run filtered tests for docs-only mode
485
- * WU-1356: Updated to use configured test command
486
- */
487
- export async function runDocsOnlyFilteredTests({ packages, agentLog, cwd = process.cwd(), }) {
488
- const start = Date.now();
489
- const logLine = makeGateLogger({ agentLog, useAgentMode: !!agentLog, cwd });
490
- if (packages.length === 0) {
491
- logLine('\uD83D\uDCDD docs-only mode: no packages to test, skipping');
492
- return { ok: true, duration: Date.now() - start };
493
- }
494
- logLine(`\n> Tests (docs-only filtered: ${packages.join(', ')})\n`);
495
- // WU-1356: Use configured test command with filter
496
- const gatesCommands = resolveGatesCommands(cwd);
497
- // If there's a configured test_docs_only command, use it
498
- if (gatesCommands.test_docs_only) {
499
- const result = run(gatesCommands.test_docs_only, { agentLog, cwd });
500
- return { ok: result.ok, duration: Date.now() - start };
501
- }
502
- // Otherwise, use the full test command with filter args
503
- const filterArgs = packages.map((pkg) => `--filter=${pkg}`);
504
- const baseCmd = gatesCommands.test_full;
505
- const filteredCmd = `${baseCmd} ${filterArgs.join(' ')}`;
506
- const result = run(filteredCmd, { agentLog });
507
- return { ok: result.ok, duration: Date.now() - start };
508
- }
509
- //# sourceMappingURL=gates-runners.js.map