▶ CONTINUE 6/24 PM (National multimodal build COMPLETE — newest handoff)
TL;DR
- THE GAP CLOSED: commute DB was national but engine :8098 had ONLY the NYC tri-state network (every non-NYC isochrone = unreach_only). Built per-metro networks (scripts/regional_network_build.py: cuGraph walk+bike SSSP via pyosmium+Geofabrik + transit RAPTOR Arrow from golden GTFS) → output/networks/
/ (31/31). - ENGINE FLIP (013ded5→main d5cde52): additive multi-region loader — region by dest lat/lon, LRU evict (max 2 non-pinned, NYC pinned), regional_fares.py (Chicago $2.50 CTA not flat $3). NYC md5 byte-identical. Verified live: Chicago transit $2.50/20,169 cells, LA bike $1.75, Toronto $3.30. Precompute 32/32 real (Denver+Montreal corrupt stop_times fixed).
- API ALL-9-MODES NATIONAL (f573a28): OTP region-picker fixed, NE-OTP→geocoder:8091, P&R/K&R SQL un-gated from NJ-only transit_station, bike→GBFS, Canada drive haversine. Traffic Google-calibrated (60 rows, commute SCHEMA). Rankings (497K POIs) LIVE: /rankings,/most-walkable-cities (DC,NYC,Toronto),/best-transit-cities (NYC,Toronto,Vancouver),/best-commute-cities (Edmonton,Calgary,Ottawa).
- TOP PENDING: P&R/K&R/Uber+transit STILL NYC-only in engine (31 non-NYC metros carry 6 modes; need per-region rail-lot data in _build_rail_access). API SF transit $20 fare-snap. Flat-fare-city SEO transit numbers (CTA/TTC need transit_fares base fallback). Traffic calib only 15 metros. Canada OSRM missing.
- GOTCHAS: /v1/isochrone returns h3-keyed DICTS (times/costs/chains) NOT a cells list — parse resp['costs'].values(). API needs explicit modes:[...] or returns 3-mode default. traffic_peak_factors in `commute` schema not public. geo3 REAL IP=172.26.1.70 (.157=gtfs4); reach via geo jump host. pyosmium not pyrosm; origin-chunk LA under 360M-cell VRAM budget; NYC pinned in LRU.
CONTINUE — 2026-06-24 (PM) — National multimodal build COMPLETE
Host: geocoder (RTX 5080, 172.26.1.95). DB: commute @ 172.26.1.152:5433 (krish, trust-auth).
Live: https://commutingcost.com · https://multimodal.certihomes.com (GPU map, now national) · https://investors.commutingcost.com
Repos (all pushed): gpu-pilot @ d5cde52 (main, via geo bundle), commutingcost-web @ acb3b27, commutingcost-api @ f573a28, commutingcost-investor-portal @ ae8282f (all geo3 direct).
Read first: memory national-multimodal-engine, commutingcost-api-service, gbfs-national-coverage, gtfs-fare-ingestion, then gpu-pilot/NATIONAL_COMPLETE.md.
UPDATE 2026-06-24 (late PM) — P&R/K&R/Uber+Ride now NATIONAL (top gap CLOSED)
Two concurrent sessions finished the #1 pending gap below. Now live + committed:
- Regional rail classification (
hexmap-api/engine.py, commite5d4672, pushed): the NYC feed-prefix classifier marks every non-NYC stopCLS_SUBWAY, so railhead snapping for P&R/K&R/Uber+Ride now derives "is this rail?" from GTFSroute_type(1=subway/metro, 2=rail; 0=streetcar excluded) via the new_rail_platform_mask. NYC path untouched → byte-identical. Regional railhead with no NYC commuter-rail agency costs the region's flat transit fare. - Re-baked precompute, all 9 modes:
25 ok / 0 failed+7 ok / 0 failed(rail metros) — everyoutput/regional/<slug>_h3_res9.parquetnow carriespnr/knr/ubrcells. Verified: chicago 3,395 / la 4,161 / toronto 1,311 / dc 189. - stop_times fleet scan CLEAN (
scripts/audit_stop_times.py→/tmp/audit.json): all 31 regionsdep_lt_arr=0,dup_trip_seq=0,seq_ceiling_hit=0(max seq 8,820 « 32,767 int16),fail=false. Denver-1and Montreal int16 defects eradicated. - Converter now INTERPOLATES timepoint stops instead of dropping them (commit
ceae1b3): new testedscripts/gtfs_stop_times.py(+test_gtfs_stop_times.py), wired intoregional_network_build.py+repair_stop_times.py. Preserves frequency/timepoint-only feeds (e.g. orlando 652K both-blank rows) instead of gutting their networks.
Remaining engine gap is now just per-region park-lot $ data (railhead snapping works everywhere; lot-specific parking price still falls back to a default off-NYC).
DONE this session (the headline)
THE GAP WE CLOSED: the commute DB was national but the GPU engine :8098 had
ONLY the NYC tri-state network — every non-NYC isochrone returned unreach_only. A
spot-test caught it; we built per-metro networks and flipped the engine multi-region.
- Engine
:8098MULTI-REGION (flip013ded5, merged to maind5cde52): 32-metro registry, region-by-dest-latlon, LRU evict (max 2 non-pinned, NYC pinned), NYC byte-identical (md5-proven). Regional fares viahexmap-api/regional_fares.py. Verified live: Chicago transit $2.50/20,169 cells, LA bike $1.75, Toronto $3.30. - Per-metro networks 31/31 built (
scripts/regional_network_build.py→output/networks/<slug>/{transit,walk,bike}/, gitignored ~5.7G): cuGraph walk+bike SSSP (pyosmium + Geofabrik PBF) + transit RAPTOR Arrow from golden GTFS feeds. - Precompute 32/32 real (
output/regional/<slug>_h3_res9.parquet, cell→CBD). Denver+Montreal were empty (corrupt stop_times — fixed ind5cde52). - API all-9-modes NATIONAL (
f573a28): OTP region-picker fixed, NE-OTP repointed to geocoder:8091, P&R/K&R SQL un-gated from NJ-only, bike→GBFS, Canada drive haversine. - Traffic Google-calibrated (15 metros, 60 rows in
commute.traffic_peak_factors). - Rankings off 497,214 POIs: live at /rankings, /most-walkable-cities, /best-transit-cities, /best-commute-cities (JSON-LD ItemList+FAQPage).
- Web: 50 SEO pages /commute-cost/[metro], /compare, /TLCcosts H+T+U maps, green UI.
- Investor portal + PPTX deck (
decks/commutingcost_comparison.pptx) updated.
PENDING (precise, act-cold)
- P&R / K&R / Uber+Ride now NATIONAL ✅ (see UPDATE section at top —
e5d4672). Railhead snapping works in all metros via GTFSroute_type; all 9 modes baked into every regional parquet. REMAINING: per-region park-lot $ (the rail leg - flat-fare resolve; only the lot-specific parking price still uses a default
off-NYC — wire
cbd_parking/agency P&R rates into the railhead cost). - API SF transit $20 fare-snap —
get_od_fare(commutingcost-api cost_model.py) picks an over-long zone pair in dense multi-agency metros; cap the OD snap distance or prefer the nearest-agency primary feed. (SF Embarcadero→Civic Center should be ~$2.50.) - Flat-fare-city transit numbers on SEO pages — CTA/TTC/MTA-subway aren't in OD
gtfs_fares; the SEO dataset pulled e.g. NICTD for Chicago. Addtransit_faresbase-fare fallback incontent/build_metros_seo.py(engine already does this). - Traffic calibration only covers 15 metros; run
scripts/calibrate_traffic.pyfor the rest (key =CC_GOOGLE_MAPS_API_KEYin geo3 .env; readsGOOGLE_MAPS_API_KEY). - Canada OSRM — geo2 OSRM graph lacks Canada; Toronto drive uses haversine estimate.
- Monthly cron
gtfs-arrow/etl/run_monthly_etl.sh(15 3 1 * *) refreshes fares; regional networks are NOT yet on a cron (rebuild via regional_network_build.py).
DECISIONS (what the user chose + why)
- Live-protection LIFTED mid-session ("we are not live") → flipped the real
:8098engine instead of only proving on a test port. Still gated with md5 NYC regression +.bakrollback. - Traffic = free OSM baseline + Google calibration (~$20-50 one-time), not paid probe.
- Deploy straight to prod (user chose, not stage) — 50 SEO + 4 ranking pages indexed live.
- Per-metro networks, not one national grid (VRAM) — LRU region loading.
GOTCHAS (don't relearn)
/v1/isochronereturns h3-keyed DICTS (times/costs/chains/distances_m), NOT acellslist. Parseresp['costs'].values(). (Cost me 3 wrong probes.)- API needs explicit
modes:[...]array in the POST or it returns a 3-mode default. traffic_peak_factorsis in thecommuteSCHEMA, notpublic— qualify it.- geo3 real IP = 172.26.1.70 (the .157 in old notes is gtfs4); geocoder can't SSH geo3 directly (publickey) — reach via geo jump host. geo3 repos have their own push key.
- gpu-pilot pushes via geo bundle (geocoder has no GitHub key): bundle
BASE..main→ scp geo →git fetch bundle main:refs/temp/x; push origin refs/temp/x:main; update-ref -d. - pyosmium not pyrosm for OSM parsing. Origin-chunk large metros (LA) under a 360M-cell VRAM budget or OOM. NYC pinned in the LRU so it never evicts.
- sudo pw =
/home/krish/secert.txt(typo'd; global CLAUDE.md'ssecret.txtdoesn't exist). - DON'T touch port 8030 (Second Brain, 2GB VRAM).