@grunnverk/tree-execution 1.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 (80) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +1576 -0
  3. package/dist/TreeExecutor.d.ts +113 -0
  4. package/dist/TreeExecutor.d.ts.map +1 -0
  5. package/dist/TreeExecutor.js +113 -0
  6. package/dist/TreeExecutor.js.map +1 -0
  7. package/dist/checkpoint/CheckpointManager.d.ts +18 -0
  8. package/dist/checkpoint/CheckpointManager.d.ts.map +1 -0
  9. package/dist/checkpoint/CheckpointManager.js +156 -0
  10. package/dist/checkpoint/CheckpointManager.js.map +1 -0
  11. package/dist/checkpoint/index.d.ts +5 -0
  12. package/dist/checkpoint/index.d.ts.map +1 -0
  13. package/dist/checkpoint/index.js +5 -0
  14. package/dist/checkpoint/index.js.map +1 -0
  15. package/dist/execution/CommandValidator.d.ts +25 -0
  16. package/dist/execution/CommandValidator.d.ts.map +1 -0
  17. package/dist/execution/CommandValidator.js +129 -0
  18. package/dist/execution/CommandValidator.js.map +1 -0
  19. package/dist/execution/DependencyChecker.d.ts +47 -0
  20. package/dist/execution/DependencyChecker.d.ts.map +1 -0
  21. package/dist/execution/DependencyChecker.js +95 -0
  22. package/dist/execution/DependencyChecker.js.map +1 -0
  23. package/dist/execution/DynamicTaskPool.d.ts +118 -0
  24. package/dist/execution/DynamicTaskPool.d.ts.map +1 -0
  25. package/dist/execution/DynamicTaskPool.js +658 -0
  26. package/dist/execution/DynamicTaskPool.js.map +1 -0
  27. package/dist/execution/RecoveryManager.d.ts +89 -0
  28. package/dist/execution/RecoveryManager.d.ts.map +1 -0
  29. package/dist/execution/RecoveryManager.js +592 -0
  30. package/dist/execution/RecoveryManager.js.map +1 -0
  31. package/dist/execution/ResourceMonitor.d.ts +73 -0
  32. package/dist/execution/ResourceMonitor.d.ts.map +1 -0
  33. package/dist/execution/ResourceMonitor.js +148 -0
  34. package/dist/execution/ResourceMonitor.js.map +1 -0
  35. package/dist/execution/Scheduler.d.ts +36 -0
  36. package/dist/execution/Scheduler.d.ts.map +1 -0
  37. package/dist/execution/Scheduler.js +83 -0
  38. package/dist/execution/Scheduler.js.map +1 -0
  39. package/dist/execution/TreeExecutionAdapter.d.ts +45 -0
  40. package/dist/execution/TreeExecutionAdapter.d.ts.map +1 -0
  41. package/dist/execution/TreeExecutionAdapter.js +260 -0
  42. package/dist/execution/TreeExecutionAdapter.js.map +1 -0
  43. package/dist/index.d.ts +29 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +25 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/tree.d.ts +13 -0
  48. package/dist/tree.d.ts.map +1 -0
  49. package/dist/tree.js +2510 -0
  50. package/dist/tree.js.map +1 -0
  51. package/dist/types/config.d.ts +174 -0
  52. package/dist/types/config.d.ts.map +1 -0
  53. package/dist/types/config.js +2 -0
  54. package/dist/types/config.js.map +1 -0
  55. package/dist/types/index.d.ts +6 -0
  56. package/dist/types/index.d.ts.map +1 -0
  57. package/dist/types/index.js +6 -0
  58. package/dist/types/index.js.map +1 -0
  59. package/dist/types/parallelExecution.d.ts +108 -0
  60. package/dist/types/parallelExecution.d.ts.map +1 -0
  61. package/dist/types/parallelExecution.js +2 -0
  62. package/dist/types/parallelExecution.js.map +1 -0
  63. package/dist/util/commandStubs.d.ts +22 -0
  64. package/dist/util/commandStubs.d.ts.map +1 -0
  65. package/dist/util/commandStubs.js +49 -0
  66. package/dist/util/commandStubs.js.map +1 -0
  67. package/dist/util/logger.d.ts +14 -0
  68. package/dist/util/logger.d.ts.map +1 -0
  69. package/dist/util/logger.js +30 -0
  70. package/dist/util/logger.js.map +1 -0
  71. package/dist/util/mutex.d.ts +38 -0
  72. package/dist/util/mutex.d.ts.map +1 -0
  73. package/dist/util/mutex.js +101 -0
  74. package/dist/util/mutex.js.map +1 -0
  75. package/dist/util/treeUtils.d.ts +46 -0
  76. package/dist/util/treeUtils.d.ts.map +1 -0
  77. package/dist/util/treeUtils.js +74 -0
  78. package/dist/util/treeUtils.js.map +1 -0
  79. package/guide/index.md +84 -0
  80. package/package.json +64 -0
