Skip to content

Prediction engine

Last reviewed against the codebase: 2026-08-06 (Phase 15.4 prove-it loop + 15.2.1 directional-uncertainty corridor UX).

Fire Path AI exists to predict where a bushfire will go, over time, correctly — and to prove it. This page is the developer-facing narrative for that engine: what it does today (honestly), the gaps, and the staged plan that closes them. The authoritative, always-current capability status lives in the repo at PREDICTION-STATUS.md; the full plan is PHASE-15-PREDICTION-ENGINE-PLAN.md.

1. What the engine does today (code-verified, post-S0)

  • Spread footprint (default, PREDICTION_ENGINE=advected)lib/spread-model/src/index.ts (computeAdvectedFootprint) is the default: Lagrangian marker advection marches the front through space — each marker advances from its current position each forecast hour — so the corridor physically curves with the veering forecast (a swept banana/comma corridor), not just reorienting. It self-falls-back to the radial lobe if a marker ring ever degenerates (safe as the default). computeSpreadFootprint (=own) is the radial-lobe alternative — it reorients + elongates with the forecast but its edges are straight radials from the ignition. Both use one unified McArthur rate. Phase 15.2.1 directional-uncertainty UX: horizons 1/3/6/12 h; the corridor fans wider at longer horizons (a horizonWidening/widenAlign weighted by forwardness — the flanks broaden while the head reach + ETA parity are untouched and the back-burn stays tight, never a disc); a red→amber→green ramp near→far (deep red “act now” → green “least certain”, honesty-guarded so green is never “safe”); a single heading arrow; and, when wind direction is unknown, a desaturated dashed all-directions worst-case ring (no fabricated bearing) with an on-map chip. The spread legend lives on the map (a collapsible “Spread key” pill). Web + native paint identically via the shared lib/spreadPaint.ts. On + visible, badged in-development; not alert-trusted until 15.4. Honest limit: marker advection, not a level-set — extreme near-reversal veers fall back to the radial lobe.
  • Legacy fallbackcomputeHazardBands (the single-wind 1 h/3 h/6 h wedge, 0.5 + 0.18·wind) is kept verbatim, stamped engine:"legacy", and used when the flag is legacy or there is no forecast series to march.
  • ETA — one rate of spreadapi-server/src/eta/computeEta.ts now delegates its rate to the shared headRateOfSpreadKmh (proven byte-identical), so the footprint edge and the ETA ring use the same maths in every direction. ETA still integrates over distance with per-segment DEM slope, wind held constant in time (the time-march is 15.2).
  • Terrain wind — WindNinja (api-server/src/sim/) is still reduced to a mean speed; direction discarded (15.5).
  • Alertsnotifications/evaluator.ts still gates on 30 km proximity + a straight-line baseline ETA (unchanged in 15.1); it does not yet use the footprint (15.3). Delivery is Expo native push; web push (VAPID) + Emergency SMS/email are config-gated off.
  • Honest labelling — one PREDICTION_VALIDATED flag (default false) drives the on-map badge, the reliability legend, and the panel disclaimer, plus a server model stamp on the prediction responses.
  • No accuracy loop yet — predictions are ephemeral; nothing scores a past prediction against the observed fire (15.4). See FIRE-PREDICTION-ARCHITECTURE.md.

2. Where it should be (the 2026 reference bar)

Government-grade AU systems are fuel-type-specific (AFDRS — 8 models / 22 fuel types; Cheney grassland; Vesta Mk 2 forest), run probabilistic ensembles, use geostationary near-real-time detection (Himawari, 10-minute), and assimilate observed fire perimeters to keep the forecast tracking reality. The operational engines are CSIRO Spark and PHOENIX RapidFire.

Technology scoping (honest):

  • Physics / empirical model = the trusted core. Deterministic, explainable, agency-trusted; always the baseline and fallback.
  • Machine learning (not LLMs) = the legitimate “AI”: surrogate emulators for fast ensembles, satellite fuel-moisture/fire perception, and calibration/assimilation against observed fires.
  • LLMs = situational fusion + per-user briefings + prediction-explainer + pipeline orchestration only. Never the predictor.

3. The plan (Phase 15 — staged, flagged, honest)

PhaseDeliverableStatus
15.0Documentation + status tracking foundation (this page, PREDICTION-STATUS.md)done
15.1Unified byte-identical ROS + honest labelling (built) · elliptical footprint + reliability gradient + decisive no-slider view + role-gated ES temporal preview (in development — built & flagged) + your-location in/out-of-path indicator (built, panel) · GPS-location ETA hero + map-dot tint + richer ES scrubber (planned; a compact per-asset ETA already shows in the peek header)S0 (2026-08-03) + ES preview + location indicator (2026-08-05)
15.2True curved front advection (swept corridor — Lagrangian), default + wired live · 15.2.1 directional-uncertainty UX: 1/3/6/12 h widening fan + red→green ramp + heading arrow + on-map legend + wind-unknown ring; + time-marched ETA (planned)default engine + 15.2.1 UX built (spread-model 69/69); ETA-march remains
15.3Alerts triggered by the predicted footprint; web-push + Emergency email deliveryplanned
15.4Prove-it loop — immutable prediction persistence + dep-free grid-sampled scoring + backtest sweep + role-gated accuracy scorecard (built + ON by default; skill claim needs real fires)built (PREDICTION_PERSISTENCE_ENABLED=true; skill claim + PREDICTION_VALIDATED await real fires + SME)
15.5Fuel-type models + BOM ACCESS-C fire weatherplanned / needs data
15.6Near-real-time tracking — exploit the ~10-min DEA feed (already blends Himawari) + optional direct Himawaripartial / planned
15.7–15.9Probabilistic ensembles → data assimilation + ML surrogate → ML calibration + LLM briefingplanned
15.10Hybrid engine flag (PREDICTION_ENGINE) + Spark/AFDRS integration scaffoldingintegrate

