Repository navigation
objectui: FilterConditionField cannot author spec’s $icontains — the case-insensitive contains is unreachable from the filter UI #6337
Description
Part of objectstack-ai/objectui#3567 (transferred to the main backlog by the triage seat — feature-level work lives in objectstack whatever repo the code lands in; see the multi-repo coordination rule "One main backlog").
Blocked-by: #5702
What is missing
packages/spec's FieldOperatorsSchema gained $icontains (case-insensitive contains, spec describe: "folds ASCII case") between 17.0.0-rc.2 and rc.5. objectui's FilterConditionField has no builder operator that can author it, so the capability is unreachable from the filter UI. The existing bidirectional parity test in packages/fields/src/widgets/__tests__/FilterConditionField.operators.test.ts ("every spec field operator is reachable from the builder", objectui#2942) went red on the rc.5 bump and was handled by objectui#3560 as an explicit, ratcheted KNOWN_UNREACHABLE entry rather than a silent exclusion.
Deliverable (lands in objectui)
- Add a case-insensitive contains operator to the
FilterConditionFieldbuilder vocabulary;condToMongoemits{ field: { $icontains: value } }. kvToConditionreads it back — without the reverse mapping a saved filter view degrades on reopen.- Ten locale packs gain the label key (the
t()call-site key gate, objectui#3547). - Remove the
$icontainsentry fromKNOWN_UNREACHABLEinFilterConditionField.operators.test.ts; the parity assertion then takes over, and objectui#3560's ratchet simultaneously validates that the removal was legitimate.
Why this is blocked, and it is not the reason the filing issue gave
$icontains. Half true, and the half that is false is the blocking half. Measured against objectstack origin/main:
$icontainsis present inpackages/speconly —filter.zod.ts,filter-operator-vocabulary.test.ts,filter-text-conformance.ts, the authorable-surface baselines and the CHANGELOG.git grep -l icontains origin/main -- packages/driversreturns nothing. No backend implements it.- The driver half is objectstack#5702 (
pm:queue+pm:blocked+domain:drivers), itself blocked by spec:$regex按 ADR-0049 退役 +$icontains入算子词表与 FILTER_LOGIC_CASES(#4706 裁决 B 案 · 契约半边,先行) #5701 (contract half: vocabulary +FILTER_LOGIC_CASES) and plugin-auth: better-auth 的contains被译成裸$regex,用户输入当正则求值 —— 且是$regex退役唯一挡路的生产者 #5710 (producer-first:plugin-auth'scontainsbranch).driver-memory/driver-mongodbimplementations sit inside the [裁决] driver-memory / driver-mongodb 投入冻结 —— 维护者 2026-08-05 口径(跨单锚点) #5499 freeze.
So the spec vocabulary accepts the token while no driver can execute it. Shipping the builder operator first would put a filter in users' hands that every backend fails — strictly worse than the capability being absent. This card returns to the queue when #5702 merges.
Open product question (default recorded, not blocking)
Should today's contains have been case-insensitive all along? If so, the better shape is to have contains emit $icontains and add an explicit containsCaseSensitive for $contains — but that changes the behaviour of stored filter views, so it needs the maintainer. Default for this card: add a new operator, leave contains semantics untouched. A dev implements the default; if the maintainer wants the flip, say so here first and this card is re-scoped (it would then move to the decision inbox).
Provenance
Measured during objectui#3560 (@objectstack/* family bump to 17.0.0-rc.5). Not a regression introduced by that bump — a capability gap it exposed. Original filing: objectstack-ai/objectui#3567.
Generated by Claude Code
Activity
os-project-manager commentedon Aug 9, 2026
Unlock sweep (maintainer-requested, 2026-08-09): UNBLOCKED —
pm:blockedremoved. Blocker #5702 closed completed 2026-08-08T06:43Z; per #6947's fresh measurement two drivers now execute$icontains(the rest refuse loudly), so the "builder would author a filter every backend fails" hazard is gone. The card's recorded default stands: add a new operator, leavecontainssemantics untouched; the case-insensitivity flip stays a maintainer question and is NOT taken by the implementing dev.Generated by Claude Code
os-zhuang commentedon Aug 10, 2026
Migrated to objectstack-ai/objectui#4023 under #7167 (file-at-destination ruling, maintainer 2026-08-10). Native GitHub issue transfer is not available to this session's credential, so the card was recreated at the destination; this thread stays as the authoritative history and is linked from the new card. Closing as not planned here — moved, not rejected.
Generated by Claude Code