feat: P3 effective configuration, memory root, and revision-scoped records

This commit is contained in:
2026-08-12 16:01:25 +02:00
parent beaba548c1
commit e23e526966
21 changed files with 1108 additions and 44 deletions
+24 -2
View File
@@ -36,7 +36,10 @@ _KEYWORD_INDEXES = (
)
def point_id(workspace_id: str, kind: str, record_key: str) -> str:
def point_id(workspace_id: str, kind: str, record_key: str, workspace_revision: str | None = None) -> str:
# P3: schema/Evidence points are revision-scoped; memory/solved remain workspace-wide.
if workspace_revision is not None:
return str(uuid5(NAMESPACE_URL, f"thothii:{workspace_id}:{workspace_revision}:{kind}:{record_key}"))
return str(uuid5(NAMESPACE_URL, f"thothii:{workspace_id}:{kind}:{record_key}"))
@@ -63,6 +66,7 @@ class QdrantVectorStore:
self._base_url = base_url.rstrip("/")
self._collection = collection
self._workspace_id = workspace_id
self._workspace_revision = None
self._workspace_revision = workspace_revision
self._expected_dimension = expected_dimension
self._collection_lifecycle = collection_lifecycle
@@ -127,6 +131,7 @@ class QdrantVectorStore:
if not allowed_record_kinds:
return []
filter_must = self._workspace_filter()
filter_must.extend(self._revision_filter(allowed_record_kinds))
filter_must.append(self._semantic_kind_filter(allowed_record_kinds))
filter_must.append({"key": "record_kind", "match": {"any": allowed_record_kinds}})
if metadata_filter is not None:
@@ -195,7 +200,12 @@ class QdrantVectorStore:
semantic_kind = qdrant_semantic_kind(write_record.record.kind)
points.append(
{
"id": point_id(self._workspace_id, semantic_kind, write_record.record.id),
"id": point_id(
self._workspace_id,
semantic_kind,
write_record.record.id,
self._workspace_revision if semantic_kind in ("schema_table", "schema_column", "evidence") else None,
),
"vector": write_record.embedding,
"payload": qdrant_payload(
write_record.record,
@@ -275,10 +285,22 @@ class QdrantVectorStore:
def _workspace_filter(self) -> list[dict]:
return [{"key": "workspace_id", "match": {"value": self._workspace_id}}]
def _revision_filter(self, kinds: list[str]) -> list[dict]:
if self._workspace_revision is None:
return []
if not any(kind in ("schema_table", "schema_column", "evidence") for kind in kinds):
return []
return [{"key": "workspace_revision", "match": {"value": self._workspace_revision}}]
def _semantic_kind_filter(self, record_kinds: list[str]) -> dict:
semantic_kinds = sorted({qdrant_semantic_kind(kind) for kind in record_kinds})
return {"key": "kind", "match": {"any": semantic_kinds}}
def bind_workspace_revision(self, workspace_revision: str) -> None:
if not re.fullmatch(r"[0-9a-f]{40}", workspace_revision):
raise VectorStoreError("workspace revision is invalid")
self._workspace_revision = workspace_revision
def _require_bound_workspace(self, workspace_id: str) -> None:
if workspace_id != self._workspace_id:
raise VectorStoreError("Evidence workspace namespace does not match bound workspace")