@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,42 @@
1
+ /**
2
+ * @lumenflow/core - Battle-tested LumenFlow workflow framework
3
+ * @module @lumenflow/core
4
+ */
5
+ export declare const VERSION = "0.0.0";
6
+ export * from './arg-parser.js';
7
+ export * from './date-utils.js';
8
+ export * from './error-handler.js';
9
+ export * from './retry-strategy.js';
10
+ export { DEFAULT_DOMAIN, inferDefaultDomain, normalizeToEmail, isValidEmail, } from './user-normalizer.js';
11
+ export * from './git-adapter.js';
12
+ export * from './state-machine.js';
13
+ export { WU_EVENT_TYPES, WU_STATUSES, WU_PATTERNS, CreateEventSchema, ClaimEventSchema, BlockEventSchema, UnblockEventSchema, CompleteEventSchema, CheckpointEventSchema, WUEventSchema, validateWUEvent, SpawnEventSchema as WUSpawnEventSchema, type CreateEvent, type ClaimEvent, type BlockEvent, type UnblockEvent, type CompleteEvent, type CheckpointEvent, type WUEvent, type SpawnEvent as WUSpawnEvent, } from './wu-state-schema.js';
14
+ export { WU_EVENTS_FILE_NAME, WUStateStore, acquireLock, releaseLock, repairStateFile, isLockStale as isWULockStale, type WUStateEntry, type LockData as WULockData, type CheckpointOptions, type RepairResult, } from './wu-state-store.js';
15
+ export * from './lane-checker.js';
16
+ export * from './lane-inference.js';
17
+ export { getStaleThresholdMs, getLocksDir, getLockFilePath, isLockStale, isZombieLock, readLockMetadata, acquireLaneLock, releaseLaneLock, checkLaneLock, forceRemoveStaleLock, getAllLaneLocks, auditedUnlock, } from './lane-lock.js';
18
+ export * from './lane-validator.js';
19
+ export * from './wu-yaml.js';
20
+ export { getAssignedEmail } from './wu-claim-helpers.js';
21
+ export * from './wu-done-worktree.js';
22
+ export * from './wu-done-validators.js';
23
+ export * from './wu-helpers.js';
24
+ export * from './wu-schema.js';
25
+ export * from './wu-validator.js';
26
+ export * from './spawn-registry-store.js';
27
+ export * from './spawn-registry-schema.js';
28
+ export * from './spawn-tree.js';
29
+ export * from './spawn-recovery.js';
30
+ export * from './spawn-monitor.js';
31
+ export * from './spawn-escalation.js';
32
+ export * from './backlog-generator.js';
33
+ export * from './backlog-parser.js';
34
+ export * from './backlog-editor.js';
35
+ export * from './backlog-sync-validator.js';
36
+ export * from './worktree-scanner.js';
37
+ export * from './worktree-ownership.js';
38
+ export * from './micro-worktree.js';
39
+ export * from './dependency-guard.js';
40
+ export * from './stamp-utils.js';
41
+ export * from './lumenflow-config.js';
42
+ export * from './lumenflow-config-schema.js';
package/dist/index.js ADDED
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @lumenflow/core - Battle-tested LumenFlow workflow framework
3
+ * @module @lumenflow/core
4
+ */
5
+ // Package version
6
+ export const VERSION = '0.0.0';
7
+ // Core utilities
8
+ export * from './arg-parser.js';
9
+ export * from './date-utils.js';
10
+ export * from './error-handler.js';
11
+ export * from './retry-strategy.js';
12
+ // User normalizer (explicit exports to avoid conflicts)
13
+ export { DEFAULT_DOMAIN, inferDefaultDomain, normalizeToEmail, isValidEmail, } from './user-normalizer.js';
14
+ // Git operations
15
+ export * from './git-adapter.js';
16
+ // State machine
17
+ export * from './state-machine.js';
18
+ // WU State Schema (explicit exports to avoid SpawnEvent conflict with spawn-registry)
19
+ export { WU_EVENT_TYPES, WU_STATUSES, WU_PATTERNS, CreateEventSchema, ClaimEventSchema, BlockEventSchema, UnblockEventSchema, CompleteEventSchema, CheckpointEventSchema, WUEventSchema, validateWUEvent,
20
+ // Rename conflicting exports
21
+ SpawnEventSchema as WUSpawnEventSchema, } from './wu-state-schema.js';
22
+ // WU State Store (explicit exports to avoid isLockStale conflict)
23
+ export { WU_EVENTS_FILE_NAME, WUStateStore, acquireLock, releaseLock, repairStateFile, isLockStale as isWULockStale, } from './wu-state-store.js';
24
+ // Lane management
25
+ export * from './lane-checker.js';
26
+ export * from './lane-inference.js';
27
+ // Lane lock (explicit exports with proper names)
28
+ export { getStaleThresholdMs, getLocksDir, getLockFilePath, isLockStale, isZombieLock, readLockMetadata, acquireLaneLock, releaseLaneLock, checkLaneLock, forceRemoveStaleLock, getAllLaneLocks, auditedUnlock, } from './lane-lock.js';
29
+ export * from './lane-validator.js';
30
+ // WU lifecycle
31
+ export * from './wu-yaml.js';
32
+ // WU claim helpers (skip isValidEmail which conflicts with user-normalizer)
33
+ export { getAssignedEmail } from './wu-claim-helpers.js';
34
+ export * from './wu-done-worktree.js';
35
+ export * from './wu-done-validators.js';
36
+ export * from './wu-helpers.js';
37
+ export * from './wu-schema.js';
38
+ export * from './wu-validator.js';
39
+ // Spawn system
40
+ export * from './spawn-registry-store.js';
41
+ export * from './spawn-registry-schema.js';
42
+ export * from './spawn-tree.js';
43
+ export * from './spawn-recovery.js';
44
+ export * from './spawn-monitor.js';
45
+ export * from './spawn-escalation.js';
46
+ // Backlog management
47
+ export * from './backlog-generator.js';
48
+ export * from './backlog-parser.js';
49
+ export * from './backlog-editor.js';
50
+ export * from './backlog-sync-validator.js';
51
+ // Worktree utilities
52
+ export * from './worktree-scanner.js';
53
+ export * from './worktree-ownership.js';
54
+ export * from './micro-worktree.js';
55
+ // Guards and validators
56
+ // NOTE: Configuration added below
57
+ export * from './dependency-guard.js';
58
+ export * from './stamp-utils.js';
59
+ // Configuration
60
+ export * from './lumenflow-config.js';
61
+ export * from './lumenflow-config-schema.js';
@@ -0,0 +1,50 @@
1
+ /**
2
+ * INV-AUTOMATED-TESTS-FOR-CODE Invariant Check (WU-2333)
3
+ *
4
+ * Validates that WUs with code files in code_paths have automated tests.
5
+ * Config files are excluded from this requirement.
6
+ *
7
+ * This invariant ensures that manual-only tests cannot satisfy validation
8
+ * for code changes, enforcing TDD discipline.
9
+ *
10
+ * Library-first check: This is custom validation logic for PatientPath WU workflow.
11
+ * No external library exists for WU YAML validation - this integrates with
12
+ * the existing manual-test-validator.mjs which already implements the core logic.
13
+ *
14
+ * @see {@link tools/lib/manual-test-validator.mjs} - Core validation logic
15
+ * @see {@link tools/invariants.yml} - Invariant registry
16
+ */
17
+ /**
18
+ * Invariant metadata
19
+ */
20
+ export declare const INVARIANT_ID = "INV-AUTOMATED-TESTS-FOR-CODE";
21
+ export declare const INVARIANT_TYPE = "wu-automated-tests";
22
+ /**
23
+ * Run the INV-AUTOMATED-TESTS-FOR-CODE invariant check.
24
+ *
25
+ * Scans WU YAML files and validates that any with code files in code_paths
26
+ * have automated tests (unit, e2e, or integration).
27
+ *
28
+ * WU-2425: When wuId is provided, only validates that specific WU instead of
29
+ * all active WUs. This prevents unrelated WUs from blocking wu:done completion.
30
+ *
31
+ * @param {CheckAutomatedTestsInvariantOptions} [options={}] - Options
32
+ * @returns {{ valid: boolean, violations: Array<object> }} Check result
33
+ */
34
+ export interface CheckAutomatedTestsInvariantOptions {
35
+ /** Base directory for path resolution */
36
+ baseDir?: string;
37
+ /** Specific WU ID to validate (WU-2425: scoped validation) */
38
+ wuId?: string;
39
+ }
40
+ export declare function checkAutomatedTestsInvariant(options?: CheckAutomatedTestsInvariantOptions): {
41
+ valid: boolean;
42
+ violations: any[];
43
+ };
44
+ /**
45
+ * Format a violation for display.
46
+ *
47
+ * @param {object} violation - Violation object
48
+ * @returns {string} Formatted error message
49
+ */
50
+ export declare function formatAutomatedTestsViolation(violation: any): string;
@@ -0,0 +1,166 @@
1
+ /**
2
+ * INV-AUTOMATED-TESTS-FOR-CODE Invariant Check (WU-2333)
3
+ *
4
+ * Validates that WUs with code files in code_paths have automated tests.
5
+ * Config files are excluded from this requirement.
6
+ *
7
+ * This invariant ensures that manual-only tests cannot satisfy validation
8
+ * for code changes, enforcing TDD discipline.
9
+ *
10
+ * Library-first check: This is custom validation logic for PatientPath WU workflow.
11
+ * No external library exists for WU YAML validation - this integrates with
12
+ * the existing manual-test-validator.mjs which already implements the core logic.
13
+ *
14
+ * @see {@link tools/lib/manual-test-validator.mjs} - Core validation logic
15
+ * @see {@link tools/invariants.yml} - Invariant registry
16
+ */
17
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
18
+ import path from 'node:path';
19
+ import { parseYAML } from '../wu-yaml.js';
20
+ import { validateAutomatedTestRequirement, isCodeFile } from '../manual-test-validator.js';
21
+ /**
22
+ * Invariant metadata
23
+ */
24
+ export const INVARIANT_ID = 'INV-AUTOMATED-TESTS-FOR-CODE';
25
+ export const INVARIANT_TYPE = 'wu-automated-tests';
26
+ /**
27
+ * WU statuses that should be validated.
28
+ * Only validate active work - in_progress and blocked WUs.
29
+ * Done, ready, and waiting WUs are either already validated or not yet being worked.
30
+ */
31
+ const ACTIVE_STATUSES = Object.freeze(['in_progress', 'blocked']);
32
+ /**
33
+ * Default path to WU YAML files relative to base directory.
34
+ */
35
+ const WU_YAML_PATH = 'docs/04-operations/tasks/wu';
36
+ /**
37
+ * Check a single WU YAML file for automated test requirement.
38
+ *
39
+ * @param {string} filePath - Path to WU YAML file
40
+ * @param {CheckWUFileOptions} [options={}] - Options
41
+ * @returns {{ valid: boolean, wuId: string|null, error: string|null }} Check result
42
+ */
43
+ function checkWUFile(filePath, options = {}) {
44
+ const { skipStatusCheck = false } = options;
45
+ try {
46
+ const content = readFileSync(filePath, 'utf-8');
47
+ const doc = parseYAML(content);
48
+ if (!doc) {
49
+ return { valid: true, wuId: null, error: null };
50
+ }
51
+ const wuId = doc.id || path.basename(filePath, '.yaml');
52
+ const status = doc.status || '';
53
+ // WU-2425: Skip status check when validating a specific WU (e.g., during wu:done)
54
+ // This is needed because wu:done may set status to 'done' before validation runs
55
+ if (!skipStatusCheck && !ACTIVE_STATUSES.includes(status)) {
56
+ return { valid: true, wuId, error: null };
57
+ }
58
+ // Use the existing validation logic from manual-test-validator.mjs
59
+ const result = validateAutomatedTestRequirement(doc);
60
+ if (!result.valid) {
61
+ return {
62
+ valid: false,
63
+ wuId,
64
+ error: result.errors.join('\n'),
65
+ codeFiles: getCodeFilesFromPaths(doc.code_paths || []),
66
+ };
67
+ }
68
+ return { valid: true, wuId, error: null };
69
+ }
70
+ catch {
71
+ // Skip files that can't be parsed
72
+ return { valid: true, wuId: null, error: null };
73
+ }
74
+ }
75
+ /**
76
+ * Get code files from code_paths (filtering out config files).
77
+ *
78
+ * @param {string[]} codePaths - Array of code paths
79
+ * @returns {string[]} Code files that require automated tests
80
+ */
81
+ function getCodeFilesFromPaths(codePaths) {
82
+ if (!codePaths || !Array.isArray(codePaths)) {
83
+ return [];
84
+ }
85
+ return codePaths.filter((p) => isCodeFile(p));
86
+ }
87
+ export function checkAutomatedTestsInvariant(options = {}) {
88
+ const { baseDir = process.cwd(), wuId } = options;
89
+ const wuDir = path.join(baseDir, WU_YAML_PATH);
90
+ const violations = [];
91
+ // Check if WU directory exists
92
+ if (!existsSync(wuDir)) {
93
+ return { valid: true, violations: [] };
94
+ }
95
+ // WU-2425: If wuId is provided, only check that specific WU file
96
+ if (wuId) {
97
+ const filePath = path.join(wuDir, `${wuId}.yaml`);
98
+ // If the WU file doesn't exist, pass gracefully (nothing to validate)
99
+ if (!existsSync(filePath)) {
100
+ return { valid: true, violations: [] };
101
+ }
102
+ // When validating a specific WU, skip status check (validate regardless of status)
103
+ // This is needed because wu:done may set status to 'done' before validation runs
104
+ const result = checkWUFile(filePath, { skipStatusCheck: true });
105
+ if (!result.valid) {
106
+ violations.push({
107
+ id: INVARIANT_ID,
108
+ type: INVARIANT_TYPE,
109
+ wuId: result.wuId,
110
+ description: `WU ${result.wuId} has code files but no automated tests`,
111
+ message: result.error,
112
+ codeFiles: result.codeFiles,
113
+ });
114
+ }
115
+ return {
116
+ valid: violations.length === 0,
117
+ violations,
118
+ };
119
+ }
120
+ // Default behavior: check all WU files (existing behavior for gates)
121
+ let files;
122
+ try {
123
+ files = readdirSync(wuDir).filter((f) => f.startsWith('WU-') && (f.endsWith('.yaml') || f.endsWith('.yml')));
124
+ }
125
+ catch {
126
+ return { valid: true, violations: [] };
127
+ }
128
+ // Check each WU file
129
+ for (const file of files) {
130
+ const filePath = path.join(wuDir, file);
131
+ const result = checkWUFile(filePath);
132
+ if (!result.valid) {
133
+ violations.push({
134
+ id: INVARIANT_ID,
135
+ type: INVARIANT_TYPE,
136
+ wuId: result.wuId,
137
+ description: `WU ${result.wuId} has code files but no automated tests`,
138
+ message: result.error,
139
+ codeFiles: result.codeFiles,
140
+ });
141
+ }
142
+ }
143
+ return {
144
+ valid: violations.length === 0,
145
+ violations,
146
+ };
147
+ }
148
+ /**
149
+ * Format a violation for display.
150
+ *
151
+ * @param {object} violation - Violation object
152
+ * @returns {string} Formatted error message
153
+ */
154
+ export function formatAutomatedTestsViolation(violation) {
155
+ const lines = [
156
+ `INVARIANT VIOLATION: ${violation.id}`,
157
+ `WU: ${violation.wuId}`,
158
+ `Description: ${violation.description}`,
159
+ ];
160
+ if (violation.codeFiles && violation.codeFiles.length > 0) {
161
+ lines.push(`Code files requiring tests: ${violation.codeFiles.join(', ')}`);
162
+ }
163
+ lines.push('');
164
+ lines.push('Action: Add automated tests (unit, e2e, or integration) to the tests field in the WU YAML.');
165
+ return lines.join('\n');
166
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Invariants Runner (WU-2252)
3
+ *
4
+ * Validates durable repo invariants from invariants.yml.
5
+ * Runs as the first gate check and also inside wu:done even when --skip-gates is used.
6
+ *
7
+ * Supported invariant types:
8
+ * - required-file: File must exist
9
+ * - forbidden-file: File must NOT exist
10
+ * - mutual-exclusivity: Only one of the listed files may exist
11
+ * - forbidden-pattern: Pattern must not appear in scoped files
12
+ * - required-pattern: Pattern MUST appear at least once in scoped files (WU-2254)
13
+ * - forbidden-import: Files must not import forbidden modules (WU-2254)
14
+ * - wu-automated-tests: WUs with code files must have automated tests (WU-2333)
15
+ *
16
+ * Performance constraints:
17
+ * - Excludes node_modules/, worktrees/, .next/, dist/, .git/ from scanning
18
+ * - For forbidden-pattern rules, scans only the specified scope paths
19
+ *
20
+ * @module tools/lib/invariants-runner
21
+ */
22
+ /**
23
+ * Invariant type constants
24
+ */
25
+ export declare const INVARIANT_TYPES: {
26
+ REQUIRED_FILE: string;
27
+ FORBIDDEN_FILE: string;
28
+ MUTUAL_EXCLUSIVITY: string;
29
+ FORBIDDEN_PATTERN: string;
30
+ REQUIRED_PATTERN: string;
31
+ FORBIDDEN_IMPORT: string;
32
+ WU_AUTOMATED_TESTS: string;
33
+ };
34
+ /**
35
+ * Custom error class for invariant violations
36
+ */
37
+ export declare class InvariantError extends Error {
38
+ /** The invariant ID */
39
+ invariantId: string;
40
+ /**
41
+ * @param {string} invariantId - The invariant ID (e.g., 'INV-001')
42
+ * @param {string} message - Error message
43
+ */
44
+ constructor(invariantId: string, message: string);
45
+ }
46
+ /**
47
+ * Load invariants from a YAML file
48
+ *
49
+ * @param {string} filePath - Path to invariants.yml
50
+ * @returns {Array<object>} Array of invariant definitions
51
+ * @throws {Error} If file doesn't exist or has invalid YAML
52
+ */
53
+ export declare function loadInvariants(filePath: any): any;
54
+ /**
55
+ * Validate all invariants against the current repo state
56
+ *
57
+ * WU-2425: When wuId is provided, WU-scoped invariants only validate that specific WU.
58
+ *
59
+ * @param {Array<object>} invariants - Array of invariant definitions
60
+ * @param {ValidateInvariantsOptions} [options={}] - Options
61
+ * @returns {{valid: boolean, violations: Array<object>}} Validation result
62
+ */
63
+ export interface ValidateInvariantsOptions {
64
+ /** Base directory for path resolution */
65
+ baseDir?: string;
66
+ /** Specific WU ID for scoped validation (WU-2425) */
67
+ wuId?: string;
68
+ }
69
+ export declare function validateInvariants(invariants: any, options?: ValidateInvariantsOptions): {
70
+ valid: boolean;
71
+ violations: any[];
72
+ };
73
+ /**
74
+ * Format an invariant violation for display
75
+ *
76
+ * @param {object} violation - Violation object from validateInvariants
77
+ * @returns {string} Formatted error message
78
+ */
79
+ export declare function formatInvariantError(violation: any): string;
80
+ /**
81
+ * Run invariants validation and format results for gates output
82
+ *
83
+ * WU-2425: When wuId is provided, WU-scoped invariants (like automated tests)
84
+ * only validate that specific WU, preventing unrelated WUs from blocking wu:done.
85
+ *
86
+ * @param {RunInvariantsOptions} [options={}] - Options
87
+ * @returns {{success: boolean, violations: Array<object>, formatted: string}} Result
88
+ */
89
+ export interface RunInvariantsOptions {
90
+ /** Path to invariants config */
91
+ configPath?: string;
92
+ /** Base directory */
93
+ baseDir?: string;
94
+ /** Suppress console output */
95
+ silent?: boolean;
96
+ /** Specific WU ID for scoped validation (WU-2425) */
97
+ wuId?: string;
98
+ }
99
+ export declare function runInvariants(options?: RunInvariantsOptions): {
100
+ success: boolean;
101
+ violations: any[];
102
+ formatted: string;
103
+ };