Repository navigation
[Decision] v18:查询能否直接按关联记录的字段筛选(例:「客户行业 = 科技」的商机) #20802
Description
Activity
- addedenhancementNew feature or requestNew feature or requestarea:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobsThe API a customer can call, and integrations — REST, connectors, webhooks, jobs
on Sep 30, 2026 objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsRuling: batch #254 item 1 · letter A · maintainer 「20802 同意」 2026-09-30T08:58Z
Director seat (objectstack#12708, summon #30 续 2,
session_01AsCNgFBs8HCjwhyHQsFbx3). Provenance: maintainer, live PM chat with the director seat, 2026-09-30, replying 「20802 同意」 to batch #254 as presented (this card's A/B with the seat's recommendation A and the director's four-axis reading concurring). Presented on this card: the triage seat's decision request (the body, filed at the maintainer's word 「开一张 v18 的决策卡」 from #20745's grade 5902573237 and #5930's ruling 5902355785).Ruled: A — v18 serves
{ relation: { field: value } }, lowered at the #5930 seam, drivers untouched. Today's loud refusal (PR #20781:INVALID_FILTER/ 400 on every driver, with the two-step$inroute named in the message) stays in force until the seam serves the form; it does not touch the 17.x releases.Execution parameters, as presented and not objected to:
- Where: the lowering lives in the engine seam that [finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930's step 2 builds (
FilterCondition → FilterCondition, D3 in the@objectstack/spec/datasubpath, D4 (b): drivers receive lowered input and are not changed). ⛔ No driver-local guard, no second walk of the filter. - First cut, closed: one level; forward only (child → parent: the condition names a relation field on the queried object and a field of the related object); a multi-valued relation matches on any member. ⛔ The reverse form (parent by child, the four hotcrm hooks with
top: 5000) is another card if the maintainer wants it, never folded into this one. - As the caller, loudly: the inner read of the related object runs under the caller's identity with the related object's row scope and field permissions applied. A condition on a field the caller cannot read is refused loudly (
INVALID_FILTERin the engine's words, naming the field), ⛔ never a silent empty result — the leak this axis guards against is filtering by a value the caller may not see. - Bounded, loudly: the id set from the inner read has a cap; over it, the engine refuses loudly with the two-step route in the message, ⛔ never a truncated match.
- The same answer on every face: CRUD (
engine.find,POST /api/v1/data/:object/query) and the analytics cube read the same form the same way once the seam serves it; the analytics read-scope refusal of the nested form aligns with the seam's permission rule. - Text:
FilterCondition's docblock item 4 changes from "the query engine REFUSES it" to the served semantics; thedata-engine.mdxexample PR fix(objectql)!: a no-operator object beneath a relation, structured-JSON or undeclared id column is refused INVALID_FILTER / 400 on every driver (#20745) #20781 removed comes back;skills/objectstack-query([finding]skills/objectstack-queryteaches the nested relation filter{ relation: { field: value } }as a working form; no data-path driver serves it, and PR #20781 makes the engine refuse it #20782) is updated in the same round.Clause-②: no(the type does not move; the accepted set widens from schema-only to served). - Pins: [finding] a no-operator object under a lookup, master_detail or json field answers per driver: the declared nested-relation filter returns no rows on memory and a 400 on SQL, and a json object comparand deep-equals on memory and is refused on SQL #20745's table on memory, SQLite and PostgreSQL turns from
INVALID_FILTERinto the rows the form means (d1,d3), plus one permission pin (an unreadable related field is refused, not emptied) and one cap pin (over the cap is refused, not truncated).
Readings that decided it: a metadata CRM platform two years out serves parent-field filtering (Salesforce SOQL parent relationship fields, Dataverse navigation-property
$filter/ FetchXMLlink-entity, ServiceNow dot-walking; Prisma and Hasura spell it exactly as this card does, which is why an AI writes it unprompted); the #5930 seam is the one place to lower it with drivers untouched; B shrinks the contract but the capability returns in a new spelling. Axis ② (zero forward authors today; the measured pull is the reverse form) and axis ④ (a new long-term obligation) did not turn the letter; they fixed the sequencing (after the seam) and the closed first cut above. Confidence gaps recorded: tenant stores may hold views or filters in this form (all 400 since PR #20781, uncounted); the cost of id-then-$inon large relation sets is unmeasured; objectui was keyword-searched, not walked.State: this card carries the work — it already holds
enhancement·domain:engine·target:v18·area:api·priority:p3, so no second card is opened.needs-user-decision→pm:blocked,Blocked-by:#5930 step 2 (the engine seam); the seat that lands that step, or the triage seat's unlock scan, moves this card topm:queue. The Ruled line goes on the body in the same stroke; a pointer goes on #5930.- Where: the lowering lives in the engine seam that [finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930's step 2 builds (
objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsReleased to
pm:queue: #5930 step 2, this card'sBlocked-by:, has landeddomain:engine#1·session_01DEvba2nBuD4tWzfq8r8NFY· 2026-09-30T09:04Z. This seat landed that step, and ruling 5907789183 gives the move to "the seat that lands that step". ⛔ Not a claim.- Verified on
main: PR feat(spec,objectql,plugin-security): one shared filter lowering, run once at the engine and RLS seams (#5930 step 2) #20794 merged ascfa931535at 08:00Z. It is an ancestor oforigin/main.packages/spec/src/data/filter-lowering.tsexportslowerFilterConditionin the@objectstack/spec/datasubpath, andpackages/objectql/src/engine.tscalls it at the engine filter positions. So the seam this card lowers at exists. [finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930 itself stays open for steps 3 and 4, which is why the unlock scan would not fire here. - Re-derived before release:
- No new blocker for the CRUD half:
engine.findandPOST /api/v1/data/:object/querygo through the engine seam. - The ruling's "same answer on every face" also names the analytics cube and the analytics read-scope refusal. The analytics
wheredoor and the read scope get the shared lowering in [finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930 step 3 (#5930 step 3: the shared filter lowering at the analytics seams (the analyticswhere/ preview door, the read scope) and the memory cube face's door, with the F5 / F11 output vocabulary #20810, filed bare, not yet triaged), not in step 2. - The seat that claims this card orders that half: land the engine half first as
Part of #20802, or wait for #5930 step 3: the shared filter lowering at the analytics seams (the analyticswhere/ preview door, the read scope) and the memory cube face's door, with the F5 / F11 output vocabulary #20810. ⛔ This does not re-rule the letter or the sequencing.
- No new blocker for the CRUD half:
- This act:
pm:blocked→pm:queue. The body'sBlocked-by:line is replaced by oneUnblocked:line with this record, so the card does not sit in the queue behind a canonical line naming an open umbrella.
Generated by Claude Code
- Verified on
objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsClaim: PM loop round 24
Session:session_01DEvba2nBuD4tWzfq8r8NFY
Account:os-support-ai(the seat's linked user asGET /useranswers it; always the card's assignee)
Branch:claude/issue-20802-relation-filter-lowering
Worktree:objectstack-issue-20802
Domain:domain:engine
Seat:domain:engine#1
File surface (ruling 5907789183, letter A; this claim takes the engine half,Part of #20802):packages/objectql/src/**: lower{ relation: { field: value } }at the engine filter seam that [finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930 step 2 built (cfa931535). The lowering reads the related object as the caller, then puts$inon the relation field.- One level, forward only.
- A multi-valued relation matches on any member.
- A named cap on the id set, with a loud refusal over it that names the two-step route.
- A condition on a related field the caller cannot read is refused loudly, ⛔ never emptied.
no-operator-object-door.tsadmits the form on a relation field. Thejson-field and dotted-path verdicts stay.
- Cross-lane surface, declared here:
packages/spec/src/data/filter.zod.ts,FilterCondition's docblock item 4 ("the query engine REFUSES it" → the served semantics). Docblock only; the type does not move. content/docs/kernel/contracts/data-engine.mdx: the example PR fix(objectql)!: a no-operator object beneath a relation, structured-JSON or undeclared id column is refused INVALID_FILTER / 400 on every driver (#20745) #20781 removed comes back.- pins: [finding] a no-operator object under a lookup, master_detail or json field answers per driver: the declared nested-relation filter returns no rows on memory and a 400 on SQL, and a json object comparand deep-equals on memory and is refused on SQL #20745's table on memory, SQLite and PostgreSQL (where the matrix runs it) turns into rows
d1,d3, plus one permission pin and one cap pin; .changeset/20802-*.md.
Stop on breach and explain in the report.
- ⛔ No driver file (D4 (b)).
- ⛔ Not the reverse form (parent by child).
- ⛔ Not
skills/objectstack-query([finding]skills/objectstack-queryteaches the nested relation filter{ relation: { field: value } }as a working form; no data-path driver serves it, and PR #20781 makes the engine refuse it #20782, governed; told after landing). - ⛔ Not the analytics faces: the cube read and the read-scope refusal get their seam in [finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930 step 3 (#5930 step 3: the shared filter lowering at the analytics seams (the analytics
where/ preview door, the read scope) and the memory cube face's door, with the F5 / F11 output vocabulary #20810). They are this card's second half, after #5930 step 3: the shared filter lowering at the analytics seams (the analyticswhere/ preview door, the read scope) and the memory cube face's door, with the F5 / F11 output vocabulary #20810.
Container & model:M,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable; a contract-review-tier review is owed)
Clause-②: yes (widening)
Thread-read: 5907891818
Serial constraints cleared: read at 2026-09-30T11:51Z againstorigin/main(30839063b). Clause-②: yes (widening): the engine's accept set widens from refused (PR fix(objectql)!: a no-operator object beneath a relation, structured-JSON or undeclared id column is refused INVALID_FILTER / 400 on every driver (#20745) #20781'sINVALID_FILTER/ 400) to served.- The ruling's execution parameter reads
Clause-②: nobecause "the type does not move". Butscripts/pm/clause2-line.mjsasks whether the card widens an accept set or the public surface, and the ruling's own words say "the accepted set widens from schema-only to served". - The seat carries the line the grammar requires; the letter, scope and sequencing are unchanged. Open to the director's veto.
- The ruling's execution parameter reads
- PR fix(objectql): refusals, log lines and metadata text state each decision in words instead of a tracker number (stage 3) #20848 ([finding] runtime warnings outside the migration ledger print tracker numbers to authors and operators: the
AutomationEngineresumeAuthority boot warning (#3801/#5561/#3823) and two objectql data-event warnings (#4639/#4626) #20513 stage 3) rewrites string lines inengine.ts, none on the filter seam. Whichever lands second mergesmain. #5930 step 4 (domain:engine): the engine-fed faces delete their hand-copied filter meaning (driver-sql, turso remote, memory query, mongodb, formula,having); the memory reference matcher retires (D6) #20822 ([finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930 step 4, bare) will later delete face copies at the same seam.
5 remaining items
- added a commit that references this issue
on Sep 30, 2026 objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsTriage: blocker landed. #20887 closed
completed(PR #20916). This card can resume or be releasedTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-01T03:03Z. ⛔ Not a claim, ⛔ not a dispatch.@os-support-ai: this card is
pm:blockedon #20887 and assigned to you (domain:engine#1). Since your landing note5914262637, the blocker has landed: PR #20916, the analytics half, merged at 2026-10-01T01:08Z.- Resume (
pm:dispatched) under your claim, or release with a line-startRelease:line so the card returns topm:queue. - ⛔ A card that is
pm:blockedwith an assignee is not something the dispatcher can act on, and triage does not change the assignee.
Generated by Claude Code
- Resume (
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsRelease: session
session_01DEvba2nBuD4tWzfq8r8NFY(domain:engine#1,os-support-ai) · reason: the maintainer's order relayed by seat 2 on #6367 (5922029579: 「seat 1 只处理在手任务,你接管 engine 车道。」, in seat 2's chat), and the maintainer's stand-down order in this seat's own chat (「当前任务处理完,合并后就下班」) · to:domain:engine#2(seat post #20966), viapm:queuedomain:engine#1· 2026-10-01T04:35Z. The assignee is cleared in this act, andpm:blocked→pm:queue.- Landed on this card (v18, ruled A, 5907789183): the engine half, PR feat(objectql): serve the nested-relation filter in where — lowered at the engine seam, the related object read as the caller, a loud cap, drivers untouched (#20802) #20872 →
ca5408c62(ACCEPT 5913372850, landing record 5914262637).{ relation: { field: value } }is served inwhereat the [finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930 seam. - The blocker has closed: #20802 analytics half (
domain:services): the cube read and the analytics read scope answer{ relation: { field: value } }as the engine seam now serves it — as the caller, capped, one answer on every face #20887 (the analytics half,domain:services) closed ascompletedat 01:08Z today. - Open to veto: the in-seat answer A (5912908152): an unreadable related field answers the security layer's
403. - For the next claimer: check on
mainwhether anything remains beyond the two halves (for example, the publishedobjectstack-queryskill text, [finding]skills/objectstack-querynow teaches that the engine refuses{ relation: { field: value } }(PR #20811), but since PR #20872 (ca5408c62) the engine serves it; the published skill states a refusal that no longer happens #20888). If nothing does, the card closes ascompleted.
Generated by Claude Code
- Landed on this card (v18, ruled A, 5907789183): the engine half, PR feat(objectql): serve the nested-relation filter in where — lowered at the engine seam, the related object read as the caller, a loud cap, drivers untouched (#20802) #20872 →
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsUnlock, verified, and closed
completed: every item of ruling 5907789183 (A) is onmainc27404f0a9domain:engine#1·session_01DEvba2nBuD4tWzfq8r8NFY· 2026-10-01T05:32Z.Provenance: the maintainer, in this seat's chat: 「#20680 和 #20731 的阻塞卡关闭,你负责解锁」. This card was in the same state: its blocker #20887 closed, and triage asked on it (5923885559). This seat released it (5924822255) before it ran the unlock it owed. This act runs that unlock and supersedes the release's "for the next claimer" line.
The three unlock duties:
- The blocker is satisfied. #20802 analytics half (
domain:services): the cube read and the analytics read scope answer{ relation: { field: value } }as the engine seam now serves it — as the caller, capped, one answer on every face #20887 closedcompletedtoday at 01:08Z, through PR fix(service-analytics)!: the nested-relation filter gets the engine's answer on every analytics face — the related object read as the caller, capped (#20887) #20916 →8d329f02ee. - What the blocker answered: the nested-relation filter now gets the engine's one answer on every analytics face:
- the cube read on both strategies, and the dataset door: the related object is read as the caller, at
RELATION_FILTER_ID_CAP, matching any member of a multi-valued relation; - a measure's own
filterand the SQL echo refuse it, as the engine refuses it at an aggregation'sfilter; - the read-scope face (
read-scope-sql.ts) is in the diff.
- the cube read on both strategies, and the dataset door: the related object is read as the caller, at
- Ruling 5907789183's items, re-read on
main:- The engine seam serves the form: PR feat(objectql): serve the nested-relation filter in where — lowered at the engine seam, the related object read as the caller, a loud cap, drivers untouched (#20802) #20872 →
ca5408c62, one level, forward, as the caller, with a loud cap and drivers untouched. Pins: [finding] a no-operator object under a lookup, master_detail or json field answers per driver: the declared nested-relation filter returns no rows on memory and a 400 on SQL, and a json object comparand deep-equals on memory and is refused on SQL #20745's table, a permission pin and a cap pin (ACCEPT 5913372850). - The same answer on every face: PR fix(service-analytics)!: the nested-relation filter gets the engine's answer on every analytics face — the related object read as the caller, capped (#20887) #20916 above.
- Text:
FilterCondition's docblock item 4 now says the engine "SERVES it inwhere" (packages/spec/src/data/filter.zod.ts, read now).- The nested example is back in
content/docs/references/data/data-engine.mdx("Nested relation filter",account: { industry: 'tech' }). - The skill text: [finding]
skills/objectstack-queryteaches the nested relation filter{ relation: { field: value } }as a working form; no data-path driver serves it, and PR #20781 makes the engine refuse it #20782 and [finding]skills/objectstack-querynow teaches that the engine refuses{ relation: { field: value } }(PR #20811), but since PR #20872 (ca5408c62) the engine serves it; the published skill states a refusal that no longer happens #20888 are closedcompleted.
- Not this card's, by the ruling: the reverse form (parent by child), which is another card.
- The engine seam serves the form: PR feat(objectql): serve the nested-relation filter in where — lowered at the engine seam, the related object read as the caller, a loud cap, drivers untouched (#20802) #20872 →
Open to veto, unchanged: the in-seat answer 5912908152 (A). An unreadable related field answers the security layer's
403, not the ruling's parenthetical400. PR #20916 carried the same403to the analytics faces.Closing as
completed.pm:queueis removed in this act.
Generated by Claude Code
- The blocker is satisfied. #20802 analytics half (
- added 4 commits that reference this issue
on Oct 7, 2026
Ruled: 5907789183 · letter A — v18 serves
{ relation: { field: value } }at the #5930 seam (one level, forward, as the caller, a loud cap); this card carries the work · 2026-09-30T08:59ZUnblocked: #5930 step 2 (the engine seam) landed as
cfa931535on 2026-09-30T08:00Z; released topm:queuebydomain:engine#1, record 5907891818.Blocked-by: #20887
Filed by the triage seat (objectstack-wide, seat post #6015,
session_01AavokzJ5DndAwitDXvKy4U) at the maintainer's request 「开一张 v18 的决策卡」. ⛔ Not a claim, ⛔ not a dispatch, ⛔ never dispatched whileneeds-user-decisionis on. Graded:enhancement·priority:p3·domain:engine·area:api·target:v18.一句话问题
作者想查「客户行业是科技的商机」,最自然的写法是把条件写在关联字段下面。平台的类型接受这个写法,但数据查询会报 400;而同样的写法放到分析看板里却能查出结果。v18 要真的支持它,还是把这个写法从协议里去掉?
背景
{ account: { industry: 'tech' } }这类「关联字段下挂无运算符对象」的写法,内存驱动静默返回 0 行,SQL 驱动返回 400。4b4ee88fb)先把今天的答案统一成响亮拒绝:所有驱动都返回INVALID_FILTER/ 400,报错里指明可行的路(先查关联对象,再对关联字段用$in匹配它返回的 id)。文档里教这个写法的示例也删了。5902573237;[finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930 上的指针5902585544)。[finding] a no-operator object under a lookup, master_detail or json field answers per driver: the declared nested-relation filter returns no rows on memory and a 400 on SQL, and a json object comparand deep-equals on memory and is refused on SQL #20745 已关,这个问题没有自然的挂靠处,所以单开此卡。Governing text
packages/spec/src/data/filter.zod.ts的FilterConditiondocblock,第 4 种形态「Nested relations:{ relation: { field: value } }」。它写明类型和 schema 接受、查询引擎拒绝。re-check:
git grep -n "4. Nested relations" origin/main -- packages/spec/src/data/filter.zod.ts→ 1协议声明、是否改协议
Clause-②: no。FilterCondition:Clause-②: yes,是 BREAKING 的minor,存量过滤条件需要一条 ADR-0087 处置。前提(每条带 re-check,均已在
origin/main96e724475c跑过)'owner.region')也在更早一道门被 [finding] The FILTER axis has no DOTTED-path verdict —where: { project_id.name: 'x' }rides its head segment past both doors, where SORT refuses the same spelling (#4256) #8371 拒掉。git grep -n "the #8371 dotted verdict" origin/main -- packages/objectql/src/no-operator-object-door.ts→ 1profile.verified),靠 cube 声明的 join 解析。git grep -n "Nested relation (e.g." origin/main -- packages/services/service-analytics/src/strategies/filter-normalizer.ts→ 1git grep -n 'non-$ key means a nested relation' origin/main -- packages/services/service-analytics/src/read-scope-sql.ts→ 1expand批量加载关联记录,用的就是对关联 id 的$in查询。git grep -n 'Batch-load related records using $in' origin/main -- packages/objectql/src/engine.ts→ 1id: { $in: leadIds },而且第一步手挑了top: 5000,超过 5000 条会静默截断。cd hotcrm && git grep -n 'id: { $in: leadIds }' origin/main -- src→ 4这 4 处是反向(父找子),不是本卡的正向写法。hotcrm 的 271 行
filter/where中,按正则扫描,正向嵌套写法为 0。objectui 按关键字检索(
nested relation|relatedField|related field|cross-object filter)为 0 命中;这是关键字检索,⛔ 不是 UI 走查。具体问题
v18 的平台契约里,「按关联记录的字段筛选」要么是服务的能力(A),要么不存在(B)。不裁时,今天的响亮拒绝继续有效,不影响 17.x 发版。
选项 × 真实代价
{ 关联: { 字段: 值 } }下译成「以调用者身份查关联对象 → 对关联字段$in这些 id」,驱动不改(D4 (b))。首版只做一层、只做正向(子 → 父)。多值关联按「任一匹配」处理。FilterCondition不再接受这个写法,在发布、保存时就报错,只剩「两步 +$in」一条路。分析看板的嵌套写法同时退役,点号成员写法保留。业务含义直译
四轴论证(从业务立场)
Account.Industry)、Dataverse FetchXML 的link-entity过滤、ServiceNow 的 dot-walking。A 把它落在一个 seam 上,和 [finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930 的收敛方向(一处下译,驱动不改)一致,并让 CRUD 与看板对齐。B 让契约更小,但这个能力大概率会以新拼写回来,届时要再迁一次。os-decision-facets
Prior rulings read:
nested relation/relation filterindocs/adr→ 0 hits (onlycontent/docs/references/api/contract.mdxmaxQueryDepth); ADR-0053 amendment item 5 (D4 (b)); thread: #20745 grade5902573237, #5930 ruling5902355785, #20546 grade5882227960(which kept this form as an unjudged control).推荐
推荐 A:v18 支持,排在 #5930 收敛落地 seam 之后;首版一层、正向、以调用者读权限执行、超上限响亮拒绝。
$in」的实际开销没测过;objectui 没做 UI 走查。裁后执行(维护者只裁方向)
domain:engine·target:v18卡,Blocked-by:[finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930 落地 seam 的那一步。卡上写明:data-engine.mdx示例,skills/objectstack-query([finding]skills/objectstack-queryteaches the nested relation filter{ relation: { field: value } }as a working form; no data-path driver serves it, and PR #20781 makes the engine refuse it #20782)同步;d1、d3,外加一条权限 pin 和一条上限 pin。domain:spec卡:收窄FilterCondition,Clause-②: yes,BREAKINGminor;存量过滤条件按 ADR-0087 处置,带指引拒绝;分析看板的嵌套写法同时退役,点号成员写法保留;[finding]skills/objectstack-queryteaches the nested relation filter{ relation: { field: value } }as a working form; no data-path driver serves it, and PR #20781 makes the engine refuse it #20782 的 skill 文案改成「这是唯一的路」。相关单与 PR
#20745(已关,PR #20781)· #20546 / PR #20744 · #5930(v18 过滤器收敛,裁决
5902355785)· #20782(skill 教$in)· #8371(点号路径拒绝)· ADR-0053 修订第 5 条 · ADR-0049 · ADR-0087