@lumenflow/cli 5.4.0 → 5.7.12

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 (227) hide show
  1. package/README.md +42 -40
  2. package/dist/db-journal-recover.js +400 -0
  3. package/dist/db-journal-recover.js.map +1 -0
  4. package/dist/docs-sync.js +8 -3
  5. package/dist/docs-sync.js.map +1 -1
  6. package/dist/gate-defaults.js +191 -9
  7. package/dist/gate-defaults.js.map +1 -1
  8. package/dist/gate-registry.js.map +1 -1
  9. package/dist/gates/monolithic-file-contention-guard.js +167 -0
  10. package/dist/gates/monolithic-file-contention-guard.js.map +1 -0
  11. package/dist/gates/prod-migration-drift.js +207 -0
  12. package/dist/gates/prod-migration-drift.js.map +1 -0
  13. package/dist/gates/test-over-deletion-guard.js +255 -0
  14. package/dist/gates/test-over-deletion-guard.js.map +1 -0
  15. package/dist/gates-runners.js +401 -2
  16. package/dist/gates-runners.js.map +1 -1
  17. package/dist/gates.js +349 -4
  18. package/dist/gates.js.map +1 -1
  19. package/dist/lumenflow-setup.js +144 -0
  20. package/dist/lumenflow-setup.js.map +1 -0
  21. package/dist/lumenflow-upgrade.js +2 -1
  22. package/dist/lumenflow-upgrade.js.map +1 -1
  23. package/dist/mem-create.js +10 -1
  24. package/dist/mem-create.js.map +1 -1
  25. package/dist/mem-signal.js +21 -4
  26. package/dist/mem-signal.js.map +1 -1
  27. package/dist/metrics-cli.js +19 -2
  28. package/dist/metrics-cli.js.map +1 -1
  29. package/dist/metrics-snapshot.js +25 -2
  30. package/dist/metrics-snapshot.js.map +1 -1
  31. package/dist/orchestrate-initiative.js +28 -3
  32. package/dist/orchestrate-initiative.js.map +1 -1
  33. package/dist/public-manifest.js +17 -0
  34. package/dist/public-manifest.js.map +1 -1
  35. package/dist/release.js +53 -18
  36. package/dist/release.js.map +1 -1
  37. package/dist/wu-done-gates.js +121 -8
  38. package/dist/wu-done-gates.js.map +1 -1
  39. package/dist/wu-done.js +30 -6
  40. package/dist/wu-done.js.map +1 -1
  41. package/dist/wu-edit-operations.js +74 -0
  42. package/dist/wu-edit-operations.js.map +1 -1
  43. package/dist/wu-edit-validators.js +58 -0
  44. package/dist/wu-edit-validators.js.map +1 -1
  45. package/dist/wu-edit.js +106 -4
  46. package/dist/wu-edit.js.map +1 -1
  47. package/dist/wu-prep.js +132 -8
  48. package/dist/wu-prep.js.map +1 -1
  49. package/dist/wu-recover.js +6 -0
  50. package/dist/wu-recover.js.map +1 -1
  51. package/dist/wu-release.js +120 -2
  52. package/dist/wu-release.js.map +1 -1
  53. package/dist/wu-sizing-validation.js +47 -17
  54. package/dist/wu-sizing-validation.js.map +1 -1
  55. package/dist/wu-status.js +33 -0
  56. package/dist/wu-status.js.map +1 -1
  57. package/package.json +13 -11
  58. package/packs/agent-runtime/package.json +1 -1
  59. package/packs/sidekick/package.json +1 -1
  60. package/packs/software-delivery/package.json +1 -1
  61. package/templates/core/AGENTS.md.template +162 -26
  62. package/templates/core/LUMENFLOW.md.template +381 -70
  63. package/templates/core/ai/onboarding/agent-invocation-guide.md.template +0 -5
  64. package/templates/core/ai/onboarding/agent-safety-card.md.template +63 -17
  65. package/templates/core/ai/onboarding/initiative-orchestration.md.template +4 -0
  66. package/templates/core/ai/onboarding/release-process.md.template +7 -7
  67. package/templates/core/ai/onboarding/vendor-support.md.template +74 -10
  68. package/templates/vendors/claude/.claude/skills/frontend-design/SKILL.md.template +1 -1
  69. package/templates/vendors/claude/.claude/skills/wu-lifecycle/SKILL.md.template +28 -0
  70. package/packs/agent-runtime/agent-heartbeat.ts +0 -163
  71. package/packs/agent-runtime/auto-session-integration.ts +0 -888
  72. package/packs/agent-runtime/capability-factory.ts +0 -104
  73. package/packs/agent-runtime/constants.ts +0 -21
  74. package/packs/agent-runtime/delegation-registry-schema.ts +0 -220
  75. package/packs/agent-runtime/delegation-registry-store.ts +0 -269
  76. package/packs/agent-runtime/delegation-tree.ts +0 -328
  77. package/packs/agent-runtime/index.ts +0 -20
  78. package/packs/agent-runtime/manifest.ts +0 -348
  79. package/packs/agent-runtime/memory-coordination-contract.ts +0 -86
  80. package/packs/agent-runtime/orchestration.ts +0 -2027
  81. package/packs/agent-runtime/pack-registration.ts +0 -110
  82. package/packs/agent-runtime/policy-factory.ts +0 -165
  83. package/packs/agent-runtime/remote-controls/index.ts +0 -7
  84. package/packs/agent-runtime/remote-controls/operations.ts +0 -405
  85. package/packs/agent-runtime/remote-controls/port.ts +0 -48
  86. package/packs/agent-runtime/remote-controls/state-store.ts +0 -258
  87. package/packs/agent-runtime/remote-controls/types.ts +0 -105
  88. package/packs/agent-runtime/session-schema.ts +0 -467
  89. package/packs/agent-runtime/tool-impl/agent-turn-tools.ts +0 -793
  90. package/packs/agent-runtime/tool-impl/index.ts +0 -6
  91. package/packs/agent-runtime/tool-impl/provider-adapters.ts +0 -1245
  92. package/packs/agent-runtime/tool-impl/remote-controls.mock.ts +0 -256
  93. package/packs/agent-runtime/tool-impl/remote-controls.ts +0 -273
  94. package/packs/agent-runtime/tools/index.ts +0 -4
  95. package/packs/agent-runtime/tools/types.ts +0 -47
  96. package/packs/agent-runtime/turn-lifecycle-events.ts +0 -590
  97. package/packs/agent-runtime/types.ts +0 -128
  98. package/packs/agent-runtime/vitest.config.ts +0 -11
  99. package/packs/sidekick/channel-ingress.ts +0 -137
  100. package/packs/sidekick/constants.ts +0 -10
  101. package/packs/sidekick/index.ts +0 -8
  102. package/packs/sidekick/manifest-schema.ts +0 -49
  103. package/packs/sidekick/manifest.ts +0 -512
  104. package/packs/sidekick/pack-registration.ts +0 -110
  105. package/packs/sidekick/policy-factory.ts +0 -38
  106. package/packs/sidekick/sidekick-events.ts +0 -694
  107. package/packs/sidekick/src/adapters/cloud-queue.ts +0 -101
  108. package/packs/sidekick/src/adapters/control-plane-bridge.adapter.ts +0 -386
  109. package/packs/sidekick/src/adapters/filesystem-bridge.adapter.ts +0 -228
  110. package/packs/sidekick/src/domain/channel.types.ts +0 -64
  111. package/packs/sidekick/src/ports/channel-bridge.port.ts +0 -92
  112. package/packs/sidekick/src/routines/commit.ts +0 -74
  113. package/packs/sidekick/tool-impl/channel-tools.ts +0 -577
  114. package/packs/sidekick/tool-impl/channel-transports.ts +0 -75
  115. package/packs/sidekick/tool-impl/index.ts +0 -29
  116. package/packs/sidekick/tool-impl/memory-tools.ts +0 -290
  117. package/packs/sidekick/tool-impl/routine-commit.ts +0 -102
  118. package/packs/sidekick/tool-impl/routine-tools.ts +0 -440
  119. package/packs/sidekick/tool-impl/runtime-context.ts +0 -28
  120. package/packs/sidekick/tool-impl/shared.ts +0 -125
  121. package/packs/sidekick/tool-impl/storage.ts +0 -325
  122. package/packs/sidekick/tool-impl/system-tools.ts +0 -160
  123. package/packs/sidekick/tool-impl/task-tools.ts +0 -506
  124. package/packs/sidekick/tools/channel-tools.ts +0 -53
  125. package/packs/sidekick/tools/index.ts +0 -9
  126. package/packs/sidekick/tools/memory-tools.ts +0 -53
  127. package/packs/sidekick/tools/routine-tools.ts +0 -53
  128. package/packs/sidekick/tools/system-tools.ts +0 -47
  129. package/packs/sidekick/tools/task-tools.ts +0 -61
  130. package/packs/sidekick/tools/types.ts +0 -57
  131. package/packs/sidekick/vitest.config.ts +0 -11
  132. package/packs/software-delivery/constants.ts +0 -10
  133. package/packs/software-delivery/extensions.ts +0 -140
  134. package/packs/software-delivery/gate-policies.ts +0 -134
  135. package/packs/software-delivery/index.ts +0 -8
  136. package/packs/software-delivery/manifest-schema.ts +0 -268
  137. package/packs/software-delivery/manifest.ts +0 -657
  138. package/packs/software-delivery/pack-registration.ts +0 -113
  139. package/packs/software-delivery/src/commands/index.ts +0 -5
  140. package/packs/software-delivery/src/config/delivery-review-contract.ts +0 -256
  141. package/packs/software-delivery/src/config/env-accessors.ts +0 -66
  142. package/packs/software-delivery/src/config/index.ts +0 -8
  143. package/packs/software-delivery/src/config/normalize-config-keys.ts +0 -9
  144. package/packs/software-delivery/src/config/schemas/lumenflow-config-schema-types.ts +0 -460
  145. package/packs/software-delivery/src/config/workspace-reader.ts +0 -375
  146. package/packs/software-delivery/src/constants/backlog-patterns.ts +0 -31
  147. package/packs/software-delivery/src/constants/client-ids.ts +0 -19
  148. package/packs/software-delivery/src/constants/config-contract.ts +0 -7
  149. package/packs/software-delivery/src/constants/docs-layout-presets.ts +0 -50
  150. package/packs/software-delivery/src/constants/duration-constants.ts +0 -20
  151. package/packs/software-delivery/src/constants/gate-constants.ts +0 -32
  152. package/packs/software-delivery/src/constants/index.ts +0 -29
  153. package/packs/software-delivery/src/constants/lock-constants.ts +0 -35
  154. package/packs/software-delivery/src/constants/object-guards.ts +0 -12
  155. package/packs/software-delivery/src/constants/section-headings.ts +0 -107
  156. package/packs/software-delivery/src/constants/wu-cli-constants.ts +0 -488
  157. package/packs/software-delivery/src/constants/wu-domain-constants.ts +0 -466
  158. package/packs/software-delivery/src/constants/wu-git-constants.ts +0 -7
  159. package/packs/software-delivery/src/constants/wu-id-format.ts +0 -327
  160. package/packs/software-delivery/src/constants/wu-paths-constants.ts +0 -384
  161. package/packs/software-delivery/src/constants/wu-statuses.ts +0 -287
  162. package/packs/software-delivery/src/constants/wu-type-helpers.ts +0 -67
  163. package/packs/software-delivery/src/constants/wu-ui-constants.ts +0 -267
  164. package/packs/software-delivery/src/constants/wu-validation-constants.ts +0 -73
  165. package/packs/software-delivery/src/domain/index.ts +0 -5
  166. package/packs/software-delivery/src/domain/orchestration.constants.ts +0 -166
  167. package/packs/software-delivery/src/domain/orchestration.schemas.ts +0 -238
  168. package/packs/software-delivery/src/domain/orchestration.types.ts +0 -176
  169. package/packs/software-delivery/src/methodology/incremental-test.ts +0 -122
  170. package/packs/software-delivery/src/methodology/index.ts +0 -6
  171. package/packs/software-delivery/src/methodology/manual-test-validator.ts +0 -292
  172. package/packs/software-delivery/src/policy/coverage-gate.ts +0 -270
  173. package/packs/software-delivery/src/policy/gates-agent-mode.ts +0 -223
  174. package/packs/software-delivery/src/policy/gates-config-internal.ts +0 -121
  175. package/packs/software-delivery/src/policy/gates-config.ts +0 -300
  176. package/packs/software-delivery/src/policy/gates-coverage.ts +0 -356
  177. package/packs/software-delivery/src/policy/gates-presets.ts +0 -134
  178. package/packs/software-delivery/src/policy/gates-schemas.ts +0 -173
  179. package/packs/software-delivery/src/policy/index.ts +0 -22
  180. package/packs/software-delivery/src/policy/package-manager-resolver.ts +0 -319
  181. package/packs/software-delivery/src/policy/resolve-policy.ts +0 -601
  182. package/packs/software-delivery/src/ports/config.ports.ts +0 -90
  183. package/packs/software-delivery/src/ports/dashboard-renderer.port.ts +0 -125
  184. package/packs/software-delivery/src/ports/index.ts +0 -10
  185. package/packs/software-delivery/src/ports/sync-validator.ports.ts +0 -59
  186. package/packs/software-delivery/src/ports/wu-helpers.ports.ts +0 -168
  187. package/packs/software-delivery/src/ports/wu-state.ports.ts +0 -241
  188. package/packs/software-delivery/src/primitives/index.ts +0 -5
  189. package/packs/software-delivery/src/runtime/index.ts +0 -6
  190. package/packs/software-delivery/src/runtime/work-classifier.ts +0 -561
  191. package/packs/software-delivery/src/sandbox/index.ts +0 -10
  192. package/packs/software-delivery/src/sandbox/sandbox-allowlist.ts +0 -118
  193. package/packs/software-delivery/src/sandbox/sandbox-backend-linux.ts +0 -88
  194. package/packs/software-delivery/src/sandbox/sandbox-backend-macos.ts +0 -154
  195. package/packs/software-delivery/src/sandbox/sandbox-backend-windows.ts +0 -47
  196. package/packs/software-delivery/src/sandbox/sandbox-profile.ts +0 -153
  197. package/packs/software-delivery/src/schemas/index.ts +0 -5
  198. package/packs/software-delivery/src/state/date-utils.ts +0 -158
  199. package/packs/software-delivery/src/state/index.ts +0 -15
  200. package/packs/software-delivery/src/state/state-machine.ts +0 -119
  201. package/packs/software-delivery/src/state/wu-doc-types.ts +0 -51
  202. package/packs/software-delivery/src/state/wu-paths.ts +0 -381
  203. package/packs/software-delivery/src/state/wu-schema.ts +0 -1139
  204. package/packs/software-delivery/src/state/wu-state-schema.ts +0 -255
  205. package/packs/software-delivery/src/state/wu-yaml.ts +0 -338
  206. package/packs/software-delivery/tool-impl/agent-tools.ts +0 -263
  207. package/packs/software-delivery/tool-impl/delegation-tools.ts +0 -66
  208. package/packs/software-delivery/tool-impl/flow-metrics-tools.ts +0 -219
  209. package/packs/software-delivery/tool-impl/git-runner.ts +0 -113
  210. package/packs/software-delivery/tool-impl/git-tools.ts +0 -316
  211. package/packs/software-delivery/tool-impl/index.ts +0 -15
  212. package/packs/software-delivery/tool-impl/initiative-orchestration-tools.ts +0 -720
  213. package/packs/software-delivery/tool-impl/lane-lock.ts +0 -246
  214. package/packs/software-delivery/tool-impl/memory-tools.ts +0 -470
  215. package/packs/software-delivery/tool-impl/pending-runtime-tools.ts +0 -21
  216. package/packs/software-delivery/tool-impl/runtime-cli-adapter.ts +0 -329
  217. package/packs/software-delivery/tool-impl/runtime-native-tools.ts +0 -687
  218. package/packs/software-delivery/tool-impl/worker-loader.ts +0 -52
  219. package/packs/software-delivery/tool-impl/worktree-tools.ts +0 -46
  220. package/packs/software-delivery/tool-impl/wu-lifecycle-tools.ts +0 -807
  221. package/packs/software-delivery/tools/delegation-tools.ts +0 -23
  222. package/packs/software-delivery/tools/git-tools.ts +0 -55
  223. package/packs/software-delivery/tools/index.ts +0 -8
  224. package/packs/software-delivery/tools/lane-lock-tool.ts +0 -37
  225. package/packs/software-delivery/tools/types.ts +0 -71
  226. package/packs/software-delivery/tools/worktree-tools.ts +0 -49
  227. package/packs/software-delivery/vitest.config.ts +0 -11