Guardrail: nothing unproven is ever presented as validated or is trusted for alerts. The Phase 15.1 elliptical footprint + reliability gradient ship on and visible but are honestly badged “modelled projection — in development” on every surface (map badge, legend, panel, docs, marketing) and driven by PREDICTION_VALIDATED=false; they do not drive alerts until the 15.4 skill score + SME sign-off flip that flag. The trusted alert maths is unchanged in 15.1. The single-wind cone stays as a labelled fallback; the canonical feature flags are in PHASE-15-PREDICTION-ENGINE-PLAN.md §8.

Phase 15.1 scope (locked 2026-08-03): the consumer view has no time slider — one decisive footprint, with time and reliability encoded spatially as nested confidence shells (near = reliable, act now; outer = still firming); the time scrubber is role-gated to emergency services. Full stage plan: PHASE-15.1-PREDICTION-UX-PLAN.md. Wind-unknown renders an honest all-directions worst-case disc (no fabricated bearing).

4. Validation criteria — what flips PREDICTION_VALIDATED

The Phase 15.4 prove-it loop is the ONLY thing that earns PREDICTION_VALIDATED=true. Flipping it is a one-way, high-consequence act: it alert-trusts the curved corridor, unlocks the ETA-into-alerts time-march (15.2), and gives the 15.9 ML calibration something to train on. So it is gated by named, documented thresholds plus a written SME sign-off — never a hunch.

The bar (SME-pending placeholders — NOT a claim). These live in one place, api-server/src/lib/validationCriteria.ts, so an SME can tune them without a code hunt:

ConstantPlaceholderMeaning
VALIDATION_MIN_CONTAINMENT_MEDIAN0.80Median containment at the 1–3 h horizons — the corridor must contain ≥ 80 % of where the fire actually went. Containment is the headline because under-prediction (the fire escaping the corridor) is the dangerous failure.
VALIDATION_MAX_POSITION_ERR_KM2.0Median predicted-head position error at ~2 h.
VALIDATION_MIN_SCORED_FIRES20Minimum DISTINCT real fires scored before the scorecard is a claim, not noise.

How to change the bar: edit those constants in validationCriteria.ts. The accuracy scorecard (GET /predictions/accuracy-scorecard, role-gated; the “Prediction accuracy” screen) renders each engine (advected@15.2.1 vs own@15.1.1) per horizon against these criteria, with the distinct-fires count so the honesty is explicit (“N=3 — not yet a skill claim”).

How to actually flip the flag (production):

  1. Review the scorecard on real accumulated fire data; confirm the model clears every criterion above.
  2. Obtain written SME sign-off (Renee Pack) recording the review.
  3. Set PREDICTION_VALIDATED=true and PREDICTION_VALIDATION_SIGNOFF=<sign-off reference> — the production boot guard (assertProdConfig) refuses to start with validated=true but no sign-off reference, so the badge can never be flipped without the attestation on record.
  4. Move PREDICTION-STATUS.md + this page + marketing together (the standing one-boolean rule); only then may “validated” + a published skill score be claimed.

Until all of that: everything stays “modelled projection — in development” and the corridor does not drive alerts.

Persistence flag: the whole loop (observation + prediction writers, backtest sweep) is gated by PREDICTION_PERSISTENCE_ENABLED (default on since 2026-08-06) and runs at the clustering + precompute seams every cycle, accumulating real-fire skill data (its observation writer needs FIRE_CLUSTERING_ENABLED, also on by default). Raw rows are pruned after PREDICTION_RAW_RETENTION_DAYS (default 30); the derived scores are kept forever. Note the loop running does not make the corridor “validated” — that stays gated on the criteria above + SME sign-off.

5. Key code

  • lib/spread-model/src/index.ts — shared spread geometry (client + server identical).
  • api-server/src/eta/computeEta.ts — rate-of-spread + ETA.
  • api-server/src/lib/nearestForecast.ts — hourly forecast series (getForecastSeries).
  • api-server/src/sim/ — WindNinja terrain wind.
  • api-server/src/notifications/evaluator.ts — threat evaluation + alert emission.
  • Client rendering — firepath-ai/components/FireMap.web.tsx / FireMap.native.tsx, HotspotDetailPanel.tsx, TimeScrubber.tsx.

See the generated reference for the exhaustive, always-current detail.

Update triggers

Edit this page (and the date above) whenever the prediction method changes, a Phase 15 stage lands, a capability moves between planned ↔ flagged ↔ built, or a feature flag is added — and mirror the change into PREDICTION-STATUS.md in the same commit.