@vibe-validate/core 0.9.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 +46 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +104 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/process-utils.d.ts +29 -0
- package/dist/process-utils.d.ts.map +1 -0
- package/dist/process-utils.js +62 -0
- package/dist/process-utils.js.map +1 -0
- package/dist/runner.d.ts +66 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +276 -0
- package/dist/runner.js.map +1 -0
- package/dist/types.d.ts +126 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @vibe-validate/core
|
|
2
|
+
|
|
3
|
+
Core validation orchestration engine for vibe-validate.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Parallel Execution**: Run multiple validation steps simultaneously
|
|
8
|
+
- **Phase-Based Orchestration**: Define validation phases with dependencies
|
|
9
|
+
- **Git Tree Hash Caching**: Skip validation when code unchanged
|
|
10
|
+
- **Process Management**: Clean up child processes on interruption
|
|
11
|
+
- **LLM-Optimized Output**: Format errors for AI consumption
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @vibe-validate/core
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { ValidationRunner } from '@vibe-validate/core';
|
|
23
|
+
|
|
24
|
+
const runner = new ValidationRunner({
|
|
25
|
+
phases: [
|
|
26
|
+
{
|
|
27
|
+
name: 'Pre-Qualification',
|
|
28
|
+
parallel: true,
|
|
29
|
+
steps: [
|
|
30
|
+
{ name: 'TypeCheck', command: 'tsc --noEmit' },
|
|
31
|
+
{ name: 'Lint', command: 'eslint src/' },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const result = await runner.run();
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## API
|
|
41
|
+
|
|
42
|
+
See [TypeScript types](./src/index.ts) for complete API documentation.
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
MIT © Jeff Dutton
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;GAIG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Vibe-Validate CLI Entry Point
|
|
4
|
+
*
|
|
5
|
+
* This script loads the configuration and runs the validation runner.
|
|
6
|
+
*/
|
|
7
|
+
import { join, resolve } from 'path';
|
|
8
|
+
import { existsSync } from 'fs';
|
|
9
|
+
import { runValidation } from './runner.js';
|
|
10
|
+
/**
|
|
11
|
+
* Find and load vibe-validate.config.ts
|
|
12
|
+
*
|
|
13
|
+
* @returns A config object with validation, git, and output settings
|
|
14
|
+
*/
|
|
15
|
+
async function loadConfig() {
|
|
16
|
+
const cwd = process.cwd();
|
|
17
|
+
const configPaths = [
|
|
18
|
+
'vibe-validate.config.ts',
|
|
19
|
+
'vibe-validate.config.js',
|
|
20
|
+
'vibe-validate.config.mjs',
|
|
21
|
+
'.vibe-validate.ts',
|
|
22
|
+
'.vibe-validate.js',
|
|
23
|
+
'.vibe-validate.mjs',
|
|
24
|
+
];
|
|
25
|
+
for (const configPath of configPaths) {
|
|
26
|
+
const fullPath = join(cwd, configPath);
|
|
27
|
+
if (existsSync(fullPath)) {
|
|
28
|
+
console.log(`📋 Loading config from ${configPath}`);
|
|
29
|
+
try {
|
|
30
|
+
// Use dynamic import to support both .ts and .js configs
|
|
31
|
+
const configModule = await import(`file://${resolve(fullPath)}`);
|
|
32
|
+
const config = configModule.default || configModule;
|
|
33
|
+
return config;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.error(`❌ Failed to load config from ${configPath}:`, error);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
console.error('❌ No vibe-validate.config.ts found in current directory');
|
|
42
|
+
console.error(' Searched for:');
|
|
43
|
+
configPaths.forEach((path) => console.error(` - ${path}`));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Main CLI entry point
|
|
48
|
+
*/
|
|
49
|
+
async function main() {
|
|
50
|
+
try {
|
|
51
|
+
// Load configuration
|
|
52
|
+
const rawConfig = await loadConfig();
|
|
53
|
+
// Adapt config structure for runner
|
|
54
|
+
// The config loader returns a structured config with {validation, git, output}
|
|
55
|
+
// The runner expects a flat config with {phases, ...}
|
|
56
|
+
// Convert process.env to Record<string, string> by filtering out undefined values
|
|
57
|
+
const envVars = {};
|
|
58
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
59
|
+
if (value !== undefined) {
|
|
60
|
+
envVars[key] = value;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const runnerConfig = {
|
|
64
|
+
phases: rawConfig.validation?.phases || [],
|
|
65
|
+
enableFailFast: rawConfig.validation?.failFast ?? true,
|
|
66
|
+
env: envVars,
|
|
67
|
+
stateFilePath: '.vibe-validate-state.yaml',
|
|
68
|
+
onPhaseStart: (phase) => console.log(`\n🔄 Running phase: ${phase.name}`),
|
|
69
|
+
onPhaseComplete: (phase, result) => {
|
|
70
|
+
if (result.passed) {
|
|
71
|
+
console.log(`✅ Phase ${phase.name} completed successfully`);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
console.log(`❌ Phase ${phase.name} failed`);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
onStepStart: (step) => console.log(` ⏳ ${step.name}...`),
|
|
78
|
+
onStepComplete: (step, result) => {
|
|
79
|
+
if (result.passed) {
|
|
80
|
+
console.log(` ✅ ${step.name} (${result.duration}ms)`);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.log(` ❌ ${step.name} failed (${result.duration}ms)`);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
// Run validation
|
|
88
|
+
const result = await runValidation(runnerConfig);
|
|
89
|
+
// Exit with appropriate code
|
|
90
|
+
process.exit(result.passed ? 0 : 1);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error('❌ Validation failed with error:', error);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Run if executed directly
|
|
98
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
99
|
+
main().catch((error) => {
|
|
100
|
+
console.error('Fatal error:', error);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vibe-validate/core
|
|
3
|
+
*
|
|
4
|
+
* Core validation engine with git tree hash caching, parallel execution, and fail-fast support.
|
|
5
|
+
*
|
|
6
|
+
* ## Features
|
|
7
|
+
*
|
|
8
|
+
* - **Git Tree Hash Caching**: Skip validation if code unchanged
|
|
9
|
+
* - **Parallel Execution**: Run validation steps concurrently for speed
|
|
10
|
+
* - **Fail-Fast**: Stop on first failure with proper process cleanup
|
|
11
|
+
* - **Signal Handling**: Graceful cleanup on SIGTERM/SIGINT
|
|
12
|
+
* - **Language Agnostic**: Works with any command-line tool
|
|
13
|
+
*
|
|
14
|
+
* ## Example Usage
|
|
15
|
+
*
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { runValidation } from '@vibe-validate/core';
|
|
18
|
+
*
|
|
19
|
+
* const result = await runValidation({
|
|
20
|
+
* phases: [
|
|
21
|
+
* {
|
|
22
|
+
* name: 'Type Checking',
|
|
23
|
+
* steps: [
|
|
24
|
+
* { name: 'TypeScript', command: 'tsc --noEmit' },
|
|
25
|
+
* { name: 'ESLint', command: 'eslint src/' },
|
|
26
|
+
* ],
|
|
27
|
+
* },
|
|
28
|
+
* {
|
|
29
|
+
* name: 'Testing',
|
|
30
|
+
* steps: [
|
|
31
|
+
* { name: 'Unit Tests', command: 'npm test' },
|
|
32
|
+
* ],
|
|
33
|
+
* },
|
|
34
|
+
* ],
|
|
35
|
+
* enableFailFast: true,
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* if (result.passed) {
|
|
39
|
+
* console.log('✅ Validation passed!');
|
|
40
|
+
* } else {
|
|
41
|
+
* console.error('❌ Validation failed:', result.failedStep);
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @packageDocumentation
|
|
46
|
+
*/
|
|
47
|
+
export type { ValidationStep, ValidationPhase, ValidationConfig, ValidationResult, StepResult, PhaseResult, } from './types.js';
|
|
48
|
+
export { runValidation, runStepsInParallel, getWorkingTreeHash, checkExistingValidation, parseFailures, setupSignalHandlers, } from './runner.js';
|
|
49
|
+
export { stopProcessGroup, } from './process-utils.js';
|
|
50
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAGH,YAAY,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACb,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,gBAAgB,GACjB,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vibe-validate/core
|
|
3
|
+
*
|
|
4
|
+
* Core validation engine with git tree hash caching, parallel execution, and fail-fast support.
|
|
5
|
+
*
|
|
6
|
+
* ## Features
|
|
7
|
+
*
|
|
8
|
+
* - **Git Tree Hash Caching**: Skip validation if code unchanged
|
|
9
|
+
* - **Parallel Execution**: Run validation steps concurrently for speed
|
|
10
|
+
* - **Fail-Fast**: Stop on first failure with proper process cleanup
|
|
11
|
+
* - **Signal Handling**: Graceful cleanup on SIGTERM/SIGINT
|
|
12
|
+
* - **Language Agnostic**: Works with any command-line tool
|
|
13
|
+
*
|
|
14
|
+
* ## Example Usage
|
|
15
|
+
*
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { runValidation } from '@vibe-validate/core';
|
|
18
|
+
*
|
|
19
|
+
* const result = await runValidation({
|
|
20
|
+
* phases: [
|
|
21
|
+
* {
|
|
22
|
+
* name: 'Type Checking',
|
|
23
|
+
* steps: [
|
|
24
|
+
* { name: 'TypeScript', command: 'tsc --noEmit' },
|
|
25
|
+
* { name: 'ESLint', command: 'eslint src/' },
|
|
26
|
+
* ],
|
|
27
|
+
* },
|
|
28
|
+
* {
|
|
29
|
+
* name: 'Testing',
|
|
30
|
+
* steps: [
|
|
31
|
+
* { name: 'Unit Tests', command: 'npm test' },
|
|
32
|
+
* ],
|
|
33
|
+
* },
|
|
34
|
+
* ],
|
|
35
|
+
* enableFailFast: true,
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* if (result.passed) {
|
|
39
|
+
* console.log('✅ Validation passed!');
|
|
40
|
+
* } else {
|
|
41
|
+
* console.error('❌ Validation failed:', result.failedStep);
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @packageDocumentation
|
|
46
|
+
*/
|
|
47
|
+
// Export core runner functions
|
|
48
|
+
export { runValidation, runStepsInParallel, getWorkingTreeHash, checkExistingValidation, parseFailures, setupSignalHandlers, } from './runner.js';
|
|
49
|
+
// Export process utilities
|
|
50
|
+
export { stopProcessGroup, } from './process-utils.js';
|
|
51
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAYH,+BAA+B;AAC/B,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACb,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,2BAA2B;AAC3B,OAAO,EACL,gBAAgB,GACjB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process management utilities for validation runner
|
|
3
|
+
*
|
|
4
|
+
* Provides reliable process group cleanup for spawned child processes.
|
|
5
|
+
* Used by validation runner for signal handling and fail-fast behavior.
|
|
6
|
+
*/
|
|
7
|
+
import { ChildProcess } from 'child_process';
|
|
8
|
+
/**
|
|
9
|
+
* Stop a child process and its entire process group
|
|
10
|
+
*
|
|
11
|
+
* Uses negative PID to kill process group, ensuring all children are terminated.
|
|
12
|
+
*
|
|
13
|
+
* **Implementation:**
|
|
14
|
+
* - Graceful shutdown: SIGTERM to process group (-PID)
|
|
15
|
+
* - Force kill after 1s: SIGKILL to process group
|
|
16
|
+
* - Ultimate timeout: Resolves after 2s regardless
|
|
17
|
+
*
|
|
18
|
+
* @param childProcess - The child process to stop
|
|
19
|
+
* @param processName - Optional name for logging (e.g., "TypeScript", "ESLint")
|
|
20
|
+
* @returns Promise that resolves when process is stopped
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const proc = spawn('tsc', ['--noEmit']);
|
|
25
|
+
* await stopProcessGroup(proc, 'TypeScript');
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function stopProcessGroup(childProcess: ChildProcess, processName?: string): Promise<void>;
|
|
29
|
+
//# sourceMappingURL=process-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-utils.d.ts","sourceRoot":"","sources":["../src/process-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,YAAY,EAC1B,WAAW,GAAE,MAAkB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAmCf"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process management utilities for validation runner
|
|
3
|
+
*
|
|
4
|
+
* Provides reliable process group cleanup for spawned child processes.
|
|
5
|
+
* Used by validation runner for signal handling and fail-fast behavior.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Stop a child process and its entire process group
|
|
9
|
+
*
|
|
10
|
+
* Uses negative PID to kill process group, ensuring all children are terminated.
|
|
11
|
+
*
|
|
12
|
+
* **Implementation:**
|
|
13
|
+
* - Graceful shutdown: SIGTERM to process group (-PID)
|
|
14
|
+
* - Force kill after 1s: SIGKILL to process group
|
|
15
|
+
* - Ultimate timeout: Resolves after 2s regardless
|
|
16
|
+
*
|
|
17
|
+
* @param childProcess - The child process to stop
|
|
18
|
+
* @param processName - Optional name for logging (e.g., "TypeScript", "ESLint")
|
|
19
|
+
* @returns Promise that resolves when process is stopped
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const proc = spawn('tsc', ['--noEmit']);
|
|
24
|
+
* await stopProcessGroup(proc, 'TypeScript');
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export async function stopProcessGroup(childProcess, processName = 'Process') {
|
|
28
|
+
return new Promise((resolve) => {
|
|
29
|
+
if (!childProcess.killed && childProcess.pid) {
|
|
30
|
+
const pid = childProcess.pid;
|
|
31
|
+
childProcess.on('exit', () => {
|
|
32
|
+
console.log(`🛑 ${processName} stopped`);
|
|
33
|
+
resolve();
|
|
34
|
+
});
|
|
35
|
+
// Kill the entire process group by negating the PID
|
|
36
|
+
// This kills the process and all its children
|
|
37
|
+
try {
|
|
38
|
+
process.kill(-pid, 'SIGTERM');
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// Process may already be dead, ignore error
|
|
42
|
+
}
|
|
43
|
+
// Force kill entire process group after 1 second if not stopped
|
|
44
|
+
setTimeout(() => {
|
|
45
|
+
try {
|
|
46
|
+
process.kill(-pid, 'SIGKILL');
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Process may already be dead, ignore error
|
|
50
|
+
}
|
|
51
|
+
}, 1000);
|
|
52
|
+
// Ultimate timeout - resolve after 2 seconds regardless
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
resolve();
|
|
55
|
+
}, 2000);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
resolve();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=process-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-utils.js","sourceRoot":"","sources":["../src/process-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,YAA0B,EAC1B,cAAsB,SAAS;IAE/B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,CAAC,YAAY,CAAC,MAAM,IAAI,YAAY,CAAC,GAAG,EAAE,CAAC;YAC7C,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC;YAE7B,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;gBAC3B,OAAO,CAAC,GAAG,CAAC,MAAM,WAAW,UAAU,CAAC,CAAC;gBACzC,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;YAEH,oDAAoD;YACpD,8CAA8C;YAC9C,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,4CAA4C;YAC9C,CAAC;YAED,gEAAgE;YAChE,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,CAAC;oBACH,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;gBAChC,CAAC;gBAAC,MAAM,CAAC;oBACP,4CAA4C;gBAC9C,CAAC;YACH,CAAC,EAAE,IAAI,CAAC,CAAC;YAET,wDAAwD;YACxD,UAAU,CAAC,GAAG,EAAE;gBACd,OAAO,EAAE,CAAC;YACZ,CAAC,EAAE,IAAI,CAAC,CAAC;QACX,CAAC;aAAM,CAAC;YACN,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Runner - Core validation orchestration with state caching
|
|
3
|
+
*
|
|
4
|
+
* This module provides the core validation engine that:
|
|
5
|
+
* 1. Executes validation steps in parallel for speed
|
|
6
|
+
* 2. Tracks state using git tree hashes for caching
|
|
7
|
+
* 3. Provides fail-fast execution with proper cleanup
|
|
8
|
+
* 4. Handles signals (SIGTERM/SIGINT) gracefully
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
import type { ValidationStep, ValidationResult, ValidationConfig, StepResult } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Git tree hash calculator
|
|
15
|
+
*
|
|
16
|
+
* IMPORTANT: Current implementation uses `git stash create` which includes timestamps.
|
|
17
|
+
* This makes hashes non-deterministic - identical code produces different hashes.
|
|
18
|
+
*
|
|
19
|
+
* TODO: Replace with deterministic git write-tree approach:
|
|
20
|
+
* git add --intent-to-add . # Mark untracked (no staging)
|
|
21
|
+
* git write-tree # Content-based hash (no timestamps)
|
|
22
|
+
* git reset # Restore index
|
|
23
|
+
*
|
|
24
|
+
* @returns SHA-1 hash representing working tree state (currently non-deterministic)
|
|
25
|
+
*/
|
|
26
|
+
export declare function getWorkingTreeHash(): string;
|
|
27
|
+
/**
|
|
28
|
+
* Check if validation has already passed for current working tree state
|
|
29
|
+
*/
|
|
30
|
+
export declare function checkExistingValidation(currentTreeHash: string, stateFilePath: string): {
|
|
31
|
+
alreadyPassed: boolean;
|
|
32
|
+
previousState?: ValidationResult;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Parse test output to extract specific failures
|
|
36
|
+
* This is a basic implementation - formatters package will have more sophisticated parsing
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseFailures(output: string): string[];
|
|
39
|
+
/**
|
|
40
|
+
* Run validation steps in parallel with smart fail-fast
|
|
41
|
+
*
|
|
42
|
+
* @param steps - Array of validation steps to execute
|
|
43
|
+
* @param phaseName - Name of the current phase (for logging)
|
|
44
|
+
* @param logPath - Path to log file for output capture
|
|
45
|
+
* @param enableFailFast - If true, kills remaining processes on first failure
|
|
46
|
+
* @param env - Environment variables to pass to child processes
|
|
47
|
+
*/
|
|
48
|
+
export declare function runStepsInParallel(steps: ValidationStep[], phaseName: string, enableFailFast?: boolean, env?: Record<string, string>): Promise<{
|
|
49
|
+
success: boolean;
|
|
50
|
+
failedStep?: ValidationStep;
|
|
51
|
+
outputs: Map<string, string>;
|
|
52
|
+
stepResults: StepResult[];
|
|
53
|
+
}>;
|
|
54
|
+
/**
|
|
55
|
+
* Validation runner with state tracking and caching
|
|
56
|
+
*
|
|
57
|
+
* Main entry point for running validation with git tree hash caching
|
|
58
|
+
*/
|
|
59
|
+
export declare function runValidation(config: ValidationConfig): Promise<ValidationResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Setup signal handlers for graceful cleanup
|
|
62
|
+
*
|
|
63
|
+
* Ensures all child processes are killed when validation runner is interrupted
|
|
64
|
+
*/
|
|
65
|
+
export declare function setupSignalHandlers(activeProcesses: Set<any>): void;
|
|
66
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EAEX,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CA0B3C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,GACpB;IAAE,aAAa,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAmB9D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAsBtD;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,cAAc,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,cAAc,GAAE,OAAe,EAC/B,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAC/B,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B,CAAC,CAiFD;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAoHvF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAenE"}
|
package/dist/runner.js
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Runner - Core validation orchestration with state caching
|
|
3
|
+
*
|
|
4
|
+
* This module provides the core validation engine that:
|
|
5
|
+
* 1. Executes validation steps in parallel for speed
|
|
6
|
+
* 2. Tracks state using git tree hashes for caching
|
|
7
|
+
* 3. Provides fail-fast execution with proper cleanup
|
|
8
|
+
* 4. Handles signals (SIGTERM/SIGINT) gracefully
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
import { spawn, execSync } from 'child_process';
|
|
13
|
+
import { writeFileSync, appendFileSync, existsSync, readFileSync } from 'fs';
|
|
14
|
+
import { stopProcessGroup } from './process-utils.js';
|
|
15
|
+
/**
|
|
16
|
+
* Git tree hash calculator
|
|
17
|
+
*
|
|
18
|
+
* IMPORTANT: Current implementation uses `git stash create` which includes timestamps.
|
|
19
|
+
* This makes hashes non-deterministic - identical code produces different hashes.
|
|
20
|
+
*
|
|
21
|
+
* TODO: Replace with deterministic git write-tree approach:
|
|
22
|
+
* git add --intent-to-add . # Mark untracked (no staging)
|
|
23
|
+
* git write-tree # Content-based hash (no timestamps)
|
|
24
|
+
* git reset # Restore index
|
|
25
|
+
*
|
|
26
|
+
* @returns SHA-1 hash representing working tree state (currently non-deterministic)
|
|
27
|
+
*/
|
|
28
|
+
export function getWorkingTreeHash() {
|
|
29
|
+
try {
|
|
30
|
+
// Use git stash create to include ALL working tree changes
|
|
31
|
+
// WARNING: This creates commit objects with timestamps (non-deterministic)
|
|
32
|
+
const stashHash = execSync('git stash create', {
|
|
33
|
+
encoding: 'utf8',
|
|
34
|
+
stdio: ['pipe', 'pipe', 'ignore']
|
|
35
|
+
}).trim();
|
|
36
|
+
// If no changes, fall back to HEAD tree
|
|
37
|
+
if (!stashHash) {
|
|
38
|
+
return execSync('git rev-parse HEAD^{tree}', {
|
|
39
|
+
encoding: 'utf8',
|
|
40
|
+
stdio: ['pipe', 'pipe', 'ignore']
|
|
41
|
+
}).trim();
|
|
42
|
+
}
|
|
43
|
+
// Extract tree hash from stash commit
|
|
44
|
+
return execSync(`git rev-parse ${stashHash}^{tree}`, {
|
|
45
|
+
encoding: 'utf8',
|
|
46
|
+
stdio: ['pipe', 'pipe', 'ignore']
|
|
47
|
+
}).trim();
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
// Fallback for non-git repos or git command failures
|
|
51
|
+
return `nogit-${Date.now()}`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Check if validation has already passed for current working tree state
|
|
56
|
+
*/
|
|
57
|
+
export function checkExistingValidation(currentTreeHash, stateFilePath) {
|
|
58
|
+
if (!existsSync(stateFilePath)) {
|
|
59
|
+
return { alreadyPassed: false };
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const content = readFileSync(stateFilePath, 'utf8');
|
|
63
|
+
// Parse as JSON (will support YAML in CLI package)
|
|
64
|
+
const state = JSON.parse(content);
|
|
65
|
+
// Check if validation passed and tree hash matches
|
|
66
|
+
if (state.passed && state.treeHash === currentTreeHash) {
|
|
67
|
+
return { alreadyPassed: true, previousState: state };
|
|
68
|
+
}
|
|
69
|
+
return { alreadyPassed: false, previousState: state };
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
return { alreadyPassed: false };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Parse test output to extract specific failures
|
|
77
|
+
* This is a basic implementation - formatters package will have more sophisticated parsing
|
|
78
|
+
*/
|
|
79
|
+
export function parseFailures(output) {
|
|
80
|
+
const failures = [];
|
|
81
|
+
// Vitest test failures - extract test names
|
|
82
|
+
const vitestFailures = output.match(/❌ .+/g);
|
|
83
|
+
if (vitestFailures) {
|
|
84
|
+
failures.push(...vitestFailures.slice(0, 10)); // Limit to first 10
|
|
85
|
+
}
|
|
86
|
+
// TypeScript errors - extract file:line
|
|
87
|
+
const tsErrors = output.match(/[^(]+\(\d+,\d+\): error TS\d+:.+/g);
|
|
88
|
+
if (tsErrors) {
|
|
89
|
+
failures.push(...tsErrors.slice(0, 10).map(e => e.trim()));
|
|
90
|
+
}
|
|
91
|
+
// ESLint errors - extract file:line
|
|
92
|
+
const eslintErrors = output.match(/\S+\.ts\(\d+,\d+\): .+/g);
|
|
93
|
+
if (eslintErrors) {
|
|
94
|
+
failures.push(...eslintErrors.slice(0, 10).map(e => e.trim()));
|
|
95
|
+
}
|
|
96
|
+
return failures;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Run validation steps in parallel with smart fail-fast
|
|
100
|
+
*
|
|
101
|
+
* @param steps - Array of validation steps to execute
|
|
102
|
+
* @param phaseName - Name of the current phase (for logging)
|
|
103
|
+
* @param logPath - Path to log file for output capture
|
|
104
|
+
* @param enableFailFast - If true, kills remaining processes on first failure
|
|
105
|
+
* @param env - Environment variables to pass to child processes
|
|
106
|
+
*/
|
|
107
|
+
export async function runStepsInParallel(steps, phaseName, enableFailFast = false, env = {}) {
|
|
108
|
+
console.log(`\n🔍 Running ${phaseName} (${steps.length} steps in parallel)...`);
|
|
109
|
+
// Find longest step name for alignment
|
|
110
|
+
const maxNameLength = Math.max(...steps.map(s => s.name.length));
|
|
111
|
+
const outputs = new Map();
|
|
112
|
+
const stepResults = [];
|
|
113
|
+
const processes = [];
|
|
114
|
+
let firstFailure = null;
|
|
115
|
+
const results = await Promise.allSettled(steps.map(step => new Promise((resolve, reject) => {
|
|
116
|
+
const paddedName = step.name.padEnd(maxNameLength);
|
|
117
|
+
console.log(` ⏳ ${paddedName} → ${step.command}`);
|
|
118
|
+
const startTime = Date.now();
|
|
119
|
+
const proc = spawn('sh', ['-c', step.command], {
|
|
120
|
+
stdio: 'pipe',
|
|
121
|
+
detached: true, // Create new process group for easier cleanup
|
|
122
|
+
env: {
|
|
123
|
+
...process.env,
|
|
124
|
+
...env,
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
// Track process for potential kill
|
|
128
|
+
processes.push({ proc, step });
|
|
129
|
+
let stdout = '';
|
|
130
|
+
let stderr = '';
|
|
131
|
+
proc.stdout.on('data', data => { stdout += data.toString(); });
|
|
132
|
+
proc.stderr.on('data', data => { stderr += data.toString(); });
|
|
133
|
+
proc.on('close', code => {
|
|
134
|
+
const duration = Date.now() - startTime;
|
|
135
|
+
const output = stdout + stderr;
|
|
136
|
+
outputs.set(step.name, output);
|
|
137
|
+
const durationSec = (duration / 1000).toFixed(1);
|
|
138
|
+
const status = code === 0 ? '✅' : '❌';
|
|
139
|
+
const result = code === 0 ? 'PASSED' : 'FAILED';
|
|
140
|
+
console.log(` ${status} ${step.name.padEnd(maxNameLength)} - ${result} (${durationSec}s)`);
|
|
141
|
+
stepResults.push({ name: step.name, passed: code === 0, duration });
|
|
142
|
+
if (code === 0) {
|
|
143
|
+
resolve({ step, output, duration });
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// On first failure, kill other processes if fail-fast enabled
|
|
147
|
+
if (enableFailFast && !firstFailure) {
|
|
148
|
+
firstFailure = { step, output };
|
|
149
|
+
console.log(`\n⚠️ Fail-fast enabled: Killing remaining processes...`);
|
|
150
|
+
// Kill all other running processes
|
|
151
|
+
for (const { proc: otherProc, step: otherStep } of processes) {
|
|
152
|
+
if (otherStep !== step && otherProc.exitCode === null) {
|
|
153
|
+
stopProcessGroup(otherProc, otherStep.name).catch(() => {
|
|
154
|
+
// Process may have already exited, ignore errors
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
reject({ step, output, duration });
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
})));
|
|
163
|
+
// Check for failures
|
|
164
|
+
for (const result of results) {
|
|
165
|
+
if (result.status === 'rejected') {
|
|
166
|
+
const { step } = result.reason;
|
|
167
|
+
return { success: false, failedStep: step, outputs, stepResults };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return { success: true, outputs, stepResults };
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Validation runner with state tracking and caching
|
|
174
|
+
*
|
|
175
|
+
* Main entry point for running validation with git tree hash caching
|
|
176
|
+
*/
|
|
177
|
+
export async function runValidation(config) {
|
|
178
|
+
const { phases, stateFilePath = '.validate-state.json', logPath = `/tmp/validation-${new Date().toISOString().replace(/[:.]/g, '-')}.log`, enableFailFast = false, forceRun = false, env = {}, onPhaseStart, onPhaseComplete, } = config;
|
|
179
|
+
// Get current working tree hash
|
|
180
|
+
const currentTreeHash = getWorkingTreeHash();
|
|
181
|
+
// Check if validation already passed for this exact code state
|
|
182
|
+
if (!forceRun) {
|
|
183
|
+
const { alreadyPassed, previousState } = checkExistingValidation(currentTreeHash, stateFilePath);
|
|
184
|
+
if (alreadyPassed && previousState) {
|
|
185
|
+
console.log('✅ Validation already passed for current working tree state');
|
|
186
|
+
console.log(` Tree hash: ${currentTreeHash.substring(0, 12)}...`);
|
|
187
|
+
console.log(` Last validated: ${previousState.timestamp}`);
|
|
188
|
+
return previousState;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Initialize log file
|
|
192
|
+
writeFileSync(logPath, `Validation started at ${new Date().toISOString()}\n\n`);
|
|
193
|
+
let fullOutput = '';
|
|
194
|
+
let failedStep = null;
|
|
195
|
+
const phaseResults = [];
|
|
196
|
+
// Run each phase
|
|
197
|
+
for (const phase of phases) {
|
|
198
|
+
if (onPhaseStart) {
|
|
199
|
+
onPhaseStart(phase);
|
|
200
|
+
}
|
|
201
|
+
const phaseStartTime = Date.now();
|
|
202
|
+
const result = await runStepsInParallel(phase.steps, phase.name, enableFailFast, env);
|
|
203
|
+
const phaseDuration = Date.now() - phaseStartTime;
|
|
204
|
+
// Append all outputs to log file
|
|
205
|
+
for (const [stepName, output] of result.outputs) {
|
|
206
|
+
appendFileSync(logPath, `\n${'='.repeat(60)}\n`);
|
|
207
|
+
appendFileSync(logPath, `${stepName}${result.failedStep?.name === stepName ? ' - FAILED' : ''}\n`);
|
|
208
|
+
appendFileSync(logPath, `${'='.repeat(60)}\n`);
|
|
209
|
+
appendFileSync(logPath, output);
|
|
210
|
+
fullOutput += output;
|
|
211
|
+
}
|
|
212
|
+
// Record phase result
|
|
213
|
+
const phaseResult = {
|
|
214
|
+
name: phase.name,
|
|
215
|
+
duration: phaseDuration,
|
|
216
|
+
passed: result.success,
|
|
217
|
+
steps: result.stepResults,
|
|
218
|
+
};
|
|
219
|
+
// If phase failed, include output
|
|
220
|
+
if (!result.success && result.failedStep) {
|
|
221
|
+
phaseResult.output = result.outputs.get(result.failedStep.name);
|
|
222
|
+
}
|
|
223
|
+
phaseResults.push(phaseResult);
|
|
224
|
+
if (onPhaseComplete) {
|
|
225
|
+
onPhaseComplete(phase, phaseResult);
|
|
226
|
+
}
|
|
227
|
+
// If phase failed, stop here
|
|
228
|
+
if (!result.success && result.failedStep) {
|
|
229
|
+
failedStep = result.failedStep;
|
|
230
|
+
const failedOutput = result.outputs.get(failedStep.name) || '';
|
|
231
|
+
const failures = parseFailures(failedOutput);
|
|
232
|
+
const validationResult = {
|
|
233
|
+
passed: false,
|
|
234
|
+
timestamp: new Date().toISOString(),
|
|
235
|
+
treeHash: currentTreeHash,
|
|
236
|
+
phases: phaseResults,
|
|
237
|
+
failedStep: failedStep.name,
|
|
238
|
+
rerunCommand: failedStep.command,
|
|
239
|
+
failedStepOutput: failedOutput,
|
|
240
|
+
failedTests: failures.length > 0 ? failures : undefined,
|
|
241
|
+
fullLogFile: logPath,
|
|
242
|
+
};
|
|
243
|
+
// Write state file
|
|
244
|
+
writeFileSync(stateFilePath, JSON.stringify(validationResult, null, 2));
|
|
245
|
+
return validationResult;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// All steps passed!
|
|
249
|
+
const validationResult = {
|
|
250
|
+
passed: true,
|
|
251
|
+
timestamp: new Date().toISOString(),
|
|
252
|
+
treeHash: currentTreeHash,
|
|
253
|
+
phases: phaseResults,
|
|
254
|
+
fullLogFile: logPath,
|
|
255
|
+
};
|
|
256
|
+
// Write state file
|
|
257
|
+
writeFileSync(stateFilePath, JSON.stringify(validationResult, null, 2));
|
|
258
|
+
return validationResult;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Setup signal handlers for graceful cleanup
|
|
262
|
+
*
|
|
263
|
+
* Ensures all child processes are killed when validation runner is interrupted
|
|
264
|
+
*/
|
|
265
|
+
export function setupSignalHandlers(activeProcesses) {
|
|
266
|
+
const cleanup = async (signal) => {
|
|
267
|
+
console.log(`\n⚠️ Received ${signal}, cleaning up ${activeProcesses.size} active processes...`);
|
|
268
|
+
// Kill all active processes
|
|
269
|
+
const cleanupPromises = Array.from(activeProcesses).map(proc => stopProcessGroup(proc, 'Validation step'));
|
|
270
|
+
await Promise.all(cleanupPromises);
|
|
271
|
+
process.exit(1);
|
|
272
|
+
};
|
|
273
|
+
process.on('SIGTERM', () => cleanup('SIGTERM'));
|
|
274
|
+
process.on('SIGINT', () => cleanup('SIGINT'));
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core validation types for vibe-validate
|
|
3
|
+
*
|
|
4
|
+
* These types define the validation configuration structure and result types.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* A single validation step (language-agnostic)
|
|
8
|
+
*/
|
|
9
|
+
export interface ValidationStep {
|
|
10
|
+
/** Human-readable step name */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Command to execute (can be any shell command, not just npm scripts) */
|
|
13
|
+
command: string;
|
|
14
|
+
/** Optional timeout in milliseconds */
|
|
15
|
+
timeout?: number;
|
|
16
|
+
/** Optional environment variables for this step */
|
|
17
|
+
env?: Record<string, string>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A validation phase containing multiple steps
|
|
21
|
+
*/
|
|
22
|
+
export interface ValidationPhase {
|
|
23
|
+
/** Human-readable phase name */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Run steps in parallel? */
|
|
26
|
+
parallel: boolean;
|
|
27
|
+
/** Phase names this phase depends on */
|
|
28
|
+
dependsOn?: string[];
|
|
29
|
+
/** Steps to execute in this phase */
|
|
30
|
+
steps: ValidationStep[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Result from executing a validation step
|
|
34
|
+
*/
|
|
35
|
+
export interface StepResult {
|
|
36
|
+
/** Step name */
|
|
37
|
+
name: string;
|
|
38
|
+
/** Did the step pass? */
|
|
39
|
+
passed: boolean;
|
|
40
|
+
/** Execution duration in milliseconds */
|
|
41
|
+
duration: number;
|
|
42
|
+
/** Output from the step (stdout + stderr) */
|
|
43
|
+
output?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Result from executing a validation phase
|
|
47
|
+
*/
|
|
48
|
+
export interface PhaseResult {
|
|
49
|
+
/** Phase name */
|
|
50
|
+
name: string;
|
|
51
|
+
/** Phase execution duration in milliseconds */
|
|
52
|
+
duration: number;
|
|
53
|
+
/** Did the phase pass? */
|
|
54
|
+
passed: boolean;
|
|
55
|
+
/** Results from individual steps */
|
|
56
|
+
steps: StepResult[];
|
|
57
|
+
/** Output from failed step (if any) */
|
|
58
|
+
output?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Overall validation result
|
|
62
|
+
*/
|
|
63
|
+
export interface ValidationResult {
|
|
64
|
+
/** Did validation pass? */
|
|
65
|
+
passed: boolean;
|
|
66
|
+
/** ISO 8601 timestamp */
|
|
67
|
+
timestamp: string;
|
|
68
|
+
/** Git tree hash (if in git repo) */
|
|
69
|
+
treeHash: string;
|
|
70
|
+
/** Results from each phase */
|
|
71
|
+
phases?: PhaseResult[];
|
|
72
|
+
/** Name of failed step (if any) */
|
|
73
|
+
failedStep?: string;
|
|
74
|
+
/** Command to re-run failed step */
|
|
75
|
+
rerunCommand?: string;
|
|
76
|
+
/** Output from the failed step */
|
|
77
|
+
failedStepOutput?: string;
|
|
78
|
+
/** Failed test names (if applicable) */
|
|
79
|
+
failedTests?: string[];
|
|
80
|
+
/** Path to full log file */
|
|
81
|
+
fullLogFile?: string;
|
|
82
|
+
/** Summary message */
|
|
83
|
+
summary?: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Validation configuration
|
|
87
|
+
*/
|
|
88
|
+
export interface ValidationConfig {
|
|
89
|
+
/** Validation phases to execute */
|
|
90
|
+
phases: ValidationPhase[];
|
|
91
|
+
/** Path to state file (default: .validate-state.json) */
|
|
92
|
+
stateFilePath?: string;
|
|
93
|
+
/** Path to log file (default: /tmp/validation-{timestamp}.log) */
|
|
94
|
+
logPath?: string;
|
|
95
|
+
/** Enable fail-fast (stop on first failure) */
|
|
96
|
+
enableFailFast?: boolean;
|
|
97
|
+
/** Force re-run even if state says validation already passed */
|
|
98
|
+
forceRun?: boolean;
|
|
99
|
+
/** Environment variables to pass to all child processes */
|
|
100
|
+
env?: Record<string, string>;
|
|
101
|
+
/** Callback when phase starts */
|
|
102
|
+
onPhaseStart?: (phase: ValidationPhase) => void;
|
|
103
|
+
/** Callback when phase completes */
|
|
104
|
+
onPhaseComplete?: (phase: ValidationPhase, result: PhaseResult) => void;
|
|
105
|
+
/** Callback when step starts */
|
|
106
|
+
onStepStart?: (step: ValidationStep) => void;
|
|
107
|
+
/** Callback when step completes */
|
|
108
|
+
onStepComplete?: (step: ValidationStep, result: StepResult) => void;
|
|
109
|
+
/** Caching configuration */
|
|
110
|
+
caching?: {
|
|
111
|
+
/** Enable git tree hash caching */
|
|
112
|
+
enabled: boolean;
|
|
113
|
+
/** Cache strategy */
|
|
114
|
+
strategy: 'git-tree-hash' | 'file-hash' | 'timestamp';
|
|
115
|
+
/** Maximum age of cached results (ms) */
|
|
116
|
+
maxAge?: number;
|
|
117
|
+
};
|
|
118
|
+
/** Output configuration */
|
|
119
|
+
output?: {
|
|
120
|
+
/** Output format */
|
|
121
|
+
format: 'auto' | 'human' | 'yaml' | 'json';
|
|
122
|
+
/** Show verbose output */
|
|
123
|
+
verbose?: boolean;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vibe-validate/core",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Core validation orchestration engine for vibe-validate",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"dev": "tsc --watch",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"clean": "rm -rf dist *.tsbuildinfo"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"validation",
|
|
26
|
+
"parallel",
|
|
27
|
+
"orchestration",
|
|
28
|
+
"git",
|
|
29
|
+
"cache"
|
|
30
|
+
],
|
|
31
|
+
"author": "Jeff Dutton",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/jdutton/vibe-validate.git",
|
|
36
|
+
"directory": "packages/core"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20.0.0"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"js-yaml": "^4.1.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/js-yaml": "^4.0.9",
|
|
49
|
+
"@types/node": "^20.17.6",
|
|
50
|
+
"typescript": "^5.7.2",
|
|
51
|
+
"vitest": "^2.1.8"
|
|
52
|
+
}
|
|
53
|
+
}
|