- Label: bug
- Severity: degrades quality (silent graph/repo drift under interrupt/kill mid-index)
- Location:
internal/analyzers/index.go IndexFile:
if err := st.ReplaceFileEdges(path, nil); err != nil { ... }
if err := st.ReplaceFileSymbols(path, symbols); err != nil { ... }
if err := st.ReplaceFileImports(path, imports); err != nil { ... }
if err := indexCodeEdges(st, path, content, lang); err != nil { ... }
Each ReplaceFile* / edge write opens its own Begin/Commit (internal/store/file_graph.go); there is no Store.WithTx wrapping the full IndexFile unit.
- Expected: File-local index updates are atomic per path (edges+symbols+imports commit together), matching “incremental / no silent corruption” design.
- Actual: A process kill, OS crash, or hard error after
ReplaceFileEdges(path, nil) and before indexCodeEdges leaves that file with no outgoing code_edges while symbols/imports may be partially updated. Empty-argv trace index walks the whole tree and hits this path for every file (see next finding), amplifying exposure.
- Repro (conceptual): index a Go file, interrupt the process after edge clear (or inject failure between the calls); query outgoing edges for that path — empty/incomplete until reindex completes.
Audited tip: 6afe0fd (main). Filed from independent Phase 1 code audit 2026-09-19.
internal/analyzers/index.goIndexFile:ReplaceFile*/ edge write opens its ownBegin/Commit(internal/store/file_graph.go); there is noStore.WithTxwrapping the full IndexFile unit.ReplaceFileEdges(path, nil)and beforeindexCodeEdgesleaves that file with no outgoing code_edges while symbols/imports may be partially updated. Empty-argvtrace indexwalks the whole tree and hits this path for every file (see next finding), amplifying exposure.Audited tip: 6afe0fd (main). Filed from independent Phase 1 code audit 2026-09-19.