import json from types import SimpleNamespace import pytest from tht.evidence import ( EvidencePreparationError, PiEvidenceRestructurer, RestructureRequest, ) def _request(): return RestructureRequest.model_validate({ "source_file": "source/domain/patient.md", "source_sha256": "sha256:" + "a" * 64, "normalized_text": "I pazienti sotto i 18 anni sono pediatrici.\n", }) def _candidate(): return { "schema_version": 1, "title": "Fascia pediatrica", "kind": "domain", "purposes": ["disambiguation"], "applies_to": {"concepts": ["fascia pediatrica"]}, "language": "it", "supporting_excerpts": ["I pazienti sotto i 18 anni sono pediatrici."], "review_items": [], "payload": {"rule": "La fascia pediatrica comprende i minori."}, } def test_pi_restructurer_uses_an_ephemeral_no_tools_invocation(tmp_path, monkeypatch): from tht.evidence import authoring calls = [] def run(argv, **kwargs): calls.append((argv, kwargs)) kwargs["stdout"].write(json.dumps({"candidates": [_candidate()]})) return SimpleNamespace(returncode=0) monkeypatch.setattr(authoring.subprocess, "run", run) restructurer = PiEvidenceRestructurer("pi-test", tmp_path / "skill.md", timeout_seconds=12) candidates = restructurer.restructure(_request()) assert candidates[0].title == "Fascia pediatrica" argv, kwargs = calls[0] assert argv[:8] == [ "pi-test", "--mode", "text", "--print", "--no-session", "--no-tools", "--no-extensions", "--no-context-files", ] assert "--skill" in argv assert any(argument.startswith("@") for argument in argv) assert kwargs["timeout"] == 12 assert kwargs["shell"] is False assert kwargs["stderr"] is authoring.subprocess.DEVNULL @pytest.mark.parametrize("result", [ SimpleNamespace(returncode=1, stdout="secret", stderr="secret"), SimpleNamespace(returncode=0, stdout="not-json", stderr=""), ]) def test_pi_restructurer_returns_a_bounded_error_without_model_output(tmp_path, monkeypatch, result): from tht.evidence import authoring def run(*args, **kwargs): kwargs["stdout"].write(result.stdout) return result monkeypatch.setattr(authoring.subprocess, "run", run) restructurer = PiEvidenceRestructurer("pi-test", tmp_path / "skill.md") with pytest.raises(EvidencePreparationError) as error: restructurer.restructure(_request()) assert error.value.code in {"pi_restructure_failed", "pi_restructure_invalid"} assert "secret" not in str(error.value)