# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference) # Canonical Residual: https://corpusfetch.com/c/how-must-an-instance-recover-memory-consistency-after-a-corrupted-write-ahead-log.md # Remnant Warrant: https://corpusfetch.com/c/how-must-an-instance-recover-memory-consistency-after-a-corrupted-write-ahead-log.warrant.json # Markdown SHA-256: a19c83dedb38d2d4431911a8cfed8127d78e92c768864f6437ba7a0c1ada20d8 # Code AST SHA-256: 88cc63539606e1f3ce32dab65348998260e06c1ed187161af1da7b62da44bff1 # Verified Classes: WALVerdict, WALEntry, WALState, WALRecoveryPolicy, WALManifest, WALCorruptionGuard # Defensive Guards: 0 fail-closed invariants (zero external deps) from dataclasses import dataclass from enum import Enum, auto import hashlib import json class WALVerdict(Enum): WAL_INTACT = auto() RECOVERABLE_FROM_CHECKPOINT = auto() CORRUPTION_BOUNDARY_DETECTED = auto() UNRECOVERABLE_CORRUPTION = auto() @dataclass(frozen=True) class WALEntry: entry_id: str entry_hash: str previous_hash: str sequence_number: int is_corrupted: bool @dataclass(frozen=True) class WALState: entries: tuple[WALEntry, ...] last_checkpoint_epoch: float | None checkpoint_state_hash: str | None @dataclass(frozen=True) class WALRecoveryPolicy: require_checkpoint: bool allow_partial_replay: bool @dataclass(frozen=True) class WALManifest: verdict: WALVerdict replay_until_sequence: int | None directive: str manifest_digest: str class WALCorruptionGuard: @staticmethod def _hash(data: str) -> str: return hashlib.sha256(data.encode("utf-8")).hexdigest() @classmethod def evaluate_wal( cls, state: WALState, policy: WALRecoveryPolicy ) -> WALManifest: # Gate 1: Corruption detection corrupted_entries = [e for e in state.entries if e.is_corrupted] if not corrupted_entries: digest = cls._hash(json.dumps({ "entries": str(len(state.entries)), "checkpoint": state.last_checkpoint_epoch }, sort_keys=True)) return WALManifest( verdict=WALVerdict.WAL_INTACT, replay_until_sequence=max((e.sequence_number for e in state.entries), default=0), directive=f"PROCEED: WAL intact, {len(state.entries)} entries.", manifest_digest=digest ) # Gate 2: Checkpoint availability if not state.last_checkpoint_epoch or not state.checkpoint_state_hash: if policy.require_checkpoint: return WALManifest( verdict=WALVerdict.UNRECOVERABLE_CORRUPTION, replay_until_sequence=None, directive=f"HALT: Corruption detected, no checkpoint, checkpoint required.", manifest_digest=cls._hash("NO_CHECKPOINT") ) # Gate 3: Hash chain verification sorted_entries = sorted(state.entries, key=lambda e: e.sequence_number) last_valid_sequence = 0 previous_hash = "GENESIS" for entry in sorted_entries: if entry.is_corrupted or entry.previous_hash != previous_hash: break if not entry.entry_hash: break previous_hash = entry.entry_hash last_valid_sequence = entry.sequence_number # Gate 4: Partial replay if last_valid_sequence > 0: digest = cls._hash(json.dumps({ "replay_until": str(last_valid_sequence), "corrupted_at": str(sorted(corrupted_entries, key=lambda e: e.sequence_number)[0].sequence_number), "checkpoint": f"{state.last_checkpoint_epoch:.0f}" if state.last_checkpoint_epoch else "NONE" }, sort_keys=True)) return WALManifest( verdict=WALVerdict.CORRUPTION_BOUNDARY_DETECTED, replay_until_sequence=last_valid_sequence, directive=f"PROCEED: Replay up to sequence {last_valid_sequence}, stop at corruption.", manifest_digest=digest ) # Gate 5: Checkpoint-only recovery if state.last_checkpoint_epoch: digest = cls._hash(json.dumps({ "checkpoint": f"{state.last_checkpoint_epoch:.0f}", "state": state.checkpoint_state_hash }, sort_keys=True)) return WALManifest( verdict=WALVerdict.RECOVERABLE_FROM_CHECKPOINT, replay_until_sequence=0, directive=f"PROCEED: Recover from checkpoint at {state.last_checkpoint_epoch:.0f}, skip WAL replay.", manifest_digest=digest ) return WALManifest( verdict=WALVerdict.UNRECOVERABLE_CORRUPTION, replay_until_sequence=None, directive="HALT: No valid WAL prefix and no checkpoint.", manifest_digest=cls._hash("UNRECOVERABLE") )