Closes #152 #199

Merged
art-bot merged 2 commits from issue-152-shared-peaks into main 2026-08-20 21:43:36 +00:00
Owner

Closes #152


Shared peaks layer — fold is_haedarpunktar in (#152)

What changed

peaks is now a shared layer instead of Iceland-only.

  • conf/shared/contracts/19-peaks.yaml (new) — the peaks contract:
    stop_z: 11 / maxz: 14 / filter_only, attributes geom(point) + elevation(int),
    and the two cross-country checks moved off Iceland: R119 (no empty partition z11–z14,
    catalogue query) and R120 (every country's peaks carry a non-NULL elevation).
  • conf/is/08-peaks.yaml — now extends: peaks, so it builds map_peaks_<z>_is
    partitions instead of ismap_peaks_<z>. The elevation ladder (zoom_filters) stays
    per-country, as does Iceland's one claim: a new R31 test asserting the z11 coarse
    floor holds only the ≥500 m summits.
  • html/style.yaml — the peaks symbol layer reads source: map now
    (source-layer: peaks unchanged). The generated html/style.json is regenerated and
    passes gl-style-validate (make build).
  • conf/world.yaml — peaks added to the shared map source's layer list (so
    zxy_map concatenates zxy_map_peaks).
  • conf/is/downloads.yaml — the is source's layer list trimmed to [contours]
    (peaks is no longer served by zxy_is).
  • docs/ — schema, style, country-requirements (R13 line + layer inventory), and
    country-iceland updated for the fold.
  • importer/configdir_test.go — shared-contract count 17 → 18.

The attribute set is deliberately elevation-only

A spot height (geom + elevation) is the shape Iceland, Sweden (#101) and Poland (#104)
all fill, and the contract does not carry a name column: Finland's source (#108) is
still undecided (MTK korkeuspiste was empty in the 2025 delivery; DEM spot heights vs
named fells from paikannimi are a different shape). The contract stays at the shared
shape rather than gambling on a name only one option needs; whichever Finland lands on
either extends this contract or becomes a sibling one. That decision is reasoned in the
contract's comment.

Numbering note

The contract is 19-peaks.yaml (not 18) deliberately: #151's contours contract is
18-contours.yaml, and while it is not yet on main it is landing, so 19 keeps the
sequence clean rather than two 18-* files.

Important: #151 is NOT merged

The task assumed #151 (contours, PR #198) was already merged, so is would have no users
after this change. PR #198 is still open — on main the three contour layers still read
source: is. I therefore kept the is source block in html/style.yaml: contours need
it until #198 merges. Once #198 lands, is has zero users and should be removed. My change
made peaks the first layer off is; #198's makes contours the second; whichever lands
second retires the source.

Verification (against the live DB, before commit)

  • make build, make test, importer config-check conf/is/ and conf/world.yaml — all
    OK (18 shared contracts).
  • Reimported the peaks layer (importer import conf/is/ --layer peaks). Iceland's data was
    already fetched (is_50v_haedargogn_epsg_4326.gpkg); no re-download.
  • Row counts per zoom in the new shared partitions — byte-identical to the old
    ismap_peaks
    : z11=5678, z12=8936, z13=8936, z14=10156. All four partitions present
    with a gist geom index; 0 NULL elevations; one country (is).
  • Decoded tiles (scripts/mvt-decode.py on zxy_map_peaks): the peaks layer carries
    the elevation and country attributes; the z11 coarse-floor tile yields 3 peaks (the
    ≥500 m summits).
  • make acceptance — the peaks-specific and config-level checks pass:
acceptance: layer peaks (is) / R31: the z11 floor holds only the ≥500 m summits — PASS (peaks=5678, below_500=0)
acceptance: shared layer peaks / R119: no peaks partition is empty at any zoom z11–z14 — PASS (partitions=4)
acceptance: shared layer peaks / R120: every country's peaks carry a valid elevation — PASS (countries=1)
acceptance: 11 test(s): 11 passed, 0 failed, 0 skipped, 0 not run

One pre-existing, unrelated flake

make acceptance over all configs hit one failure: conf/pl buildings R120
("every Poland source part becomes a classified footprint…") timed out at 10 s. It is
unrelated to this change — it reads only map_buildings_*_pl/pl_bubd, which this PR
never touches — and is load-sensitive: the full query is 6.2 s in isolation but exceeds
10 s with the machine at load ~3.0 (5 users). Not a regression from this work; I did not
fix it here as it is outside #152's scope.

Left undone / notes

  • No destructive DB ops: the old ismap_peaks_<z> tables remain (orphaned, no DROP).
  • A live CDP render was not run; the peaks draw path is verified via the decoded tile and
    gl-style-validate. The is source removal is deferred to #198's merge as above.
Closes #152 --- # Shared peaks layer — fold is_haedarpunktar in (#152) ## What changed `peaks` is now a **shared layer** instead of Iceland-only. - **`conf/shared/contracts/19-peaks.yaml`** (new) — the `peaks` contract: `stop_z: 11` / `maxz: 14` / `filter_only`, attributes `geom(point) + elevation(int)`, and the two cross-country checks moved off Iceland: R119 (no empty partition z11–z14, catalogue query) and R120 (every country's peaks carry a non-NULL elevation). - **`conf/is/08-peaks.yaml`** — now `extends: peaks`, so it builds `map_peaks_<z>_is` partitions instead of `ismap_peaks_<z>`. The elevation ladder (zoom_filters) stays per-country, as does Iceland's one claim: a new R31 test asserting the z11 coarse floor holds only the ≥500 m summits. - **`html/style.yaml`** — the `peaks` symbol layer reads `source: map` now (`source-layer: peaks` unchanged). The generated `html/style.json` is regenerated and passes `gl-style-validate` (`make build`). - **`conf/world.yaml`** — `peaks` added to the shared `map` source's layer list (so `zxy_map` concatenates `zxy_map_peaks`). - **`conf/is/downloads.yaml`** — the `is` source's layer list trimmed to `[contours]` (peaks is no longer served by `zxy_is`). - **`docs/`** — schema, style, country-requirements (R13 line + layer inventory), and country-iceland updated for the fold. - **`importer/configdir_test.go`** — shared-contract count 17 → 18. ## The attribute set is deliberately elevation-only A spot height (geom + elevation) is the shape Iceland, Sweden (#101) and Poland (#104) all fill, and the contract **does not carry a `name` column**: Finland's source (#108) is still undecided (MTK `korkeuspiste` was empty in the 2025 delivery; DEM spot heights vs named fells from `paikannimi` are a different shape). The contract stays at the shared shape rather than gambling on a `name` only one option needs; whichever Finland lands on either extends this contract or becomes a sibling one. That decision is reasoned in the contract's comment. ## Numbering note The contract is `19-peaks.yaml` (not 18) deliberately: #151's contours contract is `18-contours.yaml`, and while it is not yet on main it is landing, so 19 keeps the sequence clean rather than two `18-*` files. ## Important: #151 is NOT merged The task assumed #151 (contours, PR #198) was already merged, so `is` would have no users after this change. **PR #198 is still open** — on main the three contour layers still read `source: is`. I therefore **kept the `is` source block** in `html/style.yaml`: contours need it until #198 merges. Once #198 lands, `is` has zero users and should be removed. My change made `peaks` the *first* layer off `is`; #198's makes contours the second; whichever lands second retires the source. ## Verification (against the live DB, before commit) - `make build`, `make test`, `importer config-check conf/is/` and `conf/world.yaml` — all OK (18 shared contracts). - Reimported the peaks layer (`importer import conf/is/ --layer peaks`). Iceland's data was already fetched (`is_50v_haedargogn_epsg_4326.gpkg`); no re-download. - Row counts per zoom in the new shared partitions — **byte-identical to the old `ismap_peaks`**: z11=5678, z12=8936, z13=8936, z14=10156. All four partitions present with a gist geom index; 0 NULL elevations; one country (`is`). - Decoded tiles (`scripts/mvt-decode.py` on `zxy_map_peaks`): the `peaks` layer carries the `elevation` and `country` attributes; the z11 coarse-floor tile yields 3 peaks (the ≥500 m summits). - `make acceptance` — the peaks-specific and config-level checks pass: ``` acceptance: layer peaks (is) / R31: the z11 floor holds only the ≥500 m summits — PASS (peaks=5678, below_500=0) acceptance: shared layer peaks / R119: no peaks partition is empty at any zoom z11–z14 — PASS (partitions=4) acceptance: shared layer peaks / R120: every country's peaks carry a valid elevation — PASS (countries=1) acceptance: 11 test(s): 11 passed, 0 failed, 0 skipped, 0 not run ``` ## One pre-existing, unrelated flake `make acceptance` over all configs hit one failure: `conf/pl` buildings R120 ("every Poland source part becomes a classified footprint…") timed out at 10 s. It is unrelated to this change — it reads only `map_buildings_*_pl`/`pl_bubd`, which this PR never touches — and is load-sensitive: the full query is 6.2 s in isolation but exceeds 10 s with the machine at load ~3.0 (5 users). Not a regression from this work; I did not fix it here as it is outside #152's scope. ## Left undone / notes - No destructive DB ops: the old `ismap_peaks_<z>` tables remain (orphaned, no DROP). - A live CDP render was not run; the peaks draw path is verified via the decoded tile and `gl-style-validate`. The `is` source removal is deferred to #198's merge as above.
peaks is no longer Iceland-only: a new conf/shared/contracts/19-peaks.yaml
contract (stop_z 11 / maxz 14 / filter_only, attrs geom+elevation) carries the
R119 no-empty-partition and R120 no-NULL-elevation checks, and
conf/is/08-peaks.yaml now `extends: peaks` so it builds map_peaks_<z>_is
partitions instead of ismap_peaks_<z>. The style's peaks symbol layer reads the
shared `map` source; the `is` source's layer list drops to [contours]; world.yaml
adds peaks to the map source. The elevation ladder (zoom_filters) stays
Iceland-specific, with a new R31 test asserting the z11 coarse floor holds only
the >=500 m summits.

The attribute set is deliberately elevation-only (no `name`): that is the spot-height
shape Iceland, Sweden (#101) and Poland (#104) fill, and Finland's source (#108) is
still undecided between DEM spot heights and named fells — the contract does not
gamble on a name only one option needs. The contract is numbered 19 rather than 18 so
it does not collide with #151's in-flight 18-contours.yaml.

#151 (contours, PR #198) is NOT yet merged, so contours still read `source: is` on
main; the `is` source block is therefore kept — whoever of #198/#152 lands second
should retire it.

Verified against the live DB before commit: build, test, config-check (18 contracts);
reimported peaks (no re-download); shared partitions z11–z14 byte-identical in row
count to the old ismap_peaks (5678/8936/8936/10156), 0 NULL elevations, gist indexes
present; decoded tiles carry peaks with elevation; gl-style-validate passes. Full
acceptance: the peaks R31/R119/R120 and config-level checks all pass (11/11 on the
peaks import). One unrelated pre-existing flake: conf/pl buildings R120 times out at
10s under load (6.2s in isolation; reads only Poland buildings, untouched here).
#151 (contours) landed on main while this was open, so the two folds meet here.
Conflicts resolved to the state both describe: conf/world.yaml's map source lists
contours *and* peaks, conf/is/08-peaks.yaml keeps this branch's R31 z11-floor test
(the R119 it replaces moved to the contract), the shared-contract count is 19, and
the docs record both folds rather than each claiming the other is still pending.

The consequence neither PR could land alone: `is` now has zero layers. This PR
planned to leave it declared because #151 was open; with #151 merged, leaving it
would be worse than a no-op — source.mvtFunc() renders a layerless source as
`SELECT '\x'::bytea`, an always-empty tile function on a live route. So the source
goes, which is what #151's own style.yaml comment said #152 would do:

- conf/is/downloads.yaml drops the `sources:` entry (empty `sources:` with the
  reasoning, the shape conf/se and conf/pl already use);
- html/style.yaml drops the `is` source block, and `peaks` reads `map`;
- conf/mapsrv.yaml serves `sources: [map]` — no /tiles/is route;
- conf/shared/acceptance.yaml's R30 drops its `zxy_is` row, which would otherwise
  call a function no config creates any more, and gains the four rows #151/#152
  owe it: zxy_map_contours and zxy_map_peaks at z2 and at stop_z-1. R30 is 26
  checks now, up from 23. (airports/airport_points are still absent from that
  list; they predate it and are not this PR's to add.)

Also fixed: 19-peaks.yaml had no trailing newline.

Docs swept for the retirement rather than only for peaks — geo-primer's "two
sources in one style" passage and its tile-function walkthrough (which told a new
reader to read `zxy_ismap_roads` and count `ismap_roads_8`, both gone; the
replacement numbers are measured, 58 302 → 586 at z8), schema.md's per-country
layer list (now empty), style.md's layer counts (53 hand-authored, all on `map`)
and its yq example that selected `source == "is"`, naming.md, unification.md's
"as it played out", country-iceland.md's header, and README's not-obsolete note.
unification.md's historical blockquotes and the pre-unification table are left as
the record of what was true then.

Verified on the live DB: peaks reimported into map_peaks_<z>_is — z11 5678,
z12 8936, z13 8936, z14 10156, matching the old ismap_peaks counts exactly — then
make import-world. `tiles --check` decodes peaks from zxy_map_peaks at z11/z14
with keys [elevation country]; at 12/1831/1079 over Iceland zxy_map is 3252 B
carrying both the 127 B of peaks that used to arrive via zxy_is and 1903 B of
contours. `importer acceptance conf/is` is 41/41 including both R31s and both
contract R119/R120 pairs; make test and gl-style-validate pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2QYwuohkM9vWJs6uzsK58
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
art/ismap!199
No description provided.