@eldrforge/kodrdriv 1.2.128 → 1.2.130

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 (32) hide show
  1. package/dist/commands/audio-commit.js +2 -2
  2. package/dist/commands/audio-commit.js.map +1 -1
  3. package/dist/commands/audio-review.js +2 -2
  4. package/dist/commands/audio-review.js.map +1 -1
  5. package/dist/commands/tree.js +4 -4
  6. package/dist/commands/tree.js.map +1 -1
  7. package/dist/constants.js +1 -1
  8. package/dist/util/general.js +3 -52
  9. package/dist/util/general.js.map +1 -1
  10. package/package.json +4 -1
  11. package/dist/execution/CommandValidator.js +0 -192
  12. package/dist/execution/CommandValidator.js.map +0 -1
  13. package/dist/execution/DependencyChecker.js +0 -102
  14. package/dist/execution/DependencyChecker.js.map +0 -1
  15. package/dist/execution/DynamicTaskPool.js +0 -661
  16. package/dist/execution/DynamicTaskPool.js.map +0 -1
  17. package/dist/execution/RecoveryManager.js +0 -584
  18. package/dist/execution/RecoveryManager.js.map +0 -1
  19. package/dist/execution/ResourceMonitor.js +0 -150
  20. package/dist/execution/ResourceMonitor.js.map +0 -1
  21. package/dist/execution/Scheduler.js +0 -98
  22. package/dist/execution/Scheduler.js.map +0 -1
  23. package/dist/execution/TreeExecutionAdapter.js +0 -225
  24. package/dist/execution/TreeExecutionAdapter.js.map +0 -1
  25. package/dist/ui/ProgressFormatter.js +0 -250
  26. package/dist/ui/ProgressFormatter.js.map +0 -1
  27. package/dist/util/checkpointManager.js +0 -166
  28. package/dist/util/checkpointManager.js.map +0 -1
  29. package/dist/util/countdown.js +0 -215
  30. package/dist/util/countdown.js.map +0 -1
  31. package/dist/util/dependencyGraph.js +0 -222
  32. package/dist/util/dependencyGraph.js.map +0 -1
