Skip to content

climb13ers landed in peak_db — what changes here

For: mtn_research · From: peak_db / peak_checklist · Date: 2026-08-24 Answers: climb13ers-into-peak-db.md · tracking issue #22

The ask in that spec is done. peak_db now carries the climb13ers link as a first-class source. peak_db is the source of truth for it from here. Kyle: "mtn_research should use your db in the future."


What exists now

Three columns on peaks, alongside loj_url / fourteeners_url / peakbagger_url:

column example
climb13ers_slug un13158
climb13ers_url https://www.climb13ers.com/colorado-13ers/un13158
climb13ers_link_how PRELIDAR

597 CO 13ers linked, 597 distinct pages — no two peaks share a page. Provenance was kept per row as asked, so the soft tiers stay visibly weaker:

climb13ers_link_how rests on n
VERIFIED labelled summit marker on the page's own CalTopo map 302
PRELIDAR pre-LiDAR slug and page elevation agrees 221
REPAIRED elevation + range + name — relinked, see below 48
EXACT page cross-references listsofjohn.com/peak/<id> 17
MATCH elevation + name — a judgement, not a key 7
REVIEWED Kyle confirmed by eye 1
REPAIRED_UNNAMED elevation + range only — peak_db has no name to check 1

MATCH and REPAIRED_UNNAMED are the two tiers resting on judgement rather than a key.

Read it with the shared client:

import sys
sys.path.insert(0, "/Users/kyleknutson/Library/Mobile Documents/com~apple~CloudDocs/shared/peak_db")
from peak_db_client import peaks
rows = peaks(state="eq.CO")          # climb13ers_slug / _url / _link_how are on every row

⚠ The handover map mislinked 49 of the 597 rows

docs/data/climb13ers_map.json is not safe to re-import or regenerate. 49 rows in it point at the wrong mountain — the same class of defect the spec was written to eliminate, one axis over.

The spec's key insight was right: climb13ers keys its slugs to the pre-LiDAR elevation. What it missed is that pre_lidar_elevation_ft is not unique. Five distinct peaks share a pre-LiDAR 13,380. Each independently claimed the one page carrying that alias:

peak_db pointed at what that page actually is
108 Half Peak 13,866 un13841--atlantic-peak Atlantic Peak, Tenmile
503 James Pk 13,272 un13294-the-citadel The Citadel
737 Whale Pk 13,080 un13078 a Sawatch peak ~13 mi off
222 West Spanish Peak 13,584 un13626 not it
416 South Lookout Pk 13,420 un-13380--triangle-peak Triangle Peak

Root cause — scripts/sweep_climb13ers.py:627

cands = by_old_slug.get(old)            # pages whose slug_ft or alias_ft == peak's pre-LiDAR
if len({c["slug"] for c in cands}) > 1: # ← only fires on PAGE-side ambiguity
    cands = [c for c in cands if c["elevation"] == ft(p)]
if len({c["slug"] for c in cands}) == 1:
    prelidar[p["id"]] = cands[0]["slug"]

The second key — page current elevation vs elevation_ft — is applied only when two pages claim one pre-LiDAR number, never when two peaks do. So the tier documented as "two keys, no inference" ran on one key for every peak-side collision. Five peaks with current elevations 13378 / 13381 / 13420 / 13405 / 13365 all passed into one page; at most one of them can be right.

Fix: apply the elevation filter unconditionally, not inside the > 1 branch. Peaks that then fail it should fall through to the VERIFIED / EXACT / MATCH tiers, which is what should have happened originally.

Second, smaller issue: by_old_slug indexes pages on both slug_ft and alias_ft. For a page that was never renamed, slug_ft is its current elevation — so matching a peak's pre-LiDAR number against it is exactly the cross-key confusion the spec's opening un13155 example warns about. That produced id 171 (Grizzly Mountain), the one bad row that was not a collision.

How the 49 were repaired

Every one had its own correctly-named page sitting unusedhalf-peak, james-peak, whale-peak, west-spanish-peak. Relinked on exact current elevation + range, with name agreement on 48 of 49 (id 381 is peak_db PT 13,494, which carries no name to check; the page is peak-ten). Tagged REPAIRED so a correction never looks like a derivation — issue #23's rule.

Then all 597 links were verified against the cached pages' own <title> elevations in .cache/climb13ers/pages/: zero mismatches.

The full before/after is in docs/data/climb13ers_repaired.json — evidence for checking a regenerated map against, not an input to import.


What to do here

  1. Read climb13ers_url from peak_db. Delete the local mapping table and all URL-derivation code. The defect the spec describes becomes impossible once nothing here builds a slug.
  2. Rebind check_climb13ers_url.py to peak_db instead of docs/data/climb13ers_map.json (currently MAP_FILE, line 42; also referenced by run_gates.py:130 and test_climb13ers_url.py:49). Keep the gate — it is the thing that should have caught the original wrong-peak citation. Worth a test that it fails when handed a URL for the wrong peak; that is the case it missed.
  3. Do not re-run sweep_climb13ers.py until :627 is fixed. As it stands it will reintroduce all 49. If a regenerated map is ever re-imported into peak_db it silently overwrites the REPAIRED rows and puts Half Peak back on Atlantic Peak's page.
  4. Retire docs/data/climb13ers_map.json once (1) and (2) land, so there is one answer to "which page belongs to this peak" rather than two that can drift.

Nothing else was taken from climb13ers. It disagrees with 14ers/peak_db on elevations, names and disambiguator letters — 14ers remains the truth for facts; climb13ers contributes only the link. Letters are not a join key in either direction.

Also worth knowing

Both facts the spec asked to have written down are now in peak_checklist/schema.sql, on the peaks.id column: a peak's id IS its Lists of John id, and out-of-state peaks carry negative ids — 15 non-CO peaks (CA, HI, NM, NV, UT, WY) sit in the 13,000–14,000 ft band, so filter a "Colorado" census on state, never on elevation alone.

The staleness check suggested in the spec is still the right approach and is unbuilt: hash /colorado-13ers/peaks (one fetch, every slug + current elevation + "Formerly UN" alias) to detect renames, rather than re-crawling 650 pages.

Unrelated: this repo has 2 unpushed commits

scripts/refresh_from_peakdb.py ran after the peak_db change (its normal hook) and committed homestake_peak.md → climbed, but its push hit the pre-push gate:

  • no recording of Kyle's in gpx/homestake_peak/_kyle_existing/
  • the drive link ends 2.22 mi from where the recommended route starts

Both surfaced only because the peak flipped to climbed, subjecting the report to gates it had not faced before. Neither relates to climb13ers. A second commit, 031f37f ("Home page catches up with Homestake Peak being climbed"), came from outside that run and was left alone. The gate was not overridden — that is Kyle's call.