MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-329

6.1.2 Epic-5 predicates — custom-field (per-type), label, and component conditions via the documented join contracts

Done
Description

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 / componentslbl/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).

Acceptance criteria

  • Every CF type filters correctly through its indexed join (EXPLAIN spot-checks on the large seed: index scans); select matching includes archived-option values; is empty semantics verified per type; multi-CF + label + component conditions compose under both combinators without join collisions.
  • Label/component conditions match the 5.4 join data incl. negation + empty; the project's dynamic field entries appear/disappear with definitions (registry totality preserved — the enumeration test covers the dynamic entries).
  • Stale referents degrade to unknown-value (match-nothing + notice), asserted for field/option/label/component deletion each; injection fuzz extended over the dynamic ids.
  • pnpm test:coverage ≥90% on the extension.

Context refs

  • The 5.3.1 predicate contract (typed-EAV columns + [fieldId, value*] indexes + the JOIN sketch) and the 5.4.1 label/component join contract — written for this subtask
  • 6.1.1 registry/compiler (the extension points)
  • customFieldsService reads (5.3.2/5.3.3) for definitions/options; labelsService/componentsService reads (5.4.2/5.4.3) for values
  • The stale-referent rule in the Story 6.1 description (the 6.2 dependency)