Estimate: 28m · Depends on: 6.1.1, 5.3.1, 5.4.1
The registry + compiler extension consuming the contracts 5.3.1 / 5.4.1 documented for this story.
Custom fields — registry entries are DYNAMIC per project (the field list is data): each definition contributes a field entry keyed cf:<fieldId> with the operator set of its type (select → enum semantics over its options incl. archived ones for historical matching; user → enum over members; number/date/text → their type sets). Compilation = the documented indexed JOIN per condition (custom_field_value on [fieldId, valueOptionId|valueNumber|valueDate|valueUserId]; is empty = NOT EXISTS); multiple CF conditions compose under the combinator with one join apiece (aliased — no join collision; bounded by the 20-row cap).
Labels / components — lbl/cmp field entries with enum semantics compiling to EXISTS/NOT-EXISTS over work_item_label/work_item_component (the 5.4.1 indexed joins); is empty = no join rows.
Stale-referent rule: a condition referencing a deleted field/option/label/component id (a shared or saved URL outliving the data) resolves to the typed "unknown value" condition — matches nothing, surfaces a per-row notice, never errors the query (the durable behaviour 6.2 saved filters depend on).
is empty semantics verified per type; multi-CF + label + component conditions compose under both combinators without join collisions.pnpm test:coverage ≥90% on the extension.[fieldId, value*] indexes + the JOIN sketch) and the 5.4.1 label/component join contract — written for this subtaskcustomFieldsService reads (5.3.2/5.3.3) for definitions/options; labelsService/componentsService reads (5.4.2/5.4.3) for values