"""Layer 2: structured field comparison. Compares the *set* of items (job postings, press releases, filings, products - whatever the source's documents represent) between two snapshots' `structured_summary["urls"]`/`["titles"]`. This is what catches "a new job posting appeared" or "a press release was removed" without needing a bespoke parser per source type - collection_service already records the full current item set on every run, so this is a plain set diff between two runs. """ from __future__ import annotations from dataclasses import dataclass, field @dataclass(frozen=True) class StructuredDiff: added: list[str] = field(default_factory=list) removed: list[str] = field(default_factory=list) @property def has_changes(self) -> bool: return bool(self.added or self.removed) def diff_item_sets(previous_urls: list[str], current_urls: list[str]) -> StructuredDiff: previous_set = set(previous_urls) current_set = set(current_urls) return StructuredDiff( added=sorted(current_set - previous_set), removed=sorted(previous_set - current_set), )