@@ -0,0 +1,113 @@
1
+ /**
2
+ * TreeExecutor - Class-based tree command orchestration
3
+ *
4
+ * Refactored from tree.ts to use instance state instead of global state
5
+ * and dependency injection for commands.
6
+ */
7
+ import type { TreeExecutionConfig } from './types/config.js';
8
+ /**
9
+ * Published version tracking
10
+ */
11
+ export interface PublishedVersion {
12
+ packageName: string;
13
+ version: string;
14
+ publishTime: Date;
15
+ }
16
+ /**
17
+ * Tree execution context for persistence
18
+ */
19
+ export interface TreeExecutionContext {
20
+ command: string;
21
+ originalConfig: TreeExecutionConfig;
22
+ publishedVersions: PublishedVersion[];
23
+ completedPackages: string[];
24
+ buildOrder: string[];
25
+ startTime: Date;
26
+ lastUpdateTime: Date;
27
+ }
28
+ /**
29
+ * Command executor interface for dependency injection
30
+ */
31
+ export interface CommandExecutor {
32
+ execute(config: TreeExecutionConfig, mode?: string): Promise<any>;
33
+ }
34
+ /**
35
+ * Command registry for built-in commands
36
+ */
37
+ export interface CommandRegistry {
38
+ updates?: CommandExecutor;
39
+ commit?: CommandExecutor;
40
+ link?: CommandExecutor;
41
+ unlink?: CommandExecutor;
42
+ }
43
+ /**
44
+ * TreeExecutor options
45
+ */
46
+ export interface TreeExecutorOptions {
47
+ /**
48
+ * Command registry for dependency injection
49
+ */
50
+ commands?: CommandRegistry;
51
+ /**
52
+ * Custom logger (optional)
53
+ */
54
+ logger?: any;
55
+ }
56
+ /**
57
+ * TreeExecutor - Orchestrates tree command execution
58
+ *
59
+ * This class encapsulates all state that was previously global,
60
+ * making it testable and allowing multiple concurrent executions.
61
+ */
62
+ export declare class TreeExecutor {
63
+ private publishedVersions;
64
+ private executionContext;
65
+ private stateMutex;
66
+ private commands;
67
+ private logger;
68
+ constructor(options?: TreeExecutorOptions);
69
+ /**
70
+ * Get published versions (thread-safe)
71
+ */
72
+ getPublishedVersions(): Promise<PublishedVersion[]>;
73
+ /**
74
+ * Add published version (thread-safe)
75
+ */
76
+ addPublishedVersion(version: PublishedVersion): Promise<void>;
77
+ /**
78
+ * Get execution context (thread-safe)
79
+ * Returns a deep copy to prevent external modifications
80
+ */
81
+ getExecutionContext(): Promise<TreeExecutionContext | null>;
82
+ /**
83
+ * Set execution context (thread-safe)
84
+ */
85
+ setExecutionContext(context: TreeExecutionContext | null): Promise<void>;
86
+ /**
87
+ * Reset state (for testing)
88
+ */
89
+ reset(): Promise<void>;
90
+ /**
91
+ * Execute tree command
92
+ *
93
+ * This will be the main entry point, delegating to the execute function
94
+ * from tree.ts but with instance state instead of global state.
95
+ *
96
+ * @param config - Tree execution configuration
97
+ * @returns Result message
98
+ */
99
+ execute(config: TreeExecutionConfig): Promise<string>;
100
+ /**
101
+ * Get command executor
102
+ */
103
+ getCommand(name: keyof CommandRegistry): CommandExecutor | undefined;
104
+ /**
105
+ * Set command executor (for testing/injection)
106
+ */
107
+ setCommand(name: keyof CommandRegistry, executor: CommandExecutor): void;
108
+ }
109
+ /**
110
+ * Create a default TreeExecutor instance
111
+ */
112
+ export declare function createTreeExecutor(options?: TreeExecutorOptions): TreeExecutor;
113
+ //# sourceMappingURL=TreeExecutor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeExecutor.d.ts","sourceRoot":"","sources":["../src/TreeExecutor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAG7D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,mBAAmB,CAAC;IACpC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;IAChB,cAAc,EAAE,IAAI,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,OAAO,CAAC,MAAM,EAAE,mBAAmB,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CACrE;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,MAAM,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC;;OAEG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;IAE3B;;OAEG;IACH,MAAM,CAAC,EAAE,GAAG,CAAC;CAChB;AAED;;;;;GAKG;AACH,qBAAa,YAAY;IAErB,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,gBAAgB,CAAqC;IAC7D,OAAO,CAAC,UAAU,CAAc;IAGhC,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,MAAM,CAAM;gBAER,OAAO,GAAE,mBAAwB;IAM7C;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAMzD;;OAEG;IACG,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnE;;;OAGG;IACG,mBAAmB,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAcjE;;OAEG;IACG,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9E;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;;;;;;;OAQG;IACG,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;IAU3D;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,eAAe,GAAG,eAAe,GAAG,SAAS;IAIpE;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,eAAe,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI;CAG3E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY,CAE9E"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * TreeExecutor - Class-based tree command orchestration
3
+ *
4
+ * Refactored from tree.ts to use instance state instead of global state
5
+ * and dependency injection for commands.
6
+ */
7
+ import { SimpleMutex } from './util/mutex.js';
8
+ /**
9
+ * TreeExecutor - Orchestrates tree command execution
10
+ *
11
+ * This class encapsulates all state that was previously global,
12
+ * making it testable and allowing multiple concurrent executions.
13
+ */
14
+ export class TreeExecutor {
15
+ // Instance state (previously global)
16
+ publishedVersions = [];
17
+ executionContext = null;
18
+ stateMutex;
19
+ // Dependency injection
20
+ commands;
21
+ logger;
22
+ constructor(options = {}) {
23
+ this.commands = options.commands || {};
24
+ this.logger = options.logger;
25
+ this.stateMutex = new SimpleMutex();
26
+ }
27
+ /**
28
+ * Get published versions (thread-safe)
29
+ */
30
+ async getPublishedVersions() {
31
+ return await this.stateMutex.runExclusive(async () => {
32
+ return [...this.publishedVersions];
33
+ });
34
+ }
35
+ /**
36
+ * Add published version (thread-safe)
37
+ */
38
+ async addPublishedVersion(version) {
39
+ await this.stateMutex.runExclusive(async () => {
40
+ this.publishedVersions.push(version);
41
+ });
42
+ }
43
+ /**
44
+ * Get execution context (thread-safe)
45
+ * Returns a deep copy to prevent external modifications
46
+ */
47
+ async getExecutionContext() {
48
+ return await this.stateMutex.runExclusive(async () => {
49
+ if (!this.executionContext)
50
+ return null;
51
+ // Return deep copy to prevent external modification
52
+ return {
53
+ ...this.executionContext,
54
+ publishedVersions: [...this.executionContext.publishedVersions],
55
+ completedPackages: [...this.executionContext.completedPackages],
56
+ buildOrder: [...this.executionContext.buildOrder]
57
+ };
58
+ });
59
+ }
60
+ /**
61
+ * Set execution context (thread-safe)
62
+ */
63
+ async setExecutionContext(context) {
64
+ await this.stateMutex.runExclusive(async () => {
65
+ this.executionContext = context;
66
+ });
67
+ }
68
+ /**
69
+ * Reset state (for testing)
70
+ */
71
+ async reset() {
72
+ await this.stateMutex.runExclusive(async () => {
73
+ this.publishedVersions = [];
74
+ this.executionContext = null;
75
+ });
76
+ }
77
+ /**
78
+ * Execute tree command
79
+ *
80
+ * This will be the main entry point, delegating to the execute function
81
+ * from tree.ts but with instance state instead of global state.
82
+ *
83
+ * @param config - Tree execution configuration
84
+ * @returns Result message
85
+ */
86
+ async execute(config) {
87
+ // Import the execute function from tree.ts
88
+ // We'll need to refactor tree.ts to accept TreeExecutor instance
89
+ const { execute } = await import('./tree.js');
90
+ // For now, this is a placeholder
91
+ // We'll refactor tree.ts to accept TreeExecutor in the next step
92
+ return await execute(config);
93
+ }
94
+ /**
95
+ * Get command executor
96
+ */
97
+ getCommand(name) {
98
+ return this.commands[name];
99
+ }
100
+ /**
101
+ * Set command executor (for testing/injection)
102
+ */
103
+ setCommand(name, executor) {
104
+ this.commands[name] = executor;
105
+ }
106
+ }
107
+ /**
108
+ * Create a default TreeExecutor instance
109
+ */
110
+ export function createTreeExecutor(options) {
111
+ return new TreeExecutor(options);
112
+ }
113
+ //# sourceMappingURL=TreeExecutor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeExecutor.js","sourceRoot":"","sources":["../src/TreeExecutor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { ParallelExecutionCheckpoint } from '../types/index.js';
2
+ export declare class CheckpointManager {
3
+ private checkpointPath;
4
+ private lockPath;
5
+ private tempPath;
6
+ private logger;
7
+ private storage;
8
+ constructor(outputDirectory?: string);
9
+ save(checkpoint: ParallelExecutionCheckpoint): Promise<void>;
10
+ load(): Promise<ParallelExecutionCheckpoint | null>;
11
+ backup(): Promise<void>;
12
+ cleanup(): Promise<void>;
13
+ private acquireLock;
14
+ private validateCheckpoint;
15
+ private isCompatibleVersion;
16
+ private loadBackup;
17
+ }
18
+ //# sourceMappingURL=CheckpointManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CheckpointManager.d.ts","sourceRoot":"","sources":["../../src/checkpoint/CheckpointManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AASrE,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,OAAO,CAAmB;gBAEtB,eAAe,GAAE,MAAsB;IAM7C,IAAI,CAAC,UAAU,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB5D,IAAI,IAAI,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC;IAoCnD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IASvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAahB,WAAW;IAqCzB,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,mBAAmB;YAOb,UAAU;CAa3B"}
@@ -0,0 +1,156 @@
1
+ import path from 'path';
2
+ import fs from 'fs/promises';
3
+ import { getLogger } from '../util/logger.js';
4
+ import { createStorage } from '@grunnverk/shared';
5
+ const CHECKPOINT_VERSION = '1.0.0';
6
+ export class CheckpointManager {
7
+ checkpointPath;
8
+ lockPath;
9
+ tempPath;
10
+ logger = getLogger();
11
+ storage = createStorage();
12
+ constructor(outputDirectory = process.cwd()) {
13
+ this.checkpointPath = path.join(outputDirectory, '.kodrdriv-parallel-context.json');
14
+ this.lockPath = `${this.checkpointPath}.lock`;
15
+ this.tempPath = `${this.checkpointPath}.tmp`;
16
+ }
17
+ async save(checkpoint) {
18
+ const lock = await this.acquireLock();
19
+ try {
20
+ // Set version and timestamp
21
+ checkpoint.version = CHECKPOINT_VERSION;
22
+ checkpoint.lastUpdated = new Date().toISOString();
23
+ // Validate before saving
24
+ this.validateCheckpoint(checkpoint);
25
+ // Write to temp file
26
+ const serialized = JSON.stringify(checkpoint, null, 2);
27
+ await fs.writeFile(this.tempPath, serialized, 'utf-8');
28
+ // Atomic rename
29
+ await fs.rename(this.tempPath, this.checkpointPath);
30
+ this.logger.debug(`Checkpoint saved: ${this.checkpointPath}`);
31
+ }
32
+ finally {
33
+ await lock.release();
34
+ }
35
+ }
36
+ async load() {
37
+ if (!await this.storage.exists(this.checkpointPath)) {
38
+ return null;
39
+ }
40
+ const lock = await this.acquireLock();
41
+ try {
42
+ const content = await fs.readFile(this.checkpointPath, 'utf-8');
43
+ const checkpoint = JSON.parse(content);
44
+ // Validate
45
+ this.validateCheckpoint(checkpoint);
46
+ // Check version
47
+ if (!this.isCompatibleVersion(checkpoint.version)) {
48
+ throw new Error(`Incompatible checkpoint version: ${checkpoint.version}`);
49
+ }
50
+ return checkpoint;
51
+ }
52
+ catch (error) {
53
+ this.logger.error(`CHECKPOINT_LOAD_FAILED: Failed to load checkpoint file | Error: ${error.message} | Impact: Cannot resume execution`);
54
+ // Try backup
55
+ const backup = await this.loadBackup();
56
+ if (backup) {
57
+ this.logger.info('CHECKPOINT_RECOVERED_BACKUP: Recovered from backup checkpoint | Source: backup | Status: loaded');
58
+ return backup;
59
+ }
60
+ return null;
61
+ }
62
+ finally {
63
+ await lock.release();
64
+ }
65
+ }
66
+ async backup() {
67
+ if (!await this.storage.exists(this.checkpointPath)) {
68
+ return;
69
+ }
70
+ const backupPath = `${this.checkpointPath}.backup`;
71
+ await fs.copyFile(this.checkpointPath, backupPath);
72
+ }
73
+ async cleanup() {
74
+ const files = [
75
+ this.checkpointPath,
76
+ this.lockPath,
77
+ this.tempPath,
78
+ `${this.checkpointPath}.backup`
79
+ ];
80
+ await Promise.all(files.map(file => fs.unlink(file).catch(() => { })));
81
+ }
82
+ async acquireLock() {
83
+ const maxWaitMs = 30000;
84
+ const startTime = Date.now();
85
+ while (true) {
86
+ try {
87
+ const fileHandle = await fs.open(this.lockPath, 'wx');
88
+ try {
89
+ const pid = process.pid;
90
+ const timestamp = new Date().toISOString();
91
+ await fileHandle.writeFile(`${pid}\n${timestamp}`);
92
+ }
93
+ finally {
94
+ await fileHandle.close();
95
+ }
96
+ return {
97
+ release: async () => {
98
+ await fs.unlink(this.lockPath).catch(() => { });
99
+ }
100
+ };
101
+ }
102
+ catch (error) {
103
+ if (error.code !== 'EEXIST') {
104
+ throw error;
105
+ }
106
+ const elapsed = Date.now() - startTime;
107
+ if (elapsed > maxWaitMs) {
108
+ this.logger.warn('CHECKPOINT_LOCK_STALE: Breaking stale checkpoint lock | Reason: Lock expired | Action: Force break lock');
109
+ await fs.unlink(this.lockPath).catch(() => { });
110
+ continue;
111
+ }
112
+ await new Promise(resolve => setTimeout(resolve, 100));
113
+ }
114
+ }
115
+ }
116
+ validateCheckpoint(checkpoint) {
117
+ if (!checkpoint.executionId) {
118
+ throw new Error('Invalid checkpoint: missing executionId');
119
+ }
120
+ if (!checkpoint.state) {
121
+ throw new Error('Invalid checkpoint: missing state');
122
+ }
123
+ // Validate state consistency
124
+ const allPackages = new Set([
125
+ ...checkpoint.state.pending,
126
+ ...checkpoint.state.ready,
127
+ ...checkpoint.state.running.map(r => r.name),
128
+ ...checkpoint.state.completed,
129
+ ...checkpoint.state.failed.map(f => f.name),
130
+ ...checkpoint.state.skipped
131
+ ]);
132
+ if (allPackages.size !== checkpoint.buildOrder.length) {
133
+ this.logger.warn('CHECKPOINT_INCONSISTENCY: Checkpoint state inconsistency detected | Issue: State validation failed | Impact: May need manual recovery');
134
+ }
135
+ }
136
+ isCompatibleVersion(version) {
137
+ // Simple major version check
138
+ const [major] = version.split('.');
139
+ const [expectedMajor] = CHECKPOINT_VERSION.split('.');
140
+ return major === expectedMajor;
141
+ }
142
+ async loadBackup() {
143
+ const backupPath = `${this.checkpointPath}.backup`;
144
+ if (!await this.storage.exists(backupPath)) {
145
+ return null;
146
+ }
147
+ try {
148
+ const content = await fs.readFile(backupPath, 'utf-8');
149
+ return JSON.parse(content);
150
+ }
151
+ catch {
152
+ return null;
153
+ }
154
+ }
155
+ }
156
+ //# sourceMappingURL=CheckpointManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CheckpointManager.js","sourceRoot":"","sources":["../../src/checkpoint/CheckpointManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Checkpoint management for parallel execution
3
+ */
4
+ export { CheckpointManager } from './CheckpointManager.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/checkpoint/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Checkpoint management for parallel execution
3
+ */
4
+ export { CheckpointManager } from './CheckpointManager.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/checkpoint/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,25 @@
1
+ export interface ValidationResult {
2
+ valid: boolean;
3
+ issues: string[];
4
+ warnings: string[];
5
+ recommendations: string[];
6
+ }
7
+ /**
8
+ * CommandValidator checks if commands are safe for parallel execution
9
+ */
10
+ export declare class CommandValidator {
11
+ private static logger;
12
+ /**
13
+ * Validate a command for parallel execution
14
+ */
15
+ static validateForParallel(command: string, builtInCommand?: string): ValidationResult;
16
+ /**
17
+ * Log validation results
18
+ */
19
+ static logValidation(result: ValidationResult): void;
20
+ /**
21
+ * Get recommended concurrency for a command type
22
+ */
23
+ static getRecommendedConcurrency(builtInCommand?: string, cpuCount?: number, command?: string): number;
24
+ }
25
+ //# sourceMappingURL=CommandValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandValidator.d.ts","sourceRoot":"","sources":["../../src/execution/CommandValidator.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,qBAAa,gBAAgB;IACzB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAe;IAEpC;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,gBAAgB;IAoEtF;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAuBpD;;OAEG;IACH,MAAM,CAAC,yBAAyB,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM;CAuC5G"}
@@ -0,0 +1,129 @@
1
+ import { getLogger } from '../util/logger.js';
2
+ /**
3
+ * CommandValidator checks if commands are safe for parallel execution
4
+ */
5
+ export class CommandValidator {
6
+ static logger = getLogger();
7
+ /**
8
+ * Validate a command for parallel execution
9
+ */
10
+ static validateForParallel(command, builtInCommand) {
11
+ const issues = [];
12
+ const warnings = [];
13
+ const recommendations = [];
14
+ // Check for inherently unsafe operations
15
+ const unsafePatterns = [
16
+ { pattern: /git\s+checkout/, message: 'Branch switching is not safe for parallel execution' },
17
+ { pattern: /git\s+switch/, message: 'Branch switching is not safe for parallel execution' },
18
+ { pattern: /git\s+rebase/, message: 'Rebase operations should not run in parallel' },
19
+ { pattern: /git\s+merge/, message: 'Merge operations should not run in parallel' },
20
+ { pattern: /rm\s+-rf\s+\//, message: 'Dangerous deletion commands detected' },
21
+ { pattern: /sudo/, message: 'Sudo commands should not run in parallel' },
22
+ { pattern: /format/, message: 'Format commands may be destructive' }
23
+ ];
24
+ for (const { pattern, message } of unsafePatterns) {
25
+ if (pattern.test(command)) {
26
+ issues.push(message);
27
+ }
28
+ }
29
+ // Check for potentially problematic operations
30
+ const warningPatterns = [
31
+ { pattern: /npm\s+(link|unlink)/, message: 'npm link/unlink may conflict in parallel execution' },
32
+ { pattern: /npm\s+install/, message: 'npm install in parallel may cause lock file conflicts' },
33
+ { pattern: /npm\s+ci/, message: 'npm ci in parallel may cause lock file conflicts' },
34
+ { pattern: /package-lock\.json/, message: 'Operations modifying package-lock.json may conflict' },
35
+ { pattern: /node_modules/, message: 'Operations in node_modules may conflict' }
36
+ ];
37
+ for (const { pattern, message } of warningPatterns) {
38
+ if (pattern.test(command)) {
39
+ warnings.push(message);
40
+ }
41
+ }
42
+ // Built-in command specific checks
43
+ if (builtInCommand === 'commit') {
44
+ warnings.push('Parallel commits: Recommend max concurrency of 2 to avoid conflicts');
45
+ recommendations.push('Use: --max-concurrency 2');
46
+ }
47
+ if (builtInCommand === 'publish') {
48
+ warnings.push('Parallel publish: PR checks may take significant time');
49
+ warnings.push('Version propagation happens automatically between dependency levels');
50
+ recommendations.push('Use: --max-concurrency 2-3 for publish operations');
51
+ recommendations.push('Monitor with: kodrdriv tree --status-parallel');
52
+ }
53
+ if (builtInCommand === 'link' || builtInCommand === 'unlink') {
54
+ warnings.push('Link operations may have filesystem race conditions');
55
+ recommendations.push('Consider sequential execution for link/unlink');
56
+ }
57
+ // Check for output redirection
58
+ if (command.includes('>') || command.includes('>>')) {
59
+ warnings.push('Output redirection in parallel may interleave output');
60
+ }
61
+ return {
62
+ valid: issues.length === 0,
63
+ issues,
64
+ warnings,
65
+ recommendations
66
+ };
67
+ }
68
+ /**
69
+ * Log validation results
70
+ */
71
+ static logValidation(result) {
72
+ if (!result.valid) {
73
+ this.logger.error('VALIDATOR_FAILED: Command validation failed for parallel execution | Error Count: ' + result.issues.length + ' | Impact: Cannot proceed safely');
74
+ for (const issue of result.issues) {
75
+ this.logger.error(`VALIDATOR_ERROR_DETAIL: Validation issue | Issue: ${issue}`);
76
+ }
77
+ }
78
+ if (result.warnings.length > 0) {
79
+ this.logger.warn('VALIDATOR_WARNINGS: Command validation warnings for parallel execution | Warning Count: ' + result.warnings.length + ' | Impact: May cause issues');
80
+ for (const warning of result.warnings) {
81
+ this.logger.warn(`VALIDATOR_WARNING_DETAIL: Validation warning | Warning: ${warning}`);
82
+ }
83
+ }
84
+ if (result.recommendations.length > 0 && this.logger.verbose) {
85
+ this.logger.info('VALIDATOR_RECOMMENDATIONS: Command validation recommendations | Count: ' + result.recommendations.length + ' | Purpose: Improve parallel execution');
86
+ for (const rec of result.recommendations) {
87
+ this.logger.info(`VALIDATOR_RECOMMENDATION_DETAIL: ${rec}`);
88
+ }
89
+ }
90
+ }
91
+ /**
92
+ * Get recommended concurrency for a command type
93
+ */
94
+ static getRecommendedConcurrency(builtInCommand, cpuCount = 4, command) {
95
+ // If command is provided, check for memory-intensive patterns
96
+ if (command) {
97
+ const memoryIntensivePatterns = [
98
+ { pattern: /npm\s+test/, message: 'Test execution is memory intensive' },
99
+ { pattern: /npm\s+run\s+test/, message: 'Test execution is memory intensive' },
100
+ { pattern: /vitest/, message: 'Vitest execution is memory intensive' },
101
+ { pattern: /coverage/, message: 'Coverage generation is memory intensive' },
102
+ { pattern: /npm\s+run\s+precommit/, message: 'Precommit tasks (build+lint+test) are resource intensive' }
103
+ ];
104
+ for (const { pattern } of memoryIntensivePatterns) {
105
+ if (pattern.test(command)) {
106
+ // Return lower concurrency for memory intensive tasks: 25% of CPUs, min 2, max 4
107
+ const recommended = Math.max(2, Math.min(4, Math.floor(cpuCount * 0.25)));
108
+ return Math.min(recommended, cpuCount);
109
+ }
110
+ }
111
+ }
112
+ switch (builtInCommand) {
113
+ case 'commit':
114
+ // Lower concurrency for commit to reduce conflicts
115
+ return Math.min(2, cpuCount);
116
+ case 'publish':
117
+ // Moderate concurrency for publish (long-running)
118
+ return Math.max(2, Math.floor(cpuCount / 2));
119
+ case 'link':
120
+ case 'unlink':
121
+ // Very conservative for link operations
122
+ return 1; // Sequential recommended
123
+ default:
124
+ // Full concurrency for general commands
125
+ return cpuCount;
126
+ }
127
+ }
128
+ }
129
+ //# sourceMappingURL=CommandValidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandValidator.js","sourceRoot":"","sources":["../../src/execution/CommandValidator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { DependencyGraph } from '@grunnverk/tree-core';
2
+ import type { ExecutionState } from '../types/index.js';
3
+ /**
4
+ * DependencyChecker validates package readiness and provides dependency information
5
+ * for the task pool scheduler.
6
+ */
7
+ export declare class DependencyChecker {
8
+ private graph;
9
+ constructor(graph: DependencyGraph);
10
+ /**
11
+ * Check if a package is ready to execute
12
+ * A package is ready when all its dependencies are completed and none have failed
13
+ */
14
+ isReady(packageName: string, state: ExecutionState): boolean;
15
+ /**
16
+ * Get count of packages that depend on this one
17
+ * Higher count = higher priority (unlocks more packages)
18
+ */
19
+ getDependentCount(packageName: string): number;
20
+ /**
21
+ * Get depth of package in dependency tree
22
+ * Depth = longest path from a root package (package with no dependencies)
23
+ * Lower depth = higher priority (can unlock dependent packages sooner)
24
+ */
25
+ getDepth(packageName: string): number;
26
+ /**
27
+ * Get all dependencies for a package
28
+ */
29
+ getDependencies(packageName: string): Set<string>;
30
+ /**
31
+ * Get all dependents (packages that depend on this one)
32
+ */
33
+ getDependents(packageName: string): Set<string>;
34
+ /**
35
+ * Check if package has any dependencies
36
+ */
37
+ hasDependencies(packageName: string): boolean;
38
+ /**
39
+ * Check if package has any dependents
40
+ */
41
+ hasDependents(packageName: string): boolean;
42
+ /**
43
+ * Get packages that are blocked by a failed package
44
+ */
45
+ getBlockedPackages(failedPackage: string, state: ExecutionState): Set<string>;
46
+ }
47
+ //# sourceMappingURL=DependencyChecker.d.ts.map