@lumenflow/core 1.5.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +325 -1
  2. package/dist/adapters/context-adapters.d.ts +90 -0
  3. package/dist/adapters/context-adapters.js +99 -0
  4. package/dist/adapters/index.d.ts +14 -0
  5. package/dist/adapters/index.js +18 -0
  6. package/dist/adapters/recovery-adapters.d.ts +40 -0
  7. package/dist/adapters/recovery-adapters.js +43 -0
  8. package/dist/adapters/validation-adapters.d.ts +52 -0
  9. package/dist/adapters/validation-adapters.js +59 -0
  10. package/dist/context/context-computer.d.ts +46 -0
  11. package/dist/context/context-computer.js +125 -0
  12. package/dist/context/git-state-reader.d.ts +51 -0
  13. package/dist/context/git-state-reader.js +61 -0
  14. package/dist/context/index.d.ts +17 -0
  15. package/dist/context/index.js +17 -0
  16. package/dist/context/location-resolver.d.ts +48 -0
  17. package/dist/context/location-resolver.js +175 -0
  18. package/dist/context/wu-state-reader.d.ts +37 -0
  19. package/dist/context/wu-state-reader.js +76 -0
  20. package/dist/context-di.d.ts +184 -0
  21. package/dist/context-di.js +178 -0
  22. package/dist/context-validation-integration.d.ts +77 -0
  23. package/dist/context-validation-integration.js +157 -0
  24. package/dist/domain/context.schemas.d.ts +147 -0
  25. package/dist/domain/context.schemas.js +126 -0
  26. package/dist/domain/index.d.ts +14 -0
  27. package/dist/domain/index.js +18 -0
  28. package/dist/domain/recovery.schemas.d.ts +115 -0
  29. package/dist/domain/recovery.schemas.js +83 -0
  30. package/dist/domain/validation.schemas.d.ts +146 -0
  31. package/dist/domain/validation.schemas.js +114 -0
  32. package/dist/index.d.ts +17 -0
  33. package/dist/index.js +43 -0
  34. package/dist/lumenflow-config-schema.d.ts +41 -0
  35. package/dist/lumenflow-config-schema.js +37 -0
  36. package/dist/ports/context.ports.d.ts +135 -0
  37. package/dist/ports/context.ports.js +21 -0
  38. package/dist/ports/core-tools.ports.d.ts +266 -0
  39. package/dist/ports/core-tools.ports.js +21 -0
  40. package/dist/ports/git-validator.ports.d.ts +314 -0
  41. package/dist/ports/git-validator.ports.js +12 -0
  42. package/dist/ports/index.d.ts +20 -0
  43. package/dist/ports/index.js +20 -0
  44. package/dist/ports/recovery.ports.d.ts +58 -0
  45. package/dist/ports/recovery.ports.js +17 -0
  46. package/dist/ports/validation.ports.d.ts +74 -0
  47. package/dist/ports/validation.ports.js +17 -0
  48. package/dist/ports/wu-helpers.ports.d.ts +224 -0
  49. package/dist/ports/wu-helpers.ports.js +12 -0
  50. package/dist/recovery/index.d.ts +11 -0
  51. package/dist/recovery/index.js +11 -0
  52. package/dist/recovery/recovery-analyzer.d.ts +66 -0
  53. package/dist/recovery/recovery-analyzer.js +129 -0
  54. package/dist/usecases/analyze-recovery.usecase.d.ts +42 -0
  55. package/dist/usecases/analyze-recovery.usecase.js +45 -0
  56. package/dist/usecases/compute-context.usecase.d.ts +62 -0
  57. package/dist/usecases/compute-context.usecase.js +101 -0
  58. package/dist/usecases/index.d.ts +14 -0
  59. package/dist/usecases/index.js +18 -0
  60. package/dist/usecases/validate-command.usecase.d.ts +55 -0
  61. package/dist/usecases/validate-command.usecase.js +154 -0
  62. package/dist/validation/command-registry.d.ts +38 -0
  63. package/dist/validation/command-registry.js +229 -0
  64. package/dist/validation/index.d.ts +15 -0
  65. package/dist/validation/index.js +15 -0
  66. package/dist/validation/types.d.ts +135 -0
  67. package/dist/validation/types.js +11 -0
  68. package/dist/validation/validate-command.d.ts +27 -0
  69. package/dist/validation/validate-command.js +160 -0
  70. package/dist/wu-constants.d.ts +136 -0
  71. package/dist/wu-constants.js +124 -0
  72. package/dist/wu-helpers.d.ts +5 -1
  73. package/dist/wu-helpers.js +12 -1
  74. package/package.json +4 -2
@@ -0,0 +1,76 @@
1
+ /**
2
+ * WU State Reader for WU Context
3
+ *
4
+ * WU-1090: Context-aware state machine for WU lifecycle commands
5
+ *
6
+ * Reads WU state from YAML file and optionally cross-references
7
+ * with state store for inconsistency detection.
8
+ *
9
+ * @module
10
+ */
11
+ import { existsSync, readFileSync } from 'node:fs';
12
+ import { join } from 'node:path';
13
+ import { parse as parseYaml } from 'yaml';
14
+ import { DIRECTORIES } from '../wu-constants.js';
15
+ /**
16
+ * Normalize WU ID to uppercase format.
17
+ */
18
+ function normalizeWuId(id) {
19
+ const upper = id.toUpperCase();
20
+ // Ensure it starts with WU-
21
+ if (upper.startsWith('WU-'))
22
+ return upper;
23
+ return `WU-${upper.replace(/^WU-?/i, '')}`;
24
+ }
25
+ /**
26
+ * Build the path to WU YAML file.
27
+ */
28
+ function getWuYamlPath(wuId, repoRoot) {
29
+ const normalizedId = normalizeWuId(wuId);
30
+ return join(repoRoot, DIRECTORIES.WU_DIR, `${normalizedId}.yaml`);
31
+ }
32
+ /**
33
+ * Read WU state from YAML and detect inconsistencies.
34
+ *
35
+ * @param wuId - WU ID (e.g., 'WU-1090' or 'wu-1090')
36
+ * @param repoRoot - Repository root path
37
+ * @returns WuStateResult or null if WU not found
38
+ */
39
+ export async function readWuState(wuId, repoRoot) {
40
+ const normalizedId = normalizeWuId(wuId);
41
+ const yamlPath = getWuYamlPath(normalizedId, repoRoot);
42
+ // Check if YAML exists
43
+ if (!existsSync(yamlPath)) {
44
+ return null;
45
+ }
46
+ try {
47
+ // Read and parse YAML
48
+ const content = readFileSync(yamlPath, 'utf8');
49
+ const yaml = parseYaml(content);
50
+ if (!yaml || typeof yaml !== 'object') {
51
+ return null;
52
+ }
53
+ // Extract fields with defaults
54
+ const status = yaml.status || 'unknown';
55
+ const lane = yaml.lane || '';
56
+ const title = yaml.title || '';
57
+ // For now, we consider YAML-only reading as consistent
58
+ // Full state store integration would compare with wu-events.jsonl
59
+ // That can be added when the state store is properly integrated
60
+ const isConsistent = true;
61
+ const inconsistencyReason = null;
62
+ return {
63
+ id: normalizedId,
64
+ status,
65
+ lane,
66
+ title,
67
+ yamlPath,
68
+ isConsistent,
69
+ inconsistencyReason,
70
+ };
71
+ }
72
+ catch {
73
+ // Parse error or read error
74
+ return null;
75
+ }
76
+ }
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Context Dependency Injection
3
+ *
4
+ * WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
5
+ *
6
+ * Composition root for wiring concrete adapter implementations to use cases.
7
+ * This file provides factory functions for creating use cases with default
8
+ * or custom adapters.
9
+ *
10
+ * Design Principles:
11
+ * - Factory functions return fully wired use cases
12
+ * - Custom adapters can be injected for testing
13
+ * - Legacy function exports maintain backwards compatibility
14
+ *
15
+ * @module context-di
16
+ */
17
+ import type { ILocationResolver, IGitStateReader, IWuStateReader } from './ports/context.ports.js';
18
+ import type { ICommandRegistry } from './ports/validation.ports.js';
19
+ import type { IRecoveryAnalyzer, WuContext, RecoveryAnalysis } from './ports/recovery.ports.js';
20
+ import type { ValidationResult } from './validation/types.js';
21
+ import { ComputeContextUseCase, type ComputeContextOptions } from './usecases/compute-context.usecase.js';
22
+ import { ValidateCommandUseCase } from './usecases/validate-command.usecase.js';
23
+ import { AnalyzeRecoveryUseCase } from './usecases/analyze-recovery.usecase.js';
24
+ /**
25
+ * Context adapters bundle.
26
+ */
27
+ export interface ContextAdapters {
28
+ locationResolver: ILocationResolver;
29
+ gitStateReader: IGitStateReader;
30
+ wuStateReader: IWuStateReader;
31
+ }
32
+ /**
33
+ * Create all context adapters with default implementations.
34
+ *
35
+ * @example
36
+ * const adapters = createContextAdapters();
37
+ * const location = await adapters.locationResolver.resolveLocation();
38
+ */
39
+ export declare function createContextAdapters(): ContextAdapters;
40
+ /**
41
+ * Validation adapters bundle.
42
+ */
43
+ export interface ValidationAdapters {
44
+ commandRegistry: ICommandRegistry;
45
+ }
46
+ /**
47
+ * Create all validation adapters with default implementations.
48
+ *
49
+ * @example
50
+ * const adapters = createValidationAdapters();
51
+ * const def = adapters.commandRegistry.getCommandDefinition('wu:done');
52
+ */
53
+ export declare function createValidationAdapters(): ValidationAdapters;
54
+ /**
55
+ * Recovery adapters bundle.
56
+ */
57
+ export interface RecoveryAdapters {
58
+ recoveryAnalyzer: IRecoveryAnalyzer;
59
+ }
60
+ /**
61
+ * Create all recovery adapters with default implementations.
62
+ *
63
+ * @example
64
+ * const adapters = createRecoveryAdapters();
65
+ * const analysis = await adapters.recoveryAnalyzer.analyzeRecovery(context);
66
+ */
67
+ export declare function createRecoveryAdapters(): RecoveryAdapters;
68
+ /**
69
+ * Options for creating ComputeContextUseCase.
70
+ * All adapters are optional - defaults will be used if not provided.
71
+ */
72
+ export interface CreateComputeContextOptions {
73
+ locationResolver?: ILocationResolver;
74
+ gitStateReader?: IGitStateReader;
75
+ wuStateReader?: IWuStateReader;
76
+ }
77
+ /**
78
+ * Create a ComputeContextUseCase with default or custom adapters.
79
+ *
80
+ * @example
81
+ * // Use default adapters
82
+ * const useCase = createComputeContextUseCase();
83
+ * const context = await useCase.execute({ wuId: 'WU-1094' });
84
+ *
85
+ * @example
86
+ * // Use custom adapters for testing
87
+ * const useCase = createComputeContextUseCase({
88
+ * locationResolver: mockLocationResolver,
89
+ * });
90
+ */
91
+ export declare function createComputeContextUseCase(options?: CreateComputeContextOptions): ComputeContextUseCase;
92
+ /**
93
+ * Options for creating ValidateCommandUseCase.
94
+ */
95
+ export interface CreateValidateCommandOptions {
96
+ commandRegistry?: ICommandRegistry;
97
+ }
98
+ /**
99
+ * Create a ValidateCommandUseCase with default or custom registry.
100
+ *
101
+ * @example
102
+ * // Use default registry
103
+ * const useCase = createValidateCommandUseCase();
104
+ * const result = await useCase.execute('wu:done', context);
105
+ *
106
+ * @example
107
+ * // Use custom registry for testing
108
+ * const useCase = createValidateCommandUseCase({
109
+ * commandRegistry: mockRegistry,
110
+ * });
111
+ */
112
+ export declare function createValidateCommandUseCase(options?: CreateValidateCommandOptions): ValidateCommandUseCase;
113
+ /**
114
+ * Options for creating AnalyzeRecoveryUseCase.
115
+ */
116
+ export interface CreateAnalyzeRecoveryOptions {
117
+ recoveryAnalyzer?: IRecoveryAnalyzer;
118
+ }
119
+ /**
120
+ * Create an AnalyzeRecoveryUseCase with default or custom analyzer.
121
+ *
122
+ * @example
123
+ * // Use default analyzer
124
+ * const useCase = createAnalyzeRecoveryUseCase();
125
+ * const analysis = await useCase.execute(context);
126
+ *
127
+ * @example
128
+ * // Use custom analyzer for testing
129
+ * const useCase = createAnalyzeRecoveryUseCase({
130
+ * recoveryAnalyzer: mockAnalyzer,
131
+ * });
132
+ */
133
+ export declare function createAnalyzeRecoveryUseCase(options?: CreateAnalyzeRecoveryOptions): AnalyzeRecoveryUseCase;
134
+ /**
135
+ * Compute WU context for the given options.
136
+ *
137
+ * This is a convenience function that creates a use case with default adapters
138
+ * and executes it. Use createComputeContextUseCase() for more control.
139
+ *
140
+ * @param options - Options including optional wuId and cwd
141
+ * @returns Promise<WuContext> - Computed WU context
142
+ *
143
+ * @example
144
+ * const context = await computeWuContext({ wuId: 'WU-1094' });
145
+ * console.log(context.location.type); // 'main' or 'worktree'
146
+ */
147
+ export declare function computeWuContext(options?: ComputeContextOptions): Promise<WuContext>;
148
+ /**
149
+ * Validate a command against the given context.
150
+ *
151
+ * This is a convenience function that creates a use case with default registry
152
+ * and executes it. Use createValidateCommandUseCase() for more control.
153
+ *
154
+ * @param command - Command name (e.g., 'wu:done')
155
+ * @param context - Current WU context
156
+ * @returns Promise<ValidationResult> - Validation result
157
+ *
158
+ * @example
159
+ * const context = await computeWuContext({ wuId: 'WU-1094' });
160
+ * const result = await validateCommand('wu:done', context);
161
+ * if (!result.valid) {
162
+ * console.error(result.errors[0].message);
163
+ * }
164
+ */
165
+ export declare function validateCommand(command: string, context: WuContext): Promise<ValidationResult>;
166
+ /**
167
+ * Analyze recovery issues for the given context.
168
+ *
169
+ * This is a convenience function that creates a use case with default analyzer
170
+ * and executes it. Use createAnalyzeRecoveryUseCase() for more control.
171
+ *
172
+ * @param context - Current WU context
173
+ * @returns Promise<RecoveryAnalysis> - Recovery analysis
174
+ *
175
+ * @example
176
+ * const context = await computeWuContext({ wuId: 'WU-1094' });
177
+ * const analysis = await analyzeRecoveryIssues(context);
178
+ * if (analysis.hasIssues) {
179
+ * console.log('Issues:', analysis.issues);
180
+ * console.log('Suggested actions:', analysis.actions);
181
+ * }
182
+ */
183
+ export declare function analyzeRecoveryIssues(context: WuContext): Promise<RecoveryAnalysis>;
184
+ export type { ComputeContextOptions };
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Context Dependency Injection
3
+ *
4
+ * WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
5
+ *
6
+ * Composition root for wiring concrete adapter implementations to use cases.
7
+ * This file provides factory functions for creating use cases with default
8
+ * or custom adapters.
9
+ *
10
+ * Design Principles:
11
+ * - Factory functions return fully wired use cases
12
+ * - Custom adapters can be injected for testing
13
+ * - Legacy function exports maintain backwards compatibility
14
+ *
15
+ * @module context-di
16
+ */
17
+ // Import adapters
18
+ import { SimpleGitLocationAdapter, SimpleGitStateAdapter, FileSystemWuStateAdapter, } from './adapters/context-adapters.js';
19
+ import { CommandRegistryAdapter } from './adapters/validation-adapters.js';
20
+ import { RecoveryAnalyzerAdapter } from './adapters/recovery-adapters.js';
21
+ // Import use cases
22
+ import { ComputeContextUseCase, } from './usecases/compute-context.usecase.js';
23
+ import { ValidateCommandUseCase } from './usecases/validate-command.usecase.js';
24
+ import { AnalyzeRecoveryUseCase } from './usecases/analyze-recovery.usecase.js';
25
+ /**
26
+ * Create all context adapters with default implementations.
27
+ *
28
+ * @example
29
+ * const adapters = createContextAdapters();
30
+ * const location = await adapters.locationResolver.resolveLocation();
31
+ */
32
+ export function createContextAdapters() {
33
+ return {
34
+ locationResolver: new SimpleGitLocationAdapter(),
35
+ gitStateReader: new SimpleGitStateAdapter(),
36
+ wuStateReader: new FileSystemWuStateAdapter(),
37
+ };
38
+ }
39
+ /**
40
+ * Create all validation adapters with default implementations.
41
+ *
42
+ * @example
43
+ * const adapters = createValidationAdapters();
44
+ * const def = adapters.commandRegistry.getCommandDefinition('wu:done');
45
+ */
46
+ export function createValidationAdapters() {
47
+ return {
48
+ commandRegistry: new CommandRegistryAdapter(),
49
+ };
50
+ }
51
+ /**
52
+ * Create all recovery adapters with default implementations.
53
+ *
54
+ * @example
55
+ * const adapters = createRecoveryAdapters();
56
+ * const analysis = await adapters.recoveryAnalyzer.analyzeRecovery(context);
57
+ */
58
+ export function createRecoveryAdapters() {
59
+ return {
60
+ recoveryAnalyzer: new RecoveryAnalyzerAdapter(),
61
+ };
62
+ }
63
+ /**
64
+ * Create a ComputeContextUseCase with default or custom adapters.
65
+ *
66
+ * @example
67
+ * // Use default adapters
68
+ * const useCase = createComputeContextUseCase();
69
+ * const context = await useCase.execute({ wuId: 'WU-1094' });
70
+ *
71
+ * @example
72
+ * // Use custom adapters for testing
73
+ * const useCase = createComputeContextUseCase({
74
+ * locationResolver: mockLocationResolver,
75
+ * });
76
+ */
77
+ export function createComputeContextUseCase(options = {}) {
78
+ const defaults = createContextAdapters();
79
+ return new ComputeContextUseCase(options.locationResolver ?? defaults.locationResolver, options.gitStateReader ?? defaults.gitStateReader, options.wuStateReader ?? defaults.wuStateReader);
80
+ }
81
+ /**
82
+ * Create a ValidateCommandUseCase with default or custom registry.
83
+ *
84
+ * @example
85
+ * // Use default registry
86
+ * const useCase = createValidateCommandUseCase();
87
+ * const result = await useCase.execute('wu:done', context);
88
+ *
89
+ * @example
90
+ * // Use custom registry for testing
91
+ * const useCase = createValidateCommandUseCase({
92
+ * commandRegistry: mockRegistry,
93
+ * });
94
+ */
95
+ export function createValidateCommandUseCase(options = {}) {
96
+ const defaults = createValidationAdapters();
97
+ return new ValidateCommandUseCase(options.commandRegistry ?? defaults.commandRegistry);
98
+ }
99
+ /**
100
+ * Create an AnalyzeRecoveryUseCase with default or custom analyzer.
101
+ *
102
+ * @example
103
+ * // Use default analyzer
104
+ * const useCase = createAnalyzeRecoveryUseCase();
105
+ * const analysis = await useCase.execute(context);
106
+ *
107
+ * @example
108
+ * // Use custom analyzer for testing
109
+ * const useCase = createAnalyzeRecoveryUseCase({
110
+ * recoveryAnalyzer: mockAnalyzer,
111
+ * });
112
+ */
113
+ export function createAnalyzeRecoveryUseCase(options = {}) {
114
+ const defaults = createRecoveryAdapters();
115
+ return new AnalyzeRecoveryUseCase(options.recoveryAnalyzer ?? defaults.recoveryAnalyzer);
116
+ }
117
+ // ============================================================================
118
+ // Backwards Compatible Function Exports
119
+ // ============================================================================
120
+ /**
121
+ * Compute WU context for the given options.
122
+ *
123
+ * This is a convenience function that creates a use case with default adapters
124
+ * and executes it. Use createComputeContextUseCase() for more control.
125
+ *
126
+ * @param options - Options including optional wuId and cwd
127
+ * @returns Promise<WuContext> - Computed WU context
128
+ *
129
+ * @example
130
+ * const context = await computeWuContext({ wuId: 'WU-1094' });
131
+ * console.log(context.location.type); // 'main' or 'worktree'
132
+ */
133
+ export async function computeWuContext(options = {}) {
134
+ const useCase = createComputeContextUseCase();
135
+ return useCase.execute(options);
136
+ }
137
+ /**
138
+ * Validate a command against the given context.
139
+ *
140
+ * This is a convenience function that creates a use case with default registry
141
+ * and executes it. Use createValidateCommandUseCase() for more control.
142
+ *
143
+ * @param command - Command name (e.g., 'wu:done')
144
+ * @param context - Current WU context
145
+ * @returns Promise<ValidationResult> - Validation result
146
+ *
147
+ * @example
148
+ * const context = await computeWuContext({ wuId: 'WU-1094' });
149
+ * const result = await validateCommand('wu:done', context);
150
+ * if (!result.valid) {
151
+ * console.error(result.errors[0].message);
152
+ * }
153
+ */
154
+ export async function validateCommand(command, context) {
155
+ const useCase = createValidateCommandUseCase();
156
+ return useCase.execute(command, context);
157
+ }
158
+ /**
159
+ * Analyze recovery issues for the given context.
160
+ *
161
+ * This is a convenience function that creates a use case with default analyzer
162
+ * and executes it. Use createAnalyzeRecoveryUseCase() for more control.
163
+ *
164
+ * @param context - Current WU context
165
+ * @returns Promise<RecoveryAnalysis> - Recovery analysis
166
+ *
167
+ * @example
168
+ * const context = await computeWuContext({ wuId: 'WU-1094' });
169
+ * const analysis = await analyzeRecoveryIssues(context);
170
+ * if (analysis.hasIssues) {
171
+ * console.log('Issues:', analysis.issues);
172
+ * console.log('Suggested actions:', analysis.actions);
173
+ * }
174
+ */
175
+ export async function analyzeRecoveryIssues(context) {
176
+ const useCase = createAnalyzeRecoveryUseCase();
177
+ return useCase.execute(context);
178
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Context Validation Integration
3
+ *
4
+ * WU-1090: Context-aware state machine for WU lifecycle commands
5
+ *
6
+ * Shared module for integrating context validation into CLI commands.
7
+ * Reads validation_mode from config and applies validation accordingly.
8
+ *
9
+ * @module
10
+ */
11
+ import type { WuContext, ValidationResult } from './validation/types.js';
12
+ declare const COMMANDS: {
13
+ readonly WU_CREATE: "wu:create";
14
+ readonly WU_CLAIM: "wu:claim";
15
+ readonly WU_DONE: "wu:done";
16
+ readonly WU_BLOCK: "wu:block";
17
+ readonly WU_UNBLOCK: "wu:unblock";
18
+ readonly WU_STATUS: "wu:status";
19
+ readonly WU_RECOVER: "wu:recover";
20
+ readonly GATES: "gates";
21
+ };
22
+ /**
23
+ * Validation mode from config
24
+ */
25
+ export type ValidationMode = 'off' | 'warn' | 'error';
26
+ /**
27
+ * Result of running context validation
28
+ */
29
+ export interface ContextValidationResult {
30
+ /** Whether the command can proceed */
31
+ canProceed: boolean;
32
+ /** The computed context */
33
+ context: WuContext;
34
+ /** Validation result (null if validation was off) */
35
+ validation: ValidationResult | null;
36
+ /** Validation mode that was applied */
37
+ mode: ValidationMode;
38
+ /** Formatted output for display (if any) */
39
+ output: string | null;
40
+ }
41
+ /**
42
+ * Get validation mode from config
43
+ */
44
+ export declare function getValidationMode(): ValidationMode;
45
+ /**
46
+ * Check if next steps should be shown
47
+ */
48
+ export declare function shouldShowNextSteps(): boolean;
49
+ /**
50
+ * Format next steps for display
51
+ */
52
+ export declare function formatNextSteps(context: WuContext, commandName: string): string;
53
+ /**
54
+ * Run context validation for a command
55
+ *
56
+ * @param commandName - The wu:* command name (e.g., 'wu:claim')
57
+ * @param wuId - Optional WU ID for context
58
+ * @returns ContextValidationResult
59
+ */
60
+ export declare function runContextValidation(commandName: string, wuId?: string): Promise<ContextValidationResult>;
61
+ /**
62
+ * Apply context validation to a command
63
+ *
64
+ * This is the main integration function. It:
65
+ * 1. Runs validation according to config
66
+ * 2. Logs warnings/errors as appropriate
67
+ * 3. Returns whether the command should proceed
68
+ * 4. Exits with error if mode is 'error' and validation fails
69
+ *
70
+ * @param commandName - The wu:* command name
71
+ * @param wuId - Optional WU ID for context
72
+ * @param logPrefix - Log prefix for output
73
+ * @returns The computed context if validation passes
74
+ * @throws Exits process if mode is 'error' and validation fails
75
+ */
76
+ export declare function applyContextValidation(commandName: string, wuId?: string, logPrefix?: string): Promise<WuContext>;
77
+ export { COMMANDS };
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Context Validation Integration
3
+ *
4
+ * WU-1090: Context-aware state machine for WU lifecycle commands
5
+ *
6
+ * Shared module for integrating context validation into CLI commands.
7
+ * Reads validation_mode from config and applies validation accordingly.
8
+ *
9
+ * @module
10
+ */
11
+ import { computeContext } from './context/context-computer.js';
12
+ import { validateCommand } from './validation/validate-command.js';
13
+ import { getValidCommandsForContext } from './validation/command-registry.js';
14
+ import { getConfig } from './lumenflow-config.js';
15
+ import { EMOJI, CONTEXT_VALIDATION } from './wu-constants.js';
16
+ const { COMMANDS } = CONTEXT_VALIDATION;
17
+ /**
18
+ * Get validation mode from config
19
+ */
20
+ export function getValidationMode() {
21
+ try {
22
+ const config = getConfig();
23
+ const experimental = config?.experimental;
24
+ if (!experimental?.context_validation) {
25
+ return 'off';
26
+ }
27
+ return experimental.validation_mode || 'warn';
28
+ }
29
+ catch {
30
+ // Config not available, default to warn
31
+ return 'warn';
32
+ }
33
+ }
34
+ /**
35
+ * Check if next steps should be shown
36
+ */
37
+ export function shouldShowNextSteps() {
38
+ try {
39
+ const config = getConfig();
40
+ return config?.experimental?.show_next_steps !== false;
41
+ }
42
+ catch {
43
+ return true;
44
+ }
45
+ }
46
+ /**
47
+ * Format validation errors for display
48
+ */
49
+ function formatErrors(validation) {
50
+ const lines = [];
51
+ for (const error of validation.errors) {
52
+ lines.push(`${EMOJI.FAILURE} ${error.code}: ${error.message}`);
53
+ if (error.fixCommand) {
54
+ lines.push(` Fix: ${error.fixCommand}`);
55
+ }
56
+ }
57
+ return lines.join('\n');
58
+ }
59
+ /**
60
+ * Format validation warnings for display
61
+ */
62
+ function formatWarnings(validation) {
63
+ const lines = [];
64
+ for (const warning of validation.warnings) {
65
+ lines.push(`${EMOJI.WARNING} ${warning.id}: ${warning.message}`);
66
+ }
67
+ return lines.join('\n');
68
+ }
69
+ /**
70
+ * Format next steps for display
71
+ */
72
+ export function formatNextSteps(context, commandName) {
73
+ const validCommands = getValidCommandsForContext(context);
74
+ const commandDef = validCommands.find((c) => c.name === commandName);
75
+ if (!commandDef?.getNextSteps) {
76
+ return '';
77
+ }
78
+ const steps = commandDef.getNextSteps(context);
79
+ if (steps.length === 0) {
80
+ return '';
81
+ }
82
+ return '\n## Next Steps\n' + steps.map((s) => ` ${s}`).join('\n');
83
+ }
84
+ /**
85
+ * Run context validation for a command
86
+ *
87
+ * @param commandName - The wu:* command name (e.g., 'wu:claim')
88
+ * @param wuId - Optional WU ID for context
89
+ * @returns ContextValidationResult
90
+ */
91
+ export async function runContextValidation(commandName, wuId) {
92
+ const mode = getValidationMode();
93
+ // Compute context
94
+ const { context } = await computeContext({ wuId });
95
+ // If validation is off, just return context
96
+ if (mode === 'off') {
97
+ return {
98
+ canProceed: true,
99
+ context,
100
+ validation: null,
101
+ mode,
102
+ output: null,
103
+ };
104
+ }
105
+ // Run validation
106
+ const validation = validateCommand(commandName, context);
107
+ // Format output
108
+ let output = null;
109
+ if (!validation.valid) {
110
+ output = formatErrors(validation);
111
+ }
112
+ else if (validation.warnings.length > 0) {
113
+ output = formatWarnings(validation);
114
+ }
115
+ // Determine if command can proceed
116
+ const canProceed = mode === 'warn' || validation.valid;
117
+ return {
118
+ canProceed,
119
+ context,
120
+ validation,
121
+ mode,
122
+ output,
123
+ };
124
+ }
125
+ /**
126
+ * Apply context validation to a command
127
+ *
128
+ * This is the main integration function. It:
129
+ * 1. Runs validation according to config
130
+ * 2. Logs warnings/errors as appropriate
131
+ * 3. Returns whether the command should proceed
132
+ * 4. Exits with error if mode is 'error' and validation fails
133
+ *
134
+ * @param commandName - The wu:* command name
135
+ * @param wuId - Optional WU ID for context
136
+ * @param logPrefix - Log prefix for output
137
+ * @returns The computed context if validation passes
138
+ * @throws Exits process if mode is 'error' and validation fails
139
+ */
140
+ export async function applyContextValidation(commandName, wuId, logPrefix = '[context]') {
141
+ const result = await runContextValidation(commandName, wuId);
142
+ // Log output if any
143
+ if (result.output) {
144
+ if (result.mode === 'error' && !result.canProceed) {
145
+ console.error(`${logPrefix} Context validation failed:`);
146
+ console.error(result.output);
147
+ process.exit(1);
148
+ }
149
+ else if (result.mode === 'warn') {
150
+ console.warn(`${logPrefix} Context validation warnings:`);
151
+ console.warn(result.output);
152
+ }
153
+ }
154
+ return result.context;
155
+ }
156
+ // Re-export commands for convenience
157
+ export { COMMANDS };