feat(archive): complete recorded session lifecycle

This commit is contained in:
DCCONSTRUCTIONS
2026-07-19 01:07:21 +03:00
parent ffffee1879
commit 71c85e9894
22 changed files with 922 additions and 144 deletions
+72
View File
@@ -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: