Run PointsPath overlay on the gflight backend (work-qmx1)#7
Merged
Conversation
Drops PP's matrix-only gate. The matcher in pp/match.py joins by structural keys that don't care which backend produced the cash side, so an adapter that wraps fli's FlightResult into the same SearchResult shape is enough — matcher and renderer reuse end-to-end. Plain `flight search --pp-only` now rides gflight (~0.7s vs Matrix's ~26s) instead of being silently routed to matrix. PP flags no longer influence `_pick_backend`. Stays on `enable_matching=False` deliberately: fli doesn't expose Google's opaque flight IDs, the prior probe shows synthetic IDs produce empty PP responses, and the existing (flight#, date) + (route, time) keys already bridge codeshares. The matched-ID upgrade path is documented at docs/memories/pp_on_gflight.md for a future spike. Closes work-qmx1.
ak2k
added a commit
that referenced
this pull request
Jun 13, 2026
…bined under-reports) Revises the split-on-empty approach after a sharper look at the data. Matrix's calendar under-reporting is NOT all-or-nothing: a query over budget returns *fewer* solutions, degrading toward zero — and a non-empty combined multi-airport result is itself short of the true union (live: the combined grid reports 155 solutions where querying the four destinations separately and merging yields 620, ~4x more). So split-on-empty was wrong twice over: it only recovered on a clean empty (never on silent partial under-reporting), and it trusted a non-empty combined result that's incomplete. Rate-limit + latency probe settled the design: Matrix tolerates >=16 concurrent requests from our IP/key with flat latency and no throttling (the rps=1 default was conservative-without-evidence), and each round costs ~50s. With parallelism free and rounds expensive, the optimum is the *maximal* partition — one query per (origin, destination), all fired in parallel, merged — which is the floor on both latency (one round) and correctness (each single destination fully prices). Chunking into fewer-but-bigger groups is dominated: it optimizes query count (a resource Matrix doesn't charge us for) while risking both an extra round and silent incompleteness. _run_calendar now always fans a multi-airport calendar out per-destination at high concurrency (capped at 12, under the measured-safe 16); single-airport runs one query. Tests + AGENTS.md quirk #7 updated to the per-destination model.
ak2k
added a commit
that referenced
this pull request
Jun 13, 2026
…rge (Matrix under-reports the combined grid) (work-on0dw) (#26) * flight-cli: recover Matrix calendar compute-budget sheds by per-destination split + merge (work-on0dw) Matrix's calendar engine silently returns 0 solutions (HTTP 200, no error or warning) once a query exceeds its per-query compute budget. Measured: MIA<->[VIE, PAR,FCO,MAD] +LH+ over a 30-day window = 0, but each destination alone prices fine (VIE 155 / PAR 27 / FCO 24 / MAD 17), 3-dest=12, 2-dest=155; narrowing the window 30->7 days recovers (0->4). So cost ~= (origins x destinations) x (departure days) x (routing complexity), and the ceiling is load-dependent. It is NOT our encoding (to_wire byte-matches the calendar_nyc_munich_frankfurt SPA fixture) and NOT transient-per-request (retrying the same query in-window never recovers it) — so retry/speculative-racing can't help. `flight calendar` now auto-recovers: on an empty multi-airport result it splits into one calendar sub-search per (origin, destination) pair, runs them in parallel on one client, and merges the grids — per departure day the lowest fare across destinations, per-duration columns the cross-destination min, sols summed. Optimistic-combined / split-on-empty: it only fans out when Matrix actually sheds the combined query (self-tuning, no hard threshold) and is self-validating — if the sub-searches are also empty it surfaces a genuine no-flights result. Bounded to <=6 sub-queries. - _calendar_split.py: split_calendar_search + merge_calendar_results (pure). - cli._run_calendar / _gather_calendar: orchestration in one event loop. - Tests: split/merge units + deterministic split-on-empty orchestration (fake client). AGENTS.md quirk #7 rewritten with the precise mechanism. * flight-cli: always query multi-airport calendars per-destination (combined under-reports) Revises the split-on-empty approach after a sharper look at the data. Matrix's calendar under-reporting is NOT all-or-nothing: a query over budget returns *fewer* solutions, degrading toward zero — and a non-empty combined multi-airport result is itself short of the true union (live: the combined grid reports 155 solutions where querying the four destinations separately and merging yields 620, ~4x more). So split-on-empty was wrong twice over: it only recovered on a clean empty (never on silent partial under-reporting), and it trusted a non-empty combined result that's incomplete. Rate-limit + latency probe settled the design: Matrix tolerates >=16 concurrent requests from our IP/key with flat latency and no throttling (the rps=1 default was conservative-without-evidence), and each round costs ~50s. With parallelism free and rounds expensive, the optimum is the *maximal* partition — one query per (origin, destination), all fired in parallel, merged — which is the floor on both latency (one round) and correctness (each single destination fully prices). Chunking into fewer-but-bigger groups is dominated: it optimizes query count (a resource Matrix doesn't charge us for) while risking both an extra round and silent incompleteness. _run_calendar now always fans a multi-airport calendar out per-destination at high concurrency (capped at 12, under the measured-safe 16); single-airport runs one query. Tests + AGENTS.md quirk #7 updated to the per-destination model. * flight-cli: bound the calendar fan-out — never silently fall back to the incomplete combined The fan-out is the cartesian product of origins x destinations (just |destinations| in the common single-origin case, but a product when both axes are multi). The previous ceiling silently fell back to a single combined query above 24 pairs — which under-reports, the exact failure this feature fixes. Replace it: - Concurrency stays at 12 (measured-safe is >=16); larger lists batch into multiple ~50s rounds and a dim heads-up notes the round count. - A hard cap (36 = 3 rounds) refuses with a clear error ("narrow the airports or window") rather than silently returning an incomplete grid. Completeness is preserved for every multi-airport query we accept. * flight-cli: add --max-per-query and --max-concurrency to calendar Make the completeness/speed trade explicit and the user's, rather than a silent default. split_calendar_search now groups up to --max-per-query destinations per sub-search (default 1 = one destination each, the only size guaranteed complete); higher values cut the request/round count but Matrix may under-report a multi-destination grid, so _run_calendar warns when --max-per-query > 1. --max-concurrency exposes the fan-out concurrency (default 12; measured-safe is ≥16). The hard cap still refuses absurd fan-outs, and its error now points at --max-per-query as the lever to fit a large query.
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.
Summary
pp/gflight_adapter.pywraps fli output in aSearchResultshape — the matcher and renderer reuse unchanged.flight search --pp-onlynow stays on gflight (~0.7s) instead of being silently routed to matrix (~26s)._pick_backend; signature simplified.Why
enable_matching=FalseStays on the existing (flight#, date) + (route, time) keys deliberately. The
matched-Google-flight-id path was considered, but:
FlightResultcarries no opaque GF ID — only structured fields.research/probe_pp_matching.py, gitignored) shows syntheticflight_ids cause PP to filter to empty results; well-formed real-ID
format is unverified.
The matched-ID upgrade path is documented at
docs/memories/pp_on_gflight.md,together with the prepared
research/probe_pp_real_hints.pyprobe for thefollow-up spike (deferred — refresh token was stale when attempted).
Verification
make checkgreen: 115 tests passing (was 107: +6 adapter, +5 should-run-pp, -3 obsoleted from backend dispatch).tests/pp/test_gflight_adapter.py,tests/test_should_run_pp.py.Test plan
flight search EWR MIA --dep 2026-08-15→ gflight results render.flight search EWR MIA --dep 2026-08-15 --pp-only→ PP table renders without matrix table.flight search EWR MIA --dep 2026-08-15 --no-pp→ cash table only, no PP.flight search NYC LAX --dep 2026-08-15 --pp-airlines United,Delta→ routes to gflight (was matrix before), PP filters by airline.