fix(#4842): update #4385 archive tests to real sidecar files + document stat-gate assumption

Opus gate finding (BLOCKING): the two #4385 archive-reappears regression tests
mocked Session.load_metadata_only to return an archived stub WITHOUT writing a
real sidecar file, and never set SESSION_DIR. The new stat-gate in
_state_projection_sidecar_metadata short-circuits on SESSION_DIR/{sid}.json
before consulting metadata, so those mocks were never reached -> archived=False.

This is NOT a production regression (in prod, load_metadata_only reads exactly
SESSION_DIR/{sid}.json and returns None when absent, so archived metadata only
exists when the file does — in which case the stat() succeeds and behavior is
identical). The divergence existed only at the tests' mock boundary.

Fix: both tests now write a real archived sidecar JSON under a monkeypatched
SESSION_DIR, exercising the actual production read path (strictly better
coverage than mocking load_metadata_only). Also documented the
SESSION_DIR-as-sole-source assumption on the cache function per Opus's
forward-looking note.
This commit is contained in:
nesquena-hermes committed 2026-06-25 04:56:00 +00:00
1 parent a6d8319acb
commit b149a975c6
2 files changed
+29 -16

No files matched your search

+5
View File
@@ -4313,6 +4313,11 @@ def _state_projection_sidecar_metadata(sid: str) -> dict:
(#4842). A rename/archive/edit bumps the signature and invalidates just that
entry, so a stale title/archived flag is impossible without re-reading.
Returns a COPY so callers can't mutate the cached dict.
NOTE: this stat-gates on ``SESSION_DIR / f'{sid}.json'`` because that file is
``Session.load_metadata_only``'s sole source for title+archived. If that ever
stops being true (metadata moves to another store), this gate would short-
circuit before the real source — update both together.
"""
default = {"title": None, "archived": False}
if not is_safe_session_id(sid):
+24 -16
View File
@@ -109,16 +109,22 @@ def test_cron_state_projection_preserves_archived_sidecar(monkeypatch, tmp_path)
(sid, "Cron Session", "test-model", 1, 20, "cron", "cron"),
)
class ArchivedSidecar:
title = "Cron Session"
archived = True
monkeypatch.setattr(
models.Session,
"load_metadata_only",
staticmethod(lambda candidate: ArchivedSidecar() if candidate == sid else None),
# Write a real archived sidecar JSON under a patched SESSION_DIR so the
# projection's sidecar read exercises the production path (the #4842 perf
# fix stat-gates on SESSION_DIR/{sid}.json before consulting metadata, so a
# mock of load_metadata_only without a real file would never be reached —
# which mirrors production, where archived metadata only exists when the
# file does).
session_dir = tmp_path / "sessions"
session_dir.mkdir()
(session_dir / f"{sid}.json").write_text(
'{"session_id": "%s", "title": "Cron Session", "created_at": 1.0,'
' "updated_at": 2.0, "archived": true, "messages": []}' % sid,
encoding="utf-8",
)
monkeypatch.setattr(models, "SESSION_DIR", session_dir)
monkeypatch.setattr(models, "ensure_cron_project", lambda: "cron-project")
models.clear_sidecar_metadata_cache()
rows = models._load_cli_sessions_uncached(
tmp_path,
@@ -195,15 +201,17 @@ def test_webhook_state_projection_preserves_archived_sidecar(monkeypatch, tmp_pa
(sid,),
)
class ArchivedWebhookSidecar:
title = "Webhook Session"
archived = True
monkeypatch.setattr(
models.Session,
"load_metadata_only",
staticmethod(lambda candidate: ArchivedWebhookSidecar() if candidate == sid else None),
# Real archived sidecar JSON under a patched SESSION_DIR (see the cron test
# above — the #4842 stat-gate requires the file to exist, matching prod).
session_dir = tmp_path / "sessions"
session_dir.mkdir()
(session_dir / f"{sid}.json").write_text(
'{"session_id": "%s", "title": "Webhook Session", "created_at": 1.0,'
' "updated_at": 2.0, "archived": true, "messages": []}' % sid,
encoding="utf-8",
)
monkeypatch.setattr(models, "SESSION_DIR", session_dir)
models.clear_sidecar_metadata_cache()
rows = models._load_cli_sessions_uncached(
tmp_path,