← Compliance Horizon ScannerCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Compliance Horizon Scanner
Snapshot Sep 30, 2026 · 23:16 UTC · version 0.2.0+codex.20260914234654
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"name": "horizon-scan",
"description": "Scan US federal, optionally selected US states, EU, and UK primary regulatory sources for new and upcoming changes since the user's last scan, scoped to their saved compliance profile, and return each finding with a source citation and a materiality score. Use when the user asks what regulatory or compliance changes affect their business, what is new since their last scan, what is coming up, or which consultations are open. Requires a compliance profile; if the user has none, run the compliance-profile skill first.",
"included_files": [],
"skill_md_contents": "---\nname: horizon-scan\ndescription: Scan US federal, optionally selected US states, EU, and UK primary regulatory sources for new and upcoming changes since the user's last scan, scoped to their saved compliance profile, and return each finding with a source citation and a materiality score. Use when the user asks what regulatory or compliance changes affect their business, what is new since their last scan, what is coming up, or which consultations are open. Requires a compliance profile; if the user has none, run the compliance-profile skill first.\n---\n\nRead `../../references/runtime-safety.md` before using this workflow. Resolve relative paths from this skill directory. To use a sibling skill, read its `../<skill-name>/SKILL.md`; no special invocation tool is required.\n\n\nProduce a deduplicated, source-cited list of regulatory developments relevant to one specific\nbusiness, with a materiality score on each.\n\n**Read `../../references/citation-discipline.md` before producing any output. It governs everything\nbelow, and where anything here appears to conflict with it, it wins.** The short version: every\nclaim needs a link fetched in this session, a verbatim supporting quote, and per-claim sourcing for\ndates, deadlines, thresholds, and penalties. No link, no claim.\n\n---\n\n## 1. Get the profile\n\nAsk the user for their saved compliance profile block. If they don't have one, run\n`compliance-profile` first — do not scan against guesses about their business, because a scan scoped\nto the wrong business is worse than no scan.\n\nRead `../../references/profile-schema.md` to interpret it. Extract:\n\n- `last_scan_date` → the start of the scan window. Today is the end.\n- `operating_jurisdictions` → which source registry files to use\n- `coverage.us_states` → optional selected states; absent means none\n- `coverage.pending_state_baselines` → first/re-enabled state windows from the schema\n- `coverage.pending_scope_baselines` → historical and standing-law checks for scope changes\n- `domains_in_scope` → which domain sections apply\n- `exposure_flags` → the applicability triggers\n- `materiality_thresholds` → the reporting cut\n- `reported_ledger` → what to suppress\n- `watch_keywords` / `exclude_keywords` → extra searches and noise suppression\n\nState the window and scope back to the user in one line before scanning, so a wrong profile is\ncaught before the work rather than after:\n\n> Scanning 2026-07-11 → 2026-09-09 · US-Federal, EU, UK · privacy_ai, employment, esg,\n> trade_sanctions, consumer_protection · reporting at medium and above.\n\n## 2. Announce uncovered jurisdictions — before scanning, not after\n\nAnnounce selected states (or “state coverage off”), their scan windows, and any profile\nstates not selected. Identify EU member-state implementation, local law, and unsupported\njurisdictions as excluded. For example:\n\n> State research enabled: California and New York. Not searched: Texas (not selected),\n> city/county law, and EU national implementation. Source coverage will be reported by state.\n\nThis goes first, not in a footnote. A user who believes a jurisdiction was searched when it was not\nis the worst outcome this skill can produce.\n\n## 3. Select sources\n\nLoad only the registry files you need:\n\n- `US-Federal` → `../../references/sources-us-federal.md`\n- Nonempty `coverage.us_states` → `../../references/sources-us-states.md`\n- `EU` → `../../references/sources-eu.md`\n- `UK` → `../../references/sources-uk.md`\n\nThen read `../../references/cross-industry-domains.md` for the domains in scope, to get the\napplicability triggers and the agency slugs and feeds to watch per domain.\n\n## 4. Query primary sources first\n\nBefore ordinary delta queries, process pending scope baselines under `profile-schema.md`.\nAnnounce their affected scope and historical window separately. Search older developments and\ncurrent standing obligations, including older rules with ongoing duties or transitions; do not\nconstrain that standing-law review by publication date. Use the relevant baseline start instead\nof last_scan_date in historical queries below. Preserve pending entries on incomplete research.\n\nWork the registry in tier order — `primary`, then `regulator`. Start from the official registers when available; use official-domain search as a\nfallback to find primary documents, and disclose incomplete enumeration. Do not rely on commentary; the registers are structured, complete for their scope, and citable.\n\n**US federal.** Query the Federal Register API once per relevant agency slug, plus once per\n`watch_keyword` using `conditions[term]`. Always set\n`conditions[publication_date][gte]=<last_scan_date>` and `[lte]=<today>`. Follow all result\npages, or report the unprocessed range as a coverage gap. Request the full field list from the registry\nfile. Check `count` before paging; a wide window across many agencies can return thousands.\n\n**Selected US states.** Follow `sources-us-states.md` for each selected state and its\nbaseline window: discover official legislature, register/code, and relevant regulator\nsources, search the profile domains, and record actual coverage for every source family.\nDo not treat federal sources as state coverage. Keep state identifiers namespaced in the\nledger and return partial/deferred states explicitly.\n\n**EU.** The OJ L feed covers only the last few days. For any window longer than that, also use\nEUR-Lex search or the SPARQL endpoint. **If you cover only part of the window, the EU result is\npartial and must be labelled as such** — a feed-only result presented as a full-window EU scan is\nthe most likely way this skill produces a false \"nothing new.\"\n\n**UK.** Use the dated `/new/uk/<date>` endpoints across the window, or the year feeds filtered by\n`ukm:CreationDate`. Separate `UnitedKingdomDraftStatutoryInstrument` (stage `proposed`) from\n`UnitedKingdomStatutoryInstrument` (made, but check commencement).\n\n## 5. Filter\n\nIn this order:\n\n1. **Ledger comparison.** Follow `profile-schema.md`: re-fetch pending/future ledgered\n instruments as well as new candidates. Suppress only after checking stage and material\n changes. Re-report verified changes as updates. Legacy string IDs have unknown prior\n stages; do not fabricate history or suppress a possible update without checking.\n2. **Exclude keywords.** Drop title/summary matches on `exclude_keywords` — unless the item matches\n an `always_report` tag, which overrides exclusion.\n3. **Applicability.** Apply the domain triggers against `exposure_flags`. Drop confirmed `not_applicable` items even when a liability keyword matches.\n Keep `unassessed` items separate as applicability questions, not confirmed duties.\n\n## 6. Open the sources and score\n\nFor each surviving candidate, **fetch the actual document.** Feed metadata and API abstracts are\ntriage only — they are not sources for a finding. This is the step that costs time and the step\nthat makes the output trustworthy, so do not skip it to cover more items. Fewer fully sourced\nfindings beat more thinly sourced ones.\n\nFrom the document, extract and quote:\n\n- lifecycle stage, from the document's own words\n- every date: comment deadline, entry into force, applies-from, staged milestones, first reporting\n- any scope threshold that decides whether it binds this business\n- penalty and liability exposure\n\nThen score against `../../references/materiality-rubric.md` on all five axes, naming the profile\nfield that drove applicability.\n\n**Where a date must be computed** — an EU act's \"twentieth day following publication,\" say — show\nthe arithmetic, quote the provision it rests on, and label the result as derived rather than\npresenting it as a date the instrument states.\n\n**Where no date is published**, the value is `undated`. Never estimate. A proposed US rule has\n`effective_on: null`; that is a fact to report, not a gap to fill.\n\n## 7. Run the provenance self-check\n\nWalk every finding against the checklist in `citation-discipline.md`:\n`source_url` fetched this session and pointing at the document; `official_id` present;\n`supporting_quote` verbatim; every date, deadline, threshold, and penalty traced to a quote;\nlifecycle stage matching the source; nothing secondary-tier presented as a finding.\n\nMove every failure to **Coverage gaps** or **Unverified leads**. Do not repair a weak finding by\nsoftening its language — an unsourced claim hedged with \"reportedly\" is still an unsourced claim.\n\n## 8. Output\n\n```\n## Horizon scan · <profile_name>\nWindow 2026-07-11 → 2026-09-09 · US-Federal, EU, UK · threshold: medium\n\n**Not covered:** <uncovered jurisdictions, or \"none\">\n**Provenance:** N findings, N fully sourced · N coverage gaps · N unverified leads\n\n### Needs attention now\n<always_report matches and items where effort exceeds lead time>\n\n### Findings — <jurisdiction>\n<ordered per the rubric: always_report, then impact, then timeline, then applicability>\n\nEach finding:\n**<Title>** · `<stage>` · <official_id>\n<One line on what it does.>\n- applicability: `binds_us` — <profile field and threshold, with quote>\n- impact: `high` · effort: `policy_change` · timeline: `30-90` (to <which date>) · confidence: `high`\n- <each date with its own quote and link>\n- source: <link> (<publisher>, <tier>, retrieved <date>)\n\n### Open consultations — you can still influence these\n<items with a live comment deadline, soonest first, with the deadline quoted and the link to respond>\n\n### State source coverage\n<each selected state, source families/URLs, domains, window, and completeness; or “off”>\n\n### Coverage gaps\n<each failed source, what it would have covered, and the date attempted>\n\n### Unverified leads\n<secondary-tier signals with no primary source reached — explicitly not findings>\n\n### Updated profile — save this\n<the full profile block with new last_scan_date and extended reported_ledger>\n\n---\nRegulatory intelligence, not legal advice. Verify against the cited primary sources before acting.\n```\n\nLead with **open consultations** in your summary remarks when any deadline is close. The chance to\nshape a rule before it binds is often worth more to the user than notice after it has.\n\n## 9. Emit the updated profile\n\nFor each verified finding, append the structured deadline and rule-detail snapshot required by\nthe schema. Include an explicit previous → current comparison for verified changes, retaining\nprior sources. Separate newly relevant older rules from actual legal amendments. Unknown previous\nvalues are labeled baseline unavailable. Clear completed scope baselines only after standing-law\nand historical checks succeed; retain partial entries and explain their outstanding work.\n\nFollow `profile-schema.md` for ledger records, legacy IDs, and pruning. Set `last_scan_date`\nto today only after a complete scan of the profile's supported scope. On source failures,\npartial paging, a narrowed request, or an interrupted scan, retain the previous boundary\nand explain that the next scan must retry it. Save sourced findings in the ledger either way.\nChange no business fields without the user's request.\n\nTell the user plainly that the scan is only incremental if they save this block. That is the whole\ndelta mechanism, and it fails silently if they don't.\n\n---\n\n## Notes on judgement\n\n**A first scan is a baseline, not a delta.** With `last_scan_date` bootstrapped 90 days back across\nfive domains and three jurisdictions, expect a long list. Say so, and offer to narrow the window or\nraise the threshold instead of returning something unmanageable.\n\n**\"Nothing new\" is a legitimate result** — but only say it when the sources actually returned\nnothing, and never when a source failed. A failed source produces a coverage gap, and the honest\nsentence is \"no changes found in the sources that responded, with N gaps,\" not \"nothing new.\"\n\n**Volume is not value.** The registers carry a great deal of sector-specific matter irrelevant to any\none business. A scan returning six things that matter is more useful than one returning sixty, and\npadding a scan with `monitor_only` items to look thorough works directly against the user.\n\n**Don't let a big-name regulation crowd out a small binding one.** A minor SI that actually binds\nthis business outranks a landmark regulation that doesn't. Score against the profile, not against\nhow much the instrument has been in the news.\n"
}SHA-256: 10ed5287dcccf6d5b7a12a301fdeeeb4007db4f05bbfc48ff2b845533deb464e