From 1b619518469a1024f4f2d67ed0c6c9d2e510688b Mon Sep 17 00:00:00 2001 From: carlos-alm <127798846+carlos-alm@users.noreply.github.com> Date: Wed, 25 Mar 2026 15:57:05 -0600 Subject: [PATCH 1/2] chore: add benchmark npm script and stale embeddings warning Add `npm run benchmark` script to make benchmark execution discoverable instead of requiring manual `node --import ./scripts/ts-resolve-loader.js` invocation. Warn users when embeddings predate the last graph rebuild so they know to re-run `codegraph embed` for fresh search results. Impact: 1 functions changed, 8 affected --- package.json | 1 + src/domain/graph/builder/stages/finalize.ts | 28 +++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/package.json b/package.json index 97fe7551..e2b082ad 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true});require('fs').rmSync('.tsbuildinfo',{force:true})\"", "prepare": "npm run build:wasm && npm run build && husky && npm run deps:tree", "deps:tree": "node scripts/node-ts.js scripts/gen-deps.ts", + "benchmark": "node --experimental-strip-types --import ./scripts/ts-resolve-loader.js scripts/benchmark.ts", "release": "commit-and-tag-version", "release:dry-run": "commit-and-tag-version --dry-run", "version": "node scripts/node-ts.js scripts/sync-native-versions.ts && git add package.json crates/codegraph-core/Cargo.toml" diff --git a/src/domain/graph/builder/stages/finalize.ts b/src/domain/graph/builder/stages/finalize.ts index 90d23757..6e09b999 100644 --- a/src/domain/graph/builder/stages/finalize.ts +++ b/src/domain/graph/builder/stages/finalize.ts @@ -83,6 +83,34 @@ export async function finalize(ctx: PipelineContext): Promise { } } + // Stale embeddings warning (built before last graph rebuild) + if (hasEmbeddings) { + try { + const embedBuiltAt = ( + db.prepare("SELECT value FROM embedding_meta WHERE key = 'built_at'").get() as + | { value: string } + | undefined + )?.value; + if (embedBuiltAt) { + const embedTime = new Date(embedBuiltAt).getTime(); + const now = Date.now(); + if (embedTime < now && !Number.isNaN(embedTime)) { + const prevBuildAt = getBuildMeta(db, 'built_at'); + if (prevBuildAt) { + const prevBuildTime = new Date(prevBuildAt).getTime(); + if (embedTime < prevBuildTime) { + warn( + 'Embeddings were built before the last graph rebuild. Run "codegraph embed" to update.', + ); + } + } + } + } + } catch { + /* ignore - embedding_meta table may not exist */ + } + } + // Unused exports warning try { const unusedCount = ( From 4157d7bb47bf5c60a98fa2546ef98bdd91ed7300 Mon Sep 17 00:00:00 2001 From: carlos-alm <127798846+carlos-alm@users.noreply.github.com> Date: Wed, 25 Mar 2026 16:52:09 -0600 Subject: [PATCH 2/2] fix: correct stale-embeddings off-by-one and simplify guards (#604) - Move setBuildMeta before stale-embeddings check so built_at reflects the current build, fixing the off-by-one where the warning fired one rebuild cycle late - Fix NaN-check order: validate embedTime before comparing - Remove redundant embedTime < now guard (always true for real timestamps) - Use single buildNow timestamp for both metadata and comparison Impact: 1 functions changed, 8 affected --- src/domain/graph/builder/stages/finalize.ts | 52 ++++++++++----------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/src/domain/graph/builder/stages/finalize.ts b/src/domain/graph/builder/stages/finalize.ts index 6e09b999..f40c5a97 100644 --- a/src/domain/graph/builder/stages/finalize.ts +++ b/src/domain/graph/builder/stages/finalize.ts @@ -37,6 +37,10 @@ export async function finalize(ctx: PipelineContext): Promise { symbols._langId = undefined; } + // Capture a single wall-clock timestamp for the current build — used for + // both the stale-embeddings comparison and the persisted built_at metadata. + const buildNow = new Date(); + const nodeCount = (db.prepare('SELECT COUNT(*) as c FROM nodes').get() as { c: number }).c; const actualEdgeCount = (db.prepare('SELECT COUNT(*) as c FROM edges').get() as { c: number }).c; info(`Graph built: ${nodeCount} nodes, ${actualEdgeCount} edges`); @@ -63,6 +67,22 @@ export async function finalize(ctx: PipelineContext): Promise { } } + // Persist build metadata early so downstream checks (e.g. stale-embeddings) + // can read the *current* build's built_at rather than the previous one. + try { + setBuildMeta(db, { + engine: ctx.engineName, + engine_version: ctx.engineVersion || '', + codegraph_version: CODEGRAPH_VERSION, + schema_version: String(schemaVersion), + built_at: buildNow.toISOString(), + node_count: nodeCount, + edge_count: actualEdgeCount, + }); + } catch (err) { + warn(`Failed to write build metadata: ${(err as Error).message}`); + } + // Orphaned embeddings warning if (hasEmbeddings) { try { @@ -83,7 +103,7 @@ export async function finalize(ctx: PipelineContext): Promise { } } - // Stale embeddings warning (built before last graph rebuild) + // Stale embeddings warning (built before current graph rebuild) if (hasEmbeddings) { try { const embedBuiltAt = ( @@ -93,17 +113,10 @@ export async function finalize(ctx: PipelineContext): Promise { )?.value; if (embedBuiltAt) { const embedTime = new Date(embedBuiltAt).getTime(); - const now = Date.now(); - if (embedTime < now && !Number.isNaN(embedTime)) { - const prevBuildAt = getBuildMeta(db, 'built_at'); - if (prevBuildAt) { - const prevBuildTime = new Date(prevBuildAt).getTime(); - if (embedTime < prevBuildTime) { - warn( - 'Embeddings were built before the last graph rebuild. Run "codegraph embed" to update.', - ); - } - } + if (!Number.isNaN(embedTime) && embedTime < buildNow.getTime()) { + warn( + 'Embeddings were built before the last graph rebuild. Run "codegraph embed" to update.', + ); } } } catch { @@ -136,21 +149,6 @@ export async function finalize(ctx: PipelineContext): Promise { /* exported column may not exist on older DBs */ } - // Persist build metadata - try { - setBuildMeta(db, { - engine: ctx.engineName, - engine_version: ctx.engineVersion || '', - codegraph_version: CODEGRAPH_VERSION, - schema_version: String(schemaVersion), - built_at: new Date().toISOString(), - node_count: nodeCount, - edge_count: actualEdgeCount, - }); - } catch (err) { - warn(`Failed to write build metadata: ${(err as Error).message}`); - } - closeDb(db); // Write journal header after successful build