"""Patch rendering — an overlay as a reviewable diff (FederationRequirements ADR-05). A pure function over (base body, overlay body): the auditable change proposal that an overlay becomes before it is applied. Markdown/native text in this slice (lossless); a lossy native-syntax-with-fidelity-report variant is later (TSD §A.6). """ from __future__ import annotations import difflib from dataclasses import dataclass from shard_wiki.coordination.overlay import Overlay from shard_wiki.model import Identity __all__ = ["Patch", "render_patch"] @dataclass(frozen=True, slots=True) class Patch: target: Identity diff: str @property def is_empty(self) -> bool: return self.diff == "" def render_patch(overlay: Overlay, base_body: str) -> Patch: """Render ``base_body`` → ``overlay.body`` as a unified diff against the overlay target.""" label = str(overlay.target) lines = difflib.unified_diff( base_body.splitlines(keepends=True), overlay.body.splitlines(keepends=True), fromfile=f"a/{label}", tofile=f"b/{label}", ) return Patch(target=overlay.target, diff="".join(lines))