hazard-detector

unverified
v0.2.0 AOI: bbox -89.60, 30.15, -89.00, 30.55

Wetland and forest CHANGE over a Gulf Coast county, delivered as a subscribable alert and ranked by community vulnerability. Two Sentinel-2 composites per AOI — a baseline window and a current window — give NDVI (vegetation vigour) and MNDWI (open water / wetland inundation). The bitemporal deltas fire two independent arms: vegetation LOSS when NDVI drops past a threshold, wetland CHANGE when MNDWI moves either direction past a threshold. A cell fires if either arm crosses, and carries both deltas plus which arm drove it, so a reader sees "NDVI 0.75 -> 0.35 (-0.40) => forest loss" rather than a bare boolean. What the incumbent self-serve alert surfaces never combine is the second half: each firing is joined to its CDC/ATSDR Social Vulnerability Index tract and carries that tract's percentile, so county planners and emergency managers (MEMA / Gulf Coast counties, the named end-users) can triage by who is least able to absorb the change. The SVI RANKS delivery. It never gates detection — the fire set is identical at every svi_floor. The detector is not novel science and does not try to beat GFW or DIST-ALERT at detection. What it demonstrates is subscription + vulnerability-contextualized delivery to non-developer end-users, composed entirely from shipped ops (imagery_composite + stack_concat + raster_calc). No new op.

License
recipe
Apache-2.0
outputs
CC-BY-4.0
Map preview and live runs are available in the workbench.

The contract

governed folia/0.1

Read from this recipe's own declarations — parameters:, outputs:, requires:, and the ops its layers name. Not from its style blocks and not from any benchmark: a colour ramp is not a contract, and a measured run is evidence about one AOI rather than a domain.

Parameters

parametertypedomaindefaultwhat it does
aoi_bbox bbox [-89.6,30.15,-89,30.55] Watched extent [w, s, e, n] in WGS84. Default covers Hancock/Harrison County on the Mississippi Gulf Coast — the ms-wetlands study area. A subscription overrides this with the county geometry it watches.
baseline_start string 2023-01-01 Start of the BEFORE reference window.
baseline_end string 2023-12-31 End of the BEFORE reference window. A full calendar year by default, so the median composite averages over a whole phenological cycle rather than one season — a baseline built from summer scenes alone would read every winter current-window composite as vegetation loss.
current_start string 2026-01-01 Start of the AFTER window under test.
current_end string 2026-06-30 End of the AFTER window under test. Shorter than the baseline on purpose: this is the recent state, and a subscription's dispatcher advances it as new overpasses land (see extensions.folia/freshness-ref).
veg_loss_threshold number >= 0, <= 2 0.15 NDVI drop that counts as vegetation/forest loss. The veg arm fires where (ndvi_baseline - ndvi_current) >= this value.
wet_change_threshold number >= 0, <= 2 0.15 |MNDWI| change that counts as wetland change. The wetland arm fires where |mndwi_current - mndwi_baseline| >= this value. Magnitude, not sign: a marsh that floods and a marsh that dries are both changes an emergency manager wants.
min_affected_area integer >= 1 3 Minimum contiguous fired cells before the SUBSCRIPTION notifies (it maps to the trigger's `min_cells`, ALERTS §3). It suppresses single-cell speckle; it does not change what the detector flags.
svi_floor number >= 0, <= 1 0 OPTIONAL vulnerability triage on DELIVERY. When greater than 0, only firings whose containing tract's SVI percentile (RPL_THEMES) is at or above this value are delivered; every delivered firing carries its SVI context either way.
composite_method string one of median, mean, min, max median Per-pixel reduction over the scene stack in each window. Median by default because it is the reduction that survives residual cloud the SCL mask missed — a mean lets one bright cloud edge pull a whole composite.
scene_limit integer >= 1 24 Scene budget PER YEAR, not per window (imagery_composite stratifies its search by year). At 24 the 2023 baseline draws up to 24 scenes and the 2026 current window up to 24 more. WHY 24: roughly one clear-ish Sentinel-2 pass per fortnight, which is enough for a stable annual median over a cloudy subtropical coast; the op default of 6 admits visible cloud residue into the median at this latitude.
target_resolution_m number >= 1 20 Grid all four composites snap to, in metres.

Outputs

outputkindlayerwhat it is
hazard raster alerts/hazard-detector THE hazard output: per-cell change score, thresholdable at 1.0. A subscription watches this layer; a crossing becomes a firing carrying the deltas, the driving arm, and the affected tract's SVI percentile (extensions.folia/firing-provenance).
dndvi raster compute/dndvi Bitemporal NDVI change (current - baseline) behind the vegetation arm.
dmndwi raster compute/dmndwi Bitemporal MNDWI change (current - baseline) behind the wetland arm.
ndvi_baseline raster compute/ndvi-baseline The BEFORE vegetation composite.
ndvi_current raster compute/ndvi-current The AFTER vegetation composite.
mndwi_baseline raster compute/mndwi-baseline The BEFORE water/wetland composite.
mndwi_current raster compute/mndwi-current The AFTER water/wetland composite.

Capabilities it requires

Declares no requires: block, so it asks nothing of a host beyond the engine itself.

Where it runs

  • Browser preview does not run here alerts/_delta-stack: depends on layer "compute/dndvi", which cannot run here; alerts/hazard-detector: depends on layer "alerts/_delta-stack", which cannot run here; compute/dmndwi: depends on layer "compute/dmndwi-stack", which cannot run here; and 7 more
  • Local CLI (folia run) runs here runs locally through the governed folia/0.1 parser
  • Operated fleet (POST /plan, /run) runs here binds to a canonical digest, so a lock is checked by digest equality
open in Workbench from registry/recipes/hazard-detector/folia.yaml