hermes-agent/tests/hermes_state
joaomarcos 60645f8a53 fix(state): make a rewind truncation recoverable instead of a hard DELETE (#82756)
Guarding the *aim* of a rewind still leaves every other way of aiming it
wrong terminal. All three reported incidents (#70516, #80763, #82756) ended
at the same write — `replace_messages()` in the `prompt.submit` truncation
path — and all three were unrecoverable for the same reason: the rows are
DELETEd, which also evicts them from the FTS index, so there is no `active=0`
archive and nothing to restore from.

The codebase already draws this distinction and already has the safe half of
it. `archive_and_compact` is documented as "the durability-preserving
alternative to replace_messages"; `rewind_to_message` — the `/undo` path —
soft-deletes to `active=0, compacted=0` and keeps the rows "on disk for audit
/ forensic inspection". The desktop rewind is the same user-facing operation
as `/undo` and was the one taking the destructive branch.

`replace_messages(..., archive_dropped=True)` flips the DELETE to a
content-preserving `UPDATE messages SET active = 0`, reusing the existing
transaction and the existing `active=0, compacted=0` marking so the dropped
turns stay readable via `get_messages(..., include_inactive=True)` and stay
out of session search (`compacted=0` = "the user took it back", vs
compaction's `compacted=1` = "summarized away, still discoverable").

The live transcript is byte-identical either way — only the durability of the
dropped turns changes. The parameter defaults to False, so the fork handler,
the ACP adapter and `gateway/session.py` keep their current semantics
untouched; a test pins that.

`active_only=True` stays on the call: #80216 still applies, and archiving must
not disturb rows an earlier compaction deliberately archived.

Test doubles for `replace_messages` in the gateway suite are widened to the
real signature — they are stand-ins for SessionDB, and a double that does not
accept what production passes silently converts this write into a 5008.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 11:01:15 +05:30
..
test_append_messages_batch.py
test_aux_usage_accounting.py
test_conversation_root.py
test_get_anchored_view.py
test_get_messages_around.py
test_live_db_isolation_guard.py fix(tests): fail hard when pytest resolves the production state.db (live-DB isolation guard) 2026-08-06 07:49:50 -07:00
test_orphan_gateway_session_repair.py fix(state): recover gateway sessions stranded without a routing identity 2026-08-09 14:06:06 -07:00
test_reasoning_roundtrip.py fix(state,cli,tui-gateway): keep reasoning fields intact across forks and branches 2026-08-08 17:37:26 -07:00
test_replace_messages_archive_siblings.py fix(state): make a rewind truncation recoverable instead of a hard DELETE (#82756) 2026-08-10 11:01:15 +05:30
test_resolve_resume_session_id.py
test_restore_alternation_repair.py
test_session_archiving.py
test_session_md_export.py fix(state): stop delegate/tool children corrupting compression lineage 2026-08-05 13:50:26 +05:30
test_session_read_state.py feat(state): sessions carry read/unread state 2026-08-04 12:32:27 -06:00