from __future__ import annotations import json from pathlib import Path from typing import Any def load_registry(root: str | Path) -> dict[str, Any]: path = Path(root) / 'lineage' / 'DONOR_REGISTRY.json' if not path.exists(): return {'version': 'unavailable', 'donors': []} return json.loads(path.read_text(encoding='utf-8')) def lineage_summary(root: str | Path) -> str: registry = load_registry(root) donors = registry.get('donors', []) embedded = [d for d in donors if d.get('embedded')] indexed = [d for d in donors if not d.get('embedded')] lines = [ '# Source-Lineage Surface', '', f"Registry version: `{registry.get('version', 'unknown')}`", '', f"Embedded donor archives: **{len(embedded)}**", f"Hash-indexed heavy/private donors: **{len(indexed)}**", '', '## Governing law', '- Authority(State) must not exceed Support(Lineage).', '- Receipt presence is not equivalent to semantic validation.', '- External model review is assistance, not authority.', '- A repair compiler may prepare a descendant but may not silently replace its ancestor.', '', '## Embedded donors', ] for d in embedded: lines.append(f"- `{d['name']}` — {d.get('role','')} — `{d.get('sha256','')}`") lines.extend(['', '## Indexed but not embedded']) for d in indexed: lines.append(f"- `{d['name']}` — {d.get('reason_not_embedded','indexed only')} — `{d.get('sha256','')}`") return '\n'.join(lines)