feat: implement memory and evidence administration with guided repairs
Publish documentation / publish (push) Successful in 1m27s

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.
This commit is contained in:
Codex
2026-09-10 10:31:34 +02:00
parent 8fe526dd6e
commit 82e2c91f42
168 changed files with 11914 additions and 1772 deletions
+19 -6
View File
@@ -1,5 +1,6 @@
import json
import uuid
from contextlib import nullcontext
from datetime import UTC, datetime
from types import SimpleNamespace
@@ -7,7 +8,9 @@ from typer.testing import CliRunner
from tht.cli import app
from tht.decisions import DecisionInput
from tht.memory import MemoryRecord, recall_memories, save_registry
from tht.memory import MemoryRecord, recall_memories
from tht.memory.models import Card
from tht.memory.service import MemoryService
from tht.phase import current_phase
from tht.session.filesystem_repository import FilesystemSessionRepository
from tht.session.models import PrincipalContext, SessionManifest
@@ -42,7 +45,7 @@ class Searcher:
self.hits = hits
self.calls = []
def search(self, embedding, *, top_n, kinds):
def search(self, embedding, *, top_n, kinds, **kwargs):
self.calls.append((embedding, top_n, kinds))
return self.hits
@@ -145,11 +148,21 @@ def test_recall_cli_reconstructs_applied_and_rejected_memory_from_persisted_f2_s
records = [_memory("mem-0001"), _memory("mem-0003")]
searcher = Searcher([
SimpleNamespace(ref="mem-0003", similarity=0.9),
SimpleNamespace(ref="mem-0001", similarity=0.8),
SimpleNamespace(ref="mem-0003", similarity=0.9,
metadata={"memory_revision": "r", "memory_format": 2}),
SimpleNamespace(ref="mem-0001", similarity=0.8,
metadata={"memory_revision": "r", "memory_format": 2}),
])
embedder = Embedder()
save_registry(records, tmp_path / "artifacts" / "memory" / "registry.jsonl")
cards = {r.id: Card(id=r.id, family="domain_clarification", subject=r.subject,
detail=r.detail, scope="psd-clinical", workspace_id="psd-clinical", origin="workflow",
created_at=r.ts, updated_at=r.ts, revision="r", indexed=True) for r in records}
archive = SimpleNamespace(list=lambda query: {}, get=lambda identity: cards[identity],
close=lambda: None)
archive.operation = lambda: nullcontext(archive)
service = MemoryService(archive, PrincipalContext(issuer="local", subject="reviewer"),
store_factory=lambda: None, embedder_factory=Embedder)
monkeypatch.setattr("tht.cli.memory_cmd.memory_service", lambda cfg: service)
monkeypatch.setattr("tht.cli.vector_cmd.open_searcher", lambda cfg: searcher)
monkeypatch.setattr("tht.cli.vector_cmd.make_embedder", lambda cfg: embedder)
@@ -165,4 +178,4 @@ def test_recall_cli_reconstructs_applied_and_rejected_memory_from_persisted_f2_s
assert json.loads(response.stdout) == []
assert current_phase(repository.get(session_id)) == 2
assert embedder.questions == ["active patients"]
assert searcher.calls == [([0.1, 0.2], 5, ["memory"])]
assert searcher.calls == [([0.1, 0.2], 20, ["memory"])]