Skip to content

Run PointsPath overlay on the gflight backend (work-qmx1)#7

Merged
ak2k merged 1 commit into
mainfrom
worktree-qmx1-pp-on-gflight
May 15, 2026
Merged

Run PointsPath overlay on the gflight backend (work-qmx1)#7
ak2k merged 1 commit into
mainfrom
worktree-qmx1-pp-on-gflight

Conversation

@ak2k

@ak2k ak2k commented May 15, 2026

Copy link
Copy Markdown
Owner

Summary

  • Dropped PP's matrix-only gate. Both backends now run the overlay when tokens are present.
  • New pp/gflight_adapter.py wraps fli output in a SearchResult shape — the matcher and renderer reuse unchanged.
  • Plain flight search --pp-only now stays on gflight (~0.7s) instead of being silently routed to matrix (~26s).
  • PP flags no longer influence _pick_backend; signature simplified.

Why enable_matching=False

Stays on the existing (flight#, date) + (route, time) keys deliberately. The
matched-Google-flight-id path was considered, but:

  • fli's FlightResult carries no opaque GF ID — only structured fields.
  • The prior probe (research/probe_pp_matching.py, gitignored) shows synthetic
    flight_ids cause PP to filter to empty results; well-formed real-ID
    format is unverified.
  • Existing keys already bridge codeshares (work-22az).

The matched-ID upgrade path is documented at docs/memories/pp_on_gflight.md,
together with the prepared research/probe_pp_real_hints.py probe for the
follow-up spike (deferred — refresh token was stale when attempted).

Verification

  • make check green: 115 tests passing (was 107: +6 adapter, +5 should-run-pp, -3 obsoleted from backend dispatch).
  • New tests: tests/pp/test_gflight_adapter.py, tests/test_should_run_pp.py.

Test plan

  • Manual smoke: flight search EWR MIA --dep 2026-08-15 → gflight results render.
  • Manual smoke (post-login): flight search EWR MIA --dep 2026-08-15 --pp-only → PP table renders without matrix table.
  • Manual smoke: flight search EWR MIA --dep 2026-08-15 --no-pp → cash table only, no PP.
  • Manual smoke: flight search NYC LAX --dep 2026-08-15 --pp-airlines United,Delta → routes to gflight (was matrix before), PP filters by airline.

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 ak2k merged commit 3aba9dc into main May 15, 2026
2 checks passed
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant