diff --git a/src/domain/graph/builder/pipeline.ts b/src/domain/graph/builder/pipeline.ts index 0d85751b..2f004526 100644 --- a/src/domain/graph/builder/pipeline.ts +++ b/src/domain/graph/builder/pipeline.ts @@ -88,10 +88,17 @@ function checkEngineSchemaMismatch(ctx: PipelineContext): void { ); ctx.forceFullRebuild = true; } + // When the native engine is active, the Rust addon's version (ctx.engineVersion) + // is written into codegraph_version by setBuildMeta after a native orchestrator + // build. The check must compare against the same version, otherwise JS and Rust + // fight over which version to record — causing every incremental build to be + // promoted to a full rebuild when npm and crate versions diverge. + const effectiveVersion = + ctx.engineName === 'native' && ctx.engineVersion ? ctx.engineVersion : CODEGRAPH_VERSION; const prevVersion = meta('codegraph_version'); - if (prevVersion && prevVersion !== CODEGRAPH_VERSION) { + if (prevVersion && prevVersion !== effectiveVersion) { info( - `Codegraph version changed (${prevVersion} → ${CODEGRAPH_VERSION}), promoting to full rebuild.`, + `Codegraph version changed (${prevVersion} → ${effectiveVersion}), promoting to full rebuild.`, ); ctx.forceFullRebuild = true; } @@ -631,10 +638,16 @@ async function tryNativeOrchestrator( const p = result.phases; // Sync build_meta so JS-side version/engine checks work on next build. + // Use the Rust addon version as codegraph_version when the native + // orchestrator performed the build — the Rust side's check_version_mismatch + // compares this value against CARGO_PKG_VERSION. Writing the JS + // CODEGRAPH_VERSION here would create a permanent mismatch whenever the + // npm package version diverges from the Rust crate version, forcing every + // subsequent native build to be a full rebuild (no incremental). setBuildMeta(ctx.db, { engine: ctx.engineName, engine_version: ctx.engineVersion || '', - codegraph_version: CODEGRAPH_VERSION, + codegraph_version: ctx.engineVersion || CODEGRAPH_VERSION, schema_version: String(ctx.schemaVersion), built_at: new Date().toISOString(), node_count: String(result.nodeCount ?? 0), diff --git a/src/domain/graph/builder/stages/finalize.ts b/src/domain/graph/builder/stages/finalize.ts index 857bbf40..7794d742 100644 --- a/src/domain/graph/builder/stages/finalize.ts +++ b/src/domain/graph/builder/stages/finalize.ts @@ -81,13 +81,20 @@ function persistBuildMetadata( ): void { const useNativeDb = ctx.engineName === 'native' && !!ctx.nativeDb; if (!ctx.isFullBuild && ctx.allSymbols.size <= 3) return; + // When the native engine is active, persist the Rust addon version so that + // checkEngineSchemaMismatch compares against the same value on the next build. + // Writing CODEGRAPH_VERSION (the npm package version) here would create a + // permanent mismatch whenever npm and crate versions diverge, forcing every + // subsequent build to be a full rebuild. + const codeVersionToWrite = + ctx.engineName === 'native' && ctx.engineVersion ? ctx.engineVersion : CODEGRAPH_VERSION; try { if (useNativeDb) { ctx.nativeDb!.setBuildMeta( Object.entries({ engine: ctx.engineName, - engine_version: CODEGRAPH_VERSION, - codegraph_version: CODEGRAPH_VERSION, + engine_version: codeVersionToWrite, + codegraph_version: codeVersionToWrite, schema_version: String(ctx.schemaVersion), built_at: buildNow.toISOString(), node_count: String(nodeCount), @@ -97,8 +104,8 @@ function persistBuildMetadata( } else { setBuildMeta(ctx.db, { engine: ctx.engineName, - engine_version: CODEGRAPH_VERSION, - codegraph_version: CODEGRAPH_VERSION, + engine_version: codeVersionToWrite, + codegraph_version: codeVersionToWrite, schema_version: String(ctx.schemaVersion), built_at: buildNow.toISOString(), node_count: nodeCount,