diff --git a/.changeset/fix-incremental-false-positive.md b/.changeset/fix-incremental-false-positive.md new file mode 100644 index 00000000..78bd7c36 --- /dev/null +++ b/.changeset/fix-incremental-false-positive.md @@ -0,0 +1,5 @@ +--- +"@stainless-code/codemap": patch +--- + +Fix incremental detection reporting unchanged files as "changed" on every run when the working tree has uncommitted modifications. `getChangedFiles` now compares content hashes against the index before including candidates, so only truly modified files enter the indexing pipeline. diff --git a/src/application/index-engine.ts b/src/application/index-engine.ts index 21a35940..a883edbc 100644 --- a/src/application/index-engine.ts +++ b/src/application/index-engine.ts @@ -126,23 +126,28 @@ export function getChangedFiles(db: CodemapDatabase): { .filter(Boolean) .map((line: string) => line.slice(3).trim()); - const indexedPaths = new Set(getAllFileHashes(db).keys()); - const allChanged = [...new Set([...diffFiles, ...statusFiles])].filter( + const existingHashes = getAllFileHashes(db); + const allCandidates = [...new Set([...diffFiles, ...statusFiles])].filter( (f) => { const ext = extname(f); - return ext in LANG_MAP || indexedPaths.has(f); + return ext in LANG_MAP || existingHashes.has(f); }, ); const changed: string[] = []; const deleted: string[] = []; - for (const f of allChanged) { + for (const f of allCandidates) { + const absPath = join(getProjectRoot(), f); + let source: string; try { - statSync(join(getProjectRoot(), f)); - changed.push(f); + source = readFileSync(absPath, "utf-8"); } catch { deleted.push(f); + continue; + } + if (existingHashes.get(f) !== hashContent(source)) { + changed.push(f); } }