docs(spec): the $search expansion compiles to $icontains, not an $or of $contains - #15053
Conversation
The `DriverCapabilities.fullTextSearch` tombstone prescription and five hand-written passages still described the ADR-0061 search expansion as an `$or` of `$contains`. `expandSearchToFilter` has emitted `$icontains` since #7641; `$contains` is contractually case-sensitive (#4706 Q2 = A). One callout went further than a stale operator name: it told the reader the case-insensitivity question "remains a separate open question, and one that can now actually be answered" — inviting a reader acting in good faith to re-open an adjudicated ruling. It now states the settled answer. Site C lands in the `.describe()` source, never in the generated `.mdx`; the four reference rows are regenerated by `check:generated --fix`. Every other `$contains` mention on the three pages was classified individually — the operator's own rows, examples and case-sensitivity rulings are correct and are untouched. `packages/objectql/src/search-filter.ts` is not in this diff: its `__search` companion clause is deliberately `$contains` and must not be aligned. `content/docs/releases/` is not touched; it was already correct. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0174WZTU6XcFcS7g2kykC53i
…arch-expansion-icontains-docs
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 128 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 47a4dcf81738ebffaf518ca7d6ebb519c78042d8 && git checkout 47a4dcf81738ebffaf518ca7d6ebb519c78042d8
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 0fb944b4f6ec7437ee3abb25fcedbde629466347 25e0fcde8ec512a78054b891a174b5f719d7eb05 && git checkout -B drift-repro 0fb944b4f6ec7437ee3abb25fcedbde629466347 && git merge --no-ff 25e0fcde8ec512a78054b891a174b5f719d7eb05
node scripts/docs-audit/affected-docs.mjs --json 0fb944b4f6ec7437ee3abb25fcedbde629466347 |
|
Landing provenance (PM seat
Generated by Claude Code |
Fixes #13988
Clause ②: no — path limb fires (
packages/spec/src/data/driver.zod.tsdescribe text); content limb no: no accept-set or emitted-shape change.Triage 5487762327 ruled one card, six sites, one PR. All six land here.
⭐ Site B — the one that is worse than a stale operator name
content/docs/protocol/objectql/query-syntax.mdx, in the Full-Text Search callout, told the reader:It does not remain open. #7641 adjudicated it;
expandSearchToFilterhas compiled$searchto$icontainsever since;packages/objectql/src/search-filter.ts:23carries the ruling verbatim; andcontent/docs/releases/v17.mdxalready published it. The other five sites misspell an operator — this one told a reader in good faith that a settled ruling was theirs to re-open. It now states the settled answer, and names$containsas case-sensitive by contract (#4706 Q2 = A) so the two operators read as different operators rather than two spellings of one.A second, materially false sentence sat immediately above that callout and is corrected in the same place: the page said the expansion "emits a plain
$contains, which is case-sensitive" and that "a user typingacmedoes not findACME Corp". That is the reader-facing consequence of the same defect, stated as fact. It now says search is case-insensitive by ruling.Site C — corrected in the SOURCE, never in the generated pages
The four
fullTextSearchrows incontent/docs/references/data/carry⚠️ AUTO-GENERATED — DO NOT EDIT. Their producer is the tombstone prescription's.describe()inpackages/spec/src/data/driver.zod.ts, which is what this PR edits; the four rows were regenerated withpnpm --filter @objectstack/spec check:generated --fix. None of the four.mdxfiles was hand-edited.Measured:
check:generatedreported 1 of 15 artifacts stale —content/docs/references/**— and--fixregenerated only that one.check:api-surface,check:export-originsandcheck:authorable-surfacestayed green, confirming a describe-text change moves no other artifact. All four regenerated rows assert as carrying$icontains, with zero occurrences of the old string remaining.Sites A — the hand-written pages
query-syntax.mdx(the expansion sentence and the driver-capability clause "every driver already runs$or/$contains", the one triage noted is easier to miss because it reads as a statement about driver capability),data-modeling/queries.mdx,data-modeling/schema-design.mdx.Every
$containsmention on the three pages, classified individually⛔ No blanket replace. 24 mentions were read one by one; only expansion descriptions changed.
$likeis not a spelling of$contains$contains/$icontainsthere"$orcode example$orof$containspredicates"$icontains$or/$contains"$icontains$contains, which is case-sensitive"$containsalignment landed in three steps"$orof$contains"$icontains$containsagainst one has nothing to scan"$icontains$and-of-$or-of-$containsfilter (ADR-0061)"$icontains$containsto scan"$icontains?search=apollonow expands toname $contains …"$icontains$containspredicate against one has nothing to scan"$icontainsTwo classification notes worth a reviewer's attention:
query-syntax:1009was not on the card's site list. The card and the claim named:970-974,:1026-1027and:1053. Reading every mention one by one surfaced:1009as a third false expansion description on the same page — and the most directly harmful of them, since it tells the reader in plain words that search is case-sensitive. It is corrected under the same classification rule, not as scope expansion.query-syntax:1054,queries:533,schema-design:140) describe the predicate the expansion emits over a user-authored mirror column, so they follow the expansion. They are not the__searchcompanion clause.⛔ The deliberate
$containsis NOT touchedpackages/objectql/src/search-filter.ts:137-148emits$containsfor the normalized__searchcompanion clause. That is correct: the companion column is lowercase by construction and the term is lowercased before comparison, so a case-sensitive operator over two folded values is exact, not a case bug. Its own comment says "Do not align the two."packages/objectql/**is not in this diff at all — triage flagged a drive-by "unify the operators" sweep as this card's most likely way to do damage, so the exclusion is stated rather than assumed.content/docs/releases/**is likewise untouched: it was already correct, and it is release-owned.Verification
Run on the final commit,
25e0fcde(git rev-parse --short HEADafter the last commit; the tree is clean and this is the tree every number below was measured on).pnpm --filter @objectstack/spec test— 463 test files, 12374 tests passed;typecheckclean (tsc --noEmit,check:scripts-typecheck,check:test-typecheckall OK). Both through the shared verify lock, VERDICTcommand-exit 0.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(no paths passed — the script takes its own change set), from a tree with no STALE TREE warning after merging currentmain. It derived 8 changed paths and a family the dispatch clue did not fully cover; the additions were run too, among themcheck:doc-formula-expressions,check:doc-security-posture,check:objectui-changeset,check:role-word,check:spec-parsed-aliasandcheck:vendor-version-stamps.check:docs,check:doc-anchors,check:doc-authoring,check:docs-audit-scope,check:docs-redirects,check:docs-single-h1,check:quick-reference-counts— pluscheck:corpus-claim-drift("check-corpus-claim-drift: OK, no new claim sites beside a pinned spelling"),check:generated,check:api-surface,check:authorable-surface,check:export-origins,check:llms-txt,check:skill-refs,check:strictness-ledger,check:variant-docs,check:yaml-examples,check:nul-bytes("scanned 8174 text file(s) … no raw ASCII control bytes"),check:merge-driver,check:published-files,check:pm-half-statesandcheck:changeset-gate-self-tests.check-dev-prereqsandcheck:dual-build-cjs-loadsneed a full-workspacepnpm build(only the spec closure plus four packages were built here), andcheck-test-completenessneeds a savedturbo run testlog, which its own text says to record as NOT MEASURED when the family is run locally. CI runs the farm.check:doc-formula-expressions,check:doc-security-postureandcheck:skill-examplesfirst exited on unbuilt inputs; their packages were built and all three then ran green, so they are measurements rather than gaps.Exit codes were captured before any pipe throughout, and the verdicts quoted above are the gates' own printed lines.
Hypotheses carried in the dispatch, as measured
--fixmoves exactly the four driver rows and nothing else: CONFIRMED. 1 of 15 artifacts stale; three files moved (driver.mdxcarries two of the four rows).check:corpus-claim-driftand thecheck:docsfamily stay green: CONFIRMED. No ratchet rule covers this wording; nothing was re-worded to satisfy a gate.$icontainsinsearch-filter.ts, 8 hits). Its only other hits are correct and unrelated:driver-sql.ts:2646andsql-driver-json-column-operator-refusal.test.ts:254describe$orof$containsas the any-of spelling for JSON columns, a different mechanism.Out-of-scope finding, filed not fixed
The H3 sweep surfaced a fourth site in this family that no existing card covers:
packages/spec/src/data/search-fields.ts:9carries the same false sentence in its module docblock. It is not published (grep 'clauses over exactly this set' content/returns zero with a firing positive control), so it is outside this card's published-docs thesis, and it is in a different package from the two code cards (#13744engine.ts, #13984search-companion.ts). Filed unassigned as #15052 after a full 530-of-530 open-item dedupe enumeration with a firing positive control. It is deliberately not fixed here.Changeset
@objectstack/specpatch— a published package's describe text changes and reaches the generated reference pages. Documentation only: no accept/reject, emitted-shape or runtime behaviour change.🤖 Generated with Claude Code
Generated by Claude Code
Generated by Claude Code