@vibe-validate/cli 0.11.0 → 0.12.1

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 (82) hide show
  1. package/README.md +14 -4
  2. package/dist/bin.js +88 -13
  3. package/dist/bin.js.map +1 -1
  4. package/dist/commands/cleanup.d.ts +4 -0
  5. package/dist/commands/cleanup.d.ts.map +1 -1
  6. package/dist/commands/cleanup.js +94 -2
  7. package/dist/commands/cleanup.js.map +1 -1
  8. package/dist/commands/config.d.ts +4 -0
  9. package/dist/commands/config.d.ts.map +1 -1
  10. package/dist/commands/config.js +83 -0
  11. package/dist/commands/config.js.map +1 -1
  12. package/dist/commands/doctor.d.ts +4 -0
  13. package/dist/commands/doctor.d.ts.map +1 -1
  14. package/dist/commands/doctor.js +306 -28
  15. package/dist/commands/doctor.js.map +1 -1
  16. package/dist/commands/generate-workflow.d.ts +4 -0
  17. package/dist/commands/generate-workflow.d.ts.map +1 -1
  18. package/dist/commands/generate-workflow.js +157 -48
  19. package/dist/commands/generate-workflow.js.map +1 -1
  20. package/dist/commands/history.d.ts +13 -0
  21. package/dist/commands/history.d.ts.map +1 -0
  22. package/dist/commands/history.js +415 -0
  23. package/dist/commands/history.js.map +1 -0
  24. package/dist/commands/init.d.ts +4 -0
  25. package/dist/commands/init.d.ts.map +1 -1
  26. package/dist/commands/init.js +181 -0
  27. package/dist/commands/init.js.map +1 -1
  28. package/dist/commands/pre-commit.d.ts +4 -0
  29. package/dist/commands/pre-commit.d.ts.map +1 -1
  30. package/dist/commands/pre-commit.js +158 -7
  31. package/dist/commands/pre-commit.js.map +1 -1
  32. package/dist/commands/state.d.ts +5 -1
  33. package/dist/commands/state.d.ts.map +1 -1
  34. package/dist/commands/state.js +192 -18
  35. package/dist/commands/state.js.map +1 -1
  36. package/dist/commands/sync-check.d.ts +4 -0
  37. package/dist/commands/sync-check.d.ts.map +1 -1
  38. package/dist/commands/sync-check.js +98 -2
  39. package/dist/commands/sync-check.js.map +1 -1
  40. package/dist/commands/validate.d.ts +5 -1
  41. package/dist/commands/validate.d.ts.map +1 -1
  42. package/dist/commands/validate.js +184 -28
  43. package/dist/commands/validate.js.map +1 -1
  44. package/dist/commands/watch-pr.d.ts +4 -0
  45. package/dist/commands/watch-pr.d.ts.map +1 -1
  46. package/dist/commands/watch-pr.js +175 -14
  47. package/dist/commands/watch-pr.js.map +1 -1
  48. package/dist/schemas/watch-pr-schema.d.ts +40 -40
  49. package/dist/schemas/watch-pr-schema.js +1 -1
  50. package/dist/schemas/watch-pr-schema.js.map +1 -1
  51. package/dist/services/ci-provider.d.ts +13 -8
  52. package/dist/services/ci-provider.d.ts.map +1 -1
  53. package/dist/services/ci-providers/github-actions.d.ts +5 -4
  54. package/dist/services/ci-providers/github-actions.d.ts.map +1 -1
  55. package/dist/services/ci-providers/github-actions.js +36 -27
  56. package/dist/services/ci-providers/github-actions.js.map +1 -1
  57. package/dist/utils/check-validation.d.ts +7 -4
  58. package/dist/utils/check-validation.d.ts.map +1 -1
  59. package/dist/utils/check-validation.js +129 -48
  60. package/dist/utils/check-validation.js.map +1 -1
  61. package/dist/utils/run-validation-with-cache.d.ts +48 -0
  62. package/dist/utils/run-validation-with-cache.d.ts.map +1 -0
  63. package/dist/utils/run-validation-with-cache.js +123 -0
  64. package/dist/utils/run-validation-with-cache.js.map +1 -0
  65. package/dist/utils/runner-adapter.d.ts +1 -0
  66. package/dist/utils/runner-adapter.d.ts.map +1 -1
  67. package/dist/utils/runner-adapter.js +25 -17
  68. package/dist/utils/runner-adapter.js.map +1 -1
  69. package/dist/utils/setup-checks/gitignore-check.d.ts +10 -15
  70. package/dist/utils/setup-checks/gitignore-check.d.ts.map +1 -1
  71. package/dist/utils/setup-checks/gitignore-check.js +20 -137
  72. package/dist/utils/setup-checks/gitignore-check.js.map +1 -1
  73. package/dist/utils/validate-workflow.d.ts +28 -0
  74. package/dist/utils/validate-workflow.d.ts.map +1 -0
  75. package/dist/utils/validate-workflow.js +247 -0
  76. package/dist/utils/validate-workflow.js.map +1 -0
  77. package/dist/utils/validation-cache.d.ts +30 -0
  78. package/dist/utils/validation-cache.d.ts.map +1 -0
  79. package/dist/utils/validation-cache.js +57 -0
  80. package/dist/utils/validation-cache.js.map +1 -0
  81. package/package.json +6 -4
  82. package/watch-pr-result.schema.json +1 -1
@@ -1,155 +1,38 @@
1
1
  /**
2
- * Gitignore Setup Check
2
+ * Gitignore Setup Check (DEPRECATED)
3
3
  *
4
- * Ensures that .vibe-validate-state.yaml is listed in .gitignore
5
- * to prevent committing validation state files.
4
+ * @deprecated Since v0.12.0 - State file (.vibe-validate-state.yaml) is deprecated.
5
+ * Validation history is now stored in git notes instead of a state file.
6
+ * This check always passes and does not modify .gitignore.
7
+ *
8
+ * Use `vibe-validate doctor` to detect and remove deprecated state file entries.
6
9
  */
7
- import { readFile, writeFile } from 'fs/promises';
8
- import { existsSync } from 'fs';
9
- import { join } from 'path';
10
- import { splitLines } from '../normalize-line-endings.js';
11
- const STATE_FILE_ENTRY = '.vibe-validate-state.yaml';
12
10
  export class GitignoreSetupCheck {
13
11
  id = 'gitignore';
14
- name = 'Gitignore Setup';
15
- async check(options) {
16
- const cwd = options?.cwd ?? process.cwd();
17
- const gitignorePath = join(cwd, '.gitignore');
18
- // Check if .gitignore exists
19
- if (!existsSync(gitignorePath)) {
20
- return {
21
- passed: false,
22
- message: '.gitignore not found',
23
- suggestion: `Create .gitignore and add ${STATE_FILE_ENTRY}`,
24
- };
25
- }
26
- // Read .gitignore content
27
- const content = await readFile(gitignorePath, 'utf-8');
28
- // Check if state file entry exists (with flexible whitespace)
29
- const hasEntry = splitLines(content)
30
- .some(line => line.trim() === STATE_FILE_ENTRY);
31
- if (!hasEntry) {
32
- return {
33
- passed: false,
34
- message: `.gitignore missing ${STATE_FILE_ENTRY} entry`,
35
- suggestion: `Add ${STATE_FILE_ENTRY} to .gitignore`,
36
- };
37
- }
12
+ name = 'Gitignore Setup (deprecated)';
13
+ async check(_options) {
14
+ // DEPRECATED: State file is no longer used (git notes replaced it in v0.12.0)
15
+ // Always return passed - no .gitignore modifications needed
38
16
  return {
39
17
  passed: true,
40
- message: '.gitignore correctly configured with state file entry',
18
+ message: '.gitignore check skipped (state file deprecated in v0.12.0)',
41
19
  };
42
20
  }
43
- async preview(options) {
44
- const cwd = options?.cwd ?? process.cwd();
45
- const gitignorePath = join(cwd, '.gitignore');
46
- // Check current state
47
- const checkResult = await this.check(options);
48
- if (checkResult.passed) {
49
- return {
50
- description: '.gitignore already configured correctly',
51
- filesAffected: [],
52
- changes: [],
53
- };
54
- }
55
- // If .gitignore doesn't exist
56
- if (!existsSync(gitignorePath)) {
57
- const content = this.generateNewGitignoreContent();
58
- return {
59
- description: 'Create new .gitignore with vibe-validate state file entry',
60
- filesAffected: ['.gitignore'],
61
- changes: [
62
- {
63
- file: '.gitignore',
64
- action: 'create',
65
- content,
66
- },
67
- ],
68
- };
69
- }
70
- // If .gitignore exists but missing entry
21
+ async preview(_options) {
22
+ // DEPRECATED: No .gitignore modifications needed (state file deprecated)
71
23
  return {
72
- description: `Add ${STATE_FILE_ENTRY} entry to existing .gitignore`,
73
- filesAffected: ['.gitignore'],
74
- changes: [
75
- {
76
- file: '.gitignore',
77
- action: 'modify',
78
- },
79
- ],
24
+ description: 'Gitignore check deprecated (state file no longer used)',
25
+ filesAffected: [],
26
+ changes: [],
80
27
  };
81
28
  }
82
- async fix(options) {
83
- const cwd = options?.cwd ?? process.cwd();
84
- const gitignorePath = join(cwd, '.gitignore');
85
- const dryRun = options?.dryRun ?? false;
86
- // Check current state
87
- const checkResult = await this.check(options);
88
- if (checkResult.passed && !options?.force) {
89
- return {
90
- success: true,
91
- message: '.gitignore already configured correctly',
92
- filesChanged: [],
93
- };
94
- }
95
- if (dryRun) {
96
- return {
97
- success: true,
98
- message: '[dry-run] Would update .gitignore',
99
- filesChanged: [],
100
- };
101
- }
102
- // If .gitignore doesn't exist, create it
103
- if (!existsSync(gitignorePath)) {
104
- const content = this.generateNewGitignoreContent();
105
- await writeFile(gitignorePath, content, 'utf-8');
106
- return {
107
- success: true,
108
- message: 'Created .gitignore with state file entry',
109
- filesChanged: ['.gitignore'],
110
- };
111
- }
112
- // If .gitignore exists, add entry if missing
113
- const content = await readFile(gitignorePath, 'utf-8');
114
- const hasEntry = splitLines(content)
115
- .some(line => line.trim() === STATE_FILE_ENTRY);
116
- if (hasEntry) {
117
- // Entry already exists (idempotent)
118
- return {
119
- success: true,
120
- message: '.gitignore already contains state file entry',
121
- filesChanged: [],
122
- };
123
- }
124
- // Add entry to existing .gitignore
125
- const updatedContent = this.addEntryToGitignore(content);
126
- await writeFile(gitignorePath, updatedContent, 'utf-8');
29
+ async fix(_options) {
30
+ // DEPRECATED: No .gitignore modifications needed (state file deprecated)
127
31
  return {
128
32
  success: true,
129
- message: `Added ${STATE_FILE_ENTRY} to .gitignore`,
130
- filesChanged: ['.gitignore'],
33
+ message: 'Gitignore check deprecated (state file no longer used)',
34
+ filesChanged: [],
131
35
  };
132
36
  }
133
- /**
134
- * Generate content for a new .gitignore file
135
- */
136
- generateNewGitignoreContent() {
137
- return `# vibe-validate
138
- ${STATE_FILE_ENTRY}
139
- `;
140
- }
141
- /**
142
- * Add state file entry to existing .gitignore content
143
- */
144
- addEntryToGitignore(content) {
145
- // Ensure content ends with newline
146
- let updatedContent = content;
147
- if (!content.endsWith('\n')) {
148
- updatedContent += '\n';
149
- }
150
- // Add vibe-validate section
151
- updatedContent += `\n# vibe-validate\n${STATE_FILE_ENTRY}\n`;
152
- return updatedContent;
153
- }
154
37
  }
155
38
  //# sourceMappingURL=gitignore-check.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gitignore-check.js","sourceRoot":"","sources":["../../../src/utils/setup-checks/gitignore-check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gitignore-check.js","sourceRoot":"","sources":["../../../src/utils/setup-checks/gitignore-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH,MAAM,OAAO,mBAAmB;IACrB,EAAE,GAAG,WAAW,CAAC;IACjB,IAAI,GAAG,8BAA8B,CAAC;IAE/C,KAAK,CAAC,KAAK,CAAC,QAAqB;QAC/B,8EAA8E;QAC9E,4DAA4D;QAC5D,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,6DAA6D;SACvE,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAqB;QACjC,yEAAyE;QACzE,OAAO;YACL,WAAW,EAAE,wDAAwD;YACrE,aAAa,EAAE,EAAE;YACjB,OAAO,EAAE,EAAE;SACZ,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,QAAqB;QAC7B,yEAAyE;QACzE,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,wDAAwD;YACjE,YAAY,EAAE,EAAE;SACjB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Shared Validation Workflow
3
+ *
4
+ * Core validation logic used by both validate and pre-commit commands.
5
+ * Handles caching, history recording, and output formatting.
6
+ */
7
+ import type { VibeValidateConfig } from '@vibe-validate/config';
8
+ import type { ValidationResult } from '@vibe-validate/core';
9
+ import type { AgentContext } from './context-detector.js';
10
+ export interface ValidateWorkflowOptions {
11
+ force?: boolean;
12
+ verbose?: boolean;
13
+ yaml?: boolean;
14
+ check?: boolean;
15
+ context: AgentContext;
16
+ }
17
+ /**
18
+ * Execute validation workflow with caching, history recording, and output formatting.
19
+ *
20
+ * This is the shared implementation used by both `validate` and `pre-commit` commands.
21
+ *
22
+ * @param config - Loaded vibe-validate configuration
23
+ * @param options - Validation options (force, verbose, yaml, check, context)
24
+ * @returns Validation result
25
+ * @throws Error if validation encounters fatal error
26
+ */
27
+ export declare function runValidateWorkflow(config: VibeValidateConfig, options: ValidateWorkflowOptions): Promise<ValidationResult>;
28
+ //# sourceMappingURL=validate-workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-workflow.d.ts","sourceRoot":"","sources":["../../src/utils/validate-workflow.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAS5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAK1D,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,gBAAgB,CAAC,CAmP3B"}
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Shared Validation Workflow
3
+ *
4
+ * Core validation logic used by both validate and pre-commit commands.
5
+ * Handles caching, history recording, and output formatting.
6
+ */
7
+ import { runValidation } from '@vibe-validate/core';
8
+ import { getGitTreeHash } from '@vibe-validate/git';
9
+ import { recordValidationHistory, checkWorktreeStability, checkHistoryHealth, readHistoryNote, } from '@vibe-validate/history';
10
+ import { createRunnerConfig } from './runner-adapter.js';
11
+ import chalk from 'chalk';
12
+ import { stringify as yamlStringify } from 'yaml';
13
+ /**
14
+ * Execute validation workflow with caching, history recording, and output formatting.
15
+ *
16
+ * This is the shared implementation used by both `validate` and `pre-commit` commands.
17
+ *
18
+ * @param config - Loaded vibe-validate configuration
19
+ * @param options - Validation options (force, verbose, yaml, check, context)
20
+ * @returns Validation result
21
+ * @throws Error if validation encounters fatal error
22
+ */
23
+ export async function runValidateWorkflow(config, options) {
24
+ try {
25
+ // If --check flag is used, only check validation state without running
26
+ if (options.check) {
27
+ const yaml = options.yaml ?? false;
28
+ const { checkValidationStatus } = await import('./check-validation.js');
29
+ await checkValidationStatus(config, yaml);
30
+ // checkValidationStatus calls process.exit, so this line never executes
31
+ // But TypeScript doesn't know that, so we need to satisfy the return type
32
+ throw new Error('checkValidationStatus should have exited');
33
+ }
34
+ const verbose = options.verbose ?? false;
35
+ const yaml = options.yaml ?? false;
36
+ // Create runner config
37
+ const runnerConfig = createRunnerConfig(config, {
38
+ force: options.force,
39
+ verbose,
40
+ yaml,
41
+ context: options.context,
42
+ });
43
+ // Get tree hash BEFORE validation (for caching and stability check)
44
+ let treeHashBefore = null;
45
+ try {
46
+ treeHashBefore = await getGitTreeHash();
47
+ }
48
+ catch (_error) {
49
+ // Not in git repo or git command failed - continue without history
50
+ if (verbose) {
51
+ console.warn(chalk.yellow('⚠️ Could not get git tree hash - history recording disabled'));
52
+ }
53
+ }
54
+ // Check cache: if validation already passed for this tree hash, skip re-running
55
+ if (treeHashBefore && !options.force) {
56
+ try {
57
+ const historyNote = await readHistoryNote(treeHashBefore);
58
+ if (historyNote && historyNote.runs.length > 0) {
59
+ // Find most recent passing run
60
+ const passingRun = [...historyNote.runs]
61
+ .reverse()
62
+ .find(run => run.passed);
63
+ if (passingRun) {
64
+ if (yaml) {
65
+ // YAML mode: Output cached result as YAML to stdout
66
+ await new Promise(resolve => setTimeout(resolve, 10));
67
+ // Output YAML document separator (RFC 4627)
68
+ process.stdout.write('---\n');
69
+ process.stdout.write(yamlStringify(passingRun.result));
70
+ // Wait for stdout to flush before exiting
71
+ await new Promise(resolve => {
72
+ if (process.stdout.write('')) {
73
+ resolve();
74
+ }
75
+ else {
76
+ process.stdout.once('drain', resolve);
77
+ }
78
+ });
79
+ }
80
+ else {
81
+ // Human-readable mode: Display cache hit message
82
+ const durationSecs = (passingRun.duration / 1000).toFixed(1);
83
+ console.log(chalk.green('✅ Validation already passed for current working tree'));
84
+ console.log(chalk.gray(` Tree hash: ${treeHashBefore.substring(0, 12)}...`));
85
+ console.log(chalk.gray(` Last validated: ${passingRun.timestamp}`));
86
+ console.log(chalk.gray(` Duration: ${durationSecs}s`));
87
+ console.log(chalk.gray(` Branch: ${passingRun.branch}`));
88
+ if (passingRun.result?.phases) {
89
+ const totalSteps = passingRun.result.phases.reduce((sum, phase) => sum + (phase.steps?.length || 0), 0);
90
+ console.log(chalk.gray(` Phases: ${passingRun.result.phases.length}, Steps: ${totalSteps}`));
91
+ }
92
+ }
93
+ // Cache hit - return early without calling process.exit
94
+ // This allows tests to complete without throwing process.exit errors
95
+ // In production, Commander will exit with code 0
96
+ // Mark result as from cache so caller knows not to call process.exit
97
+ const result = passingRun.result;
98
+ result._fromCache = true;
99
+ return result;
100
+ }
101
+ }
102
+ }
103
+ catch (_error) {
104
+ // Cache check failed - proceed with validation
105
+ // This is expected for first-time validation
106
+ }
107
+ }
108
+ // Display tree hash before running validation (debugging/transparency aid)
109
+ // This goes to stderr, so it's visible even in YAML mode
110
+ if (treeHashBefore) {
111
+ console.error(chalk.gray(`🌳 Working tree: ${treeHashBefore.slice(0, 12)}...`));
112
+ if (!yaml) {
113
+ console.log(''); // Blank line for readability (human mode only)
114
+ }
115
+ }
116
+ // Run validation
117
+ const result = await runValidation(runnerConfig);
118
+ // Record validation history (if in git repo and stability check passes)
119
+ if (treeHashBefore) {
120
+ try {
121
+ // Check if worktree changed during validation
122
+ const stability = await checkWorktreeStability(treeHashBefore);
123
+ if (!stability.stable) {
124
+ console.warn(chalk.yellow('\n⚠️ Worktree changed during validation'));
125
+ console.warn(chalk.yellow(` Before: ${stability.treeHashBefore.slice(0, 12)}...`));
126
+ console.warn(chalk.yellow(` After: ${stability.treeHashAfter.slice(0, 12)}...`));
127
+ console.warn(chalk.yellow(' Results valid but history not recorded (unstable state)'));
128
+ }
129
+ else {
130
+ // Record to git notes
131
+ const recordResult = await recordValidationHistory(treeHashBefore, result);
132
+ if (recordResult.recorded) {
133
+ if (verbose) {
134
+ console.log(chalk.gray(`\n📝 History recorded (tree: ${treeHashBefore.slice(0, 12)})`));
135
+ }
136
+ }
137
+ else if (verbose) {
138
+ console.warn(chalk.yellow(`⚠️ History recording failed: ${recordResult.reason}`));
139
+ }
140
+ }
141
+ }
142
+ catch (error) {
143
+ // Silent failure - don't block validation
144
+ if (verbose) {
145
+ const errorMessage = error instanceof Error ? error.message : String(error);
146
+ console.warn(chalk.yellow(`⚠️ History recording error: ${errorMessage}`));
147
+ }
148
+ }
149
+ }
150
+ // Proactive health check (non-blocking)
151
+ try {
152
+ const health = await checkHistoryHealth();
153
+ if (health.shouldWarn) {
154
+ console.log('');
155
+ console.log(chalk.blue(health.warningMessage));
156
+ }
157
+ }
158
+ catch {
159
+ // Silent failure - don't block validation
160
+ }
161
+ // If validation failed, show agent-friendly error details
162
+ if (!result.passed) {
163
+ console.error(chalk.blue('\n📋 View error details:'), chalk.white('vibe-validate state'));
164
+ if (result.rerunCommand) {
165
+ console.error(chalk.blue('🔄 To retry:'), chalk.white(result.rerunCommand));
166
+ }
167
+ if (result.fullLogFile) {
168
+ console.error(chalk.blue('📄 Full log:'), chalk.gray(result.fullLogFile));
169
+ }
170
+ // Context-aware extraction quality feedback (only when developerFeedback is enabled)
171
+ if (config.developerFeedback) {
172
+ // Check if any steps had poor extraction quality
173
+ const poorExtractionSteps = result.phases
174
+ ?.flatMap(phase => phase.steps || [])
175
+ .filter(step => !step.passed && step.extractionQuality && step.extractionQuality.score < 50);
176
+ if (poorExtractionSteps && poorExtractionSteps.length > 0) {
177
+ // Detect if we're dogfooding (in the vibe-validate project itself)
178
+ const isDogfooding = process.cwd().includes('vibe-validate');
179
+ console.error('');
180
+ console.error(chalk.yellow('⚠️ Poor extraction quality detected'));
181
+ if (isDogfooding) {
182
+ // Developing vibe-validate itself: direct contributor call-to-action
183
+ console.error(chalk.yellow(' 💡 vibe-validate improvement opportunity: Improve extractors in packages/extractors/'));
184
+ console.error(chalk.gray(' See packages/extractors/test/samples/ for how to add test cases'));
185
+ }
186
+ else {
187
+ // External project: user feedback to improve vibe-validate
188
+ console.error(chalk.yellow(' 💡 Help improve vibe-validate by reporting this extraction issue'));
189
+ console.error(chalk.gray(' https://github.com/anthropics/vibe-validate/issues/new?template=extractor-improvement.yml'));
190
+ }
191
+ }
192
+ }
193
+ }
194
+ // Output YAML validation result if --yaml flag is set
195
+ if (yaml) {
196
+ // Small delay to ensure stderr is flushed before writing to stdout
197
+ await new Promise(resolve => setTimeout(resolve, 10));
198
+ // Output YAML document separator (RFC 4627) to mark transition from stderr to stdout
199
+ process.stdout.write('---\n');
200
+ // Output pure YAML without headers (workflow provides display framing)
201
+ process.stdout.write(yamlStringify(result));
202
+ // CRITICAL: Wait for stdout to flush before exiting
203
+ // When stdout is redirected to a file (CI), process.exit() can kill the process
204
+ // before the write buffer is flushed, causing truncated output
205
+ await new Promise(resolve => {
206
+ if (process.stdout.write('')) {
207
+ // Write buffer is empty, can exit immediately
208
+ resolve();
209
+ }
210
+ else {
211
+ // Wait for drain event
212
+ process.stdout.once('drain', resolve);
213
+ }
214
+ });
215
+ }
216
+ return result;
217
+ }
218
+ catch (error) {
219
+ console.error(chalk.red('❌ Validation failed with error:'), error);
220
+ // If YAML mode, output error as YAML to stdout for CI extraction
221
+ if (options.yaml) {
222
+ const errorResult = {
223
+ passed: false,
224
+ timestamp: new Date().toISOString(),
225
+ error: error instanceof Error ? error.message : String(error),
226
+ errorStack: error instanceof Error ? error.stack : undefined,
227
+ };
228
+ // Small delay to ensure stderr is flushed before writing to stdout
229
+ await new Promise(resolve => setTimeout(resolve, 10));
230
+ // Output YAML document separator
231
+ process.stdout.write('---\n');
232
+ process.stdout.write(yamlStringify(errorResult));
233
+ // Wait for stdout to flush before exiting
234
+ await new Promise(resolve => {
235
+ if (process.stdout.write('')) {
236
+ resolve();
237
+ }
238
+ else {
239
+ process.stdout.once('drain', resolve);
240
+ }
241
+ });
242
+ }
243
+ // Re-throw to allow caller to handle exit
244
+ throw error;
245
+ }
246
+ }
247
+ //# sourceMappingURL=validate-workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-workflow.js","sourceRoot":"","sources":["../../src/utils/validate-workflow.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,kBAAkB,EAClB,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAUlD;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAA0B,EAC1B,OAAgC;IAEhC,IAAI,CAAC;QACH,uEAAuE;QACvE,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC;YACnC,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;YACxE,MAAM,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC1C,wEAAwE;YACxE,0EAA0E;YAC1E,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC;QACzC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC;QAEnC,uBAAuB;QACvB,MAAM,YAAY,GAAG,kBAAkB,CAAC,MAAM,EAAE;YAC9C,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,OAAO;YACP,IAAI;YACJ,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAC;QAEH,oEAAoE;QACpE,IAAI,cAAc,GAAkB,IAAI,CAAC;QACzC,IAAI,CAAC;YACH,cAAc,GAAG,MAAM,cAAc,EAAE,CAAC;QAC1C,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YAChB,mEAAmE;YACnE,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,8DAA8D,CAAC,CAAC,CAAC;YAC7F,CAAC;QACH,CAAC;QAED,gFAAgF;QAChF,IAAI,cAAc,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACrC,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,cAAc,CAAC,CAAC;gBAE1D,IAAI,WAAW,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC/C,+BAA+B;oBAC/B,MAAM,UAAU,GAAG,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC;yBACrC,OAAO,EAAE;yBACT,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBAE3B,IAAI,UAAU,EAAE,CAAC;wBACf,IAAI,IAAI,EAAE,CAAC;4BACT,oDAAoD;4BACpD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;4BAEtD,4CAA4C;4BAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;4BAE9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;4BAEvD,0CAA0C;4BAC1C,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;gCAChC,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;oCAC7B,OAAO,EAAE,CAAC;gCACZ,CAAC;qCAAM,CAAC;oCACN,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gCACxC,CAAC;4BACH,CAAC,CAAC,CAAC;wBACL,CAAC;6BAAM,CAAC;4BACN,iDAAiD;4BACjD,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;4BAC7D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC,CAAC;4BACjF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,cAAc,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;4BAC/E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;4BACtE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,YAAY,GAAG,CAAC,CAAC,CAAC;4BACzD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;4BAE3D,IAAI,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;gCAC9B,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gCACxG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,YAAY,UAAU,EAAE,CAAC,CAAC,CAAC;4BACjG,CAAC;wBACH,CAAC;wBAED,wDAAwD;wBACxD,qEAAqE;wBACrE,iDAAiD;wBACjD,qEAAqE;wBACrE,MAAM,MAAM,GAAG,UAAU,CAAC,MAAqD,CAAC;wBAChF,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC;wBACzB,OAAO,MAAM,CAAC;oBAChB,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,MAAM,EAAE,CAAC;gBAChB,+CAA+C;gBAC/C,6CAA6C;YAC/C,CAAC;QACH,CAAC;QAED,2EAA2E;QAC3E,yDAAyD;QACzD,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;YAChF,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,+CAA+C;YAClE,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC,CAAC;QAEjD,wEAAwE;QACxE,IAAI,cAAc,EAAE,CAAC;YACnB,IAAI,CAAC;gBACH,8CAA8C;gBAC9C,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,cAAc,CAAC,CAAC;gBAE/D,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;oBACtB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,0CAA0C,CAAC,CAAC,CAAC;oBACvE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;oBACrF,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;oBACpF,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,4DAA4D,CAAC,CAAC,CAAC;gBAC3F,CAAC;qBAAM,CAAC;oBACN,sBAAsB;oBACtB,MAAM,YAAY,GAAG,MAAM,uBAAuB,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;oBAE3E,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;wBAC1B,IAAI,OAAO,EAAE,CAAC;4BACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;wBAC1F,CAAC;oBACH,CAAC;yBAAM,IAAI,OAAO,EAAE,CAAC;wBACnB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,iCAAiC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;oBACrF,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,0CAA0C;gBAC1C,IAAI,OAAO,EAAE,CAAC;oBACZ,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAC5E,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,gCAAgC,YAAY,EAAE,CAAC,CAAC,CAAC;gBAC7E,CAAC;YACH,CAAC;QACH,CAAC;QAED,wCAAwC;QACxC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;YAC1C,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,0CAA0C;QAC5C,CAAC;QAED,0DAA0D;QAC1D,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;YAC1F,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;gBACxB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;YAC9E,CAAC;YACD,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;gBACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;YAC5E,CAAC;YAED,qFAAqF;YACrF,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;gBAC7B,iDAAiD;gBACjD,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM;oBACvC,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;qBACpC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,iBAAiB,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;gBAE/F,IAAI,mBAAmB,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1D,mEAAmE;oBACnE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;oBAE7D,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBAClB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,sCAAsC,CAAC,CAAC,CAAC;oBAEpE,IAAI,YAAY,EAAE,CAAC;wBACjB,qEAAqE;wBACrE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,yFAAyF,CAAC,CAAC,CAAC;wBACvH,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC,CAAC;oBAClG,CAAC;yBAAM,CAAC;wBACN,2DAA2D;wBAC3D,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,qEAAqE,CAAC,CAAC,CAAC;wBACnG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,8FAA8F,CAAC,CAAC,CAAC;oBAC5H,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,sDAAsD;QACtD,IAAI,IAAI,EAAE,CAAC;YACT,mEAAmE;YACnE,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;YAEtD,qFAAqF;YACrF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAE9B,uEAAuE;YACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;YAE5C,oDAAoD;YACpD,gFAAgF;YAChF,+DAA+D;YAC/D,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;gBAChC,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC7B,8CAA8C;oBAC9C,OAAO,EAAE,CAAC;gBACZ,CAAC;qBAAM,CAAC;oBACN,uBAAuB;oBACvB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACxC,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,EAAE,KAAK,CAAC,CAAC;QAEnE,iEAAiE;QACjE,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,WAAW,GAAG;gBAClB,MAAM,EAAE,KAAK;gBACb,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;gBAC7D,UAAU,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;aAC7D,CAAC;YAEF,mEAAmE;YACnE,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;YAEtD,iCAAiC;YACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC;YAEjD,0CAA0C;YAC1C,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;gBAChC,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC7B,OAAO,EAAE,CAAC;gBACZ,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACxC,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,0CAA0C;QAC1C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Validation Cache Utility
3
+ *
4
+ * Provides git tree hash-based caching for validation results.
5
+ * Used by both validate and pre-commit commands to avoid redundant validation.
6
+ */
7
+ import type { ValidationResult } from '@vibe-validate/core';
8
+ export interface CacheCheckResult {
9
+ /** Whether a cached passing result was found */
10
+ cacheHit: boolean;
11
+ /** The git tree hash that was checked */
12
+ treeHash: string | null;
13
+ /** The cached validation result (if cache hit) */
14
+ cachedResult?: ValidationResult;
15
+ /** Metadata about the cached run */
16
+ cachedRun?: {
17
+ timestamp: string;
18
+ duration: number;
19
+ branch: string;
20
+ };
21
+ }
22
+ /**
23
+ * Check if validation has already passed for the current working tree.
24
+ * Returns cache hit info including the cached result if found.
25
+ *
26
+ * @param force - If true, bypass cache and force re-validation
27
+ * @returns Cache check result with tree hash and optional cached result
28
+ */
29
+ export declare function checkValidationCache(force?: boolean): Promise<CacheCheckResult>;
30
+ //# sourceMappingURL=validation-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-cache.d.ts","sourceRoot":"","sources":["../../src/utils/validation-cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,QAAQ,EAAE,OAAO,CAAC;IAElB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,kDAAkD;IAClD,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAEhC,oCAAoC;IACpC,SAAS,CAAC,EAAE;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,UAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2CnF"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Validation Cache Utility
3
+ *
4
+ * Provides git tree hash-based caching for validation results.
5
+ * Used by both validate and pre-commit commands to avoid redundant validation.
6
+ */
7
+ import { getGitTreeHash } from '@vibe-validate/git';
8
+ import { readHistoryNote } from '@vibe-validate/history';
9
+ /**
10
+ * Check if validation has already passed for the current working tree.
11
+ * Returns cache hit info including the cached result if found.
12
+ *
13
+ * @param force - If true, bypass cache and force re-validation
14
+ * @returns Cache check result with tree hash and optional cached result
15
+ */
16
+ export async function checkValidationCache(force = false) {
17
+ // Get tree hash for current working directory
18
+ let treeHash = null;
19
+ try {
20
+ treeHash = await getGitTreeHash();
21
+ }
22
+ catch (_error) {
23
+ // Not in git repo or git command failed
24
+ return { cacheHit: false, treeHash: null };
25
+ }
26
+ // If force flag set, skip cache check
27
+ if (force) {
28
+ return { cacheHit: false, treeHash };
29
+ }
30
+ // Check git notes for cached validation result
31
+ try {
32
+ const historyNote = await readHistoryNote(treeHash);
33
+ if (historyNote && historyNote.runs.length > 0) {
34
+ // Find most recent passing run
35
+ const passingRun = [...historyNote.runs]
36
+ .reverse()
37
+ .find(run => run.passed);
38
+ if (passingRun && passingRun.result) {
39
+ return {
40
+ cacheHit: true,
41
+ treeHash,
42
+ cachedResult: passingRun.result,
43
+ cachedRun: {
44
+ timestamp: passingRun.timestamp,
45
+ duration: passingRun.duration,
46
+ branch: passingRun.branch,
47
+ },
48
+ };
49
+ }
50
+ }
51
+ }
52
+ catch (_error) {
53
+ // Cache read failed - proceed without cache
54
+ }
55
+ return { cacheHit: false, treeHash };
56
+ }
57
+ //# sourceMappingURL=validation-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-cache.js","sourceRoot":"","sources":["../../src/utils/validation-cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAqBzD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAK,GAAG,KAAK;IACtD,8CAA8C;IAC9C,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,cAAc,EAAE,CAAC;IACpC,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,wCAAwC;QACxC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED,sCAAsC;IACtC,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IACvC,CAAC;IAED,+CAA+C;IAC/C,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;QAEpD,IAAI,WAAW,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/C,+BAA+B;YAC/B,MAAM,UAAU,GAAG,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC;iBACrC,OAAO,EAAE;iBACT,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAE3B,IAAI,UAAU,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;gBACpC,OAAO;oBACL,QAAQ,EAAE,IAAI;oBACd,QAAQ;oBACR,YAAY,EAAE,UAAU,CAAC,MAAM;oBAC/B,SAAS,EAAE;wBACT,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,QAAQ,EAAE,UAAU,CAAC,QAAQ;wBAC7B,MAAM,EAAE,UAAU,CAAC,MAAM;qBAC1B;iBACF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,4CAA4C;IAC9C,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACvC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-validate/cli",
3
- "version": "0.11.0",
3
+ "version": "0.12.1",
4
4
  "description": "Command-line interface for vibe-validate validation framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -59,9 +59,11 @@
59
59
  "yaml": "^2.6.1",
60
60
  "zod": "^3.24.1",
61
61
  "zod-to-json-schema": "^3.24.6",
62
- "@vibe-validate/config": "0.11.0",
63
- "@vibe-validate/git": "0.11.0",
64
- "@vibe-validate/core": "0.11.0"
62
+ "@vibe-validate/config": "0.12.1",
63
+ "@vibe-validate/git": "0.12.1",
64
+ "@vibe-validate/core": "0.12.1",
65
+ "@vibe-validate/extractors": "0.12.1",
66
+ "@vibe-validate/history": "0.12.1"
65
67
  },
66
68
  "devDependencies": {
67
69
  "@types/node": "^20.14.8",
@@ -103,7 +103,7 @@
103
103
  "errorSummary": {
104
104
  "type": "string"
105
105
  },
106
- "stateFile": {
106
+ "validationResult": {
107
107
  "type": "object",
108
108
  "properties": {
109
109
  "passed": {