# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/which-invariants-prevent-undetected-memory-poisoning-in-shared-agent-stores-the-write-provenance-gap-at-the-read-merge-boundary.md
# Remnant Warrant:    https://corpusfetch.com/c/which-invariants-prevent-undetected-memory-poisoning-in-shared-agent-stores-the-write-provenance-gap-at-the-read-merge-boundary.warrant.json
# Markdown SHA-256:   cf85fb1768281ea6f5cc5227263711a39527a6d3aee8a0c6ba2e0a90543878f7
# Code AST SHA-256:   78f7e59b2e548c3b4b3c7fdb2092b864e7bd3d4a6abc42856c3ab39dba931645
# Verified Classes:   ProvenanceContinuityError, MemoryRecord
# Defensive Guards:   2 fail-closed invariants (zero external deps)

import hashlib
from dataclasses import dataclass


class ProvenanceContinuityError(RuntimeError):
    """Raised when a memory record's provenance is not bound to its payload at read time."""
    pass


@dataclass(frozen=True)
class MemoryRecord:
    payload: str
    content_hash: str
    trust: int
    lineage: tuple  # writer ids contributing to this record


def canonical(payload: str) -> bytes:
    return payload.encode("utf-8").strip()


def content_hash(payload: str) -> str:
    return hashlib.sha256(canonical(payload)).hexdigest()


def admit_for_read(record: MemoryRecord, required_trust: int, banned_writers: set) -> bool:
    # Invariant 1: provenance is bound to the exact payload bytes served.
    if record.content_hash != content_hash(record.payload):
        raise ProvenanceContinuityError(
            f"content_hash mismatch on read: attested={record.content_hash!r} "
            f"actual={content_hash(record.payload)!r}; record was mutated after attestation"
        )

    # Invariant 2: derived records inherit the MINIMUM trust of their lineage,
    # never the first-writer's or maximum trust.
    effective_trust = min([record.trust, *(record.trust for _ in record.lineage)]) \
        if record.lineage else record.trust

    # Invariant 3: any banned contributor taints the whole record.
    if banned_writers.intersection(record.lineage):
        raise ProvenanceContinuityError(
            f"lineage contains banned writer(s): {banned_writers.intersection(record.lineage)}"
        )

    if effective_trust < required_trust:
        return False
    return True


def merge_records(a: MemoryRecord, b: MemoryRecord) -> MemoryRecord:
    merged_payload = a.payload + "\n" + b.payload
    return MemoryRecord(
        payload=merged_payload,
        content_hash=content_hash(merged_payload),  # re-attest derived record
        trust=min(a.trust, b.trust),                # min-trust propagation
        lineage=tuple(set(a.lineage) | set(b.lineage) | {a.trust, b.trust}),
    )
