You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
objectql: a $search expansion emits $icontains over a column the #15661 text-operator door calls never-string-capable (number, boolean, date, json), and the door never judges it; once #29008 honours searchable: true this can reach Postgres #29394
Filing gate: ① an out-of-scope finding (class a, carrier domain:server) named by the #29008 dev (os-dev-report 6578774069, Q3) and by the CONTRACT_REVIEW_TIER review of PR #29385 (④ should-fix 2). ⛔ Not a claim. No grade: triage sets it.
What the code does (read, not measured on Postgres)
In packages/objectql/src/engine.tsfind(), the #15661 door (assertTextOperatorTargetsAreStringCapable, ≈L1302) runs from the filter ladder on the caller's own where (≈L14464), and only then does expandSearchOnAst (≈L14478) add a $icontains clause for each resolved search field. So the expansion's clauses never meet that door and go straight to the driver. SQLite coerces and matches on the textual form. Postgres refuses a text operator over an integer, boolean or date column (SQLSTATE 42883, the #15683 shape), so the whole $search on that object fails.
The shape already exists for a declared searchableFields that names such a column (since #6674). PR #29385 adds a second, wider way in: under ruling 6573569376 (letter A, "of any type"), a field marked searchable: true with no searchableFields declared joins the auto set. An inert searchable: true on a number field in a tenant's metadata becomes live at upgrade. No shipped object has such a field. The census in the review shows only seven flagged lookups.
Wanted (the server half, without departing from the ruling)
Make the expansion skip, or cast to text, any resolved column the spec's text-operator sets (packages/spec/src/data/filter-text-operator-declared-type.ts) call never-string-capable. Do it for both branches, declared and auto. Pin it with a Postgres-dialect test, or a dialect-neutral test of the emitted AST, plus a CONTROL showing a text column still matches. If a cast is chosen, say what a search term matches on a date column.
Reader who acts: the packages/objectql search owner (domain:server).
Dedupe: searched expandSearchOnAst icontains non-string and search icontains number column postgres. Only #15683 (closed, operator over a temporal column on the filter face, not the search expansion) came up. New.
Claim: PM loop round 1 · card thread · 2026-11-02T15:19Z
Session: session_01ADHkmQxwoGb5fSnrFkpxmt (the seat); the card thread is session_01ADHkmRnyoAJD6oToQ2QZUK
Account: os-steve (the seat's linked user; the card's assignee)
Branch: claude/project-thread-sek37l (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#2
Ruling-ref: the maintainer, verbatim: 「开 server 2、3、5 号席位, 前任已经下班,接手所有开发,包括跟进之前未完成的开发落地。」 Card: none from the maintainer; triage graded p2 (6580220020). Context ruling 6573569376 (letter A on #29008, searchable of any type) stands and is not departed from.
File surface: packages/objectql/src/engine.ts (expandSearchOnAst or its caller only); tests; changeset. ⛔ No packages/spec/** (import only), no ui/**.
Container & model: M, mode:thread, model: opus (TIER_DEFAULT; --tier names no path mandate: PM's call), effort: medium
Clause-②: no (expected: no request refused; the search expansion stops matching text over never-string-capable columns)
Metadata-protocol: none (expected)
Responsibility: the code is the $search expansion in @objectstack/objectql · the platform path is a search over an object whose search set holds a number, boolean, date or json column, which emits $icontains the text-operator door never judges · reached by every list search on such an object, more so once #29008 honours searchable: true
Thread-read: none
Premise: holds (read by the #29008 dev and the #29385 contract review; not measured on Postgres); the dev measures red first
Serial constraints cleared: none — no open PR touches packages/objectql/src/engine.ts, and no open claim on a pm:dispatched card names it (read this act)
Resume-from: none — fresh from origin/main
State: pm:queue → pm:dispatched, assigned to os-steve, recorded by this claim.
{
"issue": 29394,
"status": "done",
"branch": "claude/project-thread-sek37l",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29502",
"session": "session_01ADHkmRnyoAJD6oToQ2QZUK",
"premise_still_valid": true,
"summary": "The $search expansion no longer emits a text clause over a field whose declared type gets the #15661 door's door-refusal verdict (textOperatorDoorVerdict, read from the spec, no second list): fieldClausesForTerm in objectql search-filter.ts returns no clause for it. SKIP was chosen, not cast. The resolved set is unchanged, so the #24284/#28120 refusals and the $searchFields door are unmoved; a set of only non-text fields answers NO ROWS (each term's $or has no arm, FALSE), 200, not an error and not every row. Premise measured narrower than the card read it: on live PostgreSQL 16 number/boolean/date clauses are already type-gated to no-match by driver-sql (no 42883); the real failure is json (one json field in the set fails EVERY search with 400 INVALID_FILTER on pg, sqlite and memory), plus driver-memory matching a date by ISO substring. Pinned on the declared branch only: PR #29385 (auto branch) has not merged.",
"tests": "Red first on main 7b1ae338: objectql engine-search-non-text-column.test.ts 6 failed | 1 passed (7); rest data-search-non-text-column-door.test.ts (real SqlDriver, SQLite) 4 failed | 1 passed (5), the 400 INVALID_FILTER JSON-column refusal. Green on head 5e332246: objectql test Test Files 534 passed (534) · Tests 10321 passed; objectql typecheck exit 0; rest search files 8/8 · 49 passed | 22 skipped; rest typecheck exit 0. Ablation: skip line replaced via ablation-replace.mjs --hold (anchor 1->0), objectql rebuilt, dist-preflight marker in 4 built files; objectql 6 failed | 1 passed, rest 4 failed | 1 passed, controls green; restored blob == HEAD 0c1d38a4, git diff HEAD empty, --absent preflight 14 files clean, tree clean. Live readings (one-off uncommitted script, engine + SqlDriver on local PostgreSQL 16 + SQLite + memory) in the PR body.",
"gates": "head 5e332246: dispatch-gates --commands derived 63; all run with stdin closed; --ran: 63 run, 0 NOT-MEASURED (DERIVED zero). Two first exit 3 (prerequisite): check-plugin-teardown-shape --self-test (re-run exit 0 after fetching pinned 621a4876, 48 cases) and check:dual-build-cjs-loads (re-run exit 0 after turbo build ./packages/** 78/78). eslint --no-inline-config packages/objectql packages/rest exit 0. CI check-runs: in_progress at report time.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "5 — issue_read get ×1, issue_read get_comments ×2, pull_request_read get ×2 (#29385, #29502); no write tools",
"api_writes": "2 — fleet-write relay pr_create (#29502, 10519 bytes sent = stored, no assignees, no labels); this os-dev-report comment via post-stamped.mjs. Plus git push (not REST).",
"files_changed": [".changeset/29394-search-skips-non-text-columns.md", "packages/objectql/src/search-filter.ts", "packages/objectql/src/engine.ts", "packages/objectql/src/engine-search-non-text-column.test.ts", "packages/rest/src/data-search-non-text-column-door.test.ts"],
"line_budget": "+440 / -0 over 5 files: source +47 (search-filter.ts +41, engine.ts +6 comment only), tests +381, changeset +12",
"deviations": [
"File surface: the fix lives in packages/objectql/src/search-filter.ts (fieldClausesForTerm, the callee expandSearchOnAst calls), not in engine.ts itself; engine.ts carries only a 6-line docblock pointer. Reason: that is where per-field clauses are chosen by type (multi-valued -> $contains, enum -> $in); filtering in engine.ts would either narrow the resolved set (turning an all-non-text set into the #24284 refusal, a new 400) or post-walk the emitted AST.",
"A test in packages/rest (real SqlDriver) is added beside the objectql AST pin; objectql has no driver devDeps.",
"Postgres was measured with a one-off uncommitted script against PostgreSQL 16 started in this container, not with a committed live cell (no CI leg feeds OS_TEST_POSTGRES_URL to objectql/rest/runtime)."
],
"open_questions": [
{ "question": "Clause-②: a search that answered 400 INVALID_FILTER (a json field in the declared set) now answers 200. Keep `no`, or grade `yes (widening)`?", "options": ["A keep `Clause-②: no` — the 400 was a driver refusal of a predicate the caller never wrote; no request is newly accepted by any door", "B re-grade `Clause-②: yes (widening)` — PR body and changeset lines edited by the seat"], "recommendation": "A, because no door's accept set changed; the ingress door and the engine refusals judge the same set as before" }
],
"security_findings": "none",
"out_of_scope_findings": ["carrier: #29385 · once it merges, a flagged non-text field in the auto set is skipped by the same line; worth one auto-branch pin in a follow-up or in #29385's next round · noted, not filed"]
}
The card thread's report 6582659644 (PR #29502, head 5e332246) put the skip where each search term becomes clauses: fieldClausesForTerm in packages/objectql/src/search-filter.ts. It reads the spec's textOperatorDoorVerdict and keeps no second list. engine.ts carries only a docblock pointer. A REST door pin rides in packages/rest. The seat accepts:
Unchanged in kind:packages/objectql/src/engine.ts (a 6-line docblock).
Overlap read this act: no other open PR edits search-filter.ts.
What the measurement found: on PG16, SQLite and the memory driver, number, boolean and date columns already answered no match. The real failure was a json column in searchableFields, which made every search 400 INVALID_FILTER on all three drivers. The memory driver also matched dates by ISO substring.
Clause-②: still no. The json case goes from 400 to 200 and answers no match on that field. The dev recommends no, and the contract review rules on it.
{
"issue": 29394,
"status": "done",
"round": 2,
"branch": "claude/project-thread-sek37l",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29502",
"head": "18f7a010436b8d069ccf78e579e05691fecd85ae",
"session": "session_01ADHkmRnyoAJD6oToQ2QZUK",
"premise_still_valid": true,
"summary": "Round 2 per contract review 6583544380 (PASS, test-only round). origin/main merged at c88467d4, which includes #29385 (29c70cacf). Auto-branch pins added: with no searchableFields, flagged searchable: true number / date / json fields are admitted to the set and get no text clause; the unflagged text control is scanned; naming a flagged field is accepted and answers no rows. Pinned on the engine (AST) and on the SQLite Data API door. No source change in this round. The new PR body, with the Clause-② basis line (search-fields.ts declared-branch text, #4254, ruling 6573569376 letter A), is at /mnt/project-files/server-seat2/29502-body-r2.md for the seat to apply.",
"tests": "head 18f7a010: objectql engine-search-non-text-column 8/8 (+1 auto), rest data-search-non-text-column-door 6/6 (+1 auto). Ablation re-run (skip line replaced, objectql rebuilt, dist-preflight marker present): objectql 7 failed | 1 passed (8), rest 5 failed | 1 passed (6), so the new auto pins red too; restored blob == HEAD 0c1d38a4, --absent preflight clean. objectql test Test Files 535 passed (535) · Tests 10399 passed; objectql typecheck exit 0; rest search files 9/9 (incl. data-search-field-searchable-flag-door) · 54 passed | 22 skipped; rest typecheck exit 0.",
"gates": "head 18f7a010: dispatch-gates --commands derived 63; --ran: 63 run, 0 NOT-MEASURED (a DERIVED zero, none exit 3). eslint on the two edited test files exit 0. CI check-runs: not read at report time.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "0 this round",
"api_writes": "1 this round — this os-dev-report comment via post-stamped.mjs. Plus git push (not REST). The PR body is handed to the seat as a file, not written.",
"files_changed": ["packages/objectql/src/engine-search-non-text-column.test.ts", "packages/rest/src/data-search-non-text-column-door.test.ts"],
"line_budget": "round 2: +58 / -3 over 2 test files; PR total +498 / -3 over 5 files (source unchanged at +47)",
"deviations": [],
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": ["carrier: seat 2 · the spec wording note (search-fields.ts calls a declared json column a scan that CAN match) goes to a spec card the seat files · noted, not filed"]
}
Landed:$search expansion emits no text clause over a column whose declared type can never hold a string (number, boolean, date, json and the rest, judged by spec's textOperatorDoorVerdict). A declared json search column no longer turns a search into 400 INVALID_FILTER. A set made only of such columns answers no rows. Clause-②: no, Metadata-protocol: none.
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p2 ·
domain:server·pm:queue· 2026-11-02T14:52Z⛔ Not a claim.
$searchexpansion emits$icontainsover number, boolean, date and json columns, which the text-operator door never judges. Once field.searchable: true has no reader: $search skips the field and $searchFields naming it answers 400 "is not searchable" while the served schema says searchable: true #29008 honourssearchable: true, more fields reach it. p2.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt
Claim: PM loop round 1 · card thread · 2026-11-02T15:19Z
Session:
session_01ADHkmQxwoGb5fSnrFkpxmt(the seat); the card thread issession_01ADHkmRnyoAJD6oToQ2QZUKAccount:
os-steve(the seat's linked user; the card's assignee)Branch:
claude/project-thread-sek37l(the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#2Ruling-ref: the maintainer, verbatim: 「开 server 2、3、5 号席位, 前任已经下班,接手所有开发,包括跟进之前未完成的开发落地。」 Card: none from the maintainer; triage graded p2 (6580220020). Context ruling 6573569376 (letter A on #29008, searchable of any type) stands and is not departed from.
File surface:
packages/objectql/src/engine.ts(expandSearchOnAstor its caller only); tests; changeset. ⛔ Nopackages/spec/**(import only), noui/**.Container & model:
M,mode:thread,model: opus(TIER_DEFAULT;--tiernames no path mandate: PM's call),effort: mediumClause-②: no (expected: no request refused; the search expansion stops matching text over never-string-capable columns)
Metadata-protocol: none (expected)
Responsibility: the code is the
$searchexpansion in@objectstack/objectql· the platform path is a search over an object whose search set holds a number, boolean, date or json column, which emits$icontainsthe text-operator door never judges · reached by every list search on such an object, more so once #29008 honourssearchable: trueThread-read: none
Premise: holds (read by the #29008 dev and the #29385 contract review; not measured on Postgres); the dev measures red first
Serial constraints cleared: none — no open PR touches
packages/objectql/src/engine.ts, and no open claim on apm:dispatchedcard names it (read this act)Resume-from: none — fresh from
origin/mainState:
pm:queue→pm:dispatched, assigned toos-steve, recorded by this claim.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-steve · session_01ADHkmRnyoAJD6oToQ2QZUK
os-dev-report
{ "issue": 29394, "status": "done", "branch": "claude/project-thread-sek37l", "pr": "https://github.com/objectstack-ai/objectstack/pull/29502", "session": "session_01ADHkmRnyoAJD6oToQ2QZUK", "premise_still_valid": true, "summary": "The $search expansion no longer emits a text clause over a field whose declared type gets the #15661 door's door-refusal verdict (textOperatorDoorVerdict, read from the spec, no second list): fieldClausesForTerm in objectql search-filter.ts returns no clause for it. SKIP was chosen, not cast. The resolved set is unchanged, so the #24284/#28120 refusals and the $searchFields door are unmoved; a set of only non-text fields answers NO ROWS (each term's $or has no arm, FALSE), 200, not an error and not every row. Premise measured narrower than the card read it: on live PostgreSQL 16 number/boolean/date clauses are already type-gated to no-match by driver-sql (no 42883); the real failure is json (one json field in the set fails EVERY search with 400 INVALID_FILTER on pg, sqlite and memory), plus driver-memory matching a date by ISO substring. Pinned on the declared branch only: PR #29385 (auto branch) has not merged.", "tests": "Red first on main 7b1ae338: objectql engine-search-non-text-column.test.ts 6 failed | 1 passed (7); rest data-search-non-text-column-door.test.ts (real SqlDriver, SQLite) 4 failed | 1 passed (5), the 400 INVALID_FILTER JSON-column refusal. Green on head 5e332246: objectql test Test Files 534 passed (534) · Tests 10321 passed; objectql typecheck exit 0; rest search files 8/8 · 49 passed | 22 skipped; rest typecheck exit 0. Ablation: skip line replaced via ablation-replace.mjs --hold (anchor 1->0), objectql rebuilt, dist-preflight marker in 4 built files; objectql 6 failed | 1 passed, rest 4 failed | 1 passed, controls green; restored blob == HEAD 0c1d38a4, git diff HEAD empty, --absent preflight 14 files clean, tree clean. Live readings (one-off uncommitted script, engine + SqlDriver on local PostgreSQL 16 + SQLite + memory) in the PR body.", "gates": "head 5e332246: dispatch-gates --commands derived 63; all run with stdin closed; --ran: 63 run, 0 NOT-MEASURED (DERIVED zero). Two first exit 3 (prerequisite): check-plugin-teardown-shape --self-test (re-run exit 0 after fetching pinned 621a4876, 48 cases) and check:dual-build-cjs-loads (re-run exit 0 after turbo build ./packages/** 78/78). eslint --no-inline-config packages/objectql packages/rest exit 0. CI check-runs: in_progress at report time.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "5 — issue_read get ×1, issue_read get_comments ×2, pull_request_read get ×2 (#29385, #29502); no write tools", "api_writes": "2 — fleet-write relay pr_create (#29502, 10519 bytes sent = stored, no assignees, no labels); this os-dev-report comment via post-stamped.mjs. Plus git push (not REST).", "files_changed": [".changeset/29394-search-skips-non-text-columns.md", "packages/objectql/src/search-filter.ts", "packages/objectql/src/engine.ts", "packages/objectql/src/engine-search-non-text-column.test.ts", "packages/rest/src/data-search-non-text-column-door.test.ts"], "line_budget": "+440 / -0 over 5 files: source +47 (search-filter.ts +41, engine.ts +6 comment only), tests +381, changeset +12", "deviations": [ "File surface: the fix lives in packages/objectql/src/search-filter.ts (fieldClausesForTerm, the callee expandSearchOnAst calls), not in engine.ts itself; engine.ts carries only a 6-line docblock pointer. Reason: that is where per-field clauses are chosen by type (multi-valued -> $contains, enum -> $in); filtering in engine.ts would either narrow the resolved set (turning an all-non-text set into the #24284 refusal, a new 400) or post-walk the emitted AST.", "A test in packages/rest (real SqlDriver) is added beside the objectql AST pin; objectql has no driver devDeps.", "Postgres was measured with a one-off uncommitted script against PostgreSQL 16 started in this container, not with a committed live cell (no CI leg feeds OS_TEST_POSTGRES_URL to objectql/rest/runtime)." ], "open_questions": [ { "question": "Clause-②: a search that answered 400 INVALID_FILTER (a json field in the declared set) now answers 200. Keep `no`, or grade `yes (widening)`?", "options": ["A keep `Clause-②: no` — the 400 was a driver refusal of a predicate the caller never wrote; no request is newly accepted by any door", "B re-grade `Clause-②: yes (widening)` — PR body and changeset lines edited by the seat"], "recommendation": "A, because no door's accept set changed; the ingress door and the engine refusals judge the same set as before" } ], "security_findings": "none", "out_of_scope_findings": ["carrier: #29385 · once it merges, a flagged non-text field in the auto set is skipped by the same line; worth one auto-branch pin in a follow-up or in #29385's next round · noted, not filed"] }Stamped 2026-11-02T16:39Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt
Claim amendment to
6580847761· 2026-11-02T16:41Z · file surface increment, declaredThe card thread's report
6582659644(PR #29502, head5e332246) put the skip where each search term becomes clauses:fieldClausesForTerminpackages/objectql/src/search-filter.ts. It reads the spec'stextOperatorDoorVerdictand keeps no second list.engine.tscarries only a docblock pointer. A REST door pin rides inpackages/rest. The seat accepts:packages/objectql/src/search-filter.ts(fieldClausesForTermonly)packages/rest/src/data-search-non-text-column-door.test.ts(test only)packages/objectql/src/engine.ts(a 6-line docblock).search-filter.ts.jsoncolumn insearchableFields, which made every search 400INVALID_FILTERon all three drivers. The memory driver also matched dates by ISO substring.no. The json case goes from 400 to 200 and answers no match on that field. The dev recommendsno, and the contract review rules on it.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-steve · session_01ADHkmRnyoAJD6oToQ2QZUK
os-dev-report
{ "issue": 29394, "status": "done", "round": 2, "branch": "claude/project-thread-sek37l", "pr": "https://github.com/objectstack-ai/objectstack/pull/29502", "head": "18f7a010436b8d069ccf78e579e05691fecd85ae", "session": "session_01ADHkmRnyoAJD6oToQ2QZUK", "premise_still_valid": true, "summary": "Round 2 per contract review 6583544380 (PASS, test-only round). origin/main merged at c88467d4, which includes #29385 (29c70cacf). Auto-branch pins added: with no searchableFields, flagged searchable: true number / date / json fields are admitted to the set and get no text clause; the unflagged text control is scanned; naming a flagged field is accepted and answers no rows. Pinned on the engine (AST) and on the SQLite Data API door. No source change in this round. The new PR body, with the Clause-② basis line (search-fields.ts declared-branch text, #4254, ruling 6573569376 letter A), is at /mnt/project-files/server-seat2/29502-body-r2.md for the seat to apply.", "tests": "head 18f7a010: objectql engine-search-non-text-column 8/8 (+1 auto), rest data-search-non-text-column-door 6/6 (+1 auto). Ablation re-run (skip line replaced, objectql rebuilt, dist-preflight marker present): objectql 7 failed | 1 passed (8), rest 5 failed | 1 passed (6), so the new auto pins red too; restored blob == HEAD 0c1d38a4, --absent preflight clean. objectql test Test Files 535 passed (535) · Tests 10399 passed; objectql typecheck exit 0; rest search files 9/9 (incl. data-search-field-searchable-flag-door) · 54 passed | 22 skipped; rest typecheck exit 0.", "gates": "head 18f7a010: dispatch-gates --commands derived 63; --ran: 63 run, 0 NOT-MEASURED (a DERIVED zero, none exit 3). eslint on the two edited test files exit 0. CI check-runs: not read at report time.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "0 this round", "api_writes": "1 this round — this os-dev-report comment via post-stamped.mjs. Plus git push (not REST). The PR body is handed to the seat as a file, not written.", "files_changed": ["packages/objectql/src/engine-search-non-text-column.test.ts", "packages/rest/src/data-search-non-text-column-door.test.ts"], "line_budget": "round 2: +58 / -3 over 2 test files; PR total +498 / -3 over 5 files (source unchanged at +47)", "deviations": [], "open_questions": [], "security_findings": "none", "out_of_scope_findings": ["carrier: seat 2 · the spec wording note (search-fields.ts calls a declared json column a scan that CAN match) goes to a spec card the seat files · noted, not filed"] }Stamped 2026-11-02T18:16Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt
Landing record · PR #29502
domain:serverseat 2 ·session_01ADHkmQxwoGb5fSnrFkpxmt· 2026-11-02T19:05Z · card #2939403797bd796git merge-base --is-ancestor 03797bd796 origin/maingit ls-remote origin refs/heads/gh-readonly-queue/*matching 29502git grep -n "29394" origin/main -- packages/objectql/src/search-filter.ts$searchexpansion emits no text clause over a column whose declared type can never hold a string (number, boolean, date, json and the rest, judged by spec'stextOperatorDoorVerdict). A declared json search column no longer turns a search into400 INVALID_FILTER. A set made only of such columns answers no rows.Clause-②: no,Metadata-protocol: none.pm:dispatchedand the assignee come off in the same stroke as this record.search-fields.tsis spec(data): search-fields.ts still calls a declared json search column "a scan that CAN match"; since #29394 the expansion skips it #29546 (domain:spec,pm:queue).Generated by Claude Code