Skip to content

fix(gateway): restore gateway sessions from JSON snapshots - #37817

Closed
konsisumer wants to merge 1 commit into
NousResearch:mainfrom
konsisumer:fix/discord-thread-session-snapshot-replay
Closed

konsisumer wants to merge 1 commit into
NousResearch:mainfrom
konsisumer:fix/discord-thread-session-snapshot-replay

Conversation

@konsisumer

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds a fail-open transcript replay path for gateway sessions whose SQLite history is empty or unavailable but whose opt-in session_<id>.json snapshot still contains the conversation. SQLite remains the canonical source and wins whenever it has rows, so normal DB-backed gateway history is unchanged. This lets a fresh Discord thread turn restore the intact same-session snapshot instead of starting cold when the DB replay row is missing.

Related Issue

Fixes #8385

Type of Change

  • Bug fix
  • New feature
  • Security
  • Documentation
  • Tests
  • Refactor
  • Other

Changes Made

  • gateway/session.py: load transcripts from state.db first, then fall back to the matching session_<id>.json snapshot only when DB replay rows are absent or unavailable.
  • tests/gateway/test_session.py: cover empty transcripts, DB transcript loading, DB-over-snapshot precedence, and snapshot salvage when DB history is empty.

How to Test

  1. pytest tests/gateway/test_session.py tests/gateway/test_load_transcript_db_only.py -q -> 77 passed.
  2. python scripts/check-windows-footguns.py gateway/session.py tests/gateway/test_session.py -> clean.
  3. git diff --check -> clean.
  4. ruff check gateway/session.py tests/gateway/test_session.py -> clean.
  5. ruff format --check gateway/session.py tests/gateway/test_session.py -> fails because both touched files have existing full-file formatting drift; I did not reformat them to avoid a broad unrelated diff.
  6. scripts/run_tests.sh -> ran via the repo wrapper and failed with 27333 passed, 776 failed on this sandbox. Relevant gateway/session coverage passed under the wrapper, including tests/gateway/test_session.py, tests/gateway/test_load_transcript_db_only.py, tests/gateway/test_discord_thread_persistence.py, tests/gateway/test_discord_free_response.py, and tests/gateway/test_discord_slash_commands.py. The failures are outside this diff and cluster around restricted $HOME/.hermes writes, localhost socket bind permission errors, live-system guard process-signal blocks, shared-venv import timeouts, missing optional modules, DNS/network lookup failures, and /tmp versus /private/tmp path expectations.

Checklist

  • Conventional Commits format used for the PR title.
  • Tests added or updated.
  • Cross-platform compatibility considered; Windows footgun scan is clean for touched files.
  • Full local test suite passed.
  • Documentation updated.
  • CLI config updated.

For New Skills

Not applicable.

Screenshots / Logs

No screenshots. Local platform tested: macOS darwin-arm64 sandbox with Python 3.11.15 through scripts/run_tests.sh.

@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists labels Jun 3, 2026
@konsisumer

Copy link
Copy Markdown
Contributor Author

I checked #11629 after the issue-side comment. It is merged, but its PR body explicitly lists #8385 as not addressed and calls it a separate session-loading concern, while this PR targets that session replay path. I do not think this PR is redundant with #11629.

@teknium1

Copy link
Copy Markdown
Collaborator

Thanks for this, and for the careful tests — appreciate the work. Closing it though, because the JSON-snapshot fallback it re-adds was removed deliberately, not by oversight.

state.db is the canonical session store. The session_<id>.json snapshot fallback in load_transcript was intentionally dropped in commit 024a8e3ee ("refactor(gateway): drop JSONL fallback in load_transcript"), after verifying on a corpus of 950 sessions / 27 jsonl files that the fallback never fired — pre-DB sessions had already been migrated into their DB rows. Re-introducing it brings back a dead defensive branch and reads stale on-disk snapshots the migration already folded into the DB.

The underlying issue (#8385) is fixed on main: the gateway round-trips thread history through state.db (append_to_transcriptappend_message on write; load_transcriptget_messages_as_conversation on read). E2E on current main restores a 3-turn Discord thread conversation with context intact — the cold-AI-per-message symptom no longer reproduces, with no JSON fallback needed.

If you hit a real case where DB rows go missing while a JSON snapshot survives, that's a session-persistence bug worth its own issue with a repro — but the fix would be to stop the DB rows from going missing, not to re-add the snapshot fallback. Closing #8385 and this PR together.

@teknium1 teknium1 closed this Jun 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Discord thread session context not auto-restored on each message

3 participants