@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,58 @@
1
+ /**
2
+ * Recovery Ports
3
+ *
4
+ * WU-1093: INIT-002 Phase 1 - Define ports and domain schemas
5
+ *
6
+ * Port interfaces for recovery-related operations.
7
+ * These abstractions allow external users to inject custom implementations.
8
+ *
9
+ * Hexagonal Architecture - Input Ports:
10
+ * - IRecoveryAnalyzer: Analyze WU state issues and suggest recovery actions
11
+ *
12
+ * Current Implementations:
13
+ * - analyzeRecovery (recovery-analyzer.ts)
14
+ *
15
+ * @module ports/recovery
16
+ */
17
+ import type { WuContext } from '../validation/types.js';
18
+ import type { RecoveryAnalysis } from '../recovery/recovery-analyzer.js';
19
+ /**
20
+ * Recovery Analyzer Port Interface
21
+ *
22
+ * Analyzes WU context to detect state inconsistencies and suggests
23
+ * appropriate recovery actions.
24
+ *
25
+ * Issue types detected:
26
+ * - Partial claim: worktree exists but status is ready
27
+ * - Orphan claim: status is in_progress but worktree missing
28
+ * - Inconsistent state: YAML and state store disagree
29
+ * - Orphan branch: branch exists but worktree missing
30
+ * - Stale lock: lock file from old session
31
+ * - Leftover worktree: WU is done but worktree exists
32
+ *
33
+ * @example
34
+ * // Custom implementation for testing
35
+ * const mockAnalyzer: IRecoveryAnalyzer = {
36
+ * analyzeRecovery: async (context) => ({
37
+ * hasIssues: false,
38
+ * issues: [],
39
+ * actions: [],
40
+ * wuId: context.wu?.id ?? null,
41
+ * }),
42
+ * };
43
+ *
44
+ * @example
45
+ * // Using default implementation
46
+ * import { analyzeRecovery } from './recovery/recovery-analyzer.js';
47
+ * const analyzer: IRecoveryAnalyzer = { analyzeRecovery };
48
+ */
49
+ export interface IRecoveryAnalyzer {
50
+ /**
51
+ * Analyze context for recovery issues.
52
+ *
53
+ * @param context - Current WU context
54
+ * @returns Promise<RecoveryAnalysis> - Recovery analysis with issues and suggested actions
55
+ */
56
+ analyzeRecovery(context: WuContext): Promise<RecoveryAnalysis>;
57
+ }
58
+ export type { WuContext, RecoveryAnalysis };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Recovery Ports
3
+ *
4
+ * WU-1093: INIT-002 Phase 1 - Define ports and domain schemas
5
+ *
6
+ * Port interfaces for recovery-related operations.
7
+ * These abstractions allow external users to inject custom implementations.
8
+ *
9
+ * Hexagonal Architecture - Input Ports:
10
+ * - IRecoveryAnalyzer: Analyze WU state issues and suggest recovery actions
11
+ *
12
+ * Current Implementations:
13
+ * - analyzeRecovery (recovery-analyzer.ts)
14
+ *
15
+ * @module ports/recovery
16
+ */
17
+ export {};
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Validation Ports
3
+ *
4
+ * WU-1093: INIT-002 Phase 1 - Define ports and domain schemas
5
+ *
6
+ * Port interfaces for validation-related operations.
7
+ * These abstractions allow external users to inject custom implementations.
8
+ *
9
+ * Hexagonal Architecture - Input Ports:
10
+ * - ICommandRegistry: Lookup command definitions and validate commands
11
+ *
12
+ * Current Implementations:
13
+ * - COMMAND_REGISTRY, getCommandDefinition, getValidCommandsForContext (command-registry.ts)
14
+ *
15
+ * @module ports/validation
16
+ */
17
+ import type { CommandDefinition, WuContext } from '../validation/types.js';
18
+ /**
19
+ * Command Registry Port Interface
20
+ *
21
+ * Provides command definitions and validation logic for wu:* commands.
22
+ * Allows looking up command requirements and determining valid commands
23
+ * for a given context.
24
+ *
25
+ * @example
26
+ * // Custom implementation for testing
27
+ * const mockRegistry: ICommandRegistry = {
28
+ * getCommandDefinition: (cmd) => cmd === 'wu:done' ? {...} : null,
29
+ * getValidCommandsForContext: (ctx) => [...],
30
+ * getAllCommands: () => [...],
31
+ * };
32
+ *
33
+ * @example
34
+ * // Using default implementation
35
+ * import {
36
+ * getCommandDefinition,
37
+ * getValidCommandsForContext,
38
+ * COMMAND_REGISTRY,
39
+ * } from './validation/command-registry.js';
40
+ *
41
+ * const registry: ICommandRegistry = {
42
+ * getCommandDefinition,
43
+ * getValidCommandsForContext,
44
+ * getAllCommands: () => Array.from(COMMAND_REGISTRY.values()),
45
+ * };
46
+ */
47
+ export interface ICommandRegistry {
48
+ /**
49
+ * Get command definition by name.
50
+ *
51
+ * @param command - Command name (e.g., 'wu:create', 'wu:done')
52
+ * @returns CommandDefinition or null if not found
53
+ */
54
+ getCommandDefinition(command: string): CommandDefinition | null;
55
+ /**
56
+ * Get all commands valid for the current context.
57
+ *
58
+ * A command is valid if:
59
+ * - Location requirement is satisfied (or null = any)
60
+ * - WU status requirement is satisfied (or null = no WU required)
61
+ * - All error-severity predicates pass
62
+ *
63
+ * @param context - Current WU context
64
+ * @returns Array of valid CommandDefinitions
65
+ */
66
+ getValidCommandsForContext(context: WuContext): CommandDefinition[];
67
+ /**
68
+ * Get all registered command definitions.
69
+ *
70
+ * @returns Array of all CommandDefinitions
71
+ */
72
+ getAllCommands(): CommandDefinition[];
73
+ }
74
+ export type { CommandDefinition, WuContext };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Validation Ports
3
+ *
4
+ * WU-1093: INIT-002 Phase 1 - Define ports and domain schemas
5
+ *
6
+ * Port interfaces for validation-related operations.
7
+ * These abstractions allow external users to inject custom implementations.
8
+ *
9
+ * Hexagonal Architecture - Input Ports:
10
+ * - ICommandRegistry: Lookup command definitions and validate commands
11
+ *
12
+ * Current Implementations:
13
+ * - COMMAND_REGISTRY, getCommandDefinition, getValidCommandsForContext (command-registry.ts)
14
+ *
15
+ * @module ports/validation
16
+ */
17
+ export {};
@@ -0,0 +1,224 @@
1
+ /**
2
+ * WU Helpers Port Interfaces
3
+ *
4
+ * WU-1102: INIT-003 Phase 2b - Port interfaces for WU helper modules
5
+ *
6
+ * Hexagonal Architecture - Input Ports:
7
+ * These abstractions allow external users to inject custom implementations
8
+ * for WU lifecycle operations.
9
+ *
10
+ * @module ports/wu-helpers
11
+ */
12
+ /**
13
+ * Git adapter interface for ensureOnMain and ensureMainUpToDate operations
14
+ */
15
+ export interface IWuGitAdapter {
16
+ /**
17
+ * Get the current git branch name
18
+ * @returns Promise resolving to branch name
19
+ */
20
+ getCurrentBranch(): Promise<string>;
21
+ /**
22
+ * Fetch from a remote
23
+ * @param remote - Remote name (e.g., 'origin')
24
+ * @param branch - Branch name (e.g., 'main')
25
+ */
26
+ fetch(remote: string, branch: string): Promise<void>;
27
+ /**
28
+ * Get commit hash for a ref
29
+ * @param ref - Git ref (branch, tag, or commit)
30
+ * @returns Promise resolving to commit hash
31
+ */
32
+ getCommitHash(ref: string): Promise<string>;
33
+ }
34
+ /**
35
+ * WU status check result
36
+ */
37
+ export interface IWuStatusCheckResult {
38
+ /** Whether the operation is allowed */
39
+ allowed: boolean;
40
+ /** Current WU status */
41
+ status: string | null;
42
+ /** Error message if not allowed */
43
+ error: string | null;
44
+ }
45
+ /**
46
+ * Branch validation result
47
+ */
48
+ export interface IBranchValidationResult {
49
+ /** Whether the branch name is valid */
50
+ valid: boolean;
51
+ /** Lane name (kebab-case) or null */
52
+ lane: string | null;
53
+ /** WU ID (uppercase) or null */
54
+ wuid: string | null;
55
+ /** Error message if invalid */
56
+ error: string | null;
57
+ }
58
+ /**
59
+ * WU YAML reader interface
60
+ */
61
+ export interface IWuYamlReader {
62
+ /**
63
+ * Read and parse WU YAML file
64
+ * @param wuPath - Path to WU YAML file
65
+ * @param expectedId - Expected WU ID for validation
66
+ * @returns Parsed WU document
67
+ */
68
+ readWU(wuPath: string, expectedId: string): unknown;
69
+ /**
70
+ * Read YAML file without ID validation
71
+ * @param yamlPath - Path to YAML file
72
+ * @returns Parsed document
73
+ */
74
+ readWURaw(yamlPath: string): unknown;
75
+ }
76
+ /**
77
+ * WU YAML writer interface
78
+ */
79
+ export interface IWuYamlWriter {
80
+ /**
81
+ * Write WU document to file
82
+ * @param wuPath - Path to WU YAML file
83
+ * @param doc - Document to write
84
+ */
85
+ writeWU(wuPath: string, doc: unknown): void;
86
+ }
87
+ /**
88
+ * WU state store interface (subset for dependency injection)
89
+ */
90
+ export interface IWuStateStore {
91
+ /**
92
+ * Load state from events file
93
+ */
94
+ load(): Promise<void>;
95
+ /**
96
+ * Claim a WU (transition to in_progress)
97
+ * @param wuId - WU identifier
98
+ * @param lane - Lane name
99
+ * @param title - WU title
100
+ */
101
+ claim(wuId: string, lane: string, title: string): Promise<void>;
102
+ /**
103
+ * Complete a WU (transition to done)
104
+ * @param wuId - WU identifier
105
+ */
106
+ complete(wuId: string): Promise<void>;
107
+ /**
108
+ * Block a WU (transition to blocked)
109
+ * @param wuId - WU identifier
110
+ * @param reason - Block reason
111
+ */
112
+ block(wuId: string, reason: string): Promise<void>;
113
+ /**
114
+ * Unblock a WU (transition back to in_progress)
115
+ * @param wuId - WU identifier
116
+ */
117
+ unblock(wuId: string): Promise<void>;
118
+ /**
119
+ * Release a WU (transition to ready)
120
+ * @param wuId - WU identifier
121
+ * @param reason - Release reason
122
+ */
123
+ release(wuId: string, reason: string): Promise<void>;
124
+ /**
125
+ * Get WU state entry
126
+ * @param wuId - WU identifier
127
+ * @returns State entry or undefined
128
+ */
129
+ getWUState(wuId: string): {
130
+ status: string;
131
+ lane: string;
132
+ title: string;
133
+ } | undefined;
134
+ /**
135
+ * Get all WU IDs by status
136
+ * @param status - Status to filter by
137
+ * @returns Set of WU IDs
138
+ */
139
+ getByStatus(status: string): Set<string>;
140
+ /**
141
+ * Get all WU IDs by lane
142
+ * @param lane - Lane to filter by
143
+ * @returns Set of WU IDs
144
+ */
145
+ getByLane(lane: string): Set<string>;
146
+ }
147
+ /**
148
+ * WU checkpoint interface
149
+ */
150
+ export interface IWuCheckpointManager {
151
+ /**
152
+ * Create a pre-gates checkpoint
153
+ */
154
+ createPreGatesCheckpoint(params: {
155
+ wuId: string;
156
+ worktreePath: string;
157
+ branchName: string;
158
+ gatesPassed?: boolean;
159
+ }, options?: {
160
+ baseDir?: string;
161
+ }): Promise<{
162
+ checkpointId: string;
163
+ gatesPassed: boolean;
164
+ }>;
165
+ /**
166
+ * Mark checkpoint as gates passed
167
+ * @param wuId - WU identifier
168
+ * @returns True if updated
169
+ */
170
+ markGatesPassed(wuId: string, options?: {
171
+ baseDir?: string;
172
+ }): boolean;
173
+ /**
174
+ * Get checkpoint for a WU
175
+ * @param wuId - WU identifier
176
+ * @returns Checkpoint or null
177
+ */
178
+ getCheckpoint(wuId: string, options?: {
179
+ baseDir?: string;
180
+ }): {
181
+ gatesPassed: boolean;
182
+ worktreeHeadSha: string;
183
+ } | null;
184
+ /**
185
+ * Clear checkpoint
186
+ * @param wuId - WU identifier
187
+ */
188
+ clearCheckpoint(wuId: string, options?: {
189
+ baseDir?: string;
190
+ }): void;
191
+ /**
192
+ * Check if gates can be skipped
193
+ */
194
+ canSkipGates(wuId: string, options?: {
195
+ baseDir?: string;
196
+ currentHeadSha?: string;
197
+ }): {
198
+ canSkip: boolean;
199
+ reason?: string;
200
+ };
201
+ }
202
+ /**
203
+ * WU paths interface
204
+ */
205
+ export interface IWuPaths {
206
+ /** Get path to WU YAML file */
207
+ WU(id: string): string;
208
+ /** Get path to WU directory */
209
+ WU_DIR(): string;
210
+ /** Get path to status.md */
211
+ STATUS(): string;
212
+ /** Get path to backlog.md */
213
+ BACKLOG(): string;
214
+ /** Get path to stamps directory */
215
+ STAMPS_DIR(): string;
216
+ /** Get path to WU done stamp file */
217
+ STAMP(id: string): string;
218
+ /** Get path to state directory */
219
+ STATE_DIR(): string;
220
+ /** Get path to initiatives directory */
221
+ INITIATIVES_DIR(): string;
222
+ /** Get path to worktrees directory */
223
+ WORKTREES_DIR(): string;
224
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * WU Helpers Port Interfaces
3
+ *
4
+ * WU-1102: INIT-003 Phase 2b - Port interfaces for WU helper modules
5
+ *
6
+ * Hexagonal Architecture - Input Ports:
7
+ * These abstractions allow external users to inject custom implementations
8
+ * for WU lifecycle operations.
9
+ *
10
+ * @module ports/wu-helpers
11
+ */
12
+ export {};
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Recovery Module
3
+ *
4
+ * WU-1090: Context-aware state machine for WU lifecycle commands
5
+ *
6
+ * Exports:
7
+ * - Recovery analysis (detect issues, suggest actions)
8
+ *
9
+ * @module
10
+ */
11
+ export * from './recovery-analyzer.js';
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Recovery Module
3
+ *
4
+ * WU-1090: Context-aware state machine for WU lifecycle commands
5
+ *
6
+ * Exports:
7
+ * - Recovery analysis (detect issues, suggest actions)
8
+ *
9
+ * @module
10
+ */
11
+ export * from './recovery-analyzer.js';
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Recovery Analyzer for WU State Issues
3
+ *
4
+ * WU-1090: Context-aware state machine for WU lifecycle commands
5
+ *
6
+ * Analyzes WU context to detect state inconsistencies and suggests
7
+ * appropriate recovery actions.
8
+ *
9
+ * Issue types detected:
10
+ * - Partial claim: worktree exists but status is ready
11
+ * - Orphan claim: status is in_progress but worktree missing
12
+ * - Inconsistent state: YAML and state store disagree
13
+ * - Orphan branch: branch exists but worktree missing
14
+ * - Stale lock: lock file from old session
15
+ * - Leftover worktree: WU is done but worktree exists
16
+ *
17
+ * @module
18
+ */
19
+ import { type RecoveryActionType, type RecoveryIssueCode } from '../wu-constants.js';
20
+ import type { WuContext } from '../validation/types.js';
21
+ /**
22
+ * Issue detected during recovery analysis.
23
+ */
24
+ export interface RecoveryIssue {
25
+ /** Issue code from RECOVERY_ISSUES */
26
+ code: RecoveryIssueCode;
27
+ /** Human-readable description */
28
+ description: string;
29
+ /** Additional context for the issue */
30
+ context?: Record<string, unknown>;
31
+ }
32
+ /**
33
+ * Suggested recovery action.
34
+ */
35
+ export interface WuRecoveryAction {
36
+ /** Action type from RECOVERY_ACTIONS */
37
+ type: RecoveryActionType;
38
+ /** Human-readable description of what this action does */
39
+ description: string;
40
+ /** Command to execute (copy-paste ready) */
41
+ command: string;
42
+ /** Whether this action requires --force flag */
43
+ requiresForce: boolean;
44
+ /** Warning message if any */
45
+ warning?: string;
46
+ }
47
+ /**
48
+ * Result of recovery analysis.
49
+ */
50
+ export interface RecoveryAnalysis {
51
+ /** Whether any issues were found */
52
+ hasIssues: boolean;
53
+ /** List of detected issues */
54
+ issues: RecoveryIssue[];
55
+ /** Suggested recovery actions */
56
+ actions: WuRecoveryAction[];
57
+ /** WU ID analyzed */
58
+ wuId: string | null;
59
+ }
60
+ /**
61
+ * Analyze context for recovery issues.
62
+ *
63
+ * @param context - Current WU context
64
+ * @returns Recovery analysis with issues and suggested actions
65
+ */
66
+ export declare function analyzeRecovery(context: WuContext): Promise<RecoveryAnalysis>;
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Recovery Analyzer for WU State Issues
3
+ *
4
+ * WU-1090: Context-aware state machine for WU lifecycle commands
5
+ *
6
+ * Analyzes WU context to detect state inconsistencies and suggests
7
+ * appropriate recovery actions.
8
+ *
9
+ * Issue types detected:
10
+ * - Partial claim: worktree exists but status is ready
11
+ * - Orphan claim: status is in_progress but worktree missing
12
+ * - Inconsistent state: YAML and state store disagree
13
+ * - Orphan branch: branch exists but worktree missing
14
+ * - Stale lock: lock file from old session
15
+ * - Leftover worktree: WU is done but worktree exists
16
+ *
17
+ * @module
18
+ */
19
+ import { existsSync } from 'node:fs';
20
+ import { join } from 'node:path';
21
+ import { CONTEXT_VALIDATION, WU_STATUS, DEFAULTS, toKebab, } from '../wu-constants.js';
22
+ const { RECOVERY_ISSUES, RECOVERY_ACTIONS } = CONTEXT_VALIDATION;
23
+ /**
24
+ * Get expected worktree path for a WU.
25
+ */
26
+ function getExpectedWorktreePath(mainCheckout, lane, wuId) {
27
+ const laneKebab = toKebab(lane);
28
+ const wuIdLower = wuId.toLowerCase();
29
+ return join(mainCheckout, DEFAULTS.WORKTREES_DIR, `${laneKebab}-${wuIdLower}`);
30
+ }
31
+ /**
32
+ * Check if worktree exists for a WU.
33
+ */
34
+ function worktreeExists(mainCheckout, lane, wuId) {
35
+ const worktreePath = getExpectedWorktreePath(mainCheckout, lane, wuId);
36
+ return existsSync(worktreePath);
37
+ }
38
+ /**
39
+ * Analyze context for recovery issues.
40
+ *
41
+ * @param context - Current WU context
42
+ * @returns Recovery analysis with issues and suggested actions
43
+ */
44
+ export async function analyzeRecovery(context) {
45
+ const issues = [];
46
+ const actions = [];
47
+ // No WU context means nothing to analyze
48
+ if (!context.wu) {
49
+ return {
50
+ hasIssues: false,
51
+ issues: [],
52
+ actions: [],
53
+ wuId: null,
54
+ };
55
+ }
56
+ const { wu } = context;
57
+ const mainCheckout = context.location.mainCheckout;
58
+ const hasWorktree = worktreeExists(mainCheckout, wu.lane, wu.id);
59
+ const worktreePath = getExpectedWorktreePath(mainCheckout, wu.lane, wu.id);
60
+ // Check for partial claim: worktree exists but status is ready
61
+ if (hasWorktree && wu.status === WU_STATUS.READY) {
62
+ issues.push({
63
+ code: RECOVERY_ISSUES.PARTIAL_CLAIM,
64
+ description: `Worktree exists for ${wu.id} but status is 'ready'. The claim may have been interrupted.`,
65
+ context: { worktreePath, status: wu.status },
66
+ });
67
+ actions.push({
68
+ type: RECOVERY_ACTIONS.RESUME,
69
+ description: 'Reconcile state and continue working (preserves work)',
70
+ command: `pnpm wu:recover --id ${wu.id} --action resume`,
71
+ requiresForce: false,
72
+ });
73
+ actions.push({
74
+ type: RECOVERY_ACTIONS.RESET,
75
+ description: 'Discard worktree and reset WU to ready',
76
+ command: `pnpm wu:recover --id ${wu.id} --action reset`,
77
+ requiresForce: false,
78
+ warning: 'This will discard any uncommitted work in the worktree',
79
+ });
80
+ }
81
+ // Check for orphan claim: status is in_progress but worktree missing
82
+ if (!hasWorktree && wu.status === WU_STATUS.IN_PROGRESS) {
83
+ issues.push({
84
+ code: RECOVERY_ISSUES.ORPHAN_CLAIM,
85
+ description: `${wu.id} is 'in_progress' but worktree is missing. The worktree may have been manually deleted.`,
86
+ context: { expectedPath: worktreePath, status: wu.status },
87
+ });
88
+ actions.push({
89
+ type: RECOVERY_ACTIONS.RESET,
90
+ description: 'Reset WU status back to ready for re-claiming',
91
+ command: `pnpm wu:recover --id ${wu.id} --action reset`,
92
+ requiresForce: false,
93
+ });
94
+ }
95
+ // Check for leftover worktree: WU is done but worktree exists
96
+ if (hasWorktree && wu.status === WU_STATUS.DONE) {
97
+ issues.push({
98
+ code: RECOVERY_ISSUES.LEFTOVER_WORKTREE,
99
+ description: `${wu.id} is 'done' but worktree still exists. The cleanup may have failed.`,
100
+ context: { worktreePath, status: wu.status },
101
+ });
102
+ actions.push({
103
+ type: RECOVERY_ACTIONS.CLEANUP,
104
+ description: 'Remove leftover worktree for completed WU',
105
+ command: `pnpm wu:recover --id ${wu.id} --action cleanup`,
106
+ requiresForce: false,
107
+ });
108
+ }
109
+ // Check for inconsistent state
110
+ if (!wu.isConsistent && wu.inconsistencyReason) {
111
+ issues.push({
112
+ code: RECOVERY_ISSUES.INCONSISTENT_STATE,
113
+ description: wu.inconsistencyReason,
114
+ context: { wuId: wu.id },
115
+ });
116
+ actions.push({
117
+ type: RECOVERY_ACTIONS.RESET,
118
+ description: 'Reconcile YAML and state store',
119
+ command: `pnpm wu:recover --id ${wu.id} --action reset`,
120
+ requiresForce: false,
121
+ });
122
+ }
123
+ return {
124
+ hasIssues: issues.length > 0,
125
+ issues,
126
+ actions,
127
+ wuId: wu.id,
128
+ };
129
+ }
@@ -0,0 +1,42 @@
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
+ import type { IRecoveryAnalyzer, WuContext, RecoveryAnalysis } from '../ports/recovery.ports.js';
16
+ /**
17
+ * AnalyzeRecoveryUseCase
18
+ *
19
+ * Analyzes WU context to detect state inconsistencies and suggests
20
+ * recovery actions.
21
+ *
22
+ * @example
23
+ * // Using default analyzer via DI factory
24
+ * const useCase = createAnalyzeRecoveryUseCase();
25
+ * const analysis = await useCase.execute(context);
26
+ *
27
+ * @example
28
+ * // Using custom analyzer for testing
29
+ * const useCase = new AnalyzeRecoveryUseCase(mockAnalyzer);
30
+ * const analysis = await useCase.execute(context);
31
+ */
32
+ export declare class AnalyzeRecoveryUseCase {
33
+ private readonly recoveryAnalyzer;
34
+ constructor(recoveryAnalyzer: IRecoveryAnalyzer);
35
+ /**
36
+ * Execute the use case to analyze recovery issues.
37
+ *
38
+ * @param context - Current WU context
39
+ * @returns Promise<RecoveryAnalysis> - Analysis with issues and suggested actions
40
+ */
41
+ execute(context: WuContext): Promise<RecoveryAnalysis>;
42
+ }