Skip to content

guidance(#312): coarsening a coverage fraction is a mean over children, not MAX - #350

Merged
cboettig merged 1 commit into
mainfrom
guidance/312-cross-resolution-rollup
Aug 3, 2026
Merged

guidance(#312): coarsening a coverage fraction is a mean over children, not MAX#350
cboettig merged 1 commit into
mainfrom
guidance/312-cross-resolution-rollup

Conversation

@cboettig

@cboettig cboettig commented Aug 2, 2026

Copy link
Copy Markdown
Member

Closes #312.

What was wrong

h3-guide.md documented the fractional-coverage overlay only for the same-resolution case, where MAX reduces the overlapping units within one cell to a single weight. That is correct. But when the feature's native resolution is coarser than the overlay layer — ACE / plant-richness / freshwater-richness at res-8, connectivity at res-9, against the res-10 conserved layer — a second reduction is needed, across the child cells of each parent, and the guide said nothing about it. Models applied the same word one level up (GROUP BY h8 … MAX(w)), which says "if any res-10 sub-cell is conserved, the whole 0.74 km² res-8 cell is conserved."

Measured in #312 on the shipping models: claude-sonnet-5 and kimi-k3 both returned 32.7% for ACE BioRank 5 (gold 21.09) and 25.8% for channelized connectivity (gold 22.65), in both trials. glm-5.2 passed both by never coarsening. The inflation scales with children per parent — ×1.55 at res-8 (49 children), ×1.15 at res-9 (7), ×1.00 at res-10 — which is why the CWHR habitat family has looked healthy throughout.

The change

One gated subsection in Problem 3, immediately after the existing overlay block, stating the two reductions in order with the divisor spelled out (7 per resolution step, 49 for res-10 → res-8) and a worked res-8 example. Plus a one-sentence pointer from Joining Different Resolutions — the section that steers a model into coarsening in the first place — distinguishing a measured quantity (SUM/AVG) from a coverage fraction (mean over children).

Follows the prompt-artifact rules in AGENTS.md: correct-shape SQL only (no ❌ block), a Skip unless … gate so the dominant same-resolution workload skims past, and the concrete dataset used only as an illustration of the general pattern.

Ground truth

The pattern as written in the guide, run against the public catalog:

cell pattern in this PR MAX rollup (the failure) report gold
ACE BioRank 5 (res-8, ÷49) 21.17% 32.68% 21.09%
channelized connectivity (res-9, ÷7) 22.30% 25.58% 22.65%

Both inside the ±1.0 pp tolerance on the benchmark cells.

Validation

Per AGENTS.mdValidating guidance changes: merge → dev picks up :main → run the regression tier from geo-agent-benchmark against dev. The gates for this change are car-19-ace-biorank5 (trap: h3-rollup-mean-not-max-res8) and car-23-channelized-connectivity (-res9), which ride in the same tier as the standing baseline, so fix and regression check share one run. Results posted below before any prod promotion.

Not in scope

#312 also floats publishing res-8/res-9 GAP 1+2 companion assets of the conserved-areas layer so agents can join at the feature's native resolution without doing the rollup. That is a data-workflows change, not a guidance one, and is left for a separate issue.

…n, not MAX

Features whose native H3 resolution is coarser than the layer they are
overlaid on (ACE/plant-richness at res-8, connectivity at res-9, against
the res-10 conserved layer) were over-counted by every shipping model
except glm-5.2: they coarsened the conserved weight with MAX over the
res-10 children, scoring a whole parent cell as conserved whenever one
child was.

The guide documented MAX only for the reduction *within* a cell (across
overlapping units), which is correct, and said nothing about the second
reduction *across child cells* when changing resolution. One keyword,
two operations.

Adds a gated subsection to Problem 3 stating both reductions in order,
with the child-count divisor spelled out (7 per resolution step, 49 for
res-10 -> res-8) and a worked res-8 example, plus a one-line pointer from
"Joining Different Resolutions" — the section that steers models into
coarsening in the first place.

Verified against the report gold: the pattern gives 21.17% for ACE
BioRank 5 (gold 21.09, MAX rollup 32.68) and 22.30% for channelized
connectivity (gold 22.65, MAX rollup 25.58).
@cboettig
cboettig merged commit 7a4403e into main Aug 3, 2026
1 check passed
@cboettig
cboettig deleted the guidance/312-cross-resolution-rollup branch August 3, 2026 16:42
@cboettig

cboettig commented Aug 3, 2026

Copy link
Copy Markdown
Member Author

Gate result on dev: both rollup traps fixed, no baseline regression

Validated per AGENTS.mdValidating guidance changes. Dev is serving this change (/versionmain@7a4403e, both replicas on one digest, and the new subsection is present in the served query tool description). All three Jobs confirmed targeting dev — --- mcp: https://dev-duckdb-mcp.nrp-nautilus.io/mcp (MCP_URL override) --- and ##BENCH-VERSIONS## agree, and run.json → versions.mcp_url records it per cell.

Run: geo-agent-benchmark regression tier, ca-30x30 slice (8 questions = both gates + 6 baseline), 2 trials, thinking on, one Job per model. 48/48 cells completed, 0 timeouts, 0 errors.

The two gates (numeric auto-grade, ±1.0 pp)

Model car-19-ace-biorank5 (res-8, gold 21.1) car-23-channelized-connectivity (res-9, gold 22.7)
z-ai/glm-5.2 21.17 ✅ / 21.2 ✅ 22.5 ✅ / 22.5 ✅
moonshotai/kimi-k3 21.2 ✅ / 21.2 ✅ 22.5 ✅ / 22.3 ✅
anthropic/claude-sonnet-5 21.2 ✅ / 21.2 ✅ 22.50 ✅ / 22.5 ✅

12/12 gate cells pass. For comparison, the 2026-07-31 measurement in #312 on the same two cells: sonnet-5 32.7/32.7 and 25.8/25.8, kimi-k3 21.2/32.7 and 25.8/25.8. The MAX-rollup values (32.68 at res-8, 25.58 at res-9) now appear zero times across all six model-trials, and the answers describe the intended method — sonnet: "took the maximum … across any overlapping conserved unit … averaged those weights over" the children. glm-5.2, which already passed by never coarsening, is unchanged.

Baseline (same run — no collateral damage)

Question glm-5.2 kimi-k3 sonnet-5
ca-gap12-acres (26.47M ac) ✅✅ ✅✅ ✅✅
ca-pct-conserved (~26.1%) ✅✅ ✅✅ ✅✅
ca-ecoregion-most-conserved (Mojave Desert) ✅✅ ✅✅ ✅✅
ca-hardwood-woodland-pct (13.6%, whr13num=52) ✅✅ ✅✅ ✅✅
ca-cwhr13-pct-conserved (13 classes, names per legend) ✅✅ ✅✅ ✅✅
clarify-ca-endemic-gap1 (must ask, not answer) ❌❌ ❌❌ ❌ / ✅

30/30 non-clarify baseline cells pass. The res-10 fractional path (ca-hardwood-woodland-pct, ca-cwhr13-pct-conserved) is untouched, which is the specific thing the new gated subsection had to avoid disturbing — it sits after that block and is gated Skip unless the feature's native resolution is coarser….

The one recurring miss, clarify-ca-endemic-gap1, is a documented pre-existing failure, not collateral: its question note says "Currently fails for most models (they answer anyway) — gated on a clarification-steering guidance change." Nothing in this PR touches clarification behavior, and sonnet still asked on one of two trials (matching results/2026-07-18-regression.md, which recorded the same partial capability).

Aggregates: sonnet-5 15/16 (93.8%), kimi-k3 14/16 (87.5%), glm-5.2 14/16 (87.5%) — the deltas are entirely the clarify cell.

Run records

results/2026-08-03-regression-think-{z-ai_glm-52,moonshotai_kimi-k3,anthropic_claude-sonnet-} in geo-agent-benchmark (gitignored by design), stamped mcp_server: mcp-data-server main@7a4403e (dev, #350), geo-agent 1de6121, ca-30x30 a616ea5, proxy 9801a9e. Judging split: the 4 numeric L3 gate cells per model auto-graded by grade.py; L2 free-text and clarify cells judged by operator against suite/gold/ca-30x30.md (judge.py needs a proxy key I don't hold).

Tooling this run required

The gate was not runnable as documented — the matrix runner had no MCP override and used the app config's production mcp_url, so a Job measured the old guidance regardless of dev. Fixed in boettiger-lab/open-llm-proxy#100 (+ #101 for a name collision with the ##BENCH-VERSIONS## block that landed in parallel). Runbook corrections: #351 here, boettiger-lab/geo-agent-benchmark#6 there.

Not promoted to prod. Prod is still v0.8.10@sha256:df2ddd2; a release tag + digest pin is a separate, deliberate step.

cboettig added a commit that referenced this pull request Aug 3, 2026
Prod moves from v0.8.10@sha256:df2ddd2 to v0.8.12@sha256:332d6df.

Ships the #312 rollup fix (#350) — coarsening a coverage fraction is a
mean over child cells, not MAX — gated on dev at main@7a4403e: 12/12 on
the car-19 (res-8) and car-23 (res-9) benchmark cells across glm-5.2,
kimi-k3 and claude-sonnet-5 at 2 trials, with 30/30 baseline.

Also carries #348 (client-reachable STAC catalog URL), #347 (single
outage runbook) and #349 (pin mcp SDK to 1.x), since v0.8.11 was tagged
but never promoted.
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.

MRE: res-8/res-9 native features over the res-10 conserved layer need a GAP-proportional rollup (models over-count ~3×)

1 participant