Skip to content

[finding] search-companion.ts docblock calls the ADR-0061 $search expansion "a $contains over source columns" — source columns compile to $icontains #13984

Description

@claude

Filed by the os-dev seat working #13744, as an out-of-scope finding. That card's dispatch scoped the fix to packages/objectql/src/engine.ts and asked explicitly that a third file carrying the same false sentence be filed as its own finding rather than folded into that PR. This is that third file.

Measured, at origin/main (merge base eb649cb8bc)

packages/objectql/src/search-companion.ts:6 — the module docblock opens:

 * `$search` (ADR-0061 Tier 1) is a `$contains` over source columns, so typing
 * the full pinyin (`zhangwei`) or initials (`zw`) of a CJK name ("张伟") can
 * never hit — the stored value is the CJK original.

The source-column clauses of the ADR-0061 expansion compile to $icontains, not $contains. The implementation is packages/objectql/src/search-filter.ts:109 / :111 (fieldClausesForTerm returns { [field]: { $icontains: term } }), and the adjudication is recorded in that file's own header at search-filter.ts:23:

 * [#7641] The case-insensitive operator is `$icontains`, NOT `$contains`.

Two tests pin the live behaviour, both green on main this hour:

Severity: low, and the argument the sentence carries still holds

Comment-only, zero behaviour — same class and same severity as #13744. Note the reasoning in that sentence survives the correction: typing zhangwei cannot hit a stored 张伟 under either operator, because case folding does not transliterate. So this is a false spelling inside an argument that remains correct, which is precisely why it reads as fine and has survived.

Worth a card for the reason #13744 gives: it is one hop from the file an agent doing query-engine work reads first, and an agent trusting it re-introduces the spelling #7641 paid to retire.

Do NOT batch-replace this file — two $contains in it are CORRECT

The same file carries two further $contains mentions, both describing the hidden __search companion clause, where $contains is the right spelling and is deliberate:

  • search-companion.ts:237 — "ORed { __search: { $contains: term } } into every $search against it"
  • search-companion.ts:286 — "which emits { __search: { $contains: term } }"

search-filter.ts:137-143 states why, and says so in the imperative: the companion column is a normalized blob already lowercase on both sides, so a case-SENSITIVE operator over two folded values is exact — "Do not 'align' the two." A naive whole-file find-and-replace here would turn two correct sentences false. Only :6 is wrong.

Adjacent, in the same docblock family (same file, separate from the above)

search-companion.ts:286 names the reader as buildSearchFilter; the exported function in search-filter.ts is expandSearchToFilter. buildSearchFilter is not an export of that module. Stale identifier, comment-only, no behaviour — folding it into the same fix would be natural, but it is a distinct claim and is recorded here rather than assumed.

Gate exposure

scripts/adr-anchors/packages__objectql__src__search-companion.ts.json anchors this file to ADR-0015 / ADR-0045 / ADR-0061 and check:adr-anchors requires those ids stay referenced in it. A spelling correction does not touch an ADR id, so the anchor is unaffected — but the anchor is worth knowing about before editing this file.

Observation class: finding label, no assignee, no lane label — routing belongs to central triage.

Refs: #13744 (the engine.ts card this was found from) - the $icontains adjudication trail cited in search-filter.ts (#7641 / #6520 / #6682).

Generated by Claude Code


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions