The filter predicate
# grade this stage (from your course directory)
npx theinference test --stage filter-predicate --watchBefore filtered search, the predicate it gates on. Implement matches(payload, filter) for a small Qdrant-like filter language: must (AND), should (OR), must_not (NONE), with leaf conditions match (equality), range (gte/lte), and is (boolean).
type Leaf =
| { match: { key; value } }
| { range: { key; gte?; lte? } }
| { is: { key; value: boolean } }
interface Filter { must?: Leaf[]; should?: Leaf[]; must_not?: Leaf[] }
What to build
Implement runMatches
Implement matches(payload, filter) in src/payload.ts. A payload satisfies the filter when all must leaves pass, none of the must_not leaves pass, and (if should is non-empty) at least one should leaf passes. Return a boolean; the adapter maps it to [1]/[0].
export function runMatches(payload: Payload, filter: Filter): number[] {
// return [ matches(payload, filter) ? 1 : 0 ]
}
This mirrors Qdrant's Filter object (must / should / must_not, match / range). The search layer calls it purely as an admission gate, so no side effects — just a clean boolean.
Adapter mode: [1]/[0] compared exactly to the reference for a fixed payload + compound filter (a must + range + must_not).