feat(archive): complete recorded session lifecycle
This commit is contained in:
@@ -178,6 +178,39 @@ def test_catalog_reconciles_sessions_removed_from_one_evidence_root(tmp_path: Pa
|
||||
assert store.list_recent().items == ()
|
||||
|
||||
|
||||
def test_corrupt_candidate_does_not_starve_later_valid_session(tmp_path: Path) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
sessions = repository / "sessions"
|
||||
corrupt = sessions / "20260716T125502Z_viewer_live"
|
||||
corrupt.mkdir(parents=True)
|
||||
(corrupt / "manifest.redacted.json").write_text("{}", encoding="utf-8")
|
||||
valid = make_legacy_session(sessions, "20260718T201659Z_viewer_live")
|
||||
store = SessionStore(repository, data_dir=tmp_path / "data")
|
||||
|
||||
assert store.reconcile_archive(xgrids_k1_archive_source(sessions)) == (valid.name,)
|
||||
assert [item.session_id for item in store.list_recent().items] == [valid.name]
|
||||
|
||||
|
||||
def test_present_corrupt_candidate_does_not_delete_its_last_valid_catalog_row(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
sessions = repository / "sessions"
|
||||
retained = make_legacy_session(sessions, "20260716T125502Z_viewer_live")
|
||||
later = make_legacy_session(sessions, "20260718T201659Z_viewer_live")
|
||||
store = SessionStore(repository, data_dir=tmp_path / "data")
|
||||
source = xgrids_k1_archive_source(sessions)
|
||||
assert store.reconcile_archive(source) == (retained.name, later.name)
|
||||
|
||||
shutil.rmtree(retained / "captures")
|
||||
|
||||
assert store.reconcile_archive(source) == (later.name,)
|
||||
assert {item.session_id for item in store.list_recent().items} == {
|
||||
retained.name,
|
||||
later.name,
|
||||
}
|
||||
|
||||
|
||||
def test_catalog_uses_valid_project_name_as_session_display_name(tmp_path: Path) -> None:
|
||||
sessions = tmp_path / "sessions"
|
||||
session = make_legacy_session(sessions, "20260716T205632Z_viewer_live")
|
||||
@@ -671,6 +704,45 @@ def test_current_session_marker_keeps_active_capture_out_of_replay(tmp_path: Pat
|
||||
assert store.get_session(session.name).summary.replayable is True
|
||||
|
||||
|
||||
def test_delete_session_removes_only_the_exact_evidence_tree_and_catalog_row(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
sessions = repository / "sessions"
|
||||
deleted = make_legacy_session(sessions, "20260716T205632Z_viewer_live")
|
||||
retained = make_legacy_session(sessions, "20260716T205633Z_viewer_live")
|
||||
store = SessionStore(repository, data_dir=tmp_path / "data")
|
||||
store.reconcile_archive(xgrids_k1_archive_source(sessions))
|
||||
|
||||
store.delete_session(deleted.name)
|
||||
|
||||
assert not deleted.exists()
|
||||
assert retained.is_dir()
|
||||
with pytest.raises(SessionNotFoundError):
|
||||
store.get_session(deleted.name)
|
||||
assert store.get_session(retained.name).summary.session_id == retained.name
|
||||
|
||||
|
||||
def test_delete_session_rejects_a_catalog_target_outside_its_allowed_root(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
sessions = repository / "sessions"
|
||||
session = make_legacy_session(sessions, "20260716T205632Z_viewer_live")
|
||||
store = SessionStore(repository, data_dir=tmp_path / "data")
|
||||
store.reconcile_archive(xgrids_k1_archive_source(sessions))
|
||||
with sqlite3.connect(store.database_path) as connection:
|
||||
connection.execute(
|
||||
"UPDATE observation_sessions SET session_root = ? WHERE session_id = ?",
|
||||
(str(repository), session.name),
|
||||
)
|
||||
|
||||
with pytest.raises(SessionIntegrityError, match="escapes"):
|
||||
store.delete_session(session.name)
|
||||
|
||||
assert session.is_dir()
|
||||
|
||||
|
||||
def test_interrupted_capture_replays_only_committed_prefix_before_partial_raw_tail(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user