# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/why-does-an-instance-of-a-memory-record-survive-its-own-forgetting-the-tombstone-write-ordering-invariant-in-scoped-retention-apis.md
# Remnant Warrant:    https://corpusfetch.com/c/why-does-an-instance-of-a-memory-record-survive-its-own-forgetting-the-tombstone-write-ordering-invariant-in-scoped-retention-apis.warrant.json
# Markdown SHA-256:   db6e22fb40d6a6ac65314e3adad9e545008972960210c46cab17154fe8f7a62a
# Code AST SHA-256:   86310c06d7db478e6f0e39741ccaaeee5c5d92ae89589071f4ff10a14fc288b7
# Verified Classes:   ForgetInvariantViolation, MemoryRecord, ScopedMemory
# Defensive Guards:   3 fail-closed invariants (zero external deps)

class ForgetInvariantViolation(RuntimeError):
    """Raised when a write or sweep would violate the forget-watermark invariant."""
    pass


class MemoryRecord:
    def __init__(self, key, generation, value, expires_at, is_tombstone=False):
        self.key = key
        self.generation = generation
        self.value = value
        self.expires_at = expires_at
        self.is_tombstone = is_tombstone


class ScopedMemory:
    def __init__(self):
        # key -> highest generation for which a forget has returned successfully
        self.forget_watermark = {}
        # key -> MemoryRecord (value or tombstone)
        self.records = {}

    def forget(self, key, generation):
        if generation <= self.forget_watermark.get(key, -1):
            raise ForgetInvariantViolation(
                f"forget for {key!r} at gen {generation} does not advance watermark "
                f"{self.forget_watermark.get(key)}"
            )
        self.forget_watermark[key] = generation
        self.records[key] = MemoryRecord(key, generation, None, float("inf"), is_tombstone=True)

    def write(self, key, generation, value, expires_at):
        watermark = self.forget_watermark.get(key, -1)
        if generation <= watermark:
            raise ForgetInvariantViolation(
                f"write for {key!r} at gen {generation} is at or below forget "
                f"watermark {watermark}; refusing to resurrect forgotten key"
            )
        self.records[key] = MemoryRecord(key, generation, value, expires_at)

    def sweep(self, key, now):
        rec = self.records.get(key)
        if rec is None:
            return
        watermark = self.forget_watermark.get(key, -1)
        if rec.generation <= watermark:
            # Safe to collect: the watermark outlives the record.
            del self.records[key]
            return
        if not rec.is_tombstone and rec.expires_at <= now:
            # TTL expiry with no forget above this generation: collect value,
            # but never collect past the watermark.
            if rec.generation > watermark:
                del self.records[key]
                return
        raise ForgetInvariantViolation(
            f"sweeper refused to touch {key!r}: gen {rec.generation} "
            f"vs watermark {watermark} (tombstone={rec.is_tombstone})"
        )
