Skip to content

A comment asserts the SEARCH-axis remedy is worded identically to SORT/FILTER, the pin does not cover SEARCH, and the emitted message does not match — declared-≠-enforced on the refusal vocabulary #8648

Description

@qq9340100

Filed out of #8372's docs work (session session_01Jqe56GnYFddggeAyfkZFVz). Unassigned and unlabeled — recording only, for triage.

Backlink: #8372 · PR #8647 · related: #8296, #6673, #6994.

The shape

A comment asserts an invariant, the test does not cover it, and the code does not honour it. That is this repo's recurring declared-≠-enforced family, landing here on the refusal vocabulary rather than on a metadata key. The wording difference alone would be a nit; the unenforced claim about it is the defect.

What was measured

Captured from the running doors — a real ObjectQL plus the protocol, each refusal triggered and its emitted message recorded verbatim (base 259f211f0). Not read out of the source strings: a literal in the tree can be dead or shadowed, and what the door emits is what a caller sees.

axisdoorenveloperemedy sentence, as emitted
SORTingress + engine.find()400 INVALID_SORTDenormalise the value onto 'showcase_task' (a stored field, written when the source changes) and sort by that.
FILTERingress + engine.find()400 INVALID_FIELDDenormalise the value onto 'showcase_task' (a stored field, written when the source changes) and filter that.
SEARCHingress400 INVALID_FIELDMirror the computed value onto a stored text field on 'showcase_task' and search that instead.

SORT and FILTER are byte-identical apart from the closing verb. SEARCH differs in verb (Mirror / Denormalise), in noun phrase, and it narrows the target to a text field. All three agree in substance — put the value on a stored column of the queried object and query that instead.

The claim, quoted

Three comments state the SEARCH agreement as a fact about wording:

packages/objectql/src/filter-comparand-shape.ts:398 carries the same sentence but names only the ingress door, so it is accurate as written.

The coverage gap

packages/objectql/src/engine.ts:857 also says the pin enforces it: "query-expression-conformance.test.ts pins the three wordings as EQUAL rather than each separately, because separate wordings is exactly how #4256 and #6673 drifted apart in the first place."

The pin — the FILTER refusals agree word-for-word with the SORT refusals on the remedy — asserts the stem Denormalise the value onto 'showcase_task' (a stored field, written when the source changes) and across four doors: filter-ingress, filter-engine, sort-ingress, sort-engine. Verified green in isolation (1 passed, 170 skipped). The SEARCH door is not among them, and its emitted message cannot match that stem — so the claim is unpinned in exactly the place where it is false. An author rewording the SEARCH message will believe a pin protects the agreement, and nothing goes red.

Boundary

This is not a request to reword SEARCH. Which way the gap should be closed is triage's call, and the routes carry very different weight:

  • correcting the comments to describe substance-agreement rather than word-identity — comment-only;
  • extending the pin to the SEARCH door, against whatever agreement is decided — test-only;
  • aligning the SEARCH wording onto the shared stem — this changes a shipped, user-visible error message on an axis that already landed, a different weight class from the other two, and the text narrowing (correct for an axis that scans text-like columns) would need somewhere to live.

No route is recommended here.

Not addressed in PR #8647: that card is docs-only and its scope explicitly excludes error messages and rules.


Generated by Claude Code

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions