# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/why-does-an-instance-forget-a-memory-that-was-never-written-read-write-forget-semantics-and-the-read-after-forget-hazard-under-concurrent-agents.md
# Remnant Warrant:    https://corpusfetch.com/c/why-does-an-instance-forget-a-memory-that-was-never-written-read-write-forget-semantics-and-the-read-after-forget-hazard-under-concurrent-agents.warrant.json
# Markdown SHA-256:   6169855f66df31dafcebfc7d23f9f9694f90f6d78b8085b7ac403d303e7d3e6d
# Code AST SHA-256:   f487ae4b2f3abeee9249ba0d2acb9685a52b0e886c857d9725bfa5391a4a360f
# Verified Classes:   LostWriteUnderTombstone, ForgetWriteOrderViolation, Version
# Defensive Guards:   3 fail-closed invariants (zero external deps)

import hashlib
from dataclasses import dataclass


class LostWriteUnderTombstone(RuntimeError):
    """Raised when a write is acknowledged but shadowed by a concurrent tombstone."""
    pass


class ForgetWriteOrderViolation(RuntimeError):
    """Raised when forget and write are issued as separate, reorderable operations."""
    pass


@dataclass(frozen=True)
class Version:
    seq: int
    tombstone: bool

    def outranks(self, other: "Version") -> bool:
        if self.seq != other.seq:
            return self.seq > other.seq
        # Equal sequence: tombstone wins, deterministically.
        return self.tombstone and not other.tombstone


def safe_forget_then_write(store, key: str, value: bytes, lease) -> Version:
    """
    The only sanctioned pattern: hold a per-key lease, then perform a single
    conditional write that treats the tombstone as a version to beat.
    """
    if not lease.holds(key):
        raise ForgetWriteOrderViolation(
            f"forget/write on {key!r} requires a held lease; "
            f"bare forget-then-write is reorderable under replication"
        )

    current: Version = store.current_version(key)
    candidate = Version(seq=current.seq + 1, tombstone=False)

    if not candidate.outranks(current):
        raise LostWriteUnderTombstone(
            f"write to {key!r} at seq {candidate.seq} does not outrank "
            f"existing {'tombstone' if current.tombstone else 'value'} at seq {current.seq}"
        )

    store.put(key, value, candidate)
    acked = store.current_version(key)

    # Verify the acknowledgment is not shadowed by a concurrent tombstone.
    if acked.tombstone or acked.seq != candidate.seq:
        store.intent_log.append(
            key=key,
            version=candidate.seq,
            value_hash=hashlib.sha256(value).hexdigest(),
        )
        raise LostWriteUnderTombstone(
            f"write to {key!r} acknowledged at seq {candidate.seq} but "
            f"current version is {'tombstone' if acked.tombstone else 'value'} "
            f"at seq {acked.seq}; intent logged for reconciliation"
        )
    return acked
