@lumenflow/core 2.10.0 → 2.11.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 (49) hide show
  1. package/dist/agent-patterns-registry.js +4 -2
  2. package/dist/arg-parser.js +5 -0
  3. package/dist/constants/linter-constants.d.ts +1 -1
  4. package/dist/constants/linter-constants.js +1 -1
  5. package/dist/docs-path-validator.js +3 -3
  6. package/dist/domain/context.schemas.d.ts +3 -3
  7. package/dist/domain/orchestration.constants.d.ts +1 -1
  8. package/dist/domain/orchestration.constants.js +1 -1
  9. package/dist/domain/orchestration.types.d.ts +2 -2
  10. package/dist/domain/validation.schemas.d.ts +4 -4
  11. package/dist/hardcoded-strings.js +1 -1
  12. package/dist/index.d.ts +2 -2
  13. package/dist/index.js +3 -3
  14. package/dist/invariants/check-automated-tests.js +3 -1
  15. package/dist/lumenflow-config-schema.d.ts +5 -5
  16. package/dist/lumenflow-config-schema.js +5 -5
  17. package/dist/lumenflow-config.d.ts +1 -1
  18. package/dist/lumenflow-config.js +7 -7
  19. package/dist/micro-worktree.d.ts +2 -2
  20. package/dist/micro-worktree.js +112 -77
  21. package/dist/orchestration-rules.js +1 -1
  22. package/dist/prompt-linter.js +5 -5
  23. package/dist/spawn-escalation.d.ts +2 -2
  24. package/dist/spawn-escalation.js +7 -3
  25. package/dist/spawn-monitor.js +3 -1
  26. package/dist/state-doctor-core.d.ts +29 -1
  27. package/dist/state-doctor-core.js +142 -2
  28. package/dist/telemetry.js +3 -3
  29. package/dist/template-loader.js +6 -3
  30. package/dist/test-baseline.d.ts +2 -2
  31. package/dist/test-baseline.js +3 -2
  32. package/dist/wu-constants.d.ts +31 -57
  33. package/dist/wu-constants.js +32 -8
  34. package/dist/wu-create-validators.d.ts +7 -0
  35. package/dist/wu-create-validators.js +12 -2
  36. package/dist/wu-done-concurrent-merge.js +2 -2
  37. package/dist/wu-done-metadata.js +2 -2
  38. package/dist/wu-done-validation.js +2 -2
  39. package/dist/wu-done-worktree.js +6 -5
  40. package/dist/wu-events-cleanup.js +2 -5
  41. package/dist/wu-list.d.ts +92 -0
  42. package/dist/wu-list.js +177 -0
  43. package/dist/wu-paths.js +4 -4
  44. package/dist/wu-spawn-context.js +3 -2
  45. package/dist/wu-spawn-skills.js +8 -5
  46. package/dist/wu-spawn.js +4 -5
  47. package/package.json +2 -2
  48. package/dist/beacon-migration.d.ts +0 -56
  49. package/dist/beacon-migration.js +0 -101
@@ -15,10 +15,11 @@
15
15
  * No external library exists for LumenFlow lane inference validation.
16
16
  */
17
17
  import { isExternalPath, normalizeSpecRef } from './lumenflow-home.js';
18
+ import { PATH_LITERALS } from './wu-constants.js';
18
19
  /** Confidence threshold for showing suggestion (percentage) */
19
20
  const CONFIDENCE_THRESHOLD_LOW = 30;
