Files
ThothII/harness/tests/test_qdrant_cli_commands.py
T
Codex 82e2c91f42
Publish documentation / publish (push) Successful in 1m27s
feat: implement memory and evidence administration with guided repairs
Add PostgreSQL-backed memory, editable evidence with source review and activation, and human-approved archive repairs across the harness, API, and UI. Include migrations, deployment support, regression coverage, and validation documentation.

Refresh permissions from validated session roles so existing administrator logins can access newly deployed archive management features.
2026-09-10 10:31:34 +02:00

228 lines
7.4 KiB
Python

from __future__ import annotations
import hashlib
import json
from pathlib import Path
from types import SimpleNamespace
import pytest
from typer.testing import CliRunner
from tht.cli import app
from tht.ports.vector import VectorStoreError
@pytest.fixture(autouse=True)
def _ignore_operator_profile(monkeypatch):
"""Exercise the self-contained server runtime fixture, not the developer's harness/.env."""
monkeypatch.delenv("THT_PROFILE", raising=False)
class _FakeEmbedder:
def embed_documents(self, documents):
return [[0.1] * 4 for _ in documents]
class _FakeVectorStore:
def __init__(self):
self.upserts = []
def existing_hashes(self, collection, kinds):
return {}
def delete_kinds(self, collection, kinds):
return 0
def upsert(self, collection, records):
self.upserts.append((collection, records))
return len(records)
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(
f"""
runtime_identity:
workspace_id: psd-clinical
workspace_revision: {'a' * 40}
dwh:
type: postgres_direct
connection: {{database: analytics, schema: mart, user: reader, password: secret}}
vectors:
type: qdrant
base_url: http://qdrant:6333
collection: psd-clinical
roots:
sessions: {tmp_path / 'sessions'}
artifacts: {tmp_path / 'artifacts'}
indexes: {tmp_path / 'indexes'}
catalog_metadata_snapshot: {tmp_path / 'catalog-metadata.json'}
embeddings:
provider: ollama_internal
base_url: http://embedding:11434
model: qwen3-embedding:0.6b
dim: 1024
"""
)
return cfg
def _write_catalog_snapshot(tmp_path: Path) -> None:
(tmp_path / "catalog-metadata.json").write_text(json.dumps({
"schemaVersion": 1,
"workspaceId": "psd-clinical",
"databaseId": "db-1",
"databaseName": "analytics",
"schemaName": "mart",
"metadataContentRevision": 1,
"tables": [{
"id": "table-1",
"name": "fact_patient",
"description": "Patients",
"descriptionSource": "curated",
"columns": [{
"id": "column-1",
"name": "id",
"ordinalPosition": 1,
"dataType": "bigint",
"isNullable": False,
"defaultExpression": None,
"primaryKeyPosition": 1,
"sensitive": False,
"description": None,
"descriptionSource": None,
}],
}],
"relationships": [],
}))
def test_vector_index_schema_accepts_qdrant_only_runtime_config(tmp_path, monkeypatch):
cfg = _qdrant_runtime_config(tmp_path)
_write_catalog_snapshot(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())
res = CliRunner().invoke(app, ["vector", "index-schema", "-c", str(cfg)])
assert res.exit_code == 0, res.output
assert store.upserts
def test_vector_index_schema_json_is_pristine_and_reports_artifacts(tmp_path, monkeypatch):
cfg = _qdrant_runtime_config(tmp_path)
_write_catalog_snapshot(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 / "catalog-metadata.json"),
"kind": "catalog_metadata_snapshot",
},
],
"code": "ok",
"collection": "psd-clinical",
"counts": {
"added": 2,
"columns": 1,
"deleted": 0,
"records": 2,
"relationships": 0,
"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_catalog_snapshot(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_adapts_qdrant_runtime_to_authoritative_service(tmp_path, monkeypatch):
cfg = _qdrant_runtime_config(tmp_path)
snapshot = object()
calls = []
service = SimpleNamespace(close=lambda: None, promote=lambda source, seqs:
calls.append((source, seqs)) or [{"indexed": True, "card": {"id": "mem-test"}}])
monkeypatch.setattr("tht.cli.memory_cmd.load_snapshot_or_exit", lambda cfg, session: snapshot)
monkeypatch.setattr("tht.cli.memory_cmd.memory_service", lambda cfg: service)
result = CliRunner().invoke(app, [
"memory", "promote", "--session", "s1", "--decision", "7", "--json", "-c", str(cfg),
])
assert result.exit_code == 0, result.output
assert json.loads(result.stdout)["indexed"] is True
assert calls == [(snapshot, [7])]
def test_memory_index_rebuilds_only_through_authoritative_service(tmp_path, monkeypatch):
cfg = _qdrant_runtime_config(tmp_path)
service = SimpleNamespace(close=lambda: None, rebuild=lambda: [{"indexed": True}])
monkeypatch.setattr("tht.cli.memory_cmd.memory_service", lambda cfg: service)
result = CliRunner().invoke(app, ["memory", "index", "--json", "-c", str(cfg)])
assert result.exit_code == 0, result.output
assert json.loads(result.stdout) == [{"indexed": True}]
def test_vector_help_exposes_only_the_supported_qdrant_command():
res = CliRunner().invoke(app, ["vector", "--help"])
assert res.exit_code == 0, res.output
assert "migrate" not in res.output
assert "init" not in res.output
assert "index-schema" in res.output
def test_vector_migrate_command_is_absent():
res = CliRunner().invoke(app, ["vector", "migrate", "--help"])
assert res.exit_code != 0
assert "No such command 'migrate'" in res.output
def test_memory_solved_index_help_uses_semantic_store_wording():
res = CliRunner().invoke(app, ["memory", "solved-index", "--help"])
assert res.exit_code == 0, res.output
assert "semantic" in res.output.lower() or "qdrant" in res.output.lower()
assert "vectordb" not in res.output.lower()