@lumenflow/core 2.2.2 → 2.3.2

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 (213) hide show
  1. package/dist/active-wu-detector.d.ts +1 -1
  2. package/dist/active-wu-detector.js +1 -1
  3. package/dist/arg-parser.js +51 -18
  4. package/dist/backlog-generator.d.ts +4 -4
  5. package/dist/backlog-generator.js +4 -4
  6. package/dist/backlog-sync-validator.js +1 -1
  7. package/dist/cleanup-lock.d.ts +9 -2
  8. package/dist/cleanup-lock.js +17 -7
  9. package/dist/code-path-validator.d.ts +3 -3
  10. package/dist/code-path-validator.js +3 -3
  11. package/dist/compliance-parser.d.ts +1 -1
  12. package/dist/compliance-parser.js +1 -1
  13. package/dist/constants/backlog-patterns.d.ts +1 -1
  14. package/dist/constants/backlog-patterns.js +1 -1
  15. package/dist/constants/dora-constants.d.ts +1 -1
  16. package/dist/constants/dora-constants.js +1 -1
  17. package/dist/constants/gate-constants.d.ts +1 -1
  18. package/dist/constants/gate-constants.js +1 -1
  19. package/dist/constants/linter-constants.d.ts +1 -1
  20. package/dist/constants/linter-constants.js +1 -1
  21. package/dist/constants/tokenizer-constants.d.ts +1 -1
  22. package/dist/constants/tokenizer-constants.js +1 -1
  23. package/dist/context/location-resolver.js +2 -1
  24. package/dist/context-validation-integration.d.ts +1 -0
  25. package/dist/core/scope-checker.d.ts +3 -3
  26. package/dist/core/scope-checker.js +3 -3
  27. package/dist/core/tool-runner.d.ts +5 -5
  28. package/dist/core/tool-runner.js +5 -5
  29. package/dist/core/tool.constants.d.ts +1 -1
  30. package/dist/core/tool.constants.js +1 -1
  31. package/dist/core/tool.schemas.d.ts +2 -2
  32. package/dist/core/tool.schemas.js +1 -1
  33. package/dist/core/worktree-guard.d.ts +1 -1
  34. package/dist/core/worktree-guard.js +1 -1
  35. package/dist/coverage-gate.d.ts +12 -3
  36. package/dist/coverage-gate.js +15 -8
  37. package/dist/date-utils.d.ts +4 -4
  38. package/dist/date-utils.js +4 -4
  39. package/dist/dependency-graph.d.ts +6 -0
  40. package/dist/dependency-graph.js +43 -2
  41. package/dist/dependency-guard.d.ts +2 -2
  42. package/dist/dependency-guard.js +3 -3
  43. package/dist/dependency-validator.d.ts +4 -4
  44. package/dist/dependency-validator.js +4 -7
  45. package/dist/domain/orchestration.constants.d.ts +31 -10
  46. package/dist/domain/orchestration.constants.js +45 -16
  47. package/dist/domain/orchestration.schemas.d.ts +54 -28
  48. package/dist/domain/orchestration.schemas.js +2 -2
  49. package/dist/domain/orchestration.types.d.ts +2 -2
  50. package/dist/domain/orchestration.types.js +2 -2
  51. package/dist/error-handler.d.ts +10 -10
  52. package/dist/error-handler.js +10 -10
  53. package/dist/file-classifiers.d.ts +6 -6
  54. package/dist/file-classifiers.js +6 -6
  55. package/dist/gates-config.d.ts +74 -0
  56. package/dist/gates-config.js +209 -2
  57. package/dist/git-adapter.d.ts +11 -11
  58. package/dist/git-adapter.js +11 -11
  59. package/dist/git-context-extractor.d.ts +112 -0
  60. package/dist/git-context-extractor.js +559 -0
  61. package/dist/hardcoded-strings.d.ts +1 -1
  62. package/dist/hardcoded-strings.js +1 -1
  63. package/dist/incremental-lint.d.ts +1 -1
  64. package/dist/incremental-lint.js +2 -2
  65. package/dist/incremental-test.d.ts +1 -1
  66. package/dist/incremental-test.js +1 -1
  67. package/dist/index.d.ts +13 -0
  68. package/dist/index.js +25 -0
  69. package/dist/invariants/check-automated-tests.d.ts +2 -2
  70. package/dist/invariants/check-automated-tests.js +3 -3
  71. package/dist/lane-checker.d.ts +28 -7
  72. package/dist/lane-checker.js +316 -159
  73. package/dist/lane-suggest-prompt.d.ts +108 -0
  74. package/dist/lane-suggest-prompt.js +359 -0
  75. package/dist/lane-validator.d.ts +3 -3
  76. package/dist/lane-validator.js +3 -3
  77. package/dist/logs-lib.d.ts +1 -1
  78. package/dist/logs-lib.js +1 -1
  79. package/dist/lumenflow-config-schema.d.ts +162 -0
  80. package/dist/lumenflow-config-schema.js +180 -0
  81. package/dist/manual-test-validator.d.ts +2 -2
  82. package/dist/manual-test-validator.js +3 -3
  83. package/dist/merge-lock.d.ts +8 -1
  84. package/dist/merge-lock.js +16 -7
  85. package/dist/micro-worktree.d.ts +81 -13
  86. package/dist/micro-worktree.js +98 -17
  87. package/dist/migration-deployer.d.ts +1 -1
  88. package/dist/migration-deployer.js +1 -1
  89. package/dist/orchestration-advisory-loader.d.ts +2 -2
  90. package/dist/orchestration-advisory-loader.js +10 -6
  91. package/dist/orchestration-advisory.d.ts +3 -3
  92. package/dist/orchestration-advisory.js +4 -4
  93. package/dist/orchestration-di.d.ts +4 -4
  94. package/dist/orchestration-di.js +4 -4
  95. package/dist/orchestration-rules.d.ts +4 -4
  96. package/dist/orchestration-rules.js +18 -10
  97. package/dist/orphan-detector.d.ts +3 -3
  98. package/dist/orphan-detector.js +3 -3
  99. package/dist/patrol-loop.d.ts +170 -0
  100. package/dist/patrol-loop.js +186 -0
  101. package/dist/process-detector.d.ts +5 -5
  102. package/dist/process-detector.js +5 -5
  103. package/dist/rebase-artifact-cleanup.d.ts +3 -3
  104. package/dist/rebase-artifact-cleanup.js +3 -3
  105. package/dist/resolve-policy.d.ts +195 -0
  106. package/dist/resolve-policy.js +203 -0
  107. package/dist/risk-detector.d.ts +2 -2
  108. package/dist/risk-detector.js +2 -2
  109. package/dist/rollback-utils.d.ts +1 -1
  110. package/dist/rollback-utils.js +1 -1
  111. package/dist/section-headings.d.ts +1 -1
  112. package/dist/section-headings.js +1 -1
  113. package/dist/spawn-escalation.d.ts +4 -4
  114. package/dist/spawn-escalation.js +3 -3
  115. package/dist/spawn-monitor.d.ts +4 -4
  116. package/dist/spawn-monitor.js +4 -4
  117. package/dist/spawn-recovery.d.ts +3 -3
  118. package/dist/spawn-recovery.js +3 -3
  119. package/dist/spawn-registry-schema.d.ts +2 -2
  120. package/dist/spawn-registry-schema.js +2 -2
  121. package/dist/spawn-registry-store.d.ts +2 -2
  122. package/dist/spawn-registry-store.js +2 -2
  123. package/dist/spawn-strategy.d.ts +17 -11
  124. package/dist/spawn-strategy.js +47 -44
  125. package/dist/spawn-tree.d.ts +3 -3
  126. package/dist/spawn-tree.js +3 -3
  127. package/dist/state-cleanup-core.d.ts +205 -0
  128. package/dist/state-cleanup-core.js +240 -0
  129. package/dist/state-doctor-core.d.ts +168 -0
  130. package/dist/state-doctor-core.js +251 -0
  131. package/dist/stream-error-handler.d.ts +67 -0
  132. package/dist/stream-error-handler.js +94 -0
  133. package/dist/telemetry.d.ts +1 -1
  134. package/dist/telemetry.js +1 -1
  135. package/dist/template-loader.d.ts +162 -0
  136. package/dist/template-loader.js +372 -0
  137. package/dist/test-baseline.d.ts +176 -0
  138. package/dist/test-baseline.js +282 -0
  139. package/dist/usecases/get-suggestions.usecase.d.ts +1 -1
  140. package/dist/validation/command-registry.js +37 -0
  141. package/dist/validators/backlog-sync.js +4 -2
  142. package/dist/worktree-scanner.d.ts +1 -1
  143. package/dist/worktree-scanner.js +1 -1
  144. package/dist/worktree-symlink.d.ts +3 -3
  145. package/dist/worktree-symlink.js +3 -3
  146. package/dist/wu-backlog-updater.d.ts +1 -1
  147. package/dist/wu-backlog-updater.js +1 -1
  148. package/dist/wu-claim-helpers.d.ts +1 -1
  149. package/dist/wu-claim-helpers.js +1 -1
  150. package/dist/wu-claim-resume.d.ts +1 -1
  151. package/dist/wu-claim-resume.js +1 -1
  152. package/dist/wu-consistency-checker.d.ts +1 -1
  153. package/dist/wu-consistency-checker.js +17 -11
  154. package/dist/wu-constants.d.ts +73 -21
  155. package/dist/wu-constants.js +65 -22
  156. package/dist/wu-done-branch-only.d.ts +1 -1
  157. package/dist/wu-done-branch-only.js +1 -1
  158. package/dist/wu-done-docs-generate.d.ts +1 -1
  159. package/dist/wu-done-docs-generate.js +1 -1
  160. package/dist/wu-done-messages.d.ts +2 -2
  161. package/dist/wu-done-messages.js +2 -2
  162. package/dist/wu-done-metadata.d.ts +3 -3
  163. package/dist/wu-done-metadata.js +3 -3
  164. package/dist/wu-done-pr.d.ts +1 -1
  165. package/dist/wu-done-pr.js +4 -2
  166. package/dist/wu-done-preflight.d.ts +8 -0
  167. package/dist/wu-done-preflight.js +18 -2
  168. package/dist/wu-done-ui.d.ts +3 -3
  169. package/dist/wu-done-ui.js +3 -3
  170. package/dist/wu-done-validation.d.ts +30 -0
  171. package/dist/wu-done-validation.js +106 -1
  172. package/dist/wu-done-worktree.d.ts +1 -1
  173. package/dist/wu-done-worktree.js +11 -1
  174. package/dist/wu-events-cleanup.d.ts +148 -0
  175. package/dist/wu-events-cleanup.js +401 -0
  176. package/dist/wu-helpers.d.ts +2 -2
  177. package/dist/wu-helpers.js +2 -2
  178. package/dist/wu-id-generator.d.ts +58 -0
  179. package/dist/wu-id-generator.js +103 -0
  180. package/dist/wu-lint.js +1 -1
  181. package/dist/wu-preflight-validators.d.ts +13 -1
  182. package/dist/wu-preflight-validators.js +56 -1
  183. package/dist/wu-recovery.d.ts +2 -2
  184. package/dist/wu-recovery.js +4 -4
  185. package/dist/wu-repair-core.d.ts +5 -5
  186. package/dist/wu-repair-core.js +6 -6
  187. package/dist/wu-schema-normalization.d.ts +1 -1
  188. package/dist/wu-schema-normalization.js +1 -1
  189. package/dist/wu-schema.d.ts +7 -7
  190. package/dist/wu-schema.js +8 -8
  191. package/dist/wu-spawn-context.d.ts +87 -0
  192. package/dist/wu-spawn-context.js +175 -0
  193. package/dist/wu-spawn-helpers.d.ts +1 -1
  194. package/dist/wu-spawn-helpers.js +1 -1
  195. package/dist/wu-spawn.d.ts +177 -4
  196. package/dist/wu-spawn.js +694 -72
  197. package/dist/wu-state-schema.d.ts +1 -1
  198. package/dist/wu-state-schema.js +1 -1
  199. package/dist/wu-state-store.d.ts +3 -3
  200. package/dist/wu-state-store.js +3 -3
  201. package/dist/wu-status-transition.d.ts +1 -1
  202. package/dist/wu-status-transition.js +1 -1
  203. package/dist/wu-status-updater.d.ts +3 -3
  204. package/dist/wu-status-updater.js +3 -3
  205. package/dist/wu-validation-constants.d.ts +2 -2
  206. package/dist/wu-validation-constants.js +2 -2
  207. package/dist/wu-validation.d.ts +3 -3
  208. package/dist/wu-validation.js +3 -3
  209. package/dist/wu-yaml-fixer.d.ts +2 -2
  210. package/dist/wu-yaml-fixer.js +3 -3
  211. package/dist/wu-yaml.d.ts +23 -0
  212. package/dist/wu-yaml.js +76 -2
  213. package/package.json +5 -2