20
- /** Prefixes that indicate repo-internal paths (WU-1069) */
21
- const REPO_INTERNAL_PREFIXES = ['./', '.lumenflow/'];
21
+ /** Prefixes that indicate repo-internal paths (WU-1069, WU-1430: Use centralized constants) */
22
+ const REPO_INTERNAL_PREFIXES = [PATH_LITERALS.CURRENT_DIR_PREFIX, PATH_LITERALS.LUMENFLOW_PREFIX];
22
23
  /**
23
24
  * WU-1069: Check if a path is a repo-internal path that should be rejected
24
25
  *
@@ -186,6 +187,15 @@ export function hasExternalSpecRefs(specRefs) {
186
187
  }
187
188
  return specRefs.some((ref) => isExternalPath(ref));
188
189
  }
190
+ /**
191
+ * WU-1429: Check if spec_refs is non-empty
192
+ *
193
+ * @param {string[]|undefined} specRefs - Array of spec reference paths
194
+ * @returns {boolean} True if spec_refs contains at least one entry
195
+ */
196
+ export function hasSpecRefs(specRefs) {
197
+ return Array.isArray(specRefs) && specRefs.length > 0;
198
+ }
189
199
  /**
190
200
  * WU-1062: Normalize all spec_refs paths
191
201
  *
@@ -18,7 +18,7 @@ import { validateWUEvent } from './wu-state-schema.js';
18
18
  import { generateBacklog, generateStatus } from './backlog-generator.js';
19
19
  import { getStateStoreDirFromBacklog } from './wu-paths.js';
20
20
  import { getGitForCwd } from './git-adapter.js';
21
- import { REMOTES, BRANCHES, BEACON_PATHS } from './wu-constants.js';
21
+ import { REMOTES, BRANCHES, LUMENFLOW_PATHS } from './wu-constants.js';
22
22
  /**
23
23
  * Creates a unique key for an event to detect duplicates.
24
24
  * Events are considered identical if they have the same type, wuId, and timestamp.
@@ -46,7 +46,7 @@ export async function fetchMainEventsContent() {
46
46
  console.warn('[wu-done] Warning: Could not fetch latest main, using cached version');
47
47
  }
48
48
  // Try to read wu-events.jsonl from origin/main
49
- const eventsPath = `${BEACON_PATHS.STATE_DIR}/${WU_EVENTS_FILE_NAME}`;
49
+ const eventsPath = `${LUMENFLOW_PATHS.STATE_DIR}/${WU_EVENTS_FILE_NAME}`;
50
50
  const content = await git.raw(['show', `${REMOTES.ORIGIN}/${BRANCHES.MAIN}:${eventsPath}`]);
51
51
  return content;
52
52
  }
@@ -11,7 +11,7 @@ import { moveWUToDoneBacklog } from './wu-backlog-updater.js';
11
11
  import { createStamp } from './stamp-utils.js';
12
12
  import { WU_EVENTS_FILE_NAME } from './wu-state-store.js';
13
13
  import { computeWUYAMLContent, computeStatusContentFromMergedState, computeBacklogContent, computeWUEventsContentAfterComplete, computeStampContent, } from './wu-transaction-collectors.js';
14
- import { DEFAULTS, LOG_PREFIX, EMOJI, PKG_MANAGER, SCRIPTS, PRETTIER_FLAGS, BEACON_PATHS, } from './wu-constants.js';
14
+ import { DEFAULTS, LOG_PREFIX, EMOJI, PKG_MANAGER, SCRIPTS, PRETTIER_FLAGS, LUMENFLOW_PATHS, } from './wu-constants.js';
15
15
  import { applyExposureDefaults } from './wu-done-validation.js';
16
16
  import { createFileNotFoundError, createValidationError } from './wu-done-errors.js';
17
17
  import { writeWU } from './wu-yaml.js';
@@ -170,7 +170,7 @@ export async function stageAndFormatMetadata({ id, wuPath, statusPath, backlogPa
170
170
  // The singleton git adapter captures cwd at import time, which is wrong after process.chdir()
171
171
  const gitCwd = getGitForCwd();
172
172
  // Stage files
173
- const wuEventsPath = path.join(BEACON_PATHS.STATE_DIR, WU_EVENTS_FILE_NAME);
173
+ const wuEventsPath = path.join(LUMENFLOW_PATHS.STATE_DIR, WU_EVENTS_FILE_NAME);
174
174
  const filesToStage = [wuPath, statusPath, backlogPath, stampsDir];
175
175
  if (existsSync(wuEventsPath)) {
176
176
  filesToStage.push(wuEventsPath);
@@ -261,7 +261,7 @@ const DOCS_ONLY_ALLOWED_PATTERNS = [
261
261
  /^memory-bank\//i,
262
262
  /^docs\//i,
263
263
  /\.md$/i,
264
- /^\.(?:beacon|lumenflow)\/stamps\//i, // Support both legacy .beacon and .lumenflow
264
+ /^\.lumenflow\/stamps\//i,
265
265
  /^\.claude\//i,
266
266
  /^ai\//i,
267
267
  /^README\.md$/i,
@@ -333,7 +333,7 @@ Allowed paths for documentation WUs:
333
333
  - ai/
334
334
  - .claude/
335
335
  - memory-bank/
336
- - .lumenflow/stamps/ (or legacy .beacon/stamps/)
336
+ - .lumenflow/stamps/
337
337
  - *.md files
338
338
 
339
339
  After fixing, retry: pnpm wu:done --id ${id}
@@ -24,7 +24,7 @@ import { generateCommitMessage, collectMetadataToTransaction, stageAndFormatMeta
24
24
  import { getGitForCwd } from './git-adapter.js';
25
25
  import { readWU, writeWU } from './wu-yaml.js';
26
26
  import { WU_PATHS } from './wu-paths.js';
27
- import { BRANCHES, REMOTES, THRESHOLDS, LOG_PREFIX, EMOJI, COMMIT_FORMATS, BOX, STRING_LITERALS, WU_STATUS, GIT_COMMANDS, GIT_FLAGS, } from './wu-constants.js';
27
+ import { BRANCHES, REMOTES, THRESHOLDS, LOG_PREFIX, EMOJI, COMMIT_FORMATS, BOX, STRING_LITERALS, WU_STATUS, GIT_COMMANDS, GIT_FLAGS, LUMENFLOW_PATHS, } from './wu-constants.js';
28
28
  import { RECOVERY, REBASE, PREFLIGHT, MERGE } from './wu-done-messages.js';
29
29
  import { getDriftLevel, DRIFT_LEVELS } from './branch-drift.js';
30
30
  import { createError, ErrorCodes } from './error-handler.js';
@@ -242,7 +242,7 @@ export async function executeWorktreeCompletion(context) {
242
242
  // WU-2310: Capture file state before transaction commit
243
243
  // This allows rollback if git commit fails AFTER files are written
244
244
  // Note: We use the relative paths since we're already chdir'd into the worktree
245
- const workingEventsPath = path.join('.lumenflow', 'state', WU_EVENTS_FILE_NAME);
245
+ const workingEventsPath = path.join(LUMENFLOW_PATHS.STATE_DIR, WU_EVENTS_FILE_NAME);
246
246
  const pathsToSnapshot = [
247
247
  workingWUPath,
248
248
  workingStatusPath,
@@ -580,13 +580,14 @@ export async function checkBranchDrift(branch) {
580
580
  * that would break if paths are rearranged.
581
581
  */
