Skip to content

Fix SQLite restore readback sidecars that block interruption recovery #102

Closed

Description

@CompleteDotTech

Confirmed restore interruption defect

Parent: #90. Initiative: #12. Required for trustworthy transition/recovery before #23 completion.

At delivered main 32fd0ab2db99441b5c4bb66973aaefb9deff3dec, trace_gc.phase_transition._file_logical() uses SQLite mode=ro. On the verified Windows runtime, reading a restored WAL-mode database creates an empty graph.sqlite3-wal and a 32,768-byte graph.sqlite3-shm. These remain after the read-only connection closes.

_restore_target_locked() permits the two databases, restore receipt and recognized pending/failed backup artifacts, but excludes these sidecars. An interruption after the public restore completes and before the external coordinator durably records its result therefore leaves a target that the same authorized restore request rejects as partial target has unknown content.

The actual restore completed successfully; its archived original files, export backups, budget reservation and logical graph contents are verified. This issue describes its independently reproduced recovery gap, not a failed actual restore. The actual sidecars were neither deleted nor modified.

Minimal mechanics reproduction

From the delivered checkout with core dependencies installed, run the following Python with bytecode writes disabled. It uses an owned temporary database only:

from pathlib import Path
import sqlite3
import tempfile
from trace_gc.phase_transition import _file_logical

with tempfile.TemporaryDirectory() as directory:
    database = Path(directory) / "graph.sqlite3"
    connection = sqlite3.connect(database)
    connection.execute("PRAGMA journal_mode=WAL")
    connection.execute("CREATE TABLE example (id INTEGER PRIMARY KEY)")
    connection.execute("INSERT INTO example VALUES (1)")
    connection.commit()
    connection.close()
    assert not database.with_name(database.name + "-wal").exists()
    _file_logical(database)
    print({p.name: p.stat().st_size for p in Path(directory).iterdir()})

The complete disposable restore reproduction additionally reaches the real partial-target allowlist under a synthetic authority/capsule fixture. It reproduces rejection on exact reentry. This mechanics fixture intentionally does not establish cryptographic or empirical qualification; the delivered signed transition tests must cover the complete authorization contract.

Proposed causal repair

For these quiescent restored files, close all destination writers, reject preexisting WAL/SHM, and use mode=ro&immutable=1 for logical readback. Check again after close that no sidecar appeared. Do not silently ignore a live/nonempty WAL, broaden the inventory allowlist indiscriminately, remove actual target files, or weaken phase identity/ownership gates.

The reviewed candidate changes only _file_logical() and passes fresh restore, same-request resume and foreign-WAL rejection fixtures. Independent assistant scoped review passed. Its production suitability still requires normal repository tests and delivery.

Evidence and identity

  • Frozen public helper SHA-256: 5acdec9e5c22eac6817a7846bc670b2f51568eca1f47a3638d410161552f40c9.
  • Disposable causal handoff: d5e8b80d3bb3d3eebb1a8f2a12d638600af6e3496dee3fa43281ae841396d33c.
  • Proposed patch: 85a8cbbd3619ae916ebefeaba039aafb3d25aab9dd05c8cdd2b1709bf853add8.
  • Independent scoped review: 0aeaf0806478d29d1cd1b306de2099fde0530d72623bb66a8f75c252d4dbf082.
  • Actual restore and independent fresh verification.

This repair changes the implementation identity. Preserve the frozen live transition checkout, signed releases and receipts. Integrate in an isolated checkout; future use requires a freshly reviewed source identity and phase authorization. Do not hotpatch the existing signed phase or use an old authorization with changed source.

Acceptance criteria

  • Add a regression that fails on the delivered code and covers a real WAL-mode restored database.
  • Fresh authorized restore leaves the two restored stores and its receipt, with no WAL/SHM created by logical verification.
  • Simulate loss of the coordinator result after public restore; the identical signed request reconciles with identical logical contents and receipt.
  • Reject nonempty WAL, unexpected SHM, changed phase binding, changed capsule, stale/conflicting authorization and foreign target content.
  • Preserve the old event chain, graph/catalog/status contents, pending immutable requests and existing reservation; consume no additional budget or model call.
  • Cover the Windows behavior and supported SQLite/Python environments; retain all existing phase and interruption regressions.
  • Review final diff; complete core/PDF release and package gates, verified signing, exact-head hosted CI, merge and postmerge verification.
  • Document identity migration requirements and any handling needed for targets restored by the previous implementation; keep actual historical artifacts untouched and Support explicitly authorized PaperPilot runtime transitions without losing history #90/Implement and validate a real paper-to-graph-to-cited-answer pilot #23 open until their remaining criteria pass.

Delivered repair and acceptance readback — 2026-10-01

Delivered in PR #103 and the isolated adversarial-test follow-up PR #104. Final verified merge: 7f01f3389e3360ba89ac780f585c9f83c9ec2aae; tree: d98347f701576931a71b0c14a772662fc80bd181. Postmerge CI passed Python 3.11, 3.12 and 3.13.

