@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,45 @@
1
+ /**
2
+ * AnalyzeRecoveryUseCase
3
+ *
4
+ * WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
5
+ *
6
+ * Use case for analyzing WU state and suggesting recovery actions.
7
+ * Uses constructor injection for recovery analyzer dependency.
8
+ *
9
+ * Hexagonal Architecture - Application Layer
10
+ * - Depends on port interface (IRecoveryAnalyzer)
11
+ * - Does NOT import from infrastructure layer
12
+ *
13
+ * @module usecases/analyze-recovery.usecase
14
+ */
15
+ /**
16
+ * AnalyzeRecoveryUseCase
17
+ *
18
+ * Analyzes WU context to detect state inconsistencies and suggests
19
+ * recovery actions.
20
+ *
21
+ * @example
22
+ * // Using default analyzer via DI factory
23
+ * const useCase = createAnalyzeRecoveryUseCase();
24
+ * const analysis = await useCase.execute(context);
25
+ *
26
+ * @example
27
+ * // Using custom analyzer for testing
28
+ * const useCase = new AnalyzeRecoveryUseCase(mockAnalyzer);
29
+ * const analysis = await useCase.execute(context);
30
+ */
31
+ export class AnalyzeRecoveryUseCase {
32
+ recoveryAnalyzer;
33
+ constructor(recoveryAnalyzer) {
34
+ this.recoveryAnalyzer = recoveryAnalyzer;
35
+ }
36
+ /**
37
+ * Execute the use case to analyze recovery issues.
38
+ *
39
+ * @param context - Current WU context
40
+ * @returns Promise<RecoveryAnalysis> - Analysis with issues and suggested actions
41
+ */
42
+ async execute(context) {
43
+ return this.recoveryAnalyzer.analyzeRecovery(context);
44
+ }
45
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * ComputeContextUseCase
3
+ *
4
+ * WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
5
+ *
6
+ * Use case for computing WU context by orchestrating multiple adapters.
7
+ * Uses constructor injection for all dependencies.
8
+ *
9
+ * Hexagonal Architecture - Application Layer
10
+ * - Depends on port interfaces (ILocationResolver, IGitStateReader, IWuStateReader)
11
+ * - Does NOT import from infrastructure layer
12
+ *
13
+ * @module usecases/compute-context.usecase
14
+ */
15
+ import type { ILocationResolver, IGitStateReader, IWuStateReader } from '../ports/context.ports.js';
16
+ import type { WuContext } from '../validation/types.js';
17
+ /**
18
+ * Options for computing WU context.
19
+ */
20
+ export interface ComputeContextOptions {
21
+ /** WU ID to look up (optional - will detect from worktree if not provided) */
22
+ wuId?: string;
23
+ /** Current working directory (defaults to process.cwd()) */
24
+ cwd?: string;
25
+ }
26
+ /**
27
+ * ComputeContextUseCase
28
+ *
29
+ * Orchestrates the computation of WU context by calling multiple adapters
30
+ * and assembling the unified context model.
31
+ *
32
+ * @example
33
+ * // Using default adapters via DI factory
34
+ * const useCase = createComputeContextUseCase();
35
+ * const context = await useCase.execute({ wuId: 'WU-1094' });
36
+ *
37
+ * @example
38
+ * // Using custom adapters for testing
39
+ * const useCase = new ComputeContextUseCase(
40
+ * mockLocationResolver,
41
+ * mockGitStateReader,
42
+ * mockWuStateReader,
43
+ * );
44
+ * const context = await useCase.execute({});
45
+ */
46
+ export declare class ComputeContextUseCase {
47
+ private readonly locationResolver;
48
+ private readonly gitStateReader;
49
+ private readonly wuStateReader;
50
+ constructor(locationResolver: ILocationResolver, gitStateReader: IGitStateReader, wuStateReader: IWuStateReader);
51
+ /**
52
+ * Execute the use case to compute WU context.
53
+ *
54
+ * @param options - Options including optional wuId and cwd
55
+ * @returns Promise<WuContext> - Computed WU context
56
+ */
57
+ execute(options?: ComputeContextOptions): Promise<WuContext>;
58
+ /**
59
+ * Get expected worktree path for a WU.
60
+ */
61
+ private getWorktreePath;
62
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * ComputeContextUseCase
3
+ *
4
+ * WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
5
+ *
6
+ * Use case for computing WU context by orchestrating multiple adapters.
7
+ * Uses constructor injection for all dependencies.
8
+ *
9
+ * Hexagonal Architecture - Application Layer
10
+ * - Depends on port interfaces (ILocationResolver, IGitStateReader, IWuStateReader)
11
+ * - Does NOT import from infrastructure layer
12
+ *
13
+ * @module usecases/compute-context.usecase
14
+ */
15
+ /**
16
+ * ComputeContextUseCase
17
+ *
18
+ * Orchestrates the computation of WU context by calling multiple adapters
19
+ * and assembling the unified context model.
20
+ *
21
+ * @example
22
+ * // Using default adapters via DI factory
23
+ * const useCase = createComputeContextUseCase();
24
+ * const context = await useCase.execute({ wuId: 'WU-1094' });
25
+ *
26
+ * @example
27
+ * // Using custom adapters for testing
28
+ * const useCase = new ComputeContextUseCase(
29
+ * mockLocationResolver,
30
+ * mockGitStateReader,
31
+ * mockWuStateReader,
32
+ * );
33
+ * const context = await useCase.execute({});
34
+ */
35
+ export class ComputeContextUseCase {
36
+ locationResolver;
37
+ gitStateReader;
38
+ wuStateReader;
39
+ constructor(locationResolver, gitStateReader, wuStateReader) {
40
+ this.locationResolver = locationResolver;
41
+ this.gitStateReader = gitStateReader;
42
+ this.wuStateReader = wuStateReader;
43
+ }
44
+ /**
45
+ * Execute the use case to compute WU context.
46
+ *
47
+ * @param options - Options including optional wuId and cwd
48
+ * @returns Promise<WuContext> - Computed WU context
49
+ */
50
+ async execute(options = {}) {
51
+ const { wuId, cwd } = options;
52
+ // Step 1: Resolve location context
53
+ const location = await this.locationResolver.resolveLocation(cwd);
54
+ // Step 2: Read git state for current directory
55
+ const git = await this.gitStateReader.readGitState(cwd);
56
+ // Step 3: Determine WU ID (explicit or from worktree)
57
+ const effectiveWuId = wuId ?? location.worktreeWuId;
58
+ // Step 4: Read WU state if we have a WU ID
59
+ let wu = null;
60
+ let worktreeGit;
61
+ if (effectiveWuId) {
62
+ const wuStateResult = await this.wuStateReader.readWuState(effectiveWuId, location.mainCheckout);
63
+ if (wuStateResult) {
64
+ wu = {
65
+ id: wuStateResult.id,
66
+ status: wuStateResult.status,
67
+ lane: wuStateResult.lane,
68
+ title: wuStateResult.title,
69
+ yamlPath: wuStateResult.yamlPath,
70
+ isConsistent: wuStateResult.isConsistent,
71
+ inconsistencyReason: wuStateResult.inconsistencyReason,
72
+ };
73
+ // Step 5: If running from main and WU is in_progress, read worktree git state
74
+ if (location.type === 'main' && wu.status === 'in_progress') {
75
+ const worktreePath = this.getWorktreePath(location.mainCheckout, wu.lane, wu.id);
76
+ worktreeGit = await this.gitStateReader.readGitState(worktreePath);
77
+ }
78
+ }
79
+ }
80
+ // Step 6: Create session state (inactive by default)
81
+ const session = {
82
+ isActive: false,
83
+ sessionId: null,
84
+ };
85
+ return {
86
+ location,
87
+ git,
88
+ wu,
89
+ session,
90
+ worktreeGit,
91
+ };
92
+ }
93
+ /**
94
+ * Get expected worktree path for a WU.
95
+ */
96
+ getWorktreePath(mainCheckout, lane, wuId) {
97
+ const laneKebab = lane.toLowerCase().replace(/[: ]+/g, '-');
98
+ const wuIdLower = wuId.toLowerCase();
99
+ return `${mainCheckout}/worktrees/${laneKebab}-${wuIdLower}`;
100
+ }
101
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Use Cases Index
3
+ *
4
+ * WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
5
+ *
6
+ * Re-exports all use case classes.
7
+ *
8
+ * @module usecases
9
+ */
10
+ export { ComputeContextUseCase, type ComputeContextOptions } from './compute-context.usecase.js';
11
+ export { ValidateCommandUseCase } from './validate-command.usecase.js';
12
+ export { AnalyzeRecoveryUseCase } from './analyze-recovery.usecase.js';
13
+ export { GetDashboardDataUseCase, type GetDashboardDataOptions, } from './get-dashboard-data.usecase.js';
14
+ export { GetSuggestionsUseCase, type GetSuggestionsOptions } from './get-suggestions.usecase.js';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Use Cases Index
3
+ *
4
+ * WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
5
+ *
6
+ * Re-exports all use case classes.
7
+ *
8
+ * @module usecases
9
+ */
10
+ // Context use cases
11
+ export { ComputeContextUseCase } from './compute-context.usecase.js';
12
+ // Validation use cases
13
+ export { ValidateCommandUseCase } from './validate-command.usecase.js';
14
+ // Recovery use cases
15
+ export { AnalyzeRecoveryUseCase } from './analyze-recovery.usecase.js';
16
+ // Existing use cases (pre-WU-1094)
17
+ export { GetDashboardDataUseCase, } from './get-dashboard-data.usecase.js';
18
+ export { GetSuggestionsUseCase } from './get-suggestions.usecase.js';
@@ -0,0 +1,55 @@
1
+ /**
2
+ * ValidateCommandUseCase
3
+ *
4
+ * WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
5
+ *
6
+ * Use case for validating commands against WU context.
7
+ * Uses constructor injection for command registry dependency.
8
+ *
9
+ * Hexagonal Architecture - Application Layer
10
+ * - Depends on port interface (ICommandRegistry)
11
+ * - Does NOT import from infrastructure layer
12
+ *
13
+ * @module usecases/validate-command.usecase
14
+ */
15
+ import type { ICommandRegistry, CommandDefinition, WuContext } from '../ports/validation.ports.js';
16
+ import type { ValidationResult } from '../validation/types.js';
17
+ /**
18
+ * ValidateCommandUseCase
19
+ *
20
+ * Validates a command against the current WU context, returning
21
+ * validation errors and warnings with fix suggestions.
22
+ *
23
+ * @example
24
+ * // Using default registry via DI factory
25
+ * const useCase = createValidateCommandUseCase();
26
+ * const result = await useCase.execute('wu:done', context);
27
+ *
28
+ * @example
29
+ * // Using custom registry for testing
30
+ * const useCase = new ValidateCommandUseCase(mockRegistry);
31
+ * const result = await useCase.execute('wu:claim', context);
32
+ */
33
+ export declare class ValidateCommandUseCase {
34
+ private readonly commandRegistry;
35
+ constructor(commandRegistry: ICommandRegistry);
36
+ /**
37
+ * Execute the use case to validate a command.
38
+ *
39
+ * @param command - Command name (e.g., 'wu:done')
40
+ * @param context - Current WU context
41
+ * @returns Promise<ValidationResult> - Validation result with errors/warnings
42
+ */
43
+ execute(command: string, context: WuContext): Promise<ValidationResult>;
44
+ /**
45
+ * Get valid commands for the current context.
46
+ *
47
+ * @param context - Current WU context
48
+ * @returns Promise<CommandDefinition[]> - Array of valid commands
49
+ */
50
+ getValidCommands(context: WuContext): Promise<CommandDefinition[]>;
51
+ /**
52
+ * Generate fix command for location errors.
53
+ */
54
+ private getLocationFixCommand;
55
+ }
@@ -0,0 +1,154 @@
1
+ /**
2
+ * ValidateCommandUseCase
3
+ *
4
+ * WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
5
+ *
6
+ * Use case for validating commands against WU context.
7
+ * Uses constructor injection for command registry dependency.
8
+ *
9
+ * Hexagonal Architecture - Application Layer
10
+ * - Depends on port interface (ICommandRegistry)
11
+ * - Does NOT import from infrastructure layer
12
+ *
13
+ * @module usecases/validate-command.usecase
14
+ */
15
+ import { CONTEXT_VALIDATION } from '../wu-constants.js';
16
+ const { ERROR_CODES, SEVERITY } = CONTEXT_VALIDATION;
17
+ /**
18
+ * ValidateCommandUseCase
19
+ *
20
+ * Validates a command against the current WU context, returning
21
+ * validation errors and warnings with fix suggestions.
22
+ *
23
+ * @example
24
+ * // Using default registry via DI factory
25
+ * const useCase = createValidateCommandUseCase();
26
+ * const result = await useCase.execute('wu:done', context);
27
+ *
28
+ * @example
29
+ * // Using custom registry for testing
30
+ * const useCase = new ValidateCommandUseCase(mockRegistry);
31
+ * const result = await useCase.execute('wu:claim', context);
32
+ */
33
+ export class ValidateCommandUseCase {
34
+ commandRegistry;
35
+ constructor(commandRegistry) {
36
+ this.commandRegistry = commandRegistry;
37
+ }
38
+ /**
39
+ * Execute the use case to validate a command.
40
+ *
41
+ * @param command - Command name (e.g., 'wu:done')
42
+ * @param context - Current WU context
43
+ * @returns Promise<ValidationResult> - Validation result with errors/warnings
44
+ */
45
+ async execute(command, context) {
46
+ const errors = [];
47
+ const warnings = [];
48
+ // Step 1: Look up command definition
49
+ const commandDef = this.commandRegistry.getCommandDefinition(command);
50
+ if (!commandDef) {
51
+ errors.push({
52
+ // Use WU_NOT_FOUND as a general "not found" error code
53
+ // The message clarifies it's an unknown command
54
+ code: ERROR_CODES.WU_NOT_FOUND,
55
+ message: `Unknown command: ${command}`,
56
+ fixCommand: null,
57
+ });
58
+ return {
59
+ valid: false,
60
+ errors,
61
+ warnings,
62
+ context,
63
+ };
64
+ }
65
+ // Step 2: Check location requirement
66
+ if (commandDef.requiredLocation !== null) {
67
+ if (context.location.type !== commandDef.requiredLocation) {
68
+ const fixCommand = this.getLocationFixCommand(commandDef.requiredLocation, context, command);
69
+ errors.push({
70
+ code: ERROR_CODES.WRONG_LOCATION,
71
+ message: `${command} must be run from ${commandDef.requiredLocation} checkout`,
72
+ fixCommand,
73
+ context: {
74
+ required: commandDef.requiredLocation,
75
+ actual: context.location.type,
76
+ },
77
+ });
78
+ }
79
+ }
80
+ // Step 3: Check WU status requirement
81
+ if (commandDef.requiredWuStatus !== null) {
82
+ const actualStatus = context.wu?.status ?? null;
83
+ if (actualStatus !== commandDef.requiredWuStatus) {
84
+ errors.push({
85
+ code: ERROR_CODES.WRONG_WU_STATUS,
86
+ message: `${command} requires WU status '${commandDef.requiredWuStatus}' but got '${actualStatus ?? 'no WU'}'`,
87
+ fixCommand: null,
88
+ context: {
89
+ required: commandDef.requiredWuStatus,
90
+ actual: actualStatus,
91
+ },
92
+ });
93
+ }
94
+ }
95
+ // Step 4: Check predicates
96
+ if (commandDef.predicates && commandDef.predicates.length > 0) {
97
+ for (const predicate of commandDef.predicates) {
98
+ const passed = predicate.check(context);
99
+ if (!passed) {
100
+ const message = predicate.getFixMessage
101
+ ? predicate.getFixMessage(context)
102
+ : predicate.description;
103
+ if (predicate.severity === SEVERITY.ERROR) {
104
+ errors.push({
105
+ // Use GATES_NOT_PASSED for predicate failures (e.g., dirty worktree)
106
+ code: ERROR_CODES.GATES_NOT_PASSED,
107
+ message,
108
+ fixCommand: null,
109
+ context: { predicateId: predicate.id },
110
+ });
111
+ }
112
+ else {
113
+ warnings.push({
114
+ id: predicate.id,
115
+ message,
116
+ });
117
+ }
118
+ }
119
+ }
120
+ }
121
+ return {
122
+ valid: errors.length === 0,
123
+ errors,
124
+ warnings,
125
+ context,
126
+ };
127
+ }
128
+ /**
129
+ * Get valid commands for the current context.
130
+ *
131
+ * @param context - Current WU context
132
+ * @returns Promise<CommandDefinition[]> - Array of valid commands
133
+ */
134
+ async getValidCommands(context) {
135
+ return this.commandRegistry.getValidCommandsForContext(context);
136
+ }
137
+ /**
138
+ * Generate fix command for location errors.
139
+ */
140
+ getLocationFixCommand(requiredLocation, context, command) {
141
+ if (requiredLocation === 'main') {
142
+ // Need to cd to main checkout
143
+ const wuIdParam = context.wu?.id ? ` --id ${context.wu.id}` : '';
144
+ return `cd ${context.location.mainCheckout} && pnpm ${command}${wuIdParam}`;
145
+ }
146
+ else if (requiredLocation === 'worktree') {
147
+ // Need to cd to worktree
148
+ if (context.location.worktreeName) {
149
+ return `cd ${context.location.mainCheckout}/worktrees/${context.location.worktreeName}`;
150
+ }
151
+ }
152
+ return '';
153
+ }
154
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Command Registry for WU Lifecycle Commands
3
+ *
4
+ * WU-1090: Context-aware state machine for WU lifecycle commands
5
+ *
6
+ * Declarative definitions for all wu:* commands specifying:
7
+ * - Required location (main vs worktree)
8
+ * - Required WU status
9
+ * - Custom validation predicates
10
+ * - Success next steps
11
+ *
12
+ * @module
13
+ */
14
+ import type { CommandDefinition, CommandPredicate, WuContext } from './types.js';
15
+ /**
16
+ * Command registry mapping command names to definitions.
17
+ */
18
+ export declare const COMMAND_REGISTRY: Map<string, CommandDefinition>;
19
+ /**
20
+ * Get command definition by name.
21
+ *
22
+ * @param command - Command name (e.g., 'wu:create')
23
+ * @returns CommandDefinition or null if not found
24
+ */
25
+ export declare function getCommandDefinition(command: string): CommandDefinition | null;
26
+ /**
27
+ * Get all commands valid for the current context.
28
+ *
29
+ * A command is valid if:
30
+ * - Location requirement is satisfied (or null = any)
31
+ * - WU status requirement is satisfied (or null = no WU required)
32
+ * - All error-severity predicates pass
33
+ *
34
+ * @param context - Current WU context
35
+ * @returns Array of valid CommandDefinitions
36
+ */
37
+ export declare function getValidCommandsForContext(context: WuContext): CommandDefinition[];
38
+ export type { CommandDefinition, CommandPredicate, WuContext };