@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.
- package/dist/agent-patterns-registry.js +4 -2
- package/dist/arg-parser.js +5 -0
- package/dist/constants/linter-constants.d.ts +1 -1
- package/dist/constants/linter-constants.js +1 -1
- package/dist/docs-path-validator.js +3 -3
- package/dist/domain/context.schemas.d.ts +3 -3
- package/dist/domain/orchestration.constants.d.ts +1 -1
- package/dist/domain/orchestration.constants.js +1 -1
- package/dist/domain/orchestration.types.d.ts +2 -2
- package/dist/domain/validation.schemas.d.ts +4 -4
- package/dist/hardcoded-strings.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/invariants/check-automated-tests.js +3 -1
- package/dist/lumenflow-config-schema.d.ts +5 -5
- package/dist/lumenflow-config-schema.js +5 -5
- package/dist/lumenflow-config.d.ts +1 -1
- package/dist/lumenflow-config.js +7 -7
- package/dist/micro-worktree.d.ts +2 -2
- package/dist/micro-worktree.js +112 -77
- package/dist/orchestration-rules.js +1 -1
- package/dist/prompt-linter.js +5 -5
- package/dist/spawn-escalation.d.ts +2 -2
- package/dist/spawn-escalation.js +7 -3
- package/dist/spawn-monitor.js +3 -1
- package/dist/state-doctor-core.d.ts +29 -1
- package/dist/state-doctor-core.js +142 -2
- package/dist/telemetry.js +3 -3
- package/dist/template-loader.js +6 -3
- package/dist/test-baseline.d.ts +2 -2
- package/dist/test-baseline.js +3 -2
- package/dist/wu-constants.d.ts +31 -57
- package/dist/wu-constants.js +32 -8
- package/dist/wu-create-validators.d.ts +7 -0
- package/dist/wu-create-validators.js +12 -2
- package/dist/wu-done-concurrent-merge.js +2 -2
- package/dist/wu-done-metadata.js +2 -2
- package/dist/wu-done-validation.js +2 -2
- package/dist/wu-done-worktree.js +6 -5
- package/dist/wu-events-cleanup.js +2 -5
- package/dist/wu-list.d.ts +92 -0
- package/dist/wu-list.js +177 -0
- package/dist/wu-paths.js +4 -4
- package/dist/wu-spawn-context.js +3 -2
- package/dist/wu-spawn-skills.js +8 -5
- package/dist/wu-spawn.js +4 -5
- package/package.json +2 -2
- package/dist/beacon-migration.d.ts +0 -56
- 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 = [
|
|
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,
|
|
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 = `${
|
|
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
|
}
|
package/dist/wu-done-metadata.js
CHANGED
|
@@ -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,
|
|
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(
|
|
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
|
-
/^\.
|
|
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/
|
|
336
|
+
- .lumenflow/stamps/
|
|
337
337
|
- *.md files
|
|
338
338
|
|
|
339
339
|
After fixing, retry: pnpm wu:done --id ${id}
|
package/dist/wu-done-worktree.js
CHANGED
|
@@ -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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
*
|
|
32
|
+
* Import centralized path constants (WU-1430)
|
|
33
33
|
*/
|
|
34
|
-
|
|
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[]>;
|
package/dist/wu-list.js
ADDED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
96
|
+
STATE_DIR: () => config.state.stateDir,
|
|
97
97
|
/**
|
|
98
98
|
* Get path to initiatives directory
|
|
99
99
|
* @returns Path to initiatives directory
|
package/dist/wu-spawn-context.js
CHANGED
|
@@ -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:
|
|
34
|
+
MEMORY_DIR: LUMENFLOW_PATHS.MEMORY_DIR,
|
|
34
35
|
MEMORY_FILE: 'memory.jsonl',
|
|
35
36
|
};
|
|
36
37
|
/**
|
package/dist/wu-spawn-skills.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
|
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.
|
|
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
|
-
|
|
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/
|
|
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/
|
|
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.
|
|
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.
|
|
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;
|