Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# reference data
# reference data (downloaded airports, etc.)
/data/*
# curated MCT starter dataset (checked in — see data/reference/mct/)
!/data/reference/
!/data/reference/.gitkeep
!/data/reference/mct/
!/data/reference/mct/**
/data/reference/airports.json
/data/reference/metro-areas.json
/data/reference/decommissioned.json

# OTAIP run/gate traces (durable JSONL written by @otaip/integration)
traces/
Expand Down
26 changes: 26 additions & 0 deletions data/reference/mct/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# MCT reference data (`data/reference/mct/`)

Curated Minimum Connecting Time rows for Agent 1.3 Connection Builder.

**Authority:** IATA SSIM Chapter 8 + PSC Resolution 765. See `docs/knowledge-base/mct.md`.

## Hierarchy (most specific → fail-closed)

| Priority | Level | File / field | When used |
| -------- | ------------------ | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| 1 | Carrier override | `carrier-overrides.json` | Matching arriving/departing carriers (+ connection status) at airport; optional terminals |
| 2 | Airport + terminal | `airport-rules.json` (`terminal_change` or terminal pair set) | No carrier match; terminal change known |
| 3 | Airport | `airport-rules.json` (station default for status) | No carrier/terminal match |
| 4 | Fail-closed | — | **No invented IATA global table.** MCT unresolved → connection invalid |

## Rules for adding rows

- Cite a source (`source` field): SSIM/aggregator extract, public doc URL, or `already-in-code:…`.
- Do **not** add airport-constant guesses or a global 60/90 table.
- Do **not** derive MCT from haversine / great-circle distance.
- Interline / unpublished carrier exceptions → leave as `DOMAIN_QUESTION` in the KB; do not invent.

## Files

- `carrier-overrides.json` — carrier@airport starter rows
- `airport-rules.json` — station/terminal rows (empty until a real extract is available)
7 changes: 7 additions & 0 deletions data/reference/mct/airport-rules.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"version": "0.1.0",
"description": "Airport / airport+terminal MCT rules from SSIM station filings. Empty until a real extract is curated — do not invent airport constants.",
"authority": ["IATA SSIM Chapter 8", "IATA PSC Resolution 765"],
"hierarchy_levels": ["airport_terminal", "airport"],
"rules": []
}
25 changes: 25 additions & 0 deletions data/reference/mct/carrier-overrides.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"version": "0.1.0",
"description": "Carrier-specific MCT overrides (SSIM Ch.8 / PSC Res 765). Starter set only — not a full industry extract.",
"authority": [
"IATA SSIM Chapter 8",
"IATA PSC Resolution 765",
"https://www.iata.org/contentassets/638f0938b3dd451b872a1d8357755421/minimum-connecting-time-user-guide_version-1.1.pdf"
],
"hierarchy_level": "carrier_override",
"overrides": [
{
"airport": "ORD",
"arriving_carrier": "UA",
"departing_carrier": "UA",
"connection_status": "DD",
"connection_type": "domestic",
"scope": "online",
"minutes": 50,
"arrival_terminal": null,
"departure_terminal": null,
"source": "already-in-code: packages/agents/search/src/connection-builder/mct-data.ts carrier_rules (pre-#141)",
"notes": "Online same-carrier domestic at ORD. Not validated against a public SSIM/OAG extract."
}
]
}
2 changes: 1 addition & 1 deletion docs/agent-map.html

Large diffs are not rendered by default.

24 changes: 22 additions & 2 deletions docs/agents/stage-1-search.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Flight availability search, schedule lookup, connection validation, fare shoppin
Queries distribution adapters in parallel, normalizes, deduplicates, filters, and sorts flight availability offers.

**Input (`AvailabilitySearchInput`):**

- `origin` -- origin airport/city IATA code
- `destination` -- destination airport/city IATA code
- `departure_date` -- ISO 8601 date
Expand All @@ -30,6 +31,7 @@ Queries distribution adapters in parallel, normalizes, deduplicates, filters, an
- `sources?` -- specific adapter names to query

**Output (`AvailabilitySearchOutput`):**

- `offers` -- deduplicated, filtered, sorted `SearchOffer[]`
- `total_raw_offers` -- count before deduplication
- `source_status` -- per-adapter query status (success, count, error, response time)
Expand All @@ -48,6 +50,7 @@ Queries distribution adapters in parallel, normalizes, deduplicates, filters, an
Flight schedule lookup with SSIM operating day parsing, codeshare detection, and connection discovery.

**Input (`ScheduleLookupInput`):**

- `origin` -- airport IATA code
- `destination` -- airport IATA code
- `date` -- ISO 8601 date
Expand All @@ -57,6 +60,7 @@ Flight schedule lookup with SSIM operating day parsing, codeshare detection, and
- `include_connections?` -- discover connecting options (default: false)

**Output (`ScheduleLookupOutput`):**

- `flights` -- `ScheduledFlight[]` (carrier, flight number, times, duration, schedule, codeshare info)
- `connections` -- `ConnectionOption[]` (two-leg connections with timing)
- `operates_on_date` -- whether any flights operate on the requested date
Expand All @@ -69,17 +73,21 @@ Flight schedule lookup with SSIM operating day parsing, codeshare detection, and
**Class:** `ConnectionBuilder`
**Status:** Implemented

Validates connections against MCT (Minimum Connection Time) rules, scores connection quality, and checks interline agreements.
Validates connections against MCT (Minimum Connecting Time) rules, scores connection quality, and checks interline agreements.

MCT authority: **IATA SSIM Chapter 8** + **PSC Resolution 765** (`docs/knowledge-base/mct.md`). Curated rows live under `data/reference/mct/`. Resolution hierarchy: carrier override → airport+terminal → airport → **fail-closed** (no invented global/airport-constant table).

**Input (`ConnectionBuilderInput`):**

- `arriving_segment` -- `FlightSegment` (from `@otaip/core`)
- `departing_segment` -- `FlightSegment`
- `connection_airport` -- IATA 3-letter code
- `has_checked_bags?` -- affects MCT
- `is_interline?` -- different carriers

**Output (`ConnectionBuilderOutput`):**
- `validation` -- MCT check result (valid, available/required minutes, buffer, applied rule)

- `validation` -- MCT check result (valid, available/required minutes or null when unavailable, buffer, applied rule)
- `quality` -- connection quality score 0-1 with factor breakdown
- `interline` -- interline agreement check (if different carriers)
- `warnings` -- connection warnings
Expand All @@ -95,12 +103,14 @@ Validates connections against MCT (Minimum Connection Time) rules, scores connec
Multi-source fare comparison with fare basis decoding, class mapping, branded fare family grouping, and passenger type pricing.

**Input (`FareShoppingInput`):**

- `origin`, `destination`, `departure_date`, `passengers` -- same as availability search
- `cabin_class?`, `currency?`, `sources?` -- filters
- `decode_fare_basis?` -- decode fare basis codes (default: true)
- `group_by_fare_family?` -- group by basic/standard/flex/premium (default: true)

**Output (`FareShoppingOutput`):**

- `fares` -- `FareOffer[]` sorted by price, each with decoded fare basis, class info, fare family, passenger pricing
- `fare_families` -- grouped by family with cheapest/most expensive
- `total_fares` -- count
Expand All @@ -119,12 +129,14 @@ Multi-source fare comparison with fare basis decoding, class mapping, branded fa
Searches for available ancillaries (baggage, seats, meals, lounge, Wi-Fi, priority) via an injectable adapter.

**Input (`AncillaryShoppingInput`):**

- `segments` -- flight segments (origin, destination, flight number, date, carrier)
- `passengers` -- passenger references with type (ADT/CHD/INF)
- `pnrRef?` -- PNR reference
- `requestedCategories?` -- filter by category (BAGGAGE, SEAT, MEAL, etc.)

**Output (`AncillaryShoppingOutput`):**

- `ancillaries` -- `AncillaryOffer[]` with RFIC/RFISC codes, pricing, availability
- `notSupportedByAdapter` -- true if no adapter configured
- `currency` -- pricing currency
Expand All @@ -140,12 +152,14 @@ Searches for available ancillaries (baggage, seats, meals, lounge, Wi-Fi, priori
Aggregates search results from multiple adapters with deduplication, price comparison, and ranking.

**Input (`MultiSourceInput`):**

- `results` -- `AdapterSearchResult[]` (adapter name, flights, errors, response time)
- `deduplicationStrategy` -- `'keep_cheapest' | 'keep_all' | 'keep_first'`
- `rankBy` -- `'price' | 'duration' | 'stops'`
- `maxResults?` -- limit output count

**Output (`MultiSourceOutput`):**

- `flights` -- `NormalizedFlight[]` with sources, lowest price, all prices across adapters
- `totalRaw` -- raw count before dedup
- `totalAfterDedup` -- final count
Expand All @@ -164,11 +178,13 @@ Car rental search (and, pending a deferred car-only migration, hotel) via plugga
**Routing ownership:** hotel search intent is owned by Hotel Search Aggregator (20.1) for all hotel queries -- standalone or within a trip. 1.7 owns car rental; it may compose with 20.1 for a combined hotel+car trip but does not own hotel intent. Route hotel queries to 20.1.

**Input (`HotelCarSearchInput`):**

- `operation` -- `'searchHotels' | 'searchCars'`
- `hotel?` -- hotel search params (destination, dates, rooms, adults, star rating, max rate)
- `car?` -- car search params (pickup/dropoff location and times, category, driver age)

**Output (`HotelCarSearchOutput`):**

- `hotelResults?` -- hotel offers with rate, room type, cancellation policy
- `carResults?` -- car offers with category, supplier, daily/total rate, features

Expand All @@ -183,10 +199,12 @@ Car rental search (and, pending a deferred car-only migration, hotel) via plugga
Natural language travel query understanding with injectable LLM provider. Parses user queries into structured search parameters.

**Input (`TravelAdvisorInput`):**

- `query` -- natural language travel query
- `travelerContext?` -- preferences (cabin, budget, preferred airlines, passenger counts)

**Output (`TravelAdvisorOutput`):**

- `searchParameters` -- extracted origin, destination, dates, trip type, cabin, passengers, flexible dates
- `summary` -- natural language summary of interpreted query
- `intent` -- `'flight_search' | 'hotel_search' | 'destination_recommendation' | 'price_check' | 'trip_planning' | 'unknown'`
Expand All @@ -205,10 +223,12 @@ Natural language travel query understanding with injectable LLM provider. Parses
Deterministic offer evaluation engine. Scores and ranks flight offers based on traveler profile, constraints, and configurable scoring weights.

**Input (`OfferEvaluatorRequest`):**

- `offers` -- `EvaluatorOffer[]` with price, itinerary (segments, duration, connections)
- `constraints?` -- latest arrival, prefer direct, max connections, price ceiling, preferred/blacklisted carriers
- `profile?` -- `'BUSINESS_TIME_CRITICAL' | 'BUSINESS_PRICE_CONSTRAINED' | 'LEISURE' | 'CORPORATE_POLICY' | 'CUSTOM'`
- `weights?` -- custom scoring weights (time_buffer, price, connection_quality, journey_duration)

**Output (`OfferEvaluatorResponse`):**

- Scored and ranked offers with structured explanation for LLM translation
53 changes: 53 additions & 0 deletions docs/knowledge-base/mct.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Minimum Connecting Time (MCT) — Domain Knowledge

Authoritative sources for Connection Builder (Agent 1.3):

- **IATA SSIM Chapter 8** — Presentation, Application and Transfer of Minimum Connecting Time (MCT) data
- **IATA PSC Resolution 765** — administration of MCTs; must be observed by ticketing and reservations outlets and automated reservations systems
- **IATA Minimum Connecting Time User Guide v1.1** — carrier filing / exception process and Record Type 2 mapping
https://www.iata.org/contentassets/638f0938b3dd451b872a1d8357755421/minimum-connecting-time-user-guide_version-1.1.pdf

Do **not** invent MCT minutes from “industry folklore,” airport-constant tables, great-circle/haversine distance, or a fake global default table. Real MCT is **carrier-filed** (via data aggregators such as OAG/Cirium), optionally with airport/terminal specificity, and distributed under SSIM Ch.8.

## Definition (passenger)

Shortest time interval required to transfer a passenger and luggage from one flight to a connecting flight at a specific location or metropolitan area (SSIM Ch.8 / PSC Res 765 context in the User Guide).

## Connection status codes (SSIM)

| Code | Meaning |
| ---- | ----------------------------- |
| `DD` | Domestic → Domestic |
| `DI` | Domestic → International |
| `ID` | International → Domestic |
| `II` | International → International |

## Resolution hierarchy (most specific wins)

Application order for this platform (aligned with the issue #141 sketch and SSIM “most specific filing wins” practice). Template field order in the carrier submission form is **not** the same as hierarchy priority (User Guide §III).

1. **Carrier override** — arriving carrier + departing carrier (+ optional flight ranges, equipment, codeshare indicators) at the connection airport, for a connection status (`DD`/`DI`/`ID`/`II`), optionally scoped to terminals.
2. **Airport + terminal** — station MCT when a terminal change (or explicit arrival/departure terminal pair) is known.
3. **Airport** — station-level MCT for the connection status when no carrier-pair row matches.
4. **Fail-closed** — if no curated row matches, **do not invent** an IATA global constant. Treat MCT as unavailable and reject the connection for shopping/validation.

Carrier overrides are **required** for trustworthy online builds at hubs. Airport-level rows are only added when taken from a real SSIM/aggregator extract or another cited public source — never as guessed “hub constants.”

## Online vs interline

- **Online** — same marketing/operating carrier context (same carrier pair in the override, typically `arriving_carrier === departing_carrier`).
- **Interline** — different carriers. SSIM filings often need **concurrence** of the receiving carrier for exceptions (User Guide §II). Alliance membership alone does **not** prove an interline MCT exists.

Starter dataset rows are online-only unless an interline row is explicitly checked in with a source citation.

## Starter dataset location

`data/reference/mct/` — curated JSON only. Incomplete by design. Prefer a few validated hub/carrier rows over a fake global table.

## Open DOMAIN_QUESTIONs

1. **DQ-MCT-1 (online vs interline MCT application):** For a given carrier pair at a station, when both online and interline filings exist (or only airport-level filings), which exact SSIM match order and concurrence rules does OTAIP use in production shopping? Unpublished carrier exceptions must not be invented.
2. **DQ-MCT-2 (DI vs ID / mixed):** How should Agent 1.3 map “mixed” domestic↔international legs to `DI` vs `ID` when country-of-airport data is incomplete?
3. **DQ-MCT-3 (codeshare):** When marketing carriers differ but the operating carrier is the same, do we apply operating-carrier MCT (User Guide examples on operating carrier / codeshare indicator) by default?
4. **DQ-MCT-4 (ingestion):** How will full SSIM Ch.8 / aggregator MCT feeds be ingested into `data/reference/mct/` (OAG vs Cirium, refresh cadence, suppression records)?
5. **DQ-MCT-5 (bags / special passenger):** `has_checked_bags` and other passenger conditions — which optional SSIM MCT elements apply, and from which filing?
Loading
Loading