@@ -0,0 +1,359 @@
1
+ /**
2
+ * Lane Suggestion Prompt Module (WU-1189)
3
+ *
4
+ * Generates prompts for LLM-driven lane suggestions based on codebase context.
5
+ * This module gathers project context and generates structured prompts for
6
+ * the LLM to analyze and suggest appropriate lane definitions.
7
+ *
8
+ * Design decisions:
9
+ * - Uses LLM for semantic understanding (not hardcoded heuristics)
10
+ * - Gathers context from docs, structure, and existing config
11
+ * - Returns structured JSON for easy parsing
12
+ */
13
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
14
+ import path from 'node:path';
15
+ import YAML from 'yaml';
16
+ import { z } from 'zod';
17
+ /**
18
+ * Schema for a single lane suggestion from the LLM
19
+ */
20
+ export const LaneSuggestionSchema = z.object({
21
+ lane: z.string().describe('Lane name in "Parent: Sublane" format'),
22
+ description: z.string().describe('Brief description of what this lane covers'),
23
+ rationale: z.string().describe('Why this lane was suggested based on the codebase'),
24
+ code_paths: z.array(z.string()).describe('Glob patterns for files in this lane'),
25
+ keywords: z.array(z.string()).describe('Keywords that indicate work belongs to this lane'),
26
+ });
27
+ /**
28
+ * Schema for the complete LLM response
29
+ */
30
+ export const LaneSuggestResponseSchema = z.object({
31
+ suggestions: z.array(LaneSuggestionSchema),
32
+ });
33
+ /**
34
+ * Read directory structure from project root
35
+ */
36
+ function readDirectoryStructure(projectRoot) {
37
+ try {
38
+ const entries = readdirSync(projectRoot, { withFileTypes: true });
39
+ return entries
40
+ .filter((e) => e.isDirectory())
41
+ .map((e) => e.name)
42
+ .filter((name) => !name.startsWith('.') && name !== 'node_modules');
43
+ }
44
+ catch {
45
+ return [];
46
+ }
47
+ }
48
+ /**
49
+ * Read README.md content
50
+ */
51
+ function readReadme(projectRoot) {
52
+ const readmePath = path.join(projectRoot, 'README.md');
53
+ if (!existsSync(readmePath))
54
+ return null;
55
+ try {
56
+ return readFileSync(readmePath, 'utf-8').slice(0, 2000);
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ }
62
+ /**
63
+ * Read package.json and detect monorepo
64
+ */
65
+ function readPackageJson(projectRoot) {
66
+ const packageJsonPath = path.join(projectRoot, 'package.json');
67
+ if (!existsSync(packageJsonPath)) {
68
+ return { packageJson: null, isMonorepo: false };
69
+ }
70
+ try {
71
+ const content = readFileSync(packageJsonPath, 'utf-8');
72
+ const pkg = JSON.parse(content);
73
+ const hasWorkspaces = !!pkg.workspaces;
74
+ const hasPnpmWorkspace = existsSync(path.join(projectRoot, 'pnpm-workspace.yaml'));
75
+ return {
76
+ packageJson: {
77
+ name: pkg.name,
78
+ description: pkg.description,
79
+ workspaces: pkg.workspaces,
80
+ },
81
+ isMonorepo: hasWorkspaces || hasPnpmWorkspace,
82
+ };
83
+ }
84
+ catch {
85
+ return { packageJson: null, isMonorepo: false };
86
+ }
87
+ }
88
+ /**
89
+ * Gather package names from packages/ directory
90
+ */
91
+ function gatherPackageNames(projectRoot) {
92
+ const packagesDir = path.join(projectRoot, 'packages');
93
+ if (!existsSync(packagesDir))
94
+ return [];
95
+ try {
96
+ const packageDirs = readdirSync(packagesDir, { withFileTypes: true })
97
+ .filter((e) => e.isDirectory())
98
+ .map((e) => e.name);
99
+ const names = [];
100
+ for (const pkgDir of packageDirs) {
101
+ const pkgPath = path.join(packagesDir, pkgDir);
102
+ if (pkgDir.startsWith('@')) {
103
+ // Scoped packages
104
+ const scopePackages = readdirSync(pkgPath, { withFileTypes: true })
105
+ .filter((e) => e.isDirectory())
106
+ .map((e) => `${pkgDir}/${e.name}`);
107
+ names.push(...scopePackages);
108
+ }
109
+ else if (existsSync(path.join(pkgPath, 'package.json'))) {
110
+ names.push(pkgDir);
111
+ }
112
+ }
113
+ return names;
114
+ }
115
+ catch {
116
+ return [];
117
+ }
118
+ }
119
+ /**
120
+ * Read existing lane configuration
121
+ */
122
+ function readExistingLanes(projectRoot) {
123
+ const laneConfigPath = path.join(projectRoot, '.lumenflow.lane-inference.yaml');
124
+ if (!existsSync(laneConfigPath))
125
+ return [];
126
+ try {
127
+ const content = readFileSync(laneConfigPath, 'utf-8');
128
+ const config = YAML.parse(content);
129
+ const lanes = [];
130
+ for (const [parent, sublanes] of Object.entries(config)) {
131
+ if (typeof sublanes === 'object' && sublanes !== null) {
132
+ for (const sublane of Object.keys(sublanes)) {
133
+ lanes.push(`${parent}: ${sublane}`);
134
+ }
135
+ }
136
+ }
137
+ return lanes;
138
+ }
139
+ catch {
140
+ return [];
141
+ }
142
+ }
143
+ /**
144
+ * Gather project context from the filesystem
145
+ */
146
+ export function gatherProjectContext(projectRoot) {
147
+ const directoryStructure = readDirectoryStructure(projectRoot);
148
+ const { packageJson, isMonorepo: isMonorepoPkg } = readPackageJson(projectRoot);
149
+ const hasPnpmWorkspace = existsSync(path.join(projectRoot, 'pnpm-workspace.yaml'));
150
+ const hasPackagesDir = directoryStructure.includes('packages');
151
+ return {
152
+ directoryStructure,
153
+ hasDocsDir: directoryStructure.includes('docs'),
154
+ hasAppsDir: directoryStructure.includes('apps'),
155
+ hasPackagesDir,
156
+ readme: readReadme(projectRoot),
157
+ packageJson,
158
+ isMonorepo: isMonorepoPkg || hasPnpmWorkspace,
159
+ packageNames: hasPackagesDir ? gatherPackageNames(projectRoot) : [],
160
+ existingLanes: readExistingLanes(projectRoot),
161
+ };
162
+ }
163
+ /**
164
+ * Generate the system prompt for lane suggestion
165
+ */
166
+ export function generateSystemPrompt() {
167
+ return `You are an expert software architect helping configure a LumenFlow workflow project.
168
+
169
+ LumenFlow uses "lanes" to organize work. Each lane has:
170
+ - A name in "Parent: Sublane" format (e.g., "Framework: Core", "Operations: CI/CD")
171
+ - code_paths: Glob patterns for files that belong to this lane
172
+ - keywords: Terms that indicate work belongs to this lane
173
+ - description: Brief explanation of what the lane covers
174
+
175
+ Lane naming conventions:
176
+ - Parent categories: Framework, Operations, Content, Experience, Intelligence, Quality
177
+ - Sublane names should be specific and descriptive
178
+ - Use "/" for sublanes that are further subdivisions (e.g., "Operations: CI/CD")
179
+
180
+ Your task is to analyze the provided project context and suggest appropriate lane definitions.
181
+
182
+ Respond with a JSON object containing an array of lane suggestions. Each suggestion must include:
183
+ - lane: The lane name in "Parent: Sublane" format
184
+ - description: Brief description of what this lane covers
185
+ - rationale: Why you're suggesting this lane based on the project structure
186
+ - code_paths: Array of glob patterns for files in this lane
187
+ - keywords: Array of keywords that indicate work belongs to this lane
188
+
189
+ Example response:
190
+ {
191
+ "suggestions": [
192
+ {
193
+ "lane": "Framework: Core",
194
+ "description": "Core library with shared utilities and base functionality",
195
+ "rationale": "Found packages/core with TypeScript source files and utility modules",
196
+ "code_paths": ["packages/core/**"],
197
+ "keywords": ["core", "utilities", "shared", "base"]
198
+ }
199
+ ]
200
+ }`;
201
+ }
202
+ /**
203
+ * Generate the user prompt with project context
204
+ */
205
+ export function generateUserPrompt(context) {
206
+ const sections = [];
207
+ sections.push('# Project Analysis Request\n');
208
+ sections.push('Please analyze this project structure and suggest appropriate LumenFlow lanes.\n');
209
+ // Project type
210
+ sections.push(`## Project Type`);
211
+ sections.push(`- Monorepo: ${context.isMonorepo ? 'Yes' : 'No'}`);
212
+ sections.push(`- Has packages/: ${context.hasPackagesDir ? 'Yes' : 'No'}`);
213
+ sections.push(`- Has apps/: ${context.hasAppsDir ? 'Yes' : 'No'}`);
214
+ sections.push(`- Has docs/: ${context.hasDocsDir ? 'Yes' : 'No'}`);
215
+ sections.push('');
216
+ // Directory structure
217
+ if (context.directoryStructure.length > 0) {
218
+ sections.push('## Top-Level Directories');
219
+ sections.push(context.directoryStructure.map((d) => `- ${d}/`).join('\n'));
220
+ sections.push('');
221
+ }
222
+ // Package names
223
+ if (context.packageNames.length > 0) {
224
+ sections.push('## Packages Found');
225
+ sections.push(context.packageNames.map((p) => `- ${p}`).join('\n'));
226
+ sections.push('');
227
+ }
228
+ // Package.json info
229
+ if (context.packageJson) {
230
+ sections.push('## Package Info');
231
+ if (context.packageJson.name) {
232
+ sections.push(`- Name: ${context.packageJson.name}`);
233
+ }
234
+ if (context.packageJson.description) {
235
+ sections.push(`- Description: ${context.packageJson.description}`);
236
+ }
237
+ sections.push('');
238
+ }
239
+ // README excerpt
240
+ if (context.readme) {
241
+ sections.push('## README Excerpt');
242
+ sections.push('```');
243
+ sections.push(context.readme.slice(0, 1000));
244
+ sections.push('```');
245
+ sections.push('');
246
+ }
247
+ // Existing lanes
248
+ if (context.existingLanes.length > 0) {
249
+ sections.push('## Existing Lanes (for reference)');
250
+ sections.push('The project already has these lanes configured:');
251
+ sections.push(context.existingLanes.map((l) => `- ${l}`).join('\n'));
252
+ sections.push('');
253
+ sections.push('Consider these when making suggestions to maintain consistency.');
254
+ sections.push('');
255
+ }
256
+ sections.push('## Instructions');
257
+ sections.push('Based on this context, suggest lanes that would help organize work on this project.');
258
+ sections.push('Consider:');
259
+ sections.push('- The types of packages/modules present');
260
+ sections.push('- Common development patterns for this project type');
261
+ sections.push('- Standard lanes for documentation, CI/CD, and operations');
262
+ sections.push('');
263
+ sections.push('Respond with JSON only, no markdown code fences or explanation.');
264
+ return sections.join('\n');
265
+ }
266
+ /**
267
+ * Parse and validate LLM response
268
+ */
269
+ export function parseLLMResponse(response) {
270
+ // Try to extract JSON from response (LLMs sometimes add markdown code fences)
271
+ let jsonStr = response.trim();
272
+ // Remove markdown code fences if present
273
+ if (jsonStr.startsWith('```json')) {
274
+ jsonStr = jsonStr.slice(7);
275
+ }
276
+ else if (jsonStr.startsWith('```')) {
277
+ jsonStr = jsonStr.slice(3);
278
+ }
279
+ if (jsonStr.endsWith('```')) {
280
+ jsonStr = jsonStr.slice(0, -3);
281
+ }
282
+ jsonStr = jsonStr.trim();
283
+ // Parse JSON
284
+ const parsed = JSON.parse(jsonStr);
285
+ // Validate with schema
286
+ return LaneSuggestResponseSchema.parse(parsed);
287
+ }
288
+ /**
289
+ * Validate that a lane name follows the "Parent: Sublane" format
290
+ */
291
+ export function isValidLaneFormat(lane) {
292
+ // Format: "Parent: Sublane" where both start with uppercase
293
+ return /^[A-Z][a-zA-Z]+: [A-Z][a-zA-Z/]+$/.test(lane);
294
+ }
295
+ /**
296
+ * Generate a dry-run preview of what would be sent to the LLM
297
+ */
298
+ export function generateDryRunPreview(projectRoot) {
299
+ const context = gatherProjectContext(projectRoot);
300
+ const systemPrompt = generateSystemPrompt();
301
+ const userPrompt = generateUserPrompt(context);
302
+ return {
303
+ context,
304
+ systemPrompt,
305
+ userPrompt,
306
+ };
307
+ }
308
+ /**
309
+ * Get default lane suggestions for a minimal project
310
+ * Used when LLM is not available or for dry-run
311
+ */
312
+ export function getDefaultSuggestions(context) {
313
+ const suggestions = [];
314
+ // Always suggest documentation lane if docs exist
315
+ if (context.hasDocsDir) {
316
+ suggestions.push({
317
+ lane: 'Content: Documentation',
318
+ description: 'Project documentation and guides',
319
+ rationale: 'Found docs/ directory',
320
+ code_paths: ['docs/**', 'README.md', '*.md'],
321
+ keywords: ['docs', 'documentation', 'readme', 'guide'],
322
+ });
323
+ }
324
+ // Suggest operations lane for CI/CD
325
+ if (context.directoryStructure.some((d) => d === '.github' || d === '.gitlab-ci')) {
326
+ suggestions.push({
327
+ lane: 'Operations: CI/CD',
328
+ description: 'Continuous integration and deployment',
329
+ rationale: 'Found CI/CD configuration directory',
330
+ code_paths: ['.github/**', '.gitlab-ci.yml'],
331
+ keywords: ['ci', 'cd', 'workflow', 'pipeline', 'actions'],
332
+ });
333
+ }
334
+ // For monorepos, suggest lanes based on package names
335
+ if (context.isMonorepo && context.packageNames.length > 0) {
336
+ for (const pkg of context.packageNames) {
337
+ const pkgName = pkg.split('/').pop() || pkg;
338
+ const capitalizedName = pkgName.charAt(0).toUpperCase() + pkgName.slice(1);
339
+ suggestions.push({
340
+ lane: `Framework: ${capitalizedName}`,
341
+ description: `${capitalizedName} package functionality`,
342
+ rationale: `Found package: ${pkg}`,
343
+ code_paths: [`packages/${pkg}/**`],
344
+ keywords: [pkgName.toLowerCase()],
345
+ });
346
+ }
347
+ }
348
+ // Fallback: suggest a core development lane
349
+ if (suggestions.length === 0) {
350
+ suggestions.push({
351
+ lane: 'Development: Core',
352
+ description: 'Main application code',
353
+ rationale: 'Default lane for project source code',
354
+ code_paths: ['src/**', 'lib/**'],
355
+ keywords: ['source', 'core', 'main'],
356
+ });
357
+ }
358
+ return suggestions;
359
+ }
@@ -5,13 +5,13 @@
5
5
  * Validates that a WU's code_paths are consistent with its assigned lane.
6
6
  * This is an advisory validation - it warns but never blocks wu:claim or wu:done.
7
7
  *
8
- * Uses LANE_PATH_PATTERNS from wu-constants.mjs to define which paths
8
+ * Uses LANE_PATH_PATTERNS from wu-constants.ts to define which paths
9
9
  * are discouraged for each lane parent.
10
10
  *
11
11
  * Part of INIT-002: Workflow Integrity initiative.
12
12
  *
13
- * @see {@link wu-constants.mjs} - LANE_PATH_PATTERNS definition
14
- * @see {@link lane-checker.mjs} - extractParent for lane parsing
13
+ * @see {@link wu-constants.ts} - LANE_PATH_PATTERNS definition
14
+ * @see {@link lane-checker.ts} - extractParent for lane parsing
15
15
  */
16
16
  /**
17
17
  * @typedef {object} LaneValidationResult
@@ -5,13 +5,13 @@
5
5
  * Validates that a WU's code_paths are consistent with its assigned lane.
6
6
  * This is an advisory validation - it warns but never blocks wu:claim or wu:done.
7
7
  *
8
- * Uses LANE_PATH_PATTERNS from wu-constants.mjs to define which paths
8
+ * Uses LANE_PATH_PATTERNS from wu-constants.ts to define which paths
9
9
  * are discouraged for each lane parent.
10
10
  *
11
11
  * Part of INIT-002: Workflow Integrity initiative.
12
12
  *
13
- * @see {@link wu-constants.mjs} - LANE_PATH_PATTERNS definition
14
- * @see {@link lane-checker.mjs} - extractParent for lane parsing
13
+ * @see {@link wu-constants.ts} - LANE_PATH_PATTERNS definition
14
+ * @see {@link lane-checker.ts} - extractParent for lane parsing
15
15
  */
16
16
  import micromatch from 'micromatch';
17
17
  import { extractParent } from './lane-checker.js';
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * LIBRARY-FIRST: No general-purpose library exists for project-specific log
12
12
  * aggregation across custom log locations. Uses native JSON.parse like existing
13
- * tail-logs.mjs in the codebase.
13
+ * tail-logs.ts in the codebase.
14
14
  *
15
15
  * @see docs/02-technical/standards/logging.md
16
16
  */
package/dist/logs-lib.js CHANGED
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * LIBRARY-FIRST: No general-purpose library exists for project-specific log
12
12
  * aggregation across custom log locations. Uses native JSON.parse like existing
13
- * tail-logs.mjs in the codebase.
13
+ * tail-logs.ts in the codebase.
14
14
  *
15
15
  * @see docs/02-technical/standards/logging.md
16
16
  */
@@ -7,6 +7,16 @@
7
7
  * @module lumenflow-config-schema
8
8
  */
9
9
  import { z } from 'zod';
10
+ /**
11
+ * Event archival configuration (WU-1207)
12
+ *
13
+ * Configures archival of old WU events from .lumenflow/state/wu-events.jsonl
14
+ * to .lumenflow/archive/wu-events-YYYY-MM.jsonl to prevent unbounded growth.
15
+ */
16
+ export declare const EventArchivalConfigSchema: z.ZodObject<{
17
+ archiveAfter: z.ZodDefault<z.ZodNumber>;
18
+ keepArchives: z.ZodDefault<z.ZodBoolean>;
19
+ }, z.core.$strip>;
10
20
  /**
11
21
  * Directory paths configuration
12
22
  */
@@ -32,6 +42,7 @@ export declare const DirectoriesSchema: z.ZodObject<{
32
42
  export declare const BeaconPathsSchema: z.ZodObject<{
33
43
  base: z.ZodDefault<z.ZodString>;
34
44
  stateDir: z.ZodDefault<z.ZodString>;
45
+ archiveDir: z.ZodDefault<z.ZodString>;
35
46
  stampsDir: z.ZodDefault<z.ZodString>;
36
47
  mergeLock: z.ZodDefault<z.ZodString>;
37
48
  telemetry: z.ZodDefault<z.ZodString>;
@@ -39,6 +50,10 @@ export declare const BeaconPathsSchema: z.ZodObject<{
39
50
  sessions: z.ZodDefault<z.ZodString>;
40
51
  incidents: z.ZodDefault<z.ZodString>;
41
52
  commandsLog: z.ZodDefault<z.ZodString>;
53
+ eventArchival: z.ZodDefault<z.ZodObject<{
54
+ archiveAfter: z.ZodDefault<z.ZodNumber>;
55
+ keepArchives: z.ZodDefault<z.ZodBoolean>;
56
+ }, z.core.$strip>>;
42
57
  }, z.core.$strip>;
43
58
  /**
44
59
  * Git configuration
@@ -110,6 +125,35 @@ export declare const GatesConfigSchema: z.ZodObject<{
110
125
  }, z.core.$strip>]>>;
111
126
  }, z.core.$strip>>;
112
127
  }, z.core.$strip>;
128
+ /**
129
+ * WU-1203: Progress signals configuration for sub-agent coordination
130
+ *
131
+ * When enabled, spawn prompts will include mandatory progress signal directives
132
+ * at configurable triggers (milestone completion, tests pass, before gates, when blocked).
133
+ * Frequency-based signals (every N tool calls) also supported.
134
+ *
135
+ * Addresses sub-agent coordination needs without unnecessary token waste.
136
+ */
137
+ export declare const ProgressSignalsConfigSchema: z.ZodObject<{
138
+ enabled: z.ZodDefault<z.ZodBoolean>;
139
+ frequency: z.ZodDefault<z.ZodNumber>;
140
+ on_milestone: z.ZodDefault<z.ZodBoolean>;
141
+ on_tests_pass: z.ZodDefault<z.ZodBoolean>;
142
+ before_gates: z.ZodDefault<z.ZodBoolean>;
143
+ on_blocked: z.ZodDefault<z.ZodBoolean>;
144
+ auto_checkpoint: z.ZodDefault<z.ZodBoolean>;
145
+ }, z.core.$strip>;
146
+ /**
147
+ * Signal cleanup configuration (WU-1204)
148
+ *
149
+ * Configures TTL-based cleanup for signals in .lumenflow/memory/signals.jsonl
150
+ * to prevent unbounded growth.
151
+ */
152
+ export declare const SignalCleanupConfigSchema: z.ZodObject<{
153
+ ttl: z.ZodDefault<z.ZodNumber>;
154
+ unreadTtl: z.ZodDefault<z.ZodNumber>;
155
+ maxEntries: z.ZodDefault<z.ZodNumber>;
156
+ }, z.core.$strip>;
113
157
  /**
114
158
  * Memory layer configuration
115
159
  */
@@ -118,6 +162,21 @@ export declare const MemoryConfigSchema: z.ZodObject<{
118
162
  sessionTtl: z.ZodDefault<z.ZodNumber>;
119
163
  checkpointTtl: z.ZodDefault<z.ZodNumber>;
120
164
  enableAutoCleanup: z.ZodDefault<z.ZodBoolean>;
165
+ progress_signals: z.ZodOptional<z.ZodObject<{
166
+ enabled: z.ZodDefault<z.ZodBoolean>;
167
+ frequency: z.ZodDefault<z.ZodNumber>;
168
+ on_milestone: z.ZodDefault<z.ZodBoolean>;
169
+ on_tests_pass: z.ZodDefault<z.ZodBoolean>;
170
+ before_gates: z.ZodDefault<z.ZodBoolean>;
171
+ on_blocked: z.ZodDefault<z.ZodBoolean>;
172
+ auto_checkpoint: z.ZodDefault<z.ZodBoolean>;
173
+ }, z.core.$strip>>;
174
+ signalCleanup: z.ZodDefault<z.ZodObject<{
175
+ ttl: z.ZodDefault<z.ZodNumber>;
176
+ unreadTtl: z.ZodDefault<z.ZodNumber>;
177
+ maxEntries: z.ZodDefault<z.ZodNumber>;
178
+ }, z.core.$strip>>;
179
+ spawn_context_max_size: z.ZodDefault<z.ZodNumber>;
121
180
  }, z.core.$strip>;
122
181
  /**
123
182
  * UI configuration
@@ -231,6 +290,25 @@ export declare const ExperimentalConfigSchema: z.ZodObject<{
231
290
  show_next_steps: z.ZodDefault<z.ZodBoolean>;
232
291
  recovery_command: z.ZodDefault<z.ZodBoolean>;
233
292
  }, z.core.$strip>;
293
+ /**
294
+ * WU-1270: Methodology telemetry configuration
295
+ *
296
+ * Opt-in telemetry to track which methodology modes are being used.
297
+ * Privacy-preserving: No PII or project-identifying information collected.
298
+ */
299
+ export declare const MethodologyTelemetryConfigSchema: z.ZodObject<{
300
+ enabled: z.ZodDefault<z.ZodBoolean>;
301
+ }, z.core.$strip>;
302
+ /**
303
+ * WU-1270: Telemetry configuration
304
+ *
305
+ * Configuration for opt-in telemetry features.
306
+ */
307
+ export declare const TelemetryConfigSchema: z.ZodObject<{
308
+ methodology: z.ZodDefault<z.ZodObject<{
309
+ enabled: z.ZodDefault<z.ZodBoolean>;
310
+ }, z.core.$strip>>;
311
+ }, z.core.$strip>;
234
312
  /**
235
313
  * Complete LumenFlow configuration schema
236
314
  */
@@ -255,6 +333,7 @@ export declare const LumenFlowConfigSchema: z.ZodObject<{
255
333
  beacon: z.ZodDefault<z.ZodObject<{
256
334
  base: z.ZodDefault<z.ZodString>;
257
335
  stateDir: z.ZodDefault<z.ZodString>;
336
+ archiveDir: z.ZodDefault<z.ZodString>;
258
337
  stampsDir: z.ZodDefault<z.ZodString>;
259
338
  mergeLock: z.ZodDefault<z.ZodString>;
260
339
  telemetry: z.ZodDefault<z.ZodString>;
@@ -262,6 +341,10 @@ export declare const LumenFlowConfigSchema: z.ZodObject<{
262
341
  sessions: z.ZodDefault<z.ZodString>;
263
342
  incidents: z.ZodDefault<z.ZodString>;
264
343
  commandsLog: z.ZodDefault<z.ZodString>;
344
+ eventArchival: z.ZodDefault<z.ZodObject<{
345
+ archiveAfter: z.ZodDefault<z.ZodNumber>;
346
+ keepArchives: z.ZodDefault<z.ZodBoolean>;
347
+ }, z.core.$strip>>;
265
348
  }, z.core.$strip>>;
266
349
  git: z.ZodDefault<z.ZodObject<{
267
350
  mainBranch: z.ZodDefault<z.ZodString>;
@@ -328,6 +411,21 @@ export declare const LumenFlowConfigSchema: z.ZodObject<{
328
411
  sessionTtl: z.ZodDefault<z.ZodNumber>;
329
412
  checkpointTtl: z.ZodDefault<z.ZodNumber>;
330
413
  enableAutoCleanup: z.ZodDefault<z.ZodBoolean>;
414
+ progress_signals: z.ZodOptional<z.ZodObject<{
415
+ enabled: z.ZodDefault<z.ZodBoolean>;
416
+ frequency: z.ZodDefault<z.ZodNumber>;
417
+ on_milestone: z.ZodDefault<z.ZodBoolean>;
418
+ on_tests_pass: z.ZodDefault<z.ZodBoolean>;
419
+ before_gates: z.ZodDefault<z.ZodBoolean>;
420
+ on_blocked: z.ZodDefault<z.ZodBoolean>;
421
+ auto_checkpoint: z.ZodDefault<z.ZodBoolean>;
422
+ }, z.core.$strip>>;
423
+ signalCleanup: z.ZodDefault<z.ZodObject<{
424
+ ttl: z.ZodDefault<z.ZodNumber>;
425
+ unreadTtl: z.ZodDefault<z.ZodNumber>;
426
+ maxEntries: z.ZodDefault<z.ZodNumber>;
427
+ }, z.core.$strip>>;
428
+ spawn_context_max_size: z.ZodDefault<z.ZodNumber>;
331
429
  }, z.core.$strip>>;
332
430
  ui: z.ZodDefault<z.ZodObject<{
333
431
  errorBoxWidth: z.ZodDefault<z.ZodNumber>;
@@ -372,6 +470,31 @@ export declare const LumenFlowConfigSchema: z.ZodObject<{
372
470
  show_next_steps: z.ZodDefault<z.ZodBoolean>;
373
471
  recovery_command: z.ZodDefault<z.ZodBoolean>;
374
472
  }, z.core.$strip>>;
473
+ telemetry: z.ZodDefault<z.ZodObject<{
474
+ methodology: z.ZodDefault<z.ZodObject<{
475
+ enabled: z.ZodDefault<z.ZodBoolean>;
476
+ }, z.core.$strip>>;
477
+ }, z.core.$strip>>;
478
+ methodology: z.ZodOptional<z.ZodObject<{
479
+ testing: z.ZodDefault<z.ZodEnum<{
480
+ tdd: "tdd";
481
+ "test-after": "test-after";
482
+ none: "none";
483
+ }>>;
484
+ architecture: z.ZodDefault<z.ZodEnum<{
485
+ none: "none";
486
+ hexagonal: "hexagonal";
487
+ layered: "layered";
488
+ }>>;
489
+ overrides: z.ZodOptional<z.ZodObject<{
490
+ coverage_threshold: z.ZodOptional<z.ZodNumber>;
491
+ coverage_mode: z.ZodOptional<z.ZodEnum<{
492
+ off: "off";
493
+ warn: "warn";
494
+ block: "block";
495
+ }>>;
496
+ }, z.core.$strip>>;
497
+ }, z.core.$strip>>;
375
498
  }, z.core.$strip>;
376
499
  /**
377
500
  * TypeScript types inferred from schemas
@@ -381,6 +504,9 @@ export type BeaconPaths = z.infer<typeof BeaconPathsSchema>;
381
504
  export type GitConfig = z.infer<typeof GitConfigSchema>;
382
505
  export type WuConfig = z.infer<typeof WuConfigSchema>;
383
506
  export type GatesConfig = z.infer<typeof GatesConfigSchema>;
507
+ export type ProgressSignalsConfig = z.infer<typeof ProgressSignalsConfigSchema>;
508
+ export type SignalCleanupConfig = z.infer<typeof SignalCleanupConfigSchema>;
509
+ export type EventArchivalConfig = z.infer<typeof EventArchivalConfigSchema>;
384
510
  export type MemoryConfig = z.infer<typeof MemoryConfigSchema>;
385
511
  export type UiConfig = z.infer<typeof UiConfigSchema>;
386
512
  export type YamlConfig = z.infer<typeof YamlConfigSchema>;
@@ -391,7 +517,10 @@ export type ClientConfig = z.infer<typeof ClientConfigSchema>;
391
517
  export type AgentsConfig = z.infer<typeof AgentsConfigSchema>;
392
518
  export type ExperimentalConfig = z.infer<typeof ExperimentalConfigSchema>;
393
519
  export type ValidationMode = z.infer<typeof ValidationModeSchema>;
520
+ export type MethodologyTelemetryConfig = z.infer<typeof MethodologyTelemetryConfigSchema>;
521
+ export type TelemetryConfig = z.infer<typeof TelemetryConfigSchema>;
394
522
  export type LumenFlowConfig = z.infer<typeof LumenFlowConfigSchema>;
523
+ export type { MethodologyConfig, MethodologyOverrides } from './resolve-policy.js';
395
524
  /**
396
525
  * Validate configuration data
397
526
  *
@@ -419,6 +548,7 @@ export declare function validateConfig(data: unknown): z.ZodSafeParseResult<{
419
548
  beacon: {
420
549
  base: string;
421
550
  stateDir: string;
551
+ archiveDir: string;
422
552
  stampsDir: string;
423
553
  mergeLock: string;
424
554
  telemetry: string;
@@ -426,6 +556,10 @@ export declare function validateConfig(data: unknown): z.ZodSafeParseResult<{
426
556
  sessions: string;
427
557
  incidents: string;
428
558
  commandsLog: string;
559
+ eventArchival: {
560
+ archiveAfter: number;
561
+ keepArchives: boolean;
562
+ };
429
563
  };
430
564
  git: {
431
565
  mainBranch: string;
@@ -492,6 +626,21 @@ export declare function validateConfig(data: unknown): z.ZodSafeParseResult<{
492
626
  sessionTtl: number;
493
627
  checkpointTtl: number;
494
628
  enableAutoCleanup: boolean;
629
+ signalCleanup: {
630
+ ttl: number;
631
+ unreadTtl: number;
632
+ maxEntries: number;
633
+ };
634
+ spawn_context_max_size: number;
635
+ progress_signals?: {
636
+ enabled: boolean;
637
+ frequency: number;
638
+ on_milestone: boolean;
639
+ on_tests_pass: boolean;
640
+ before_gates: boolean;
641
+ on_blocked: boolean;
642
+ auto_checkpoint: boolean;
643
+ };
495
644
  };
496
645
  ui: {
497
646
  errorBoxWidth: number;
@@ -529,6 +678,19 @@ export declare function validateConfig(data: unknown): z.ZodSafeParseResult<{
529
678
  show_next_steps: boolean;
530
679
  recovery_command: boolean;
531
680
  };
681
+ telemetry: {
682
+ methodology: {
683
+ enabled: boolean;
684
+ };
685
+ };
686
+ methodology?: {
687
+ testing: "tdd" | "test-after" | "none";
688
+ architecture: "none" | "hexagonal" | "layered";
689
+ overrides?: {
690
+ coverage_threshold?: number;
691
+ coverage_mode?: "off" | "warn" | "block";
692
+ };
693
+ };
532
694
  }>;
533
695
  /**
534
696
  * Parse configuration with defaults