@lumenflow/cli 4.24.0 → 5.0.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 (294) hide show
  1. package/README.md +54 -52
  2. package/dist/agent-issues-query.js +10 -2
  3. package/dist/agent-issues-query.js.map +1 -1
  4. package/dist/agent-runtime-enrollment-events.js +44 -0
  5. package/dist/agent-runtime-enrollment-events.js.map +1 -0
  6. package/dist/agent-session-end.js +47 -0
  7. package/dist/agent-session-end.js.map +1 -1
  8. package/dist/agent-session-heartbeat.js +250 -0
  9. package/dist/agent-session-heartbeat.js.map +1 -0
  10. package/dist/agent-session.js +299 -5
  11. package/dist/agent-session.js.map +1 -1
  12. package/dist/capacity-snapshot-emitter.js +73 -0
  13. package/dist/capacity-snapshot-emitter.js.map +1 -0
  14. package/dist/claim-queue.js +276 -0
  15. package/dist/claim-queue.js.map +1 -0
  16. package/dist/config-set.js +22 -3
  17. package/dist/config-set.js.map +1 -1
  18. package/dist/control-plane-sidecar-runner.js +145 -0
  19. package/dist/control-plane-sidecar-runner.js.map +1 -0
  20. package/dist/delegation-list.js +160 -1
  21. package/dist/delegation-list.js.map +1 -1
  22. package/dist/delegation-role-resolver.js +69 -0
  23. package/dist/delegation-role-resolver.js.map +1 -0
  24. package/dist/docs-generate-pack-reference.js +500 -0
  25. package/dist/docs-generate-pack-reference.js.map +1 -0
  26. package/dist/docs-sync.js +116 -1
  27. package/dist/docs-sync.js.map +1 -1
  28. package/dist/file-edit.js +28 -8
  29. package/dist/file-edit.js.map +1 -1
  30. package/dist/file-write.js +29 -5
  31. package/dist/file-write.js.map +1 -1
  32. package/dist/gate-co-change.js +25 -7
  33. package/dist/gate-co-change.js.map +1 -1
  34. package/dist/gate-conditional.js +19 -7
  35. package/dist/gate-conditional.js.map +1 -1
  36. package/dist/gates-runners.js +42 -33
  37. package/dist/gates-runners.js.map +1 -1
  38. package/dist/gates-utils.js +34 -20
  39. package/dist/gates-utils.js.map +1 -1
  40. package/dist/gates.js +79 -7
  41. package/dist/gates.js.map +1 -1
  42. package/dist/hooks/config-resolver.js +10 -1
  43. package/dist/hooks/config-resolver.js.map +1 -1
  44. package/dist/init-package-config.js +1 -1
  45. package/dist/init-package-config.js.map +1 -1
  46. package/dist/init-scaffolding.js +5 -1
  47. package/dist/init-scaffolding.js.map +1 -1
  48. package/dist/init-templates.js +10 -0
  49. package/dist/init-templates.js.map +1 -1
  50. package/dist/init.js +1 -1
  51. package/dist/init.js.map +1 -1
  52. package/dist/initiative-create.js +17 -0
  53. package/dist/initiative-create.js.map +1 -1
  54. package/dist/initiative-remove-wu.js +17 -3
  55. package/dist/initiative-remove-wu.js.map +1 -1
  56. package/dist/kernel-event-sync/emitters.js +104 -0
  57. package/dist/kernel-event-sync/emitters.js.map +1 -0
  58. package/dist/kernel-event-sync/index.js +13 -0
  59. package/dist/kernel-event-sync/index.js.map +1 -0
  60. package/dist/kernel-event-sync/lifecycle-emitters.js +160 -0
  61. package/dist/kernel-event-sync/lifecycle-emitters.js.map +1 -0
  62. package/dist/kernel-event-sync/narrow-emissions.js +89 -0
  63. package/dist/kernel-event-sync/narrow-emissions.js.map +1 -0
  64. package/dist/kernel-event-sync/software-delivery-emitters.js +297 -0
  65. package/dist/kernel-event-sync/software-delivery-emitters.js.map +1 -0
  66. package/dist/lane-lock.js +14 -1
  67. package/dist/lane-lock.js.map +1 -1
  68. package/dist/lane-suggest.js +21 -0
  69. package/dist/lane-suggest.js.map +1 -1
  70. package/dist/lumenflow-upgrade.js +7 -5
  71. package/dist/lumenflow-upgrade.js.map +1 -1
  72. package/dist/mem-context.js +145 -0
  73. package/dist/mem-context.js.map +1 -1
  74. package/dist/mem-create.js +39 -6
  75. package/dist/mem-create.js.map +1 -1
  76. package/dist/mem-inbox.js +16 -0
  77. package/dist/mem-inbox.js.map +1 -1
  78. package/dist/mem-roster.js +95 -0
  79. package/dist/mem-roster.js.map +1 -0
  80. package/dist/mem-signal.js +97 -2
  81. package/dist/mem-signal.js.map +1 -1
  82. package/dist/metrics-snapshot.js +3 -2
  83. package/dist/metrics-snapshot.js.map +1 -1
  84. package/dist/orchestrate-init-status.js +117 -2
  85. package/dist/orchestrate-init-status.js.map +1 -1
  86. package/dist/orchestrate-initiative.js +83 -10
  87. package/dist/orchestrate-initiative.js.map +1 -1
  88. package/dist/orchestrate-monitor-quality.js +289 -0
  89. package/dist/orchestrate-monitor-quality.js.map +1 -0
  90. package/dist/orchestrate-monitor.js +85 -0
  91. package/dist/orchestrate-monitor.js.map +1 -1
  92. package/dist/pack-validate.js +127 -2
  93. package/dist/pack-validate.js.map +1 -1
  94. package/dist/plan-create.js +18 -0
  95. package/dist/plan-create.js.map +1 -1
  96. package/dist/plan-link.js +13 -0
  97. package/dist/plan-link.js.map +1 -1
  98. package/dist/plan-promote.js +14 -0
  99. package/dist/plan-promote.js.map +1 -1
  100. package/dist/pre-commit-check.js +4 -3
  101. package/dist/pre-commit-check.js.map +1 -1
  102. package/dist/public-manifest.js +17 -3
  103. package/dist/public-manifest.js.map +1 -1
  104. package/dist/release.js +10 -10
  105. package/dist/release.js.map +1 -1
  106. package/dist/session-cross-link.js +139 -0
  107. package/dist/session-cross-link.js.map +1 -0
  108. package/dist/sidecar-manager.js +208 -0
  109. package/dist/sidecar-manager.js.map +1 -0
  110. package/dist/state-path-resolvers.js +18 -0
  111. package/dist/state-path-resolvers.js.map +1 -1
  112. package/dist/stream-heartbeat.js +151 -0
  113. package/dist/stream-heartbeat.js.map +1 -0
  114. package/dist/sync-templates.js +56 -2
  115. package/dist/sync-templates.js.map +1 -1
  116. package/dist/wu-block.js +47 -5
  117. package/dist/wu-block.js.map +1 -1
  118. package/dist/wu-claim-branch.js +8 -4
  119. package/dist/wu-claim-branch.js.map +1 -1
  120. package/dist/wu-claim-state.js +5 -3
  121. package/dist/wu-claim-state.js.map +1 -1
  122. package/dist/wu-claim-worktree.js +5 -3
  123. package/dist/wu-claim-worktree.js.map +1 -1
  124. package/dist/wu-claim.js +261 -9
  125. package/dist/wu-claim.js.map +1 -1
  126. package/dist/wu-done-auto-cleanup.js +3 -2
  127. package/dist/wu-done-auto-cleanup.js.map +1 -1
  128. package/dist/wu-done-git-ops.js +12 -8
  129. package/dist/wu-done-git-ops.js.map +1 -1
  130. package/dist/wu-done-preflight.js +3 -3
  131. package/dist/wu-done-preflight.js.map +1 -1
  132. package/dist/wu-done.js +46 -10
  133. package/dist/wu-done.js.map +1 -1
  134. package/dist/wu-lifecycle-sync/gate-scope-resolver.js +16 -0
  135. package/dist/wu-lifecycle-sync/gate-scope-resolver.js.map +1 -0
  136. package/dist/wu-lifecycle-sync/kernel-event-sync-shim.js +10 -0
  137. package/dist/wu-lifecycle-sync/kernel-event-sync-shim.js.map +1 -0
  138. package/dist/wu-prep.js +363 -22
  139. package/dist/wu-prep.js.map +1 -1
  140. package/dist/wu-prune.js +68 -27
  141. package/dist/wu-prune.js.map +1 -1
  142. package/dist/wu-release.js +34 -3
  143. package/dist/wu-release.js.map +1 -1
  144. package/dist/wu-review.js +167 -0
  145. package/dist/wu-review.js.map +1 -0
  146. package/dist/wu-spawn-prompt-builders.js +296 -40
  147. package/dist/wu-spawn-prompt-builders.js.map +1 -1
  148. package/dist/wu-spawn-strategy-resolver.js +126 -14
  149. package/dist/wu-spawn-strategy-resolver.js.map +1 -1
  150. package/dist/wu-unblock.js +52 -22
  151. package/dist/wu-unblock.js.map +1 -1
  152. package/package.json +13 -8
  153. package/packs/agent-runtime/.turbo/turbo-build.log +1 -1
  154. package/packs/agent-runtime/.turbo/turbo-test.log +25 -0
  155. package/packs/agent-runtime/.turbo/turbo-typecheck.log +4 -0
  156. package/packs/agent-runtime/agent-heartbeat.ts +163 -0
  157. package/packs/agent-runtime/auto-session-integration.ts +874 -0
  158. package/packs/agent-runtime/delegation-registry-schema.ts +220 -0
  159. package/packs/agent-runtime/delegation-registry-store.ts +269 -0
  160. package/packs/agent-runtime/delegation-tree.ts +328 -0
  161. package/packs/agent-runtime/index.ts +9 -0
  162. package/packs/agent-runtime/manifest.ts +103 -19
  163. package/packs/agent-runtime/manifest.yaml +132 -0
  164. package/packs/agent-runtime/memory-coordination-contract.ts +86 -0
  165. package/packs/agent-runtime/memory.d.ts +19 -0
  166. package/packs/agent-runtime/orchestration.ts +238 -23
  167. package/packs/agent-runtime/package.json +11 -2
  168. package/packs/agent-runtime/remote-controls/index.ts +7 -0
  169. package/packs/agent-runtime/remote-controls/operations.ts +399 -0
  170. package/packs/agent-runtime/remote-controls/port.ts +48 -0
  171. package/packs/agent-runtime/remote-controls/state-store.ts +258 -0
  172. package/packs/agent-runtime/remote-controls/types.ts +105 -0
  173. package/packs/agent-runtime/session-schema.ts +423 -0
  174. package/packs/agent-runtime/tool-impl/index.ts +1 -0
  175. package/packs/agent-runtime/tool-impl/remote-controls.mock.ts +252 -0
  176. package/packs/agent-runtime/tool-impl/remote-controls.ts +273 -0
  177. package/packs/agent-runtime/tsconfig.json +1 -1
  178. package/packs/agent-runtime/turn-lifecycle-events.ts +501 -0
  179. package/packs/sidekick/.lumenflow/state/conductor/outbox/sidekick-events.jsonl +213 -0
  180. package/packs/sidekick/.turbo/turbo-build.log +1 -1
  181. package/packs/sidekick/.turbo/turbo-test.log +25 -0
  182. package/packs/sidekick/.turbo/turbo-typecheck.log +4 -0
  183. package/packs/sidekick/channel-ingress.ts +137 -0
  184. package/packs/sidekick/manifest.ts +74 -0
  185. package/packs/sidekick/manifest.yaml +88 -0
  186. package/packs/sidekick/package.json +3 -1
  187. package/packs/sidekick/sidekick-events.ts +517 -0
  188. package/packs/sidekick/src/adapters/cloud-queue.ts +101 -0
  189. package/packs/sidekick/src/adapters/control-plane-bridge.adapter.ts +378 -0
  190. package/packs/sidekick/src/adapters/filesystem-bridge.adapter.ts +224 -0
  191. package/packs/sidekick/src/domain/channel.types.ts +84 -0
  192. package/packs/sidekick/src/ports/channel-bridge.port.ts +75 -0
  193. package/packs/sidekick/src/routines/commit.ts +74 -0
  194. package/packs/sidekick/tool-impl/channel-tools.ts +47 -0
  195. package/packs/sidekick/tool-impl/memory-tools.ts +17 -0
  196. package/packs/sidekick/tool-impl/routine-commit.ts +102 -0
  197. package/packs/sidekick/tool-impl/routine-tools.ts +67 -7
  198. package/packs/sidekick/tool-impl/runtime-context.ts +4 -0
  199. package/packs/sidekick/tool-impl/storage.ts +3 -0
  200. package/packs/sidekick/tool-impl/system-tools.ts +7 -0
  201. package/packs/sidekick/tool-impl/task-tools.ts +46 -0
  202. package/packs/sidekick/tsconfig.json +1 -1
  203. package/packs/software-delivery/.turbo/turbo-build.log +1 -1
  204. package/packs/software-delivery/.turbo/turbo-test.log +63 -0
  205. package/packs/software-delivery/.turbo/turbo-typecheck.log +4 -0
  206. package/packs/software-delivery/manifest-schema.ts +30 -0
  207. package/packs/software-delivery/manifest.ts +99 -1
  208. package/packs/software-delivery/manifest.yaml +46 -0
  209. package/packs/software-delivery/package.json +88 -3
  210. package/packs/software-delivery/src/commands/index.ts +5 -0
  211. package/packs/software-delivery/src/config/delivery-review-contract.ts +20 -0
  212. package/packs/software-delivery/src/config/env-accessors.ts +19 -0
  213. package/packs/software-delivery/src/config/index.ts +8 -0
  214. package/packs/software-delivery/src/config/normalize-config-keys.ts +19 -0
  215. package/packs/software-delivery/src/config/schemas/lumenflow-config-schema-types.ts +436 -0
  216. package/packs/software-delivery/src/config/workspace-reader.ts +310 -0
  217. package/packs/software-delivery/src/constants/backlog-patterns.ts +31 -0
  218. package/packs/software-delivery/src/constants/client-ids.ts +19 -0
  219. package/packs/software-delivery/src/constants/config-contract.ts +7 -0
  220. package/packs/software-delivery/src/constants/docs-layout-presets.ts +50 -0
  221. package/packs/software-delivery/src/constants/duration-constants.ts +20 -0
  222. package/packs/software-delivery/src/constants/gate-constants.ts +32 -0
  223. package/packs/software-delivery/src/constants/index.ts +29 -0
  224. package/packs/software-delivery/src/constants/lock-constants.ts +35 -0
  225. package/packs/software-delivery/src/constants/object-guards.ts +12 -0
  226. package/packs/software-delivery/src/constants/section-headings.ts +107 -0
  227. package/packs/software-delivery/src/constants/wu-cli-constants.ts +485 -0
  228. package/packs/software-delivery/src/constants/wu-domain-constants.ts +466 -0
  229. package/packs/software-delivery/src/constants/wu-git-constants.ts +7 -0
  230. package/packs/software-delivery/src/constants/wu-id-format.ts +327 -0
  231. package/packs/software-delivery/src/constants/wu-paths-constants.ts +358 -0
  232. package/packs/software-delivery/src/constants/wu-statuses.ts +287 -0
  233. package/packs/software-delivery/src/constants/wu-type-helpers.ts +67 -0
  234. package/packs/software-delivery/src/constants/wu-ui-constants.ts +267 -0
  235. package/packs/software-delivery/src/constants/wu-validation-constants.ts +73 -0
  236. package/packs/software-delivery/src/domain/index.ts +5 -0
  237. package/packs/software-delivery/src/domain/orchestration.constants.ts +168 -0
  238. package/packs/software-delivery/src/domain/orchestration.schemas.ts +239 -0
  239. package/packs/software-delivery/src/domain/orchestration.types.ts +178 -0
  240. package/packs/software-delivery/src/methodology/incremental-test.ts +90 -0
  241. package/packs/software-delivery/src/methodology/index.ts +6 -0
  242. package/packs/software-delivery/src/methodology/manual-test-validator.ts +292 -0
  243. package/packs/software-delivery/src/policy/coverage-gate.ts +270 -0
  244. package/packs/software-delivery/src/policy/gates-agent-mode.ts +223 -0
  245. package/packs/software-delivery/src/policy/gates-config-internal.ts +121 -0
  246. package/packs/software-delivery/src/policy/gates-config.ts +293 -0
  247. package/packs/software-delivery/src/policy/gates-coverage.ts +247 -0
  248. package/packs/software-delivery/src/policy/gates-presets.ts +134 -0
  249. package/packs/software-delivery/src/policy/gates-schemas.ts +173 -0
  250. package/packs/software-delivery/src/policy/index.ts +22 -0
  251. package/packs/software-delivery/src/policy/package-manager-resolver.ts +319 -0
  252. package/packs/software-delivery/src/policy/resolve-policy.ts +518 -0
  253. package/packs/software-delivery/src/ports/config.ports.ts +90 -0
  254. package/packs/software-delivery/src/ports/dashboard-renderer.port.ts +125 -0
  255. package/packs/software-delivery/src/ports/index.ts +10 -0
  256. package/packs/software-delivery/src/ports/sync-validator.ports.ts +59 -0
  257. package/packs/software-delivery/src/ports/wu-helpers.ports.ts +168 -0
  258. package/packs/software-delivery/src/ports/wu-state.ports.ts +241 -0
  259. package/packs/software-delivery/src/primitives/index.ts +5 -0
  260. package/packs/software-delivery/src/runtime/index.ts +6 -0
  261. package/packs/software-delivery/src/runtime/work-classifier.ts +561 -0
  262. package/packs/software-delivery/src/sandbox/index.ts +10 -0
  263. package/packs/software-delivery/src/sandbox/sandbox-allowlist.ts +118 -0
  264. package/packs/software-delivery/src/sandbox/sandbox-backend-linux.ts +88 -0
  265. package/packs/software-delivery/src/sandbox/sandbox-backend-macos.ts +154 -0
  266. package/packs/software-delivery/src/sandbox/sandbox-backend-windows.ts +47 -0
  267. package/packs/software-delivery/src/sandbox/sandbox-profile.ts +153 -0
  268. package/packs/software-delivery/src/schemas/index.ts +5 -0
  269. package/packs/software-delivery/src/state/date-utils.ts +158 -0
  270. package/packs/software-delivery/src/state/index.ts +15 -0
  271. package/packs/software-delivery/src/state/state-machine.ts +119 -0
  272. package/packs/software-delivery/src/state/wu-doc-types.ts +51 -0
  273. package/packs/software-delivery/src/state/wu-paths.ts +381 -0
  274. package/packs/software-delivery/src/state/wu-schema.ts +1139 -0
  275. package/packs/software-delivery/src/state/wu-state-schema.ts +255 -0
  276. package/packs/software-delivery/src/state/wu-yaml.ts +338 -0
  277. package/packs/software-delivery/src/types.d.ts +16 -0
  278. package/packs/software-delivery/tool-impl/wu-lifecycle-tools.ts +18 -0
  279. package/packs/software-delivery/tsconfig.json +28 -2
  280. package/templates/core/AGENTS.md.template +76 -17
  281. package/templates/core/LUMENFLOW.md.template +265 -66
  282. package/templates/core/_frameworks/lumenflow/wu-sizing-guide.md.template +180 -116
  283. package/templates/core/ai/onboarding/agent-invocation-guide.md.template +26 -8
  284. package/templates/core/ai/onboarding/existing-project-bootstrap.md.template +171 -0
  285. package/templates/core/ai/onboarding/first-15-mins.md.template +3 -1
  286. package/templates/core/ai/onboarding/first-wu-mistakes.md.template +1 -1
  287. package/templates/core/ai/onboarding/initiative-orchestration.md.template +46 -30
  288. package/templates/core/ai/onboarding/quick-ref-commands.md.template +36 -33
  289. package/templates/core/ai/onboarding/release-process.md.template +8 -7
  290. package/templates/core/ai/onboarding/starting-prompt.md.template +2 -0
  291. package/templates/core/ai/onboarding/troubleshooting-wu-done.md.template +62 -0
  292. package/templates/vendors/claude/.claude/CLAUDE.md.template +29 -54
  293. package/templates/vendors/cursor/.cursor/rules/lumenflow.md.template +24 -52
  294. package/templates/vendors/windsurf/.windsurf/rules/lumenflow.md.template +24 -52
