@lumenflow/core 1.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 (263) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +119 -0
  3. package/dist/active-wu-detector.d.ts +33 -0
  4. package/dist/active-wu-detector.js +106 -0
  5. package/dist/adapters/filesystem-metrics.adapter.d.ts +108 -0
  6. package/dist/adapters/filesystem-metrics.adapter.js +519 -0
  7. package/dist/adapters/terminal-renderer.adapter.d.ts +106 -0
  8. package/dist/adapters/terminal-renderer.adapter.js +337 -0
  9. package/dist/arg-parser.d.ts +63 -0
  10. package/dist/arg-parser.js +560 -0
  11. package/dist/backlog-editor.d.ts +98 -0
  12. package/dist/backlog-editor.js +179 -0
  13. package/dist/backlog-generator.d.ts +111 -0
  14. package/dist/backlog-generator.js +381 -0
  15. package/dist/backlog-parser.d.ts +45 -0
  16. package/dist/backlog-parser.js +102 -0
  17. package/dist/backlog-sync-validator.d.ts +78 -0
  18. package/dist/backlog-sync-validator.js +294 -0
  19. package/dist/branch-drift.d.ts +34 -0
  20. package/dist/branch-drift.js +51 -0
  21. package/dist/cleanup-install-config.d.ts +33 -0
  22. package/dist/cleanup-install-config.js +37 -0
  23. package/dist/cleanup-lock.d.ts +139 -0
  24. package/dist/cleanup-lock.js +313 -0
  25. package/dist/code-path-validator.d.ts +146 -0
  26. package/dist/code-path-validator.js +537 -0
  27. package/dist/code-paths-overlap.d.ts +55 -0
  28. package/dist/code-paths-overlap.js +245 -0
  29. package/dist/commands-logger.d.ts +77 -0
  30. package/dist/commands-logger.js +254 -0
  31. package/dist/commit-message-utils.d.ts +25 -0
  32. package/dist/commit-message-utils.js +41 -0
  33. package/dist/compliance-parser.d.ts +150 -0
  34. package/dist/compliance-parser.js +507 -0
  35. package/dist/constants/backlog-patterns.d.ts +20 -0
  36. package/dist/constants/backlog-patterns.js +23 -0
  37. package/dist/constants/dora-constants.d.ts +49 -0
  38. package/dist/constants/dora-constants.js +53 -0
  39. package/dist/constants/gate-constants.d.ts +15 -0
  40. package/dist/constants/gate-constants.js +15 -0
  41. package/dist/constants/linter-constants.d.ts +16 -0
  42. package/dist/constants/linter-constants.js +16 -0
  43. package/dist/constants/tokenizer-constants.d.ts +15 -0
  44. package/dist/constants/tokenizer-constants.js +15 -0
  45. package/dist/core/scope-checker.d.ts +97 -0
  46. package/dist/core/scope-checker.js +163 -0
  47. package/dist/core/tool-runner.d.ts +161 -0
  48. package/dist/core/tool-runner.js +393 -0
  49. package/dist/core/tool.constants.d.ts +105 -0
  50. package/dist/core/tool.constants.js +101 -0
  51. package/dist/core/tool.schemas.d.ts +226 -0
  52. package/dist/core/tool.schemas.js +226 -0
  53. package/dist/core/worktree-guard.d.ts +130 -0
  54. package/dist/core/worktree-guard.js +242 -0
  55. package/dist/coverage-gate.d.ts +108 -0
  56. package/dist/coverage-gate.js +196 -0
  57. package/dist/date-utils.d.ts +75 -0
  58. package/dist/date-utils.js +140 -0
  59. package/dist/dependency-graph.d.ts +142 -0
  60. package/dist/dependency-graph.js +550 -0
  61. package/dist/dependency-guard.d.ts +54 -0
  62. package/dist/dependency-guard.js +142 -0
  63. package/dist/dependency-validator.d.ts +105 -0
  64. package/dist/dependency-validator.js +154 -0
  65. package/dist/docs-path-validator.d.ts +36 -0
  66. package/dist/docs-path-validator.js +95 -0
  67. package/dist/domain/orchestration.constants.d.ts +99 -0
  68. package/dist/domain/orchestration.constants.js +97 -0
  69. package/dist/domain/orchestration.schemas.d.ts +280 -0
  70. package/dist/domain/orchestration.schemas.js +211 -0
  71. package/dist/domain/orchestration.types.d.ts +133 -0
  72. package/dist/domain/orchestration.types.js +12 -0
  73. package/dist/error-handler.d.ts +116 -0
  74. package/dist/error-handler.js +136 -0
  75. package/dist/file-classifiers.d.ts +62 -0
  76. package/dist/file-classifiers.js +108 -0
  77. package/dist/gates-agent-mode.d.ts +81 -0
  78. package/dist/gates-agent-mode.js +94 -0
  79. package/dist/generate-traceability.d.ts +107 -0
  80. package/dist/generate-traceability.js +411 -0
  81. package/dist/git-adapter.d.ts +395 -0
  82. package/dist/git-adapter.js +649 -0
  83. package/dist/git-staged-validator.d.ts +32 -0
  84. package/dist/git-staged-validator.js +48 -0
  85. package/dist/hardcoded-strings.d.ts +61 -0
  86. package/dist/hardcoded-strings.js +270 -0
  87. package/dist/incremental-lint.d.ts +78 -0
  88. package/dist/incremental-lint.js +129 -0
  89. package/dist/incremental-test.d.ts +39 -0
  90. package/dist/incremental-test.js +61 -0
  91. package/dist/index.d.ts +42 -0
  92. package/dist/index.js +61 -0
  93. package/dist/invariants/check-automated-tests.d.ts +50 -0
  94. package/dist/invariants/check-automated-tests.js +166 -0
  95. package/dist/invariants-runner.d.ts +103 -0
  96. package/dist/invariants-runner.js +527 -0
  97. package/dist/lane-checker.d.ts +50 -0
  98. package/dist/lane-checker.js +319 -0
  99. package/dist/lane-inference.d.ts +39 -0
  100. package/dist/lane-inference.js +195 -0
  101. package/dist/lane-lock.d.ts +211 -0
  102. package/dist/lane-lock.js +474 -0
  103. package/dist/lane-validator.d.ts +48 -0
  104. package/dist/lane-validator.js +114 -0
  105. package/dist/logs-lib.d.ts +104 -0
  106. package/dist/logs-lib.js +207 -0
  107. package/dist/lumenflow-config-schema.d.ts +272 -0
  108. package/dist/lumenflow-config-schema.js +207 -0
  109. package/dist/lumenflow-config.d.ts +95 -0
  110. package/dist/lumenflow-config.js +236 -0
  111. package/dist/manual-test-validator.d.ts +80 -0
  112. package/dist/manual-test-validator.js +200 -0
  113. package/dist/merge-lock.d.ts +115 -0
  114. package/dist/merge-lock.js +251 -0
  115. package/dist/micro-worktree.d.ts +159 -0
  116. package/dist/micro-worktree.js +427 -0
  117. package/dist/migration-deployer.d.ts +69 -0
  118. package/dist/migration-deployer.js +151 -0
  119. package/dist/orchestration-advisory-loader.d.ts +28 -0
  120. package/dist/orchestration-advisory-loader.js +87 -0
  121. package/dist/orchestration-advisory.d.ts +58 -0
  122. package/dist/orchestration-advisory.js +94 -0
  123. package/dist/orchestration-di.d.ts +48 -0
  124. package/dist/orchestration-di.js +57 -0
  125. package/dist/orchestration-rules.d.ts +57 -0
  126. package/dist/orchestration-rules.js +201 -0
  127. package/dist/orphan-detector.d.ts +131 -0
  128. package/dist/orphan-detector.js +226 -0
  129. package/dist/path-classifiers.d.ts +57 -0
  130. package/dist/path-classifiers.js +93 -0
  131. package/dist/piped-command-detector.d.ts +34 -0
  132. package/dist/piped-command-detector.js +64 -0
  133. package/dist/ports/dashboard-renderer.port.d.ts +112 -0
  134. package/dist/ports/dashboard-renderer.port.js +25 -0
  135. package/dist/ports/metrics-collector.port.d.ts +132 -0
  136. package/dist/ports/metrics-collector.port.js +26 -0
  137. package/dist/process-detector.d.ts +84 -0
  138. package/dist/process-detector.js +172 -0
  139. package/dist/prompt-linter.d.ts +72 -0
  140. package/dist/prompt-linter.js +312 -0
  141. package/dist/prompt-monitor.d.ts +15 -0
  142. package/dist/prompt-monitor.js +205 -0
  143. package/dist/rebase-artifact-cleanup.d.ts +145 -0
  144. package/dist/rebase-artifact-cleanup.js +433 -0
  145. package/dist/retry-strategy.d.ts +189 -0
  146. package/dist/retry-strategy.js +283 -0
  147. package/dist/risk-detector.d.ts +108 -0
  148. package/dist/risk-detector.js +252 -0
  149. package/dist/rollback-utils.d.ts +76 -0
  150. package/dist/rollback-utils.js +104 -0
  151. package/dist/section-headings.d.ts +43 -0
  152. package/dist/section-headings.js +49 -0
  153. package/dist/spawn-escalation.d.ts +90 -0
  154. package/dist/spawn-escalation.js +253 -0
  155. package/dist/spawn-monitor.d.ts +229 -0
  156. package/dist/spawn-monitor.js +672 -0
  157. package/dist/spawn-recovery.d.ts +82 -0
  158. package/dist/spawn-recovery.js +298 -0
  159. package/dist/spawn-registry-schema.d.ts +98 -0
  160. package/dist/spawn-registry-schema.js +108 -0
  161. package/dist/spawn-registry-store.d.ts +146 -0
  162. package/dist/spawn-registry-store.js +273 -0
  163. package/dist/spawn-tree.d.ts +121 -0
  164. package/dist/spawn-tree.js +285 -0
  165. package/dist/stamp-status-validator.d.ts +84 -0
  166. package/dist/stamp-status-validator.js +134 -0
  167. package/dist/stamp-utils.d.ts +100 -0
  168. package/dist/stamp-utils.js +229 -0
  169. package/dist/state-machine.d.ts +26 -0
  170. package/dist/state-machine.js +83 -0
  171. package/dist/system-map-validator.d.ts +80 -0
  172. package/dist/system-map-validator.js +272 -0
  173. package/dist/telemetry.d.ts +80 -0
  174. package/dist/telemetry.js +213 -0
  175. package/dist/token-counter.d.ts +51 -0
  176. package/dist/token-counter.js +145 -0
  177. package/dist/usecases/get-dashboard-data.usecase.d.ts +52 -0
  178. package/dist/usecases/get-dashboard-data.usecase.js +61 -0
  179. package/dist/usecases/get-suggestions.usecase.d.ts +100 -0
  180. package/dist/usecases/get-suggestions.usecase.js +153 -0
  181. package/dist/user-normalizer.d.ts +41 -0
  182. package/dist/user-normalizer.js +141 -0
  183. package/dist/validators/phi-constants.d.ts +97 -0
  184. package/dist/validators/phi-constants.js +152 -0
  185. package/dist/validators/phi-scanner.d.ts +58 -0
  186. package/dist/validators/phi-scanner.js +215 -0
  187. package/dist/worktree-ownership.d.ts +50 -0
  188. package/dist/worktree-ownership.js +74 -0
  189. package/dist/worktree-scanner.d.ts +103 -0
  190. package/dist/worktree-scanner.js +168 -0
  191. package/dist/worktree-symlink.d.ts +99 -0
  192. package/dist/worktree-symlink.js +359 -0
  193. package/dist/wu-backlog-updater.d.ts +17 -0
  194. package/dist/wu-backlog-updater.js +37 -0
  195. package/dist/wu-checkpoint.d.ts +124 -0
  196. package/dist/wu-checkpoint.js +233 -0
  197. package/dist/wu-claim-helpers.d.ts +26 -0
  198. package/dist/wu-claim-helpers.js +63 -0
  199. package/dist/wu-claim-resume.d.ts +106 -0
  200. package/dist/wu-claim-resume.js +276 -0
  201. package/dist/wu-consistency-checker.d.ts +95 -0
  202. package/dist/wu-consistency-checker.js +567 -0
  203. package/dist/wu-constants.d.ts +1275 -0
  204. package/dist/wu-constants.js +1382 -0
  205. package/dist/wu-create-validators.d.ts +42 -0
  206. package/dist/wu-create-validators.js +93 -0
  207. package/dist/wu-done-branch-only.d.ts +63 -0
  208. package/dist/wu-done-branch-only.js +191 -0
  209. package/dist/wu-done-messages.d.ts +119 -0
  210. package/dist/wu-done-messages.js +185 -0
  211. package/dist/wu-done-pr.d.ts +72 -0
  212. package/dist/wu-done-pr.js +174 -0
  213. package/dist/wu-done-retry-helpers.d.ts +85 -0
  214. package/dist/wu-done-retry-helpers.js +172 -0
  215. package/dist/wu-done-ui.d.ts +37 -0
  216. package/dist/wu-done-ui.js +69 -0
  217. package/dist/wu-done-validators.d.ts +411 -0
  218. package/dist/wu-done-validators.js +1229 -0
  219. package/dist/wu-done-worktree.d.ts +182 -0
  220. package/dist/wu-done-worktree.js +1097 -0
  221. package/dist/wu-helpers.d.ts +128 -0
  222. package/dist/wu-helpers.js +248 -0
  223. package/dist/wu-lint.d.ts +70 -0
  224. package/dist/wu-lint.js +234 -0
  225. package/dist/wu-paths.d.ts +171 -0
  226. package/dist/wu-paths.js +178 -0
  227. package/dist/wu-preflight-validators.d.ts +86 -0
  228. package/dist/wu-preflight-validators.js +251 -0
  229. package/dist/wu-recovery.d.ts +138 -0
  230. package/dist/wu-recovery.js +341 -0
  231. package/dist/wu-repair-core.d.ts +131 -0
  232. package/dist/wu-repair-core.js +669 -0
  233. package/dist/wu-schema-normalization.d.ts +17 -0
  234. package/dist/wu-schema-normalization.js +82 -0
  235. package/dist/wu-schema.d.ts +793 -0
  236. package/dist/wu-schema.js +881 -0
  237. package/dist/wu-spawn-helpers.d.ts +121 -0
  238. package/dist/wu-spawn-helpers.js +271 -0
  239. package/dist/wu-spawn.d.ts +158 -0
  240. package/dist/wu-spawn.js +1306 -0
  241. package/dist/wu-state-schema.d.ts +213 -0
  242. package/dist/wu-state-schema.js +156 -0
  243. package/dist/wu-state-store.d.ts +264 -0
  244. package/dist/wu-state-store.js +691 -0
  245. package/dist/wu-status-transition.d.ts +63 -0
  246. package/dist/wu-status-transition.js +382 -0
  247. package/dist/wu-status-updater.d.ts +25 -0
  248. package/dist/wu-status-updater.js +116 -0
  249. package/dist/wu-transaction-collectors.d.ts +116 -0
  250. package/dist/wu-transaction-collectors.js +272 -0
  251. package/dist/wu-transaction.d.ts +170 -0
  252. package/dist/wu-transaction.js +273 -0
  253. package/dist/wu-validation-constants.d.ts +60 -0
  254. package/dist/wu-validation-constants.js +66 -0
  255. package/dist/wu-validation.d.ts +118 -0
  256. package/dist/wu-validation.js +243 -0
  257. package/dist/wu-validator.d.ts +62 -0
  258. package/dist/wu-validator.js +325 -0
  259. package/dist/wu-yaml-fixer.d.ts +97 -0
  260. package/dist/wu-yaml-fixer.js +264 -0
  261. package/dist/wu-yaml.d.ts +86 -0
  262. package/dist/wu-yaml.js +222 -0
  263. package/package.json +114 -0
