HERMES-GIELIE/api
Hermes Agent 3d34a72ee8 stage-353: apply Opus SHOULD-FIX — unconditional parent_session_id stamp on compression rotation
Opus identified that PR #2227's preservation block had two related bugs in
the parent_session_id handling:

1. During preservation save: code did
     _old_parent = s.parent_session_id
     s.parent_session_id = None
     s.save(touch_updated_at=False, skip_index=True)
     s.parent_session_id = _old_parent
   The save persisted parent=None to disk. The in-memory restoration didn't
   reach the disk copy. Result: a /branch fork session that subsequently
   compressed lost its 'Forked from X' badge on the preserved old snapshot.

2. Stamping the continuation: code did
     if not s.parent_session_id:
         s.parent_session_id = old_sid
   The 'if not' guard skipped the stamp when the session already had a
   parent_session_id from a prior fork. Result: fork-of-fork compression
   broke lineage — the continuation jumped back to the original fork parent
   instead of the just-preserved immediate predecessor snapshot.

Fix (matches Opus's recommendation):
  - Remove the parent clearing during preservation save (preserve as-is)
  - Drop the 'if not' guard; always stamp continuation to old_sid

This makes the lineage chain consistent: new → old → old.parent → ... root.
Traversal from the continuation always walks through the just-preserved
snapshot to get to its parent's parent, never jumping over the snapshot.

Two new regression tests pin both invariants:
  - test_parent_session_id_stamped_unconditionally (no 'if not' guard)
  - test_old_session_parent_preserved_during_archive_save (no parent=None)

Both pass against the fix. All 8 tests in the file pass.
2026-05-14 03:59:02 +00:00
..
__init__.py
agent_health.py fix(agent-health): treat stale running gateway as unknown 2026-05-11 23:13:09 +00:00
agent_sessions.py fix: align fork lineage projection paths 2026-05-11 17:15:22 +08:00
auth.py fix(auth): add type hint to verify_session() 2026-05-13 14:18:47 -03:00
background.py
clarify.py
commands.py fix(security): drop unsafe-eval + add jsdelivr to CSP, sanitize plugin error 2026-05-11 17:53:02 +00:00
compression_anchor.py docs: clarify compression anchor helpers 2026-05-12 01:43:16 -07:00
config.py Add extra large font size option 2026-05-14 11:09:21 +08:00
dashboard_probe.py
extensions.py
gateway_watcher.py
goals.py fix(i18n): localize /goal runtime status strings 2026-05-10 15:21:24 +08:00
helpers.py stage-348: apply Opus SHOULD-FIX-pre-merge — add '://' to _SENSITIVE_LOWER_MARKERS 2026-05-13 16:54:36 +00:00
kanban_bridge.py
metering.py
models.py perf(sessions): cache CLI session scans 2026-05-12 11:24:29 -06:00
oauth.py
onboarding.py Fix Xiaomi API key env detection 2026-05-11 07:33:52 +08:00
profiles.py docs: clarify compression anchor helpers 2026-05-12 01:43:16 -07:00
providers.py fix(providers): load Codex quota from credential pool 2026-05-11 21:46:24 -06:00
request_diagnostics.py
rollback.py
routes.py Merge pull request #2149 into stage-351 2026-05-13 23:54:15 +00:00
session_ops.py
session_recovery.py fix: audit turn journal terminal collisions 2026-05-12 05:20:06 -07:00
startup.py
state_sync.py
streaming.py stage-353: apply Opus SHOULD-FIX — unconditional parent_session_id stamp on compression rotation 2026-05-14 03:59:02 +00:00
system_health.py
terminal.py
turn_journal.py fix: audit turn journal terminal collisions 2026-05-12 05:20:06 -07:00
updates.py fix: cap _summary_cache with OrderedDict LRU 2026-05-14 09:14:28 +08:00
upload.py
workspace.py refactor: reduce stale workspace recovery fix 2026-05-12 06:28:35 -06:00
worktrees.py Harden worktree removal safeguards 2026-05-13 09:49:15 +08:00