"""Review state-transition core (pure, tested): proposed -> approved. No I/O, no clock — the timestamp is injected so the logic stays deterministic. The CLI persists the result via hef.catalog.save_catalog after re-validating. """ from __future__ import annotations from dataclasses import replace def proposed_records(records): """Records still awaiting review.""" return [r for r in records if r.review_status == "proposed"] def approve(record, *, reviewed_at, coordinate=None, rationale=None): """Return an approved copy of `record` (the input is not mutated). review_status -> 'approved' and reviewed_at is stamped. Optionally override the four coordinates with a human correction and/or replace the rationale. The caller re-validates before saving. """ changes = {"review_status": "approved", "reviewed_at": reviewed_at} if coordinate is not None: changes.update( left=coordinate.left, right=coordinate.right, dark=coordinate.dark, light=coordinate.light, ) if rationale is not None: changes["rationale"] = rationale return replace(record, **changes)