@lumenflow/core 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +362 -7
- package/dist/adapters/context-adapters.d.ts +90 -0
- package/dist/adapters/context-adapters.js +99 -0
- package/dist/adapters/index.d.ts +14 -0
- package/dist/adapters/index.js +18 -0
- package/dist/adapters/recovery-adapters.d.ts +40 -0
- package/dist/adapters/recovery-adapters.js +43 -0
- package/dist/adapters/validation-adapters.d.ts +52 -0
- package/dist/adapters/validation-adapters.js +59 -0
- package/dist/agent-patterns-registry.d.ts +100 -2
- package/dist/agent-patterns-registry.js +124 -0
- package/dist/arg-parser.js +7 -0
- package/dist/branch-check.d.ts +32 -3
- package/dist/branch-check.js +81 -15
- package/dist/color-support.d.ts +32 -0
- package/dist/color-support.js +64 -0
- package/dist/context/context-computer.d.ts +46 -0
- package/dist/context/context-computer.js +125 -0
- package/dist/context/git-state-reader.d.ts +51 -0
- package/dist/context/git-state-reader.js +61 -0
- package/dist/context/index.d.ts +17 -0
- package/dist/context/index.js +17 -0
- package/dist/context/location-resolver.d.ts +48 -0
- package/dist/context/location-resolver.js +175 -0
- package/dist/context/wu-state-reader.d.ts +37 -0
- package/dist/context/wu-state-reader.js +76 -0
- package/dist/context-di.d.ts +184 -0
- package/dist/context-di.js +178 -0
- package/dist/context-validation-integration.d.ts +77 -0
- package/dist/context-validation-integration.js +157 -0
- package/dist/cycle-detector.d.ts +51 -0
- package/dist/cycle-detector.js +89 -0
- package/dist/dependency-graph.js +1 -11
- package/dist/domain/context.schemas.d.ts +147 -0
- package/dist/domain/context.schemas.js +126 -0
- package/dist/domain/index.d.ts +14 -0
- package/dist/domain/index.js +18 -0
- package/dist/domain/recovery.schemas.d.ts +115 -0
- package/dist/domain/recovery.schemas.js +83 -0
- package/dist/domain/validation.schemas.d.ts +146 -0
- package/dist/domain/validation.schemas.js +114 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +47 -0
- package/dist/lumenflow-config-schema.d.ts +47 -0
- package/dist/lumenflow-config-schema.js +84 -4
- package/dist/ports/context.ports.d.ts +135 -0
- package/dist/ports/context.ports.js +21 -0
- package/dist/ports/index.d.ts +14 -0
- package/dist/ports/index.js +14 -0
- package/dist/ports/recovery.ports.d.ts +58 -0
- package/dist/ports/recovery.ports.js +17 -0
- package/dist/ports/validation.ports.d.ts +74 -0
- package/dist/ports/validation.ports.js +17 -0
- package/dist/recovery/index.d.ts +11 -0
- package/dist/recovery/index.js +11 -0
- package/dist/recovery/recovery-analyzer.d.ts +66 -0
- package/dist/recovery/recovery-analyzer.js +129 -0
- package/dist/usecases/analyze-recovery.usecase.d.ts +42 -0
- package/dist/usecases/analyze-recovery.usecase.js +45 -0
- package/dist/usecases/compute-context.usecase.d.ts +62 -0
- package/dist/usecases/compute-context.usecase.js +101 -0
- package/dist/usecases/index.d.ts +14 -0
- package/dist/usecases/index.js +18 -0
- package/dist/usecases/validate-command.usecase.d.ts +55 -0
- package/dist/usecases/validate-command.usecase.js +154 -0
- package/dist/validation/command-registry.d.ts +38 -0
- package/dist/validation/command-registry.js +229 -0
- package/dist/validation/index.d.ts +15 -0
- package/dist/validation/index.js +15 -0
- package/dist/validation/types.d.ts +135 -0
- package/dist/validation/types.js +11 -0
- package/dist/validation/validate-command.d.ts +27 -0
- package/dist/validation/validate-command.js +160 -0
- package/dist/wu-constants.d.ts +136 -0
- package/dist/wu-constants.js +124 -0
- package/dist/wu-done-preflight.js +8 -1
- package/dist/wu-helpers.d.ts +5 -1
- package/dist/wu-helpers.js +12 -1
- package/package.json +3 -6
package/README.md
CHANGED
|
@@ -8,6 +8,45 @@ Core WU lifecycle tools for the LumenFlow workflow framework.
|
|
|
8
8
|
pnpm add @lumenflow/core
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
This package follows **hexagonal architecture** (ports and adapters) to enable dependency injection and testing.
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
+---------------------------+
|
|
17
|
+
| Use Cases | Application layer
|
|
18
|
+
| ComputeContextUseCase |
|
|
19
|
+
| ValidateCommandUseCase |
|
|
20
|
+
| AnalyzeRecoveryUseCase |
|
|
21
|
+
+------------+--------------+
|
|
22
|
+
|
|
|
23
|
+
| depends on
|
|
24
|
+
v
|
|
25
|
+
+---------------------------+
|
|
26
|
+
| Port Interfaces | Abstractions
|
|
27
|
+
| ILocationResolver |
|
|
28
|
+
| IGitStateReader |
|
|
29
|
+
| IWuStateReader |
|
|
30
|
+
+------------+--------------+
|
|
31
|
+
^
|
|
32
|
+
| implements
|
|
33
|
+
|
|
|
34
|
+
+---------------------------+
|
|
35
|
+
| Adapter Classes | Infrastructure
|
|
36
|
+
| SimpleGitLocationAdapter |
|
|
37
|
+
| FileSystemWuStateAdapter |
|
|
38
|
+
+---------------------------+
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Key Benefits:**
|
|
42
|
+
|
|
43
|
+
- **Testability**: Inject mock adapters for deterministic testing
|
|
44
|
+
- **Extensibility**: Replace adapters for different environments (CI/CD, testing)
|
|
45
|
+
- **Maintainability**: Clear separation of concerns
|
|
46
|
+
- **Backwards Compatible**: Original functions still work unchanged
|
|
47
|
+
|
|
48
|
+
See [ADR-001: Hexagonal Architecture](../../docs/04-operations/adr/ADR-001-hexagonal-architecture.md) for the full decision record.
|
|
49
|
+
|
|
11
50
|
## Usage
|
|
12
51
|
|
|
13
52
|
### Git Operations
|
|
@@ -70,23 +109,54 @@ await worktrees.remove('worktrees/operations-wu-123');
|
|
|
70
109
|
|
|
71
110
|
### Agent Branch Patterns
|
|
72
111
|
|
|
73
|
-
Check if a branch is an agent branch that can bypass worktree requirements. Patterns are fetched from a central registry with 7-day caching.
|
|
112
|
+
Check if a branch is an agent branch that can bypass worktree requirements. Patterns are fetched from a central registry with 7-day caching, and can be configured via `.lumenflow.config.yaml`.
|
|
74
113
|
|
|
75
114
|
```typescript
|
|
76
|
-
import { isAgentBranch,
|
|
115
|
+
import { isAgentBranch, isAgentBranchWithDetails, resolveAgentPatterns } from '@lumenflow/core';
|
|
77
116
|
|
|
78
117
|
// Check if branch can bypass worktree requirements (async, uses registry)
|
|
79
118
|
if (await isAgentBranch('claude/session-12345')) {
|
|
80
119
|
console.log('Agent branch - bypass allowed');
|
|
81
120
|
}
|
|
82
121
|
|
|
83
|
-
// Get
|
|
84
|
-
const
|
|
85
|
-
|
|
122
|
+
// Get detailed result for observability
|
|
123
|
+
const result = await isAgentBranchWithDetails('claude/session-123');
|
|
124
|
+
if (result.isMatch) {
|
|
125
|
+
console.log(`Matched via ${result.patternResult.source}`); // 'registry', 'merged', 'override', 'config', 'defaults'
|
|
126
|
+
console.log(`Registry fetched: ${result.patternResult.registryFetched}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Resolve patterns with custom options (useful for testing)
|
|
130
|
+
const resolved = await resolveAgentPatterns({
|
|
131
|
+
configPatterns: ['my-agent/*'], // Merge with registry
|
|
132
|
+
// overridePatterns: ['only-this/*'], // Replace registry entirely
|
|
133
|
+
// disableAgentPatternRegistry: true, // Airgapped mode
|
|
134
|
+
});
|
|
135
|
+
console.log(resolved.patterns, resolved.source);
|
|
86
136
|
|
|
87
137
|
// Synchronous version (uses local config only, no registry fetch)
|
|
88
138
|
import { isAgentBranchSync } from '@lumenflow/core';
|
|
89
|
-
const
|
|
139
|
+
const syncResult = isAgentBranchSync('agent/task-123');
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### Configuration Options
|
|
143
|
+
|
|
144
|
+
In `.lumenflow.config.yaml`:
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
git:
|
|
148
|
+
# Patterns to MERGE with registry (default: [])
|
|
149
|
+
agentBranchPatterns:
|
|
150
|
+
- 'my-custom-agent/*'
|
|
151
|
+
- 'internal-tool/*'
|
|
152
|
+
|
|
153
|
+
# Patterns that REPLACE registry entirely (optional)
|
|
154
|
+
# agentBranchPatternsOverride:
|
|
155
|
+
# - 'claude/*'
|
|
156
|
+
# - 'codex/*'
|
|
157
|
+
|
|
158
|
+
# Disable registry fetch for airgapped environments (default: false)
|
|
159
|
+
# disableAgentPatternRegistry: true
|
|
90
160
|
```
|
|
91
161
|
|
|
92
162
|
Protected branches (main, master, lane/\*) are **never** bypassed, regardless of patterns.
|
|
@@ -121,12 +191,295 @@ Protected branches (main, master, lane/\*) are **never** bypassed, regardless of
|
|
|
121
191
|
| `list()` | List all worktrees |
|
|
122
192
|
| `exists(path)` | Check if worktree exists |
|
|
123
193
|
|
|
194
|
+
### Context-Aware Validation Ports (WU-1093)
|
|
195
|
+
|
|
196
|
+
Port interfaces for context-aware validation system. These abstractions allow external users to inject custom implementations.
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
import type {
|
|
200
|
+
ILocationResolver,
|
|
201
|
+
IGitStateReader,
|
|
202
|
+
IWuStateReader,
|
|
203
|
+
ICommandRegistry,
|
|
204
|
+
IRecoveryAnalyzer,
|
|
205
|
+
} from '@lumenflow/core';
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Adapter Classes (WU-1094)
|
|
209
|
+
|
|
210
|
+
Concrete adapter implementations that wrap the existing functions:
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
import {
|
|
214
|
+
// Context adapters
|
|
215
|
+
SimpleGitLocationAdapter,
|
|
216
|
+
SimpleGitStateAdapter,
|
|
217
|
+
FileSystemWuStateAdapter,
|
|
218
|
+
// Validation adapters
|
|
219
|
+
CommandRegistryAdapter,
|
|
220
|
+
// Recovery adapters
|
|
221
|
+
RecoveryAnalyzerAdapter,
|
|
222
|
+
} from '@lumenflow/core';
|
|
223
|
+
|
|
224
|
+
// Create adapters implementing port interfaces
|
|
225
|
+
const locationResolver = new SimpleGitLocationAdapter();
|
|
226
|
+
const gitStateReader = new SimpleGitStateAdapter();
|
|
227
|
+
const wuStateReader = new FileSystemWuStateAdapter();
|
|
228
|
+
const commandRegistry = new CommandRegistryAdapter();
|
|
229
|
+
const recoveryAnalyzer = new RecoveryAnalyzerAdapter();
|
|
230
|
+
|
|
231
|
+
// Use adapters
|
|
232
|
+
const location = await locationResolver.resolveLocation();
|
|
233
|
+
const gitState = await gitStateReader.readGitState();
|
|
234
|
+
const wuState = await wuStateReader.readWuState('WU-1094', '/repo');
|
|
235
|
+
const cmdDef = commandRegistry.getCommandDefinition('wu:done');
|
|
236
|
+
const analysis = await recoveryAnalyzer.analyzeRecovery(context);
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Use Cases with Dependency Injection (WU-1094)
|
|
240
|
+
|
|
241
|
+
Use case classes with constructor injection enable testing with mock adapters:
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
import {
|
|
245
|
+
ComputeContextUseCase,
|
|
246
|
+
ValidateCommandUseCase,
|
|
247
|
+
AnalyzeRecoveryUseCase,
|
|
248
|
+
SimpleGitLocationAdapter,
|
|
249
|
+
SimpleGitStateAdapter,
|
|
250
|
+
FileSystemWuStateAdapter,
|
|
251
|
+
CommandRegistryAdapter,
|
|
252
|
+
RecoveryAnalyzerAdapter,
|
|
253
|
+
} from '@lumenflow/core';
|
|
254
|
+
|
|
255
|
+
// Manual wiring with real adapters
|
|
256
|
+
const computeContext = new ComputeContextUseCase(
|
|
257
|
+
new SimpleGitLocationAdapter(),
|
|
258
|
+
new SimpleGitStateAdapter(),
|
|
259
|
+
new FileSystemWuStateAdapter(),
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
const validateCommand = new ValidateCommandUseCase(new CommandRegistryAdapter());
|
|
263
|
+
|
|
264
|
+
const analyzeRecovery = new AnalyzeRecoveryUseCase(new RecoveryAnalyzerAdapter());
|
|
265
|
+
|
|
266
|
+
// Execute use cases
|
|
267
|
+
const context = await computeContext.execute({ wuId: 'WU-1094' });
|
|
268
|
+
const validation = await validateCommand.execute('wu:done', context);
|
|
269
|
+
const recovery = await analyzeRecovery.execute(context);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### DI Factory Functions (WU-1094)
|
|
273
|
+
|
|
274
|
+
Factory functions create fully wired use cases with default or custom adapters:
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
import {
|
|
278
|
+
createComputeContextUseCase,
|
|
279
|
+
createValidateCommandUseCase,
|
|
280
|
+
createAnalyzeRecoveryUseCase,
|
|
281
|
+
} from '@lumenflow/core';
|
|
282
|
+
|
|
283
|
+
// Use defaults - simplest approach
|
|
284
|
+
const useCase = createComputeContextUseCase();
|
|
285
|
+
const context = await useCase.execute({ wuId: 'WU-1094' });
|
|
286
|
+
|
|
287
|
+
// Inject custom adapters for testing
|
|
288
|
+
const mockLocationResolver = {
|
|
289
|
+
resolveLocation: async () => ({
|
|
290
|
+
type: 'main' as const,
|
|
291
|
+
cwd: '/test',
|
|
292
|
+
gitRoot: '/test',
|
|
293
|
+
mainCheckout: '/test',
|
|
294
|
+
worktreeName: null,
|
|
295
|
+
worktreeWuId: null,
|
|
296
|
+
}),
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const testUseCase = createComputeContextUseCase({
|
|
300
|
+
locationResolver: mockLocationResolver,
|
|
301
|
+
// gitStateReader and wuStateReader use defaults
|
|
302
|
+
});
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Convenience Functions (WU-1094)
|
|
306
|
+
|
|
307
|
+
For simple use cases, backwards compatible functions are available:
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
import { computeWuContext, validateCommand, analyzeRecoveryIssues } from '@lumenflow/core';
|
|
311
|
+
|
|
312
|
+
// Compute context (uses default adapters internally)
|
|
313
|
+
const context = await computeWuContext({ wuId: 'WU-1094' });
|
|
314
|
+
|
|
315
|
+
// Validate a command
|
|
316
|
+
const validation = await validateCommand('wu:done', context);
|
|
317
|
+
if (!validation.valid) {
|
|
318
|
+
console.error(validation.errors[0].message);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Analyze for recovery issues
|
|
322
|
+
const recovery = await analyzeRecoveryIssues(context);
|
|
323
|
+
if (recovery.hasIssues) {
|
|
324
|
+
for (const action of recovery.actions) {
|
|
325
|
+
console.log(`Fix: ${action.command}`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Domain Schemas (Zod)
|
|
331
|
+
|
|
332
|
+
Runtime validation schemas for domain types. Types are inferred from Zod schemas using `z.infer<>`.
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
import {
|
|
336
|
+
// Context schemas
|
|
337
|
+
LocationContextSchema,
|
|
338
|
+
GitStateSchema,
|
|
339
|
+
WuStateResultSchema,
|
|
340
|
+
SessionStateSchema,
|
|
341
|
+
WuContextSchema,
|
|
342
|
+
|
|
343
|
+
// Validation schemas
|
|
344
|
+
ValidationErrorSchema,
|
|
345
|
+
ValidationWarningSchema,
|
|
346
|
+
ValidationResultSchema,
|
|
347
|
+
CommandPredicateConfigSchema,
|
|
348
|
+
CommandDefinitionConfigSchema,
|
|
349
|
+
|
|
350
|
+
// Recovery schemas
|
|
351
|
+
RecoveryIssueSchema,
|
|
352
|
+
RecoveryActionSchema,
|
|
353
|
+
RecoveryAnalysisSchema,
|
|
354
|
+
|
|
355
|
+
// Types (inferred from schemas)
|
|
356
|
+
type LocationContext,
|
|
357
|
+
type GitState,
|
|
358
|
+
type WuStateResult,
|
|
359
|
+
type ValidationError,
|
|
360
|
+
type RecoveryAnalysis,
|
|
361
|
+
} from '@lumenflow/core';
|
|
362
|
+
|
|
363
|
+
// Validate runtime data
|
|
364
|
+
const result = LocationContextSchema.safeParse(unknownData);
|
|
365
|
+
if (result.success) {
|
|
366
|
+
const location: LocationContext = result.data;
|
|
367
|
+
console.log(`Type: ${location.type}, CWD: ${location.cwd}`);
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Testing with Custom Adapters
|
|
372
|
+
|
|
373
|
+
The hexagonal architecture makes testing straightforward. Inject mock adapters to create deterministic tests without file system or git dependencies.
|
|
374
|
+
|
|
375
|
+
### Example: Testing with Mock Adapters
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
import { describe, it, expect } from 'vitest';
|
|
379
|
+
import { createComputeContextUseCase } from '@lumenflow/core';
|
|
380
|
+
import type { ILocationResolver, IGitStateReader, IWuStateReader } from '@lumenflow/core';
|
|
381
|
+
|
|
382
|
+
describe('ComputeContextUseCase', () => {
|
|
383
|
+
it('should detect worktree context', async () => {
|
|
384
|
+
// Create mock adapters
|
|
385
|
+
const mockLocation: ILocationResolver = {
|
|
386
|
+
resolveLocation: async () => ({
|
|
387
|
+
type: 'worktree',
|
|
388
|
+
cwd: '/test/worktrees/ops-wu-1095',
|
|
389
|
+
gitRoot: '/test/worktrees/ops-wu-1095',
|
|
390
|
+
mainCheckout: '/test',
|
|
391
|
+
worktreeName: 'ops-wu-1095',
|
|
392
|
+
worktreeWuId: 'WU-1095',
|
|
393
|
+
}),
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const mockGitState: IGitStateReader = {
|
|
397
|
+
readGitState: async () => ({
|
|
398
|
+
branch: 'lane/operations/wu-1095',
|
|
399
|
+
isDetached: false,
|
|
400
|
+
isDirty: false,
|
|
401
|
+
hasStaged: false,
|
|
402
|
+
ahead: 1,
|
|
403
|
+
behind: 0,
|
|
404
|
+
tracking: 'origin/lane/operations/wu-1095',
|
|
405
|
+
modifiedFiles: [],
|
|
406
|
+
hasError: false,
|
|
407
|
+
errorMessage: null,
|
|
408
|
+
}),
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
const mockWuState: IWuStateReader = {
|
|
412
|
+
readWuState: async () => ({
|
|
413
|
+
id: 'WU-1095',
|
|
414
|
+
status: 'in_progress',
|
|
415
|
+
lane: 'Content: Documentation',
|
|
416
|
+
title: 'Test WU',
|
|
417
|
+
yamlPath: '/test/docs/04-operations/tasks/wu/WU-1095.yaml',
|
|
418
|
+
isConsistent: true,
|
|
419
|
+
inconsistencyReason: null,
|
|
420
|
+
}),
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
// Create use case with mocks
|
|
424
|
+
const useCase = createComputeContextUseCase({
|
|
425
|
+
locationResolver: mockLocation,
|
|
426
|
+
gitStateReader: mockGitState,
|
|
427
|
+
wuStateReader: mockWuState,
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// Execute
|
|
431
|
+
const context = await useCase.execute({ wuId: 'WU-1095' });
|
|
432
|
+
|
|
433
|
+
// Assert - fully deterministic
|
|
434
|
+
expect(context.location.type).toBe('worktree');
|
|
435
|
+
expect(context.location.worktreeWuId).toBe('WU-1095');
|
|
436
|
+
expect(context.wu?.status).toBe('in_progress');
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Example: CI/CD Custom Adapter
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
import type { ILocationResolver, LocationContext } from '@lumenflow/core';
|
|
445
|
+
import { createComputeContextUseCase } from '@lumenflow/core';
|
|
446
|
+
|
|
447
|
+
// CI environments always run in main checkout
|
|
448
|
+
class CILocationResolver implements ILocationResolver {
|
|
449
|
+
constructor(private readonly repoPath: string) {}
|
|
450
|
+
|
|
451
|
+
async resolveLocation(cwd?: string): Promise<LocationContext> {
|
|
452
|
+
return {
|
|
453
|
+
type: 'main',
|
|
454
|
+
cwd: cwd || this.repoPath,
|
|
455
|
+
gitRoot: this.repoPath,
|
|
456
|
+
mainCheckout: this.repoPath,
|
|
457
|
+
worktreeName: null,
|
|
458
|
+
worktreeWuId: null,
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Usage in CI
|
|
464
|
+
const useCase = createComputeContextUseCase({
|
|
465
|
+
locationResolver: new CILocationResolver('/github/workspace'),
|
|
466
|
+
});
|
|
467
|
+
```
|
|
468
|
+
|
|
124
469
|
## Features
|
|
125
470
|
|
|
126
471
|
- **Type-safe**: Full TypeScript support with detailed type definitions
|
|
127
|
-
- **Dependency injection**: Easy to test with mock
|
|
472
|
+
- **Dependency injection**: Easy to test with mock adapters
|
|
473
|
+
- **Hexagonal architecture**: Port interfaces for external injection
|
|
128
474
|
- **Safe worktree cleanup**: Handles orphan directories and corrupted metadata
|
|
129
475
|
- **Modern**: Node 22+, ESM-only, strict TypeScript
|
|
476
|
+
- **Zod schemas**: Runtime validation for all domain types
|
|
477
|
+
|
|
478
|
+
## Further Reading
|
|
479
|
+
|
|
480
|
+
- [ADR-001: Hexagonal Architecture](../../docs/04-operations/adr/ADR-001-hexagonal-architecture.md)
|
|
481
|
+
- [Migration Guide](../../docs/04-operations/adr/migration-guide-hexagonal-architecture.md)
|
|
482
|
+
- [Port Interfaces Reference](https://lumenflow.dev/reference/ports/)
|
|
130
483
|
|
|
131
484
|
## Status
|
|
132
485
|
|
|
@@ -134,6 +487,8 @@ This package is under active development. Current features:
|
|
|
134
487
|
|
|
135
488
|
- Git operations (GitAdapter)
|
|
136
489
|
- Worktree management (WorktreeManager)
|
|
490
|
+
- Context-aware validation (WU-1090)
|
|
491
|
+
- Hexagonal architecture with DI (INIT-002)
|
|
137
492
|
- Modern tooling (Node 22, ESLint 9, TypeScript 5.7, Vitest 4)
|
|
138
493
|
- Security and code quality linting
|
|
139
494
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Adapters
|
|
3
|
+
*
|
|
4
|
+
* WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
|
|
5
|
+
*
|
|
6
|
+
* Concrete adapter implementations for context-related port interfaces.
|
|
7
|
+
* These adapters wrap the existing implementation functions to conform
|
|
8
|
+
* to the port interfaces, enabling dependency injection.
|
|
9
|
+
*
|
|
10
|
+
* Adapters:
|
|
11
|
+
* - SimpleGitLocationAdapter - Implements ILocationResolver
|
|
12
|
+
* - SimpleGitStateAdapter - Implements IGitStateReader
|
|
13
|
+
* - FileSystemWuStateAdapter - Implements IWuStateReader
|
|
14
|
+
*
|
|
15
|
+
* @module adapters/context-adapters
|
|
16
|
+
*/
|
|
17
|
+
import type { ILocationResolver, IGitStateReader, IWuStateReader, LocationContext, GitState, WuStateResult } from '../ports/context.ports.js';
|
|
18
|
+
/**
|
|
19
|
+
* SimpleGitLocationAdapter
|
|
20
|
+
*
|
|
21
|
+
* Implements ILocationResolver by delegating to the resolveLocation function.
|
|
22
|
+
* Uses simple-git library under the hood.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // Use default adapter
|
|
26
|
+
* const adapter = new SimpleGitLocationAdapter();
|
|
27
|
+
* const location = await adapter.resolveLocation();
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* // Use as port interface
|
|
31
|
+
* const resolver: ILocationResolver = new SimpleGitLocationAdapter();
|
|
32
|
+
*/
|
|
33
|
+
export declare class SimpleGitLocationAdapter implements ILocationResolver {
|
|
34
|
+
/**
|
|
35
|
+
* Resolve location context for the given working directory.
|
|
36
|
+
*
|
|
37
|
+
* @param cwd - Current working directory (defaults to process.cwd())
|
|
38
|
+
* @returns Promise<LocationContext> - Resolved location context
|
|
39
|
+
*/
|
|
40
|
+
resolveLocation(cwd?: string): Promise<LocationContext>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* SimpleGitStateAdapter
|
|
44
|
+
*
|
|
45
|
+
* Implements IGitStateReader by delegating to the readGitState function.
|
|
46
|
+
* Uses simple-git library under the hood.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* // Use default adapter
|
|
50
|
+
* const adapter = new SimpleGitStateAdapter();
|
|
51
|
+
* const gitState = await adapter.readGitState();
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* // Use as port interface
|
|
55
|
+
* const reader: IGitStateReader = new SimpleGitStateAdapter();
|
|
56
|
+
*/
|
|
57
|
+
export declare class SimpleGitStateAdapter implements IGitStateReader {
|
|
58
|
+
/**
|
|
59
|
+
* Read current git state for the given working directory.
|
|
60
|
+
*
|
|
61
|
+
* @param cwd - Current working directory (defaults to process.cwd())
|
|
62
|
+
* @returns Promise<GitState> - Current git state
|
|
63
|
+
*/
|
|
64
|
+
readGitState(cwd?: string): Promise<GitState>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* FileSystemWuStateAdapter
|
|
68
|
+
*
|
|
69
|
+
* Implements IWuStateReader by delegating to the readWuState function.
|
|
70
|
+
* Reads WU state from YAML files in the filesystem.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* // Use default adapter
|
|
74
|
+
* const adapter = new FileSystemWuStateAdapter();
|
|
75
|
+
* const wuState = await adapter.readWuState('WU-1094', '/repo');
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* // Use as port interface
|
|
79
|
+
* const reader: IWuStateReader = new FileSystemWuStateAdapter();
|
|
80
|
+
*/
|
|
81
|
+
export declare class FileSystemWuStateAdapter implements IWuStateReader {
|
|
82
|
+
/**
|
|
83
|
+
* Read WU state from YAML and detect inconsistencies.
|
|
84
|
+
*
|
|
85
|
+
* @param wuId - WU ID (e.g., 'WU-1094' or 'wu-1094')
|
|
86
|
+
* @param repoRoot - Repository root path
|
|
87
|
+
* @returns Promise<WuStateResult | null> - WU state or null if not found
|
|
88
|
+
*/
|
|
89
|
+
readWuState(wuId: string, repoRoot: string): Promise<WuStateResult | null>;
|
|
90
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Adapters
|
|
3
|
+
*
|
|
4
|
+
* WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
|
|
5
|
+
*
|
|
6
|
+
* Concrete adapter implementations for context-related port interfaces.
|
|
7
|
+
* These adapters wrap the existing implementation functions to conform
|
|
8
|
+
* to the port interfaces, enabling dependency injection.
|
|
9
|
+
*
|
|
10
|
+
* Adapters:
|
|
11
|
+
* - SimpleGitLocationAdapter - Implements ILocationResolver
|
|
12
|
+
* - SimpleGitStateAdapter - Implements IGitStateReader
|
|
13
|
+
* - FileSystemWuStateAdapter - Implements IWuStateReader
|
|
14
|
+
*
|
|
15
|
+
* @module adapters/context-adapters
|
|
16
|
+
*/
|
|
17
|
+
// Import existing implementations
|
|
18
|
+
import { resolveLocation } from '../context/location-resolver.js';
|
|
19
|
+
import { readGitState } from '../context/git-state-reader.js';
|
|
20
|
+
import { readWuState } from '../context/wu-state-reader.js';
|
|
21
|
+
/**
|
|
22
|
+
* SimpleGitLocationAdapter
|
|
23
|
+
*
|
|
24
|
+
* Implements ILocationResolver by delegating to the resolveLocation function.
|
|
25
|
+
* Uses simple-git library under the hood.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // Use default adapter
|
|
29
|
+
* const adapter = new SimpleGitLocationAdapter();
|
|
30
|
+
* const location = await adapter.resolveLocation();
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Use as port interface
|
|
34
|
+
* const resolver: ILocationResolver = new SimpleGitLocationAdapter();
|
|
35
|
+
*/
|
|
36
|
+
export class SimpleGitLocationAdapter {
|
|
37
|
+
/**
|
|
38
|
+
* Resolve location context for the given working directory.
|
|
39
|
+
*
|
|
40
|
+
* @param cwd - Current working directory (defaults to process.cwd())
|
|
41
|
+
* @returns Promise<LocationContext> - Resolved location context
|
|
42
|
+
*/
|
|
43
|
+
async resolveLocation(cwd) {
|
|
44
|
+
return resolveLocation(cwd);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* SimpleGitStateAdapter
|
|
49
|
+
*
|
|
50
|
+
* Implements IGitStateReader by delegating to the readGitState function.
|
|
51
|
+
* Uses simple-git library under the hood.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* // Use default adapter
|
|
55
|
+
* const adapter = new SimpleGitStateAdapter();
|
|
56
|
+
* const gitState = await adapter.readGitState();
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // Use as port interface
|
|
60
|
+
* const reader: IGitStateReader = new SimpleGitStateAdapter();
|
|
61
|
+
*/
|
|
62
|
+
export class SimpleGitStateAdapter {
|
|
63
|
+
/**
|
|
64
|
+
* Read current git state for the given working directory.
|
|
65
|
+
*
|
|
66
|
+
* @param cwd - Current working directory (defaults to process.cwd())
|
|
67
|
+
* @returns Promise<GitState> - Current git state
|
|
68
|
+
*/
|
|
69
|
+
async readGitState(cwd) {
|
|
70
|
+
return readGitState(cwd);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* FileSystemWuStateAdapter
|
|
75
|
+
*
|
|
76
|
+
* Implements IWuStateReader by delegating to the readWuState function.
|
|
77
|
+
* Reads WU state from YAML files in the filesystem.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* // Use default adapter
|
|
81
|
+
* const adapter = new FileSystemWuStateAdapter();
|
|
82
|
+
* const wuState = await adapter.readWuState('WU-1094', '/repo');
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* // Use as port interface
|
|
86
|
+
* const reader: IWuStateReader = new FileSystemWuStateAdapter();
|
|
87
|
+
*/
|
|
88
|
+
export class FileSystemWuStateAdapter {
|
|
89
|
+
/**
|
|
90
|
+
* Read WU state from YAML and detect inconsistencies.
|
|
91
|
+
*
|
|
92
|
+
* @param wuId - WU ID (e.g., 'WU-1094' or 'wu-1094')
|
|
93
|
+
* @param repoRoot - Repository root path
|
|
94
|
+
* @returns Promise<WuStateResult | null> - WU state or null if not found
|
|
95
|
+
*/
|
|
96
|
+
async readWuState(wuId, repoRoot) {
|
|
97
|
+
return readWuState(wuId, repoRoot);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapters Index
|
|
3
|
+
*
|
|
4
|
+
* WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
|
|
5
|
+
*
|
|
6
|
+
* Re-exports all adapter implementations.
|
|
7
|
+
*
|
|
8
|
+
* @module adapters
|
|
9
|
+
*/
|
|
10
|
+
export { SimpleGitLocationAdapter, SimpleGitStateAdapter, FileSystemWuStateAdapter, } from './context-adapters.js';
|
|
11
|
+
export { CommandRegistryAdapter } from './validation-adapters.js';
|
|
12
|
+
export { RecoveryAnalyzerAdapter } from './recovery-adapters.js';
|
|
13
|
+
export { TerminalDashboardRenderer } from './terminal-renderer.adapter.js';
|
|
14
|
+
export { FileSystemMetricsCollector } from './filesystem-metrics.adapter.js';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapters Index
|
|
3
|
+
*
|
|
4
|
+
* WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
|
|
5
|
+
*
|
|
6
|
+
* Re-exports all adapter implementations.
|
|
7
|
+
*
|
|
8
|
+
* @module adapters
|
|
9
|
+
*/
|
|
10
|
+
// Context adapters
|
|
11
|
+
export { SimpleGitLocationAdapter, SimpleGitStateAdapter, FileSystemWuStateAdapter, } from './context-adapters.js';
|
|
12
|
+
// Validation adapters
|
|
13
|
+
export { CommandRegistryAdapter } from './validation-adapters.js';
|
|
14
|
+
// Recovery adapters
|
|
15
|
+
export { RecoveryAnalyzerAdapter } from './recovery-adapters.js';
|
|
16
|
+
// Existing adapters (pre-WU-1094)
|
|
17
|
+
export { TerminalDashboardRenderer } from './terminal-renderer.adapter.js';
|
|
18
|
+
export { FileSystemMetricsCollector } from './filesystem-metrics.adapter.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recovery Adapters
|
|
3
|
+
*
|
|
4
|
+
* WU-1094: INIT-002 Phase 2 - Implement adapters and dependency injection
|
|
5
|
+
*
|
|
6
|
+
* Concrete adapter implementations for recovery-related port interfaces.
|
|
7
|
+
* These adapters wrap the existing implementation functions to conform
|
|
8
|
+
* to the port interfaces, enabling dependency injection.
|
|
9
|
+
*
|
|
10
|
+
* Adapters:
|
|
11
|
+
* - RecoveryAnalyzerAdapter - Implements IRecoveryAnalyzer
|
|
12
|
+
*
|
|
13
|
+
* @module adapters/recovery-adapters
|
|
14
|
+
*/
|
|
15
|
+
import type { IRecoveryAnalyzer, WuContext, RecoveryAnalysis } from '../ports/recovery.ports.js';
|
|
16
|
+
/**
|
|
17
|
+
* RecoveryAnalyzerAdapter
|
|
18
|
+
*
|
|
19
|
+
* Implements IRecoveryAnalyzer by delegating to the analyzeRecovery function.
|
|
20
|
+
* Analyzes WU context to detect state inconsistencies and suggests
|
|
21
|
+
* recovery actions.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Use default adapter
|
|
25
|
+
* const adapter = new RecoveryAnalyzerAdapter();
|
|
26
|
+
* const analysis = await adapter.analyzeRecovery(context);
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Use as port interface
|
|
30
|
+
* const analyzer: IRecoveryAnalyzer = new RecoveryAnalyzerAdapter();
|
|
31
|
+
*/
|
|
32
|
+
export declare class RecoveryAnalyzerAdapter implements IRecoveryAnalyzer {
|
|
33
|
+
/**
|
|
34
|
+
* Analyze context for recovery issues.
|
|
35
|
+
*
|
|
36
|
+
* @param context - Current WU context
|
|
37
|
+
* @returns Promise<RecoveryAnalysis> - Recovery analysis with issues and suggested actions
|
|
38
|
+
*/
|
|
39
|
+
analyzeRecovery(context: WuContext): Promise<RecoveryAnalysis>;
|
|
40
|
+
}
|