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
[finding] once #14080's refusal lands, three prose sites still describe $gt: null as the one null comparand the contract accepts, and the TYPE door's undefined sentence prescribes a now-refused spelling at the ordering positions #14426
Filed unassigned by the #14080 dev (session session_0112hMx9hjJ9BgB28X97DS68, PR #14425). Recording only — an observation, no severity asserted; routing is triage's. (The refusal lands as PR #14425 under issue #14080; until it lands every sentence below is still true.)
What becomes stale
PR #14425 executes the 2026-09-01 ruling on #14080: a null comparand of $gt / $gte / $lt / $lte is refused at parseFilterAST (INVALID_FILTER / 400). The census that gated that PR (its body carries the method and the table) found the shape written down in prose at three places that describe the PRE-ruling state and are outside the PR's fence (packages/drivers/driver-memory/src/** other than the new pin was ⛔ for that card):
packages/drivers/driver-memory/src/memory-matcher-null-value-and-comparand.test.ts line ~63 — the header's "⚠️ A null COMPARAND in an ORDERING position ({$gte: null}) is absent … and it is the one such position the contract still ACCEPTS". The absence stays deliberate; the sentence's reason moves to "refused, ruled 2026-09-01" — the same wording the file already uses for the list positions.
packages/spec/src/data/filter-comparand-type.ts — undefinedComparandRefusal's prescription "Write null for the null predicate, or omit the key" is position-agnostic. At an ordering position ({ $gt: undefined }) an author who follows it writes { $gt: null } and meets the new refusal, which then names $eq: null / $ne: null. Two loud hops, right final answer — but the first hop's advice is wrong for four of the positions it is emitted at. Not a defect in the door; a wording drift worth one sentence ("the null predicate is $eq: null / $null: true", which is position-safe).
Not in this finding
The test fixtures that exercise the shape in consumers OUTSIDE the door (service-analytics's normalizer on the object-form where, formula's matchesFilter) are boundary pins, not stale prose — PR #14425's body records them as the honest boundary the refusal does not widen.
Suggested shape
One small PR after #14425 lands: the two driver-memory comments re-pointed at the ruling, and the TYPE door's undefined sentence made position-safe, with the existing message pins in filter-comparand-type.test.ts updated if they quote it. No behaviour change.
Blocked-by: #14080
Filed unassigned by the #14080 dev (session
session_0112hMx9hjJ9BgB28X97DS68, PR #14425). Recording only — an observation, no severity asserted; routing is triage's. (The refusal lands as PR #14425 under issue #14080; until it lands every sentence below is still true.)What becomes stale
PR #14425 executes the 2026-09-01 ruling on #14080: a
nullcomparand of$gt/$gte/$lt/$lteis refused atparseFilterAST(INVALID_FILTER/ 400). The census that gated that PR (its body carries the method and the table) found the shape written down in prose at three places that describe the PRE-ruling state and are outside the PR's fence (packages/drivers/driver-memory/src/**other than the new pin was ⛔ for that card):packages/drivers/driver-memory/src/memory-matcher.tsline ~342 — the driver-memory's reference matcher puts a NULL-VALUED row inside$gt/$gte/$lt/$lteon a NUMERIC column —nullcoerces to0, and the live mingo path excludes it #13553 guard's comment: "$gt: nullis the one null-comparand position the contract still ACCEPTS (measured atparseFilterAST) … Deciding it in an operator arm would pick a camp the platform declined to pick". After feat(spec): refuse a null comparand in the ordering positions — $gt / $gte / $lt / $lte (#14080) #14425 the position is refused, so the comment's reason for excluding a no-value COMPARAND from the guard changes from "no ruling covers it" to "ruled unreachable — refused at the door" (the exclusion itself stays right: ⛔ 不单独修 matcher).packages/drivers/driver-memory/src/memory-matcher-null-value-and-comparand.test.tsline ~63 — the header's "{$gte: null}) is absent … and it is the one such position the contract still ACCEPTS". The absence stays deliberate; the sentence's reason moves to "refused, ruled 2026-09-01" — the same wording the file already uses for the list positions.packages/spec/src/data/filter-comparand-type.ts—undefinedComparandRefusal's prescription "Write null for the null predicate, or omit the key" is position-agnostic. At an ordering position ({ $gt: undefined }) an author who follows it writes{ $gt: null }and meets the new refusal, which then names$eq: null/$ne: null. Two loud hops, right final answer — but the first hop's advice is wrong for four of the positions it is emitted at. Not a defect in the door; a wording drift worth one sentence ("the null predicate is$eq: null/$null: true", which is position-safe).Not in this finding
The test fixtures that exercise the shape in consumers OUTSIDE the door (
service-analytics's normalizer on the object-formwhere,formula'smatchesFilter) are boundary pins, not stale prose — PR #14425's body records them as the honest boundary the refusal does not widen.Suggested shape
One small PR after #14425 lands: the two driver-memory comments re-pointed at the ruling, and the TYPE door's
undefinedsentence made position-safe, with the existing message pins infilter-comparand-type.test.tsupdated if they quote it. No behaviour change.Generated by Claude Code