@@ -0,0 +1,171 @@
1
+ /**
2
+ * WU Paths - Centralized path management for Work Units
3
+ *
4
+ * All paths are configurable via .lumenflow.config.yaml
5
+ *
6
+ * @module wu-paths
7
+ */
8
+ /**
9
+ * Resolve repo root from an absolute file path by traversing up N directory levels.
10
+ *
11
+ * @param absolutePath - Absolute path to a file within the repo
12
+ * @param depth - Number of directory levels to traverse up
13
+ * @returns Absolute path to repo root
14
+ */
15
+ export declare function resolveRepoRoot(absolutePath: string, depth: number): string;
16
+ /**
17
+ * Get the state store directory path from backlog.md path.
18
+ *
19
+ * @param backlogPath - Absolute path to backlog.md
20
+ * @returns Absolute path to state store directory
21
+ */
22
+ export declare function getStateStoreDirFromBacklog(backlogPath: string): string;
23
+ /**
24
+ * Create WU paths object with configurable base paths
25
+ *
26
+ * @param options - Options for path generation
27
+ * @param options.projectRoot - Override project root
28
+ * @returns WU paths object
29
+ */
30
+ export declare function createWuPaths(options?: {
31
+ projectRoot?: string;
32
+ }): {
33
+ /**
34
+ * Get path to WU YAML file
35
+ * @param id - WU ID (e.g., 'WU-123')
36
+ * @returns Path to WU YAML file
37
+ */
38
+ WU: (id: string) => string;
39
+ /**
40
+ * Get path to WU directory
41
+ * @returns Path to WU directory
42
+ */
43
+ WU_DIR: () => string;
44
+ /**
45
+ * Get path to status.md
46
+ * @returns Path to status.md
47
+ */
48
+ STATUS: () => string;
49
+ /**
50
+ * Get path to backlog.md
51
+ * @returns Path to backlog.md
52
+ */
53
+ BACKLOG: () => string;
54
+ /**
55
+ * Get path to stamps directory
56
+ * @returns Path to stamps directory
57
+ */
58
+ STAMPS_DIR: () => string;
59
+ /**
60
+ * Get path to WU done stamp file
61
+ * @param id - WU ID (e.g., 'WU-123')
62
+ * @returns Path to stamp file
63
+ */
64
+ STAMP: (id: string) => string;
65
+ /**
66
+ * Get path to state directory
67
+ * @returns Path to state directory
68
+ */
69
+ STATE_DIR: () => string;
70
+ /**
71
+ * Get path to initiatives directory
72
+ * @returns Path to initiatives directory
73
+ */
74
+ INITIATIVES_DIR: () => string;
75
+ /**
76
+ * Get path to worktrees directory
77
+ * @returns Path to worktrees directory
78
+ */
79
+ WORKTREES_DIR: () => string;
80
+ };
81
+ /**
82
+ * Default WU paths using default config
83
+ * For backwards compatibility with existing code
84
+ */
85
+ export declare const WU_PATHS: {
86
+ /**
87
+ * Get path to WU YAML file
88
+ * @param id - WU ID (e.g., 'WU-123')
89
+ * @returns Path to WU YAML file
90
+ */
91
+ WU: (id: string) => string;
92
+ /**
93
+ * Get path to WU directory
94
+ * @returns Path to WU directory
95
+ */
96
+ WU_DIR: () => string;
97
+ /**
98
+ * Get path to status.md
99
+ * @returns Path to status.md
100
+ */
101
+ STATUS: () => string;
102
+ /**
103
+ * Get path to backlog.md
104
+ * @returns Path to backlog.md
105
+ */
106
+ BACKLOG: () => string;
107
+ /**
108
+ * Get path to stamps directory
109
+ * @returns Path to stamps directory
110
+ */
111
+ STAMPS_DIR: () => string;
112
+ /**
113
+ * Get path to WU done stamp file
114
+ * @param id - WU ID (e.g., 'WU-123')
115
+ * @returns Path to stamp file
116
+ */
117
+ STAMP: (id: string) => string;
118
+ /**
119
+ * Get path to state directory
120
+ * @returns Path to state directory
121
+ */
122
+ STATE_DIR: () => string;
123
+ /**
124
+ * Get path to initiatives directory
125
+ * @returns Path to initiatives directory
126
+ */
127
+ INITIATIVES_DIR: () => string;
128
+ /**
129
+ * Get path to worktrees directory
130
+ * @returns Path to worktrees directory
131
+ */
132
+ WORKTREES_DIR: () => string;
133
+ };
134
+ /**
135
+ * Generate default worktree path from WU document
136
+ *
137
+ * @param doc - WU document with lane and id fields
138
+ * @returns Worktree path or null if inputs are invalid
139
+ */
140
+ export declare function defaultWorktreeFrom(doc: {
141
+ lane?: string;
142
+ id?: string;
143
+ } | null | undefined): string | null;
144
+ /**
145
+ * Resolve a repo-root-relative path to an absolute path using project root.
146
+ *
147
+ * @param relativePath - Path relative to project root
148
+ * @param moduleUrl - import.meta.url of the calling module (for backwards compat)
149
+ * @returns Absolute path resolved from project root
150
+ */
151
+ export declare function resolveFromProjectRoot(relativePath: string, moduleUrl?: string): string;
152
+ /**
153
+ * Get absolute path to WU YAML file
154
+ *
155
+ * @param id - WU ID (e.g., 'WU-123')
156
+ * @param options - Options
157
+ * @returns Absolute path to WU YAML file
158
+ */
159
+ export declare function getAbsoluteWuPath(id: string, options?: {
160
+ projectRoot?: string;
161
+ }): string;
162
+ /**
163
+ * Get absolute path to stamp file
164
+ *
165
+ * @param id - WU ID (e.g., 'WU-123')
166
+ * @param options - Options
167
+ * @returns Absolute path to stamp file
168
+ */
169
+ export declare function getAbsoluteStampPath(id: string, options?: {
170
+ projectRoot?: string;
171
+ }): string;
@@ -0,0 +1,178 @@
1
+ /**
2
+ * WU Paths - Centralized path management for Work Units
3
+ *
4
+ * All paths are configurable via .lumenflow.config.yaml
5
+ *
6
+ * @module wu-paths
7
+ */
8
+ import * as path from 'node:path';
9
+ import { getWorktreePath, getProjectRoot as getProjectRootFromConstants } from './wu-constants.js';
10
+ import { getConfig, getProjectRoot as getProjectRootFromConfig } from './lumenflow-config.js';
11
+ /**
12
+ * Directory depth constants for path resolution.
13
+ * These define how many levels deep each standard file is from repo root.
14
+ */
15
+ const PATH_DEPTHS = {
16
+ /** backlog.md is 4 levels deep: docs/04-operations/tasks/backlog.md */
17
+ BACKLOG: 4,
18
+ /** status.md is 4 levels deep: docs/04-operations/tasks/status.md */
19
+ STATUS: 4,
20
+ /** WU YAML files are 5 levels deep: docs/04-operations/tasks/wu/{id}.yaml */
21
+ WU_YAML: 5,
22
+ /** State store is 3 levels deep: .beacon/state/wu-events.jsonl */
23
+ STATE_STORE: 3,
24
+ };
25
+ /**
26
+ * Resolve repo root from an absolute file path by traversing up N directory levels.
27
+ *
28
+ * @param absolutePath - Absolute path to a file within the repo
29
+ * @param depth - Number of directory levels to traverse up
30
+ * @returns Absolute path to repo root
31
+ */
32
+ export function resolveRepoRoot(absolutePath, depth) {
33
+ let result = absolutePath;
34
+ for (let i = 0; i < depth; i++) {
35
+ result = path.dirname(result);
36
+ }
37
+ return result;
38
+ }
39
+ /**
40
+ * Get the state store directory path from backlog.md path.
41
+ *
42
+ * @param backlogPath - Absolute path to backlog.md
43
+ * @returns Absolute path to state store directory
44
+ */
45
+ export function getStateStoreDirFromBacklog(backlogPath) {
46
+ const config = getConfig();
47
+ const repoRoot = resolveRepoRoot(backlogPath, PATH_DEPTHS.BACKLOG);
48
+ return path.join(repoRoot, config.beacon.stateDir);
49
+ }
50
+ /**
51
+ * Create WU paths object with configurable base paths
52
+ *
53
+ * @param options - Options for path generation
54
+ * @param options.projectRoot - Override project root
55
+ * @returns WU paths object
56
+ */
57
+ export function createWuPaths(options = {}) {
58
+ const config = getConfig({ projectRoot: options.projectRoot });
59
+ return {
60
+ /**
61
+ * Get path to WU YAML file
62
+ * @param id - WU ID (e.g., 'WU-123')
63
+ * @returns Path to WU YAML file
64
+ */
65
+ WU: (id) => path.join(config.directories.wuDir, `${id}.yaml`),
66
+ /**
67
+ * Get path to WU directory
68
+ * @returns Path to WU directory
69
+ */
70
+ WU_DIR: () => config.directories.wuDir,
71
+ /**
72
+ * Get path to status.md
73
+ * @returns Path to status.md
74
+ */
75
+ STATUS: () => config.directories.statusPath,
76
+ /**
77
+ * Get path to backlog.md
78
+ * @returns Path to backlog.md
79
+ */
80
+ BACKLOG: () => config.directories.backlogPath,
81
+ /**
82
+ * Get path to stamps directory
83
+ * @returns Path to stamps directory
84
+ */
85
+ STAMPS_DIR: () => config.beacon.stampsDir,
86
+ /**
87
+ * Get path to WU done stamp file
88
+ * @param id - WU ID (e.g., 'WU-123')
89
+ * @returns Path to stamp file
90
+ */
91
+ STAMP: (id) => path.join(config.beacon.stampsDir, `${id}.done`),
92
+ /**
93
+ * Get path to state directory
94
+ * @returns Path to state directory
95
+ */
96
+ STATE_DIR: () => config.beacon.stateDir,
97
+ /**
98
+ * Get path to initiatives directory
99
+ * @returns Path to initiatives directory
100
+ */
101
+ INITIATIVES_DIR: () => config.directories.initiativesDir,
102
+ /**
103
+ * Get path to worktrees directory
104
+ * @returns Path to worktrees directory
105
+ */
106
+ WORKTREES_DIR: () => config.directories.worktrees,
107
+ };
108
+ }
109
+ /**
110
+ * Default WU paths using default config
111
+ * For backwards compatibility with existing code
112
+ */
113
+ export const WU_PATHS = createWuPaths();
114
+ /**
115
+ * Generate default worktree path from WU document
116
+ *
117
+ * @param doc - WU document with lane and id fields
118
+ * @returns Worktree path or null if inputs are invalid
119
+ */
120
+ export function defaultWorktreeFrom(doc) {
121
+ if (!doc)
122
+ return null;
123
+ const lane = doc.lane;
124
+ const id = doc.id;
125
+ // Validate inputs
126
+ if (!lane || !id)
127
+ return null;
128
+ // Convert to string and trim
129
+ const laneStr = String(lane).trim();
130
+ const idStr = String(id).trim();
131
+ // Check for empty strings after trimming
132
+ if (laneStr === '' || idStr === '')
133
+ return null;
134
+ // Use centralized getWorktreePath from wu-constants
135
+ return getWorktreePath(laneStr, idStr);
136
+ }
137
+ /**
138
+ * Resolve a repo-root-relative path to an absolute path using project root.
139
+ *
140
+ * @param relativePath - Path relative to project root
141
+ * @param moduleUrl - import.meta.url of the calling module (for backwards compat)
142
+ * @returns Absolute path resolved from project root
143
+ */
144
+ export function resolveFromProjectRoot(relativePath, moduleUrl) {
145
+ // Try config-based project root first, fall back to constants-based
146
+ let projectRoot;
147
+ try {
148
+ projectRoot = getProjectRootFromConfig();
149
+ }
150
+ catch {
151
+ projectRoot = moduleUrl ? getProjectRootFromConstants(moduleUrl) : process.cwd();
152
+ }
153
+ return path.join(projectRoot, relativePath);
154
+ }
155
+ /**
156
+ * Get absolute path to WU YAML file
157
+ *
158
+ * @param id - WU ID (e.g., 'WU-123')
159
+ * @param options - Options
160
+ * @returns Absolute path to WU YAML file
161
+ */
162
+ export function getAbsoluteWuPath(id, options = {}) {
163
+ const projectRoot = options.projectRoot || getProjectRootFromConfig();
164
+ const paths = createWuPaths({ projectRoot });
165
+ return path.join(projectRoot, paths.WU(id));
166
+ }
167
+ /**
168
+ * Get absolute path to stamp file
169
+ *
170
+ * @param id - WU ID (e.g., 'WU-123')
171
+ * @param options - Options
172
+ * @returns Absolute path to stamp file
173
+ */
174
+ export function getAbsoluteStampPath(id, options = {}) {
175
+ const projectRoot = options.projectRoot || getProjectRootFromConfig();
176
+ const paths = createWuPaths({ projectRoot });
177
+ return path.join(projectRoot, paths.STAMP(id));
178
+ }
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Preflight validation functions for wu:preflight command
4
+ *
5
+ * WU-1803: Fast validation of code_paths and test paths before gates run.
6
+ * WU-1810: Upgraded to use canonical Zod schema validation (catches created format issues).
7
+ *
8
+ * This catches YAML mismatches early, saving time compared to full wu:done validation.
9
+ *
10
+ * Key validations:
11
+ * - WU YAML schema is valid (full canonical schema, not just required fields)
12
+ * - created field is YYYY-MM-DD format (fails fast on ISO timestamps)
13
+ * - code_paths files exist
14
+ * - test file paths exist (unit, e2e, integration - not manual)
15
+ *
16
+ * Design goals:
17
+ * - Complete in under 5 seconds
18
+ * - Clear error messages pointing to missing files
19
+ * - Reusable by wu:done for early validation
20
+ */
21
+ /**
22
+ * Result structure for preflight validation
23
+ * @typedef {object} PreflightResult
24
+ * @property {boolean} valid - Whether all validations passed
25
+ * @property {string[]} errors - List of error messages
26
+ * @property {string[]} missingCodePaths - Code paths that don't exist
27
+ * @property {string[]} missingTestPaths - Test file paths that don't exist
28
+ */
29
+ /**
30
+ * Create a PreflightResult object
31
+ *
32
+ * @param {object} params - Result parameters
33
+ * @param {boolean} params.valid - Whether validation passed
34
+ * @param {string[]} [params.errors=[]] - Error messages
35
+ * @param {string[]} [params.missingCodePaths=[]] - Missing code paths
36
+ * @param {string[]} [params.missingTestPaths=[]] - Missing test paths
37
+ * @returns {PreflightResult}
38
+ */
39
+ export declare function createPreflightResult({ valid, errors, missingCodePaths, missingTestPaths, }: {
40
+ valid: any;
41
+ errors?: any[];
42
+ missingCodePaths?: any[];
43
+ missingTestPaths?: any[];
44
+ }): {
45
+ valid: any;
46
+ errors: any[];
47
+ missingCodePaths: any[];
48
+ missingTestPaths: any[];
49
+ };
50
+ /**
51
+ * Run preflight validation for a WU
52
+ *
53
+ * Validates:
54
+ * 1. WU YAML schema is valid
55
+ * 2. code_paths files exist
56
+ * 3. test file paths exist (unit, e2e, integration)
57
+ *
58
+ * WU-1830: When worktreePath is provided, YAML is read from worktree (not rootDir).
59
+ * This ensures that when agent runs wu:edit to update code_paths in worktree,
60
+ * preflight validation uses the updated YAML, not stale main.
61
+ *
62
+ * @param {string} id - WU ID (e.g., 'WU-999')
63
+ * @param {ValidatePreflightOptions} [options={}] - Options
64
+ * @returns {Promise<PreflightResult>}
65
+ */
66
+ export interface ValidatePreflightOptions {
67
+ /** Root directory for path resolution (fallback) */
68
+ rootDir?: string;
69
+ /** Worktree path (preferred source for YAML and file checks) */
70
+ worktreePath?: string | null;
71
+ }
72
+ export declare function validatePreflight(id: any, options?: ValidatePreflightOptions): Promise<{
73
+ valid: any;
74
+ errors: any[];
75
+ missingCodePaths: any[];
76
+ missingTestPaths: any[];
77
+ }>;
78
+ /**
79
+ * Format preflight result as user-friendly message
80
+ *
81
+ * @param {string} id - WU ID
82
+ * @param {PreflightResult} result - Validation result
83
+ * @returns {string} Formatted message
84
+ */
85
+ export declare function formatPreflightResult(id: any, result: any): string;
86
+ export declare const PreflightResult: {};
@@ -0,0 +1,251 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Preflight validation functions for wu:preflight command
4
+ *
5
+ * WU-1803: Fast validation of code_paths and test paths before gates run.
6
+ * WU-1810: Upgraded to use canonical Zod schema validation (catches created format issues).
7
+ *
8
+ * This catches YAML mismatches early, saving time compared to full wu:done validation.
9
+ *
10
+ * Key validations:
11
+ * - WU YAML schema is valid (full canonical schema, not just required fields)
12
+ * - created field is YYYY-MM-DD format (fails fast on ISO timestamps)
13
+ * - code_paths files exist
14
+ * - test file paths exist (unit, e2e, integration - not manual)
15
+ *
16
+ * Design goals:
17
+ * - Complete in under 5 seconds
18
+ * - Clear error messages pointing to missing files
19
+ * - Reusable by wu:done for early validation
20
+ */
21
+ /* eslint-disable security/detect-non-literal-fs-filename, security/detect-object-injection */
22
+ import { existsSync } from 'node:fs';
23
+ import path from 'node:path';
24
+ import { WU_PATHS } from './wu-paths.js';
25
+ import { readWURaw } from './wu-yaml.js';
26
+ import { TEST_TYPES, LOG_PREFIX, EMOJI } from './wu-constants.js';
27
+ // WU-1810: Import canonical schema for full validation
28
+ import { BaseWUSchema } from './wu-schema.js';
29
+ // WU-1810: Import fixer to detect fixable issues
30
+ import { detectFixableIssues, FIXABLE_ISSUES } from './wu-yaml-fixer.js';
31
+ /**
32
+ * Result structure for preflight validation
33
+ * @typedef {object} PreflightResult
34
+ * @property {boolean} valid - Whether all validations passed
35
+ * @property {string[]} errors - List of error messages
36
+ * @property {string[]} missingCodePaths - Code paths that don't exist
37
+ * @property {string[]} missingTestPaths - Test file paths that don't exist
38
+ */
39
+ /**
40
+ * Create a PreflightResult object
41
+ *
42
+ * @param {object} params - Result parameters
43
+ * @param {boolean} params.valid - Whether validation passed
44
+ * @param {string[]} [params.errors=[]] - Error messages
45
+ * @param {string[]} [params.missingCodePaths=[]] - Missing code paths
46
+ * @param {string[]} [params.missingTestPaths=[]] - Missing test paths
47
+ * @returns {PreflightResult}
48
+ */
49
+ export function createPreflightResult({ valid, errors = [], missingCodePaths = [], missingTestPaths = [], }) {
50
+ return {
51
+ valid,
52
+ errors,
53
+ missingCodePaths,
54
+ missingTestPaths,
55
+ };
56
+ }
57
+ /**
58
+ * WU-1810: Validate WU YAML schema using canonical Zod schema
59
+ *
60
+ * Uses BaseWUSchema (structural validation) rather than minimal required fields.
61
+ * This catches created format issues, invalid type/status enums, etc. early.
62
+ *
63
+ * Special handling for created field:
64
+ * - Detects ISO timestamps and Date scalars via wu-yaml-fixer
65
+ * - Provides actionable error message suggesting auto-fix
66
+ *
67
+ * @param {object} doc - Parsed WU YAML document
68
+ * @param {string} id - Expected WU ID
69
+ * @returns {{ valid: boolean, errors: string[] }}
70
+ */
71
+ function validateSchema(doc, id) {
72
+ const errors = [];
73
+ // Check ID matches (before schema validation for clear error)
74
+ if (doc.id !== id) {
75
+ errors.push(`WU ID mismatch: expected ${id}, found ${doc.id}`);
76
+ }
77
+ // WU-1810: Check for fixable issues (especially created field)
78
+ // This provides better error messages than raw Zod schema errors
79
+ const fixableIssues = detectFixableIssues(doc);
80
+ const createdIssue = fixableIssues.find((issue) => issue.type === FIXABLE_ISSUES.DATE_ISO_TIMESTAMP);
81
+ if (createdIssue) {
82
+ errors.push(`created field has invalid format: "${createdIssue.current}" is an ISO timestamp. ` +
83
+ `Expected YYYY-MM-DD format. Suggested fix: change to "${createdIssue.suggested}". ` +
84
+ `Fix by editing the WU YAML file (created: '${createdIssue.suggested}').`);
85
+ }
86
+ // WU-1810: Validate against canonical Zod schema
87
+ const schemaResult = BaseWUSchema.safeParse(doc);
88
+ if (!schemaResult.success) {
89
+ // Format Zod errors with field paths
90
+ for (const issue of schemaResult.error.issues) {
91
+ const fieldPath = issue.path.join('.');
92
+ const message = issue.message;
93
+ // Skip created errors if we already reported a fixable issue
94
+ if (fieldPath === 'created' && createdIssue) {
95
+ continue;
96
+ }
97
+ errors.push(`${fieldPath}: ${message}`);
98
+ }
99
+ }
100
+ return { valid: errors.length === 0, errors };
101
+ }
102
+ /**
103
+ * Validate code_paths files exist
104
+ *
105
+ * @param {string[]} codePaths - List of code paths from WU YAML
106
+ * @param {string} rootDir - Root directory to resolve paths against
107
+ * @returns {{ valid: boolean, errors: string[], missing: string[] }}
108
+ */
109
+ function validateCodePathsExistence(codePaths, rootDir) {
110
+ if (!codePaths || !Array.isArray(codePaths) || codePaths.length === 0) {
111
+ return { valid: true, errors: [], missing: [] };
112
+ }
113
+ const missing = [];
114
+ for (const filePath of codePaths) {
115
+ if (!filePath || typeof filePath !== 'string')
116
+ continue;
117
+ const fullPath = path.join(rootDir, filePath);
118
+ if (!existsSync(fullPath)) {
119
+ missing.push(filePath);
120
+ }
121
+ }
122
+ if (missing.length > 0) {
123
+ const errors = [
124
+ `code_paths validation failed - ${missing.length} file(s) not found:`,
125
+ ...missing.map((p) => ` - ${p}`),
126
+ ];
127
+ return { valid: false, errors, missing };
128
+ }
129
+ return { valid: true, errors: [], missing: [] };
130
+ }
131
+ /**
132
+ * Validate test file paths exist (unit, e2e, integration - not manual)
133
+ *
134
+ * Manual tests are descriptions, not file paths, so they're skipped.
135
+ *
136
+ * @param {object} tests - tests object from WU YAML
137
+ * @param {string} rootDir - Root directory to resolve paths against
138
+ * @returns {{ valid: boolean, errors: string[], missing: string[] }}
139
+ */
140
+ function validateTestPathsExistence(tests, rootDir) {
141
+ if (!tests || typeof tests !== 'object') {
142
+ return { valid: true, errors: [], missing: [] };
143
+ }
144
+ const missing = [];
145
+ // Test types that are file paths (not manual descriptions)
146
+ const fileTestTypes = [TEST_TYPES.UNIT, TEST_TYPES.E2E, TEST_TYPES.INTEGRATION];
147
+ for (const testType of fileTestTypes) {
148
+ const paths = tests[testType];
149
+ if (!paths || !Array.isArray(paths))
150
+ continue;
151
+ for (const filePath of paths) {
152
+ if (!filePath || typeof filePath !== 'string')
153
+ continue;
154
+ const fullPath = path.join(rootDir, filePath);
155
+ if (!existsSync(fullPath)) {
156
+ missing.push(filePath);
157
+ }
158
+ }
159
+ }
160
+ if (missing.length > 0) {
161
+ const errors = [
162
+ `test paths validation failed - ${missing.length} test file(s) not found:`,
163
+ ...missing.map((p) => ` - ${p}`),
164
+ ];
165
+ return { valid: false, errors, missing };
166
+ }
167
+ return { valid: true, errors: [], missing: [] };
168
+ }
169
+ export async function validatePreflight(id, options = {}) {
170
+ const rootDir = options.rootDir || process.cwd();
171
+ const worktreePath = options.worktreePath || rootDir;
172
+ const allErrors = [];
173
+ const missingCodePaths = [];
174
+ const missingTestPaths = [];
175
+ // Step 1: Read WU YAML from worktree (WU-1830)
176
+ // When worktreePath is provided, read YAML from there to get latest code_paths
177
+ const wuPath = path.join(worktreePath, WU_PATHS.WU(id));
178
+ // Debug logging for YAML source (WU-1830)
179
+ if (options.worktreePath && options.worktreePath !== rootDir) {
180
+ process.env.DEBUG && console.log(`[wu-preflight] Reading WU YAML from worktree: ${wuPath}`);
181
+ }
182
+ let doc;
183
+ try {
184
+ // First try to read raw (without ID validation) to provide better errors
185
+ doc = readWURaw(wuPath);
186
+ }
187
+ catch (err) {
188
+ return createPreflightResult({
189
+ valid: false,
190
+ errors: [`Failed to read WU YAML: ${err.message}`],
191
+ });
192
+ }
193
+ // Step 2: Validate schema
194
+ const schemaResult = validateSchema(doc, id);
195
+ if (!schemaResult.valid) {
196
+ allErrors.push(...schemaResult.errors);
197
+ }
198
+ // Step 3: Validate code_paths exist
199
+ const codePathsResult = validateCodePathsExistence(doc.code_paths, worktreePath);
200
+ if (!codePathsResult.valid) {
201
+ allErrors.push(...codePathsResult.errors);
202
+ missingCodePaths.push(...codePathsResult.missing);
203
+ }
204
+ // Step 4: Validate test file paths exist
205
+ // Support both 'tests' and legacy 'test_paths' field
206
+ const testsObj = doc.tests || doc.test_paths || {};
207
+ const testPathsResult = validateTestPathsExistence(testsObj, worktreePath);
208
+ if (!testPathsResult.valid) {
209
+ allErrors.push(...testPathsResult.errors);
210
+ missingTestPaths.push(...testPathsResult.missing);
211
+ }
212
+ return createPreflightResult({
213
+ valid: allErrors.length === 0,
214
+ errors: allErrors,
215
+ missingCodePaths,
216
+ missingTestPaths,
217
+ });
218
+ }
219
+ /**
220
+ * Format preflight result as user-friendly message
221
+ *
222
+ * @param {string} id - WU ID
223
+ * @param {PreflightResult} result - Validation result
224
+ * @returns {string} Formatted message
225
+ */
226
+ export function formatPreflightResult(id, result) {
227
+ if (result.valid) {
228
+ return `${LOG_PREFIX.PREFLIGHT} ${EMOJI.SUCCESS} Preflight validation passed for ${id}`;
229
+ }
230
+ const lines = [
231
+ `${LOG_PREFIX.PREFLIGHT} ${EMOJI.FAILURE} Preflight validation failed for ${id}`,
232
+ '',
233
+ ...result.errors,
234
+ ];
235
+ if (result.missingCodePaths.length > 0) {
236
+ lines.push('');
237
+ lines.push('Fix options:');
238
+ lines.push(' 1. Create the missing files');
239
+ lines.push(` 2. Update code_paths in ${id}.yaml to match actual files`);
240
+ }
241
+ if (result.missingTestPaths.length > 0) {
242
+ lines.push('');
243
+ lines.push('For test paths:');
244
+ lines.push(' 1. Create the missing test files');
245
+ lines.push(` 2. Update tests in ${id}.yaml to match actual files`);
246
+ lines.push(' 3. Or use tests.manual for non-file test descriptions');
247
+ }
248
+ return lines.join('\n');
249
+ }
250
+ // Export PreflightResult type for documentation
251
+ export const PreflightResult = {};