feat: complete evidence restructuring worktree

This commit is contained in:
Codex
2026-08-26 11:39:02 +02:00
parent a54d4769dd
commit 38f02cfd08
56 changed files with 1981 additions and 1801 deletions
+1
View File
@@ -11,6 +11,7 @@
"decision add-batch",
"decision add-join-set",
"evidence evaluate",
"evidence migrate",
"evidence prepare",
"evidence resolve",
"evidence validate",
+1 -1
View File
@@ -32,7 +32,7 @@ def test_typer_tree_matches_the_approved_command_surface():
approved = _approved_surface()
expected = set(approved["maintained"]) | set(approved["enhanced"])
assert len(approved["maintained"]) == 60
assert len(approved["maintained"]) == 61
assert len(approved["enhanced"]) == 8
assert len(approved["erased"]) == 14
assert not (expected & set(approved["erased"]))
+1 -1
View File
@@ -121,7 +121,7 @@ def pipeline(tmp_path, source, *, embedder=None, vectors=None, model="model-a",
def test_pipeline_embeds_validated_curated_evidence_as_semantic_fragments(tmp_path):
evidence = CuratedEvidence.model_validate(
{
"schema_version": 1,
"schema_version": 2,
"id": "evidence:fascia-pediatrica",
"title": "Fascia pediatrica",
"kind": "formula",
+35
View File
@@ -1,4 +1,5 @@
import hashlib
import subprocess
import threading
import unicodedata
@@ -15,6 +16,7 @@ from tht.evidence import (
dump_manifest,
load_curated_tree,
load_manifest,
migrate_workspace_evidence,
prepare_workspace_evidence,
validate_workspace_evidence,
)
@@ -346,9 +348,41 @@ def test_prepare_changed_source_uses_one_model_call_and_applies_a_valid_batch(tm
assert report.created == ()
assert len(restructurer.requests) == 1
assert restructurer.requests[0].previous_units[0].id == "evidence:fascia-pediatrica"
curated_path = tmp_path / "evidence" / "curated" / "domain" / "fascia-pediatrica.md"
curated = load_curated_tree(tmp_path / "evidence" / "curated")[0]
assert curated.schema_version == 2
assert "# Fascia pediatrica\n" in curated_path.read_text(encoding="utf-8")
assert validate_workspace_evidence(tmp_path).publishable is True
def test_migrate_workspace_evidence_rewrites_v1_units_without_a_model_call(tmp_path):
source_text = "I pazienti sotto i 18 anni sono pediatrici."
_write_workspace(tmp_path, _evidence(source_text), source_text)
report = migrate_workspace_evidence(tmp_path, git_status=lambda _: ())
curated_path = tmp_path / "evidence" / "curated" / "domain" / "fascia-pediatrica.md"
migrated = load_curated_tree(tmp_path / "evidence" / "curated")[0]
assert report.migrated == ("evidence:fascia-pediatrica",)
assert report.unchanged == ()
assert migrated.schema_version == 2
assert migrated.payload.rule == "La fascia pediatrica comprende i minori."
assert "## Regola\n\nLa fascia pediatrica comprende i minori." in curated_path.read_text(
encoding="utf-8",
)
assert report.findings == ()
def test_migrate_workspace_evidence_rejects_dirty_curated_files_in_a_nested_workspace(tmp_path):
subprocess.run(["git", "init", "--quiet", str(tmp_path)], check=True)
workspace_root = tmp_path / "psd-clinical"
source_text = "I pazienti sotto i 18 anni sono pediatrici."
_write_workspace(workspace_root, _evidence(source_text), source_text)
with pytest.raises(EvidencePreparationError, match="authoring_worktree_dirty"):
migrate_workspace_evidence(workspace_root)
def test_prepare_can_issue_independent_source_calls_concurrently(tmp_path):
source_text = "I pazienti sotto i 18 anni sono pediatrici."
_write_workspace(tmp_path, _evidence(source_text), source_text)
@@ -512,6 +546,7 @@ def test_prepare_marks_an_omitted_prior_unit_for_human_review(tmp_path):
"supporting_excerpt_missing", "unresolved_review_item",
]
retained = load_curated_tree(tmp_path / "evidence" / "curated")[0]
assert retained.schema_version == 2
assert retained.review_items[0].code == "source_no_longer_supports_unit"
+148
View File
@@ -206,6 +206,154 @@ def _formula_evidence() -> CuratedEvidence:
})
def _domain_evidence_v2() -> CuratedEvidence:
return CuratedEvidence.model_validate({
**COMMON,
"schema_version": 2,
"title": "Dominio Ablazione",
"kind": "domain",
"payload": {
"rule": (
"Il dominio Ablazione rappresenta la procedura transcatetere.\n\n"
"La fact centrale è `clinical.fact_ablazione`."
),
},
})
def test_v2_curated_markdown_renders_domain_content_in_the_markdown_body(tmp_path):
evidence = _domain_evidence_v2()
path = tmp_path / "curated" / "domain" / "dominio-ablazione.md"
text = dump_curated_markdown(evidence)
frontmatter = text.split("---\n", 2)[1]
parsed = parse_curated_markdown(text, path=path)
assert "domain:" not in frontmatter
assert "supporting_excerpts:" not in frontmatter
assert "review_items:" not in frontmatter
assert "# Dominio Ablazione\n" in text
assert "## Regola\n\nIl dominio Ablazione" in text
assert "## Estratti di supporto\n\n> I pazienti sotto i 18 anni sono pediatrici." in text
assert parsed == evidence
@pytest.mark.parametrize(("kind", "payload", "rendered"), [
("glossary", {
"definition": "Un paziente con età inferiore a 18 anni.",
"synonyms": ["minore"],
"variants": ["pediatrico"],
}, "## Sinonimi\n\n- minore"),
("enum", {
"column": "clinical.episode.discharge_status",
"values": {"D": "dimesso", "T": "trasferito | altra struttura"},
}, "| `D` | dimesso |"),
("example", {
"question": "Come riconosco un paziente pediatrico?",
"interpretation": "Applicare la formula della fascia pediatrica.",
}, "## Domanda\n\nCome riconosco un paziente pediatrico?"),
("mapping", {
"concept": "fascia pediatrica",
"tables": ["clinical.patient"],
"columns": ["clinical.patient.birth_date"],
}, "## Tabelle\n\n- `clinical.patient`"),
("normalization", {
"input": "PEDS",
"output": "pediatrico",
"rule": "Converte il codice abbreviato nella forma canonica.",
}, "## Output\n\npediatrico"),
("formula", {
"concept": "fascia pediatrica",
"columns": ["clinical.patient.birth_date"],
"sql": "CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulta' END",
}, "```sql\nCASE WHEN age < 18"),
("reference", {
"url": "https://example.test/linea-guida",
"label": "Linea guida",
"description": "Criteri clinici di riferimento.",
}, "## URL\n\n<https://example.test/linea-guida>"),
])
def test_v2_curated_markdown_renders_and_round_trips_every_typed_payload(
tmp_path, kind, payload, rendered,
):
evidence = CuratedEvidence.model_validate({
**COMMON,
"schema_version": 2,
"kind": kind,
"payload": payload,
})
path = tmp_path / "curated" / kind / "fascia-pediatrica.md"
text = dump_curated_markdown(evidence)
assert rendered in text
assert parse_curated_markdown(text, path=path) == evidence
def test_v2_curated_markdown_renders_review_items_as_readable_blocks(tmp_path):
evidence = CuratedEvidence.model_validate({
**COMMON,
"schema_version": 2,
"kind": "domain",
"review_items": [{
"code": "ambiguous_source_statement",
"message": "Il sorgente non chiarisce la data di riferimento.",
"field": "domain.rule",
}],
"payload": {"rule": "L'età è calcolata alla data di ricovero."},
})
path = tmp_path / "curated" / "domain" / "fascia-pediatrica.md"
text = dump_curated_markdown(evidence)
assert "## Elementi da rivedere" in text
assert "### `ambiguous_source_statement`" in text
assert "Il sorgente non chiarisce la data di riferimento." in text
assert "**Campo:** `domain.rule`" in text
assert parse_curated_markdown(text, path=path) == evidence
@pytest.mark.parametrize("legacy_field", [
"review_items: []\n",
"payload:\n rule: should-not-be-ignored\n",
])
def test_v2_curated_markdown_rejects_body_owned_fields_in_frontmatter(legacy_field):
text = dump_curated_markdown(_domain_evidence_v2()).replace(
"kind: domain\n",
f"kind: domain\n{legacy_field}",
)
with pytest.raises(ValueError, match="frontmatter"):
parse_curated_markdown(text)
def test_v2_curated_markdown_rejects_unstructured_body_content():
text = dump_curated_markdown(_domain_evidence_v2()) + "should-not-be-ignored\n"
with pytest.raises(ValueError, match="unstructured"):
parse_curated_markdown(text)
def test_v2_curated_markdown_round_trips_an_empty_enum_as_an_explicit_empty_state(tmp_path):
evidence = CuratedEvidence.model_validate({
**COMMON,
"schema_version": 2,
"kind": "enum",
"payload": {
"column": "clinical.episode.discharge_status",
"values": {},
},
})
text = dump_curated_markdown(evidence)
assert "Nessun elemento" in text
assert parse_curated_markdown(
text,
path=tmp_path / "curated" / "enum" / "discharge-status.md",
) == evidence
def test_curated_markdown_round_trip_uses_the_kind_specific_key(tmp_path):
evidence = _formula_evidence()
path = tmp_path / "curated" / "formula" / "fascia-pediatrica.md"
+30
View File
@@ -21,10 +21,40 @@ def test_evidence_authoring_commands_are_distinct_from_runtime_preprocessing():
assert result.exit_code == 0
assert "prepare" in result.output
assert "migrate" in result.output
assert "resolve" in result.output
assert "validate" in result.output
def test_evidence_migrate_json_is_pristine(monkeypatch, tmp_path):
from tht.cli import evidence_cmd
from tht.evidence import EvidenceMigrationReport
monkeypatch.setattr(evidence_cmd, "_canonical_worktree", lambda root: root)
monkeypatch.setattr(
evidence_cmd,
"migrate_workspace_evidence",
lambda *args, **kwargs: EvidenceMigrationReport(
migrated=("evidence:fascia-pediatrica",),
unchanged=("evidence:fascia-adulta",),
findings=(),
),
)
result = CliRunner().invoke(app, ["evidence", "migrate", str(tmp_path), "--json"])
assert result.exit_code == 0
assert result.stderr == ""
assert json.loads(result.stdout) == {
"findings": [],
"migrated": ["evidence:fascia-pediatrica"],
"operation": "evidence_migrate",
"schemaVersion": 1,
"status": "migrated",
"unchanged": ["evidence:fascia-adulta"],
}
def test_evidence_prepare_failure_identifies_the_source_file(monkeypatch, tmp_path):
from tht.cli import evidence_cmd
from tht.evidence import EvidencePreparationError
@@ -1,155 +0,0 @@
"""Migration boundary: legacy formulas become curated evidence or session proposals."""
import hashlib
from tht.evidence import formula_store
from tht.evidence.authoring import normalize_source_text
from tht.evidence.canonical import CuratedEvidence
from tht.evidence.formula_store import ConceptFormula
def test_reviewed_formula_migration_has_deterministic_provenance_hash():
formula = ConceptFormula(
concept="fascia pediatrica",
columns=["clinical.patient.birth_date"],
sql="CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulta' END",
status="reviewed",
sources=["Regola clinica approvata dal gruppo pediatrico."],
)
original_source = """---
concept: fascia pediatrica
columns: [clinical.patient.birth_date]
status: reviewed
sources:
- Regola clinica approvata dal gruppo pediatrico.
---
CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulta' END
"""
first = formula_store.legacy_formula_to_curated(
formula,
legacy_path="formulas/fascia-pediatrica-1.sql.md",
source_content=original_source,
)
second = formula_store.legacy_formula_to_curated(
formula,
legacy_path="formulas/fascia-pediatrica-1.sql.md",
source_content=original_source,
)
assert isinstance(first, CuratedEvidence)
assert isinstance(second, CuratedEvidence)
assert first.provenance.source_sha256 == second.provenance.source_sha256
expected = hashlib.sha256(normalize_source_text(original_source).encode("utf-8")).hexdigest()
assert first.provenance.source_sha256 == f"sha256:{expected}"
def test_reviewed_formula_without_original_source_fails_closed():
formula = ConceptFormula(
concept="fascia pediatrica",
columns=["clinical.patient.birth_date"],
sql="CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulta' END",
status="reviewed",
sources=["Regola clinica approvata dal gruppo pediatrico."],
)
outcome = formula_store.legacy_formula_to_curated(
formula, legacy_path="formulas/fascia-pediatrica-1.sql.md",
)
assert outcome.code == "legacy_formula_requires_manual_review"
assert outcome.problems == ("original_source_required",)
def test_reviewed_formula_without_verified_supporting_excerpts_fails_closed():
formula = ConceptFormula(
concept="fascia pediatrica",
columns=["clinical.patient.birth_date"],
sql="CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulta' END",
status="reviewed",
sources=["Nota non presente nel sorgente originale."],
)
original_source = """---
concept: fascia pediatrica
columns: [clinical.patient.birth_date]
status: reviewed
sources:
- >-
Nota non presente nel
sorgente originale.
---
CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulta' END
"""
outcome = formula_store.legacy_formula_to_curated(
formula,
legacy_path="formulas/fascia-pediatrica-1.sql.md",
source_content=original_source,
)
assert outcome.code == "legacy_formula_requires_manual_review"
assert outcome.problems == ("supporting_excerpt_unverified",)
def test_reviewed_formula_without_provenance_notes_fails_closed():
formula = ConceptFormula(
concept="fascia pediatrica",
columns=["clinical.patient.birth_date"],
sql="CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulta' END",
status="reviewed",
sources=[],
)
outcome = formula_store.legacy_formula_to_curated(
formula,
legacy_path="formulas/fascia-pediatrica-1.sql.md",
source_content=formula.dump(),
)
assert outcome.code == "legacy_formula_requires_manual_review"
assert outcome.problems == ("supporting_excerpts_required",)
def test_reviewed_formula_must_match_the_original_source_record():
formula = ConceptFormula(
concept="fascia pediatrica",
columns=["clinical.patient.birth_date"],
sql="CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulta' END",
status="reviewed",
sources=["Regola clinica approvata dal gruppo pediatrico."],
)
different_source = ConceptFormula(
concept=formula.concept,
columns=formula.columns,
sql="CASE WHEN age < 16 THEN 'pediatrica' ELSE 'adulta' END",
status=formula.status,
sources=formula.sources,
).dump()
outcome = formula_store.legacy_formula_to_curated(
formula,
legacy_path="formulas/fascia-pediatrica-1.sql.md",
source_content=different_source,
)
assert outcome.code == "legacy_formula_requires_manual_review"
assert outcome.problems == ("original_source_mismatch",)
def test_incompatible_reviewed_legacy_formula_fails_closed_with_the_original_record():
formula = ConceptFormula(
concept="ablazione",
columns=["testo"],
sql="SELECT 2",
status="reviewed",
sources=["legacy manual"],
)
outcome = formula_store.legacy_formula_to_curated(
formula, legacy_path="formulas/ablazione-2.sql.md",
)
assert outcome.code == "legacy_formula_requires_manual_review"
assert outcome.legacy_path == "formulas/ablazione-2.sql.md"
assert outcome.formula == formula
+12 -145
View File
@@ -1,161 +1,22 @@
"""L1: SQL formula evidence -- concept->formula units (spec D14b).
A concept (e.g. 'fascia pediatrica') maps to a SQL formula (CASE WHEN ...) that
derives it from physical columns. These are reusable, reviewable units: the gate
surfaces a candidate formula, the reviewer approves or rejects it (recorded via
concept_formula_approved / concept_formula_rejected), and approved formulas are
part of the schema-linking artifact. The store is frontmatter-YAML + SQL body.
"""
"""L1: session-local Formula proposals and their reviewer decisions."""
from datetime import UTC, datetime
from tht.decisions import DecisionRecord
from tht.evidence import formula_store
from tht.evidence.formula_store import ConceptFormula, retrieve_formula, save_formula
from tht.evidence.session import project_session
from tht.session.models import SchemaLinking
def test_formula_retrieval_by_concept(tmp_path):
f = ConceptFormula(
concept="fascia pediatrica",
columns=["data_nascita"],
sql="CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulto' END",
status="reviewed",
sources=["src1"],
)
save_formula(tmp_path, f)
results = retrieve_formula(tmp_path, "fascia pediatrica")
assert len(results) == 1
assert results[0].sql.startswith("CASE WHEN")
assert results[0].concept == "fascia pediatrica"
assert results[0].status == "reviewed"
assert "data_nascita" in results[0].columns
def test_save_and_reload_roundtrip_preserves_sql_body(tmp_path):
f = ConceptFormula(
concept="fascia pediatrica",
columns=["data_nascita"],
sql="CASE\n WHEN x THEN 1\nEND",
status="draft",
sources=[],
)
path = save_formula(tmp_path, f)
assert path.exists()
# the file is frontmatter YAML + SQL body
text = path.read_text()
assert text.startswith("---")
assert "concept: fascia pediatrica" in text
assert "CASE" in text # SQL body preserved
def test_retrieve_multiple_formulas_for_concept(tmp_path):
# two competing formulas for the same concept (different sources/status)
save_formula(tmp_path, ConceptFormula(concept="ablazione", columns=["flag"],
sql="SELECT 1", status="draft", sources=["a"]))
save_formula(tmp_path, ConceptFormula(concept="ablazione", columns=["testo"],
sql="SELECT 2", status="reviewed", sources=["b"]))
results = retrieve_formula(tmp_path, "ablazione")
assert len(results) == 2
statuses = {r.status for r in results}
assert statuses == {"draft", "reviewed"}
def test_retrieve_empty_when_no_match(tmp_path):
save_formula(tmp_path, ConceptFormula(concept="altro", columns=["c"],
sql="SELECT 1", status="reviewed", sources=[]))
assert retrieve_formula(tmp_path, "inesistente") == []
def test_retrieve_empty_on_missing_dir(tmp_path):
# no formulas dir at all -> empty list, not error
assert retrieve_formula(tmp_path / "nope", "anything") == []
def test_concept_formula_decision_types_exist():
import typing
from tht.decisions import DecisionType
args = typing.get_args(DecisionType)
assert "concept_formula_approved" in args
assert "concept_formula_rejected" in args
def test_concept_formula_default_status(tmp_path):
# status has a sensible default so an author can write a draft quickly
f = ConceptFormula(concept="x", columns=["c"], sql="SELECT 1")
assert f.status == "draft" # not yet reviewed
assert f.sources == []
def test_reviewed_legacy_formula_becomes_curated_formula_with_stable_provenance():
formula = ConceptFormula(
concept="fascia pediatrica",
columns=["clinical.patient.birth_date"],
sql="CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulta' END",
status="reviewed",
sources=["Regola clinica approvata dal gruppo pediatrico."],
)
migrated = formula_store.legacy_formula_to_curated(
formula,
legacy_path="formulas/fascia-pediatrica-1.sql.md",
source_content=formula.dump(),
)
assert migrated is not None
assert migrated.id.startswith("evidence:fascia-pediatrica-")
assert migrated.title == "Fascia pediatrica"
assert migrated.kind == "formula"
assert migrated.payload.concept == formula.concept
assert migrated.payload.columns == ("clinical.patient.birth_date",)
assert migrated.payload.sql == formula.sql
assert migrated.provenance.source_file == "source/formulas/fascia-pediatrica-1.sql.md"
assert migrated.provenance.supporting_excerpts == tuple(formula.sources)
assert migrated.review_items == ()
assert formula_store.legacy_formula_to_curated(
formula,
legacy_path="formulas/fascia-pediatrica-1.sql.md",
source_content=formula.dump(),
).id == migrated.id
def test_reviewed_legacy_formulas_with_the_same_concept_keep_distinct_path_identities():
first = ConceptFormula(
concept="fascia pediatrica",
columns=["clinical.patient.birth_date"],
sql="CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulta' END",
status="reviewed",
sources=["Regola legacy revisionata."],
)
second = ConceptFormula(
concept="fascia pediatrica",
columns=["clinical.patient.birth_date"],
sql="CASE WHEN age < 16 THEN 'pediatrica' ELSE 'adulta' END",
status="reviewed",
sources=["Regola legacy revisionata."],
)
first_migration = formula_store.legacy_formula_to_curated(
first,
legacy_path="formulas/fascia-pediatrica-1.sql.md",
source_content=first.dump(),
)
second_migration = formula_store.legacy_formula_to_curated(
second,
legacy_path="formulas/fascia-pediatrica-2.sql.md",
source_content=second.dump(),
)
assert first_migration is not None
assert second_migration is not None
assert first_migration.id != second_migration.id
assert first_migration.id.startswith("evidence:fascia-pediatrica-")
assert second_migration.id.startswith("evidence:fascia-pediatrica-")
def test_session_formula_proposal_is_versioned_and_is_not_published_evidence(tmp_path):
linking = SchemaLinking(
question="Conta i pazienti pediatrici",
@@ -199,12 +60,18 @@ def test_session_formula_proposals_require_an_unretracted_positive_f4_decision(t
)
decisions = [
DecisionRecord(
seq=3, ts=datetime(2026, 8, 25, tzinfo=UTC), type="concept_formula_approved",
subject="phase:4", detail="approvata",
seq=3,
ts=datetime(2026, 8, 25, tzinfo=UTC),
type="concept_formula_approved",
subject="phase:4",
detail="approvata",
),
DecisionRecord(
seq=4, ts=datetime(2026, 8, 25, tzinfo=UTC), type="concept_formula_rejected",
subject="phase:4", detail="rifiutata",
seq=4,
ts=datetime(2026, 8, 25, tzinfo=UTC),
type="concept_formula_rejected",
subject="phase:4",
detail="rifiutata",
),
]
+24 -60
View File
@@ -1,63 +1,14 @@
"""D14b wiring: status=auto, search_formulas, and evidence loader skips formula files.
"""L1: Formula Evidence search uses only the typed, published Evidence surface."""
Completes the formula layer beyond the store: the `auto` status the spec requires
(§4.7.2), the concept-substring retrieval that `tht search find --kind formula` uses,
and the guarantee that load_evidence_dir does NOT choke on *.sql.md formula files when
they live under the evidence root.
"""
import json
from types import SimpleNamespace
from typer.testing import CliRunner
from tht.cli import app, search_cmd
from tht.evidence import formula_store
from tht.evidence.formula_store import ConceptFormula, save_formula, search_formulas
from tht.evidence.model import EvidenceDoc, load_evidence_dir
from tht.evidence.search import EvidenceSearchOutcome
def test_status_auto_is_valid():
f = ConceptFormula(concept="x", sql="SELECT 1", status="auto")
assert f.status == "auto"
# round-trips through parse/dump
assert ConceptFormula.parse(f.dump()).status == "auto"
def test_search_formulas_substring_case_insensitive(tmp_path):
save_formula(tmp_path, ConceptFormula(concept="fascia pediatrica", sql="SELECT 1"))
save_formula(tmp_path, ConceptFormula(concept="indice di Charlson", sql="SELECT 2"))
hits = search_formulas(tmp_path, "PEDIATRICA")
assert len(hits) == 1
assert hits[0].concept == "fascia pediatrica"
assert search_formulas(tmp_path, "charlson")[0].concept == "indice di Charlson"
def test_load_evidence_dir_skips_formula_files(tmp_path):
# a real evidence doc + a formula file under the same root
(tmp_path / "ev1.md").write_text(
"---\nid: ev1\ntitle: T\n---\nbody text\n"
)
save_formula(tmp_path, ConceptFormula(concept="ablazione", sql="SELECT 1"))
docs = load_evidence_dir(tmp_path)
ids = [d.id for d in docs]
assert ids == ["ev1"] # the .sql.md formula file is skipped, no crash
assert all(isinstance(d, EvidenceDoc) for d in docs)
def test_unreviewed_legacy_formulas_cannot_become_curated_evidence():
for status in ("auto", "draft"):
formula = ConceptFormula(
concept="fascia pediatrica",
columns=["clinical.patient.birth_date"],
sql="CASE WHEN age < 18 THEN 'pediatrica' ELSE 'adulta' END",
status=status,
)
assert formula_store.legacy_formula_to_curated(
formula, legacy_path="formulas/pediatric-1.sql.md",
) is None
def test_formula_search_uses_typed_evidence_with_a_formula_constraint():
class Searcher:
vector_generation = "gen:" + "a" * 32
@@ -68,8 +19,11 @@ def test_formula_search_uses_typed_evidence_with_a_formula_constraint():
def search(self, embedding, **kwargs):
self.calls.append((embedding, kwargs))
return [SimpleNamespace(
id="fragment:formula", similarity=0.9, content="formula excerpt",
title="Fascia pediatrica", metadata={
id="fragment:formula",
similarity=0.9,
content="formula excerpt",
title="Fascia pediatrica",
metadata={
"evidence_id": "evidence:fascia-pediatrica",
"evidence_kind": "formula",
"document_id": "doc:formula",
@@ -89,16 +43,26 @@ def test_formula_search_uses_typed_evidence_with_a_formula_constraint():
)
assert outcome.status == "available"
assert [result.evidence_id for result in outcome.results] == ["evidence:fascia-pediatrica"]
assert [result.evidence_id for result in outcome.results] == [
"evidence:fascia-pediatrica",
]
assert searcher.calls[0][1]["metadata_filter"]["required_kinds"] == ["formula"]
def test_formula_search_json_is_pristine_while_human_output_warns_about_legacy_store(monkeypatch):
monkeypatch.setattr(search_cmd, "_load_config_or_exit", lambda _path: SimpleNamespace(embeddings=object()))
def test_formula_search_json_is_pristine_and_human_output_uses_only_published_evidence(
monkeypatch,
):
monkeypatch.setattr(
search_cmd,
"_load_config_or_exit",
lambda _path: SimpleNamespace(embeddings=object()),
)
monkeypatch.setattr(search_cmd, "workspace_id_for_config", lambda _cfg, _path: "workspace-a")
monkeypatch.setattr(search_cmd, "search_formula_evidence", lambda *args, **kwargs: EvidenceSearchOutcome(
"available", "gen:" + "a" * 32,
))
monkeypatch.setattr(
search_cmd,
"search_formula_evidence",
lambda *args, **kwargs: EvidenceSearchOutcome("available", "gen:" + "a" * 32),
)
monkeypatch.setattr("tht.cli.vector_cmd.require_vector_cfg", lambda _cfg: None)
monkeypatch.setattr("tht.cli.vector_cmd.open_searcher", lambda _cfg: object())
monkeypatch.setattr("tht.cli.vector_cmd.make_embedder", lambda _cfg: object())
@@ -114,6 +78,6 @@ def test_formula_search_json_is_pristine_while_human_output_warns_about_legacy_s
assert json_result.exit_code == 0
assert json.loads(json_result.stdout) == []
assert "ATTENZIONE" not in json_result.stdout
assert human_result.exit_code == 0
assert "ATTENZIONE" in human_result.output
assert "ATTENZIONE" not in human_result.output
assert "Nessuna formula" in human_result.output