Files
ThothII/harness/tests/test_evidence_editable.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

131 lines
4.2 KiB
Python

import pytest
from tht.evidence.canonical import (
CuratedEvidence,
ManualEvidenceProvenance,
dump_curated_markdown,
parse_curated_markdown,
)
def unit(kind="domain", payload=None):
return CuratedEvidence.model_validate(
{
"schema_version": 4,
"id": "evidence:example",
"title": "Example",
"kind": kind,
"purposes": ["sql_generation"],
"language": "en",
"provenance": {"kind": "manual", "declared_by": "curator"},
"payload": payload or {"rule": "Count orders once, using their complete key."},
}
)
@pytest.mark.parametrize(
("kind", "payload"),
[
("domain", {"rule": "A rule.\n\n### Explanation\n\n- First line\n- Second line"}),
(
"glossary",
{
"definition": "A patient.",
"synonyms": ["person", "a\nmultiline synonym"],
"variants": [],
},
),
(
"enum",
{
"column": "sales.orders.status",
"values": {"": "Unknown", "A": "Active\n\nwith details"},
},
),
("example", {"question": "How many?", "interpretation": "Count distinct orders."}),
(
"mapping",
{"concept": "Orders", "tables": ["sales.orders"], "columns": ["sales.orders.id"]},
),
("normalization", {"input": "A", "output": "active", "rule": "Expand the abbreviation."}),
("formula", {"concept": "Total", "columns": ["sales.lines.amount"], "sql": "sum(amount)"}),
(
"reference",
{"url": "https://example.test/rule", "label": "Policy", "description": "Rule source."},
),
],
)
def test_editable_round_trip_preserves_every_typed_payload(kind, payload):
original = unit(kind, payload)
rendered = dump_curated_markdown(original)
assert parse_curated_markdown(rendered) == original
assert "<!-- tht:" not in rendered
assert "payload:" not in rendered
def test_visible_edit_is_the_only_authoritative_text():
original = unit()
edited = dump_curated_markdown(original).replace(
"Count orders once, using their complete key.", "Use order ID and year."
)
parsed = parse_curated_markdown(edited)
assert parsed.payload.rule == "Use order ID and year."
assert parsed.id == original.id
def test_manual_file_needs_no_source_document_hash_or_encoded_metadata():
text = """---
schema_version: 4
id: evidence:manual
kind: domain
language: it
purposes: [sql_generation]
applies_to:
tables: [sales.orders]
---
# Una regola manuale
## Regola
Le righe vengono collegate tramite numero ordine ed esercizio.
"""
parsed = parse_curated_markdown(text)
assert isinstance(parsed.provenance, ManualEvidenceProvenance)
assert parsed.provenance.original is None
assert parsed.payload.rule.startswith("Le righe")
def test_code_fences_cannot_inject_structural_sections():
original = unit(
"normalization",
{
"input": "A",
"output": "active",
"rule": "Example:\n\n```markdown\n## Input\nDo not parse this heading.\n```",
},
)
assert parse_curated_markdown(dump_curated_markdown(original)) == original
@pytest.mark.parametrize(
"mutation",
[
lambda text: text.replace("## Rule", "## Missing"),
lambda text: text + "\n## Rule\n\nAnother rule.\n",
lambda text: text.replace("kind: domain", "kind: domain\npayload: {rule: hidden}"),
lambda text: text.replace("kind: domain", "kind: glossary\nkind: domain"),
lambda text: text.replace("kind: domain", "kind: ["),
lambda text: text.replace("- sql_generation", ""),
lambda text: text.replace("language: en", "language: ''"),
],
)
def test_invalid_edit_is_rejected_with_a_correctable_error(mutation):
with pytest.raises(ValueError):
parse_curated_markdown(mutation(dump_curated_markdown(unit())))
def test_unrepresentable_legacy_content_is_reported_instead_of_silently_trimmed():
with pytest.raises(ValueError, match="losslessly"):
dump_curated_markdown(unit(payload={"rule": " significant indentation"}))