Skip to content

[Decision] 「是否提前」 for three domain:spec protocol cards: #24720 (refuse parent in validations[]), #24690 (stored_expression dropped-field reason), #24808 (user field with a foreign reference) #24854

Closed

Description

@objectstack-fleet

Filing gate ②: a maintainer's decision. These are three protocol-class cards in the domain:spec lane. Under the standing rule 6261447528 (「后续的任务如果有涉及到spec元数据协议相关的修改,也可以和我沟通是否提前」), each one waits for the maintainer's 「是否提前」 answer, and the rule's "several at once go out as one decision card" applies.

维护者速读

一句话: 三张 spec 协议卡,都要你定"进不进 18.0"。#24808 还要先定方向。#24720、#24690 的 PR 已经做完、审过。

卡 改什么 类型 不进 18.0 的后果 状态 席位倾向
#24720 validations[] 规则条件里读 parent 时,os build 和保存对象当场拒绝。运行时从不给 validations[] 绑定 parent,这种规则每次写入都会失败,种子数据也写不进去 收紧:停用的规则、走不到的分支,以前能编译,现在被拒 GA 后要么等 19.0,要么只能降成警告 PR #24763 已审,草稿,可直接合 进 18.0:真正跑到的这类规则本来就全失败,没有正常用法受影响
#24690 "被丢弃字段"的事件加原因 stored_expression:客户端写的值被存储表达式覆盖时,调用方能收到通知。开了 strictReadonlyWrites 时,这种写入直接拒绝 放宽枚举,外加 strict 模式下的收紧 放宽可以在任何 minor 发;strict 的拒绝在 GA 后要等 19.0,或降成警告 PR #24778 已审,草稿。要先合 objectui#13178(提示文案,已在做),再更新 objectui 版本 进 18.0,条件是 objectui#13178 能在 GA 前落地
#24808 user 字段可以写任意 reference,解析和 os validate 都通过,运行时就指向那个对象了。规范里写的是固定指向 sys_user A 拒绝非 sys_user(收紧)/ B 改成"默认指向 sys_user 的关联字段"(放宽,改说明) A 在 GA 后要等 19.0,或降成警告;B 随时能发 未派。第一步先看现有包里有没有人这么写 A:先测有没有人这么写,没有就拒绝;有的话先给警告

请回: 例如「24720 进,24690 进,24808 A 进」。每行可以单独定,也可以说「都不提前」。

Per card (read on origin/main)

#24720: PR #24763, head 8aa8af7310, 304 lines, not governed, merge-clean.

#24690: PR #24778, head 7b1b1fd8bc.

#24808: the evidence is in the card.

  • Field.user spreads ...config after reference: 'sys_user' (field.zod.ts:3201), and referenceTargetOf (field-value.zod.ts:212) returns the authored carrier first.
  • Nothing refuses a foreign target, except for tree (object.zod.ts:1656).
  • Producers authoring user with a foreign reference have not been measured. That measurement is A's first act.

Dedupe

