Skip to content

docs(spec): a declared never-string-capable search column is admitted but contributes no clause - #29584

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-6re9b8
Nov 2, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-6re9b8

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Warren · project thread

Fixes #29546

Clause-②: no
Metadata-protocol: none

Dispatched by domain:spec#3 · os-warren · session_01JQwxbahe4v7GBD94QeSnir; dev = card thread session_01JQwxbWkmiSMGh5SFWcG7XY.

维护者速读

  • 改了什么:只改注释。resolveSearchFieldResolution 的 declared 分支说明和对应测试注释,改为「从不存字符串的列(如 json)仍可声明、进入搜索集,但搜索展开不给它出子句」。
  • 为什么改:fix(objectql): $search emits no text clause over a column that can never hold text #29502 之后 $search 展开跳过这类列,旧注释仍说 json 列「a scan that CAN match」,作者和 AI 会以为把 json 字段放进 searchableFields 能搜到东西。
  • 风险与回滚:零行为改动,无 schema、无接受值变化;回滚即 revert 本 PR。
  • 先看:packages/spec/src/data/search-fields.ts(declared 分支两条列表项)、packages/spec/src/data/search-fields.test.ts(CONTROL 用例注释)、.changeset/29546-declared-search-column-no-clause-comment.md。
  • 两分钟验证:git diff origin/main -- packages/spec/src 只见注释行变化;pnpm --filter @objectstack/spec exec vitest run src/data/search-fields.test.ts 应 50/50 通过。
  • 需要你做的:无,席位落地。

What changes

  • packages/spec/src/data/search-fields.ts, the declared-branch docblock on resolveSearchFieldResolution: a declared lookup or json column is ADMITTED to the set, and what it contributes is the expansion's call (expandSearchToFilter, @objectstack/objectql). A single-valued lookup becomes an $icontains over the stored foreign key, a scan that can match. A column whose declared type can never hold a string (the text-operator door's door-refusal verdict, textOperatorDoorVerdict) contributes NO clause, and a set made only of such columns answers no rows, never an error. Only "there is no column at all" is refused, as before. The SEARCH_VIRTUAL_TYPES docblock in the same file said the same stale json sentence; it now says a declared json or lookup column is admitted because a stored column exists. The generic scan word on Filter 2 and that docblock is now "substring scan".
  • packages/spec/src/data/search-fields.test.ts, the CONTROL case comment: the same reading, single-valued lookup. The assertion is unchanged.
  • .changeset/29546-declared-search-column-no-clause-comment.md: @objectstack/spec patch. The docblock sits on an exported function and ships in dist/data/index.d.ts (measured below), so the published text changes.

Why

The declared-branch text is the written contract authors and AI read to decide what to put in searchableFields. Since #29502 (#29394) the expansion skips never-string-capable columns, so "a scan that CAN match" for json was false. lookup is in REFERENCE_VALUE_TYPES (verdict passes), so it still matches and keeps that wording.

Tests

  • pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/data/search-fields.test.ts at 691a1581b: Test Files 1 passed (1), Tests 50 passed (50).
  • pnpm --filter @objectstack/spec typecheck under the verify lock: VERDICT command-exit 0.
  • No ablation: no tested behaviour moved.

Acceptance notes

  • Premise measured on origin/main ff827bcf: packages/objectql/src/search-filter.ts fieldClausesForTerm returns no clause when neverHoldsText(meta), which is textOperatorDoorVerdict(...) === 'door-refusal'; json sits in STRUCTURED_JSON_TYPES (verdict door-refusal). A single-valued lookup falls to the default $icontains clause, so the old text also said $contains where the expansion emits $icontains; the new text says $icontains.
  • Changeset decision: the card said "no changeset unless the gate asks". The os-dev standard (published = what files[] ships) wins on conflict: after pnpm --filter @objectstack/spec build, grep -c "contributes NO clause" packages/spec/dist/data/index.d.ts = 1 and the old phrase = 0 (positive control: SCANNABILITY hits the same file on the base build). So a patch changeset rides.
  • Not changed here, same stale sentence: packages/lint/src/validate-searchable-fields.ts docblock (about L95 to L100) still says a declared json column is "a scan that CAN match". Outside this card's file surface; named in the report for the seat.
  • Contract review 6587379147 should-fixes applied in 691a1581: no formula in the no-clause bullet (Filter 2 drops every formula before admission), same in the changeset.
  • packages/lint/CHANGELOG.md and packages/metadata-protocol/CHANGELOG.md carry the old phrase in released entries; release-owned, untouched.

