fix(state): make automatic repair non-destructive

Reproduce the schema-btree failure where the in-place writable_schema/VACUUM ladder can reduce a 3,048-page canonical state.db to 113 pages and still return repaired=False.

Move all mutating strategies behind a complete SQLite online-backup snapshot, retain one exclusive SQLite guard from staging through transactional promotion, preserve committed WAL frames and the live inode, fail closed on environmental hazards, and add adversarial regression coverage for failed-repair preservation, post-stage writer races, interrupted copies, stale scratch, disk admission, attempt-ledger semantics, and durability routing.

Fixes #93064
Supersedes the delivery mechanics of #87409 while preserving its implementation provenance.

Co-authored-by: cervantesh <11169707+cervantesh@users.noreply.github.com>
This commit is contained in:
Andrex Ibiza, MBA
2026-08-23 17:39:13 -05:00
committed by Teknium
parent a2a43f7e82
commit 31a01f373b
3 changed files with 1374 additions and 78 deletions
+38 -14
View File
@@ -29,7 +29,7 @@ only the repair-connection durability half.)
from __future__ import annotations
import re
import ast
import sqlite3
import sys
from pathlib import Path
@@ -102,23 +102,47 @@ def test_repair_path_has_no_bare_connects() -> None:
Source-level guard: the bare form is exactly what regressed, and a unit
test on the helper alone would not notice a sixth site being added.
"""
source = Path(hermes_state.__file__).read_text()
pattern = r"^\s*conn = sqlite3\.connect\(str\(db_path\), isolation_level=None\)"
source = Path(hermes_state.__file__).read_text(encoding="utf-8")
tree = ast.parse(source, filename=str(hermes_state.__file__))
# The one legitimate bare connect is inside the helper itself; everything
# after that definition must go through it.
helper = source.index("def _connect_repair_durable(")
body_end = source.index("\ndef ", helper + 1)
inside_helper = re.findall(pattern, source[helper:body_end], flags=re.MULTILINE)
assert len(inside_helper) == 1, (
"_connect_repair_durable no longer opens the connection itself"
def is_db_path_connect(node: ast.AST) -> bool:
if not isinstance(node, ast.Call):
return False
callee = node.func
if not (
isinstance(callee, ast.Attribute)
and isinstance(callee.value, ast.Name)
and callee.value.id == "sqlite3"
and callee.attr == "connect"
):
return False
if not node.args:
return False
first = node.args[0]
return (
isinstance(first, ast.Call)
and isinstance(first.func, ast.Name)
and first.func.id == "str"
and len(first.args) == 1
and isinstance(first.args[0], ast.Name)
and first.args[0].id == "db_path"
)
helper = next(
node
for node in tree.body
if isinstance(node, ast.FunctionDef)
and node.name == "_connect_repair_durable"
)
helper_calls = [node for node in ast.walk(helper) if is_db_path_connect(node)]
assert len(helper_calls) == 1, (
"_connect_repair_durable must own exactly one sqlite3.connect(str(db_path), ...)"
)
elsewhere = re.findall(
pattern, source[:helper] + source[body_end:], flags=re.MULTILINE
)
all_calls = [node for node in ast.walk(tree) if is_db_path_connect(node)]
elsewhere = [node for node in all_calls if node not in helper_calls]
assert elsewhere == [], (
f"{len(elsewhere)} repair-path connection(s) still bypass "
f"{len(elsewhere)} repair/probe connection(s) still bypass "
"_connect_repair_durable() and write state.db without the macOS "
"fsync barriers"
)