@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
@@ -12,6 +12,7 @@
12
12
  import * as fs from 'node:fs';
13
13
  import * as path from 'node:path';
14
14
  import * as os from 'node:os';
15
+ import { LUMENFLOW_PATHS } from './wu-constants.js';
15
16
  /** Default agent branch patterns (narrow: just agent/*) */
16
17
  export const DEFAULT_AGENT_PATTERNS = ['agent/*'];
17
18
  /** Remote registry URL */
@@ -34,9 +35,10 @@ let memoryCacheTime = 0;
34
35
  export function getCacheDir() {
35
36
  const lumenflowHome = process.env.LUMENFLOW_HOME;
36
37
  if (lumenflowHome) {
37
- return path.join(lumenflowHome, 'cache');
38
+ return path.join(lumenflowHome, LUMENFLOW_PATHS.HOME_CACHE);
38
39
  }
39
- return path.join(os.homedir(), '.lumenflow', 'cache');
40
+ // WU-1430: Compose home cache path from centralized constants
41
+ return path.join(os.homedir(), LUMENFLOW_PATHS.BASE, LUMENFLOW_PATHS.HOME_CACHE);
40
42
  }
41
43
  /**
42
44
  * Validate registry response
@@ -317,6 +317,11 @@ export const WU_OPTIONS = {
317
317
  description: 'Acceptance criterion (repeatable, use multiple times)',
318
318
  isRepeatable: true,
319
319
  },
320
+ notes: {
321
+ name: 'notes',
322
+ flags: '--notes <text>',
323
+ description: 'Implementation notes or context (optional)',
324
+ },
320
325
  codePaths: {
321
326
  name: 'codePaths',
322
327
  flags: '--code-paths <paths>',
@@ -10,7 +10,7 @@ export declare const LINTER_CONFIG: {
10
10
  WATCHDOG_TIMEOUT_MS: number;
11
11
  /**
12
12
  * Maximum allowed glass surfaces in UI components.
13
- * Per Beacon spec glass cap artifacts rule.
13
+ * Per design system glass cap artifacts rule.
14
14
  */
15
15
  MAX_GLASS_SURFACES: number;
16
16
  };
@@ -10,7 +10,7 @@ export const LINTER_CONFIG = {
10
10
  WATCHDOG_TIMEOUT_MS: 55000,
11
11
  /**
12
12
  * Maximum allowed glass surfaces in UI components.
13
- * Per Beacon spec glass cap artifacts rule.
13
+ * Per design system glass cap artifacts rule.
14
14
  */
15
15
  MAX_GLASS_SURFACES: 6,
16
16
  };
@@ -22,7 +22,7 @@
22
22
  */
23
23
  import path from 'node:path';
24
24
  import { WU_EVENTS_FILE_NAME } from './wu-state-store.js';
25
- import { BEACON_PATHS, DIRECTORIES, FILE_EXTENSIONS, STRING_LITERALS } from './wu-constants.js';
25
+ import { LUMENFLOW_PATHS, DIRECTORIES, FILE_EXTENSIONS, STRING_LITERALS } from './wu-constants.js';
26
26
  const POSIX = path.posix;