@@ -1,584 +0,0 @@
1
- import { getLogger } from '../logging.js';
2
- import { findAllDependents } from '../util/dependencyGraph.js';
3
- import { CheckpointManager } from '../util/checkpointManager.js';
4
- import * as path from 'path';
5
-
6
- function _define_property(obj, key, value) {
7
- if (key in obj) {
8
- Object.defineProperty(obj, key, {
9
- value: value,
10
- enumerable: true,
11
- configurable: true,
12
- writable: true
13
- });
14
- } else {
15
- obj[key] = value;
16
- }
17
- return obj;
18
- }
19
- /**
20
- * RecoveryManager provides granular control over execution state recovery
21
- */ class RecoveryManager {
22
- /**
23
- * Resolve a package identifier (directory name or package name) to a package name
24
- */ resolvePackageName(identifier) {
25
- // Try exact package name match first
26
- if (this.graph.packages.has(identifier)) {
27
- return identifier;
28
- }
29
- // Try directory name match
30
- for (const [pkgName, pkgInfo] of this.graph.packages){
31
- const dirName = path.basename(pkgInfo.path);
32
- if (dirName === identifier) {
33
- return pkgName;
34
- }
35
- }
36
- return null;
37
- }
38
- /**
39
- * Mark packages as completed
40
- * Accepts either package names (e.g., "@eldrforge/git-tools") or directory names (e.g., "git-tools")
41
- */ async markCompleted(packages) {
42
- this.logger.info(`RECOVERY_MARKING_COMPLETED: Marking packages as completed | Package Count: ${packages.length} | Action: Update checkpoint state | Purpose: Manual recovery`);
43
- for (const pkgIdentifier of packages){
44
- // Resolve identifier to package name
45
- const pkg = this.resolvePackageName(pkgIdentifier);
46
- if (!pkg) {
47
- // List available packages for better error message
48
- const available = Array.from(this.graph.packages.entries()).map(([name, info])=>`${path.basename(info.path)} (${name})`).join(', ');
49
- throw new Error(`Package not found: ${pkgIdentifier}. Available packages: ${available}`);
50
- }
51
- // Validate not already completed
52
- if (this.checkpoint.state.completed.includes(pkg)) {
53
- this.logger.warn(`RECOVERY_ALREADY_COMPLETED: Package already marked as completed | Package: ${pkg} | Action: Skipping | Status: already-completed`);
54
- continue;
55
- }
56
- // Remove from other states
57
- this.removeFromAllStates(pkg);
58
- // Add to completed
59
- this.checkpoint.state.completed.push(pkg);
60
- this.logger.info(`RECOVERY_PACKAGE_COMPLETED: Package marked as completed | Package: ${pkg} | Status: completed | Checkpoint: Updated`);
61
- }
62
- // Update ready queue and count what got unblocked
63
- const beforeSkipped = this.checkpoint.state.skipped.length;
64
- const beforeReady = this.checkpoint.state.ready.length;
65
- this.updateReadyState();
66
- const afterSkipped = this.checkpoint.state.skipped.length;
67
- const afterReady = this.checkpoint.state.ready.length;
68
- const unblockedCount = beforeSkipped - afterSkipped;
69
- const newReadyCount = afterReady - beforeReady;
70
- // Save checkpoint
71
- await this.saveCheckpoint();
72
- this.logger.info('State updated successfully');
73
- if (unblockedCount > 0) {
74
- this.logger.info(`✓ Unblocked ${unblockedCount} package(s)`);
75
- }
76
- if (newReadyCount > 0) {
77
- this.logger.info(`✓ ${newReadyCount} package(s) ready to execute`);
78
- }
79
- if (unblockedCount === 0 && newReadyCount === 0 && this.checkpoint.state.skipped.length > 0) {
80
- this.logger.warn(`⚠️ No packages unblocked. ${this.checkpoint.state.skipped.length} packages still blocked by dependencies.`);
81
- this.logger.warn(' Use --status to see what\'s blocking them.');
82
- }
83
- }
84
- /**
85
- * Mark packages as failed
86
- */ async markFailed(packages, reason = 'Manually marked as failed') {
87
- this.logger.info(`RECOVERY_MARKING_FAILED: Marking packages as failed | Package Count: ${packages.length} | Action: Update checkpoint state | Purpose: Skip dependent packages`);
88
- for (const pkg of packages){
89
- // Validate package exists
90
- if (!this.graph.packages.has(pkg)) {
91
- throw new Error(`Package not found: ${pkg}`);
92
- }
93
- // Remove from other states
94
- this.removeFromAllStates(pkg);
95
- // Add to failed
96
- const failureInfo = {
97
- name: pkg,
98
- error: reason,
99
- isRetriable: false,
100
- attemptNumber: 1,
101
- failedAt: new Date().toISOString(),
102
- dependencies: Array.from(this.graph.edges.get(pkg) || []),
103
- dependents: Array.from(findAllDependents(pkg, this.graph))
104
- };
105
- this.checkpoint.state.failed.push(failureInfo);
106
- this.logger.info(`RECOVERY_PACKAGE_FAILED: Package marked as failed | Package: ${pkg} | Status: failed | Checkpoint: Updated`);
107
- // Cascade to dependents
108
- const dependents = findAllDependents(pkg, this.graph);
109
- for (const dep of dependents){
110
- this.removeFromAllStates(dep);
111
- this.checkpoint.state.skipped.push(dep);
112
- this.logger.warn(`RECOVERY_DEPENDENT_SKIPPED: Dependent package skipped | Package: ${dep} | Failed Dependency: ${pkg} | Reason: dependency-failed`);
113
- }
114
- }
115
- await this.saveCheckpoint();
116
- }
117
- /**
118
- * Skip packages and their dependents
119
- */ async skipPackages(packages) {
120
- this.logger.info(`Skipping ${packages.length} package(s)...`);
121
- const toSkip = new Set(packages);
122
- // Find all dependents
123
- for (const pkg of packages){
124
- const dependents = findAllDependents(pkg, this.graph);
125
- for (const dep of dependents){
126
- toSkip.add(dep);
127
- }
128
- }
129
- this.logger.info(`Total packages to skip (including dependents): ${toSkip.size}`);
130
- for (const pkg of toSkip){
131
- this.removeFromAllStates(pkg);
132
- if (!this.checkpoint.state.skipped.includes(pkg)) {
133
- this.checkpoint.state.skipped.push(pkg);
134
- }
135
- this.logger.info(`RECOVERY_PACKAGE_SKIPPED: Package marked as skipped | Package: ${pkg} | Status: skipped | Checkpoint: Updated`);
136
- }
137
- await this.saveCheckpoint();
138
- }
139
- /**
140
- * Retry failed packages
141
- */ async retryFailed(options) {
142
- const failed = this.checkpoint.state.failed;
143
- if (failed.length === 0) {
144
- this.logger.info('RECOVERY_NO_FAILED: No failed packages found | Action: Nothing to retry | Status: All packages succeeded or skipped');
145
- return;
146
- }
147
- this.logger.info(`RECOVERY_RETRY_STARTING: Initiating retry for failed packages | Failed Count: ${failed.length} | Action: Reset to pending and retry`);
148
- const retriable = [];
149
- const nonRetriable = [];
150
- for (const failedPkg of failed){
151
- if (failedPkg.isRetriable || (options === null || options === void 0 ? void 0 : options.maxRetries)) {
152
- retriable.push(failedPkg);
153
- } else {
154
- nonRetriable.push(failedPkg);
155
- }
156
- }
157
- if (nonRetriable.length > 0) {
158
- this.logger.warn(`${nonRetriable.length} package(s) are not retriable: ${nonRetriable.map((p)=>p.name).join(', ')}`);
159
- if (!(options === null || options === void 0 ? void 0 : options.maxRetries)) {
160
- this.logger.warn('Use --max-retries to force retry of non-retriable packages');
161
- }
162
- }
163
- for (const failedPkg of retriable){
164
- // Reset retry count if max retries overridden
165
- if (options === null || options === void 0 ? void 0 : options.maxRetries) {
166
- this.checkpoint.retryAttempts[failedPkg.name] = 0;
167
- }
168
- // Move back to pending
169
- this.removeFromAllStates(failedPkg.name);
170
- this.checkpoint.state.pending.push(failedPkg.name);
171
- // Un-skip dependents if they were skipped
172
- for (const dependent of failedPkg.dependents){
173
- if (this.checkpoint.state.skipped.includes(dependent)) {
174
- this.checkpoint.state.skipped = this.checkpoint.state.skipped.filter((p)=>p !== dependent);
175
- this.checkpoint.state.pending.push(dependent);
176
- this.logger.info(`RECOVERY_DEPENDENT_RESTORED: Dependent package moved back to pending | Package: ${dependent} | Previous Status: skipped | New Status: pending | Reason: Retry parent package`);
177
- }
178
- }
179
- this.logger.info(`RECOVERY_PACKAGE_PENDING: Package moved to pending for retry | Package: ${failedPkg.name} | Previous Status: failed | New Status: pending | Action: Will retry`);
180
- }
181
- // Keep only non-retriable failures in failed state
182
- this.checkpoint.state.failed = nonRetriable;
183
- // Update ready queue
184
- this.updateReadyState();
185
- await this.saveCheckpoint();
186
- this.logger.info(`RECOVERY_RETRY_READY: Packages reset and ready for retry | Package Count: ${retriable.length} | Status: pending | Next: Will execute`);
187
- }
188
- /**
189
- * Skip failed packages and continue with remaining
190
- */ async skipFailed() {
191
- const failed = this.checkpoint.state.failed.map((f)=>f.name);
192
- if (failed.length === 0) {
193
- this.logger.info('RECOVERY_NO_FAILED_TO_SKIP: No failed packages found | Action: Nothing to skip | Status: Clean state');
194
- return;
195
- }
196
- this.logger.info(`RECOVERY_SKIP_FAILED: Skipping failed packages and dependents | Failed Count: ${failed.length} | Action: Mark as skipped | Purpose: Continue with remaining packages`);
197
- await this.skipPackages(failed);
198
- // Clear failed state
199
- this.checkpoint.state.failed = [];
200
- this.logger.info('RECOVERY_SKIP_COMPLETE: Failed packages skipped successfully | Status: Execution can continue | Next: Process remaining packages');
201
- }
202
- /**
203
- * Reset specific package to initial state
204
- */ async resetPackage(packageName) {
205
- this.logger.info(`RECOVERY_PACKAGE_RESETTING: Resetting package to initial state | Package: ${packageName} | Action: Clear all state | Purpose: Fresh start`);
206
- if (!this.graph.packages.has(packageName)) {
207
- throw new Error(`Package not found: ${packageName}`);
208
- }
209
- // Remove from all states
210
- this.removeFromAllStates(packageName);
211
- // Add back to pending
212
- this.checkpoint.state.pending.push(packageName);
213
- // Clear retry attempts
214
- delete this.checkpoint.retryAttempts[packageName];
215
- delete this.checkpoint.packageStartTimes[packageName];
216
- delete this.checkpoint.packageEndTimes[packageName];
217
- delete this.checkpoint.packageDurations[packageName];
218
- await this.saveCheckpoint();
219
- this.logger.info(`RECOVERY_PACKAGE_RESET: Package reset to initial state | Package: ${packageName} | Status: pending | Checkpoint: Updated`);
220
- }
221
- /**
222
- * Validate checkpoint state integrity
223
- */ validateState() {
224
- const issues = [];
225
- const warnings = [];
226
- // Check for duplicates across states
227
- const allPackages = [
228
- ...this.checkpoint.state.pending,
229
- ...this.checkpoint.state.ready,
230
- ...this.checkpoint.state.running.map((r)=>r.name),
231
- ...this.checkpoint.state.completed,
232
- ...this.checkpoint.state.failed.map((f)=>f.name),
233
- ...this.checkpoint.state.skipped,
234
- ...this.checkpoint.state.skippedNoChanges
235
- ];
236
- const duplicates = this.findDuplicates(allPackages);
237
- if (duplicates.length > 0) {
238
- issues.push(`Packages in multiple states: ${duplicates.join(', ')}`);
239
- }
240
- // Check for missing packages
241
- const missing = this.checkpoint.buildOrder.filter((pkg)=>!allPackages.includes(pkg));
242
- if (missing.length > 0) {
243
- issues.push(`Missing packages: ${missing.join(', ')}`);
244
- }
245
- // Check dependency consistency
246
- for (const pkg of this.checkpoint.state.completed){
247
- const deps = this.graph.edges.get(pkg) || new Set();
248
- for (const dep of deps){
249
- if (!this.checkpoint.state.completed.includes(dep)) {
250
- warnings.push(`${pkg} completed but dependency ${dep} not completed`);
251
- }
252
- }
253
- }
254
- // Check for stale running packages
255
- const now = Date.now();
256
- for (const running of this.checkpoint.state.running){
257
- const elapsed = now - new Date(running.startTime).getTime();
258
- if (elapsed > 3600000) {
259
- warnings.push(`${running.name} has been running for ${this.formatDuration(elapsed)}`);
260
- }
261
- }
262
- return {
263
- valid: issues.length === 0,
264
- issues,
265
- warnings
266
- };
267
- }
268
- /**
269
- * Generate recovery hints based on current state
270
- */ generateRecoveryHints() {
271
- const hints = [];
272
- // Check for retriable failures
273
- const retriableFailed = this.checkpoint.state.failed.filter((f)=>f.isRetriable);
274
- if (retriableFailed.length > 0) {
275
- hints.push({
276
- type: 'info',
277
- message: `${retriableFailed.length} package(s) failed with retriable errors`,
278
- actionable: true,
279
- suggestedCommand: 'kodrdriv tree [command] --continue --retry-failed'
280
- });
281
- }
282
- // Check for non-retriable failures
283
- const permanentFailed = this.checkpoint.state.failed.filter((f)=>!f.isRetriable);
284
- if (permanentFailed.length > 0) {
285
- hints.push({
286
- type: 'warning',
287
- message: `${permanentFailed.length} package(s) failed permanently`,
288
- actionable: true,
289
- suggestedCommand: 'kodrdriv tree [command] --continue --skip-failed'
290
- });
291
- for (const pkg of permanentFailed.slice(0, 3)){
292
- var _this_graph_packages_get;
293
- hints.push({
294
- type: 'error',
295
- message: `${pkg.name}: ${pkg.error}`,
296
- actionable: true,
297
- suggestedCommand: `# Fix the issue, then:\nkodrdriv tree [command] --continue --mark-completed "${path.basename(((_this_graph_packages_get = this.graph.packages.get(pkg.name)) === null || _this_graph_packages_get === void 0 ? void 0 : _this_graph_packages_get.path) || pkg.name)}"`
298
- });
299
- }
300
- }
301
- // Check for long-running packages
302
- const now = Date.now();
303
- for (const running of this.checkpoint.state.running){
304
- const elapsed = now - new Date(running.startTime).getTime();
305
- if (elapsed > 1800000) {
306
- hints.push({
307
- type: 'warning',
308
- message: `${running.name} has been running for ${this.formatDuration(elapsed)} - may be stuck`,
309
- actionable: false
310
- });
311
- }
312
- }
313
- // Check for state inconsistencies
314
- const validation = this.validateState();
315
- if (!validation.valid) {
316
- hints.push({
317
- type: 'error',
318
- message: 'State inconsistencies detected - checkpoint may be corrupted',
319
- actionable: true,
320
- suggestedCommand: 'kodrdriv tree --validate-state'
321
- });
322
- }
323
- return hints;
324
- }
325
- /**
326
- * Show detailed status
327
- */ async showStatus() {
328
- const lines = [];
329
- lines.push('═══════════════════════════════════════');
330
- lines.push(' Parallel Execution Status');
331
- lines.push('═══════════════════════════════════════');
332
- lines.push('');
333
- lines.push(`Execution ID: ${this.checkpoint.executionId}`);
334
- lines.push(`Started: ${new Date(this.checkpoint.totalStartTime).toLocaleString()}`);
335
- lines.push(`Last Updated: ${new Date(this.checkpoint.lastUpdated).toLocaleString()}`);
336
- lines.push('');
337
- // Progress summary
338
- const total = this.checkpoint.buildOrder.length;
339
- const completed = this.checkpoint.state.completed.length;
340
- const skippedNoChanges = this.checkpoint.state.skippedNoChanges.length;
341
- const failed = this.checkpoint.state.failed.length;
342
- const skipped = this.checkpoint.state.skipped.length;
343
- const running = this.checkpoint.state.running.length;
344
- const pending = this.checkpoint.state.pending.length + this.checkpoint.state.ready.length;
345
- lines.push('📊 Progress:');
346
- lines.push(` Completed: ${completed}/${total} (${Math.round(completed / total * 100)}%)`);
347
- lines.push(` Skipped (no changes): ${skippedNoChanges}`);
348
- lines.push(` Running: ${running}`);
349
- lines.push(` Pending: ${pending}`);
350
- lines.push(` Failed: ${failed}`);
351
- lines.push(` Skipped (dependency failed): ${skipped}`);
352
- lines.push('');
353
- // Progress bar
354
- const progressBar = this.createProgressBar(completed, total);
355
- lines.push(`Progress: [${progressBar}] ${Math.round(completed / total * 100)}%`);
356
- lines.push('');
357
- // Running packages
358
- if (running > 0) {
359
- lines.push('🔄 Currently Running:');
360
- for (const pkg of this.checkpoint.state.running){
361
- const elapsed = Date.now() - new Date(pkg.startTime).getTime();
362
- lines.push(` • ${pkg.name} (${this.formatDuration(elapsed)})`);
363
- }
364
- lines.push('');
365
- }
366
- // Failed packages
367
- if (failed > 0) {
368
- lines.push('❌ Failed Packages:');
369
- for (const pkg of this.checkpoint.state.failed){
370
- lines.push(` ✗ ${pkg.name}`);
371
- lines.push(` Error: ${pkg.error}`);
372
- lines.push(` Retriable: ${pkg.isRetriable ? 'Yes' : 'No'}`);
373
- lines.push(` Attempts: ${pkg.attemptNumber}`);
374
- if (pkg.dependents.length > 0) {
375
- lines.push(` Blocked: ${pkg.dependents.length} dependent(s)`);
376
- }
377
- }
378
- lines.push('');
379
- }
380
- // Skipped packages with dependency details
381
- if (skipped > 0) {
382
- lines.push('🔒 Blocked Packages (dependency issues):');
383
- for (const pkgName of this.checkpoint.state.skipped){
384
- const deps = this.graph.edges.get(pkgName) || new Set();
385
- const depStatus = Array.from(deps).map((dep)=>{
386
- if (this.checkpoint.state.completed.includes(dep) || this.checkpoint.state.skippedNoChanges.includes(dep)) {
387
- return `${dep} ✓`;
388
- } else if (this.checkpoint.state.failed.some((f)=>f.name === dep)) {
389
- return `${dep} ❌`;
390
- } else if (this.checkpoint.state.running.some((r)=>r.name === dep)) {
391
- return `${dep} ⏳`;
392
- } else if (this.checkpoint.state.skipped.includes(dep)) {
393
- return `${dep} 🔒`;
394
- } else if (this.checkpoint.state.pending.includes(dep) || this.checkpoint.state.ready.includes(dep)) {
395
- return `${dep} ⏳`;
396
- } else {
397
- return `${dep} ❓`;
398
- }
399
- });
400
- lines.push(` • ${pkgName}`);
401
- if (depStatus.length > 0) {
402
- lines.push(` Dependencies: ${depStatus.join(', ')}`);
403
- }
404
- }
405
- lines.push('');
406
- lines.push('Legend: ✓ = complete, ❌ = failed, ⏳ = pending/running, 🔒 = blocked');
407
- lines.push('');
408
- }
409
- // Ready to execute
410
- if (this.checkpoint.state.ready.length > 0) {
411
- lines.push('⏳ Ready to Execute:');
412
- for (const pkgName of this.checkpoint.state.ready){
413
- const deps = this.graph.edges.get(pkgName) || new Set();
414
- if (deps.size === 0) {
415
- lines.push(` • ${pkgName} (no dependencies)`);
416
- } else {
417
- const depList = Array.from(deps).join(', ');
418
- lines.push(` • ${pkgName} (depends on: ${depList})`);
419
- }
420
- }
421
- lines.push('');
422
- }
423
- // Recovery hints
424
- const hints = this.generateRecoveryHints();
425
- if (hints.length > 0) {
426
- lines.push('💡 Recovery Suggestions:');
427
- for (const hint of hints){
428
- const icon = hint.type === 'error' ? '❌' : hint.type === 'warning' ? '⚠️' : 'ℹ️';
429
- lines.push(` ${icon} ${hint.message}`);
430
- if (hint.suggestedCommand) {
431
- lines.push(` ${hint.suggestedCommand}`);
432
- }
433
- }
434
- lines.push('');
435
- }
436
- // State validation
437
- const validation = this.validateState();
438
- if (!validation.valid) {
439
- lines.push('⚠️ State Issues Detected:');
440
- for (const issue of validation.issues){
441
- lines.push(` • ${issue}`);
442
- }
443
- lines.push('');
444
- }
445
- if (validation.warnings.length > 0) {
446
- lines.push('⚠️ Warnings:');
447
- for (const warning of validation.warnings){
448
- lines.push(` • ${warning}`);
449
- }
450
- lines.push('');
451
- }
452
- return lines.join('\n');
453
- }
454
- /**
455
- * Apply multiple recovery options at once
456
- */ async applyRecoveryOptions(options) {
457
- this.logger.info('RECOVERY_OPTIONS_APPLYING: Applying recovery options to checkpoint | Purpose: Modify execution state | Options: Complete, fail, skip, retry, reset');
458
- if (options.markCompleted && options.markCompleted.length > 0) {
459
- await this.markCompleted(options.markCompleted);
460
- }
461
- if (options.markFailed && options.markFailed.length > 0) {
462
- await this.markFailed(options.markFailed);
463
- }
464
- if (options.skipPackages && options.skipPackages.length > 0) {
465
- await this.skipPackages(options.skipPackages);
466
- }
467
- if (options.retryFailed) {
468
- await this.retryFailed({
469
- maxRetries: options.maxRetries
470
- });
471
- }
472
- if (options.skipFailed) {
473
- await this.skipFailed();
474
- }
475
- if (options.resetPackage) {
476
- await this.resetPackage(options.resetPackage);
477
- }
478
- this.logger.info('RECOVERY_OPTIONS_APPLIED: Recovery options applied successfully | Status: Checkpoint updated | Next: Resume execution or exit');
479
- }
480
- /**
481
- * Get checkpoint for external access
482
- */ getCheckpoint() {
483
- return this.checkpoint;
484
- }
485
- // Private helper methods
486
- removeFromAllStates(packageName) {
487
- this.checkpoint.state.pending = this.checkpoint.state.pending.filter((p)=>p !== packageName);
488
- this.checkpoint.state.ready = this.checkpoint.state.ready.filter((p)=>p !== packageName);
489
- this.checkpoint.state.running = this.checkpoint.state.running.filter((r)=>r.name !== packageName);
490
- this.checkpoint.state.completed = this.checkpoint.state.completed.filter((p)=>p !== packageName);
491
- this.checkpoint.state.failed = this.checkpoint.state.failed.filter((f)=>f.name !== packageName);
492
- this.checkpoint.state.skipped = this.checkpoint.state.skipped.filter((p)=>p !== packageName);
493
- this.checkpoint.state.skippedNoChanges = this.checkpoint.state.skippedNoChanges.filter((p)=>p !== packageName);
494
- }
495
- updateReadyState() {
496
- // CRITICAL FIX: First, re-evaluate skipped packages
497
- // Packages that were skipped due to failed dependencies might now be eligible
498
- // to run if those dependencies have been completed (e.g., via --mark-completed)
499
- const unblocked = [];
500
- for (const pkg of this.checkpoint.state.skipped){
501
- const deps = this.graph.edges.get(pkg) || new Set();
502
- const allDepsCompleted = Array.from(deps).every((dep)=>this.checkpoint.state.completed.includes(dep) || this.checkpoint.state.skippedNoChanges.includes(dep));
503
- // Check if any dependencies are still failed
504
- const anyDepsFailed = Array.from(deps).some((dep)=>this.checkpoint.state.failed.some((f)=>f.name === dep));
505
- if (allDepsCompleted && !anyDepsFailed) {
506
- unblocked.push(pkg);
507
- }
508
- }
509
- // Move unblocked packages back to pending
510
- for (const pkg of unblocked){
511
- this.checkpoint.state.skipped = this.checkpoint.state.skipped.filter((p)=>p !== pkg);
512
- this.checkpoint.state.pending.push(pkg);
513
- this.logger.info(`RECOVERY_PACKAGE_UNBLOCKED: Package unblocked due to satisfied dependencies | Package: ${pkg} | Previous Status: skipped | New Status: pending | Reason: Dependencies satisfied`);
514
- }
515
- // Move packages from pending to ready if dependencies met
516
- const nowReady = [];
517
- for (const pkg of this.checkpoint.state.pending){
518
- const deps = this.graph.edges.get(pkg) || new Set();
519
- const allDepsCompleted = Array.from(deps).every((dep)=>this.checkpoint.state.completed.includes(dep) || this.checkpoint.state.skippedNoChanges.includes(dep));
520
- if (allDepsCompleted) {
521
- nowReady.push(pkg);
522
- }
523
- }
524
- for (const pkg of nowReady){
525
- this.checkpoint.state.pending = this.checkpoint.state.pending.filter((p)=>p !== pkg);
526
- this.checkpoint.state.ready.push(pkg);
527
- }
528
- }
529
- findDuplicates(arr) {
530
- const seen = new Set();
531
- const duplicates = new Set();
532
- for (const item of arr){
533
- if (seen.has(item)) {
534
- duplicates.add(item);
535
- }
536
- seen.add(item);
537
- }
538
- return Array.from(duplicates);
539
- }
540
- async saveCheckpoint() {
541
- this.checkpoint.lastUpdated = new Date().toISOString();
542
- await this.checkpointManager.save(this.checkpoint);
543
- }
544
- formatDuration(ms) {
545
- const seconds = Math.floor(ms / 1000);
546
- const minutes = Math.floor(seconds / 60);
547
- const hours = Math.floor(minutes / 60);
548
- if (hours > 0) {
549
- return `${hours}h ${minutes % 60}m`;
550
- }
551
- if (minutes > 0) {
552
- return `${minutes}m ${seconds % 60}s`;
553
- }
554
- return `${seconds}s`;
555
- }
556
- createProgressBar(current, total, width = 30) {
557
- const percent = current / total;
558
- const filled = Math.round(width * percent);
559
- const empty = width - filled;
560
- return '█'.repeat(filled) + '░'.repeat(empty);
561
- }
562
- constructor(checkpoint, graph, checkpointManager){
563
- _define_property(this, "checkpoint", void 0);
564
- _define_property(this, "graph", void 0);
565
- _define_property(this, "checkpointManager", void 0);
566
- _define_property(this, "logger", getLogger());
567
- this.checkpoint = checkpoint;
568
- this.graph = graph;
569
- this.checkpointManager = checkpointManager;
570
- }
571
- }
572
- /**
573
- * Load checkpoint and create recovery manager
574
- */ async function loadRecoveryManager(graph, outputDirectory) {
575
- const checkpointManager = new CheckpointManager(outputDirectory);
576
- const checkpoint = await checkpointManager.load();
577
- if (!checkpoint) {
578
- return null;
579
- }
580
- return new RecoveryManager(checkpoint, graph, checkpointManager);
581
- }
582
-
583
- export { RecoveryManager, loadRecoveryManager };
584
- //# sourceMappingURL=RecoveryManager.js.map