You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds a non-destructive offline recovery path for state databases that remain unusable after the existing in-place repair ladder.
The new hermes sessions recover command never opens the supplied source through SQLite. It copies the database and any WAL, SHM, or rollback-journal sidecars into a disposable working directory, reads canonical data from that copy, and rebuilds it into a separate current-schema database. Derived FTS indexes and migration metadata are recreated instead of copied.
Recovery refuses existing outputs and source aliases, fingerprints the source bundle before and after copying, and never installs the recovered database automatically. A successful result requires integrity, foreign-key, schema-version, canonical row-count, and FTS verification.
Before copying, the command checks available disk space. It reserves room for the complete source bundle, a full-size output allowance, and the larger of 256 MiB or 5 percent additional headroom. Work and output filesystems are checked independently when they differ.
This complements the in-place repair work merged in #43149 and #68653. It covers the remaining failure mode where canonical sessions and messages are readable from a disposable writable-schema connection, but repair_state_db_schema cannot restore the original database to a cleanly openable state.
Type of Change
🐛 Bug fix (non-breaking change that fixes an issue)
✨ New feature (non-breaking change that adds functionality)
🔒 Security fix
📝 Documentation update
✅ Tests (adding or improving test coverage)
♻️ Refactor (no behavior change)
🎯 New skill (bundled or hub)
Changes Made
Add hermes sessions recover with explicit source, output, inspection-only, work-directory, chunk-size, and JSON-report options.
Add hermes_cli/session_recovery.py for source isolation, sidecar-aware snapshots, disk-space preflight, bounded canonical-table copying, derived-index rebuilding, and final verification.
Add disposable-database tests covering malformed FTS schema recovery, source immutability, overwrite guards, insufficient-space refusal, required-table failure, and the real CLI/report path.
How to Test
Run scripts/run_tests.sh -j 4 tests/hermes_cli/test_session_recovery.py tests/test_state_db_malformed_repair.py -q.
Against a disposable damaged database, run python -m hermes_cli.main sessions recover --source damaged.db --output recovered.db --work-dir PATH.
Confirm the command leaves damaged.db unchanged, creates recovered.db plus recovered.db.recovery.json, and reports complete only when integrity, counts, schema, and FTS verification pass.
Merged via #71629 — your commit was cherry-picked onto current main with your authorship preserved in git log (a9b8128bcb).
Thanks for this one. It closes a real dead end: hermes sessions repair would exhaust its in-place ladder, print "keep state.db and the backup", and stop — leaving a user whose sessions had vanished with two files and nothing to run. The design decisions that made it mergeable as-is were the right ones: copying the sidecars before SQLite opens anything, rebuilding derived FTS indexes instead of copying them, fingerprinting the source bundle before and after, and never installing the result automatically.
Verified end to end against a genuinely unopenable database (25 sessions / 2500 messages, FTS shadow schema rewritten to reference a missing table, WAL mode):
source bundle sha256 byte-identical after recovery, every sidecar
25/25 sessions and 2500/2500 messages recovered, integrity_check: ok, schema v23, zero FK violations
recovered database usable by the real SessionDB, FTS search returning hits
derived fts_rebuild_high_water correctly absent; real meta preserved
overwrite and source-alias guards both raise
real CLI recover and --inspect-only both rc 0
One follow-up commit on top (ec2a0f8c1e): the failed-repair branch now names your command — --inspect-only first, then --output — pre-filled with the backup path it just preserved. The recovery path existed but the affected user had no way to discover it. Covered by a CLI-surface regression test that drives the real sessions repair subprocess against an unrepairable database, sabotage-verified so it can't pass vacuously.
This is going straight to use on a reported incident: the next step there is an inspection-only pass against the user's preserved state.db.malformed-backup-*.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
area/sessionsSession lifecycle, resume, persistence, historycomp/cliCLI entry point, hermes_cli/, setup wizardP2Medium — degraded but workaround existssweeper:risk-session-stateSweeper risk: may lose/corrupt/mis-associate session or context statetype/featureNew feature or request
3 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds a non-destructive offline recovery path for state databases that remain unusable after the existing in-place repair ladder.
The new hermes sessions recover command never opens the supplied source through SQLite. It copies the database and any WAL, SHM, or rollback-journal sidecars into a disposable working directory, reads canonical data from that copy, and rebuilds it into a separate current-schema database. Derived FTS indexes and migration metadata are recreated instead of copied.
Recovery refuses existing outputs and source aliases, fingerprints the source bundle before and after copying, and never installs the recovered database automatically. A successful result requires integrity, foreign-key, schema-version, canonical row-count, and FTS verification.
Before copying, the command checks available disk space. It reserves room for the complete source bundle, a full-size output allowance, and the larger of 256 MiB or 5 percent additional headroom. Work and output filesystems are checked independently when they differ.
Related Issue
No GitHub issue. Reported in Discord: https://discord.com/channels/1053877538025386074/1530627291120537771
This complements the in-place repair work merged in #43149 and #68653. It covers the remaining failure mode where canonical sessions and messages are readable from a disposable writable-schema connection, but repair_state_db_schema cannot restore the original database to a cleanly openable state.
Type of Change
Changes Made
How to Test
Checklist
Code
Documentation & Housekeeping
Screenshots / Logs
Focused local validation on Windows:
Full-suite coverage is left to GitHub CI.