Skip to content

h3-guide: area-weight the fractional-overlay examples, and use the published per-cell weights assets - #357

Merged
cboettig merged 1 commit into
mainfrom
fix/356-fractional-overlay-area-weight
Aug 7, 2026
Merged

h3-guide: area-weight the fractional-overlay examples, and use the published per-cell weights assets#357
cboettig merged 1 commit into
mainfrom
fix/356-fractional-overlay-area-weight

Conversation

@cboettig

@cboettig cboettig commented Aug 7, 2026

Copy link
Copy Markdown
Member

Closes #356.

Important

Not validated yet — do not promote to prod on the strength of this PR. Per AGENTS.md §"Validating guidance changes", a prompt-artifact change is not done until the headless model suite on dev shows both (a) the targeted failure fixed and (b) no baseline regression. That run happens after merge, since dev tracks :main. Everything below is operator SQL establishing ground truth — which AGENTS.md is explicit does not substitute: it proves the pattern works, not that the guidance steers the model to it. Two blockers are flagged at the bottom.

What was wrong

h3-guide.md carried two worked examples for overlaying a partial-coverage feature against a partial-coverage layer, and they disagreed on whether to weight by cell area. The same-resolution one (line 305, repeated at 339) divided by SUM(frac); the coarse-feature one (line 333) divided by SUM(h3_cell_area). Line 36 of the same file states the rule — H3 cells are not equal-area — and line 38 calls the scoped case the accuracy-critical one.

The unweighted branch is the one that fires for a res-10 feature, which is the CWHR13-vs-conserved-areas question a partner asked the California 30x30 app.

The fix

  1. Carry h3_cell_area through both fractional-overlay examples, matching line 333.
  2. Point the examples at the published per-cell weights assets (…-hex-weights, …-hex-weights-res9, …-hex-weights-res8, from data-workflows#506/#508) instead of deriving the weight by hand from MAX(Acres / Total_Acre) and a SUM(w) / 49 rollup. The issue flagged this as worth doing in the same pass; it also removes a second source of error, since Acres / Total_Acre is a unit's GAP 1+2 share, not its share of the cell.
  3. Bound the denominator with the dense land grid. The res-10 weights asset is sparse (52.5M-acre inventory footprint, not California's 101.5M acres), so the example keeps LEFT JOIN + COALESCE(…, 0) and joins ca30x30-ecoregion at res 10. This turned out to be load-bearing, not cosmetic: the cwhr13 layer extends past California, and without the mask code 32 comes out at 29.89 rather than 33.31.
  4. Weight the coarse case by land area, nland * h3_cell_area(h8, 'km^2'), since coastal and border res-8 cells are only partly land.

The general reductions (MAX within a fine cell, mean across children) are kept in prose as the fallback for layers with no published weights asset. No antipattern blocks, per AGENTS.md:137. The section grows 547 → 598 words (+9%) — worth a reviewer's eye against AGENTS.md's "tighter wording is safer wording"; the growth is the fallback paragraph.

Ground truth (operator SQL, prod MCP)

The issue's reproduce query, after the fix:

CWHR13 class before (guide as written) after 2025 assessment
Conifer Woodland (32) 32.07 33.31 33.27
Hardwood Forest (51) 21.32 21.65 21.59
Conifer Forest (31) 23.75 24.20 24.14
Shrub (70) 27.57 27.82 27.79
Barren/Other (20) 51.97 51.70 51.67

Two independent totals cross-check the corrected form: per-class areas now sum to 101.45M acres (California's land area) against 96.4M for the old formula, and GAP 1+2 to 26.51M against the 26.47M stated in the collection description, where the old formula gave 24.49M.

For the coarse case, statewide GAP 1+2 share from the res-8 weights asset:

weighting result
nland * h3_cell_area(h8) (this PR) 26.135%
nland alone 25.684%
res-10 ground truth 26.135%

105 passed on tests/.

Blockers before this can ship

  1. The benchmark gold is wrong in the same way and will report this fix as a regression. geo-agent-benchmark/suite/gold/ca-30x30.md Q4 and suite/questions/ca-30x30/ca-cwhr13-pct-conserved.yaml carry gold SQL that is verbatim the old line-305 formula — same MAX(Acres/Total_Acre) CTE, same SUM(frac*w)/SUM(frac). Gold says 28.8% for Conifer Woodland against a ±3pt tolerance; the corrected guidance yields 33.3%, so the regression tier fails the fix. The gold needs re-deriving first (branch prepared, PR held — see 2). Q5 (hardwood woodland, L3 report-authoritative, 13.6%) is unaffected: the corrected form still gives 13.60%.
  2. data-workflows#523 contradicts this change at the STAC layer. The -hex-weights-res9/-res8 asset descriptions document SUM((w1+w2)*nland)/SUM(nland) as correct — the 25.684% row above. Until that lands, the injected guide and the per-dataset text tell a model opposite things about the same operation.

Suggested order: data-workflows#523 → re-derive gold → merge here → dev matrix (MODELS="z-ai/glm-5.2 deepseek/deepseek-v4-flash-0731", the cost-bounded standard pair) → prod.

The same-resolution overlay example divided by SUM(frac), weighting every
cell equally, while the coarse-feature example on the same page divided by
SUM(h3_cell_area). H3 cells are not equal-area, so the unweighted form pulls
a share toward whichever latitudes hold more cells — the CWHR13-vs-conserved
question missed California's published 2025 Biodiversity Assessment on 12 of
13 habitat classes, by up to 1.24pp.

Carry h3_cell_area through both fractional-overlay examples, and point them
at the published per-cell weights assets (-hex-weights, -hex-weights-res9,
-hex-weights-res8; data-workflows#506/#508) instead of deriving the weight
by hand from Acres/Total_Acre and a SUM(w)/49 rollup. The res-10 weights
asset is sparse, so the example keeps LEFT JOIN + COALESCE and bounds the
denominator with the dense ca30x30-ecoregion land grid.

The coarse case weights by nland * h3_cell_area rather than cell area alone:
statewide GAP 1+2 share comes to 26.135% from the res-8 asset that way,
matching the res-10 ground truth exactly, versus 25.684% weighting by nland
alone and 26.4% ignoring the partial-land correction.

Verified against live data: the issue's reproduce query now returns 33.31
for CWHR13 code 32 (assessment: 33.27), 21.65 for code 51 (21.59), and
51.70 for code 20 (51.67).
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.

h3-guide: fractional-overlay example omits h3_cell_area, contradicting the coarse-feature example on the same page

1 participant