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
formula/objectql: relationship traversal in predicates — a validation rule or visibility predicate reads one hop through a lookup (record.crm_account.type); replaces the removed os.lookup declaration (#18318, batch #148) #18682
Filed by the director seat (summon #24, session_01Wj1HUjzyeiBQ8atRf1ZhaL) executing batch #148 item 1, letter B on #18318 (maintainer 「同意」, ruling 5716041368): the never-bound EvalContext.api declaration is removed there; the real need behind it is filed here, judged by the maintainer's standard for a development platform (「根据开发相关的业务系统会不会有需求…主流平台会不会提供」, seat-post record 5715688324).
The need
A validation rule or visibility predicate on one object needs to read a field of the record it points to — record.crm_account.type on crm_opportunity. Mainstream platforms provide exactly this (Salesforce cross-object formulas and validation rules read parent fields through the relationship; Dataverse calculated columns read the related row). Enterprise apps built on this protocol will write it as a matter of course. The reference app already tried: hotcrm #1915 (REQ-0003) needs a gate on crm_opportunity that reads the owning account's category; measured on the current engine it fails with runtime: No such key: type because checkPredicate() evaluates with { record, previous } only — the lookup field carries an id, not the related row.
Scope — relationship traversal, ⛔ not query functions
One hop through a lookup / master-detail field: record.<lookup_field>.<field> resolves to the related record's field value in predicate evaluation (validation rules, visibleWhen / readonlyWhen / requiredWhen, RLS-adjacent predicates ⛔ excluded in v1 — see below).
Resolution is data supplied to the evaluation context, not I/O inside CEL: the call site that has the query engine loads the referenced fields the predicate names (static analysis of the expression tells it which lookups and which fields) before evaluation, so stdlib.ts's purity invariant (every registered function pure once now is pinned; objectstack build byte-stable) holds. ⛔ No os.lookup(...) / os.exists / os.count — those were the removed declaration's shape and stay removed.
N+1 is bounded by construction: one hop, only the fields the expression names, loaded once per evaluation.
Depth: one hop in v1; a second hop is a measured follow-up, not a v1 option.
Clause-②: yes (published predicate surface widens); contract review at tier; changesets on @objectstack/formula, @objectstack/objectql (or wherever checkPredicate assembles the context) and @objectstack/spec if the expression grammar's documentation changes.
Sequencing
Blocked on #18545 (can + permission data into EvalContext, ruled A): both change how the evaluation context is assembled at buildScope / checkPredicate; this lands after it on the same seam. hotcrm #1915 waits on this card.
Acceptance (ADR-0136 D2.4)
A checklist item under records-forms (validation rule reading a parent field: passes when the parent field matches, refuses the write when it does not, faults loudly when the user cannot read the parent field) plus a dogfood case on the showcase app; hotcrm #1915's gate is the reference use.
Dedup words: relationship traversal predicate · parent field in validation rule · record.crm_account.type · checkPredicate context · No such key lookup hop · #18318 · hotcrm #1915
Filed by the director seat (summon #24,
session_01Wj1HUjzyeiBQ8atRf1ZhaL) executing batch #148 item 1, letter B on #18318 (maintainer 「同意」, ruling 5716041368): the never-boundEvalContext.apideclaration is removed there; the real need behind it is filed here, judged by the maintainer's standard for a development platform (「根据开发相关的业务系统会不会有需求…主流平台会不会提供」, seat-post record 5715688324).The need
A validation rule or visibility predicate on one object needs to read a field of the record it points to —
record.crm_account.typeoncrm_opportunity. Mainstream platforms provide exactly this (Salesforce cross-object formulas and validation rules read parent fields through the relationship; Dataverse calculated columns read the related row). Enterprise apps built on this protocol will write it as a matter of course. The reference app already tried: hotcrm #1915 (REQ-0003) needs a gate oncrm_opportunitythat reads the owning account's category; measured on the current engine it fails withruntime: No such key: typebecausecheckPredicate()evaluates with{ record, previous }only — the lookup field carries an id, not the related row.Scope — relationship traversal, ⛔ not query functions
record.<lookup_field>.<field>resolves to the related record's field value in predicate evaluation (validation rules,visibleWhen/readonlyWhen/requiredWhen, RLS-adjacent predicates ⛔ excluded in v1 — see below).stdlib.ts's purity invariant (every registered function pure oncenowis pinned;objectstack buildbyte-stable) holds. ⛔ Noos.lookup(...)/os.exists/os.count— those were the removed declaration's shape and stay removed.Clause-②: yes(published predicate surface widens); contract review at tier; changesets on@objectstack/formula,@objectstack/objectql(or wherevercheckPredicateassembles the context) and@objectstack/specif the expression grammar's documentation changes.Sequencing
Blocked on #18545 (
can+ permission data intoEvalContext, ruled A): both change how the evaluation context is assembled atbuildScope/checkPredicate; this lands after it on the same seam. hotcrm #1915 waits on this card.Acceptance (ADR-0136 D2.4)
A checklist item under
records-forms(validation rule reading a parent field: passes when the parent field matches, refuses the write when it does not, faults loudly when the user cannot read the parent field) plus a dogfood case on the showcase app; hotcrm #1915's gate is the reference use.Dedup words: relationship traversal predicate · parent field in validation rule ·
record.crm_account.type·checkPredicatecontext ·No such keylookup hop · #18318 · hotcrm #1915⬆️ 行首
Blocked-by: #18545由分诊席于 2026-09-20T14:26Z 移除 —— #18545 现读closed/completed,阻塞已解除,卡早已是pm:queue,只有这条机器可读行被落下。⛔ 正文其余部分一字未动;车道改判与判据见issuecomment-5750405280。Generated by Claude Code