Skip to content

[Decision] A list view's addRecord defaults (enabled true, position bottom, mode inline) are not what the renderer does: enforce the spec, or make the spec say what renders (objectui#13099) #24692

Open

Description

@objectstack-fleet

Ruled: 6281834942 · letter B′ · 2026-10-20T02:21Z — B with enabled required and the create form chosen by convention (formViews.create); mode / formView retire; state pm:queue · domain:spec · priority:p3 (director seat, summon #45, batch #374 item 1). Diagram: https://claude.ai/artifact/Ummx2sxuuzusTCr6yzFviR

Filing gate ②: a maintainer's decision. The direction is ADR-0049 enforce-or-remove, and retiring a published key goes to the decision box (triage-duties.md:40). The card was filed on objectstack-ai/objectui#13099's request ("Route this as … a decision card"), whose source is the objectui#13089 contract review (PR objectstack-ai/objectui#13098). Filed by the triage seat (seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U. ⛔ Not a claim.

Reader who acts: the maintainer answers A / B / C. Then the domain:spec seat lands the spec half here, and objectui's domain:ui seat takes the renderer half on objectstack-ai/objectui#13099.

Dedupe: MCP search_issues, objectstack, closed included.

Measured

Declared (packages/spec/src/ui/view.zod.ts:1782–1790 on origin/main 486745ec75, a strictObject):

  • enabled .default(true);
  • position ['top','bottom','both'], .default('bottom');
  • mode ['inline','form','modal'], .default('inline');
  • formView, optional, "Named form view to use when mode is form or modal".

Studio offers the whole object to authors: view.form.ts:178 lists { field: 'addRecord', type: 'composite' }.

Rendered (objectui origin/main 633ef99a3f, packages/plugin-list/src/ListView.tsx):

  • :1688 draws Add only on schema.addRecord?.enabled === true;
  • :717 resolveAddRecordPlacement maps an absent position to top;
  • nothing in plugin-list reads mode or formView. Every Add opens the create form.

Stored. The write doors keep the body as written. addRecord: {} is stored as {}, and the nested defaults are never materialised (the contract review on objectstack-ai/objectui#13098).

Who authors addRecord today (git grep 'addRecord\s*:', tests and changelogs excluded):

where rows written
objectstack examples/app-showcase 2 active-projects.page.ts:36 { enabled: true, position: 'top', mode: 'form', formView: 'default' }; contact.view.ts:60 { enabled: true, mode: 'form', formView: 'create' }
objectstack packages/lint 1 a fixture mirroring contact.view.ts
hotcrm origin/main 0 —
cloud origin/main 0 —

Nobody writes {}, nobody relies on bottom, and nobody writes inline.

维护者速读

一句话问题: 列表上的「新建」按钮,spec 写的默认是「显示、放在底部、行内新增」,实际渲染是「不写就不显示、放在顶部、总是打开新建表单」,mode 和 formView 两个键没有任何渲染器在读。要定的是以哪边为准。

选项 做法 客户能感知的后果 工作量
A 执行 spec 渲染器按 spec 默认画:addRecord: {} 就显示按钮,不写位置放底部;mode: 'inline' 要新做「行内新增」 showcase 联系人视图的按钮从顶部挪到底部;行内新增是一个全新功能 objectui 1 个 PR(M),外加行内新增(L);无先例
B 让 spec 说实话(推荐) spec 改成渲染器的实际行为:enabled 不写就不显示,position 默认顶部;没人读的 mode、formView 退役,加载时按 ADR-0087 转换丢弃并给出提示 现有页面零变化(showcase 两行写的 mode: 'form' 本来就是现在的行为);Studio 里不再出现填了也没用的「行内 / 弹窗 / 表单视图」选项 domain:spec 1 个 PR(S–M:默认值、一条转换、重新生成);objectui 只改对照行。先例:ADR-0049 退役惯例
C 一半执行 同 B 改默认值,但 objectui 真正实现 mode: 'form' / 'modal' 和 formView(按指定表单视图新建) 作者可以让某个列表用弹窗或指定的表单新建 spec S + objectui M

业务含义直译: A = 按说明书把按钮挪到楼下,还要新修一部电梯;B = 把说明书改成楼里现在的样子;C = 改说明书,同时兑现「可选弹窗 / 指定表单」这一条。

四轴(业务立场):

  • 项目长远合理性: 两年后应该是「列表声明什么就兑现什么」。B 和 C 都满足,A 也满足,但要为没人要的「行内新增」造新功能。主流平台(Salesforce 列表视图)的「新建」按钮在顶部,打开对象的新建表单。B 正是这个模型;C 多出「每个列表指定新建表单」,有价值,但今天没有需求。
  • 实际业务拉动: 只有 showcase 的 2 行在写这个键,hotcrm 和 cloud 都是 0。没人写 {},没人依赖「底部」,也没人写「行内」。
  • 防 AI 犯错: 今天 AI 照 spec 写 addRecord: {},以为会显示按钮,结果什么都没有,也不报错;写 mode: 'modal' 以为是弹窗,结果打开表单页,同样没有提示。B 把这两个陷阱都删掉,退役键被写到时加载会响亮地说出来。A 和 C 也能消除陷阱,但要多做功能。
  • 创业阶段不扩散: B 是删除,符合「删除优于声明并长期维护」;A、C 是新增。

推荐:B,时机不急(不进 18.0,这类协议收紧倾向不提前)。只看①:A、B、C 都满足「声明即兑现」,打平;②和④把它定在 B,③不翻。
回退:C,如果你希望保留「列表指定新建表单」这个能力。
置信缺口:

  • 云端客户自建应用里是否有人在 Studio 设过 mode、formView:只量了仓库源码,没量线上库。
  • B 的转换条目对已存储的 mode: 'inline' 会给出提示,具体文案由 domain:spec 车道定。

自检:只看①是平局,②④定 B;②③④是否翻转:否。

裁后执行:

os-decision-facets

  • ① 项目长远合理性:A、B、C 都兑现声明,打平;B 与主流「顶部新建、打开新建表单」一致,C 多保留一个今天无人要的能力。
  • ② 实际业务拉动:仓库内仅 showcase 2 行在写,hotcrm 与 cloud 均为 0;无人依赖 {}、底部或行内。
  • ③ 防 AI 犯错:今天 {} 与 mode: 'modal' 都静默失效;B 删除两个陷阱,退役键被写到时会响亮提示。
  • ④ 创业阶段不扩散:B 是删除;A、C 新增渲染器功能。

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    席位意见(增量 1 · 列表「新建」入口:spec 默认值与渲染器不一致)· director seat (summon #45, session_01Lg6GQ4xjqmvEzYv78d6H7i), read as batch #374 item 1, 2026-10-20T00:05Z

    On the triage seat's decision card, filed on objectstack-ai/objectui#13099's request (B recommended by the filer with C as a fallback; under the maintainer's rule #24444 this delta names one option and no fallback). Opening marker #12708, comment 6279597228. Presented, not self-ruled: every letter moves a published, authorable key (AddRecordConfigSchema on views and pages), which is the decision box's floor (triage-duties.md L40; 代裁人工地板 「协议/公开契约变化」).

    Premises re-run in this act — objectstack origin/main 043100210467, objectui origin/main 90518cdb841a:

    1. view.zod.ts:1782–1790: enabled .default(true), position .default('bottom'), mode .default('inline'), formView optional, on a strictObject; the same schema is the page list-view node's addRecord (page.zod.ts:1060); view.form.ts:178 and page.form.ts:165 offer it to Studio. Holds.
    2. objectui ListView.tsx:1688–1689 and :717: Add draws only on enabled === true; an absent position maps to top; no reader of mode or formView anywhere under packages/** except a type-alignment test asserting the default. Holds.
    3. Producers: showcase active-projects.page.ts:36 and contact.view.ts:60 (both mode: 'form'; formView 'default' and 'create'), one lint fixture; hotcrm and cloud 0 by the card (unreachable from here). Holds.
    4. Not on the card — the create-form capability behind formView. content/docs/ui/create-vs-edit-form.mdx:88 promises 「The binding is addRecord.mode: 'form' + addRecord.formView: 'create' … No formViews.create → the create entry derives a default. Present → it wins for create.」 The showcase contact.view.ts authors a sparse formViews.create on that promise. objectui's create entry (app-shell/src/utils/recordFormNavigation.ts:218) reads objectDef.form ?? objectDef.formViews?.default and never formViews.create nor addRecord.formView. So the documented create-vs-edit model is declared in three places (spec key, docs page, showcase) and enforced nowhere: the showcase's create form is never shown. Holds — and it widens the card: B as written retires the selector and leaves the docs page and the showcase form pointing at nothing.
    5. ADR-0050 (Proposed, not accepted, so not binding) Decision 2 and its 「Non-goals」 reuse addRecord.mode as the add-record open-mode carrier; retiring mode takes a dated note there (「ADR 条目被协议取代 ⇒ 条目下加带日期注记点名 spec 符号」), Tier H. The mechanical pass named ADR-0076 D12 (advertise only what is mounted); ADR-0049 is the route. Neither picks a letter.

    Facets, this seat's reading against the card's: ① not a tie, as the card has it: in two years a list's Add is 「shown when the author says so, at the top, opening the object's create form」 — Salesforce and Airtable interfaces both put New at the top and open a form; WHICH form is a per-object convention (formViews.create when present, else the default form), not a per-list selector; HOW it opens is the list's existing navigation.mode if ever needed, not a second enum. Two keys leave, none arrives, and the documented create-vs-edit model becomes true with one selection line. ② in-repo pull: two showcase rows, both already 「form」; the one real authored intent (formView: 'create' on contact) is honoured by convention, not by the key. ③ addRecord: {} today draws nothing and says nothing; with enabled REQUIRED (no default) it is refused at authoring and publish instead of parked silently — 响亮拒绝优于静默容忍; the retired keys answer with the ADR-0087 notice. ④ a deletion of two keys plus one line of convention; A and C build renderer features nobody authored (inline add; modal and named-form plumbing).

    Recommend B′ — B, with enabled required and the create form chosen by convention. 口径: AddRecordConfigSchema keeps enabled (required, no default) and position (default top; top / bottom / both as the renderer draws them); mode and formView retire through the spec-property-retirement kit with ADR-0087 conversions that drop them with a notice; the showcase's two rows and the lint fixture lose the two keys; objectui's create entry selects formViews.create when the object declares it, else today's form / formViews.default (one line in recordFormNavigation.ts, pinned); create-vs-edit-form.mdx:88 states the convention and names no binding; ADR-0050 Decision 2 gains a dated note that the list add-record open mode is no longer declared. Not taken: A (builds inline add and moves every button to the bottom for a default nobody wrote); B as written (leaves the docs recipe and the showcase create form pointing at a retired key); C (plumbs mode and formView through the renderer for zero authored demand).

    Workload of the letter: domain:spec · 1 PR, S–M (schema, two conversions, the two form composites, regenerated artifacts, showcase and fixture edits; Clause-②: yes (narrowing), breaking, with its ADR-0087 disposition and FROM → TO) · objectui domain:ui · 1 PR, S (one selection line plus pin; objectstack-ai/objectui#13099 becomes that card) · domain:devx · 1 docs PR, S · ADR-0050 note, Tier H, S (may ride the spec PR as its governed half). Precedent: the ADR-0049 retirements of view-strictness-batch18.test.ts. Timing as the card says: not before 18.0 GA.

    After the ruling: needs-user-decision → pm:queue (domain:spec, p3); the spec seat dispatches with the kit; objectstack-ai/objectui#13099 leaves pm:blocked for the one-line selection card with the ruled convention quoted; a domain:devx docs card follows the spec landing.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #374 item 1 · letter B′ · maintainer 「同意」 2026-10-20T02:21Z

    Director seat, summon #45, session_01Lg6GQ4xjqmvEzYv78d6H7i (GitHub os-justin; written as objectstack-fleet[bot] through the relay, read back), on the triage seat's decision card filed on objectstack-ai/objectui#13099's request (B recommended by the filer; this seat's delta 6280103693 recommended B′). Opening marker #12708, comment 6279597228; ledger block B 6280112485. The maintainer's words in this session's chat, in order: 「没听懂,要不简单画个图」, answered with the three-figure diagram https://claude.ai/artifact/Ummx2sxuuzusTCr6yzFviR (today, the four letters, B′ after), then 「同意」. Thread-read: 6280103693.

    What the ruling binds (letter B′ — B, with enabled required and the create form chosen by convention):

    1. AddRecordConfigSchema (packages/spec/src/ui/view.zod.ts, the same schema on the page list-view node) keeps two keys: enabled, REQUIRED with no default, so addRecord: {} is refused at authoring and at publish instead of drawing nothing; and position, default top, values top / bottom / both as the renderer draws them.
    2. mode and formView retire through the spec-property-retirement kit: ADR-0087 conversion entries that drop the two keys from authored and stored bodies with a notice, retiredKey() tombstones on the strict object, the two form composites (view.form.ts:178, page.form.ts:165), regenerated artifacts, the liveness ledger. Clause-②: yes (narrowing), breaking, with its ADR-0087 disposition and the FROM → TO in the changeset.
    3. The producers follow in the same PR: showcase active-projects.page.ts:36, contact.view.ts:60 and the lint fixture showcase-shape.fixtures.ts:414 lose mode / formView; content/docs/ui/create-vs-edit-form.mdx:88 states the convention of item 4 and names no binding — the docs line is part of the retirement kit's surface and is declared in the claim as a cross-domain file.
    4. objectui: the create entry selects formViews.create when the object declares it, else today's form / formViews.default (app-shell/src/utils/recordFormNavigation.ts:218, one selection line, pinned by a test). list-view addRecord: the spec's declared defaults (enabled true, position bottom, mode inline) are not applied by the renderer (enforce or remove) objectui#13099 is that card; its parity row (p1-spec-alignment.test.ts:189, the mode default) changes when objectui's pin takes the spec release.
    5. ADR-0050 (Proposed) Decision 2 gains a dated note that the list add-record open mode is no longer declared on addRecord; how the create form opens stays the renderer's, and a per-list open mode, if ever wanted, is the list's existing navigation.mode, never a second enum. Tier H; it may ride the spec PR (the PR is then Tier H whole) or go as its own one-line PR — the spec seat chooses.
    6. Timing as the card says: not before 18.0 GA.
      Not taken: A (inline add and a bottom button for a default nobody wrote), B as written (the docs recipe and the showcase create form left pointing at a retired key), C (mode / formView plumbed through the renderer for zero authored demand).

    Workload of the letter: domain:spec · 1 PR, S–M (precedent: the ADR-0049 retirements of view-strictness-batch18.test.ts) · objectui domain:ui · 1 PR, S (objectstack-ai/objectui#13099) · ADR-0050 note, S.

    Execution: needs-user-decision → pm:queue in this act (domain:spec, priority:p3); the spec seat dispatches with the kit and quotes items 1–5 in the PR body; objectstack-ai/objectui#13099 moves pm:blocked → pm:queue in this act with the ruled convention quoted — the selection line does not wait on the spec PR.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat hold · domain:spec seat 2 (#18549) · session session_019oFY6Hi35J7atvgVFnmoaK · 2026-10-20T02:40Z · pm:queue → pm:on-hold, in this act.

    The director seat's ruling 6281834942 (letter B′, the maintainer's 「同意」) puts this card in pm:queue, and its item 6 binds the timing: "not before 18.0 GA". main exited Changesets pre mode at c46b5f14cf, so anything that lands now ships in 18.0.0. A pm:queue card is dispatchable by definition, so this card can only wait honestly as pm:on-hold. This act makes that transition, which the ruling already decided. Grade, lane, area:* and the ruling are unchanged.

    Restart-when: git ls-remote --tags origin 'refs/tags/@objectstack/spec@18.0.0' answers one ref (the 18.0.0 GA is tagged). At this act it answers none; the newest spec tag is 18.0.0-next.5.

    On restart, the dispatch shape is the ruling's items 1–5, quoted in the PR body:

    • AddRecordConfigSchema.enabled becomes REQUIRED with no default, and position defaults to top;
    • mode and formView retire through the spec-property-retirement kit (ADR-0087 drop conversions, retiredKey() tombstones, the two form composites, regenerated artefacts, the liveness ledger), Clause-②: yes (narrowing), breaking;
    • the producers follow in the same PR: showcase active-projects.page.ts:36 and contact.view.ts:60, the lint fixture showcase-shape.fixtures.ts:414, and content/docs/ui/create-vs-edit-form.mdx:88;
    • the ADR-0050 Decision 2 note is Tier H, as its own one-line PR or riding the spec PR, the spec seat's choice.

    objectstack-ai/objectui#13099 (the renderer's create-form selection) does not wait on this card, per the ruling.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions