DEV Community

Nakabiri Knolz
Nakabiri Knolz

Posted on

CabinClaim - a cabin-rules desk search cannot run

Sanity Challenge Path One Submission

This is a submission for the Sanity Challenge, Path One: Ship an Agent That Queries Real Content

What I Built

CabinClaim is a cabin-rules desk, not a travel blog.

A guest asks one question. The desk answers what is allowed in the cabin for this carrier and this travel date from dated ruleClaim documents in Sanity. It does not search the web at ask time.

This only works because the content is structured. Official pages stay live at the same time and disagree:

  1. TSA publishes a 100Wh spare-lithium cap and a cabin-only rule.
  2. United publishes cabin centimetres and a spare-count wording the TSA power-bank page does not repeat.
  3. A 120ml sunscreen bottle is "a liquid" on every page. Only a liquid_ml field can fail it.

Keyword search finds "allowed," "100Wh," and "carry-on" in one blob. CabinClaim stores each official sentence as its own claim: operator, value, appliesTo, effectiveFrom, sourceUrl, and the exact quote. GROQ keeps claims still in force. When two current claims conflict, both quotes stay on screen with their sources.

If you delete value, operator, or effectiveFrom, the desk refuses. That is the Path One test.

Demo

Judge question — leave this as-is, then click Ask:

United UA 934, SFO to LHR. I have a 99Wh Anker power bank, a second 30Wh spare, and 120ml sunscreen in a 56 x 36 x 23 cm bag. What is allowed in the cabin, and which official pages disagree?

Expected:

Item Verdict Why search fails
99Wh power bank Allowed in cabin Search cannot apply lithium_wh lte 100
30Wh spare Allowed in cabin Same watt-hour field
Two spares Conflict — both quotes shown United count vs TSA page with no two-spare cap
120ml sunscreen Not allowed liquid_ml lte 100, not the word "liquid"
56 × 36 × 23 cm bag Not allowed United width 35cm and depth 22cm are fields

No login is required.

Code

GitHub: https://github.com/python07070/cabinclaim

The pieces that make the desk refuse a keyword answer:

  • src/sanity/schemaTypes/carrier.ts and ruleClaim.ts — one official sentence per document
  • src/lib/queries.ts — current-claims GROQ by IATA and travel date
  • src/lib/solveCabin.ts — refuse unless required fields exist
  • src/lib/mcp.tsinitial_context, then knowledge_base_read
  • scripts/seed.mjs — dated quotes with observedOn

Current-claims GROQ:


groq
*[_type == "ruleClaim"
  && (
    carrier->iata == $iata
    || carrier->iata == "ANY"
    || !defined(carrier)
  )
  && effectiveFrom <= $travelDate
  && (!defined(effectiveUntil) || effectiveUntil >= $travelDate)
]
Enter fullscreen mode Exit fullscreen mode

Top comments (0)