@@ -1,327 +0,0 @@
1
- // Copyright (c) 2026 Hellmai Ltd
2
- // SPDX-License-Identifier: LicenseRef-LumenFlow-Proprietary
3
-
4
- /**
5
- * WU ID Format Primitives (WU-2552)
6
- *
7
- * Canonical zero-padded WU ID primitives. All ID formatting, parsing,
8
- * and regex construction flows through this module so that width, strict
9
- * mode, and prefix can be centrally configured via workspace.yaml
10
- * `software_delivery.wu_id.{width,strict,prefix}`.
11
- *
12
- * Design principles:
13
- * - Pure functions, no I/O, no config reads (caller supplies config).
14
- * - Hardcoded choices: separator '-', lowercase digits, padding char '0',
15
- * starting number 1, gap-fill policy 'never reuse'.
16
- * - `wuIdRegex` is intentionally permissive (matches both padded and unpadded
17
- * digit counts) so that consumers scanning files for legacy + canonical
18
- * IDs stay backward compatible during the transition. Strict canonical
19
- * form is enforced separately via `isCanonicalWuId`.
20
- *
21
- * @module wu-id-format
22
- */
23
-
24
- import { existsSync, readdirSync, readFileSync } from 'node:fs';
25
- import { createError, ErrorCodes } from '@lumenflow/kernel/primitives/error-handler';
26
- import { readSoftwareDeliveryConfig } from '../config/workspace-reader.js';
27
-
28
- /** Minimum allowed zero-padding width. */
29
- export const WU_ID_WIDTH_MIN = 1;
30
-
31
- /** Maximum allowed zero-padding width. */
32
- export const WU_ID_WIDTH_MAX = 6;
33
-
34
- /**
35
- * Prefix validation pattern: uppercase letter start, followed by 1-9 more
36
- * uppercase-alphanumeric characters, terminated by a dash. Matches 'WU-',
37
- * 'TASK-', 'STORY-', 'TICKET-', 'JIRA123-'. Rejects lowercase, missing dash,
38
- * single-char prefixes, and over-long prefixes.
39
- */
40
- export const WU_ID_PREFIX_PATTERN = /^[A-Z][A-Z0-9]{1,9}-$/;
41
-
42
- /** Canonical WU ID configuration. */
43
- export interface WuIdConfig {
44
- /** Zero-padding width. Default 4 (WU-0001). */
45
- width: number;
46
- /**
47
- * Strict mode. When true, non-canonical legacy IDs are flagged as errors
48
- * by wu:doctor and wu:create canonicalizes --id input. When false, legacy
49
- * IDs are tolerated as warnings for incremental migration.
50
- */
51
- strict: boolean;
52
- /** Canonical prefix including trailing dash. Default 'WU-'. */
53
- prefix: string;
54
- }
55
-
56
- /** Default WU ID configuration. */
57
- export const WU_ID_DEFAULTS: WuIdConfig = Object.freeze({
58
- width: 4,
59
- strict: true,
60
- prefix: 'WU-',
61
- });
62
-
63
- /**
64
- * Validate and resolve a partial WU ID config against the defaults.
65
- *
66
- * @throws {Error} If width is not an integer in [1, 6] or prefix does not
67
- * match {@link WU_ID_PREFIX_PATTERN}.
68
- */
69
- export function validateWuIdConfig(partial: Partial<WuIdConfig> = {}): WuIdConfig {
70
- const width = partial.width ?? WU_ID_DEFAULTS.width;
71
- const strict = partial.strict ?? WU_ID_DEFAULTS.strict;
72
- const prefix = partial.prefix ?? WU_ID_DEFAULTS.prefix;
73
-
74
- if (!Number.isInteger(width) || width < WU_ID_WIDTH_MIN || width > WU_ID_WIDTH_MAX) {
75
- throw createError(
76
- ErrorCodes.VALIDATION_ERROR,
77
- `Invalid wu_id.width: ${String(width)}. Must be an integer between ${WU_ID_WIDTH_MIN} and ${WU_ID_WIDTH_MAX}.`,
78
- );
79
- }
80
-
81
- if (typeof prefix !== 'string' || !WU_ID_PREFIX_PATTERN.test(prefix)) {
82
- throw createError(
83
- ErrorCodes.VALIDATION_ERROR,
84
- `Invalid wu_id.prefix: "${String(prefix)}". Must match ${WU_ID_PREFIX_PATTERN} (e.g., 'WU-', 'TASK-', 'STORY-').`,
85
- );
86
- }
87
-
88
- return { width, strict, prefix };
89
- }
90
-
91
- /**
92
- * Format an integer as a canonical WU ID.
93
- *
94
- * Zero-pads to the configured width. If the integer exceeds 10^width, the
95
- * result is wider than width (overflow is preserved, never truncated).
96
- *
97
- * @throws {Error} If n is not a positive integer.
98
- */
99
- export function formatWuId(n: number, config: Partial<WuIdConfig> = {}): string {
100
- if (!Number.isInteger(n) || n < 1) {
101
- throw createError(
102
- ErrorCodes.VALIDATION_ERROR,
103
- `Invalid WU number: ${String(n)}. Must be a positive integer.`,
104
- );
105
- }
106
- const { width, prefix } = validateWuIdConfig(config);
107
- return `${prefix}${String(n).padStart(width, '0')}`;
108
- }
109
-
110
- /**
111
- * Parse a WU ID (or YAML/stamp filename) into its prefix and numeric parts.
112
- *
113
- * Returns null for any input that does not match the configured prefix or
114
- * does not carry a positive integer body. Accepts both canonical padded and
115
- * legacy unpadded forms.
116
- *
117
- * Strips `.yaml` and `.done` extensions before parsing.
118
- */
119
- export function parseWuId(
120
- id: string,
121
- config: Partial<WuIdConfig> = {},
122
- ): { prefix: string; num: number } | null {
123
- if (typeof id !== 'string' || id.length === 0) {
124
- return null;
125
- }
126
- const { prefix } = validateWuIdConfig(config);
127
- const stripped = id.replace(/\.(yaml|done)$/, '');
128
- if (!stripped.startsWith(prefix)) {
129
- return null;
130
- }
131
- const body = stripped.slice(prefix.length);
132
- if (!/^\d+$/.test(body)) {
133
- return null;
134
- }
135
- const num = parseInt(body, 10);
136
- if (!Number.isFinite(num) || num < 1) {
137
- return null;
138
- }
139
- return { prefix, num };
140
- }
141
-
142
- /**
143
- * Build an anchored regex that matches WU IDs (both padded and unpadded
144
- * digit counts) for the configured prefix. Intended for file scans and
145
- * consumers that previously hardcoded `/^WU-\d+$/`.
146
- *
147
- * Strict canonical-form enforcement lives in {@link isCanonicalWuId}, not here.
148
- */
149
- export function wuIdRegex(config: Partial<WuIdConfig> = {}): RegExp {
150
- // eslint-disable-next-line security/detect-non-literal-regexp -- prefix escaped
151
- return new RegExp(`^${wuIdBodyPattern(config)}$`);
152
- }
153
-
154
- /**
155
- * Return an unanchored pattern string (for embedding in longer regexes)
156
- * that matches the WU id body — the configured prefix followed by one
157
- * or more digits. Consumers that previously hardcoded `WU-\\d+` inside
158
- * a larger regex should use this helper so prefix configuration
159
- * (`software_delivery.wu_id.prefix`) is honored.
160
- *
161
- * The pattern does NOT include anchors; callers decide whether to
162
- * anchor with `^`/`$` or embed in a path/substring match.
163
- */
164
- export function wuIdBodyPattern(config: Partial<WuIdConfig> = {}): string {
165
- const { prefix } = validateWuIdConfig(config);
166
- const escaped = prefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
167
- return `${escaped}\\d+`;
168
- }
169
-
170
- /**
171
- * Return true if the given string is a canonical WU ID for the configured
172
- * width and prefix. Canonical means:
173
- * - Prefix matches.
174
- * - Digit body is at least `width` characters long.
175
- * - The digit body is not shorter than width (no unpadded legacy).
176
- * - Overflow (body wider than width) is allowed so the sequence never truncates.
177
- */
178
- export function isCanonicalWuId(id: string, config: Partial<WuIdConfig> = {}): boolean {
179
- const { width, prefix } = validateWuIdConfig(config);
180
- if (typeof id !== 'string' || !id.startsWith(prefix)) {
181
- return false;
182
- }
183
- const body = id.slice(prefix.length);
184
- if (!/^\d+$/.test(body)) {
185
- return false;
186
- }
187
- return body.length >= width;
188
- }
189
-
190
- /**
191
- * Canonicalize a (possibly legacy) WU ID to the canonical form for the
192
- * configured width. Returns null for unparseable input or prefix mismatch.
193
- *
194
- * Already-canonical IDs are returned unchanged. Overflow IDs (wider than
195
- * width) are preserved.
196
- */
197
- export function canonicalizeWuId(id: string, config: Partial<WuIdConfig> = {}): string | null {
198
- const parsed = parseWuId(id, config);
199
- if (!parsed) {
200
- return null;
201
- }
202
- return formatWuId(parsed.num, config);
203
- }
204
-
205
- /**
206
- * Load the canonical WU id config from workspace.yaml
207
- * `software_delivery.wu_id.{width,strict,prefix}`.
208
- *
209
- * Falls back to {@link WU_ID_DEFAULTS} when the block is absent, so
210
- * existing repos without any wu_id config continue to see WU- prefixed
211
- * ids (backward compatible) with the only visible change being
212
- * zero-padding on newly-generated ids.
213
- *
214
- * @param options.projectRoot - Optional override for the project root.
215
- */
216
- export function loadWuIdConfig(options: { projectRoot?: string } = {}): WuIdConfig {
217
- const cwd = options.projectRoot ?? process.cwd();
218
- let section: Record<string, unknown>;
219
- try {
220
- section = readSoftwareDeliveryConfig(cwd);
221
- } catch {
222
- // Graceful fallback when workspace.yaml is absent/unreadable — matches
223
- // core's non-strictWorkspace behaviour.
224
- return validateWuIdConfig({});
225
- }
226
- // Accept both snake_case (canonical YAML) and camelCase (post-normalization)
227
- // spellings so this primitive stays callable whether the caller passes a raw
228
- // YAML section or a pre-normalized shape.
229
- const wuIdBlock =
230
- (section['wuId'] as Partial<WuIdConfig> | undefined) ??
231
- (section['wu_id'] as Partial<WuIdConfig> | undefined);
232
- return validateWuIdConfig(wuIdBlock ?? {});
233
- }
234
-
235
- /** Inputs for {@link scanExistingWuNumbers}. */
236
- export interface ScanExistingWuNumbersInput {
237
- /** Absolute path to the WU YAML directory. */
238
- wuDir: string;
239
- /** Absolute path to the stamps directory. */
240
- stampsDir: string;
241
- /** Absolute path to `wu-events.jsonl` (may or may not exist). */
242
- eventsPath: string;
243
- }
244
-
245
- /**
246
- * Scan every existing WU id integer across the yaml directory, stamps
247
- * directory, and event log. Used by wu:create for integer-level
248
- * collision detection so `WU-14` and `WU-0014` can never coexist.
249
- *
250
- * Results are deduplicated across sources. Entries whose prefix does
251
- * not match the configured prefix are ignored. Extension suffixes
252
- * (`.yaml`, `.done`) are stripped before parsing.
253
- */
254
- export function scanExistingWuNumbers(
255
- input: ScanExistingWuNumbersInput,
256
- config: Partial<WuIdConfig> = {},
257
- ): Set<number> {
258
- const result = new Set<number>();
259
-
260
- const addFromEntries = (entries: readonly string[]): void => {
261
- for (const entry of entries) {
262
- const parsed = parseWuId(entry, config);
263
- if (parsed) {
264
- result.add(parsed.num);
265
- }
266
- }
267
- };
268
-
269
- if (existsSync(input.wuDir)) {
270
- addFromEntries(readdirSync(input.wuDir));
271
- }
272
- if (existsSync(input.stampsDir)) {
273
- addFromEntries(readdirSync(input.stampsDir));
274
- }
275
- if (existsSync(input.eventsPath)) {
276
- try {
277
- const content = readFileSync(input.eventsPath, { encoding: 'utf-8' });
278
- for (const line of content.split('\n')) {
279
- const trimmed = line.trim();
280
- if (trimmed.length === 0) continue;
281
- try {
282
- const event = JSON.parse(trimmed) as {
283
- wuId?: string;
284
- from?: string;
285
- to?: string;
286
- };
287
- for (const candidate of [event.wuId, event.from, event.to]) {
288
- if (typeof candidate === 'string') {
289
- const parsed = parseWuId(candidate, config);
290
- if (parsed) {
291
- result.add(parsed.num);
292
- }
293
- }
294
- }
295
- } catch {
296
- // Ignore malformed lines; the events file is allowed to have gaps.
297
- }
298
- }
299
- } catch {
300
- // Read errors fall through; caller treats this as "no known ids".
301
- }
302
- }
303
-
304
- return result;
305
- }
306
-
307
- /**
308
- * Returns true when `num` is already present in the given set.
309
- * Thin wrapper for call-site readability at the wu:create integration point.
310
- */
311
- export function integerCollides(existing: ReadonlySet<number>, num: number): boolean {
312
- return existing.has(num);
313
- }
314
-
315
- /**
316
- * Returns true when the given WU number is within the width-exhaustion
317
- * warning band (>= 90% of 10^width) but still below the width ceiling.
318
- *
319
- * Numbers that already exceed the width capacity return false so the
320
- * warning only fires once, not on every subsequent overflow id.
321
- */
322
- export function isWidthExhaustionWarning(num: number, config: Partial<WuIdConfig> = {}): boolean {
323
- const { width } = validateWuIdConfig(config);
324
- const capacity = Math.pow(10, width);
325
- const threshold = capacity * 0.9;
326
- return num >= threshold && num < capacity;
327
- }
@@ -1,384 +0,0 @@
1
- // Copyright (c) 2026 Hellmai Ltd
2
- // SPDX-License-Identifier: LicenseRef-LumenFlow-Proprietary
3
-
4
- /**
5
- * Path and File System Constants
6
- *
7
- * WU-1549: Extracted from wu-constants.ts for bounded-concern modularity.
8
- * Contains LumenFlow directory paths, file extensions, config files, filesystem
9
- * constants, build artifacts, and path manipulation helpers.
10
- *
11
- * @module wu-paths-constants
12
- */
13
-
14
- import path from 'node:path';
15
- import { tmpdir } from 'node:os';
16
- import { GIT_DIRECTORY_NAME, WORKSPACE_CONFIG_FILE_NAME } from './config-contract.js';
17
- import { DEFAULT_DOCS_LAYOUT, DOCS_LAYOUT_PRESETS } from './docs-layout-presets.js';
18
-
19
- const DEFAULT_DOCS_PATHS = DOCS_LAYOUT_PRESETS[DEFAULT_DOCS_LAYOUT];
20
-
21
- /**
22
- * WU-1548: Shared Node.js filesystem error interface.
23
- *
24
- * Consolidates duplicated NodeFsError definitions that existed across
25
- * memory-store.ts, mem-triage-core.ts, mem-signal-core.ts, mem-ready-core.ts,
26
- * signal-cleanup-core.ts, and wu-events-cleanup.ts.
27
- *
28
- * Use this interface when catching fs errors and checking the `code` property
29
- * (e.g., 'ENOENT', 'EACCES', 'EPERM').
30
- */
31
- export interface NodeFsError extends Error {
32
- code?: string;
33
- }
34
-
35
- const UTF8_ENCODING = 'utf8' as const;
36
-
37
- /**
38
- * File system constants
39
- *
40
- * WU-923: Centralized to eliminate hardcoded strings
41
- */
42
- export const FILE_SYSTEM = {
43
- /** Standard file encoding */
44
- ENCODING: UTF8_ENCODING,
45
-
46
- /** UTF-8 encoding (alias for compatibility) */
47
- UTF8: UTF8_ENCODING,
48
- };
49
-
50
- /**
51
- * Configuration file paths
52
- *
53
- * WU-923: Centralized config file names
54
- */
55
- export const CONFIG_FILES = {
56
- /** Canonical workspace config */
57
- WORKSPACE_CONFIG: WORKSPACE_CONFIG_FILE_NAME,
58
-
59
- /** Lane inference taxonomy */
60
- LANE_INFERENCE: '.lumenflow.lane-inference.yaml',
61
- };
62
-
63
- /**
64
- * Directory paths within the monorepo
65
- *
66
- * Centralized directory path strings.
67
- */
68
- export const DIRECTORIES = {
69
- APPS_WEB: 'apps/web/',
70
- WORKTREES: 'worktrees/',
71
- AI: 'ai/',
72
- CLAUDE: '.claude/',
73
- CLAUDE_HOOKS: '.claude/hooks/',
74
- DOCS: 'docs/',
75
- PACKAGES: 'packages/',
76
- TOOLS: 'tools/',
77
- MEMORY_BANK: 'memory-bank/',
78
- WU_DIR: `${DEFAULT_DOCS_PATHS.tasks}/wu`,
79
- INITIATIVES_DIR: `${DEFAULT_DOCS_PATHS.tasks}/initiatives`,
80
- // WU-1814: Paths for active WU detection
81
- BACKLOG_PATH: `${DEFAULT_DOCS_PATHS.tasks}/backlog.md`,
82
- STATUS_PATH: `${DEFAULT_DOCS_PATHS.tasks}/status.md`,
83
- };
84
-
85
- /**
86
- * Shared agent/client surface paths.
87
- *
88
- * Keeps vendor overlay and shared projection roots centralized so runtime code
89
- * does not scatter hardcoded path literals through CLI/core packages.
90
- */
91
- export const AGENT_SURFACES = {
92
- /** Claude-projected skills directory */
93
- CLAUDE_SKILLS_DIR: '.claude/skills',
94
-
95
- /** Claude agent overlay directory */
96
- CLAUDE_AGENTS_DIR: '.claude/agents',
97
-
98
- /** Shared cross-vendor projected skills directory */
99
- SHARED_SKILLS_DIR: '.agents/skills',
100
-
101
- /** Codex agent overlay directory */
102
- CODEX_AGENTS_DIR: '.codex/agents',
103
-
104
- /** Gemini projected skills directory */
105
- GEMINI_SKILLS_DIR: '.gemini/skills',
106
-
107
- /** Gemini agent overlay directory */
108
- GEMINI_AGENTS_DIR: '.gemini/agents',
109
- };
110
-
111
- /**
112
- * Build artifact cleanup globs
113
- *
114
- * Centralized glob patterns for worktree artifact cleanup.
115
- */
116
- export const BUILD_ARTIFACT_GLOBS = {
117
- /** Common dist directories inside worktrees */
118
- DIST_DIRS: [
119
- 'packages/*/dist',
120
- 'packages/**/dist',
121
- 'apps/*/dist',
122
- 'apps/**/dist',
123
- 'tools/*/dist',
124
- 'tools/**/dist',
125
- ],
126
-
127
- /** TypeScript build info files */
128
- TSBUILDINFO_FILES: ['**/*.tsbuildinfo'],
129
- };
130
-
131
- /**
132
- * Build artifact cleanup ignore patterns
133
- *
134
- * Centralized ignore globs for artifact cleanup.
135
- */
136
- const GIT_ARTIFACT_IGNORE_GLOB = `**/${GIT_DIRECTORY_NAME}/**`;
137
- export const BUILD_ARTIFACT_IGNORES = [
138
- '**/node_modules/**',
139
- GIT_ARTIFACT_IGNORE_GLOB,
140
- '**/.turbo/**',
141
- ];
142
-
143
- /**
144
- * Script file paths
145
- *
146
- * Centralized paths to validation scripts.
147
- */
148
- export const SCRIPT_PATHS = {
149
- /** Prompt registry validation */
150
- VALIDATE_PROMPT_REGISTRY: 'tools/validate-prompt-registry.js',
151
- };
152
-
153
- /**
154
- * File extensions
155
- *
156
- * Centralized file extension strings to avoid magic strings.
157
- */
158
- export const FILE_EXTENSIONS = {
159
- /** Newline-delimited JSON format */
160
- NDJSON: '.ndjson',
161
-
162
- /** Markdown format */
163
- MARKDOWN: '.md',
164
-
165
- /** YAML format */
166
- YAML: '.yaml',
167
-
168
- /** YAML alternate extension */
169
- YML: '.yml',
170
-
171
- /** JSON format */
172
- JSON: '.json',
173
-
174
- /** Log format */
175
- LOG: '.log',
176
-
177
- /** Stamp files (completion markers) */
178
- STAMP: '.done',
179
- };
180
-
181
- /**
182
- * Path-related constants
183
- *
184
- * WU-1062: Centralized path literals for lumenflow-home and spec-branch operations.
185
- */
186
- export const PATH_LITERALS = {
187
- /** Tilde prefix for home directory expansion (e.g., ~/path) */
188
- TILDE_PREFIX: '~/',
189
-
190
- /** Tilde character for home directory */
191
- TILDE: '~',
192
-
193
- /** Plan file suffix for WU plans */
194
- PLAN_FILE_SUFFIX: '-plan.md',
195
-
196
- /** Trailing slash regex pattern */
197
- TRAILING_SLASH_REGEX: /\/+$/,
198
-
199
- /** .lumenflow path prefix for internal path detection (WU-1430) */
200
- LUMENFLOW_PREFIX: '.lumenflow/',
201
-
202
- /** Current directory prefix for repo-internal paths (WU-1430) */
203
- CURRENT_DIR_PREFIX: './',
204
- };
205
-
206
- /**
207
- * Slice lengths for path operations
208
- *
209
- * WU-1062: Magic numbers extracted for path manipulation.
210
- */
211
- export const PATH_SLICE_LENGTHS = {
212
- /** Length of '~/' prefix for tilde expansion */
213
- TILDE_PREFIX_LENGTH: 2,
214
-
215
- /** Length of '/' for leading slash removal */
216
- LEADING_SLASH_LENGTH: 1,
217
- };
218
-
219
- /**
220
- * WU-1174: Lock directory name constant
221
- *
222
- * Defined separately so it can be used both in LUMENFLOW_PATHS.LOCK_DIR
223
- * and for test isolation in cleanup-lock.ts/merge-lock.ts.
224
- */
225
- export const LOCK_DIR_NAME = '.lumenflow-locks';
226
-
227
- /**
228
- * LumenFlow directory paths
229
- *
230
- * Centralized paths for .lumenflow directory structure to eliminate hardcoded strings.
231
- * Used by telemetry, agent-session, agent-incidents, memory, and commands-logger modules.
232
- */
233
- export const LUMENFLOW_PATHS = {
234
- /** Base directory for all LumenFlow runtime data */
235
- BASE: '.lumenflow',
236
-
237
- /** WU state store directory */
238
- STATE_DIR: '.lumenflow/state',
239
-
240
- /** Stamp directory (WU completion markers) */
241
- STAMPS_DIR: '.lumenflow/stamps',
242
-
243
- /** Archive directory for old WU events (WU-1430) */
244
- ARCHIVE_DIR: '.lumenflow/archive',
245
-
246
- /** Merge lock file (runtime coordination, WU-1747) */
247
- MERGE_LOCK: '.lumenflow/merge.lock',
248
-
249
- /** Base telemetry directory */
250
- TELEMETRY: '.lumenflow/telemetry',
251
-
252
- /** Flow log file (WU flow events) */
253
- FLOW_LOG: '.lumenflow/flow.log',
254
-
255
- /** Agent sessions directory */
256
- SESSIONS: '.lumenflow/sessions',
257
-
258
- /** Agent incidents directory */
259
- INCIDENTS: '.lumenflow/incidents',
260
-
261
- /** Git commands log file */
262
- COMMANDS_LOG: '.lumenflow/commands.log',
263
-
264
- /** Memory layer directory */
265
- MEMORY_DIR: '.lumenflow/memory',
266
-
267
- /** Memory layer JSONL file */
268
- MEMORY_JSONL: '.lumenflow/memory/memory.jsonl',
269
-
270
- /** WU-1539: Memory signals JSONL file */
271
- MEMORY_SIGNALS: '.lumenflow/memory/signals.jsonl',
272
-
273
- /** Audit log for tool calls */
274
- AUDIT_LOG: '.lumenflow/telemetry/tools.ndjson',
275
-
276
- /** Feedback drafts directory */
277
- FEEDBACK_DRAFTS: '.lumenflow/feedback-drafts',
278
-
279
- /** Feedback index file */
280
- FEEDBACK_INDEX: '.lumenflow/feedback-index.ndjson',
281
-
282
- /** Current session file */
283
- SESSION_CURRENT: '.lumenflow/sessions/current.json',
284
-
285
- /** WU events log */
286
- WU_EVENTS: '.lumenflow/state/wu-events.jsonl',
287
-
288
- /** Lock files directory (lane locks - persisted) */
289
- LOCKS_DIR: '.lumenflow/locks',
290
-
291
- /** Force bypass audit log */
292
- FORCE_BYPASSES: '.lumenflow/force-bypasses.log',
293
-
294
- /** WU-1539: Skip-gates audit log */
295
- SKIP_GATES_AUDIT: '.lumenflow/skip-gates-audit.log',
296
-
297
- /** WU-1539: Skip-COS-gates audit log */
298
- SKIP_COS_GATES_AUDIT: '.lumenflow/skip-cos-gates-audit.log',
299
-
300
- /** Test baseline file for ratchet pattern (WU-1430) */
301
- TEST_BASELINE: '.lumenflow/test-baseline.json',
302
-
303
- /** Templates directory (WU-1430) */
304
- TEMPLATES_DIR: '.lumenflow/templates',
305
-
306
- /** Spawn prompt templates (WU-1674) */
307
- SPAWN_PROMPT_DIR: '.lumenflow/templates/spawn-prompt',
308
-
309
- /** Template manifest file (WU-1430) */
310
- TEMPLATE_MANIFEST: '.lumenflow/templates/manifest.yaml',
311
-
312
- /** Skills directory for agent skills (WU-1430) */
313
- SKILLS_DIR: '.lumenflow/skills',
314
-
315
- /** Agents directory for agent definitions (WU-1430) */
316
- AGENTS_DIR: '.lumenflow/agents',
317
-
318
- /** Methodology log for delegation telemetry (WU-1430) */
319
- METHODOLOGY_LOG: '.lumenflow/telemetry/methodology.ndjson',
320
-
321
- /** Prompt metrics cache (WU-1430) */
322
- PROMPT_METRICS: '.lumenflow/telemetry/prompt-metrics.json',
323
-
324
- /** Prompt lint results (WU-1430) */
325
- PROMPT_LINT: '.lumenflow/telemetry/prompt-lint.ndjson',
326
-
327
- /** Recovery markers directory (WU-1430) */
328
- RECOVERY_DIR: '.lumenflow/recovery',
329
-
330
- /** Checkpoints directory (WU-1430) */
331
- CHECKPOINTS_DIR: '.lumenflow/checkpoints',
332
-
333
- /** WU-1471: Hook counters directory for auto-checkpoint interval tracking */
334
- HOOK_COUNTERS_DIR: '.lumenflow/state/hook-counters',
335
-
336
- /** Cache directory under user home (WU-1430) */
337
- HOME_CACHE: 'cache',
338
-
339
- /**
340
- * WU-1174: Runtime lock directory for merge/cleanup locks
341
- *
342
- * These locks are transient and should NOT be created in the main checkout
343
- * because wu:done runs from main. Using os.tmpdir() ensures:
344
- * 1. Locks don't pollute the git working tree
345
- * 2. Locks work across processes on the same machine
346
- * 3. No "Working tree is not clean" errors if process crashes
347
- *
348
- * Note: Lane locks still use LOCKS_DIR (.lumenflow/locks) because they need
349
- * to persist across sessions and be visible to other agents.
350
- */
351
- LOCK_DIR: path.join(tmpdir(), LOCK_DIR_NAME),
352
- };
353
-
354
- /**
355
- * File tool constants (WU-1403)
356
- *
357
- * Centralized strings for file:read, file:write, file:edit tools.
358
- * Prevents duplicate string literals and hardcoded magic values.
359
- */
360
- export const FILE_TOOLS = {
361
- /** Tool name prefixes */
362
- NAMES: {
363
- READ: 'file:read',
364
- WRITE: 'file:write',
365
- EDIT: 'file:edit',
366
- DELETE: 'file:delete',
367
- },
368
-
369
- /** Tool domain */
370
- DOMAIN: 'file',
371
-
372
- /** Permission levels */
373
- PERMISSIONS: {
374
- READ: 'read',
375
- WRITE: 'write',
376
- },
377
-
378
- /** Worktree instruction templates (WU-1403: provides reusable instruction strings) */
379
- WORKTREE_INSTRUCTIONS: {
380
- CLAIM_COMMAND: 'pnpm wu:claim --id <wu-id> --lane "<lane>"',
381
- CD_COMMAND: 'cd worktrees/<lane>-<wu-id>/',
382
- DOC_REFERENCE: 'CLAUDE.md §2 (Worktree Discipline)',
383
- },
384
- };