[fix](backend): search/ingestion/reminder correctness fixes + offline RAPTOR test suite - #87
Open
SirQuackyy wants to merge 4 commits into
Open
[fix](backend): search/ingestion/reminder correctness fixes + offline RAPTOR test suite#87SirQuackyy wants to merge 4 commits into
SirQuackyy wants to merge 4 commits into
Conversation
…ests added for verification
SirQuackyy
marked this pull request as draft
August 27, 2026 18:14
SirQuackyy
marked this pull request as ready for review
August 27, 2026 19:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds a deterministic, offline test suite for the journey-planning stack (RAPTOR core, prediction ingestion,
/plan-journey, API handlers) built around a brute-force reference implementation, and fixes the correctness bugs that suite plus a full-workspace review surfaced. Covers routing, prediction ingestion, the reminder pipeline, the walking/street-graph layer, request validation, background jobs, and CI. Delayed ("DLY") buses are now surfaced to the frontend instead of being dropped.Type of Change
fix)feat)Related Issues
none
Changes Made
npm run test:search):raptor-core,raptor-property,ingestion,journey-plan,api-handlerstest/helpers/oracle.ts— brute-force Pareto enumerator written independently of the algorithm, plus a per-journey validator that replays legs against the raw data (buffers, pickUp/dropOff, transfer windows, criteria)test/helpers/network.ts/mockBusApi.ts— network DSL and realistic BusTime v3 payload builders (prd/ptrshapes,DUE,DLY, waypoints, loop passes)raptor-propertyruns 500 seeded random networks (loops, overtaking expresses, minute-quantized ties, boarding restrictions, windowed transfers) against the oracle; a 5,000-seed sweep was run out-of-bandapi/path/search-stress) now throw instead ofprocess.exit(1), which was killing the vitest worker and masking other files' resultsreminder.test.ts:every(allThere)short-circuited after index 0 (only the first prediction was ever validated) →forEach; ride clock assertion tightened from ±2 days to ±1 hour; live-pipeline test no longer fails when no vehicles are in serviceraptor/,services/journey.ts):pickUp: false/dropOff: falsehandled correctly; footpath relaxation snapshots labels so walks can't chain; on-board labels advance per stopdeparture − walk − buffer) plus the window end, journeys are keyed by trip identity (a missingtatripidno longer misclassifies a bus journey as walking), and the full Pareto set per trip signature is keptdepartureTimeis the first leg's start time (wasarrival − Σ durations, wrong with any wait);walkingPenaltyof 0 is respected;walkingDistancedocs corrected (penalty-weighted seconds, not meters)services/graphBuilder.ts,state/):DLYpredictions are surfaced to the prediction endpoints (finite far-futureprdtm, sorted last) and excluded from routing and reminder trackingtatripidfrom different vehicles no longer merge into one tripisExtrapolatedcarried into the graphfindNearestStopsheap comparator fixed (it evicted the nearest stop, not the farthest) and now uses the sharedhaversineservices/bustimeClient.ts,mbus.ts,ride.ts):ride.tswas a drifting copy ofmbus.ts— both are now thin wrappers over one shared factoryerrorbody; those (and any out-of-protocol 200 body, e.g. a proxy maintenance page) are now treated as failures instead of "no buses", which previously wiped the prediction caches and mass-fired false "Bus Disappeared" pusheswalkingCache.json(224 MB) andlandmark_dist.jsonare written atomically (temp + rename) with guarded parses — a kill mid-write used to make the server crash-loop on every bootMinHeapreplaced with the already-installed@datastructures-js/priority-queueDLYflip holds rather than guessingregistration-token-not-registeredswapTokendedups against the target token and is a no-op for identical tokens; errors log with real stacks (JSON.stringify(err)was printing{}); failure logs name the correct batch's tokens; Firebase init is idempotent/plan-journeyvalidates coordinates,walkingPenalty, andrange(non-numeric input returned 500 before)threshbounded to 1–120 minutes;modifyRemindersvalidates the whole batch before applying anything; sharedparseBodyhelper replaces four copies of the zod error block/getBusPredictions1/:busIdno longer interpolates a user-controlled param into a query string carrying the API key, and honorsMBUS_URL/getBusPredictions/constructorno longer breaks the response shapemin_supported_versionrestored to2.0.2(branch had it lowered to2.0.0for dev, which would re-admit clientsmainlocked out)notifyMeLaterreturns a real 400 and restores its 10s delay;nearest-stopsfalls back tok=2on garbage inputprocess.cwd(); boot jobs share the interval overlap guards;startBackgroundJobsis skipped under vitestsrc/types.tsand the unusedts-array-utilsdependency;documented_design.mdstatus corrected from "Implemented" (the files it references don't exist on this branch)sendEachForMulticast(a rejection could take down the server), idempotentinitializeAppmain(fork PRs previously always failed the deploy step for lack of secrets, and any branch push published docs); test job waits on real data readiness instead of a no-opcurlloop that exited on the server's 404;npx tscwith a pinnedtypescriptdevDependency instead of the runner's global oneTesting Done
99 automated tests pass (77 offline + 22 reminder),
tsc --noEmitclean. The offline suite runs in ~0.5s with no network and no live server. A 5,000-seed differential fuzz against the brute-force oracle passes on the final routing code, and A* was re-verified to match Dijkstra to sub-second rounding on the real Ann Arbor graph. Also smoke-tested against a locally running server with the live feed: journey planning, range mode, validation paths, and error handling all behave correctly, and the working tree stays clean. Every fix in this PR was additionally put through an adversarial review pass that specifically hunted for regressions and incomplete fixes in the diff; that pass found 13 issues with the first round of fixes, all of which are fixed here and covered by tests.Screenshots / Demo (if UI or notification change)
n/a
Checklist
[type](scope): short descriptionmainand is our current working update branch (e.g.maizebus2.1)print()/debugPrint()/console.log()left in production code