Verification

Gate union at head 691a1581b:

dispatch-gates --commands / --ran
  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 79 derived families, run from a runner writing one exit line each.
  • 78 exited 0, the teardown-shape self-test included (its pinned control commit was already fetched).
  • pnpm check:dual-build-cjs-loads exited 3, PREREQUISITE NOT MET (needs every package built). NOT MEASURED locally, left to CI.
  • node scripts/pm/dispatch-gates.mjs --ran FILE --repo objectstack-ai/objectstack: exit 0, "79 derived famil(ies) accounted for, 78 run, 1 NOT-MEASURED".
  • --ran printed STALE TREE: base ff827bcf is 14 commits behind origin/main; the 8 changed inputs are scripts/pm tooling, none reads this diff.
  • Prerequisite builds under the lock: turbo run build for objectql, lint, formula, client, client-react (38 tasks), then spec.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic.
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; pnpm lint passes. (No formatter ran. Repo-wide pnpm lint is CI's run, not run locally.)
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset.
  • 6. packages/spec touched: its generated artifacts are regenerated and committed.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English.
  • The Before Submitting list in CONTRIBUTING.md is done.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JQwxbWkmiSMGh5SFWcG7XY


Generated by Claude Code

… but contributes no clause

The declared-branch comment in search-fields.ts and its test comment still
called a declared json column "a scan that CAN match". Since the search
expansion skips a column whose declared type can never hold a string (the
text-operator door's door-refusal verdict), such a column is admitted to the
set but contributes no clause, and a set made only of such columns answers no
rows. Comment-only; no behaviour change. The docblock ships in the spec
package's .d.ts, so a patch changeset rides.

Claude-Session: https://claude.ai/code/session_01JQwxbWkmiSMGh5SFWcG7XY
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation protocol:data tests tooling labels Nov 2, 2026
@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 1 changed file(s) yielded no anchor (packages/spec/src/data/search-fields.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/spec/src/data/search-fields.ts) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 168 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json b16ee8ba069d00bc00d01295869c1036fc9ea2e2 → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#3 · os-warren · session_01JQwxbahe4v7GBD94QeSnir

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 76fde58e651c2fd8897fba95e8bb38c24aee39f5
Local-runs: none
Scope: packages/spec/src/data/search-fields.ts + packages/spec/src/data/search-fields.test.ts, packages/objectql/src/search-filter.ts (fieldClausesForTerm, neverHoldsText, expandSearchToFilter), packages/spec/src/data/filter-text-operator-declared-type.ts (textOperatorDoorVerdict, TEXT_OPERATOR_DOOR_REFUSED_TYPES), packages/spec/src/data/field-value.zod.ts (the class sets), packages/objectql/src/search-companion.ts (resolveSearchCompanionSources), all read on main e832ddb1

Inputs read: card #29546 body + its 3 comments (triage, claim, os-dev-report); PR #29584 body, file list (3 files), net diff against the merge-base ff827bcf; check-runs on the head.

① Derived judgments

  • No accept set moves — right. The diff against the merge-base touches two comment blocks and adds one changeset. resolveSearchFieldResolution's body, SEARCH_VIRTUAL_TYPES, SEARCH_AUTO_EXCLUDED_TYPES and every test assertion are byte-identical to main. The CONTROL case still asserts { allowed: ['project_id', 'payload'], source: 'declared' }.
  • "A declared json column is admitted but contributes no clause" — right against the live code. fieldClausesForTerm on main returns [] when neverHoldsText(meta), which is textOperatorDoorVerdict(...) === 'door-refusal'; json is in STRUCTURED_JSON_TYPES, which TEXT_OPERATOR_DOOR_REFUSED_TYPES spreads. Admission is unmoved: the declared branch filters only by existence and isVirtualSearchField (formula).
  • "A single-valued lookup becomes an $icontains over the stored foreign key" — right, and the $contains → $icontains correction is right. lookup sits in REFERENCE_VALUE_TYPES (door verdict passes), is not in SEARCHABLE_ENUM_TYPES (select only), and is not multi-valued unless multiple: true, so it falls to the function's final { [field]: { $icontains: term } }. The old text's $contains has been wrong since $search is case-sensitive on textual fields, contrary to three declarations that say case-insensitive #7641 (the module header on main says so in as many words). The "single-valued" qualifier is load-bearing: a lookup declared multiple: true takes the [finding] $startsWith / $icontains on a multi-valued lookup answer 500 on PostgreSQL and a wrong count on SQLite: the text operators other than $contains reach a JSON column unrefused and unruled #21009 membership branch ($contains) instead, and the docblock keeps it.
  • "A set made only of such columns answers no rows: never an error, never every row" — right. expandSearchToFilter only answers null (the metadata-protocol / objectql: a search term on an object with no searchable field is dropped silently, so the read answers every row (an empty auto-default search set is not refused) #24284 INVALID_FIELD refusal upstream) on an EMPTY resolved set; a non-empty never-text set yields { $or: [] } per term, FALSE under FILTER_LOGIC_CASES. The __search companion cannot rescue such a set: resolveSearchCompanionSources only ever names the display field when its type is in TITLE_ELIGIBLE_TYPES (text-family), and companionWithinSearchFields requires that source to be inside the set, so a set of never-text columns never carries the companion arm.
  • The door's class list in the docblock (numeric, boolean, calendar-date, instant, clock-time, structured-JSON, plus a formula by readable returnType) — matches TEXT_OPERATOR_DOOR_TYPE_CLASSES and textOperatorDoorVerdict's formula branch exactly. The relative path ./filter-text-operator-declared-type is right (same directory). expandSearchToFilter exists under that name in @objectstack/objectql (search-filter.ts, imported by engine.ts).
  • Public surface: the docblock sits on an exported function re-exported through packages/spec/src/data/index.ts (export * from './search-fields'), and @objectstack/spec's build emits dist/data/index.d.ts via tsup BUILD_DTS, which preserves TSDoc. The published .d.ts text therefore changes; nothing a type-checker or runtime consumer reads changes.

② Semver level

@objectstack/spec patch, Clause-②: no, Metadata-protocol: none on both the PR body and the changeset — right. AGENTS.md § Post-Task Checklist 3: a changeset for anything that publishes; skip-changeset is only for a diff that publishes nothing from any released package. The docblock ships in the package's .d.ts, so a patch is the correct level and the dev's deviation from the card's "no changeset unless the gate asks" is the standard winning over the order, as the report says. Check Changeset on the head: success. The triage's "not published text: no .describe() moves" was about the /meta/types surface, not the .d.ts; both are true at once. The changeset body states the four points the docblock makes and nothing more.

③ Boundary flags

  • open_questions: [] — nothing to answer.
  • Dev flag, changeset added against the order: answered above (right).
  • Dev flag, Human Minimum 3 unchecked (repo-wide pnpm lint left to CI): Lint · ESLint, Lint · docs & code guards, Lint · scoped · tooling self-tests report success on the head; the remaining lint and type-check runs were still in_progress at review time with no failure recorded. A comment-only diff on two files carries no lint risk the scoped runs would not already have surfaced.
  • Dev out-of-scope finding, packages/lint/src/validate-searchable-fields.ts docblock (~L95-L100 on main) still says a declared json column is "a $contains over the stored JSON text ... a scan that CAN match": confirmed on main. Outside this card's file surface; the seat should carry it as a follow-up card, since the linter's docblock is the second place an author reads this rule.
  • check:dual-build-cjs-loads NOT MEASURED locally: left to CI; not a derived family a comment-only diff can move.

④ Design judgment

packages/spec/src/data/search-fields.ts — judged against the card's Wanted and the code it cites. The declared-branch text now says exactly what the card asked: never-string-capable types are admitted, contribute no clause, a set made only of them answers no rows, and only "no column at all" is refused. Every claim checked above against search-filter.ts and textOperatorDoorVerdict on main holds. The test comment makes the same reading over a fixture (project_id: lookup, payload: json) where it is literally true.

Tried to break it:

  • Could a reader take "a formula whose readable returnType names one ... contributes NO clause" as "a formula is admitted to the set"? The sentence sits inside a paragraph about what an ADMITTED column contributes, but Filter 2 two paragraphs up says a formula entry is dropped before admission (SEARCH_VIRTUAL_TYPES is exactly formula). The formula mention is copied from the objectql module header, where it is the door's rule at the expansion seam; in THIS function's docblock it describes a type that never reaches the expansion through the declared branch. Not false (a dropped formula trivially contributes no clause), and the objectql header is the one that matters for the auto-default path, so a should-fix, not a must-fix.
  • Could a multi-valued lookup make the test comment's unqualified "lookup becomes an $icontains" wrong? Only for multiple: true, which the fixture does not declare; the docblock carries the qualifier. Nit, folded into should-fix 2.

Must-fix: none.

Should-fix (none blocks; fold into a follow-up or a later touch of the same docblock):

  1. search-fields.ts docblock, the [#29394] bullet: mark the formula case as unreachable on this branch, e.g. "plus a formula whose readable returnType names one — though Filter 2 drops a formula entry before it gets here", or drop the formula parenthetical and leave the door's class list to filter-text-operator-declared-type. As written, the admitted-column paragraph names a type the same docblock says is never admitted.
  2. The same docblock still says $contains where it means "a substring scan" in two unchanged lines (Filter 2: "no stored column for $contains to scan"; SEARCH_VIRTUAL_TYPES' note at ~L92: "a $contains scan has nothing to look at"), while the corrected bullet now names $icontains. Harmless as a generic word, but the hunk made the docblock mixed. Same fix pass as 1.
  3. search-fields.test.ts CONTROL comment: "lookup becomes an $icontains" could carry "single-valued" like the docblock does, since a multiple: true lookup takes the membership branch.

Check-runs on the head at review time: 15 success, 0 failure, 36 in_progress (Test Core, Test UI, Type Check · workspace, the remaining lint families), 9 skipped. No gate family has refused the head; the running ones cannot be moved by a two-comment diff and a changeset, and the record stands on the diff and the cited code.

Implemented-by: claude/project-thread-6re9b8
Reviewed-by: session_01JQwxbahe4v7GBD94QeSnir (seat subagent)

VERDICT: PASS


Generated by Claude Code

…omments

- Drop the formula mention from the no-clause bullet: Filter 2 drops every
  formula before admission, so no formula reaches the expansion from the
  declared branch (same fix in the changeset bullet).
- Say "substring scan" for the generic scan on the docblocks, and correct the
  SEARCH_VIRTUAL_TYPES docblock, which still said a declared json column is a
  scan that can match.
- Test CONTROL comment: "single-valued" lookup, as in the docblock.

Comment-only; no behaviour change.

Claude-Session: https://claude.ai/code/session_01JQwxbWkmiSMGh5SFWcG7XY
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#3 · os-warren · session_01JQwxbahe4v7GBD94QeSnir

Contract review — delta

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 691a1581b7591b4aa0dc40eb6aebd8cafa556630
Prior-head: 76fde58e651c2fd8897fba95e8bb38c24aee39f5 — prior record 6587379147 (PASS, must-fix none, should-fix 1-3)
Local-runs: none
Delta-scope: the compare 76fde58e...691a1581, one commit ahead, zero behind: packages/spec/src/data/search-fields.ts (+9/-10, comments only), packages/spec/src/data/search-fields.test.ts (+3/-2, one comment), .changeset/29546-declared-search-column-no-clause-comment.md (+1/-1); judged against packages/objectql/src/search-filter.ts and packages/spec/src/data/filter-text-operator-declared-type.ts on main e832ddb1, as read for the prior record.

Closure of the prior should-fixes

  1. Formula parenthetical in the admitted-column paragraph — closed. The [#29394] bullet now lists the door's refused classes as "numeric, boolean, calendar-date, instant, clock-time and structured-JSON types such as json" and no longer names formula there. That is exactly the six classes TEXT_OPERATOR_DOOR_REFUSED_TYPES spreads; the formula-by-returnType rule stays where it is reachable, in the objectql module header, and a formula entry is still described as dropped by Filter 2 in the same docblock.
  2. Mixed $contains wording in unchanged lines — closed. Filter 2 now reads "no stored column for a substring scan to read"; the SEARCH_VIRTUAL_TYPES note reads "a substring scan has nothing to look at". The delta also rewrote the third stale sentence in that note, which the prior record did not list: "the engine executes it (a $contains over the stored JSON text, over the stored foreign key), which is a choice that can match" became "it is admitted, because a stored column exists (what each then contributes to a search is set out on {@link resolveSearchFieldResolution}). A formula entry is not: the drivers materialize no column for it". True against the tree: admission on the declared branch is existence plus isVirtualSearchField, the {@link} target is in the same file, and the formula sentence keeps its existing driver citations unchanged.
  3. "single-valued" in the test CONTROL comment — closed. The comment now says "a single-valued lookup becomes an $icontains over the stored foreign key", matching the docblock and fieldClausesForTerm's final branch; the fixture's project_id: { type: 'lookup' } is single-valued.

New findings

None. The delta is comment-only; no code line, test assertion, export or schema moves. Nothing in the new text contradicts fieldClausesForTerm, neverHoldsText, expandSearchToFilter or textOperatorDoorVerdict on main.

Changeset edit

The one-line change drops "or a formula whose returnType names one" from the first bullet, so the changeset now matches the docblock it describes. Level (@objectstack/spec patch), Clause-②: no and Metadata-protocol: none are unchanged and still right; the other three bullets are untouched.

Check-runs on the head

Read on 691a1581b7591b4aa0dc40eb6aebd8cafa556630: 64 check-runs, 55 success, 9 skipped, 0 failure, 0 in progress. Every family that was still running on the prior head (Test Core, Test UI, Type Check · workspace, the remaining lint families) has completed green.

Implemented-by: claude/project-thread-6re9b8
Reviewed-by: session_01JQwxbahe4v7GBD94QeSnir (seat subagent)

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#3 · os-warren · session_01JQwxbahe4v7GBD94QeSnir

维护者速读

席位核对

ACCEPT · domain:spec#3 · head 691a1581b7591b4aa0dc40eb6aebd8cafa556630 · 2026-11-02T20:45Z

  1. Shape: three files: packages/spec/src/data/search-fields.ts (comments only), packages/spec/src/data/search-fields.test.ts (one comment), .changeset/29546-declared-search-column-no-clause-comment.md (@objectstack/spec patch). Inside the claim (6586412598); no packages/objectql edit, no .describe().
  2. Premise, measured: the reviewer read fieldClausesForTerm / neverHoldsText / expandSearchToFilter in packages/objectql/src/search-filter.ts and textOperatorDoorVerdict on main: a declared never-string column is admitted and contributes no clause; a single-valued lookup falls to $icontains.
  3. Gates: dev local 79 derived / 78 exit 0 / 1 NOT MEASURED (check:dual-build-cjs-loads, left to CI). On this head 64 check-runs, 55 success, 9 skipped, none failing; mergeable_state clean.
  4. Accepted deviations: a patch changeset rides although the order said "only if a gate asks": the docblock ships in the published .d.ts, so AGENTS.md's publish rule wins over the order.
  5. Out of scope: the same stale sentence in packages/lint/src/validate-searchable-fields.ts is card lint(searchable-fields): the validate-searchable-fields docblock still calls a declared json column "a scan that CAN match"; since #29394 the expansion gives it no clause #29585. Skills-docs: n/a (Metadata-protocol: none).
  6. Landing: not governed (check-governed-merges --pr 29584: NOT governed, 69 changed lines), Clause-②: no, contract review at CONTRACT_REVIEW_TIER PASS (6587379147) plus delta PASS on this head (6588008946). Seat lands it: pr_ready + automerge_enable.

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 2, 2026 20:46
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit fdb9a07 Nov 2, 2026
69 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-6re9b8 branch November 2, 2026 21:09
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#3 · os-warren · session_01JQwxbahe4v7GBD94QeSnir

Landed · 2026-11-02T21:11Z

Reading Value
PR #29584 MERGED 2026-11-02T21:09Z via merge queue, merge commit fdb9a072 on main
Card #29546 closed completed by Fixes #29546; no other closing keyword in the body

State change: pm:dispatched removed from #29546. Delivered: the search-fields.ts docblocks and the CONTROL test comment say a declared never-string column is admitted but contributes no clause, and a single-valued lookup takes $icontains. Remaining: the packages/lint twin is card #29585.


Generated by Claude Code

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

Labels

documentation Improvements or additions to documentation protocol:data size/s tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

spec(data): search-fields.ts still calls a declared json search column "a scan that CAN match"; since #29394 the expansion skips it

1 participant