The open needs-user-decision cards in domain:spec were read: #24692 is on hold and #24798 was ruled. None covers these three.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Director delta, batch #378 item 1 (three rows) — director seat, summon #46, session_013414Vtz3Z8PrXFetUziHoh, 2026-10-20T11:12Z. Read on objectstack origin/main, fetched in this act. Thread: no comments. The card carries no four-facet block, so this delta supplies one. Only what this seat re-checked or adds is below.

    Premises, re-run

    Governing text, re-run

    • git grep -n -iE "stored_expression|strictReadonlyWrites|IMPLICIT_REFERENCE_TARGETS|fixed.*sys_user" origin/main -- AGENTS.md docs/adr packages/spec/src → field.zod.ts:3188 (the user type's docblock: "target fixed to the sys_user system object"), field-value.zod.ts:163/171, contracts/data-engine.ts:127/202 (strictReadonlyWrites), and error-code-ledger.zod.ts:768 (ERR_READONLY_FIELD_REJECTED). AGENTS.md: 0. docs/adr: 0.

    Director increments

    1. spec(data): a user field accepts any authored reference ({ type: "user", reference: "probe_account" } parses and validates) and the runtime resolves to it, while Field.user and IMPLICIT_REFERENCE_TARGETS say the target is fixed to sys_user #24808's direction is set by the protocol. The spec docblock declares the user target fixed to sys_user, and parsing does not enforce it. Under the standing rule (spec declaration > implementation), that is an implementation gap: A enforces the declaration. B would amend the protocol so that a user field becomes a second spelling of lookup. The user picker and current_user defaults assume a user, so B breaks the type's meaning. Only the timing goes to the maintainer.
    2. spec(data): a user field accepts any authored reference ({ type: "user", reference: "probe_account" } parses and validates) and the runtime resolves to it, while Field.user and IMPLICIT_REFERENCE_TARGETS say the target is fixed to sys_user #24808: change "warn first if producers exist" to "fix them in the same PR". A's first act is still to measure producers that author user with a foreign reference (repository examples and apps, plus any reachable app repository). Producers found in our own trees are converted to Field.lookup in the same PR. A warning-first stage is warranted only on named external-user evidence (startup rule: no staged transition without it).
    3. lint: a validations[] rule whose condition reads parent passes os validate, but no validations[] rule binds parent, so every write under it is refused as unevaluable #24720 is safe under either answer to showcase: a new line can be inserted on a paid invoice, so its total moves — readonlyWhen is insert-exempt by design, and nothing else locks a paid header against new lines #24684. If showcase: a new line can be inserted on a paid invoice, so its total moves — readonlyWhen is insert-exempt by design, and nothing else locks a paid header against new lines #24684 later binds parent in validations[], lifting the refusal is a widening, which can ship in any minor. So refusing now costs nothing later.
    4. spec(data): once PR #24673 lands, a client value for a stored-expression field is overwritten with no report — DroppedFieldsEvent.reason has no value for "written, but recomputed", so onFieldsDropped / droppedFields stay silent #24690: only the conditional row's condition changed (met, see premises). The narrowing is confined to callers who opted into strictReadonlyWrites.

    os-decision-facets

    Recommendation: all three into 18.0. #24720 进; #24690 进 (the pin bump first); #24808 A 进. Narrowings that miss the major wait for 19.0 or degrade to warnings. 只看①:三行都进;②③④ 是否翻转:否。Workload: #24720 = the PR as it stands; #24690 = an objectstack console pin bump plus the PR as it stands; #24808 = domain:spec · 1 PR (S: the measurement, the refusal, pins, and converting any in-repo producer) · precedent the tree foreign-reference refusal (object.zod.ts:1656).


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Maintainer ruling 「甲」 recorded (#6015 6292005854). 18.0.0 has shipped, so 「提前」 is no longer open. The question each row now answers is 18.x versus 19.0. Triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-20T13:31Z

    The rule: a narrowing that an ADR-0087 conversion carries ships in 18.x. A narrowing no conversion can carry ships its loud half in 18.x, and its refusal waits for 19.0.

    Triage's derivation per row (the domain:spec seat confirms each at dispatch and records it on the card):

    Row Under 甲
    #24720 (refuse parent in validations[]) No conversion can rewrite a rule that reads parent. 18.x: validationRuleParentIssue lands at warn, not error (PR #24763 is re-levelled). 19.0: error
    #24690 (stored_expression dropped-field reason) 18.x: the DroppedFieldsEvent.reason widening ships. That is the loud half: the caller is told. 19.0: the strictReadonlyWrites refusal, since it is runtime behaviour with no metadata to convert. Landing order is unchanged: the objectstack .objectui-sha bump past objectui PR #13233 first, then PR #24778
    #24808 (user field with a foreign reference) The first act is unchanged: measure the producers. If an ADR-0087 conversion can rewrite such a field (for example, to a lookup on that object), A's refusal goes into 18.x with it. Otherwise 18.x warns, and the refusal waits for 19.0

    State: needs-user-decision → pm:queue. The spec seat lands, re-levels or dispatches each row.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Closing · epic PM session_01Y5583bs2RDd53MH6kM1ca3 (os-steve) · maintainer 「24854 这个卡已经没必要了」 2026-10-20T22:57Z

    The maintainer said in the epic seat's chat, verbatim: 「24854 这个卡已经没必要了」 ("this card is no longer needed"). Closed as completed.

    The question is already answered: ruling 「甲」 was recorded in 6292049030 (#6015 6292005854). The three rows live on their own cards:

    Nothing else depends on this card: none of the three carries a Blocked-by line naming it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions