From 09392c81f79e4638049a7a841eef37776321e8ab Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 06:08:42 +0000 Subject: [PATCH] =?UTF-8?q?=E2=98=91=EF=B8=8F=20Optimize=20`vibe-check-run?= =?UTF-8?q?ner.js`=20with=20concurrent=20validation=20and=20stateful=20seg?= =?UTF-8?q?regation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 💡 What - Transitioned asynchronous `vibe-check-runner.js` validation tasks from an iteration-blocking `for...of` sequence to an overlapping `Promise.all` model. - Restructured `syncBenchmarks` mechanism to deduplicate payload analysis per root technology identifier, accumulating contextual documentation streams linearly prior to execution. - Extracted and isolated localized Git orchestration (i.e. `add`, `commit`, `push`) out of the concurrent resolution cycle into a sequential post-process block traversing an intermediate state repository (`filesToCommit`). - Refactored all synchronous `fs.existsSync` invocations occurring within non-blocking loop scopes to utilize the established `await fileOrDirExists` helper variant. - Upgraded standalone runner logic adhering to script isolation standards: exposed internal functions via the `export` keyword and bound terminal executions to `import.meta.url === pathToFileURL(process.argv[1]).href`. 💡 Why - Adheres directly to designated repository architecture bounds dictating that execution cycles manage concurrent tasks securely (via `Promise.all`) whilst restricting state-side operations (CLI invocations) to synchronous streams avoiding internal collision. - Deduplication prevents repetitive, overlapping AI payload requests, avoiding superfluous rate-limiting constraints whilst preserving broader benchmark generation context via concatenation. - Binds standard event loop isolation methodologies by averting sequential event thread blocking stemming from I/O calls (`fs.existsSync`). ✅ Verification - Validated abstract AST construction manually. - Ensured syntactic integrity of ECMAScript constructs executing `node -c vibe-check-runner.js`. - Passed pre-commit repository lifecycle execution using `python3 commit_verify.py`. ✨ Result - Execution logic is cleanly isolated from independent concurrent validation tasks, safeguarding asynchronous consistency and protecting internal git trees from race condition locking errors. Co-authored-by: beginwebdev2002 <102213457+beginwebdev2002@users.noreply.github.com> --- vibe-check-runner.js | 105 +++++++++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 34 deletions(-) diff --git a/vibe-check-runner.js b/vibe-check-runner.js index f56ee94..63864a8 100644 --- a/vibe-check-runner.js +++ b/vibe-check-runner.js @@ -9,7 +9,7 @@ const ai = new GoogleGenAI({ apiKey: process.env.GOOGLE_AI_API_KEY }); // Constants for scoring -async function fileOrDirExists(filePath) { +export async function fileOrDirExists(filePath) { try { await fsPromises.stat(filePath); return true; @@ -25,7 +25,7 @@ const SCORES = { EFFICIENCY: 10, }; -function getModifiedFiles() { +export function getModifiedFiles() { try { // In CI (daily run), check files modified in the last 24 hours. // We filter for non-empty lines that end in .md and are in frontend/ or backend/ @@ -43,7 +43,7 @@ function getModifiedFiles() { } } -async function syncBenchmarks(tech, mdContent, retries = 5, delay = 10000) { +export async function syncBenchmarks(tech, mdContent, retries = 5, delay = 10000) { try { const prompt = `Based on the following documentation:\n\n${mdContent}\n\n1. Generate a "Golden Prompt" (a comprehensive instruction for generating a typical module using this technology) in JSON format: {"golden_prompt": "...", "tech": "${tech}"}\n2. Generate a JSON Schema for TS-Morph AST validation rules enforcing DDD/FSD layers and strict typing for this technology. The generated JSON schema must explicitly follow a nested structure compatible with \`analyzeAST\`. Format: {"$schema": "...", "type": "object", "properties": {"forbidden_types": {"contains": {"enum": ["any"]}}}}.\n\nRespond strictly with ONLY a JSON array containing these two objects in order. No markdown wrappers.`; const response = await ai.models.generateContent({ @@ -85,7 +85,7 @@ async function syncBenchmarks(tech, mdContent, retries = 5, delay = 10000) { } } -async function simulateAIGeneration(goldenPrompt, tech, mdContent, retries = 5, delay = 10000) { +export async function simulateAIGeneration(goldenPrompt, tech, mdContent, retries = 5, delay = 10000) { try { const prompt = `${goldenPrompt}\n\nConstraints and instructions from the following documentation:\n\n${mdContent}\n\nGenerate ONLY raw code. No markdown formatting, no explanations.`; const response = await ai.models.generateContent({ @@ -110,7 +110,7 @@ async function simulateAIGeneration(goldenPrompt, tech, mdContent, retries = 5, } } -function analyzeAST(sourceFile, tech) { +export function analyzeAST(sourceFile, tech) { let score = { arch: SCORES.ARCH, type: SCORES.TYPE, @@ -222,7 +222,7 @@ function analyzeAST(sourceFile, tech) { return { total, breakdown: score }; } -async function runVibeCheck() { +export async function runVibeCheck() { console.log('Running Vibe-Check Runner...'); const modifiedFiles = getModifiedFiles(); @@ -241,12 +241,48 @@ async function runVibeCheck() { console.warn('Failed to configure git user. If running locally, this is expected.'); } + // Group files by tech + const filesByTech = {}; for (const file of modifiedFiles) { + let tech = ''; + if (file.includes('/angular/')) tech = 'angular'; + else if (file.includes('/nestjs/')) tech = 'nestjs'; + else if (file.includes('/typescript/')) tech = 'typescript'; + else if (file.includes('/express/')) tech = 'express'; + else if (file.includes('/nodejs/')) tech = 'nodejs'; + else { + const parts = file.split('/'); + if (parts.length > 1) tech = parts[1]; + } + if (tech) { + if (!filesByTech[tech]) filesByTech[tech] = []; + filesByTech[tech].push(file); + } + } + + // Deduplicate and process syncBenchmarks sequentially by technology + for (const [tech, files] of Object.entries(filesByTech)) { + console.log(`Syncing benchmarks for ${tech}...`); + let combinedMdContent = ''; + for (const file of files) { + if (await fileOrDirExists(file)) { + combinedMdContent += (await fsPromises.readFile(file, 'utf-8')) + '\n\n'; + } + } + if (combinedMdContent) { + await syncBenchmarks(tech, combinedMdContent); + } + } + + const filesToCommit = []; + + // Then process files concurrently + await Promise.all(modifiedFiles.map(async (file) => { console.log(`Processing ${file}...`); - if (!fs.existsSync(file)) { + if (!(await fileOrDirExists(file))) { console.log(`File ${file} does not exist. Skipping.`); - continue; + return; } let tech = ''; @@ -256,23 +292,17 @@ async function runVibeCheck() { else if (file.includes('/express/')) tech = 'express'; else if (file.includes('/nodejs/')) tech = 'nodejs'; else { - // Fallback const parts = file.split('/'); - if (parts.length > 1) { - tech = parts[1]; - } else { - continue; - } + if (parts.length > 1) tech = parts[1]; + else return; // Promise.all maps replace continue with return } const mdContent = await fsPromises.readFile(file, 'utf-8'); - await syncBenchmarks(tech, mdContent); - const suitePath = path.join('benchmarks', 'suites', `${tech}.json`); - if (!fs.existsSync(suitePath)) { + if (!(await fileOrDirExists(suitePath))) { console.log(`No benchmark suite found for ${tech}. Skipping.`); - continue; + return; } const suiteConfig = JSON.parse(await fsPromises.readFile(suitePath, 'utf-8')); @@ -281,7 +311,7 @@ async function runVibeCheck() { if (!generatedCode) { console.error(`Failed to generate code for ${tech}.`); - continue; + return; } const sourceFile = project.createSourceFile(`temp_${tech}.ts`, generatedCode, { overwrite: true }); @@ -299,20 +329,9 @@ async function runVibeCheck() { await fsPromises.writeFile(file, content); } - try { - execFileSync('git', ['add', file]); - try { execFileSync('sh', ['-c', 'git add benchmarks/suites/*.json benchmarks/criteria/*.json 2>/dev/null || true']); } catch (e) {} - // Only commit if there are changes (badge might already be there) - const status = execFileSync('git', ['status', '--porcelain'], { encoding: 'utf-8' }); - if (status.includes(file) || status.includes('benchmarks/')) { - execFileSync('git', ['commit', '-m', '[chore: benchmark-sync]']); - execFileSync('git', ['push', 'origin', 'HEAD:main']); - } else { - console.log(`Badge already present in ${file}, skipping commit.`); - } - } catch (err) { - console.error('Failed to commit or push:', err.message); - } + // Git operations are stateful and can conflict if run concurrently + // Therefore, we'll collect the files to be staged, and handle git operations after Promise.all + filesToCommit.push(file); } else { console.error(`❌ Validation failed for ${file}. Score below 95%.`); @@ -335,7 +354,25 @@ async function runVibeCheck() { process.exitCode = 1; } + })); // End Promise.all + + if (filesToCommit.length > 0) { + try { + execFileSync('git', ['add', ...filesToCommit]); + try { execFileSync('sh', ['-c', 'git add benchmarks/suites/*.json benchmarks/criteria/*.json 2>/dev/null || true']); } catch (e) {} + const status = execFileSync('git', ['status', '--porcelain'], { encoding: 'utf-8' }); + if (status.length > 0) { + execFileSync('git', ['commit', '-m', '[chore: benchmark-sync]']); + execFileSync('git', ['push', 'origin', 'HEAD:main']); + } + } catch (err) { + console.error('Failed to commit:', err.message); + } } } -runVibeCheck().catch(console.error); \ No newline at end of file +import { pathToFileURL } from 'node:url'; + +if (import.meta.url === pathToFileURL(process.argv[1]).href) { + runVibeCheck().catch(console.error); +} \ No newline at end of file