582
582
  const APPEND_ONLY_FILES = [
583
- // State store events file (append-only by design)
584
- path.join('.lumenflow', 'state', WU_EVENTS_FILE_NAME),
583
+ // State store events file (append-only by design) - WU-1430: Use centralized constant
584
+ path.join(LUMENFLOW_PATHS.STATE_DIR, WU_EVENTS_FILE_NAME),
585
585
  // Status and backlog are generated from state store but may conflict during rebase
586
586
  WU_PATHS.STATUS(),
587
587
  WU_PATHS.BACKLOG(),
588
588
  ];
589
- const WU_EVENTS_PATH = path.join('.lumenflow', 'state', WU_EVENTS_FILE_NAME);
589
+ // WU-1430: Use centralized constant
590
+ const WU_EVENTS_PATH = path.join(LUMENFLOW_PATHS.STATE_DIR, WU_EVENTS_FILE_NAME);
590
591
  function normalizeEventForKey(event) {
591
592
  const normalized = {};
592
593
  for (const key of Object.keys(event).sort()) {
@@ -29,12 +29,9 @@ import { WUStateStore, WU_EVENTS_FILE_NAME } from './wu-state-store.js';
29
29
  */
30
30
  const ONE_DAY_MS = 24 * 60 * 60 * 1000;
31
31
  /**
32
- * LumenFlow paths for state and archive
32
+ * Import centralized path constants (WU-1430)
33
33
  */
34
- const LUMENFLOW_PATHS = {
35
- STATE_DIR: '.lumenflow/state',
36
- ARCHIVE_DIR: '.lumenflow/archive',
37
- };
34
+ import { LUMENFLOW_PATHS } from './wu-constants.js';
38
35
  /**
39
36
  * Default event archival configuration
40
37
  */
@@ -0,0 +1,92 @@
1
+ /**
2
+ * WU List Helper (WU-1411)
3
+ *
4
+ * Provides a consistent list of WUs by merging WUStateStore with YAML metadata.
5
+ * MCP server and other tools can use this instead of duplicating listing logic.
6
+ *
7
+ * Key behaviors:
8
+ * - Status from state store takes precedence over YAML status (more current)
9
+ * - Falls back to YAML status when WU is not in state store
10
+ * - Supports filtering by status and lane
11
+ * - Gracefully handles errors (missing files, invalid YAML)
12
+ *
13
+ * @module wu-list
14
+ * @see {@link ./wu-state-store.ts} - State store for runtime status
15
+ * @see {@link ./wu-yaml.ts} - YAML operations
16
+ * @see {@link ./wu-paths.ts} - Path utilities
17
+ */
18
+ /**
19
+ * WU list entry returned by listWUs.
20
+ * Contains essential fields for display and filtering.
21
+ */
22
+ export interface WUListEntry {
23
+ /** WU identifier (e.g., 'WU-100') */
24
+ id: string;
25
+ /** Short title describing the work */
26
+ title: string;
27
+ /** Lane assignment (e.g., 'Framework: Core') */
28
+ lane: string;
29
+ /** Current status (from state store or YAML) */
30
+ status: string;
31
+ /** Work type (feature, bug, documentation, etc.) */
32
+ type: string;
33
+ /** Priority level (P0-P3) */
34
+ priority: string;
35
+ /** Parent initiative reference (optional) */
36
+ initiative?: string;
37
+ /** Phase number within parent initiative (optional) */
38
+ phase?: number;
39
+ /** Creation date (YYYY-MM-DD) */
40
+ created?: string;
41
+ }
42
+ /**
43
+ * Options for listWUs function.
44
+ */
45
+ export interface ListWUsOptions {
46
+ /** Project root directory (default: cwd) */
47
+ projectRoot?: string;
48
+ /** Filter by status (e.g., 'in_progress', 'blocked', 'done') */
49
+ status?: string;
50
+ /** Filter by lane (e.g., 'Framework: Core') */
51
+ lane?: string;
52
+ /**
53
+ * Direct path to WU directory (overrides config-based path).
54
+ * Useful for testing with virtual filesystems.
55
+ */
56
+ wuDir?: string;
57
+ /**
58
+ * Direct path to state directory (overrides config-based path).
59
+ * Useful for testing with virtual filesystems.
60
+ */
61
+ stateDir?: string;
62
+ }
63
+ /**
64
+ * Lists WUs by merging state store status with YAML metadata.
65
+ *
66
+ * The state store contains the most current status (claim, block, complete events),
67
+ * while YAML files contain the full metadata (title, lane, type, etc.).
68
+ *
69
+ * Status precedence:
70
+ * 1. State store status (if WU has events)
71
+ * 2. YAML status (fallback if not in state store)
72
+ *
73
+ * @param options - Listing options
74
+ * @returns Array of WU list entries
75
+ *
76
+ * @example
77
+ * // List all WUs
78
+ * const allWUs = await listWUs();
79
+ *
80
+ * @example
81
+ * // Filter by status
82
+ * const inProgress = await listWUs({ status: 'in_progress' });
83
+ *
84
+ * @example
85
+ * // Filter by lane
86
+ * const coreWUs = await listWUs({ lane: 'Framework: Core' });
87
+ *
88
+ * @example
89
+ * // Filter by both
90
+ * const blockedCore = await listWUs({ status: 'blocked', lane: 'Framework: Core' });
91
+ */
92
+ export declare function listWUs(options?: ListWUsOptions): Promise<WUListEntry[]>;
@@ -0,0 +1,177 @@
1
+ /**
2
+ * WU List Helper (WU-1411)
3
+ *
4
+ * Provides a consistent list of WUs by merging WUStateStore with YAML metadata.
5
+ * MCP server and other tools can use this instead of duplicating listing logic.
6
+ *
7
+ * Key behaviors:
8
+ * - Status from state store takes precedence over YAML status (more current)
9
+ * - Falls back to YAML status when WU is not in state store
10
+ * - Supports filtering by status and lane
11
+ * - Gracefully handles errors (missing files, invalid YAML)
12
+ *
13
+ * @module wu-list
14
+ * @see {@link ./wu-state-store.ts} - State store for runtime status
15
+ * @see {@link ./wu-yaml.ts} - YAML operations
16
+ * @see {@link ./wu-paths.ts} - Path utilities
17
+ */
18
+ import { readdir } from 'node:fs/promises';
19
+ import { join } from 'node:path';
20
+ import { parse as parseYaml } from 'yaml';
21
+ import { readFile } from 'node:fs/promises';
22
+ import { WUStateStore } from './wu-state-store.js';
23
+ import { getConfig } from './lumenflow-config.js';
24
+ /**
25
+ * Lists WUs by merging state store status with YAML metadata.
26
+ *
27
+ * The state store contains the most current status (claim, block, complete events),
28
+ * while YAML files contain the full metadata (title, lane, type, etc.).
29
+ *
30
+ * Status precedence:
31
+ * 1. State store status (if WU has events)
32
+ * 2. YAML status (fallback if not in state store)
33
+ *
34
+ * @param options - Listing options
35
+ * @returns Array of WU list entries
36
+ *
37
+ * @example
38
+ * // List all WUs
39
+ * const allWUs = await listWUs();
40
+ *
41
+ * @example
42
+ * // Filter by status
43
+ * const inProgress = await listWUs({ status: 'in_progress' });
44
+ *
45
+ * @example
46
+ * // Filter by lane
47
+ * const coreWUs = await listWUs({ lane: 'Framework: Core' });
48
+ *
49
+ * @example
50
+ * // Filter by both
51
+ * const blockedCore = await listWUs({ status: 'blocked', lane: 'Framework: Core' });
52
+ */
53
+ export async function listWUs(options = {}) {
54
+ const { projectRoot = process.cwd(), status: filterStatus, lane: filterLane, wuDir: wuDirOverride, stateDir: stateDirOverride, } = options;
55
+ // Determine paths: use overrides if provided, otherwise use config
56
+ let wuDir;
57
+ let stateDir;
58
+ if (wuDirOverride && stateDirOverride) {
59
+ // Direct paths provided (e.g., for testing)
60
+ wuDir = wuDirOverride;
61
+ stateDir = stateDirOverride;
62
+ }
63
+ else {
64
+ // Get configuration for paths
65
+ const config = getConfig({ projectRoot });
66
+ wuDir = wuDirOverride ?? join(projectRoot, config.directories.wuDir);
67
+ stateDir = stateDirOverride ?? join(projectRoot, config.state.stateDir);
68
+ }
69
+ // Load state store for runtime statuses
70
+ const stateMap = await loadStateStore(stateDir);
71
+ // Read all WU YAML files
72
+ const wuEntries = await readWUYamlFiles(wuDir);
73
+ // Merge state store status with YAML data
74
+ const entries = [];
75
+ for (const yamlData of wuEntries) {
76
+ // Skip invalid entries
77
+ if (!yamlData.id || typeof yamlData.id !== 'string') {
78
+ continue;
79
+ }
80
+ const wuId = yamlData.id;
81
+ // Get status: state store takes precedence
82
+ const stateEntry = stateMap.get(wuId);
83
+ const yamlStatus = typeof yamlData.status === 'string' ? yamlData.status : 'ready';
84
+ const status = stateEntry?.status ?? yamlStatus;
85
+ // Get lane: prefer state store (more current), fall back to YAML
86
+ const yamlLane = typeof yamlData.lane === 'string' ? yamlData.lane : '';
87
+ const lane = stateEntry?.lane ?? yamlLane;
88
+ // Extract string fields with type guards
89
+ const yamlTitle = typeof yamlData.title === 'string' ? yamlData.title : '';
90
+ const yamlType = typeof yamlData.type === 'string' ? yamlData.type : 'feature';
91
+ const yamlPriority = typeof yamlData.priority === 'string' ? yamlData.priority : 'P2';
92
+ // Build entry
93
+ const entry = {
94
+ id: wuId,
95
+ title: stateEntry?.title ?? yamlTitle,
96
+ lane,
97
+ status,
98
+ type: yamlType,
99
+ priority: yamlPriority,
100
+ };
101
+ // Add optional fields if present with type guards
102
+ if (typeof yamlData.initiative === 'string') {
103
+ entry.initiative = yamlData.initiative;
104
+ }
105
+ if (typeof yamlData.phase === 'number') {
106
+ entry.phase = yamlData.phase;
107
+ }
108
+ if (typeof yamlData.created === 'string') {
109
+ entry.created = yamlData.created;
110
+ }
111
+ // Apply filters
112
+ if (filterStatus && status !== filterStatus) {
113
+ continue;
114
+ }
115
+ if (filterLane && lane !== filterLane) {
116
+ continue;
117
+ }
118
+ entries.push(entry);
119
+ }
120
+ return entries;
121
+ }
122
+ /**
123
+ * Loads state store and returns a map of WU ID to state entry.
124
+ * Returns empty map on errors (graceful degradation).
125
+ */
126
+ async function loadStateStore(stateDir) {
127
+ const map = new Map();
128
+ try {
129
+ const store = new WUStateStore(stateDir);
130
+ await store.load();
131
+ // Collect all known statuses
132
+ const statuses = ['in_progress', 'blocked', 'done', 'ready'];
133
+ for (const status of statuses) {
134
+ const wuIds = store.getByStatus(status);
135
+ for (const wuId of wuIds) {
136
+ const state = store.getWUState(wuId);
137
+ if (state) {
138
+ map.set(wuId, state);
139
+ }
140
+ }
141
+ }
142
+ }
143
+ catch {
144
+ // Graceful degradation: return empty map on errors
145
+ }
146
+ return map;
147
+ }
148
+ /**
149
+ * Reads all WU YAML files from the WU directory.
150
+ * Skips invalid files (graceful degradation).
151
+ */
152
+ async function readWUYamlFiles(wuDir) {
153
+ const entries = [];
154
+ try {
155
+ const files = await readdir(wuDir);
156
+ for (const file of files) {
157
+ // Only process WU-*.yaml files
158
+ if (!file.startsWith('WU-') || !file.endsWith('.yaml')) {
159
+ continue;
160
+ }
161
+ try {
162
+ const content = await readFile(join(wuDir, file), 'utf-8');
163
+ const parsed = parseYaml(content);
164
+ if (parsed && typeof parsed === 'object') {
165
+ entries.push(parsed);
166
+ }
167
+ }
168
+ catch {
169
+ // Skip invalid YAML files
170
+ }
171
+ }
172
+ }
173
+ catch {
174
+ // Directory doesn't exist or can't be read
175
+ }
176
+ return entries;
177
+ }
package/dist/wu-paths.js CHANGED
@@ -45,7 +45,7 @@ export function resolveRepoRoot(absolutePath, depth) {
45
45
  export function getStateStoreDirFromBacklog(backlogPath) {
46
46
  const config = getConfig();
47
47
  const repoRoot = resolveRepoRoot(backlogPath, PATH_DEPTHS.BACKLOG);
48
- return path.join(repoRoot, config.beacon.stateDir);
48
+ return path.join(repoRoot, config.state.stateDir);
49
49
  }
50
50
  /**
51
51
  * Create WU paths object with configurable base paths
@@ -82,18 +82,18 @@ export function createWuPaths(options = {}) {
82
82
  * Get path to stamps directory
83
83
  * @returns Path to stamps directory
84
84
  */
85
- STAMPS_DIR: () => config.beacon.stampsDir,
85
+ STAMPS_DIR: () => config.state.stampsDir,
86
86
  /**
87
87
  * Get path to WU done stamp file
88
88
  * @param id - WU ID (e.g., 'WU-123')
89
89
  * @returns Path to stamp file
90
90
  */
91
- STAMP: (id) => path.join(config.beacon.stampsDir, `${id}.done`),
91
+ STAMP: (id) => path.join(config.state.stampsDir, `${id}.done`),
92
92
  /**
93
93
  * Get path to state directory
94
94
  * @returns Path to state directory
95
95
  */
96
- STATE_DIR: () => config.beacon.stateDir,
96
+ STATE_DIR: () => config.state.stateDir,
97
97
  /**
98
98
  * Get path to initiatives directory
99
99
  * @returns Path to initiatives directory
@@ -22,15 +22,16 @@
22
22
  */
23
23
  import { existsSync, statSync } from 'node:fs';
24
24
  import path from 'node:path';
25
+ import { LUMENFLOW_PATHS } from './wu-constants.js';
25
26
  /**
26
27
  * Default maximum context size in bytes (4KB)
27
28
  */
28
29
  const DEFAULT_MAX_SIZE = 4096;
29
30
  /**
30
- * Memory layer paths
31
+ * Memory layer paths (WU-1430: Use centralized constants)
31
32
  */
32
33
  const MEMORY_PATHS = {
33
- MEMORY_DIR: '.lumenflow/memory',
34
+ MEMORY_DIR: LUMENFLOW_PATHS.MEMORY_DIR,
34
35
  MEMORY_FILE: 'memory.jsonl',
35
36
  };
36
37
  /**
@@ -1,12 +1,15 @@
1
1
  import { existsSync } from 'node:fs';
2
+ import { LUMENFLOW_PATHS } from './wu-constants.js';
3
+ /** WU-1430: Compose known skills directories from centralized constants */
2
4
  const KNOWN_SKILLS_DIRS = [
3
- '.lumenflow/skills',
5
+ LUMENFLOW_PATHS.SKILLS_DIR,
4
6
  '.claude/skills',
5
7
  '.codex/skills',
6
8
  '.gemini/skills',
7
9
  ];
10
+ /** WU-1430: Compose known agents directories from centralized constants */
8
11
  const KNOWN_AGENTS_DIRS = [
9
- '.lumenflow/agents',
12
+ LUMENFLOW_PATHS.AGENTS_DIR,
10
13
  '.claude/agents',
11
14
  '.codex/agents',
12
15
  '.gemini/agents',
@@ -30,7 +33,7 @@ const CONTEXT_HINTS = {
30
33
  tddWorkflow: '- `tdd-workflow` — TDD is mandatory for feature/enhancement WUs',
31
34
  bugClassification: '- `bug-classification` — Bug severity assessment',
32
35
  lumenflowGates: '- `lumenflow-gates` — Tooling often affects gates',
33
- beaconCompliance: '- `beacon-compliance` — Intelligence lane requires Beacon validation',
36
+ llmCompliance: '- `llm-compliance` — Intelligence lane requires LLM validation',
34
37
  promptManagement: '- `prompt-management` — For prompt template work',
35
38
  frontendDesign: '- `frontend-design` — For UI component work',
36
39
  };
@@ -38,7 +41,7 @@ const ADDITIONAL_SKILLS_TABLE = `| Skill | Use When |
38
41
  |-------|----------|
39
42
  | lumenflow-gates | Gates fail, debugging format/lint/typecheck errors |
40
43
  | bug-classification | Bug discovered mid-WU, need priority classification |
41
- | beacon-compliance | Code touches LLM, prompts, classification |
44
+ | llm-compliance | Code touches LLM, prompts, classification |
42
45
  | prompt-management | Working with prompt templates, golden datasets |
43
46
  | frontend-design | Building UI components, pages |
44
47
  | initiative-management | Multi-phase projects, INIT-XXX coordination |
@@ -159,7 +162,7 @@ export function generateSkillsSelectionSection(doc, config, clientName) {
159
162
  contextHints.push(CONTEXT_HINTS.lumenflowGates);
160
163
  }
161
164
  if (laneParent === 'Intelligence') {
162
- contextHints.push(CONTEXT_HINTS.beaconCompliance);
165
+ contextHints.push(CONTEXT_HINTS.llmCompliance);
163
166
  contextHints.push(CONTEXT_HINTS.promptManagement);
164
167
  }
165
168
  if (laneParent === 'Experience') {
package/dist/wu-spawn.js CHANGED
@@ -1191,9 +1191,8 @@ export function emitMethodologyTelemetry(config, policy) {
1191
1191
  methodology_architecture: policy.architecture,
1192
1192
  event_context: 'spawn',
1193
1193
  };
1194
- // Use the telemetry emit function from telemetry.ts
1195
- const METHODOLOGY_LOG = '.lumenflow/telemetry/methodology.ndjson';
1196
- emitTelemetry(METHODOLOGY_LOG, event);
1194
+ // Use the telemetry emit function from telemetry.ts - WU-1430: Use centralized constant
1195
+ emitTelemetry(LUMENFLOW_PATHS.METHODOLOGY_LOG, event);
1197
1196
  }
1198
1197
  /**
1199
1198
  * Generate Lane Selection section (WU-2107)
@@ -1261,10 +1260,10 @@ When creating \`.lumenflow/\` stamps or other artifacts:
1261
1260
  # CORRECT: Create stamp in worktree
1262
1261
  WORKTREE_ROOT=$(git rev-parse --show-toplevel)
1263
1262
  mkdir -p "$WORKTREE_ROOT/.lumenflow/agent-runs"
1264
- touch "$WORKTREE_ROOT/.lumenflow/agent-runs/beacon-guardian.stamp"
1263
+ touch "$WORKTREE_ROOT/.lumenflow/agent-runs/code-reviewer.stamp"
1265
1264
 
1266
1265
  # WRONG: Hardcoded path to main
1267
- # touch /path/to/main/.lumenflow/agent-runs/beacon-guardian.stamp
1266
+ # touch /path/to/main/.lumenflow/agent-runs/code-reviewer.stamp
1268
1267
  \`\`\`
1269
1268
 
1270
1269
  ### Why This Matters
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumenflow/core",
3
- "version": "2.10.0",
3
+ "version": "2.11.0",
4
4
  "description": "Core WU lifecycle tools for LumenFlow workflow framework",
5
5
  "keywords": [
6
6
  "lumenflow",
@@ -99,7 +99,7 @@
99
99
  "vitest": "^4.0.17"
100
100
  },
101
101
  "peerDependencies": {
102
- "@lumenflow/memory": "2.10.0"
102
+ "@lumenflow/memory": "2.11.0"
103
103
  },
104
104
  "peerDependenciesMeta": {
105
105
  "@lumenflow/memory": {
@@ -1,56 +0,0 @@
1
- /**
2
- * @file beacon-migration.ts
3
- * @description Migration utility for renaming .beacon directories to .lumenflow (WU-1075)
4
- *
5
- * This module provides a one-time migration function that renames the legacy
6
- * .beacon directory to .lumenflow. It's safe to run multiple times - it will
7
- * only migrate if .beacon exists and .lumenflow does not.
8
- *
9
- * @example
10
- * ```typescript
11
- * import { migrateBeaconToLumenflow } from '@lumenflow/core';
12
- *
13
- * // Run migration in project root
14
- * const result = migrateBeaconToLumenflow();
15
- * if (result.migrated) {
16
- * console.log('Successfully migrated .beacon/ → .lumenflow/');
17
- * }
18
- * ```
19
- */
20
- /**
21
- * Result of a migration attempt
22
- */
23
- export interface MigrationResult {
24
- /** Whether migration was performed */
25
- migrated: boolean;
26
- /** Reason for the result */
27
- reason: 'migrated' | 'already_migrated' | 'no_legacy_dir' | 'both_exist';
28
- /** Path that was migrated from (if migrated) */
29
- fromPath?: string;
30
- /** Path that was migrated to (if migrated) */
31
- toPath?: string;
32
- /** Error message if migration failed */
33
- error?: string;
34
- }
35
- /**
36
- * Migrate .beacon directory to .lumenflow
37
- *
38
- * This function safely renames the legacy .beacon directory to .lumenflow.
39
- * It handles the following scenarios:
40
- *
41
- * - .beacon exists, .lumenflow does not → Migrate (rename)
42
- * - .beacon does not exist, .lumenflow exists → Already migrated (no-op)
43
- * - Neither exists → No legacy directory (no-op)
44
- * - Both exist → Conflict, manual resolution needed
45
- *
46
- * @param {string} [baseDir=process.cwd()] - Base directory to check for migration
47
- * @returns {MigrationResult} Result of the migration attempt
48
- */
49
- export declare function migrateBeaconToLumenflow(baseDir?: string): MigrationResult;
50
- /**
51
- * Check if migration is needed without performing it
52
- *
53
- * @param {string} [baseDir=process.cwd()] - Base directory to check
54
- * @returns {boolean} True if .beacon exists and .lumenflow does not
55
- */
56
- export declare function needsMigration(baseDir?: string): boolean;