Repository navigation
fix(objectql): the no-operator-object refusal prints its route inside the client cap - #27350
Conversation
… the client cap Every kind of the no-operator-object filter refusal (scalar, structured-JSON, single- and multi-valued relation) now reads verdict, route, then "NOT applied" and the reasoning, so the route lands inside the 500 characters a client reads. The verdict names the column by its type, since the head already names the field twice. The cap, truncation, code and status are unchanged. Claude-Session: https://claude.ai/code/session_01Utp6CXc5hequf76uJfzrdK Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift Check4 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 — 19 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 549d3e90c0f8fad9fb2006302b7089ec6fef74c7 && git checkout 549d3e90c0f8fad9fb2006302b7089ec6fef74c7
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 73725c206f55580db058645dbffe68280b095ef6 885fc60787fb0943b6b875b6b74866bb07cec8cd && git checkout -B drift-repro 73725c206f55580db058645dbffe68280b095ef6 && git merge --no-ff 885fc60787fb0943b6b875b6b74866bb07cec8cd
node scripts/docs-audit/affected-docs.mjs --json 73725c206f55580db058645dbffe68280b095ef6 |
|
domain:server#3 · os-bill · session_01Utp6CXc5hequf76uJfzrdK 席位核对 — ACCEPT ·
|
domain:server#3 · os-bill · session_01Utp6CXc5hequf76uJfzrdK
Requested by Bill · project thread
Fixes #27337
Clause-②: no
Metadata-protocol: none
维护者速读
$运算符的对象"时,报错文字改为先说"该怎么写",再说"未执行"和原因;四类字段(单值/多值 lookup、json/address、普通标量)都按此顺序。$in示例。INVALID_FILTER、状态 400、截断上限都不变;回滚即 revert 本 PR。packages/objectql/src/no-operator-object-door.ts(四个 words 函数)、packages/objectql/src/no-operator-object-prescription-cap.test.ts(按客户端读法逐类钉住)。pnpm --filter @objectstack/objectql exec vitest run src/no-operator-object-prescription-cap.test.ts,预期 4/4 通过。What changes
packages/objectql/src/no-operator-object-door.ts— every kind of the no-operator-object refusal now reads verdict, route, then "NOT applied" and the reasoning, so the route sits inside the 499 characters a client reads (CLIENT_MESSAGE_MAX,@objectstack/types, unchanged):aggregations[i].filter,having) — the card's arm. The$inroute moved ahead of "NOT applied"; it opens "Move the condition to 'where'" and names the related object by its name alone (filter 'TARGET' first and match the ids it returns: { "FIELD": { "$in": [ID, …] } }.).a lookup field,an aggregated lookup column,a platform-provisioned text column): the head already names the field twice (filter on 'FIELD' … at PATH.FIELD). The full name (the declared lookup field 'FIELD',the aggregated column 'FIELD', which carries a … value) moved into the reasoning after "NOT applied".INVALID_FILTER/ 400, the envelope, the cap and the truncation, and every phrase another package's test reads (which the engine serves in 'where',The filter was NOT applied.,is filter structure, not a value,Compare 'id' with a value ({ "id": VALUE }),{ "meta": { "$null": false } }, or store the part you filter on in a field of its own).Tests: a new
no-operator-object-prescription-cap.test.tsreads each kind throughmapDataError, as a client does, with a long fixture (21-character object, 20- to 24-character fields, a three-key object, a path through an aggregation's filter and a nested$and/$or), and requires the whole route in the client text, ending at least 40 characters before the cut, ahead of "NOT applied". Measured route ends on that fixture: 368–444 (margin 55–131). Two in-surface tests updated for the new verdict wording (engine-nested-object-door.test.ts,engine-nested-relation-lowering.test.ts). Onepatchchangeset for@objectstack/objectql.Tests
Targeted and package runs (head 885fc60)
pnpm --filter @objectstack/objectql test— Test Files 479 passed (479), Tests 8942 passed (8942); thencheck:test-typecheckgreen (lock VERDICT command-exit 0).pnpm --filter @objectstack/objectql typecheck— exit 0, afterpnpm --filter @objectstack/objectql build.pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 src/data-nested-object-door.test.ts src/data-no-operator-object-door.test.ts— 10 passed, 20 skipped (the live PostgreSQL / MySQL cells, no env here; the SQLite cell ran).eslint --no-inline-config packages/objectql— exit 0.Ablation, once (the fix committed first)
no-operator-object-door.tsreplaced by itsorigin/main6d7634a9blob (hash4ebc814bconfirmed on disk; the new wording absent, the old present):no-operator-object-prescription-cap.test.ts→ 4 failed (4), e.g. "the route ends at 488 … expected 488 to be less than or equal to 459". Restored withgit checkout HEAD --: hash58f30588equals the HEAD blob,git diff HEADempty, 4 passed (4). The subject is imported by a relativesrcpath, so nodistbuild sits between the test and the edit.Verification — route offsets before and after
Measured with
tsxthroughnarrowNumberComparands(aggregations[12].filter, nested$and/$or) andnarrowHavingNumberComparands, read throughmapDataError. "Field chars" counts the field name; objectcustomer_support_caseand targetcustomer_accountfor the first table; "2 keys" iscity/zip, "4 keys" is four 9- to 15-character keys. A multi-valued lookup athavinghas no row: an aggregated column has no declaration, so it gets the single-valued words.Long field (24 chars): before, every arm cut; after, every arm inside
Stress: 27-character object and target, 18- and 32-character fields
Acceptance notes
aggregations[i].filter; json / address athaving, 502–528). There the head alone (context, field, keys, path) takes about 270 characters before any arm's words; closing it means shortening the shared head (describeObjectshows three keys), which every position and arm prints. Not done here; recorded for the seat.relationConditionRefusalMessageinpackages/objectql/src/relation-filter-lowering.ts(thewhererefusals of a nested-relation condition) prints its route LAST. Measured with a 21-character field, a 16-character target, three keys and a nested path:second-level608 characters,dotted-key527,empty508 — each route ends past the 499 cut. Reported to the seat in the dev report.Generated by Claude Code