@@ -0,0 +1,466 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+
4
+ /**
5
+ * Domain Constants
6
+ *
7
+ * WU-1549: Extracted from wu-constants.ts for domain-specific modularity.
8
+ * Contains WU patterns, commit formats, consistency checks, cleanup guards,
9
+ * defaults, validation thresholds, safety tests, lane path patterns, and
10
+ * utility functions (toKebab, getWorktreePath, getLaneBranch, getProjectRoot).
11
+ *
12
+ * @module wu-domain-constants
13
+ */
14
+
15
+ import path from 'node:path';
16
+ import { kebabCase } from 'change-case';
17
+ import { LOG_PREFIX } from './wu-ui-constants.js';
18
+
19
+ /**
20
+ * Regex patterns for WU operations
21
+ *
22
+ * Note: WU_ID pattern is also in wu-schema.ts for Zod validation
23
+ */
24
+ export const PATTERNS = {
25
+ /** WU identifier format: WU-123 */
26
+ WU_ID: /^WU-\d+$/,
27
+
28
+ /** Extract WU ID from text: captures "WU-123" */
29
+ WU_ID_EXTRACT: /WU-\d+/,
30
+
31
+ /**
32
+ * Extract WU ID from worktree paths (case-insensitive)
33
+ *
34
+ * WU-1090: Worktree names use lowercase like 'framework-core-wu-1090'
35
+ * This pattern matches both 'WU-123' and 'wu-123' to support
36
+ * extracting WU IDs from worktree paths.
37
+ */
38
+ WU_ID_EXTRACT_CI: /wu-\d+/i,
39
+
40
+ /** Lane branch format: lane/<lane-kebab>/wu-<id> */
41
+ LANE_BRANCH: /^lane\/[\w-]+\/wu-\d+$/,
42
+
43
+ /** Worktree path format: worktrees/<lane-kebab>-wu-<id> */
44
+ WORKTREE_PATH: /^worktrees\/[\w-]+-wu-\d+$/,
45
+ };
46
+
47
+ /**
48
+ * Commit message formats
49
+ *
50
+ * These are functions that generate properly formatted commit messages
51
+ */
52
+ export const COMMIT_FORMATS = {
53
+ CLAIM: (id: string, laneKebab: string) => `wu(${id}): claim for ${laneKebab} lane`,
54
+ DONE: (id: string, title: string) => `wu(${id}): done - ${title}`,
55
+ CREATE: (id: string, title: string) => `docs: create ${id.toLowerCase()} for ${title}`,
56
+ EDIT: (id: string) => `docs: edit ${id.toLowerCase()} spec`,
57
+ SPEC_UPDATE: (id: string) => `wu(${id.toLowerCase()}): spec update`,
58
+ BLOCK: (id: string) => `wu(${id}): block`,
59
+ UNBLOCK: (id: string) => `wu(${id}): unblock`,
60
+ REPAIR: (id: string) => `fix(${id}): repair state inconsistency`,
61
+ REBASE_ARTIFACT_CLEANUP: (id: string) =>
62
+ `chore(${id.toLowerCase()}): remove rebased completion artifacts`,
63
+ BACKLOG_REPAIR: (id: string) =>
64
+ `chore(repair): repair backlog duplicates for ${id.toLowerCase()}`,
65
+ ESCALATE: (id: string) => `wu(${id.toLowerCase()}): resolve escalation`,
66
+ };
67
+
68
+ /**
69
+ * Consistency check types (WU-1276)
70
+ *
71
+ * Layer 2 defense-in-depth: detect and repair WU state inconsistencies
72
+ */
73
+ export const CONSISTENCY_TYPES = {
74
+ /** WU YAML has status 'done' but WU appears in status.md In Progress section */
75
+ YAML_DONE_STATUS_IN_PROGRESS: 'YAML_DONE_STATUS_IN_PROGRESS',
76
+
77
+ /** WU appears in both Done AND In Progress sections of backlog.md */
78
+ BACKLOG_DUAL_SECTION: 'BACKLOG_DUAL_SECTION',
79
+
80
+ /** WU YAML has status 'done' but no stamp file exists */
81
+ YAML_DONE_NO_STAMP: 'YAML_DONE_NO_STAMP',
82
+
83
+ /** WU has status 'done' but still has an associated worktree */
84
+ ORPHAN_WORKTREE_DONE: 'ORPHAN_WORKTREE_DONE',
85
+
86
+ /** Stamp file exists but WU YAML status is not 'done' (partial wu:done failure) */
87
+ STAMP_EXISTS_YAML_NOT_DONE: 'STAMP_EXISTS_YAML_NOT_DONE',
88
+
89
+ /** WU is claimed but its worktree directory is missing */
90
+ MISSING_WORKTREE_CLAIMED: 'MISSING_WORKTREE_CLAIMED',
91
+ };
92
+
93
+ /**
94
+ * Consistency check messages
95
+ */
96
+ export const CONSISTENCY_MESSAGES = {
97
+ MISSING_WORKTREE_CLAIMED: (id: string, status: string, worktreePath: string) =>
98
+ `WU ${id} is '${status}' but worktree path is missing (${worktreePath})`,
99
+ MISSING_WORKTREE_CLAIMED_REPAIR: 'Recover worktree or re-claim WU',
100
+ };
101
+
102
+ /**
103
+ * Worktree warning messages
104
+ */
105
+ export const WORKTREE_WARNINGS = {
106
+ MISSING_TRACKED_HEADER: 'Tracked worktrees missing on disk (possible manual deletion):',
107
+ MISSING_TRACKED_LINE: (worktreePath: string) => `Missing: ${worktreePath}`,
108
+ };
109
+
110
+ /**
111
+ * Cleanup guard constants
112
+ */
113
+ export const CLEANUP_GUARD = {
114
+ REASONS: {
115
+ UNCOMMITTED_CHANGES: 'UNCOMMITTED_CHANGES',
116
+ UNPUSHED_COMMITS: 'UNPUSHED_COMMITS',
117
+ STATUS_NOT_DONE: 'STATUS_NOT_DONE',
118
+ MISSING_STAMP: 'MISSING_STAMP',
119
+ PR_NOT_MERGED: 'PR_NOT_MERGED',
120
+ },
121
+ TITLES: {
122
+ BLOCKED: 'CLEANUP BLOCKED',
123
+ NEXT_STEPS: 'Next steps:',
124
+ },
125
+ MESSAGES: {
126
+ UNCOMMITTED_CHANGES: 'Worktree has uncommitted changes. Refusing to delete.',
127
+ UNPUSHED_COMMITS: 'Worktree has unpushed commits. Refusing to delete.',
128
+ STATUS_NOT_DONE: 'WU YAML status is not done. Refusing to delete.',
129
+ MISSING_STAMP: 'WU stamp is missing. Refusing to delete.',
130
+ PR_NOT_MERGED: 'PR is not merged (or cannot be verified). Refusing to delete.',
131
+ },
132
+ /* eslint-disable sonarjs/no-duplicate-string -- Intentional: cleanup instructions repeated for each error type for readability */
133
+ NEXT_STEPS: {
134
+ DEFAULT: [
135
+ { text: '1. Resolve the issue above', appendId: false },
136
+ { text: '2. Re-run: pnpm wu:cleanup --id', appendId: true },
137
+ ],
138
+ UNCOMMITTED_CHANGES: [
139
+ { text: '1. Commit or stash changes in the worktree', appendId: false },
140
+ { text: '2. Re-run: pnpm wu:cleanup --id', appendId: true },
141
+ ],
142
+ UNPUSHED_COMMITS: [
143
+ { text: '1. Push the lane branch to origin', appendId: false },
144
+ { text: '2. Re-run: pnpm wu:cleanup --id', appendId: true },
145
+ ],
146
+ STATUS_NOT_DONE: [
147
+ {
148
+ text: `1. Complete the WU with ${LOG_PREFIX.DONE} (creates stamp + done status)`,
149
+ appendId: false,
150
+ },
151
+ { text: '2. Re-run: pnpm wu:cleanup --id', appendId: true },
152
+ ],
153
+ MISSING_STAMP: [
154
+ { text: '1. Run wu:done to create the stamp file', appendId: false },
155
+ { text: '2. Re-run: pnpm wu:cleanup --id', appendId: true },
156
+ ],
157
+ PR_NOT_MERGED: [
158
+ { text: '1. Merge the PR in GitHub', appendId: false },
159
+ { text: '2. Re-run: pnpm wu:cleanup --id', appendId: true },
160
+ ],
161
+ },
162
+ /* eslint-enable sonarjs/no-duplicate-string */
163
+ PR_CHECK: {
164
+ START: 'Verifying PR merge status...',
165
+ RESULT: 'PR merge verification via',
166
+ },
167
+ };
168
+
169
+ /**
170
+ * Session display constants
171
+ *
172
+ * Emergency fix (Session 2): Centralized from hardcoded magic numbers
173
+ */
174
+ export const SESSION = {
175
+ /** Standard length for displaying session ID prefix (e.g., "sess-123") */
176
+ ID_DISPLAY_LENGTH: 8,
177
+ };
178
+
179
+ /**
180
+ * Validation constants
181
+ *
182
+ * WU-1281: Centralized from local constants in validators
183
+ */
184
+ export const VALIDATION = {
185
+ /** Minimum description length for WU spec completeness */
186
+ MIN_DESCRIPTION_LENGTH: 50,
187
+ };
188
+
189
+ /**
190
+ * Threshold constants for pre-flight checks
191
+ *
192
+ * WU-1302: Centralized to eliminate magic numbers
193
+ * WU-1370: Added graduated drift thresholds for early warnings
194
+ */
195
+ export const THRESHOLDS = {
196
+ /** Info threshold: commits behind main to suggest rebasing (WU-1370) */
197
+ BRANCH_DRIFT_INFO: 10,
198
+
199
+ /** Warning threshold: commits behind main where rebase is recommended (WU-1370) */
200
+ BRANCH_DRIFT_WARNING: 15,
201
+
202
+ /** Maximum commits behind main before requiring rebase (WU-755 pre-flight) */
203
+ BRANCH_DRIFT_MAX: 20,
204
+ };
205
+
206
+ /**
207
+ * Default values
208
+ */
209
+ export const DEFAULTS = {
210
+ /** Default worktrees directory */
211
+ WORKTREES_DIR: 'worktrees',
212
+
213
+ /** Maximum commit subject length (commitlint default) */
214
+ MAX_COMMIT_SUBJECT: 100,
215
+
216
+ /** Parent directory traversal depth from tools/lib to project root */
217
+ PROJECT_ROOT_DEPTH: 2,
218
+
219
+ /**
220
+ * Default email domain for username -> email conversion
221
+ * WU-1068: Made configurable, no longer hardcoded to exampleapp.co.uk
222
+ * @see user-normalizer.ts - Infers from git config first
223
+ */
224
+ EMAIL_DOMAIN: 'example.com',
225
+ };
226
+
227
+ /**
228
+ * Default values for WU YAML fields
229
+ *
230
+ * WU-1337: Centralized defaults for auto-repair in schema validation
231
+ * DRY principle: Single source of truth for optional field defaults
232
+ *
233
+ * Used by wu-schema.ts Zod transformations to provide sensible defaults
234
+ * when agents omit optional fields, reducing validation errors.
235
+ */
236
+ export const WU_DEFAULTS = {
237
+ /** Default priority level (medium priority) */
238
+ priority: 'P2',
239
+
240
+ /** Default status for new WUs */
241
+ status: 'ready',
242
+
243
+ /** Default work type */
244
+ type: 'feature',
245
+
246
+ /** Default code paths (empty until populated) */
247
+ code_paths: [] as string[],
248
+
249
+ /** Default test structure (includes all test types) */
250
+ tests: {
251
+ manual: [] as string[],
252
+ unit: [] as string[],
253
+ integration: [] as string[],
254
+ e2e: [] as string[],
255
+ },
256
+
257
+ /** Default artifacts (empty - wu:done adds stamp) */
258
+ artifacts: [] as string[],
259
+
260
+ /** Default dependencies (no blockers) */
261
+ dependencies: [] as string[],
262
+
263
+ /** Default risks (none identified) */
264
+ risks: [] as string[],
265
+
266
+ /** Default notes (empty string, not undefined) */
267
+ notes: '',
268
+
269
+ /** Default review requirement (agent-completed WUs) */
270
+ requires_review: false,
271
+ };
272
+
273
+ /**
274
+ * Safety-critical test glob patterns
275
+ *
276
+ * WU-2242: Centralized list of glob patterns for safety tests that MUST exist.
277
+ * Gates fail if UnsafeAny of these patterns find no matches.
278
+ */
279
+ export const SAFETY_CRITICAL_TEST_GLOBS = Object.freeze([
280
+ // Escalation trigger tests
281
+ 'apps/web/src/**/*escalation*.test.{ts,tsx}',
282
+ 'apps/web/src/**/*Escalation*.test.{ts,tsx}',
283
+
284
+ // Privacy detection tests
285
+ 'apps/web/src/**/*privacy*.test.{ts,tsx}',
286
+ 'apps/web/src/**/*Privacy*.test.{ts,tsx}',
287
+
288
+ // Constitutional enforcer tests
289
+ 'apps/web/src/**/*constitutional*.test.{ts,tsx}',
290
+ 'apps/web/src/**/*Constitutional*.test.{ts,tsx}',
291
+
292
+ // Safe prompt wrapper tests
293
+ 'apps/web/src/**/*safePrompt*.test.{ts,tsx}',
294
+ 'apps/web/src/**/*SafePrompt*.test.{ts,tsx}',
295
+
296
+ // Crisis/emergency handling tests
297
+ 'apps/web/src/**/*crisis*.test.{ts,tsx}',
298
+ 'apps/web/src/**/*Crisis*.test.{ts,tsx}',
299
+ ]);
300
+
301
+ /**
302
+ * Lane-to-code_paths validation patterns (WU-1372)
303
+ *
304
+ * Advisory patterns to warn when a WU's lane doesn't match its code_paths.
305
+ */
306
+ export const LANE_PATH_PATTERNS = {
307
+ Operations: {
308
+ exclude: ['ai/prompts/**', 'apps/web/src/lib/prompts/**'],
309
+ allowExceptions: [] as string[],
310
+ },
311
+ Intelligence: {
312
+ exclude: ['tools/**'],
313
+ allowExceptions: ['tools/lib/prompt-*', 'tools/prompts-eval/**'],
314
+ },
315
+ };
316
+
317
+ /**
318
+ * Convert lane name to kebab-case using change-case library
319
+ *
320
+ * @param lane - Lane name (e.g., 'Operations: Tooling')
321
+ * @returns Kebab-case lane (e.g., 'operations-tooling')
322
+ */
323
+ export function toKebab(lane: string | null | undefined): string {
324
+ if (lane == null) return '';
325
+ const normalized = String(lane).trim();
326
+ if (normalized === '') return '';
327
+ return kebabCase(normalized);
328
+ }
329
+
330
+ /**
331
+ * Generate worktree path from lane and WU ID
332
+ *
333
+ * @param lane - Lane name
334
+ * @param id - WU ID
335
+ * @returns Worktree path (e.g., 'worktrees/operations-tooling-wu-123')
336
+ */
337
+ export function getWorktreePath(lane: string, id: string): string {
338
+ const laneKebab = toKebab(lane);
339
+ const idLower = id.toLowerCase();
340
+ return `${DEFAULTS.WORKTREES_DIR}/${laneKebab}-${idLower}`;
341
+ }
342
+
343
+ /**
344
+ * Generate lane branch name from lane and WU ID
345
+ *
346
+ * @param lane - Lane name
347
+ * @param id - WU ID
348
+ * @returns Branch name (e.g., 'lane/operations-tooling/wu-123')
349
+ */
350
+ export function getLaneBranch(lane: string, id: string): string {
351
+ const laneKebab = toKebab(lane);
352
+ const idLower = id.toLowerCase();
353
+ return `lane/${laneKebab}/${idLower}`;
354
+ }
355
+
356
+ /**
357
+ * Get project root directory from a module URL
358
+ *
359
+ * WU-923: Centralized path resolution to eliminate '../..' magic strings
360
+ *
361
+ * @param moduleUrl - import.meta.url of the calling module
362
+ * @returns Absolute path to project root
363
+ */
364
+ export function getProjectRoot(moduleUrl: string): string {
365
+ const { dirname } = path;
366
+ const currentDir = dirname(new URL(moduleUrl).pathname);
367
+
368
+ let root = currentDir;
369
+ for (let i = 0; i < DEFAULTS.PROJECT_ROOT_DEPTH; i++) {
370
+ root = dirname(root);
371
+ }
372
+ return root;
373
+ }
374
+
375
+ /**
376
+ * Options for discovering safety tests
377
+ */
378
+ export interface DiscoverSafetyTestsOptions {
379
+ /** Project root directory */
380
+ projectRoot?: string;
381
+ }
382
+
383
+ /**
384
+ * Discover safety-critical test files
385
+ *
386
+ * WU-2242: Scans for test files matching safety-critical patterns.
387
+ * Uses glob to find all matching files.
388
+ *
389
+ * @param options - Discovery options
390
+ * @returns List of discovered test file paths
391
+ */
392
+ export async function discoverSafetyTests(
393
+ options: DiscoverSafetyTestsOptions = {},
394
+ ): Promise<string[]> {
395
+ const { projectRoot = process.cwd() } = options;
396
+ const { glob } = await import('glob');
397
+ const foundFiles: string[] = [];
398
+
399
+ for (const pattern of SAFETY_CRITICAL_TEST_GLOBS) {
400
+ try {
401
+ const matches = await glob(pattern, {
402
+ cwd: projectRoot,
403
+ absolute: false,
404
+ });
405
+ foundFiles.push(...matches);
406
+ } catch {
407
+ // Pattern may not match anything, that's fine
408
+ }
409
+ }
410
+
411
+ return [...new Set(foundFiles)]; // Deduplicate
412
+ }
413
+
414
+ /**
415
+ * Validate that required safety-critical tests exist
416
+ *
417
+ * WU-2242: Checks that each pattern category has at least one matching test file.
418
+ * Returns a validation result with missing patterns and found files.
419
+ */
420
+ export async function validateSafetyTestsExist(options: DiscoverSafetyTestsOptions = {}) {
421
+ const { projectRoot = process.cwd() } = options;
422
+ const { glob } = await import('glob');
423
+
424
+ const missingTests: string[] = [];
425
+ const foundTests: string[] = [];
426
+
427
+ const categories = [
428
+ { name: 'Escalation', patterns: SAFETY_CRITICAL_TEST_GLOBS.slice(0, 2) },
429
+ { name: 'Privacy detection', patterns: SAFETY_CRITICAL_TEST_GLOBS.slice(2, 4) },
430
+ { name: 'Constitutional', patterns: SAFETY_CRITICAL_TEST_GLOBS.slice(4, 6) },
431
+ { name: 'Safe prompt wrapper', patterns: SAFETY_CRITICAL_TEST_GLOBS.slice(6, 8) },
432
+ { name: 'Crisis handling', patterns: SAFETY_CRITICAL_TEST_GLOBS.slice(8, 10) },
433
+ ];
434
+
435
+ for (const category of categories) {
436
+ let categoryHasTests = false;
437
+
438
+ for (const pattern of category.patterns) {
439
+ try {
440
+ const matches = await glob(pattern, {
441
+ cwd: projectRoot,
442
+ absolute: false,
443
+ });
444
+ if (matches.length > 0) {
445
+ categoryHasTests = true;
446
+ foundTests.push(...matches);
447
+ }
448
+ } catch {
449
+ // Pattern error, treat as no matches
450
+ }
451
+ }
452
+
453
+ if (!categoryHasTests) {
454
+ missingTests.push(`${category.name}: ${category.patterns.join(', ')}`);
455
+ }
456
+ }
457
+
458
+ const valid = missingTests.length === 0;
459
+
460
+ return {
461
+ valid,
462
+ missingTests,
463
+ foundTests: [...new Set(foundTests)],
464
+ error: valid ? undefined : `Missing safety-critical tests: ${missingTests.join('; ')}`,
465
+ };
466
+ }
@@ -0,0 +1,7 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+
4
+ // WU-2681 (INIT-058 L2e): Shim — real module lives in @lumenflow/kernel/primitives/git-constants.
5
+ // Re-export preserves the `@lumenflow/packs-software-delivery/constants/wu-git-constants` subpath
6
+ // for existing consumers (including core's WU-2679 shim) until Layer 7 removes the shim.
7
+ export * from '@lumenflow/kernel/primitives/git-constants';