feat: pristine harness JSON interfaces and require-existing semantic mode (P2)

This commit is contained in:
2026-08-11 18:40:11 +02:00
parent 3cfc8c53e6
commit ca391ba59c
12 changed files with 1204 additions and 252 deletions
+74 -3
View File
@@ -1,5 +1,6 @@
from __future__ import annotations
import hashlib
import json
from datetime import UTC, datetime
from pathlib import Path
@@ -9,6 +10,7 @@ from typer.testing import CliRunner
from tht.cli import app
from tht.memory import MemoryRecord, save_registry
from tht.ports.vector import VectorStoreError
class _FakeEmbedder:
@@ -33,6 +35,10 @@ class _FakeVectorStore:
return 3
def _sha_file(path: Path) -> str:
return "sha256:" + hashlib.sha256(path.read_bytes()).hexdigest()
def _qdrant_runtime_config(tmp_path: Path) -> Path:
cfg = tmp_path / "workspace.yaml"
cfg.write_text(
@@ -76,9 +82,7 @@ tables:
type: bigint
"""
)
(tmp_path / "artifacts" / "mschema" / "annotations.yaml").write_text(
"tables: {}\n"
)
(tmp_path / "artifacts" / "mschema" / "annotations.yaml").write_text("tables: {}\n")
def _memory_record() -> MemoryRecord:
@@ -111,6 +115,73 @@ def test_vector_index_schema_accepts_qdrant_only_runtime_config(tmp_path, monkey
assert store.upserts
def test_vector_index_schema_json_is_pristine_and_reports_artifacts(tmp_path, monkeypatch):
cfg = _qdrant_runtime_config(tmp_path)
_write_schema_artifacts(tmp_path)
store = _FakeVectorStore()
monkeypatch.setattr("tht.adapters.factory.build_vector_store", lambda cfg, require_write: store)
monkeypatch.setattr("tht.cli.vector_cmd.make_embedder", lambda _: _FakeEmbedder())
response = CliRunner().invoke(app, ["vector", "index-schema", "--json", "-c", str(cfg)])
assert response.exit_code == 0, response.output
assert response.stderr == ""
assert json.loads(response.stdout) == {
"artifactIdentities": [
{
"digest": _sha_file(tmp_path / "artifacts" / "mschema" / "annotations.yaml"),
"kind": "schema_annotations",
},
{
"digest": _sha_file(tmp_path / "artifacts" / "mschema" / "physical.yaml"),
"kind": "physical_schema",
},
],
"code": "ok",
"collection": "psd-clinical",
"counts": {
"added": 2,
"columns": 1,
"deleted": 0,
"records": 2,
"tables": 1,
"unchanged": 0,
"updated": 0,
},
"operation": "index_schema",
"schemaVersion": 1,
"status": "succeeded",
"workspaceId": "psd-clinical",
"workspaceRevision": "a" * 40,
}
def test_vector_index_schema_json_failure_is_pristine(tmp_path, monkeypatch):
cfg = _qdrant_runtime_config(tmp_path)
_write_schema_artifacts(tmp_path)
def boom(cfg, require_write):
raise VectorStoreError("semantic_index_incompatible")
monkeypatch.setattr("tht.adapters.factory.build_vector_store", boom)
monkeypatch.setattr("tht.cli.vector_cmd.make_embedder", lambda _: _FakeEmbedder())
response = CliRunner().invoke(app, ["vector", "index-schema", "--json", "-c", str(cfg)])
assert response.exit_code == 1
assert response.stderr == ""
assert json.loads(response.stdout) == {
"code": "semantic_index_incompatible",
"error": "semantic index incompatible",
"operation": "index_schema",
"schemaVersion": 1,
"status": "failed",
"workspaceId": "psd-clinical",
"workspaceRevision": "a" * 40,
}
def test_memory_promote_accepts_qdrant_only_runtime_config(tmp_path, monkeypatch):
cfg = _qdrant_runtime_config(tmp_path)
store = _FakeVectorStore()