Skip to content

test(backup): a restored store keeps its version chains and source links (#731, slice 5) - #984

Merged
github-actions[bot] merged 1 commit into
mainfrom
fix/731-backup-lineage
Nov 11, 2026
Merged

github-actions[bot] merged 1 commit into
mainfrom
fix/731-backup-lineage

Conversation

@cdeust

@cdeust cdeust commented Nov 11, 2026 •

Copy link
Copy Markdown
Owner

Refs #731 (slice 5; the issue stays open, see "Still open").

Summary

Root cause.

The #731 criterion "a consistent backup under concurrent writes, preserving source links and version chains" had no dedicated proof. Slice 3 (#979) proved that a copy holds whole transactions; slice 4 (#983) reads back one memory and one wiki page. Nothing checked that the supersession chain (supersedes_id / superseded_by_id) and each version's source survive the backup and the restore.

What.

Test only, no production change: tests_py/handlers/test_backup_restore_lineage.py.

  • test_a_chain_and_its_sources_are_restored_link_for_link: a live SqliteMemoryStore holds a chain of four versions written by supersede_atomic; after snapshot_backup and restore_backup, the restored rows (id, content, source, both link columns) equal the live rows.
  • test_backups_taken_while_the_chain_grows_restore_one_whole_chain: five backups are taken while another thread keeps extending the chain. Each restored copy holds one chain: every link has its reverse, there is one head, the walk from the head back covers every row, and every version keeps its source. Restored sizes never decrease.

Type of change

Tests only, no production change.

Test plan

  • pytest tests_py/handlers/test_backup_restore_lineage.py: 2 passed, 8 runs in a row (sizes seen in one run: 1, 6, 11, 15, 18 rows).
  • pytest tests_py/handlers/test_backup_restore.py: 14 passed.
  • ruff check and ruff format --check on the new file: clean. scripts/check_craftsmanship.py: OK.

Audit notes

Not verified:

  • Windows and macOS: the CI runs them.
  • The full suite: torch cannot be fetched through this environment's proxy, so the local env was synced without torch and sentence-transformers.

Breaking changes

None.

Still open on #731

  1. Managed PostgreSQL cluster: refused on both the backup and the restore side.
  2. Tested recovery and upgrade-rollback documentation per platform.
  3. No MCP tool or CLI is registered for backup or restore; these are handler functions only.

https://claude.ai/code/session_018kyZYrcoSSQ9a5uRFL2DLD


Generated by Claude Code

…nks (#731, slice 5)

The #731 criterion "a consistent backup under concurrent writes, preserving
source links and version chains" had no dedicated proof: the slice 4 test
reads back one memory. Two tests now restore a SQLite store whose memories
form a supersession chain written by supersede_atomic: once at rest (the
restored rows equal the live rows), and five times while another thread keeps
extending the chain. Every restored copy holds one chain with both directions
of every link, a single head, and the source each version was written from.

Refs #731

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018kyZYrcoSSQ9a5uRFL2DLD
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-11T10:28:17.908118Z 506de48 PR opened
🔒 Security Review ✅ Completed 2026-11-11T10:29:35.326558Z 506de48 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Claude finished @cdeust's task in 2m 27s —— View job


Review of PR #984 (review 1 of 3)

  • Read the diff and CLAUDE.md
  • Run the new tests and lint locally: not done, because uv sync was not permitted in this job (no venv). The review is from reading the code only.
  • Run the five reviewer agents (quality, performance, test coverage, documentation, security)
  • Post the review: review comment

Summary: No Blockers. Three Notes, no action needed before merge:

  • a possible slow-runner race on sizes[-1] > 1 at line 123
  • an O(n²) chain-head walk caused by passing first at line 97
  • the concurrent test is a smoke test, not a deterministic proof of tear-freedom

Verdict: approve

@claude

claude Bot commented Nov 11, 2026

Copy link
Copy Markdown

Review 1 of 3: PR #984

The five reviews (code quality, performance, test coverage, documentation, security) are done. No Blockers.

The tests use only tmp_path stores, close the writer thread's connection, and need no production change. Their assertions check what the PR claims: both directions of every link, one head, a full walk back from the head, and every source. The module docstring's claim about slice 3 holds: see tests_py/infrastructure/test_sqlite_snapshot.py:53, and sqlite_snapshot.py:73 makes the copy in one backup step.

Notes, no action before merge

  • test_backup_restore_lineage.py:123: nothing waits for the writer's first commit before the snapshot loop, so sizes[-1] > 1 could fail on a very slow runner. Setting a threading.Event after the first supersede_atomic and waiting on it would remove the race.
  • test_backup_restore_lineage.py:97: passing first on every call makes _current_chain_head walk the whole chain each time (O(n²) overall). Passing the last new_id would make each write cost the same.
  • test_backup_restore_lineage.py:106-122: nothing records whether a commit happened while a backup was running, so this is a smoke test for tear-freedom. The deterministic guarantee is slice 3's single-step backup.

Not run here: uv sync was not permitted in this job, so I reviewed the code by reading it only. I did not run pytest, ruff or the craftsmanship gate.

View job run
Verdict: approve

@github-actions
github-actions Bot merged commit 13bd36c into main Nov 11, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants