Skip to content

geolocator: Rev 6A agri_yield_pipeline physical-state overlay - #18

Open
aurascoper wants to merge 2 commits into
masterfrom
publish/agri-overlay
Open

geolocator: Rev 6A agri_yield_pipeline physical-state overlay#18
aurascoper wants to merge 2 commits into
masterfrom
publish/agri-overlay

Conversation

@aurascoper

Copy link
Copy Markdown
Owner

Summary

  • New agri_overlay TrackedSource, REFERENCE class, registered in the same pattern as power/worldgrid. Reads a hash-verified JSON export from a separate repo (agri_yield_pipeline, data/overlay/latest.json — a symlink that repo's export script retargets each run). Never imports that repo's code, only its frozen export — same two-product boundary already established for the trading-lattice proxy.
  • _load_agri_overlay() verifies the export's own embedded cells_sha256 before accepting it — same corruption-detection discipline as the snapshot loaders recently added to live_trading's energy-market-bridge research harness.
  • Fixed the /api/layers color_field ternary before it grew a third, wrong case — the existing comment already documents a two-way ternary once telling the legend something false for one layer; converted to an explicit per-layer dict.
  • Fixed a real bug the public test suite caught on first run: capacity_mw was None for counties with no NDVI baseline, but two existing endpoints (/api/stats, /api/plants) assume it's always a float (the repo-wide _f() convention). Now defaults to 0.0, consistent with every other layer.

What this is not

No trading claim. County-level NDVI z-score, a July Daymet weather anomaly (the exporting repo's data doesn't extend past 2023-12-31), the static county tmax-yield sensitivity table, and Sentinel-1 SAR reported as an explicitly-stale reference value (the exporting repo's weekly refresh automation has been broken for 4 months — documented in its own export, not silently smoothed over here).

Test plan

  • python3.13 -m pytest -q geolocator/tests — 107 passed (was 105 passed / 2 failed before the capacity_mw fix)
  • Verified live on the running service: /api/health reports class: reference, a real vintage (the export's own generated_at, never live)
  • Verified live: touching the export file reloads it (reloaded_at advances) without changing the reported vintage
  • Verified live: a deliberately corrupted export is rejected (status: unavailable, clear hash-mismatch error) before being served
  • /api/stats?layer=agri_overlay and /api/plants?layer=agri_overlay now return 200 on the live service

🤖 Generated with Claude Code

https://claude.ai/code/session_019ULbfnMy6CKDWWD9aQdYY2

New agri_overlay TrackedSource, REFERENCE class, registered in the same
pattern as power/worldgrid. Reads a hash-verified JSON export from a
separate repo (agri_yield_pipeline/data/overlay/latest.json, a symlink
that repo's export script retargets each run) -- never imports that
repo's code, only its frozen export.

_load_agri_overlay() verifies the export's own embedded cells_sha256
before accepting it -- same corruption-detection discipline recently
added to live_trading's energy_market_bridge_probe*.py snapshot loaders.
Verified live: a deliberately corrupted export is rejected (status
unavailable, clear hash-mismatch error) before being served, and touching
the file reloads it (reloaded_at advances) without changing the reported
vintage.

Also fixed the /api/layers color_field ternary before it grew a third,
wrong case -- the existing comment already documents that a two-way
ternary once told the legend something false for one layer; converted to
an explicit per-layer dict.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 177226aece

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread geolocator/api.py
Comment on lines +436 to +440
"agri_overlay": TrackedSource(
# Rev 6A: county-level NDVI/weather/yield-sensitivity physical-state overlay from
# agri_yield_pipeline. No trading claim; see that repo's plan for scope. REFERENCE, not
# LIVE -- the vintage is the export's generated_at, never today's clock.
id="agri_overlay", path=AGRI_OVERLAY_JSON, layer_class=REFERENCE,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Register the agricultural overlay in the site renderer

Adding this source makes agri_overlay available through the API, but the globe UI still hardcodes only the original six IDs in geolocator/static/app/layers.js:21-28; all group creation, toggles, and /api/plants fetches iterate that list. Consequently, even when AGRI_OVERLAY_JSON contains valid data, users have no way to enable or view the new physical-state overlay in the application.

Useful? React with 👍 / 👎.

Comment thread geolocator/api.py Outdated
# a float (see _f()); /api/stats and /api/plants both compare/sum it
# unconditionally, so a missing z becomes 0.0, not None -- caught by the
# public test suite before this ever shipped.
"capacity_mw": abs(z) if z is not None else 0.0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep NDVI anomaly magnitude out of the MW capacity field

When this layer is queried, storing abs(z) as capacity_mw exposes a dimensionless NDVI z-score as megawatts: /api/stats sums it into total_capacity_mw, while the globe HUD and tooltip label the same value as Capacity ... MW and apply the Min MW filter. This produces physically false statistics and labels for every overlay cell with NDVI data; use a separate marker-magnitude property or make the shared consumers layer-aware instead.

Useful? React with 👍 / 👎.

Second review pass, before the first cherry-pick's fix (None -> 0.0)
merged anywhere:

- _load_agri_overlay reverts capacity_mw to None when no NDVI baseline
  exists. 0.0 made "unknown" indistinguishable from "measured zero" in
  any sum or average -- the fix belonged in the two generic endpoints
  that assumed always-float, not in this loader picking a number to make
  them stop crashing.
- /api/stats excludes None from total_capacity_mw and capacity_by_fuel,
  and always reports unknown_capacity_count (not just implied by a
  smaller-than-count total).
- /api/plants: an explicit min_capacity/max_capacity filter can't be
  verified against an unknown value, so it's excluded -- but the
  *default* min_capacity=0.0 must not exclude unknowns just because 0.0
  is a technically-passable floor. excluded_unknown_capacity is always
  present (0 by default), matching /api/stats's convention, so a
  consumer can tell "no filter active" apart from "filter active,
  nothing excluded" instead of the two endpoints answering the same
  question in different shapes.
- _load_agri_overlay verifies payload_sha256 (schema_version>=2) over
  the whole payload minus that key, not cells_sha256 over cells alone --
  a cells-only hash left generated_at/source_git_sha/provenance
  unprotected. Falls back to the old cells_sha256 check for
  schema_version 1 exports.

New tests/test_agri_overlay.py: valid-payload parsing, a positive control
(corrupt cells -> rejected) and the negative control that actually proves
the hash widened (corrupt generated_at specifically -> rejected; would
have passed silently under the old cells-only scheme), a
schema-version-1 backward-compatibility check, and endpoint-level
coverage for both the default and active-filter paths through
/api/stats and /api/plants.
@aurascoper

Copy link
Copy Markdown
Owner Author

Second review pass, pushed as c65434c before the first commit's fix went anywhere:

  • capacity_mw: reverted None → 0.0 back to None. Unknown and measured-zero are different claims; the fix belongs in /api/stats//api/plants (both now null-safe, both always report an exclusion count — unknown_capacity_count / excluded_unknown_capacity), not in the loader picking a number to stop them crashing.
  • Hash coverage widened: payload_sha256 now covers the whole export (generated_at, source_git_sha, provenance) instead of cells_sha256 covering only the cells array — a corrupted generated_at previously passed verification untouched. Falls back to the old scheme for schema_version 1 exports.
  • New tests (geolocator/tests/test_agri_overlay.py, 8 cases): includes a negative control that corrupts generated_at specifically — proving the hash widening actually did something, since corrupting cells alone would pass under both the old and new schemes.

107 → 115 passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant