fix(rag): make dim check robust to file locks (ignore_errors=True)

Replaces self.client.delete_collection(name) with shutil.rmtree on the
collection directory + recreate PersistentClient. This is more robust
to file locks (WinError 32 on Windows) where the live_gui subprocess
holds the file lock on the chroma collection.

The original delete_collection call fails on locked files, leaving the
collection in a broken state (dim mismatch) that causes subsequent
RAG searches to hang. shutil.rmtree with ignore_errors=True handles
this case more gracefully.

Note: This fix is an improvement but may not fully resolve the
test_rag_phase4_final_verify timeout in batched runs. The fundamental
issue is that the live_gui subprocess (session-scoped fixture) holds
file locks on the workspace's .slop_cache, and the test's pre-test
cleanup cannot remove locked files from the same process. A complete
fix would require either changing the fixture scope or implementing
a more sophisticated lock-handling strategy in the RAG engine.

Diagnosis documented in docs/reports/DIAGNOSIS_test_rag_phase4_final_verify.md.
This commit is contained in:
ed
2026-06-27 17:24:31 -04:00
parent 721449d6c6
commit 24e93a750f
2 changed files with 219 additions and 1 deletions
+10 -1
View File
@@ -15,6 +15,7 @@ from src.result_types import ErrorInfo, ErrorKind, NilRAGState, Result
from src.type_aliases import Metadata
from src.file_cache import ASTParser
import shutil
@dataclass(frozen=True)
@@ -195,7 +196,15 @@ class RAGEngine:
f"Recreating collection to prevent silent corruption.\n"
)
sys.stderr.flush()
self.client.delete_collection(self.collection.name)
# Per fix_test_rag_phase4_final_verify_diagnosis_20260627: shutil.rmtree with
# ignore_errors=True is more robust to file locks (WinError 32 on Windows) where
# the live_gui subprocess holds the file lock on the chroma collection. The
# original delete_collection call fails on locked files, leaving the collection
# in a broken state (dim mismatch) that causes subsequent RAG searches to hang.
db_path = os.path.abspath(os.path.join(self.base_dir, ".slop_cache", f"chroma_{self.collection.name}"))
if os.path.exists(db_path):
shutil.rmtree(db_path, ignore_errors=True)
self.client = chromadb.PersistentClient(path=os.path.dirname(db_path))
self.collection = self.client.get_or_create_collection(name=self.collection.name)
return Result(data=None)
except Exception as e: