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
[spec] parseFilterAST lowers ['a', '=', { $field: 'b' }] to a bare field spec no backend reads as equality #7597
Measured while implementing #5222 (cross-field push-down). Filing unassigned — recording, not claiming.
The fact
parseFilterAST lowers an authored triple differently depending on the operator spelling. Measured on current main:
Authored
Lowered to
[['amount', '>', { $field: 'budget' }]]
{"amount":{"$gt":{"$field":"budget"}}}
[['amount', 'gt', { $field: 'budget' }]]
{"amount":{"$gt":{"$field":"budget"}}}
[['amount', '=', { $field: 'budget' }]]
{"amount":{"$field":"budget"}} ← bare
[['amount', 'equals', { $field: 'budget' }]]
{"amount":{"$field":"budget"}} ← bare
The equality spellings drop the operator, because a literal comparand's implicit-equality form is { field: value } — correct for a literal, but for a field reference it produces a field spec whose only key is $field.
Nothing reads that shape as an equality. In matches-filter.ts, evalField sees an all-$ key set and dispatches $field to evalOp, which has no arm for it and returns its fail-closed false. So the filter silently matches no record. On the SQL side the same shape arrives as an OPERATOR named $field.
Why it matters
Two authored spellings of one intent, two fates: ['amount', '>', ref] works (post-#5222 on SQL, and always in memory), ['amount', '=', ref] silently matches nothing. The failure is invisible on the path that produces it.
#5222 narrowed the SQL side to give this shape an actionable refusal naming $eq rather than a generic operator list — but that is a driver-side mitigation of a lowering defect, and it deliberately did NOT compile the shape, because compiling it would make SQL answer rows for a filter the memory evaluator answers false for (a new divergence in the change that closed one).
The decision this needs
Most likely: parseFilterAST should lower an equality triple whose comparand is a FieldReferenceSchema to { field: { $eq: ref } } rather than the bare form — the spelling that IS implemented on both paths. That is a one-sink change (parseFilterAST is the single lowering sink per #5158), but it is a semantics change at the authoring face, so it wants a ruling rather than a drive-by fix.
Alternatively, matches-filter.ts could read a bare { $field } field spec as an implicit equality — but that changes the evaluator's unknown-operator posture, which #6520 examined and deliberately KEPT.
Classification: the card's own conclusion — lowering an equality triple with a FieldReferenceSchema comparand to { field: { $eq: ref } } "is a semantics change at the authoring face, so it wants a ruling rather than a drive-by fix" — and the alternative (reading bare { $field } as implicit equality) reverses the evaluator posture JS 求值面全体拒收 $icontains(driver-memory 两面 / driver-mongodb / objectql having / formula)—— SQL 族已实现,同一 filter 在内存 double 上抛错 #6520 deliberately kept. Both branches move the authoring-face semantics of packages/spec, so domain:spec per standing instruction ③'s reverse red line.
Maintainer ruling recorded 2026-08-11 (PM session, executing the maintainer's direct instruction in chat — verbatim: 「接受你的全部建议,请更新 issue 的状态和标签」, accepting the four-lens decision-inbox review in full).
Ruling: fix the lowering.parseFilterAST lowers an equality triple whose comparand is a FieldReferenceSchema to { field: { $eq: ref } } — the spelling already implemented on both evaluation paths. ⛔ Do NOT change the memory evaluator's unknown-operator posture; #6520's decision stands. Single-sink change per #5158.
Rationale (four-lens): silent zero-row matching is the worst failure shape; the fix is one sink, no new capability surface, and removes a trap AI-authored filters walk straight into.
Round-1 selection note (spec lane, session session_01JY2Q5Xto1u8YHADgrZDTnk): deferred to the NEXT round by the batch cap — round 1 took #7495/#7496/#7513 (fan-out-ordered). Not shelved; this card rides first in round 2, ahead of #7596 (same-file serialization: both edit packages/spec/src/data/filter.zod.ts, and this ruled silent-zero-rows fix outranks the removal).
Facts recorded for the dispatching round (all re-verified 09:18Z on origin/main):
Claim: PM loop round 1 backfill (spec lane — slot freed by #7495's voiding; maintainer instructed 加速派发)
Session: session_01JY2Q5Xto1u8YHADgrZDTnk
Branch: claude/issue-7597-equality-field-ref-lowering
Worktree: cloud dev session (own container)
Domain: domain:spec
File surface: packages/spec/src/data/filter.zod.ts (parseFilterAST, ~:1415) + its tests + the cross-field conformance corpus (cross-field-conformance-cases.ts region, additive). ⛔ Not the $between/$in/$nin unions — that region is #7596's, serialized behind this card. Stop on breach; explain in the report.
Container & model: M (ruled authoring-face semantics change with cross-path conformance obligations), mode:cloud, model: opus
Serial constraints cleared: #7596 (same file) is explicitly queued BEHIND this card (hot-file serial queue, seat post #6017; defer note on #7596 09:27Z). No in-flight PR touches filter.zod.ts (checked 09:20Z; #7593 merged this morning — anchors re-verified post-merge). #7617 (in flight, sibling sub-lane) declares a docs-prose face.
Premise verified, then fixed. Measured on origin/main before the first edit: all four $eq spellings (=, ==, equals, eq) lowered ['amount', '<op>', { $field: 'budget' }] to the bare {"amount":{"$field":"budget"}} and the in-memory evaluator returned [], while > / gt lowered to {"$gt":ref} and returned ["1"]. After the fix all four lower to {"amount":{"$eq":{"$field":"budget"}}} and return ["3","6"] — the conformance corpus's declared $eq row set. parseFilterAST is at filter.zod.ts:1415 as the dispatch said (the triage comment's :1205 was stale); confirmed single sink — no second definition.
Full spelling set measured, not assumed.AST_OPERATOR_MAP folds exactly those four onto $eq, and convertComparison's implicit-equality branch intercepts exactly those four, so the two lists coincide. A new test sweeps the whole exported VALID_AST_OPERATORS vocabulary and fails if any spelling lowers a reference comparand to a bare field spec.
Compile-surface enumeration (full evidence in the PR body): face 1 driver-sql already conformant and now exercised by the new authoring arm; face 2 turso RemoteTransport already conformant (loud INVALID_FILTER before and after); face 3 read-scope-sql not reachable (read scopes are policy-compiled, never through this sink) and owned by #7598; face 5 formula is the reference implementation; half-face objectql having out of reach (having is a FilterCondition object, never AST-lowered); driver-memory/driver-mongodb out of scope per the #5499 freeze.
⚠️One measured consequence the PM should weigh — face 4, service-analyticsfilter-normalizer. The equality triple moves there from a loud INVALID_FILTER/400 ("Unsupported filter operator $field") into the same SILENT bucket the ordering spellings have occupied since #3948: assertCompilableComparand gates only the LIKE family and $in/$nin members, so a scalar operator's object comparand falls through to toSqlBindValue and is bound as JSON text. Not a new defect class — one more spelling entering an existing one — and the same shift lands on the frozen driver-memory. Left unfixed deliberately, on the precedent this exact surface set: #7604's triage records that #5222's dev seat declined to widen analytics as a side effect and the PM called that right; refusing only $eq there would create a fresh asymmetry inside the face, and refusing all six is #7598's open question 1. Measurement posted to #7598.
Re-pricing #7596: untouched. The list positions are unchanged by this PR (in/nin/between lowerings pass their comparand through as before), and the two diff hunks start at :1350/:1376, so #7596's unions at :319-320 and :819-820 are byte-identical and unshifted. It gets marginally cleaner to argue — after this fix the remaining declared-but-unexecutable $field positions are exactly the ones #7596 removes — but neither easier nor harder to do.
Region boundary respected: the $between/$in/$nin unions were not touched.
{
"issue": 7597,
"status": "done",
"branch": "claude/issue-7597-equality-field-ref-lowering",
"pr": "https://github.com/objectstack-ai/objectstack/pull/7672",
"premise_still_valid": true,
"summary": "parseFilterAST's implicit-equality shorthand now branches on the comparand: an equality triple whose comparand is a FieldReferenceSchema lowers to { field: { $eq: ref } } instead of the bare { field: { $field } } that no backend reads as an equality, so ['amount','=',ref] finally behaves like ['amount','>',ref] on both evaluation paths. All four $eq spellings are covered and a vocabulary sweep test keeps a fifth from re-opening it; literal comparands, non-string $field carriers, and the evaluator's #6520 unknown-operator posture are untouched — a hand-authored bare field spec keeps today's fate on every backend. The cross-field conformance corpus gains an AUTHORING arm (CROSS_FIELD_AUTHORED_CASES) that enters through the sink and holds the lowered filter to the same both-paths-same-rows rule, run by driver-sql per dialect cell and by driver-sqlite-wasm. One consequence to weigh: at service-analytics' filter-normalizer (and the frozen driver-memory) the equality spelling shifts from a loud refusal into the silent JSON-bind bucket the ordering spellings already sit in — measured, reported, and left to #7598 rather than widening analytics as a side effect.",
"tests": "pnpm --filter @objectstack/spec test => 377 files / 9880 tests passed (includes the new src/data/filter-field-reference-lowering.test.ts). pnpm --filter @objectstack/driver-sql test => 86 passed | 4 skipped (90) files, 1399 passed | 50 skipped tests; the 15 new authoring-arm cases confirmed running by name under -t '#7597'. pnpm --filter @objectstack/driver-sqlite-wasm test => 24 files / 374 tests passed. pnpm --filter @objectstack/formula test => 25 files / 631 tests passed. typecheck (spec, driver-sql, driver-sqlite-wasm) clean. Gates: check:driver-conformance OK (37 covered cells, 3 DEBT, 0 exempt); check:merge-driver, check:adr-anchors, check:spec-parsed-alias OK; check:authorable-surface OK (1276 defaults unchanged, no anchor diff); scripts/check-nul-bytes.mjs OK (7069 files). REVERSE VERIFICATION, direction predicted first: removing the fix via a patch file must turn the AUTHORING arm red and leave the hand-authored bare-form refusal green. Measured exactly that -- 14 authoring cases plus 'the equality TRIPLE no longer lowers to that bare spelling' failed with \"expected { amount: { '$field': 'budget' } } to deeply equal { amount: { '$eq': ... } }\", while the '>' control and the bare-form refusal pin stayed green; restored with git apply. CI status at report time: in_progress (draft PR just opened; PM owns convergence).",
"open_questions": [
{
"question": "service-analytics' filter-normalizer (face 4) and the frozen driver-memory now answer the equality-with-$field shape SILENTLY (JSON-bound comparand, zero rows) where they previously refused loudly. Fix inside #7598's scope, or does the PM want a narrow refusal landed sooner?",
"options": [
"A - leave it to #7598 (queued, domain:services, owns both analytics emitters; its open question 1 is implement-vs-refuse for exactly these faces)",
"B - land a narrow $field refusal at the analytics scalar-comparand door in a follow-up card, ahead of #7598's larger decision, so the face stays loud for all six operators"
],
"recommendation": "A. Refusing only $eq at that door would create a fresh asymmetry inside the analytics face -- the exact defect class this card closes -- and refusing all six pre-empts #7598's ruling on whether these emitters implement $field instead. The shift is not a new defect class: the ordering spellings have been silent there since #3948, so this is one more spelling joining an existing, already-filed hole. The measurement has been posted to #7598 so its executor inherits it rather than re-deriving it."
}
],
"out_of_scope_findings": [
"not filed (existing card): the analytics silent-bind residue above belongs to #7598 (#7604 was closed as its duplicate) - measurement posted there as a comment rather than a twin issue",
"FieldReferenceSchema's execution-support docblock (packages/spec/src/data/filter.zod.ts, ~:36-64) still says SQL push-down refuses a field reference and that compiling it 'is tracked as its own capability in #5222' - stale since #7582 landed that compilation. Doc-only, adjacent to but not part of this card's change; left untouched, flagged here for the PM to route (a docs-accuracy pass on the same file would also catch it)."
]
}
The ruling lands exactly: one branch in the single sink (convertComparison) — a FieldReferenceSchema comparand in the equality shorthand lowers to { $eq: ref }; literals keep implicit equality (pinned); a non-string $field is not a reference (predicate mirrors driver-sql's fieldReferenceOf — good cross-layer consistency); JS 求值面全体拒收 $icontains(driver-memory 两面 / driver-mongodb / objectql having / formula)—— SQL 族已实现,同一 filter 在内存 double 上抛错 #6520's evaluator posture untouched and pinned on the hand-authored bare form.
The spelling set was measured, not assumed: all four $eq spellings fixed, case folding covered, and a vocabulary sweep over VALID_AST_OPERATORS pins that NO spelling can lower a reference comparand to a bare field spec — a fifth spelling entering the map cannot silently re-open this.
Compile-surface enumeration is complete — every face has a conclusion with evidence, including the half-face (having never passes the sink — stated with the metadata-protocol quote) and the frozen faces (measured anyway, for the record).
Reverse verification in the predicted direction (patch-file restore): 14 authoring cases + the triple pin red with the fix removed; the > control and the re-authored bare-form refusal stayed green.
Activity
os-zhuang commentedon Aug 11, 2026
Triage:
needs-user-decisionappended;domain:spec(filer-applied) confirmed correct.FieldReferenceSchemacomparand to{ field: { $eq: ref } }"is a semantics change at the authoring face, so it wants a ruling rather than a drive-by fix" — and the alternative (reading bare{ $field }as implicit equality) reverses the evaluator posture JS 求值面全体拒收$icontains(driver-memory 两面 / driver-mongodb / objectqlhaving/ formula)—— SQL 族已实现,同一 filter 在内存 double 上抛错 #6520 deliberately kept. Both branches move the authoring-face semantics ofpackages/spec, sodomain:specper standing instruction ③'s reverse red line.origin/main@744b8f5:parseFilterASTlives atpackages/spec/src/data/filter.zod.ts:1205(single lowering sink per [engine] driver-sql 编译 spec 未声明的「数组 where 方言」—— 与 Turso remote 的拒收分叉,需一次定调(接纳进 spec 或响亮弃用) #5158 holds — no second definition found).FieldReferenceSchemais declared in the$betweenendpoints but NO backend resolves a$fieldinside a list #7596 (declared-but-unresolved list positions) and [spec]service-analytics' read-scope / Cube filter compilers still refuse$field, so a CEL field-to-field RLS rule 400s on those faces #7598 (analytics faces) — this one is the lowering sink itself. No existing card names the bare-$fieldequality lowering; no open PR touches it.$fieldcapability whose SQL half ([spec] SqlDriver 将$field编译为列对列比较(cross-field comparison push-down) #5222) is still in flight and now refuses this shape loudly with an actionable message; not judged RC-blocking on its own — the ruling can ride the [spec] SqlDriver 将$field编译为列对列比较(cross-field comparison push-down) #5222 follow-up window.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-zhuang commentedon Aug 11, 2026
Maintainer ruling recorded 2026-08-11 (PM session, executing the maintainer's direct instruction in chat — verbatim: 「接受你的全部建议,请更新 issue 的状态和标签」, accepting the four-lens decision-inbox review in full).
Ruling: fix the lowering.
parseFilterASTlowers an equality triple whose comparand is aFieldReferenceSchemato{ field: { $eq: ref } }— the spelling already implemented on both evaluation paths. ⛔ Do NOT change the memory evaluator's unknown-operator posture; #6520's decision stands. Single-sink change per #5158.Rationale (four-lens): silent zero-row matching is the worst failure shape; the fix is one sink, no new capability surface, and removes a trap AI-authored filters walk straight into.
State:
needs-user-decision→pm:queue(domain:specseat).Generated by Claude Code
os-zhuang commentedon Aug 11, 2026
Round-1 selection note (spec lane, session
session_01JY2Q5Xto1u8YHADgrZDTnk): deferred to the NEXT round by the batch cap — round 1 took #7495/#7496/#7513 (fan-out-ordered). Not shelved; this card rides first in round 2, ahead of #7596 (same-file serialization: both editpackages/spec/src/data/filter.zod.ts, and this ruled silent-zero-rows fix outranks the removal).Facts recorded for the dispatching round (all re-verified 09:18Z on
origin/main):parseFilterASTis now at:1415— the triage comment's:1205is stale.fieldsstops prescribing a dotted path no driver resolves (#7601) #7617 (docs prose, in flight, sibling sub-lane) declares a different file face; re-verify at dispatch time.FieldReferenceSchemais declared in the$betweenendpoints but NO backend resolves a$fieldinside a list #7596's removal scope (re-pricing rule — both cards share the filter contract face).Generated by Claude Code
os-zhuang commentedon Aug 11, 2026
Claim: PM loop round 1 backfill (spec lane — slot freed by #7495's voiding; maintainer instructed 加速派发)
Session:
session_01JY2Q5Xto1u8YHADgrZDTnkBranch:
claude/issue-7597-equality-field-ref-loweringWorktree: cloud dev session (own container)
Domain:
domain:specFile surface:
packages/spec/src/data/filter.zod.ts(parseFilterAST, ~:1415) + its tests + the cross-field conformance corpus (cross-field-conformance-cases.tsregion, additive). ⛔ Not the$between/$in/$ninunions — that region is #7596's, serialized behind this card. Stop on breach; explain in the report.Container & model: M (ruled authoring-face semantics change with cross-path conformance obligations),
mode:cloud, model: opusSerial constraints cleared: #7596 (same file) is explicitly queued BEHIND this card (hot-file serial queue, seat post #6017; defer note on #7596 09:27Z). No in-flight PR touches
filter.zod.ts(checked 09:20Z; #7593 merged this morning — anchors re-verified post-merge). #7617 (in flight, sibling sub-lane) declares a docs-prose face.Generated by Claude Code
os-zhuang commentedon Aug 11, 2026
OS-DEV-REPORT — #7597
os-dev-report
Draft PR: #7672 · Branch:
claude/issue-7597-equality-field-ref-lowering· Base:origin/main@cc3555ePremise verified, then fixed. Measured on
origin/mainbefore the first edit: all four$eqspellings (=,==,equals,eq) lowered['amount', '<op>', { $field: 'budget' }]to the bare{"amount":{"$field":"budget"}}and the in-memory evaluator returned[], while>/gtlowered to{"$gt":ref}and returned["1"]. After the fix all four lower to{"amount":{"$eq":{"$field":"budget"}}}and return["3","6"]— the conformance corpus's declared$eqrow set.parseFilterASTis atfilter.zod.ts:1415as the dispatch said (the triage comment's:1205was stale); confirmed single sink — no second definition.Full spelling set measured, not assumed.
AST_OPERATOR_MAPfolds exactly those four onto$eq, andconvertComparison's implicit-equality branch intercepts exactly those four, so the two lists coincide. A new test sweeps the whole exportedVALID_AST_OPERATORSvocabulary and fails if any spelling lowers a reference comparand to a bare field spec.Compile-surface enumeration (full evidence in the PR body): face 1
driver-sqlalready conformant and now exercised by the new authoring arm; face 2 turso RemoteTransport already conformant (loudINVALID_FILTERbefore and after); face 3read-scope-sqlnot reachable (read scopes are policy-compiled, never through this sink) and owned by #7598; face 5formulais the reference implementation; half-face objectqlhavingout of reach (havingis aFilterConditionobject, never AST-lowered);driver-memory/driver-mongodbout of scope per the #5499 freeze.service-analyticsfilter-normalizer. The equality triple moves there from a loudINVALID_FILTER/400("Unsupported filter operator$field") into the same SILENT bucket the ordering spellings have occupied since #3948:assertCompilableComparandgates only the LIKE family and$in/$ninmembers, so a scalar operator's object comparand falls through totoSqlBindValueand is bound as JSON text. Not a new defect class — one more spelling entering an existing one — and the same shift lands on the frozendriver-memory. Left unfixed deliberately, on the precedent this exact surface set: #7604's triage records that #5222's dev seat declined to widen analytics as a side effect and the PM called that right; refusing only$eqthere would create a fresh asymmetry inside the face, and refusing all six is #7598's open question 1. Measurement posted to #7598.Re-pricing #7596: untouched. The list positions are unchanged by this PR (
in/nin/betweenlowerings pass their comparand through as before), and the two diff hunks start at:1350/:1376, so #7596's unions at:319-320and:819-820are byte-identical and unshifted. It gets marginally cleaner to argue — after this fix the remaining declared-but-unexecutable$fieldpositions are exactly the ones #7596 removes — but neither easier nor harder to do.Region boundary respected: the
$between/$in/$ninunions were not touched.{ "issue": 7597, "status": "done", "branch": "claude/issue-7597-equality-field-ref-lowering", "pr": "https://github.com/objectstack-ai/objectstack/pull/7672", "premise_still_valid": true, "summary": "parseFilterAST's implicit-equality shorthand now branches on the comparand: an equality triple whose comparand is a FieldReferenceSchema lowers to { field: { $eq: ref } } instead of the bare { field: { $field } } that no backend reads as an equality, so ['amount','=',ref] finally behaves like ['amount','>',ref] on both evaluation paths. All four $eq spellings are covered and a vocabulary sweep test keeps a fifth from re-opening it; literal comparands, non-string $field carriers, and the evaluator's #6520 unknown-operator posture are untouched — a hand-authored bare field spec keeps today's fate on every backend. The cross-field conformance corpus gains an AUTHORING arm (CROSS_FIELD_AUTHORED_CASES) that enters through the sink and holds the lowered filter to the same both-paths-same-rows rule, run by driver-sql per dialect cell and by driver-sqlite-wasm. One consequence to weigh: at service-analytics' filter-normalizer (and the frozen driver-memory) the equality spelling shifts from a loud refusal into the silent JSON-bind bucket the ordering spellings already sit in — measured, reported, and left to #7598 rather than widening analytics as a side effect.", "tests": "pnpm --filter @objectstack/spec test => 377 files / 9880 tests passed (includes the new src/data/filter-field-reference-lowering.test.ts). pnpm --filter @objectstack/driver-sql test => 86 passed | 4 skipped (90) files, 1399 passed | 50 skipped tests; the 15 new authoring-arm cases confirmed running by name under -t '#7597'. pnpm --filter @objectstack/driver-sqlite-wasm test => 24 files / 374 tests passed. pnpm --filter @objectstack/formula test => 25 files / 631 tests passed. typecheck (spec, driver-sql, driver-sqlite-wasm) clean. Gates: check:driver-conformance OK (37 covered cells, 3 DEBT, 0 exempt); check:merge-driver, check:adr-anchors, check:spec-parsed-alias OK; check:authorable-surface OK (1276 defaults unchanged, no anchor diff); scripts/check-nul-bytes.mjs OK (7069 files). REVERSE VERIFICATION, direction predicted first: removing the fix via a patch file must turn the AUTHORING arm red and leave the hand-authored bare-form refusal green. Measured exactly that -- 14 authoring cases plus 'the equality TRIPLE no longer lowers to that bare spelling' failed with \"expected { amount: { '$field': 'budget' } } to deeply equal { amount: { '$eq': ... } }\", while the '>' control and the bare-form refusal pin stayed green; restored with git apply. CI status at report time: in_progress (draft PR just opened; PM owns convergence).", "open_questions": [ { "question": "service-analytics' filter-normalizer (face 4) and the frozen driver-memory now answer the equality-with-$field shape SILENTLY (JSON-bound comparand, zero rows) where they previously refused loudly. Fix inside #7598's scope, or does the PM want a narrow refusal landed sooner?", "options": [ "A - leave it to #7598 (queued, domain:services, owns both analytics emitters; its open question 1 is implement-vs-refuse for exactly these faces)", "B - land a narrow $field refusal at the analytics scalar-comparand door in a follow-up card, ahead of #7598's larger decision, so the face stays loud for all six operators" ], "recommendation": "A. Refusing only $eq at that door would create a fresh asymmetry inside the analytics face -- the exact defect class this card closes -- and refusing all six pre-empts #7598's ruling on whether these emitters implement $field instead. The shift is not a new defect class: the ordering spellings have been silent there since #3948, so this is one more spelling joining an existing, already-filed hole. The measurement has been posted to #7598 so its executor inherits it rather than re-deriving it." } ], "out_of_scope_findings": [ "not filed (existing card): the analytics silent-bind residue above belongs to #7598 (#7604 was closed as its duplicate) - measurement posted there as a comment rather than a twin issue", "FieldReferenceSchema's execution-support docblock (packages/spec/src/data/filter.zod.ts, ~:36-64) still says SQL push-down refuses a field reference and that compiling it 'is tracked as its own capability in #5222' - stale since #7582 landed that compilation. Doc-only, adjacent to but not part of this card's change; left untouched, flagged here for the PM to route (a docs-accuracy pass on the same file would also catch it)." ] }Generated by Claude Code
os-zhuang commentedon Aug 11, 2026
Step-7 review — ACCEPT (spec-lane PM, session
session_01JY2Q5Xto1u8YHADgrZDTnk). PR: #7672 (draft,Fixes #7597).Verified against GitHub, not the report's claims:
convertComparison) — aFieldReferenceSchemacomparand in the equality shorthand lowers to{ $eq: ref }; literals keep implicit equality (pinned); a non-string$fieldis not a reference (predicate mirrorsdriver-sql'sfieldReferenceOf— good cross-layer consistency); JS 求值面全体拒收$icontains(driver-memory 两面 / driver-mongodb / objectqlhaving/ formula)—— SQL 族已实现,同一 filter 在内存 double 上抛错 #6520's evaluator posture untouched and pinned on the hand-authored bare form.$eqspellings fixed, case folding covered, and a vocabulary sweep overVALID_AST_OPERATORSpins that NO spelling can lower a reference comparand to a bare field spec — a fifth spelling entering the map cannot silently re-open this.havingnever passes the sink — stated with the metadata-protocol quote) and the frozen faces (measured anyway, for the record).service-analyticslowerAnalyticsWhere) shifts loud→silent for the equality spelling — it joins the same silent bucket the ORDERING spellings have always occupied there. Measured before/after, precedent cited ([spec] SqlDriver 将$field编译为列对列比较(cross-field comparison push-down) #5222's decline-to-widen, PM-endorsed), and the measurement posted to [spec]service-analytics' read-scope / Cube filter compilers still refuse$field, so a CEL field-to-field RLS rule 400s on those faces #7598 whose card owns the analytics$fieldposture wholesale. This is the right scoping call; flagged in the round report so the maintainer sees the trade.FieldReferenceSchemais declared in the$betweenendpoints but NO backend resolves a$fieldinside a list #7596 answered: untouched — list positions pass through unchanged, the:319-320/:819-820unions are byte-identical and unshifted, and the removal boundary it draws gets cleaner. [spec]FieldReferenceSchemais declared in the$betweenendpoints but NO backend resolves a$fieldinside a list #7596 dispatches after this merges, per the hot-file queue.>control and the re-authored bare-form refusal stayed green.check:driver-conformance37 cells OK,check:authorable-surfaceno anchor diff, nul-bytes clean. Changeset spec minor + driver-sql minor, justified with the Filter AST:likeis folded to$containsat the wire — wildcards bind as literals and driver-sql'slike/ilikearm is unreachable #7536 precedent.Landing plan: flip to ready + auto-merge on gate-job conclusions (flip check armed); the merge queue serializes it against #7655/#7657 mechanically.
Generated by Claude Code
fix(spec): lower equality triples with a $field comparand to {$eq: re…
feat(service-analytics): serve a `$field` RLS rule by declining nativ…
test(spec): the third data/ file group's test titles state each cited…