@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,76 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Rollback Utilities for WU Tooling
4
+ *
5
+ * WU-1255: Per-file error tracking for robust rollback operations.
6
+ * Ensures all files are attempted even if some fail, with clear error reporting.
7
+ *
8
+ * @see {@link tools/wu-done.mjs} - Consumer (rollbackTransaction function)
9
+ */
10
+ /**
11
+ * Error entry for failed file restoration
12
+ */
13
+ interface RollbackError {
14
+ name: string;
15
+ path: string;
16
+ error: string;
17
+ }
18
+ /**
19
+ * Result of a rollback operation.
20
+ * Tracks which files were restored and which failed.
21
+ *
22
+ * @class
23
+ */
24
+ export declare class RollbackResult {
25
+ /** Names of successfully restored files */
26
+ restored: string[];
27
+ /** Failed file restorations */
28
+ errors: RollbackError[];
29
+ constructor();
30
+ /**
31
+ * Record a successful file restoration.
32
+ * @param {string} name - File identifier (e.g., 'backlog.md')
33
+ */
34
+ addSuccess(name: any): void;
35
+ /**
36
+ * Record a failed file restoration.
37
+ * @param {string} name - File identifier
38
+ * @param {string} path - Full file path
39
+ * @param {string} error - Error message
40
+ */
41
+ addError(name: any, path: any, error: any): void;
42
+ /**
43
+ * Check if all files were restored successfully.
44
+ * @returns {boolean} True if no errors occurred
45
+ */
46
+ get success(): boolean;
47
+ }
48
+ /**
49
+ * Restore multiple files with per-file error tracking.
50
+ *
51
+ * Each file is restored independently - if one fails, subsequent files
52
+ * are still attempted. This ensures maximum recovery even in partial
53
+ * failure scenarios.
54
+ *
55
+ * @param {Array<{name: string, path: string, content: string}>} filesToRestore - Files to restore
56
+ * @returns {RollbackResult} Result with restored files and any errors
57
+ *
58
+ * @example
59
+ * const result = rollbackFiles([
60
+ * { name: 'backlog.md', path: '/path/to/backlog.md', content: 'original content' },
61
+ * { name: 'status.md', path: '/path/to/status.md', content: 'original content' },
62
+ * ]);
63
+ *
64
+ * if (!result.success) {
65
+ * console.error('Rollback had errors:', result.errors);
66
+ * }
67
+ */
68
+ export declare function rollbackFiles(filesToRestore: any): RollbackResult;
69
+ /**
70
+ * Delete multiple files with per-file error tracking.
71
+ *
72
+ * @param {Array<{name: string, path: string}>} filesToDelete - Files to delete
73
+ * @returns {RollbackResult} Result with deleted files and any errors
74
+ */
75
+ export declare function deleteFiles(filesToDelete: any): RollbackResult;
76
+ export {};
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Rollback Utilities for WU Tooling
4
+ *
5
+ * WU-1255: Per-file error tracking for robust rollback operations.
6
+ * Ensures all files are attempted even if some fail, with clear error reporting.
7
+ *
8
+ * @see {@link tools/wu-done.mjs} - Consumer (rollbackTransaction function)
9
+ */
10
+ /* eslint-disable security/detect-non-literal-fs-filename */
11
+ import { writeFileSync, unlinkSync } from 'node:fs';
12
+ /**
13
+ * Result of a rollback operation.
14
+ * Tracks which files were restored and which failed.
15
+ *
16
+ * @class
17
+ */
18
+ export class RollbackResult {
19
+ /** Names of successfully restored files */
20
+ restored;
21
+ /** Failed file restorations */
22
+ errors;
23
+ constructor() {
24
+ this.restored = [];
25
+ this.errors = [];
26
+ }
27
+ /**
28
+ * Record a successful file restoration.
29
+ * @param {string} name - File identifier (e.g., 'backlog.md')
30
+ */
31
+ addSuccess(name) {
32
+ this.restored.push(name);
33
+ }
34
+ /**
35
+ * Record a failed file restoration.
36
+ * @param {string} name - File identifier
37
+ * @param {string} path - Full file path
38
+ * @param {string} error - Error message
39
+ */
40
+ addError(name, path, error) {
41
+ this.errors.push({ name, path, error });
42
+ }
43
+ /**
44
+ * Check if all files were restored successfully.
45
+ * @returns {boolean} True if no errors occurred
46
+ */
47
+ get success() {
48
+ return this.errors.length === 0;
49
+ }
50
+ }
51
+ /**
52
+ * Restore multiple files with per-file error tracking.
53
+ *
54
+ * Each file is restored independently - if one fails, subsequent files
55
+ * are still attempted. This ensures maximum recovery even in partial
56
+ * failure scenarios.
57
+ *
58
+ * @param {Array<{name: string, path: string, content: string}>} filesToRestore - Files to restore
59
+ * @returns {RollbackResult} Result with restored files and any errors
60
+ *
61
+ * @example
62
+ * const result = rollbackFiles([
63
+ * { name: 'backlog.md', path: '/path/to/backlog.md', content: 'original content' },
64
+ * { name: 'status.md', path: '/path/to/status.md', content: 'original content' },
65
+ * ]);
66
+ *
67
+ * if (!result.success) {
68
+ * console.error('Rollback had errors:', result.errors);
69
+ * }
70
+ */
71
+ export function rollbackFiles(filesToRestore) {
72
+ const result = new RollbackResult();
73
+ for (const file of filesToRestore) {
74
+ try {
75
+ writeFileSync(file.path, file.content, { encoding: 'utf-8' });
76
+ result.addSuccess(file.name);
77
+ }
78
+ catch (err) {
79
+ const message = err instanceof Error ? err.message : String(err);
80
+ result.addError(file.name, file.path, message);
81
+ }
82
+ }
83
+ return result;
84
+ }
85
+ /**
86
+ * Delete multiple files with per-file error tracking.
87
+ *
88
+ * @param {Array<{name: string, path: string}>} filesToDelete - Files to delete
89
+ * @returns {RollbackResult} Result with deleted files and any errors
90
+ */
91
+ export function deleteFiles(filesToDelete) {
92
+ const result = new RollbackResult();
93
+ for (const file of filesToDelete) {
94
+ try {
95
+ unlinkSync(file.path);
96
+ result.addSuccess(file.name);
97
+ }
98
+ catch (err) {
99
+ const message = err instanceof Error ? err.message : String(err);
100
+ result.addError(file.name, file.path, message);
101
+ }
102
+ }
103
+ return result;
104
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Section Headings Constants
3
+ *
4
+ * Centralized section heading defaults for backlog.md and status.md
5
+ * Eliminates magic strings scattered throughout wu-* tools
6
+ *
7
+ * Usage: Use getSectionHeadingsWithDefaults() to get frontmatter-configured
8
+ * headings with sensible fallbacks if frontmatter is missing/malformed
9
+ */
10
+ /**
11
+ * Default section headings (fallbacks when frontmatter is missing)
12
+ * Re-exports from wu-constants.mjs for backwards compatibility
13
+ */
14
+ export declare const DEFAULT_SECTION_HEADINGS: {
15
+ backlog: {
16
+ ready: string;
17
+ in_progress: string;
18
+ blocked: string;
19
+ done: string;
20
+ };
21
+ status: {
22
+ in_progress: string;
23
+ completed: string;
24
+ blocked: string;
25
+ };
26
+ };
27
+ /**
28
+ * Get section headings with frontmatter override + defaults
29
+ *
30
+ * Replaces scattered pattern: headings.done || '## ✅ Done'
31
+ * Centralizes fallback logic for consistent heading resolution
32
+ *
33
+ * @param {object|null} frontmatter - Parsed frontmatter from backlog.md/status.md
34
+ * @param {'backlog'|'status'} docType - Document type
35
+ * @returns {object} Section headings (configured or default)
36
+ */
37
+ export declare function getSectionHeadingsWithDefaults(frontmatter: any, docType?: string): {
38
+ ready: any;
39
+ in_progress: any;
40
+ blocked: any;
41
+ done: any;
42
+ completed: any;
43
+ };
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Section Headings Constants
3
+ *
4
+ * Centralized section heading defaults for backlog.md and status.md
5
+ * Eliminates magic strings scattered throughout wu-* tools
6
+ *
7
+ * Usage: Use getSectionHeadingsWithDefaults() to get frontmatter-configured
8
+ * headings with sensible fallbacks if frontmatter is missing/malformed
9
+ */
10
+ import { getSectionHeadings } from './backlog-parser.js';
11
+ import { BACKLOG_SECTIONS, STATUS_SECTIONS } from './wu-constants.js';
12
+ /**
13
+ * Default section headings (fallbacks when frontmatter is missing)
14
+ * Re-exports from wu-constants.mjs for backwards compatibility
15
+ */
16
+ export const DEFAULT_SECTION_HEADINGS = {
17
+ backlog: {
18
+ ready: BACKLOG_SECTIONS.READY,
19
+ in_progress: BACKLOG_SECTIONS.IN_PROGRESS,
20
+ blocked: BACKLOG_SECTIONS.BLOCKED,
21
+ done: BACKLOG_SECTIONS.DONE,
22
+ },
23
+ status: {
24
+ in_progress: STATUS_SECTIONS.IN_PROGRESS,
25
+ completed: STATUS_SECTIONS.COMPLETED,
26
+ blocked: STATUS_SECTIONS.BLOCKED,
27
+ },
28
+ };
29
+ /**
30
+ * Get section headings with frontmatter override + defaults
31
+ *
32
+ * Replaces scattered pattern: headings.done || '## ✅ Done'
33
+ * Centralizes fallback logic for consistent heading resolution
34
+ *
35
+ * @param {object|null} frontmatter - Parsed frontmatter from backlog.md/status.md
36
+ * @param {'backlog'|'status'} docType - Document type
37
+ * @returns {object} Section headings (configured or default)
38
+ */
39
+ export function getSectionHeadingsWithDefaults(frontmatter, docType = 'backlog') {
40
+ const defaults = DEFAULT_SECTION_HEADINGS[docType];
41
+ const configured = frontmatter ? getSectionHeadings(frontmatter) : {};
42
+ return {
43
+ ready: configured.ready || defaults.ready,
44
+ in_progress: configured.in_progress || defaults.in_progress,
45
+ blocked: configured.blocked || defaults.blocked,
46
+ done: configured.done || defaults.done,
47
+ completed: configured.completed || defaults.completed,
48
+ };
49
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Spawn Escalation Module (WU-1952, WU-1967)
3
+ *
4
+ * WU-1967: Replaced Bug WU creation with memory bus signalling.
5
+ * Signals orchestrator inbox instead of creating human-in-loop Bug WUs.
6
+ *
7
+ * Escalation Flow:
8
+ * 1. recoverStuckSpawn() returns { recovered: false, action: ESCALATED_STUCK }
9
+ * 2. escalateStuckSpawn() signals orchestrator via memory bus
10
+ * 3. Spawn status updated to ESCALATED (prevents duplicate signals)
11
+ * 4. Orchestrator decides: retry (1st), block (2nd), human escalate (3rd+)
12
+ *
13
+ * Library-First Note: This is project-specific spawn escalation code for
14
+ * PatientPath's custom spawn-registry.jsonl and memory bus patterns.
15
+ * No external library exists for this domain-specific agent lifecycle management.
16
+ *
17
+ * @see {@link tools/lib/__tests__/spawn-escalation.test.mjs} - Tests
18
+ * @see {@link tools/lib/spawn-recovery.mjs} - Recovery logic
19
+ * @see {@link tools/lib/mem-signal-core.mjs} - Signal creation
20
+ */
21
+ /**
22
+ * Signal type for spawn failures
23
+ */
24
+ export declare const SPAWN_FAILURE_SIGNAL_TYPE = "spawn_failure";
25
+ /**
26
+ * Severity levels for spawn failure signals
27
+ */
28
+ export declare const SignalSeverity: Readonly<{
29
+ WARNING: "warning";
30
+ ERROR: "error";
31
+ CRITICAL: "critical";
32
+ }>;
33
+ /**
34
+ * Suggested actions for spawn failure signals
35
+ */
36
+ export declare const SuggestedAction: Readonly<{
37
+ RETRY: "retry";
38
+ BLOCK: "block";
39
+ HUMAN_ESCALATE: "human_escalate";
40
+ }>;
41
+ /**
42
+ * Escalates a stuck spawn by signalling the orchestrator.
43
+ *
44
+ * WU-1967: Replaced Bug WU creation with memory bus signalling.
45
+ * Called when recoverStuckSpawn() returns ESCALATED_STUCK.
46
+ * Signals orchestrator inbox with spawn failure context.
47
+ *
48
+ * Escalation levels based on recovery attempts:
49
+ * - 1st attempt: severity=warning, suggested_action=retry
50
+ * - 2nd attempt: severity=error, suggested_action=block
51
+ * - 3rd+ attempt: severity=critical, suggested_action=human_escalate
52
+ *
53
+ * @param {string} spawnId - ID of the stuck spawn
54
+ * @param {Object} options - Options
55
+ * @param {string} options.baseDir - Base directory for .beacon/
56
+ * @param {boolean} [options.dryRun=false] - If true, returns signal without sending
57
+ * @returns {Promise<EscalationResult>} Escalation result with signal details
58
+ *
59
+ * @throws {Error} If spawn not found
60
+ * @throws {Error} If spawn already escalated (duplicate prevention)
61
+ * @throws {Error} If no escalation audit log exists
62
+ *
63
+ * @example
64
+ * // After recoverStuckSpawn returns ESCALATED_STUCK
65
+ * const result = await escalateStuckSpawn('spawn-1234', { baseDir: '/path/to/project' });
66
+ * console.log(`Signal sent: ${result.signalId}, action: ${result.signal.suggested_action}`);
67
+ */
68
+ export interface EscalateStuckSpawnOptions {
69
+ /** Base directory for .beacon/ */
70
+ baseDir?: string;
71
+ /** If true, return spec only without sending signal */
72
+ dryRun?: boolean;
73
+ }
74
+ export declare function escalateStuckSpawn(spawnId: any, options?: EscalateStuckSpawnOptions): Promise<{
75
+ signalId: string;
76
+ signal: {
77
+ type: string;
78
+ severity: "error" | "warning" | "critical";
79
+ spawn_id: any;
80
+ target_wu_id: any;
81
+ parent_wu_id: any;
82
+ lane: any;
83
+ recovery_action: any;
84
+ recovery_attempts: any;
85
+ last_checkpoint: any;
86
+ suggested_action: "retry" | "block" | "human_escalate";
87
+ message: string;
88
+ };
89
+ spawnStatus: "escalated";
90
+ }>;
@@ -0,0 +1,253 @@
1
+ /**
2
+ * Spawn Escalation Module (WU-1952, WU-1967)
3
+ *
4
+ * WU-1967: Replaced Bug WU creation with memory bus signalling.
5
+ * Signals orchestrator inbox instead of creating human-in-loop Bug WUs.
6
+ *
7
+ * Escalation Flow:
8
+ * 1. recoverStuckSpawn() returns { recovered: false, action: ESCALATED_STUCK }
9
+ * 2. escalateStuckSpawn() signals orchestrator via memory bus
10
+ * 3. Spawn status updated to ESCALATED (prevents duplicate signals)
11
+ * 4. Orchestrator decides: retry (1st), block (2nd), human escalate (3rd+)
12
+ *
13
+ * Library-First Note: This is project-specific spawn escalation code for
14
+ * PatientPath's custom spawn-registry.jsonl and memory bus patterns.
15
+ * No external library exists for this domain-specific agent lifecycle management.
16
+ *
17
+ * @see {@link tools/lib/__tests__/spawn-escalation.test.mjs} - Tests
18
+ * @see {@link tools/lib/spawn-recovery.mjs} - Recovery logic
19
+ * @see {@link tools/lib/mem-signal-core.mjs} - Signal creation
20
+ */
21
+ import fs from 'node:fs/promises';
22
+ import path from 'node:path';
23
+ import { SpawnRegistryStore } from './spawn-registry-store.js';
24
+ import { SpawnStatus } from './spawn-registry-schema.js';
25
+ import { RECOVERY_DIR_NAME } from './spawn-recovery.js';
26
+ let createSignal = null;
27
+ try {
28
+ const mod = await import('@lumenflow/memory/signal');
29
+ createSignal = mod.createSignal;
30
+ }
31
+ catch {
32
+ // @lumenflow/memory not available - signal features disabled
33
+ }
34
+ /**
35
+ * Log prefix for spawn-escalation messages
36
+ */
37
+ const LOG_PREFIX = '[spawn-escalation]';
38
+ /**
39
+ * Signal type for spawn failures
40
+ */
41
+ export const SPAWN_FAILURE_SIGNAL_TYPE = 'spawn_failure';
42
+ /**
43
+ * Severity levels for spawn failure signals
44
+ */
45
+ export const SignalSeverity = Object.freeze({
46
+ WARNING: 'warning',
47
+ ERROR: 'error',
48
+ CRITICAL: 'critical',
49
+ });
50
+ /**
51
+ * Suggested actions for spawn failure signals
52
+ */
53
+ export const SuggestedAction = Object.freeze({
54
+ RETRY: 'retry',
55
+ BLOCK: 'block',
56
+ HUMAN_ESCALATE: 'human_escalate',
57
+ });
58
+ /**
59
+ * @typedef {Object} SpawnFailureSignal
60
+ * @property {string} type - Always 'spawn_failure'
61
+ * @property {string} severity - 'warning' | 'error' | 'critical'
62
+ * @property {string} spawn_id - Spawn ID
63
+ * @property {string} target_wu_id - Target WU ID
64
+ * @property {string} parent_wu_id - Parent WU ID (orchestrator)
65
+ * @property {string} lane - Lane name
66
+ * @property {string} recovery_action - Recovery action that triggered escalation
67
+ * @property {number} recovery_attempts - Number of recovery attempts
68
+ * @property {string|null} last_checkpoint - Last checkpoint timestamp
69
+ * @property {string} suggested_action - 'retry' | 'block' | 'human_escalate'
70
+ * @property {string} message - Human-readable message
71
+ */
72
+ /**
73
+ * @typedef {Object} EscalationResult
74
+ * @property {string} signalId - Signal ID (e.g., 'sig-abc12345')
75
+ * @property {SpawnFailureSignal} signal - The signal payload
76
+ * @property {string} spawnStatus - Updated spawn status (ESCALATED)
77
+ */
78
+ /**
79
+ * @typedef {Object} AuditLogEntry
80
+ * @property {string} timestamp - ISO timestamp of recovery action
81
+ * @property {string} spawnId - ID of the spawn being recovered
82
+ * @property {string} action - Recovery action taken
83
+ * @property {string} reason - Explanation of why action was taken
84
+ * @property {Object} context - Additional context
85
+ */
86
+ /**
87
+ * Counts existing escalation attempts for a spawn by reading audit logs.
88
+ *
89
+ * @param {string} baseDir - Base directory
90
+ * @param {string} spawnId - Spawn ID to count attempts for
91
+ * @returns {Promise<number>} Number of previous escalation attempts
92
+ */
93
+ async function countEscalationAttempts(baseDir, spawnId) {
94
+ const recoveryDir = path.join(baseDir, '.beacon', RECOVERY_DIR_NAME);
95
+ try {
96
+ const files = await fs.readdir(recoveryDir);
97
+ const spawnFiles = files.filter((f) => f.startsWith(`${spawnId}-`) && f.endsWith('.json'));
98
+ return spawnFiles.length;
99
+ }
100
+ catch (error) {
101
+ if (error.code === 'ENOENT') {
102
+ return 0;
103
+ }
104
+ throw error;
105
+ }
106
+ }
107
+ /**
108
+ * Determines severity and suggested action based on recovery attempts.
109
+ *
110
+ * @param {number} attempts - Number of recovery attempts
111
+ * @returns {{ severity: string, suggestedAction: string }}
112
+ */
113
+ function determineEscalationLevel(attempts) {
114
+ if (attempts <= 1) {
115
+ return {
116
+ severity: SignalSeverity.WARNING,
117
+ suggestedAction: SuggestedAction.RETRY,
118
+ };
119
+ }
120
+ else if (attempts === 2) {
121
+ return {
122
+ severity: SignalSeverity.ERROR,
123
+ suggestedAction: SuggestedAction.BLOCK,
124
+ };
125
+ }
126
+ else {
127
+ return {
128
+ severity: SignalSeverity.CRITICAL,
129
+ suggestedAction: SuggestedAction.HUMAN_ESCALATE,
130
+ };
131
+ }
132
+ }
133
+ /**
134
+ * Find the most recent escalation audit log for a spawn.
135
+ *
136
+ * @param {string} baseDir - Base directory
137
+ * @param {string} spawnId - Spawn ID to find audit log for
138
+ * @returns {Promise<AuditLogEntry|null>} Audit log entry or null if not found
139
+ */
140
+ async function findEscalationAuditLog(baseDir, spawnId) {
141
+ const recoveryDir = path.join(baseDir, '.beacon', RECOVERY_DIR_NAME);
142
+ try {
143
+ const files = await fs.readdir(recoveryDir);
144
+ // Filter files for this spawn ID, sorted by name (timestamp-based)
145
+ const spawnFiles = files
146
+ .filter((f) => f.startsWith(`${spawnId}-`) && f.endsWith('.json'))
147
+ .sort()
148
+ .reverse(); // Most recent first
149
+ if (spawnFiles.length === 0) {
150
+ return null;
151
+ }
152
+ // Read the most recent audit log
153
+ const auditPath = path.join(recoveryDir, spawnFiles[0]);
154
+ const content = await fs.readFile(auditPath, 'utf-8');
155
+ return JSON.parse(content);
156
+ }
157
+ catch (error) {
158
+ if (error.code === 'ENOENT') {
159
+ return null;
160
+ }
161
+ throw error;
162
+ }
163
+ }
164
+ /**
165
+ * Builds a spawn failure signal payload.
166
+ *
167
+ * @param {Object} spawn - Spawn event data
168
+ * @param {AuditLogEntry} auditLog - Escalation audit log
169
+ * @param {number} attempts - Number of recovery attempts
170
+ * @returns {SpawnFailureSignal} Signal payload
171
+ */
172
+ function buildSpawnFailureSignal(spawn, auditLog, attempts) {
173
+ const { severity, suggestedAction } = determineEscalationLevel(attempts);
174
+ const lastCheckpoint = auditLog.context.lastCheckpoint || null;
175
+ return {
176
+ type: SPAWN_FAILURE_SIGNAL_TYPE,
177
+ severity,
178
+ spawn_id: spawn.id,
179
+ target_wu_id: spawn.targetWuId,
180
+ parent_wu_id: spawn.parentWuId,
181
+ lane: spawn.lane,
182
+ recovery_action: auditLog.action,
183
+ recovery_attempts: attempts,
184
+ last_checkpoint: lastCheckpoint,
185
+ suggested_action: suggestedAction,
186
+ message: `Spawn ${spawn.id} for ${spawn.targetWuId} stuck: ${auditLog.reason}`,
187
+ };
188
+ }
189
+ export async function escalateStuckSpawn(spawnId, options = {}) {
190
+ const { baseDir = process.cwd(), dryRun = false } = options;
191
+ const registryDir = path.join(baseDir, '.beacon', 'state');
192
+ // Load spawn registry
193
+ const store = new SpawnRegistryStore(registryDir);
194
+ try {
195
+ await store.load();
196
+ }
197
+ catch {
198
+ throw new Error(`Spawn ${spawnId} not found: registry unavailable`);
199
+ }
200
+ // Find the spawn
201
+ const spawn = store.getById(spawnId);
202
+ if (!spawn) {
203
+ throw new Error(`Spawn ${spawnId} not found in registry`);
204
+ }
205
+ // Check if signal module is available
206
+ if (!createSignal) {
207
+ throw new Error('Signal module (@lumenflow/memory) not available - cannot escalate');
208
+ }
209
+ // WU-1967: Check if already escalated (prevents duplicate signals)
210
+ if (spawn.status === SpawnStatus.ESCALATED) {
211
+ throw new Error(`Spawn ${spawnId} already escalated`);
212
+ }
213
+ // Find escalation audit log
214
+ const auditLog = await findEscalationAuditLog(baseDir, spawnId);
215
+ if (!auditLog) {
216
+ throw new Error(`No escalation audit log found for spawn ${spawnId}`);
217
+ }
218
+ // Count previous escalation attempts
219
+ const attempts = await countEscalationAttempts(baseDir, spawnId);
220
+ // Build signal payload
221
+ const signalPayload = buildSpawnFailureSignal(spawn, auditLog, attempts);
222
+ if (dryRun) {
223
+ console.log(`${LOG_PREFIX} [dry-run] Would signal orchestrator`);
224
+ console.log(`${LOG_PREFIX} [dry-run] Severity: ${signalPayload.severity}`);
225
+ console.log(`${LOG_PREFIX} [dry-run] Suggested action: ${signalPayload.suggested_action}`);
226
+ console.log(`${LOG_PREFIX} [dry-run] Message: ${signalPayload.message}`);
227
+ return {
228
+ signalId: 'sig-dry-run',
229
+ signal: signalPayload,
230
+ spawnStatus: SpawnStatus.ESCALATED,
231
+ };
232
+ }
233
+ // WU-1967: Send signal to orchestrator inbox
234
+ console.log(`${LOG_PREFIX} Signalling orchestrator for spawn ${spawnId}`);
235
+ console.log(`${LOG_PREFIX} Target WU: ${spawn.targetWuId}`);
236
+ console.log(`${LOG_PREFIX} Severity: ${signalPayload.severity}`);
237
+ console.log(`${LOG_PREFIX} Suggested action: ${signalPayload.suggested_action}`);
238
+ // Create signal with structured message (JSON payload in message field)
239
+ const signalResult = await createSignal(baseDir, {
240
+ message: JSON.stringify(signalPayload),
241
+ wuId: spawn.parentWuId, // Signal targets the orchestrator (parent WU)
242
+ lane: spawn.lane,
243
+ });
244
+ // Update spawn status to ESCALATED (prevents duplicate signals)
245
+ await store.updateStatus(spawnId, SpawnStatus.ESCALATED);
246
+ console.log(`${LOG_PREFIX} Signal sent: ${signalResult.signal.id}`);
247
+ console.log(`${LOG_PREFIX} Spawn ${spawnId} status updated to ESCALATED`);
248
+ return {
249
+ signalId: signalResult.signal.id,
250
+ signal: signalPayload,
251
+ spawnStatus: SpawnStatus.ESCALATED,
252
+ };
253
+ }