Files
ThothII/harness/tests/test_decision_retract_cli.py
T

64 lines
2.7 KiB
Python

"""D15 granularity (a): `tht decision retract` tombstones the last substantive decision.
Wires the step-granularity rollback ("re-ask current widget, discard last answer") to a
reachable CLI command. The data model (decision_retracted + retracts, honored by
effective_decisions) already existed; this pins the command that emits it.
"""
from pathlib import Path
from tht.cli.decision_cmd import retract_cmd
from tht.decisions import append_decision, list_decisions
from tht.phase import current_phase, effective_decisions
def _walk_to_phase(session: Path, target: int) -> None:
while current_phase(session) < target:
append_decision(session, type="phase_approved", subject=f"phase:{current_phase(session)}")
def test_retract_drops_last_substantive_decision(tmp_path, monkeypatch):
s = tmp_path / "2026-01-01-000000-x"
s.mkdir(parents=True)
_walk_to_phase(s, 4)
append_decision(s, type="table_promoted", subject="phase:4", detail="dim_pazienti")
append_decision(s, type="table_promoted", subject="phase:4", detail="fact_ricoveri")
# stub config + session loading (the command only needs a session dir)
import tht.cli.decision_cmd as mod
import tht.cli.session_cmd as session_mod
from tht.session.models import SessionManifest, SessionSnapshot
class _Cfg:
class paths:
sessions = tmp_path
monkeypatch.setattr(mod, "_load_config_or_exit", lambda _c: _Cfg())
monkeypatch.setattr(mod, "load_session_or_exit", lambda _cfg, _s: None)
class _Repository:
def get(self, session_id):
return SessionSnapshot(
manifest=SessionManifest(id=session_id, created_at="2026-01-01T00:00:00Z", question="q", database="d", schema="s"),
decisions=list_decisions(tmp_path / session_id),
)
def append_decisions(self, session_id, decisions):
from tht.decisions import append_decisions
return append_decisions(tmp_path / session_id, list(decisions))
repository = _Repository()
monkeypatch.setattr(mod, "load_snapshot_or_exit", lambda _cfg, sid: repository.get(sid))
monkeypatch.setattr(mod, "session_repository", lambda _cfg: repository)
monkeypatch.setattr(session_mod, "load_snapshot_or_exit", lambda _cfg, sid: repository.get(sid))
retract_cmd(session="2026-01-01-000000-x", config=Path("x"))
eff = effective_decisions(s)
promoted = [d for d in eff if d.type == "table_promoted"]
assert len(promoted) == 1 # the last one was retracted
assert promoted[0].detail == "dim_pazienti"
# the audit log keeps everything (append-only): 2 promotions + the retract marker
raw = [d.type for d in list_decisions(s)]
assert raw.count("table_promoted") == 2
assert "decision_retracted" in raw