import uuid from datetime import UTC, datetime from pathlib import Path from types import SimpleNamespace from tht.cli import session_cmd from tht.decisions import DecisionInput from tht.session.filesystem_repository import FilesystemSessionRepository from tht.session.models import PrincipalContext, SessionManifest def test_finalize_commits_session_without_implicitly_reading_or_saving_memory( tmp_path, monkeypatch, capsys ): repository = FilesystemSessionRepository( tmp_path / "home", "demo", PrincipalContext(issuer="local", subject="reviewer"), root=tmp_path / "sessions", ) session_id = str(uuid.uuid4()) repository.create(SessionManifest( id=session_id, created_at=datetime(2026, 8, 24, tzinfo=UTC), question="active patients", database="analytics", schema="mart", )) repository.write_artifact(session_id, "sql_final", "SELECT 1\n") repository.write_artifact( session_id, "schema_linking", '{"question":"active patients","candidates":[],"excluded":[]}', ) repository.append_decisions(session_id, [ DecisionInput(type="sql_approved", subject="phase:7"), *[ DecisionInput(type="phase_approved", subject=f"phase:{phase}") for phase in range(1, 9) ], ]) cfg = SimpleNamespace( execution=SimpleNamespace(forbidden_functions=[], max_preview_rows=10), paths=SimpleNamespace(artifacts=tmp_path / "artifacts"), embeddings=object(), ) class FailingPostCommitRead: def get(self, sid): snapshot = repository.get(sid) if snapshot.manifest.status == "finalized": raise RuntimeError("finalized snapshot unavailable") return snapshot def finalize(self, manifest, artifacts): return repository.finalize(manifest, artifacts) failing_read_repository = FailingPostCommitRead() monkeypatch.setattr(session_cmd, "_load_config_or_exit", lambda config: cfg) monkeypatch.setattr( session_cmd, "session_repository", lambda config: failing_read_repository, ) monkeypatch.setattr(session_cmd, "load_snapshot_or_exit", lambda config, sid: repository.get(sid)) monkeypatch.setattr(session_cmd, "session_problems", lambda config, sid: []) monkeypatch.setattr("tht.cli.sql_cmd._load_physical_or_exit", lambda config: object()) monkeypatch.setattr("tht.cli.sql_cmd.promoted_tables_for", lambda config, sid: set()) monkeypatch.setattr("tht.cli.sql_cmd.do_explain", lambda config, sql: object()) monkeypatch.setattr("tht.cli.sql_cmd.do_run", lambda config, sql, limit: object()) monkeypatch.setattr( "tht.sqlcheck.validate_sql", lambda *args, **kwargs: SimpleNamespace(ok=True, errors=[], ast=object()), ) monkeypatch.setattr("tht.execute.warnings.plan_warnings", lambda *args: []) monkeypatch.setattr("tht.execute.warnings.runtime_warnings", lambda *args: []) monkeypatch.setattr("tht.execute.warnings.static_warnings", lambda *args: []) monkeypatch.setattr("tht.report.render_validation_report", lambda **kwargs: "verified\n") monkeypatch.setattr("tht.evidence.project_session", lambda *args: []) session_cmd.finalize_cmd(session_id, config=Path("unused.yaml")) captured = capsys.readouterr() assert repository.get(session_id).manifest.status == "finalized" assert "finalized snapshot unavailable" not in captured.err assert f"OK: sessione {session_id} finalizzata" in captured.out