The Buffalo River Watershed Study has wrapped up after 122 days — a month longer than planned — and its page is now a finished, browsable archive.
Not user-facing, recorded for completeness: the study's nightly Claude Opus narrative stream was retired on 2026-07-01 (cron study_daily_analysis.py --no-opus), ending the project's only per-night external API cost; the local qwen3.6:27b stream continues a no-cost nightly pulse on ScriptPi for periodic hand-review. /study/ pages are frozen at Day 122 (June 30, 2026); the concluded banner + per-page frozen-archive notes are served from dashboard.py (study_index/study_hypothesis/study_daily). See ARCHITECTURE §4.7 + §16 item 16 (version 2026.7.1.2).
Arkansas Creek Intelligence has its own web address now: arcreekintel.com.
New page: the Illinois River and the Upper Illinois Water Trail.
Not user-facing, recorded for completeness: new ScriptPi basin /home/dave/illinois/ (config + assembler + multi-gauge fetch / read-qpe / weather+QPF, cloned from Big Piney with Buffalo's signal_for multi-gauge pattern grafted on), cron every 15 min → illinois_output.json. Full history collected to the harness research/illinois_*: 8 USGS gauges' complete records + hourly MRMS per-HUC12 QPE 2014→present over the 21 HUC12s above Watts. Empirical illinois_below block trained on the above-Hwy-16 basin (calibrated_table.json + lookup index + empirical_config.yaml). Upstream→Hwy-16 propagation lags from storm-pulse cross-correlation (Savoy 6–8 h, Osage 8–13 h, Mud 11–16 h; Watts +3–5 h downstream). New DMZPi routes /illinois/ + /illinois/historical/. See ARCHITECTURE §4.9c (version 2026.6.30.1).
The rainfall forecast on the five creek pages now gives you an honest percentage instead of a vague "rise likely."

Not user-facing, recorded for completeness: new calibrated engine (empirical_forecast/calibrated.py + calibrated_table.json — denominator-corrected P(rise | rain, soil) over the full 2014-2026 MRMS+USGS record) feeds the headline in empirical_predict.py, with a per-basin warm rolling factor off the local settled archives. Boxley (no page) unchanged; empirical stays off Facebook per standing choice (Watersheds only). Full research + validation in the harness research/empirical_recalibration/ (REPORT.md). ARCHITECTURE §4.13/§16-11 updated.
Added a privacy policy page.
Our forecast "report card" got clearer and more honest, and a couple of predictions were tuned based on what it's been telling us.
/scorecard) is easier to read and harder to mislead. The recession-countdown table now hides the dozens of barely-started rows so you only see the gauges with enough data to mean something, and each predictor's "bias" now shows its average and its typical (median) miss side by side — so a single freak event (like the June 22 flash flood) no longer makes an otherwise-solid predictor look broken. (Experimental, self-grading page.)Not user-facing, recorded for completeness: this came out of the weekly scorecard / Signal-digest review. score_all.py now emits a per-predictor median error, min-n-gates the recession rows (MIN_RECESSION_GRADED), and adds a recession timing-bias flag; ponca_analog.py decays the dominant-driver flood-floor toward the raw k-NN once Ponca is past crest (raw values still logged for backtest); big_piney_assemble.py had recession_baseline support restored to its ported compute_recession (the port had dropped it) and above_longpool was given recession_baseline: 2.0. The empirical engine's over-warning (also visible on the scorecard) is a deeper rebuild blocked on an offline tool — tracked, not yet changed. See ARCHITECTURE §4.13 / §16-11 (version 2026.6.29.5).
Creek Intelligence is now on Facebook — follow Arkansas Creek Intelligence for automatic creek alerts and a weekend forecast.
Not user-facing, recorded for completeness: new creek-social toolset on the harness server — creek_social.py mirrors the watershed alerts to Facebook (fully decoupled from ScriptPi: it reads the same predictor_output.json the dashboard already produces, replays the alert engine's new/escalation logic against its own state, and posts via the Facebook Graph API), weekend_forecast.py (Friday cron; recession-based "holds through the weekend" filter), and announce.py (auto-posts a short feature announcement to the page whenever we ship a user-facing change — a new shipping convention now in CLAUDE.md §8 + ARCHITECTURE §4.2). Posts are deliberately link-free and bot-signed.
The Buffalo Study pages now correctly report the June 22 flash flood — it had been mistakenly logged as a "data gap"
/study/), June 22 is now described accurately as the biggest event of the study so far: a dry-ground flash flood that set records up in the headwaters — Boxley, Ponca, and Pruitt all hit study-record levels — then faded to just below flood stage by the time it reached St. Joe / Grinder Ferry. The running write-up had previously called this stretch a "data gap" and guessed it was only a moderate event, because the night-of analysis that captured the flood never made it into the rolling summary. Both the gap and the wrong guess are now corrected, with the real numbers.Not user-facing, recorded for completeness: two fixes to the nightly Buffalo Study analyzer (study_daily_analysis.py) plus a data backfill. (1) The transfer-ratio validator was QPE-gated — its 2,000 cfs/in cap had unconditionally false-rejected the model's correct 06-22 headwater numbers (Ponca 2,756 cfs/in matched the deterministic truth card), silently dropping that night's calibration; the cap now applies only on low-rainfall days, where the frame-override artifact it guards against actually occurs. (2) The Opus output cap was raised 40000→56000 after the daily+thinking+hypothesis rewrite pinned at the cap for five straight nights (06-21..06-25, incl. the flood), freezing the rolling hypothesis. (3) The 06-22 study-record flood was backfilled into both the qwen knowledge.md calibration tables and the Opus hypothesis.md (now live on /study/), from the truth card + the existing night-of Opus daily; logged in analysis/curation_audit.md. The qwen-only (--no-opus) cutover stays deferred — even post-fix, qwen still drops a gauge on the complex flood night. See ARCHITECTURE §4.7 + §16 item 16.
More accurate downstream forecasts: the St. Joe / Grinder Ferry propagation card no longer overshoots when the rain falls up high
Not user-facing, recorded for completeness: the St. Joe magnitude in ponca_analog.py build_propagation() was a fixed basin-wide amplification (≈2.9× Ponca) applied unconditionally; on an upper-concentrated event the wave routes through the dry 1,342 km² intervening basin and attenuates (~0.9×), so the constant over-predicted 2–4× (6-22: card 19–33k, actual 7.9k). Recalibrated against 152 historical Ponca events (2014–2026) from the local buffalo_huc_qpe + buffalo_gauges archives (research/buffalo_propagation_calibration/, with REPORT.md + figures). St. Joe is now a rainfall-distribution + antecedent conditioned log-linear model (SJ_MODEL) reading the upper-vs-intervening qpe_24hr ratio and the intervening 7-day antecedent — all already in buffalo_output.json — with a crest band floored at the routed wave (0.85×) and the reach's current flow. Leave-one-out CV cut the upper-concentrated bias from +46% to ≈0; out-of-sample on 6-22 it predicts St. Joe 8.5k–11.9k–16.9k (lower bound ≈ actual). Pruitt kept at ~1.13× (rain-insensitive, 11-yr confirmed); peak-to-peak lags re-derived. ScriptPi-only — render_propagation_card() reads only the kept crest-band fields, so no DMZPi change. See ARCHITECTURE §4.6 + §16 item 15.
New: a 24-hour gauge chart on the Cossatot, Richland, and Hailstone pages
Not user-facing, recorded for completeness: each physics-basin assembler now emits gauge.readings_24h (a [[epoch, value], …] array of the last 24 h, ~96 pts at 15-min) via a build_readings_24h() helper — Cossatot/Richland stitch yesterday+today's daily height files to span midnight, Hailstone uses its already-rolling cfs buffer from creeks/gauge_data.json. dashboard.py gained render_hydrograph(), an inline-SVG renderer (tier bands + line + peak + "now" dot, fully self-contained, no chart library), placed under the gauge card on all three pages. Display-only, no DMZPi compute (same contract as the HTML tables and Leaflet maps). See ARCHITECTURE §5.4.
The Scorecard now flags what needs attention — and reports its own drift weekly
Not user-facing, recorded for completeness: score_all.py now computes a flags array (min-n-guarded: empirical over-warn ≥70% no-rise at n≥20, band inversion above_p75 vs. p50_to_p75, physics within-±20% <50% at n≥15, Ponca override-vs-raw flood-Brier gap, recession never-reached ≥60% once graded) into scorecard.json; /scorecard renders the "Needs attention" box from it. New prediction_eval/scorecard_digest.py (weekly cron Mon 07:30 Central) reads the scorecard, formats a per-family accuracy snapshot + the flags, and sends a Signal DM via the existing signal_config.yaml (same signal-cli plumbing as scp_alert / data_age_alert). This is Phase 3 of the prediction-logging initiative — the self-checking / feedback half. The harness-consolidation refactor was deliberately deferred (a risky change to working cron code with no user benefit). See ARCHITECTURE §4.13 + §16-14 + §7.2.
Scorecard now also tracks the downstream-propagation forecast (recording started)
Not user-facing, recorded for completeness: ponca_analog.py now folds the per-reach propagation block (lag window, crest band, bump/no-bump flag, current flow) into each ponca_analog_history.jsonl record — the record step the predictions had been missing. New prediction_eval/propagation_eval.py settles each matured event two-stage: it finds Ponca's actual peak from buffalo_study/data/gauges, then for Pruitt (07055680) and St. Joe (07056000) grades the bump/no-bump call (crest ≥ 1.25× baseline & +50 cfs), the magnitude-band hit, and the timing window relative to Ponca's peak — using the cycle nearest Ponca's peak as the representative prediction. A --selftest (10 checks) validates the logic. score_all.py folds the settle in and adds a propagation block; /scorecard renders it; Coverage flips the propagation forecast to "graded." This completes Phase 2 of the prediction-logging initiative — every live predictor family is now recorded and graded. See ARCHITECTURE §4.13 + §16-14.
The Ponca "AI Analysis" cards now read like a person — and the numbers make sense
Not user-facing, recorded for completeness: in buffalo_dashboard/ponca_analog.py, both qwen system prompts were slimmed and rewritten for a casual-paddler audience (no jargon, fact-fed, model reasons rather than recites) with one hard rule — never state a peak/crest at or below the current flow. build_propagation() now models est_crest = reach_current + (Ponca rise above baseline) × amplification, floored at the reach's current value (was Ponca_flow × amp absolute, which fell below a downstream gauge's own flow whenever Ponca was small relative to that reach's drainage), plus a significant / added_bump_cfs gate so small pulses read "minor bump, no noticeable change." A qualitative 6-hour trend word (holding steady / creeping up / rising steadily / rising fast / easing down / dropping fast) keeps the model from overstating a slow creep. The deterministic override floors (upstream Boxley wave, heavy-rain, watershed-feeder alerts) are unchanged — only their narration. See ARCHITECTURE §4.6.
Scorecard now tracks the Buffalo rise engine (recording started)
Not user-facing, recorded for completeness: new prediction_eval/buffalo_predictions_archive.py (modeled on recession_archive.py) — --record on a 15-min cron (:09,:24,:39,:54, debounced) logs each active predictions[gauge].combined_category from buffalo_output.json (with timing window + current value) to buffalo_ledger/<date>.jsonl; --settle grades vs. the gauge's actual discharge rise over [generated_at, timing_high + 18 h] (rose if peak ≥ 1.25× start AND ≥ +30 cfs → records rise magnitude, hours-to-peak, timing-in-window; else no_rise / censored); --score aggregates. A --selftest (14 synthetic checks) validates the logic since production is dry. score_all.py folds the settle in and adds a buffalo_rise block; /scorecard renders it; Coverage splits Buffalo into "rise predictions: graded" and "flood_risk + propagation_alerts: not yet logged." Magnitude is captured per category (categories derive from rainfall, not gauge rise) so the rainfall→rise mapping calibrates over time. ARCHITECTURE §4.13 + §16-14 + §7.1.
Scorecard now grades the Ponca "AI Rainfall Event Analysis"
Not user-facing, recorded for completeness: new prediction_eval/ponca_analog_eval.py reads the producer's append-only ponca_analog_history.jsonl (read-only) and grades each armed call against Ponca 07055660's max discharge over a forward 36 h window (from buffalo_study/data/gauges), writing ponca_analog_settled.jsonl (idempotent, keyed by generated_at). It grades the k-NN class/peak (modal vs. actual class, median_peak_cfs MAE, p25–p75 band hit) and the flood Brier for flood_risk_pct (override-floored) vs. raw_flood_risk_pct (raw k-NN, on the common sample). score_all.py calls settle() inline (no extra cron) and adds a ponca_analog block to scorecard.json; the /scorecard route renders it; the Coverage table flips Ponca from "logged, not graded" → "graded." See ARCHITECTURE §4.13 + §16-14.
Retired the experimental neural-net (LSTM) predictor
Not user-facing, recorded for completeness: the :14 nn_predict.py inference cron was commented out, the dead nn_prediction read/embed was removed from cossatot_assemble.py + richland_assemble.py (the key no longer appears in their output JSON), the stale "LSTM forecast" wording was dropped from the Richland page's social/meta description, and all LSTM-only artifacts (nn_predict.py, nn_predict_debug.py, nn_alert.py, nn_alert_state.json, nn_output.json, both model_epoch100.pt weight files) were moved to /home/dave/creeks/retired_lstm/ (reversible — a README there documents how to resurrect). The HUC12 masks under /home/dave/models/ were kept — they are read by the live Richland physics QPE reader and the map-polygon builder, not just the LSTM. Full record in ARCHITECTURE.md §4.10 + §14 Gotcha #10. Side benefit: one less hourly job on the 2 GB ScriptPi.
New: a Prediction Scorecard page — see how accurate the site's forecasts have actually been
Not user-facing, recorded for completeness: a new ScriptPi subsystem /home/dave/prediction_eval/ (score_all.py, cron 01:30 daily) reads the settled prediction archives for three already-self-recording families — physics (<basin>/predictions/), empirical (<gauge>_empirical_predictions/), and recession (recession_eval/ledger/) — and writes one display-ready scorecard.json, SCP'd to DMZPi. Physics is scored on peak MAE / bias / within-±20%; empirical on hit-rate (rose to ≥ called tier = verified + missed_higher) vs. no-rise rate (no_change), broken out by basin, confidence, and rainfall percentile band (which surfaces the known selection bias — the above_p75 band currently shows a higher no-rise rate than p50_to_p75); recession reuses recession_archive.score(). The DMZPi /scorecard route renders the JSON read-only (no compute on DMZPi; validated via the venv test_client before the gunicorn restart). This is Phase 1 of a system-wide "log every prediction, grade it later" initiative — audit + plan in creekintelligence/research/prediction_audit/. The still-ungraded predictors (Ponca analog, downstream propagation, the Buffalo per-gauge rise engine, the retired LSTM) are listed as not-yet-graded in the page's Coverage table and are Phase 2.
Recession countdowns are now realistic — and honest about how sure we are
Not user-facing, recorded for completeness: the timing model is a per-gauge master recession curve — a flow-dependent decay rate k(Q) learned from USGS history, integrated to a transit time and event-anchored to the current observed rate (clamped 0.5–2×) — in /home/dave/recession_eval/recession_curve.py + recession_curves.json (9 gauge curves), imported by every *_assemble.py compute_recession() with the old single-exponential kept as a fallback. The St. Joe/Harriet suppression uses a config recession_baseline (empirical floor, ~p10) as the decay asymptote so any threshold below it returns no countdown. Confidence is now derived from each prediction's relative spread + horizon (recession_curve.confidence_level). A prediction-evaluation framework (recession_archive.py, on cron) now records every recession countdown to a ledger and settles it against actuals to score accuracy over time. Threshold keys were standardized to too_low/low_floatable/optimal across all configs/assemblers. Full design, history pulls, and analysis live in creekintelligence/research/recession_eval/.
Clearer recession countdowns + gauges stop briefly greying out
Not user-facing, recorded for completeness: the three height/CFS recession cards were consolidated into one shared render_recession_card() helper in dashboard.py (they had drifted into near-duplicate blocks edited in parallel). Hailstone's recession model now also emits hours_to_high (time to fall to the 2000-cfs Above-Recommended boundary) in hailstone_output.json. The gauge-fetch resilience lives in creeks/fetch_gauges.py: fetch_stream_readings() retries transient empty USGS responses, and main() carries forward the previous good reading (new carried_forward flag, 90-minute cap) so one failed pull no longer greys a gauge.
Ponca rainfall card now leads with the trusted signals + new downstream propagation card
/buffalo/) — appears above the mainstem gauges only while the river is rising. It narrates how a rise at Ponca rolls downstream: roughly when the surge will crest at Pruitt (~5 h behind Ponca, about Ponca's level) and at St. Joe / Grinder Ferry (~14 h behind, typically several times higher), and how high each is expected to get — as a range, compared to that spot's own flood stage. Travel time shifts with how wet the ground is (dry ground = slower). Built for NPS rangers and campers weighing the gravel bars downstream — it answers "how high will Grinders get, and how long before it spikes." Experimental — timing is approximate and magnitude is a range; verify against the gauges. Runs on the same local AI model (no external calls, no cost).Not user-facing, recorded for completeness: the rainfall card now reads the live creek-alert state (read-only) and the Buffalo physics propagation/flood signals already in buffalo_output.json; the propagation card's lag/amplification constants come from the 12-year USGS archive cross-checked against the Buffalo Study's calibrated 2026 event log, and are antecedent-conditional. Both narratives are produced by the local qwen3.6:27b model — the propagation one is a separate focused prompt embedded in ponca_outlook.json.
Ponca Gauge historical event reporting + experimental AI rainfall event analysis
/ponca/historical/) — a deep history of how the Buffalo at Ponca has behaved, using the National Park Service flow buckets for the Ponca→Pruitt commercial-float section (Very Low <100, Low 100–200, Moderate 200–900, High 900–1600, Flood ≥1600 cfs; outfitters may launch 100–1600). It shows days per year in each stage and a storm-by-storm catalog back through the radar-rainfall record (Feb 2015→present, with earlier flow-only events on an extended page). Each storm lists the rainfall that drove it (basin-average over the four HUC12s above Ponca, plus a per-HUC breakdown and the wettest single sub-watershed), the starting flow, and every ≥4-hour stage the river held on the way up and down. Linked from the Buffalo page below the 3-day forecast./buffalo/) — appears above the mainstem gauges only when rain is actively falling over the Ponca headwaters (≥0.25″ accumulated). It compares the unfolding storm to ~166 similar past storms and writes a short, plain-English outlook — the most likely peak stage, and whether there's meaningful risk of blowing past the 1,600 cfs launch ceiling — in qualitative terms ("watching… / likely Moderate / high confidence of Flood"). It updates each hour as the storm builds, switches to an "already crested, now receding" read once past the peak, and disappears after about a day of dry weather. Runs on a local AI model (no external API calls, no cost). Experimental — it's a directional read of upstream rainfall vs. history, not a forecast; always verify against the gauge.Not user-facing, recorded for completeness: built a local archive of MRMS radar rainfall for all 37 Buffalo HUC12 sub-watersheds (2014→present, two source archives) plus full USGS history for all 7 Buffalo gauges, which back the historical report and the analog evaluator. The evaluator (buffalo_dashboard/ponca_analog.py, hourly cron :20, flock) runs a numpy k-NN match against a shipped analog library and calls the local model only when its call changes (~10 inferences per event), writing ponca_outlook.json for the dashboard to render.
PayPal-based donation support
/support/ page — explains what donations fund and embeds a PayPal donate button (merchant KZM3SRM3W34US). Dark-themed to match the rest of the site. Includes a fallback text link for cases where the PayPal button image fails to load, and a required disclosure that donations are personal gifts (not tax-deductible — Arkansas Creek Intelligence by Druidnetworks is not a 501(c)(3))./support/thanks/ page — optional return destination after a completed donation. Short thank-you, link back to the gauges./, /gauges/, /watersheds, /cossatot/, /richland/, /hailstone/, /mulberry/, and /buffalo/. Deliberately styled in muted gray near the existing disclaimer — available without nagging. Not added to /admin/, /suggest, /study/*, /changelog, or /guide/.paypal.com; PayPal handles payment, receipt email, and merchant deposit. Removing the routes removes the donation surface entirely.Hailstone reaches feature parity + nightly AI analysis moves to local inference
cossatot_predict.py and richland_predict.py was double-counting in-transit water during active rainfall, producing fake peaks of up to +2.0 ft on Cossatot dawn predictions and a similar pattern on Richland. The baseline now holds at the current gauge value until band contributions finish arriving, then transitions to the recession decay. Validation on the worst archived errors: Cossatot 2026-05-20 06:09 prediction went from 5.28 ft → 3.33 ft against an actual peak of 3.29 ft. A retrospective supplement at /cossatot/analysis/2026-05-20-Opus-Supplement documents the diagnosis and the per-prediction replay improvements.recession_k / recession_h_base parameters are still computed in case the physics predictor needs them, but the dashboard hides time-to-tier estimates that the exponential-decay assumption can't honor mid-event.USGS {gauge id} · {river} near {town}, AR, matching the USGS station's official name. Previously Richland listed zones in the subtitle and Hailstone listed the run name.Underlying schema, infrastructure, and unit-bug cleanups (not user-facing but recorded for completeness): new hailstone_predict.py + hailstone_calibration.json + hailstone_predictions_archive.py, three new cron entries (:17 Hailstone QPE consumer, :21 Hailstone physics predictor, 23:55 Hailstone nightly analyzer), fixed a 25.4× unit error in the new Hailstone QPE consumer (had been treating already-in-inches shared QPE values as mm and dividing again — antecedent moisture was reading DRY when the basin was actually NORMAL/WET), exposed recession_k/recession_h_base on Richland's gauge output (latent gap that left the physics predictor falling back to a flat baseline instead of an exponential decay), and added a per-supplement file-naming convention (YYYY-MM-DD-suffix.md) for retrospective analyses written outside the nightly cadence.
Stale-Data Warning Banners Across All Mobile Dashboards
/) freshness pill — new always-on indicator at the top of the page with three states: green "Live — updated N min ago" when data is fresh, yellow "Data may be stale — last update was N minutes ago" when past the 30-min threshold, and red "Data feed unavailable — ScriptPi push may be down" when predictor_output.json can't be loaded at all (previously the page silently rendered as "All Quiet" during push failures, hiding the outage)/cossatot/, /richland/, /hailstone/, /mulberry/, and /buffalo/ now render the same yellow top-of-page warning banner that /gauges/ and /watersheds have had. Fires only when each page's underlying JSON is past its 30-min _stale threshold, so the banner only appears when something is actually wrongrender_stale_banner(data, expected_interval_min=15) and render_freshness_pill(data, expected_interval_min=15) live alongside the other freshness utilities (_format_age, _age_color). The banner markup was previously duplicated inline on /gauges/ and /watersheds; those two pages now call the helper (no visual change)Creek Page Title & Buffalo Card Standardization
#ffffff) to match the landing page style (previously cyan #4fc3f7)Buffalo River Dashboard
/buffalo/ dashboard — Buffalo River Dashboard page with 5 mainstem gauge cards (Boxley, Ponca, Pruitt, St. Joe, Harriet), 2 tributary signal separator cards (Richland Creek, Bear Creek), interactive Leaflet.js HUC12 rainfall map, zone rainfall table, flood/propagation alert banners, rise prediction and recession countdown sections per gaugebuffalo_output.json data source — pushed by ScriptPi every 15 min, contains 7 gauge readings, 37 HUC12 QPE values, 8-zone rainfall aggregates, per-gauge rise predictions, recession countdowns, propagation alerts, and flood risk levelsbuffalo_huc12_simple.geojson (136KB, 37 features) served from new /static/ directorybuffalo_only: true) filtered from /gauges/ table and landing page cards/counts/watersheds/ — "Buffalo QPF" family drainages (pruitt_zone, stjoe_zone, bear_creek_zone, harriet_zone) filtered from the watersheds pagenav_button_footer() bottom row alongside Guide, Changelog, and Suggestionsnav_button_footer() blue button gridRichland Creek Dashboard & Neural Net Predictors
/richland/ dashboard — Richland Creek Watershed Intelligence page (USGS 07055875) with gauge status card, recession countdown, two-zone watershed rainfall table (Upper Richland + Falling Water + Combined), physics predictor card, and LSTM neural net forecast card (8 horizons)/richland/analysis/ placeholder routes — "Nightly analysis coming soon" index page; date routes return 404richland_output.json data source — pushed by ScriptPi every 15 min, contains gauge data, two-zone rainfall, physics prediction, and neural net prediction/cossatot/ — 12-horizon LSTM forecast with peak CFS, forecast timeline table, threshold crossings, and data quality indicatorsrender_nn_card() helper — renders identical card layout for both rivers; shows peak forecast, per-hour timeline with peak row highlighted, CFS-to-level threshold crossings, and QPE/ASOS data quality footer; handles null (initializing), error, stale (>90 min), and active states/cossatot/ — "Rise Prediction" / "Prediction" headers changed to "Physics Predictor" with gear emoji across all card states (active, quiet, no data)nav_button_footer() used across all pages; renamed Cossatot link to matchCOSSATOT_LEVEL_COLORS renamed to LEVEL_COLORS, COSSATOT_TREND_SYMBOLS renamed to TREND_SYMBOLS (used by both river dashboards)NN_THRESHOLDS (CFS-to-level mappings per basin: Richland 500/1000/1500, Cossatot 150/730/1800), NN_LEVEL_COLORS (gray/green/blue for Too Low/Optimal/High), is_nn_stale() helperDMZPI_ARCH_4_7_26.md supersedes DMZPI_ARCH_3_11_26.mdLanding Page & Route Restructure
- New landing page at / — mobile-first dark theme with site title, orientation blurb, live status summary, and dynamic creek condition cards
- Creek cards show all Optimal gauges (green) or, if none, all Low but Floatable gauges (yellow); "All Quiet" message when no creeks are runnable
- Status summary line shows gauge and watershed condition counts with color-coded text
- Tool navigation grid — four main buttons (Gauges, Watersheds, Cossatot Predictor, Buffalo Study) plus secondary links (Guide, Changelog, Suggest a Creek)
- Gauge table moved from / to /gauges/ — all table logic unchanged
- Temporary legacy link on landing page points to /gauges/ for returning users
- New /guide/ placeholder page — "Coming Soon" with back link to home
- Back link audit — watersheds, changelog, study, and suggest pages link back to /gauges/; error pages and Cossatot nav link to / (landing)
- Last updated timestamp on landing page converted from UTC to Central time
Four-Color Unification - Unified color language across creek levels, prediction status, and recent rain: Red (nothing) / Yellow (maybe) / Green (go) / Blue (lots) - Prediction status expanded to four tiers: No Alert (red), Watch (yellow), Warning (green), Flood (blue) - Recent Rain column now shows 7-day precipitation total in inches with color-coded background, replacing category labels (MOIST/SEMI-DRY/DROUGHT) - Recent Rain multipliers updated: <0.25" = 1.4x trigger, <0.75" = 1.2x, <1.50" = 1.0x, ≥1.50" = 0.9x - FLOOD status triggers at 200% of effective trigger threshold — indicates exceptional rainfall - Micro-creek lag display: Drainages with 0-1 hour lag now show "NOW" instead of numeric range - Signal alerts updated with lag-aware messaging (micro-creeks show "NOW", mainstem rivers show hours)
Drainage Trigger & Timing Calibration - Adkins: 2.0" / 4hr → 2.5" / 6hr - Boen Gulf: 2.0" / 4hr → 2.5" / 6hr - Upper Buffalo: window 6hr → 12hr, lag 4-6hr → 6-8hr - Beech Creek: 1.5" → 2.0" - Upper Kings: 1.5" → 2.0" - Osage: 1.5" / 4hr → 2.5" / 6hr - Richland Main: window 6hr → 12hr - Falling Water: 1.5" / 6hr → 1.75" / 12hr - Upper Cossatot: window 6hr → 12hr - Upper Big Piney: window 6hr → 24hr, lag 10-12hr → 12-16hr - EFLB: 1.5" → 2.0" - Pine Creek OK: window 6hr → 12hr
Cosmetic Updates - Renamed "DRY" status to "QUIET" on the Watersheds page and in alert bar logic (same red styling, new CSS class .st-quiet). - Renamed "Conditions" column to "Recent Rain" and changed from styled badge spans to full-cell background coloring (matching the Status column style). - Updated status_colors/status_text_colors dicts to use "QUIET" key.
Sticky Status Hold - WATCH and WARNING statuses now hold for the duration of a drainage's lag time plus a 2-hour buffer before clearing, preventing premature status downgrade before water reaches the gauge.
Antecedent Dryness System - New "Conditions" column on Watersheds page showing MOIST, SEMI-DRY, or DROUGHT based on recent rainfall history. - Trigger thresholds automatically increase during dry conditions: +15% for SEMI-DRY, +30% for DROUGHT. - Dryness is computed from rolling 7-day and 30-day precipitation totals per drainage. - Trigger column on Watersheds page now shows the effective (adjusted) trigger value.
Cossatot Drainage Update - Upper Cossatot trigger raised from 1.00" to 1.25" in 6 hours. - Upper Cossatot lag time updated from 3-6 hours to 8-10 hours based on observed March 5 event.
YAML Sync - Creek and drainage definitions now automatically sync from ScriptPi to DMZPi every 15 minutes, ensuring single source of truth.
Changelog - Added this changelog page, accessible from the footer of both dashboard pages.
Baseline version. All prior changes consolidated.
WATCH / WARNING Terminology - Renamed "TRIGGER" status to "WARNING" to align with NWS conventions. - WATCH threshold raised from 50% to 75% of trigger value to reduce false positives.
Color Scheme Standardization - Watersheds page: RED = DRY (no go), YELLOW = WATCH (maybe), GREEN = WARNING (go time). - Main creek page: Watershed radar column and alert bar colors match the same scheme. - Alert bar is now green for WARNING, yellow for WATCH-only.
Drainage Trigger Updates - Bobtail Creek: 1.5" → 2.0" in 6hr - Long Devils Fork: 1.5" / 4hr → 2.5" / 6hr - Big Devils Fork: 1.5" / 4hr → 2.5" / 6hr - West Fork Shop Creek: 2.0" / 4hr → 2.5" / 6hr - Thomas Creek: 2.0" / 4hr → 2.5" / 6hr