27
27
  const DOCS_ONLY_PREFIXES = Object.freeze([
28
28
  DIRECTORIES.DOCS,
@@ -31,8 +31,8 @@ const DOCS_ONLY_PREFIXES = Object.freeze([
31
31
  DIRECTORIES.MEMORY_BANK,
32
32
  ]);
33
33
  const TOOLS_TESTS_PREFIX = `${POSIX.join(DIRECTORIES.TOOLS, '__tests__')}${STRING_LITERALS.SLASH}`;
34
- const STAMPS_PREFIX = `${BEACON_PATHS.STAMPS_DIR}${STRING_LITERALS.SLASH}`;
35
- const WU_EVENTS_PATH = POSIX.join(BEACON_PATHS.STATE_DIR, WU_EVENTS_FILE_NAME);
34
+ const STAMPS_PREFIX = `${LUMENFLOW_PATHS.STAMPS_DIR}${STRING_LITERALS.SLASH}`;
35
+ const WU_EVENTS_PATH = POSIX.join(LUMENFLOW_PATHS.STATE_DIR, WU_EVENTS_FILE_NAME);
36
36
  /**
37
37
  * Check if a file path is allowed for docs-only WUs
38
38
  * @param {string} filePath - The file path to validate
@@ -41,10 +41,10 @@ export declare const LocationType: {
41
41
  * Schema for location types
42
42
  */
43
43
  export declare const LocationTypeSchema: z.ZodEnum<{
44
- unknown: "unknown";
45
44
  main: "main";
46
45
  worktree: "worktree";
47
46
  detached: "detached";
47
+ unknown: "unknown";
48
48
  }>;
49
49
  /**
50
50
  * Schema for location context
@@ -53,10 +53,10 @@ export declare const LocationTypeSchema: z.ZodEnum<{
53
53
  */
54
54
  export declare const LocationContextSchema: z.ZodObject<{
55
55
  type: z.ZodEnum<{
56
- unknown: "unknown";
57
56
  main: "main";
58
57
  worktree: "worktree";
59
58
  detached: "detached";
59
+ unknown: "unknown";
60
60
  }>;
61
61
  cwd: z.ZodString;
62
62
  gitRoot: z.ZodString;
@@ -112,10 +112,10 @@ export declare const SessionStateSchema: z.ZodObject<{
112
112
  export declare const WuContextSchema: z.ZodObject<{
113
113
  location: z.ZodObject<{
114
114
  type: z.ZodEnum<{
115
- unknown: "unknown";
116
115
  main: "main";
117
116
  worktree: "worktree";
118
117
  detached: "detached";
118
+ unknown: "unknown";
119
119
  }>;
120
120
  cwd: z.ZodString;
121
121
  gitRoot: z.ZodString;
@@ -96,7 +96,7 @@ export type MandatoryAgentName = (typeof MANDATORY_AGENT_NAMES)[number];
96
96
  *
97
97
  * Example application-specific triggers (configure in your project):
98
98
  * - security-auditor: supabase/migrations/**, auth/**, rls/**
99
- * - beacon-guardian: prompts/**, llm/**
99
+ * - llm-reviewer: prompts/**, llm/**
100
100
  *
101
101
  * Usage:
102
102
  * ```typescript
@@ -99,7 +99,7 @@ export const MANDATORY_AGENT_NAMES = [];
99
99
  *
100
100
  * Example application-specific triggers (configure in your project):
101
101
  * - security-auditor: supabase/migrations/**, auth/**, rls/**
102
- * - beacon-guardian: prompts/**, llm/**
102
+ * - llm-reviewer: prompts/**, llm/**
103
103
  *
104
104
  * Usage:
105
105
  * ```typescript
@@ -51,7 +51,7 @@ export type AgentMetric = z.infer<typeof AgentMetricSchema>;
51
51
  * title: 'LLM Classification Feature',
52
52
  * dodProgress: 8,
53
53
  * dodTotal: 11,
54
- * agents: { 'beacon-guardian': 'pass', 'code-reviewer': 'pending' },
54
+ * agents: { 'llm-reviewer': 'pass', 'code-reviewer': 'pending' },
55
55
  * headline: 'Blocked on code-reviewer - awaiting approval',
56
56
  * };
57
57
  */
@@ -102,7 +102,7 @@ export type Suggestion = z.infer<typeof SuggestionSchema>;
102
102
  * const plan: ExecutionPlan = {
103
103
  * wuId: 'WU-1234',
104
104
  * steps: [
105
- * { order: 1, agent: 'beacon-guardian', status: 'pending' },
105
+ * { order: 1, agent: 'llm-reviewer', status: 'pending' },
106
106
  * { order: 2, action: 'gates', status: 'pending' },
107
107
  * ],
108
108
  * estimatedTokens: 5000,
@@ -21,8 +21,8 @@ export declare const VALIDATION_ERROR_CODE_VALUES: readonly ["WRONG_LOCATION", "
21
21
  * Schema for validation error codes
22
22
  */
23
23
  export declare const ValidationErrorCodeSchema: z.ZodEnum<{
24
- WU_NOT_FOUND: "WU_NOT_FOUND";
25
24
  WRONG_LOCATION: "WRONG_LOCATION";
25
+ WU_NOT_FOUND: "WU_NOT_FOUND";
26
26
  WU_ALREADY_EXISTS: "WU_ALREADY_EXISTS";
27
27
  WRONG_WU_STATUS: "WRONG_WU_STATUS";
28
28
  LANE_OCCUPIED: "LANE_OCCUPIED";
@@ -51,8 +51,8 @@ export declare const PredicateSeveritySchema: z.ZodEnum<{
51
51
  */
52
52
  export declare const ValidationErrorSchema: z.ZodObject<{
53
53
  code: z.ZodEnum<{
54
- WU_NOT_FOUND: "WU_NOT_FOUND";
55
54
  WRONG_LOCATION: "WRONG_LOCATION";
55
+ WU_NOT_FOUND: "WU_NOT_FOUND";
56
56
  WU_ALREADY_EXISTS: "WU_ALREADY_EXISTS";
57
57
  WRONG_WU_STATUS: "WRONG_WU_STATUS";
58
58
  LANE_OCCUPIED: "LANE_OCCUPIED";
@@ -84,8 +84,8 @@ export declare const ValidationResultSchema: z.ZodObject<{
84
84
  valid: z.ZodBoolean;
85
85
  errors: z.ZodArray<z.ZodObject<{
86
86
  code: z.ZodEnum<{
87
- WU_NOT_FOUND: "WU_NOT_FOUND";
88
87
  WRONG_LOCATION: "WRONG_LOCATION";
88
+ WU_NOT_FOUND: "WU_NOT_FOUND";
89
89
  WU_ALREADY_EXISTS: "WU_ALREADY_EXISTS";
90
90
  WRONG_WU_STATUS: "WRONG_WU_STATUS";
91
91
  LANE_OCCUPIED: "LANE_OCCUPIED";
@@ -129,10 +129,10 @@ export declare const CommandDefinitionConfigSchema: z.ZodObject<{
129
129
  name: z.ZodString;
130
130
  description: z.ZodString;
131
131
  requiredLocation: z.ZodNullable<z.ZodEnum<{
132
- unknown: "unknown";
133
132
  main: "main";
134
133
  worktree: "worktree";
135
134
  detached: "detached";
135
+ unknown: "unknown";
136
136
  }>>;
137
137
  requiredWuStatus: z.ZodNullable<z.ZodString>;
138
138
  predicateIds: z.ZodArray<z.ZodString>;
@@ -160,7 +160,7 @@ export function classifyPath(pathStr) {
160
160
  * Remediation messages for each path type
161
161
  */
162
162
  const REMEDIATION_MESSAGES = Object.freeze({
163
- [PATH_TYPES.ROUTE]: 'Route path - use an endpoint constant or config (e.g., BEACON_API_ENDPOINT, API_ROUTES.ASSISTANT)',
163
+ [PATH_TYPES.ROUTE]: 'Route path - use an endpoint constant or config (e.g., API_ENDPOINT, API_ROUTES.ASSISTANT)',
164
164
  [PATH_TYPES.FILESYSTEM]: 'File path - use path.join() with constants',
165
165
  [PATH_TYPES.UNKNOWN]: 'Path string - use a constant or configuration value',
166
166
  });
package/dist/index.d.ts CHANGED
@@ -7,7 +7,6 @@ export * from './arg-parser.js';
7
7
  export * from './date-utils.js';
8
8
  export * from './error-handler.js';
9
9
  export * from './retry-strategy.js';
10
- export * from './beacon-migration.js';
11
10
  export * from './cycle-detector.js';
12
11
  export { DEFAULT_DOMAIN, inferDefaultDomain, normalizeToEmail, isValidEmail, } from './user-normalizer.js';
13
12
  export * from './git-adapter.js';
@@ -52,7 +51,7 @@ export * from './branch-check.js';
52
51
  export * from './agent-patterns-registry.js';
53
52
  export * from './lumenflow-home.js';
54
53
  export * from './force-bypass-audit.js';
55
- export { LUMENFLOW_PATHS, BEACON_PATHS } from './wu-constants.js';
54
+ export { LUMENFLOW_PATHS } from './wu-constants.js';
56
55
  export { STREAM_ERRORS, EXIT_CODES } from './wu-constants.js';
57
56
  export * from './stream-error-handler.js';
58
57
  export * from './color-support.js';
@@ -84,3 +83,4 @@ export { loadManifest, loadTemplate, loadTemplatesWithOverrides, assembleTemplat
84
83
  export { tryAssembleSpawnTemplates, buildTemplateContext } from './wu-spawn.js';
85
84
  export * from './patrol-loop.js';
86
85
  export { resolvePolicy, getDefaultPolicy, MethodologyConfigSchema, MethodologyOverridesSchema, TestingMethodologySchema, ArchitectureMethodologySchema, CoverageModeSchema, TESTING_METHODOLOGY, ARCHITECTURE_METHODOLOGY, COVERAGE_MODE, type ResolvedPolicy, type ResolvePolicyOptions, type MethodologyConfig, type MethodologyOverrides, type TestingMethodology, type ArchitectureMethodology, type CoverageMode, } from './resolve-policy.js';
86
+ export { listWUs, type WUListEntry, type ListWUsOptions } from './wu-list.js';
package/dist/index.js CHANGED
@@ -9,8 +9,6 @@ export * from './arg-parser.js';
9
9
  export * from './date-utils.js';
10
10
  export * from './error-handler.js';
11
11
  export * from './retry-strategy.js';
12
- // Migration utilities (WU-1075)
13
- export * from './beacon-migration.js';
14
12
  // Cycle detection (WU-1088 - extracted from initiatives to break circular dependency)
15
13
  export * from './cycle-detector.js';
16
14
  // User normalizer (explicit exports to avoid conflicts)
@@ -85,7 +83,7 @@ export * from './lumenflow-home.js';
85
83
  // WU-1070: Force bypass audit logging
86
84
  export * from './force-bypass-audit.js';
87
85
  // WU-1075: LumenFlow directory paths (exported from wu-constants)
88
- export { LUMENFLOW_PATHS, BEACON_PATHS } from './wu-constants.js';
86
+ export { LUMENFLOW_PATHS } from './wu-constants.js';
89
87
  // WU-1233: Stream error handling (EPIPE protection)
90
88
  export { STREAM_ERRORS, EXIT_CODES } from './wu-constants.js';
91
89
  export * from './stream-error-handler.js';
@@ -157,3 +155,5 @@ export { tryAssembleSpawnTemplates, buildTemplateContext } from './wu-spawn.js';
157
155
  export * from './patrol-loop.js';
158
156
  // WU-1259: Methodology policy resolution
159
157
  export { resolvePolicy, getDefaultPolicy, MethodologyConfigSchema, MethodologyOverridesSchema, TestingMethodologySchema, ArchitectureMethodologySchema, CoverageModeSchema, TESTING_METHODOLOGY, ARCHITECTURE_METHODOLOGY, COVERAGE_MODE, } from './resolve-policy.js';
158
+ // WU-1411: WU list helper for MCP server and other tools
159
+ export { listWUs } from './wu-list.js';
@@ -18,6 +18,7 @@ import { existsSync, readdirSync, readFileSync } from 'node:fs';
18
18
  import path from 'node:path';
19
19
  import { parseYAML } from '../wu-yaml.js';
20
20
  import { validateAutomatedTestRequirement, isCodeFile } from '../manual-test-validator.js';
21
+ import { DIRECTORIES } from '../wu-constants.js';
21
22
  /**
22
23
  * Invariant metadata
23
24
  */
@@ -31,8 +32,9 @@ export const INVARIANT_TYPE = 'wu-automated-tests';
31
32
  const ACTIVE_STATUSES = Object.freeze(['in_progress', 'blocked']);
32
33
  /**
33
34
  * Default path to WU YAML files relative to base directory.
35
+ * WU-1430: Use centralized constant instead of hardcoded path.
34
36
  */
35
- const WU_YAML_PATH = 'docs/04-operations/tasks/wu';
37
+ const WU_YAML_PATH = DIRECTORIES.WU_DIR;
36
38
  /**
37
39
  * Check a single WU YAML file for automated test requirement.
38
40
  *
@@ -126,9 +126,9 @@ export declare const DirectoriesSchema: z.ZodObject<{
126
126
  onboardingDir: z.ZodDefault<z.ZodString>;
127
127
  }, z.core.$strip>;
128
128
  /**
129
- * Beacon paths configuration (.lumenflow directory structure)
129
+ * State paths configuration (.lumenflow directory structure)
130
130
  */
131
- export declare const BeaconPathsSchema: z.ZodObject<{
131
+ export declare const StatePathsSchema: z.ZodObject<{
132
132
  base: z.ZodDefault<z.ZodString>;
133
133
  stateDir: z.ZodDefault<z.ZodString>;
134
134
  archiveDir: z.ZodDefault<z.ZodString>;
@@ -619,7 +619,7 @@ export declare const LumenFlowConfigSchema: z.ZodObject<{
619
619
  templatesDir: z.ZodDefault<z.ZodString>;
620
620
  onboardingDir: z.ZodDefault<z.ZodString>;
621
621
  }, z.core.$strip>>;
622
- beacon: z.ZodDefault<z.ZodObject<{
622
+ state: z.ZodDefault<z.ZodObject<{
623
623
  base: z.ZodDefault<z.ZodString>;
624
624
  stateDir: z.ZodDefault<z.ZodString>;
625
625
  archiveDir: z.ZodDefault<z.ZodString>;
@@ -876,7 +876,7 @@ export declare const LumenFlowConfigSchema: z.ZodObject<{
876
876
  * TypeScript types inferred from schemas
877
877
  */
878
878
  export type Directories = z.infer<typeof DirectoriesSchema>;
879
- export type BeaconPaths = z.infer<typeof BeaconPathsSchema>;
879
+ export type StatePaths = z.infer<typeof StatePathsSchema>;
880
880
  export type PushRetryConfig = z.infer<typeof PushRetryConfigSchema>;
881
881
  export type GitConfig = z.infer<typeof GitConfigSchema>;
882
882
  export type WuConfig = z.infer<typeof WuConfigSchema>;
@@ -928,7 +928,7 @@ export declare function validateConfig(data: unknown): z.ZodSafeParseResult<{
928
928
  templatesDir: string;
929
929
  onboardingDir: string;
930
930
  };
931
- beacon: {
931
+ state: {
932
932
  base: string;
933
933
  stateDir: string;
934
934
  archiveDir: string;
@@ -164,10 +164,10 @@ export const DirectoriesSchema = z.object({
164
164
  onboardingDir: z.string().default('docs/04-operations/_frameworks/lumenflow/agent/onboarding'),
165
165
  });
166
166
  /**
167
- * Beacon paths configuration (.lumenflow directory structure)
167
+ * State paths configuration (.lumenflow directory structure)
168
168
  */
169
- export const BeaconPathsSchema = z.object({
170
- /** Base beacon directory (default: '.lumenflow') */
169
+ export const StatePathsSchema = z.object({
170
+ /** Base state directory (default: '.lumenflow') */
171
171
  base: z.string().default('.lumenflow'),
172
172
  /** State directory (default: '.lumenflow/state') */
173
173
  stateDir: z.string().default('.lumenflow/state'),
@@ -847,8 +847,8 @@ export const LumenFlowConfigSchema = z.object({
847
847
  version: z.string().default('1.0.0'),
848
848
  /** Directory paths */
849
849
  directories: DirectoriesSchema.default(() => DirectoriesSchema.parse({})),
850
- /** Beacon paths */
851
- beacon: BeaconPathsSchema.default(() => BeaconPathsSchema.parse({})),
850
+ /** State paths (.lumenflow directory structure) */
851
+ state: StatePathsSchema.default(() => StatePathsSchema.parse({})),
852
852
  /** Git configuration */
853
853
  git: GitConfigSchema.default(() => GitConfigSchema.parse({})),
854
854
  /** WU configuration */
@@ -95,5 +95,5 @@ export declare function validateConfigFile(configPath: string): {
95
95
  export declare function createSampleConfig(outputPath: string, options?: {
96
96
  includeComments?: boolean;
97
97
  }): void;
98
- export type { LumenFlowConfig, Directories, BeaconPaths, PushRetryConfig, GitConfig, WuConfig, GatesConfig, MemoryConfig, UiConfig, YamlConfig, } from './lumenflow-config-schema.js';
98
+ export type { LumenFlowConfig, Directories, StatePaths, PushRetryConfig, GitConfig, WuConfig, GatesConfig, MemoryConfig, UiConfig, YamlConfig, } from './lumenflow-config-schema.js';
99
99
  export { getDefaultConfig } from './lumenflow-config-schema.js';
@@ -139,8 +139,8 @@ export function getResolvedPaths(options = {}) {
139
139
  backlogPath: path.join(projectRoot, config.directories.backlogPath),
140
140
  statusPath: path.join(projectRoot, config.directories.statusPath),
141
141
  worktrees: path.join(projectRoot, config.directories.worktrees),
142
- stampsDir: path.join(projectRoot, config.beacon.stampsDir),
143
- stateDir: path.join(projectRoot, config.beacon.stateDir),
142
+ stampsDir: path.join(projectRoot, config.state.stampsDir),
143
+ stateDir: path.join(projectRoot, config.state.stateDir),
144
144
  skillsDir: path.join(projectRoot, config.directories.skillsDir),
145
145
  agentsDir: path.join(projectRoot, config.directories.agentsDir),
146
146
  memoryBank: path.join(projectRoot, config.directories.memoryBank),
@@ -215,11 +215,11 @@ directories:
215
215
  # Onboarding directory
216
216
  onboardingDir: "${defaultConfig.directories.onboardingDir}"
217
217
 
218
- # Beacon paths (.lumenflow directory structure)
219
- beacon:
220
- base: "${defaultConfig.beacon.base}"
221
- stampsDir: "${defaultConfig.beacon.stampsDir}"
222
- stateDir: "${defaultConfig.beacon.stateDir}"
218
+ # State paths (.lumenflow directory structure)
219
+ state:
220
+ base: "${defaultConfig.state.base}"
221
+ stampsDir: "${defaultConfig.state.stampsDir}"
222
+ stateDir: "${defaultConfig.state.stateDir}"
223
223
 
224
224
  # Git configuration
225
225
  git:
@@ -348,7 +348,7 @@ export declare function mergeWithRetry(tempBranchName: string, microWorktreePath
348
348
  * @param {string} logPrefix - Log prefix for console output
349
349
  * @throws {Error} If push fails after all retries
350
350
  */
351
- export declare function pushWithRetry(mainGit: GitAdapter, worktreeGit: GitAdapter, remote: string, branch: string, tempBranchName: string, logPrefix?: string): Promise<void>;
351
+ export declare function pushWithRetry(mainGit: GitAdapter, worktreeGit: GitAdapter, remote: string, branch: string, tempBranchName: string, logPrefix?: string, operation?: string): Promise<void>;
352
352
  /**
353
353
  * WU-1332: Push to origin with configurable retry using p-retry
354
354
  *
@@ -374,7 +374,7 @@ export declare function pushWithRetry(mainGit: GitAdapter, worktreeGit: GitAdapt
374
374
  * @param {PushRetryConfig} config - Push retry configuration
375
375
  * @throws {Error} If push fails after all retries or if retry is disabled
376
376
  */
377
- export declare function pushWithRetryConfig(mainGit: GitAdapter, worktreeGit: GitAdapter, remote: string, branch: string, tempBranchName: string, logPrefix?: string, config?: PushRetryConfig): Promise<void>;
377
+ export declare function pushWithRetryConfig(mainGit: GitAdapter, worktreeGit: GitAdapter, remote: string, branch: string, tempBranchName: string, logPrefix?: string, config?: PushRetryConfig, operation?: string): Promise<void>;
378
378
  /**
379
379
  * Push using refspec with LUMENFLOW_FORCE to bypass pre-push hooks
380
380
  *
@@ -597,42 +597,59 @@ export async function mergeWithRetry(tempBranchName, microWorktreePath, logPrefi
597
597
  * @param {string} logPrefix - Log prefix for console output
598
598
  * @throws {Error} If push fails after all retries
599
599
  */
600
- export async function pushWithRetry(mainGit, worktreeGit, remote, branch, tempBranchName, logPrefix = DEFAULT_LOG_PREFIX) {
600
+ export async function pushWithRetry(mainGit, worktreeGit, remote, branch, tempBranchName, logPrefix = DEFAULT_LOG_PREFIX, operation) {
601
601
  const maxRetries = MAX_PUSH_RETRIES;
602
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
603
- try {
604
- console.log(`${logPrefix} Pushing to ${remote}/${branch} (attempt ${attempt}/${maxRetries})...`);
605
- await mainGit.push(remote, branch);
606
- console.log(`${logPrefix} ✅ Pushed to ${remote}/${branch}`);
607
- return;
602
+ // WU-1418: Save original LUMENFLOW_WU_TOOL value
603
+ const originalWuTool = process.env[LUMENFLOW_WU_TOOL_ENV];
604
+ try {
605
+ // WU-1418: Set LUMENFLOW_WU_TOOL to allow pre-push hook to recognize this as an automated operation
606
+ if (operation) {
607
+ process.env[LUMENFLOW_WU_TOOL_ENV] = operation;
608
608
  }
609
- catch (pushErr) {
610
- if (attempt < maxRetries) {
611
- console.log(`${logPrefix} ⚠️ Push failed (origin moved). Fetching and rebasing before retry...`);
612
- // WU-1348: Do NOT reset main checkout - preserve micro-worktree isolation
613
- // Instead, fetch latest remote state and rebase the temp branch
614
- // Step 1: Fetch latest origin/main
615
- console.log(`${logPrefix} Fetching ${remote}/${branch}...`);
616
- await mainGit.fetch(remote, branch);
617
- // Step 2: Rebase temp branch onto updated origin/main
618
- console.log(`${logPrefix} Rebasing temp branch onto ${remote}/${branch}...`);
619
- await worktreeGit.rebase(`${remote}/${branch}`);
620
- // Step 3: Re-merge temp branch to local main (ff-only)
621
- // This updates local main to include the rebased commits
622
- console.log(`${logPrefix} Re-merging temp branch to ${branch}...`);
623
- await mainGit.merge(tempBranchName, { ffOnly: true });
609
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
610
+ try {
611
+ console.log(`${logPrefix} Pushing to ${remote}/${branch} (attempt ${attempt}/${maxRetries})...`);
612
+ await mainGit.push(remote, branch);
613
+ console.log(`${logPrefix} Pushed to ${remote}/${branch}`);
614
+ return;
624
615
  }
625
- else {
626
- const errMsg = pushErr instanceof Error ? pushErr.message : String(pushErr);
627
- throw new Error(`Push failed after ${maxRetries} attempts. ` +
628
- `Origin ${branch} may have significant traffic.\n\n` +
629
- `Suggestions:\n` +
630
- ` - Wait a few seconds and retry the operation\n` +
631
- ` - Check if another agent is rapidly pushing changes\n` +
632
- `Error: ${errMsg}`);
616
+ catch (pushErr) {
617
+ if (attempt < maxRetries) {
618
+ console.log(`${logPrefix} ⚠️ Push failed (origin moved). Fetching and rebasing before retry...`);
619
+ // WU-1348: Do NOT reset main checkout - preserve micro-worktree isolation
620
+ // Instead, fetch latest remote state and rebase the temp branch
621
+ // Step 1: Fetch latest origin/main
622
+ console.log(`${logPrefix} Fetching ${remote}/${branch}...`);
623
+ await mainGit.fetch(remote, branch);
624
+ // Step 2: Rebase temp branch onto updated origin/main
625
+ console.log(`${logPrefix} Rebasing temp branch onto ${remote}/${branch}...`);
626
+ await worktreeGit.rebase(`${remote}/${branch}`);
627
+ // Step 3: Re-merge temp branch to local main (ff-only)
628
+ // This updates local main to include the rebased commits
629
+ console.log(`${logPrefix} Re-merging temp branch to ${branch}...`);
630
+ await mainGit.merge(tempBranchName, { ffOnly: true });
631
+ }
632
+ else {
633
+ const errMsg = pushErr instanceof Error ? pushErr.message : String(pushErr);
634
+ throw new Error(`Push failed after ${maxRetries} attempts. ` +
635
+ `Origin ${branch} may have significant traffic.\n\n` +
636
+ `Suggestions:\n` +
637
+ ` - Wait a few seconds and retry the operation\n` +
638
+ ` - Check if another agent is rapidly pushing changes\n` +
639
+ `Error: ${errMsg}`);
640
+ }
633
641
  }
634
642
  }
635
643
  }
644
+ finally {
645
+ // WU-1418: Restore original LUMENFLOW_WU_TOOL value
646
+ if (originalWuTool === undefined) {
647
+ Reflect.deleteProperty(process.env, LUMENFLOW_WU_TOOL_ENV);
648
+ }
649
+ else {
650
+ process.env[LUMENFLOW_WU_TOOL_ENV] = originalWuTool;
651
+ }
652
+ }
636
653
  }
637
654
  /**
638
655
  * WU-1332: Push to origin with configurable retry using p-retry
@@ -659,56 +676,73 @@ export async function pushWithRetry(mainGit, worktreeGit, remote, branch, tempBr
659
676
  * @param {PushRetryConfig} config - Push retry configuration
660
677
  * @throws {Error} If push fails after all retries or if retry is disabled
661
678
  */
662
- export async function pushWithRetryConfig(mainGit, worktreeGit, remote, branch, tempBranchName, logPrefix = DEFAULT_LOG_PREFIX, config = DEFAULT_PUSH_RETRY_CONFIG) {
663
- // If retry is disabled, just try once and throw on failure
664
- if (!config.enabled) {
665
- console.log(`${logPrefix} Pushing to ${remote}/${branch} (retry disabled)...`);
666
- await mainGit.push(remote, branch);
667
- console.log(`${logPrefix} ✅ Pushed to ${remote}/${branch}`);
668
- return;
669
- }
670
- let attemptNumber = 0;
671
- await pRetry(async () => {
672
- attemptNumber++;
673
- console.log(`${logPrefix} Pushing to ${remote}/${branch} (attempt ${attemptNumber}/${config.retries})...`);
674
- try {
679
+ export async function pushWithRetryConfig(mainGit, worktreeGit, remote, branch, tempBranchName, logPrefix = DEFAULT_LOG_PREFIX, config = DEFAULT_PUSH_RETRY_CONFIG, operation) {
680
+ // WU-1418: Save original LUMENFLOW_WU_TOOL value
681
+ const originalWuTool = process.env[LUMENFLOW_WU_TOOL_ENV];
682
+ try {
683
+ // WU-1418: Set LUMENFLOW_WU_TOOL to allow pre-push hook to recognize this as an automated operation
684
+ if (operation) {
685
+ process.env[LUMENFLOW_WU_TOOL_ENV] = operation;
686
+ }
687
+ // If retry is disabled, just try once and throw on failure
688
+ if (!config.enabled) {
689
+ console.log(`${logPrefix} Pushing to ${remote}/${branch} (retry disabled)...`);
675
690
  await mainGit.push(remote, branch);
676
691
  console.log(`${logPrefix} ✅ Pushed to ${remote}/${branch}`);
692
+ return;
677
693
  }
678
- catch (pushErr) {
679
- console.log(`${logPrefix} ⚠️ Push failed (origin moved). Fetching and rebasing before retry...`);
680
- // WU-1348: Do NOT reset main checkout - preserve micro-worktree isolation
681
- // Instead, fetch latest remote state and rebase the temp branch
682
- // Fetch latest origin/main
683
- console.log(`${logPrefix} Fetching ${remote}/${branch}...`);
684
- await mainGit.fetch(remote, branch);
685
- // Rebase temp branch onto updated origin/main
686
- console.log(`${logPrefix} Rebasing temp branch onto ${remote}/${branch}...`);
687
- await worktreeGit.rebase(`${remote}/${branch}`);
688
- // Re-merge temp branch to local main (ff-only)
689
- // This updates local main to include the rebased commits
690
- console.log(`${logPrefix} Re-merging temp branch to ${branch}...`);
691
- await mainGit.merge(tempBranchName, { ffOnly: true });
692
- // Re-throw to trigger p-retry
693
- throw pushErr;
694
+ let attemptNumber = 0;
695
+ await pRetry(async () => {
696
+ attemptNumber++;
697
+ console.log(`${logPrefix} Pushing to ${remote}/${branch} (attempt ${attemptNumber}/${config.retries})...`);
698
+ try {
699
+ await mainGit.push(remote, branch);
700
+ console.log(`${logPrefix} ✅ Pushed to ${remote}/${branch}`);
701
+ }
702
+ catch (pushErr) {
703
+ console.log(`${logPrefix} ⚠️ Push failed (origin moved). Fetching and rebasing before retry...`);
704
+ // WU-1348: Do NOT reset main checkout - preserve micro-worktree isolation
705
+ // Instead, fetch latest remote state and rebase the temp branch
706
+ // Fetch latest origin/main
707
+ console.log(`${logPrefix} Fetching ${remote}/${branch}...`);
708
+ await mainGit.fetch(remote, branch);
709
+ // Rebase temp branch onto updated origin/main
710
+ console.log(`${logPrefix} Rebasing temp branch onto ${remote}/${branch}...`);
711
+ await worktreeGit.rebase(`${remote}/${branch}`);
712
+ // Re-merge temp branch to local main (ff-only)
713
+ // This updates local main to include the rebased commits
714
+ console.log(`${logPrefix} Re-merging temp branch to ${branch}...`);
715
+ await mainGit.merge(tempBranchName, { ffOnly: true });
716
+ // Re-throw to trigger p-retry
717
+ throw pushErr;
718
+ }
719
+ }, {
720
+ retries: config.retries - 1, // p-retry counts retries after first attempt
721
+ minTimeout: config.min_delay_ms,
722
+ maxTimeout: config.max_delay_ms,
723
+ randomize: config.jitter,
724
+ onFailedAttempt: () => {
725
+ // Logging is handled in the try/catch above
726
+ },
727
+ }).catch(() => {
728
+ // p-retry exhausted all retries, throw descriptive error
729
+ throw new Error(`Push failed after ${config.retries} attempts. ` +
730
+ `Origin ${branch} may have significant traffic.\n\n` +
731
+ `Suggestions:\n` +
732
+ ` - Wait a few seconds and retry the operation\n` +
733
+ ` - Increase git.push_retry.retries in .lumenflow.config.yaml\n` +
734
+ ` - Check if another agent is rapidly pushing changes`);
735
+ });
736
+ }
737
+ finally {
738
+ // WU-1418: Restore original LUMENFLOW_WU_TOOL value
739
+ if (originalWuTool === undefined) {
740
+ Reflect.deleteProperty(process.env, LUMENFLOW_WU_TOOL_ENV);
694
741
  }
695
- }, {
696
- retries: config.retries - 1, // p-retry counts retries after first attempt
697
- minTimeout: config.min_delay_ms,
698
- maxTimeout: config.max_delay_ms,
699
- randomize: config.jitter,
700
- onFailedAttempt: () => {
701
- // Logging is handled in the try/catch above
702
- },
703
- }).catch(() => {
704
- // p-retry exhausted all retries, throw descriptive error
705
- throw new Error(`Push failed after ${config.retries} attempts. ` +
706
- `Origin ${branch} may have significant traffic.\n\n` +
707
- `Suggestions:\n` +
708
- ` - Wait a few seconds and retry the operation\n` +
709
- ` - Increase git.push_retry.retries in .lumenflow.config.yaml\n` +
710
- ` - Check if another agent is rapidly pushing changes`);
711
- });
742
+ else {
743
+ process.env[LUMENFLOW_WU_TOOL_ENV] = originalWuTool;
744
+ }
745
+ }
712
746
  }
713
747
  /**
714
748
  * Push using refspec with LUMENFLOW_FORCE to bypass pre-push hooks
@@ -921,7 +955,8 @@ export async function withMicroWorktree(options) {
921
955
  await mergeWithRetry(tempBranchName, microWorktreePath, logPrefix);
922
956
  // WU-1179: Use pushWithRetry to handle race conditions
923
957
  // On push failure, rollback local main and retry with rebase
924
- await pushWithRetry(mainGit, gitWorktree, REMOTES.ORIGIN, BRANCHES.MAIN, tempBranchName, logPrefix);
958
+ // WU-1418: Pass operation name to set LUMENFLOW_WU_TOOL for pre-push hook bypass
959
+ await pushWithRetry(mainGit, gitWorktree, REMOTES.ORIGIN, BRANCHES.MAIN, tempBranchName, logPrefix, operation);
925
960
  return { ...result, ref: BRANCHES.MAIN };
926
961
  }
927
962
  }
@@ -127,7 +127,7 @@ const AGENT_TRIGGER_DESCRIPTIONS = {
127
127
  // No mandatory agent triggers for LumenFlow framework development.
128
128
  // Example for application-specific triggers:
129
129
  // 'security-auditor': 'supabase/migrations/**, auth/**, rls/**',
130
- // 'beacon-guardian': 'prompts/**, llm/**',
130
+ // 'llm-reviewer': 'prompts/**, llm/**',
131
131
  };
132
132
  /**
133
133
  * WU-1542: Build a formatted error message for mandatory agent enforcement failures.