import json import subprocess from typer.testing import CliRunner from tht.cli import app def test_evidence_authoring_accepts_a_canonical_workspace_inside_the_git_worktree(tmp_path): from tht.cli.evidence_cmd import _canonical_worktree subprocess.run(["git", "init", "--quiet", str(tmp_path)], check=True) workspace_root = tmp_path / "psd-clinical" workspace_root.mkdir() assert _canonical_worktree(workspace_root) == workspace_root.resolve() def test_evidence_authoring_commands_are_distinct_from_runtime_preprocessing(): result = CliRunner().invoke(app, ["evidence", "--help"]) 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 monkeypatch.setattr(evidence_cmd, "_canonical_worktree", lambda root: root) monkeypatch.setattr( evidence_cmd, "prepare_workspace_evidence", lambda *args, **kwargs: (_ for _ in ()).throw( EvidencePreparationError("pi_restructure_invalid", "source/domain/patient.md") ), ) result = CliRunner().invoke(app, ["evidence", "prepare", str(tmp_path), "--json"]) assert result.exit_code == 1 assert result.stderr == "" assert json.loads(result.stdout) == { "code": "pi_restructure_invalid", "operation": "evidence_prepare", "schemaVersion": 1, "sourceFile": "source/domain/patient.md", "status": "failed", } def test_evidence_resolve_json_is_pristine(monkeypatch, tmp_path): from tht.cli import evidence_cmd from tht.evidence.authoring import EvidenceResolutionReport monkeypatch.setattr(evidence_cmd, "_canonical_worktree", lambda root: root) monkeypatch.setattr(evidence_cmd, "resolve_workspace_evidence", lambda *args, **kwargs: EvidenceResolutionReport( action="retired", evidence_id="evidence:fascia-pediatrica", source_file=None, findings=(), )) result = CliRunner().invoke(app, [ "evidence", "resolve", str(tmp_path), "evidence:fascia-pediatrica", "--retire", "--json", ]) assert result.exit_code == 0 assert result.stderr == "" assert json.loads(result.stdout) == { "action": "retired", "evidenceId": "evidence:fascia-pediatrica", "findings": [], "operation": "evidence_resolve", "schemaVersion": 1, "sourceFile": None, "status": "resolved", } def test_evidence_resolve_reports_unsafe_source_as_cli_misuse(monkeypatch, tmp_path): from tht.cli import evidence_cmd from tht.evidence import EvidencePreparationError monkeypatch.setattr(evidence_cmd, "_canonical_worktree", lambda root: root) monkeypatch.setattr( evidence_cmd, "resolve_workspace_evidence", lambda *args, **kwargs: (_ for _ in ()).throw(EvidencePreparationError("source_invalid")), ) result = CliRunner().invoke(app, [ "evidence", "resolve", str(tmp_path), "evidence:fascia-pediatrica", "--source", "source/domain/x.md", "--json", ]) assert result.exit_code == 2 assert result.stderr == "" assert json.loads(result.stdout) == { "code": "source_invalid", "operation": "evidence_resolve", "schemaVersion": 1, "status": "failed", } def test_evidence_resolve_reports_structural_findings_as_operational_failure(monkeypatch, tmp_path): from tht.cli import evidence_cmd from tht.evidence import ValidationFinding from tht.evidence.authoring import EvidenceResolutionReport monkeypatch.setattr(evidence_cmd, "_canonical_worktree", lambda root: root) monkeypatch.setattr(evidence_cmd, "resolve_workspace_evidence", lambda *args, **kwargs: EvidenceResolutionReport( action="relinked", evidence_id="evidence:fascia-pediatrica", source_file="source/domain/patient.md", findings=(ValidationFinding( "error", "supporting_excerpt_missing", "source/domain/patient.md", "Excerpt missing.", ),), )) result = CliRunner().invoke(app, [ "evidence", "resolve", str(tmp_path), "evidence:fascia-pediatrica", "--source", "source/domain/patient.md", ]) assert result.exit_code == 1 def test_evidence_validate_json_is_pristine_and_reports_review_required(monkeypatch, tmp_path): from tht.cli import evidence_cmd from tht.evidence import ValidationFinding, ValidationReport monkeypatch.setattr(evidence_cmd, "_canonical_worktree", lambda root: root) monkeypatch.setattr(evidence_cmd, "validate_workspace_evidence", lambda root: ValidationReport(( ValidationFinding("error", "unresolved_review_item", "curated/domain/x.md", "Review needed."), ))) result = CliRunner().invoke(app, ["evidence", "validate", str(tmp_path), "--json"]) assert result.exit_code == 3 assert result.stderr == "" assert json.loads(result.stdout) == { "findings": [{ "code": "unresolved_review_item", "message": "Review needed.", "path": "curated/domain/x.md", "severity": "error", }], "operation": "evidence_validate", "publishable": False, "schemaVersion": 1, "status": "review_required", } def test_evidence_evaluate_json_reports_the_read_only_generation(monkeypatch, tmp_path): from tht.cli import evidence_cmd monkeypatch.setattr(evidence_cmd, "_canonical_worktree", lambda root: root) monkeypatch.setattr(evidence_cmd, "evaluate_from_config", lambda *args, **kwargs: { "workspaceRevision": "a" * 40, "vectorGeneration": "gen:" + "1" * 32, "rrf": {"algorithm": "rrf", "k": 60, "prefetch_limit_multiplier": 2}, "passed": True, "countsByExpectedKind": {"formula": 1}, "queries": [], }) result = CliRunner().invoke(app, [ "evidence", "evaluate", str(tmp_path), "--json", "-c", str(tmp_path / "runtime.yaml"), ]) assert result.exit_code == 0 assert result.stderr == "" assert json.loads(result.stdout) == { "countsByExpectedKind": {"formula": 1}, "operation": "evidence_evaluate", "passed": True, "queries": [], "rrf": {"algorithm": "rrf", "k": 60, "prefetch_limit_multiplier": 2}, "schemaVersion": 1, "status": "passed", "vectorGeneration": "gen:" + "1" * 32, "workspaceRevision": "a" * 40, }