The eight acceptance criteria above are met for this public code repair. The WAL regression reproduces actual Windows SQLite sidecar behavior. Signed authored restore/reentry tests cover identical-request reconciliation and unchanged budget; negative cases independently isolate capsule drift and freshly signed conflicting authorizations. These restore tests use a synthetic capsule and fence fixture. They establish the API mechanics, not a new real historical-phase restore.

Final signed-head release gate: 1,403 tests run, 1,395 passed, eight documented optional skips, zero failures/errors. PDF coverage passed. Skips comprise two optional NumPy tests, five Windows symlink privilege tests and one external pinned-core test. Package validation, owned installation, CLI version and 66 installed-file comparisons passed. Source ZIP SHA-256 96d2f4f282732d8db4abc6827c2dab74641726bce5f6faee1eeb97394af01645: all 619 members match signed Git and the clean delivered tree.

The delivered immutable reader also verified the four actual closed historical backup databases and preserved their byte/logical identities, 39 checkpoint events, 11 journal events, 19 completed requests, eight source statuses and the existing reservation of one model call / 14,120 request bytes. This was read-only verification: no new restore, import, activation, provider call or graph write. The historical provider outcome remains UNKNOWN_UNATTESTED; its reservation is not evidence of a provider outcome.

Evidence SHA-256: final acceptance audit bed1fec8a47fd465f8ead3087776f3380362b63d41997b9989bdc5f88486173c; final full-validation receipt c1f06a79788fbd13ab2994a1c09fb58bcd4db30ed47f386b3e24fc59ed8bc20a; postmerge/package readback 5671f5b21d53d40555f683d96df573c248b1c459a72cd9746cb2ba66815016bb; actual closed-capsule readback ffc5555cb177b566b415dc67f403091ddc4fc5c78f8579caca080207115731c4; independent actual-capsule review e5bc1aae5be77d9d62bcbeb5b464f14b49a037050b8cc5bfca55d2e6dce29be9.

The frozen historical 32fd transition checkout, its old sidecars, signed releases and receipts remain preserved. The new helper changes implementation identity and requires separately reviewed phase authorization before any future use. Closing this repair leaves #90, #23 and epic #12 open for their remaining real recovery and empirical acceptance gates.

Activity

  1. added
    bugSomething isn't working
    area:storageGraph read adapters, indexes, and persistence
    initiative:paper-graphragPaper extraction, evidence admission, retrieval and real GraphRAG qualification
    area:reproducibilityPinned runtimes, immutable inputs, provenance and replay
    priority:P1Required to repair known correctness failures or make acceptance evidence trustworthy
    on Oct 1, 2026
  2. CompleteDotTech commented on Oct 1, 2026

    @CompleteDotTech
    CollaboratorAuthor

    Verified delivery and remaining acceptance audit

    PR #103 merged as 31b21b6c9035356a5f106a74c31d94eddb51d297. GitHub verifies the merge signature; its tree equals the reviewed, locally SSH-verified PR head 80489bdc2bcec294294752eb0bc5582a754f844b.

    • All six exact PR-head CI jobs passed. Exact merge/main run 36823348043 passed on Python 3.11, 3.12 and 3.13.
    • Fresh Windows postmerge phase checks: 31 passed, zero skips. The initial isolated test launcher omitted the checkout from its import path; that invocation failed at import and was preserved. The corrected launcher explicitly imports the delivered checkout and passes.
    • Premerge release gate: 1,402 tests, 1,396 passed, six documented skips, with actual optional PDF coverage. Package validation, installation, and the audited 619-member source ZIP passed. Generated artifacts were reviewed; the ZIP and delivered source tree match.
    • Postmerge CI evidence identity: 683cf1802858ba5af301c5cf8b651c3a4f3fd4f6d33f03f2d47c641a218e21b5.

    The final acceptance audit found two negative-test gaps: the changed-capsule assertion can be masked by an existing foreign file, and a validly signed but conflicting authorization needs an explicit test. Follow-up test work is underway; #102 remains open until those checks are delivered and verified. Audit identity: ea70bdbca0ed33c25769fa5899ebb388905cffdf34a56d824f33d6ae3efa7a9c.

    The historical transition checkout and signed phase remain pinned to their original implementation. They were not hotpatched. Future use of the new implementation requires a new reviewed identity and appropriate authorization. #90 and #23 remain open.

    The original 200-paper extraction method map matches delivered main in 87/87 files. The image closure matches 128/129, with the sole delta in this phase-transition repair. Its historical acceptance receipt remains unchanged; a new reviewed mapping or gate is required for exact current image binding. This is not a new 200-paper run or unseen qualification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:reproducibilityPinned runtimes, immutable inputs, provenance and replayarea:storageGraph read adapters, indexes, and persistencebugSomething isn't workinginitiative:paper-graphragPaper extraction, evidence admission, retrieval and real GraphRAG qualificationpriority:P1Required to repair known correctness failures or make acceptance evidence trustworthy

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions