Repository navigation
[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
Description
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.
- Query: "AddRecordConfigSchema addRecord default enabled position bottom mode inline formView not applied renderer". 3 hits, all closed and on other keys: record:details sections cannot survive an empty record:
hideEmpty/collapsible/showBorderare honoured by the renderer but undeclared by the strict section schema #11289 (record:detailssection keys), PageComponentSchema.dataSource 在 list-view 之外仍无人消费:element:record_picker 丢 view,object-grid/form/kanban/calendar 等整条绑定不读(按 spec 写 dataSource 渲染出空) #6953 (PageComponentSchema.dataSource) and sort on ListView renders blank repeater in Edit View Config — z.union hides items from SchemaForm 🐛 #3379 (ListView sort editor). None covers this. - The objectui side is 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 itself.
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):
:1688draws Add only onschema.addRecord?.enabled === true;:717resolveAddRecordPlacementmaps an absent position to top;- nothing in
plugin-listreadsmodeorformView. 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;②③④是否翻转:否。
裁后执行:
- 裁 A: 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 改为实现卡(objectui
domain:ui),本卡关闭。 - 裁 B:
domain:spec席位一个 PR,包括默认值、mode/formView的 ADR-0087 转换、view.form.ts组合字段和生成物;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 只改对照行后关闭。 - 裁 C: spec PR 同 B 的默认值部分;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 实现
mode与formView。
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
objectstack-fleet commentedon Oct 20, 2026
席位意见(增量 1 · 列表「新建」入口:spec 默认值与渲染器不一致)· director seat (summon #45,
session_01Lg6GQ4xjqmvEzYv78d6H7i), read as batch #374 item 1, 2026-10-20T00:05ZOn 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 (
AddRecordConfigSchemaon views and pages), which is the decision box's floor (triage-duties.mdL40; 代裁人工地板 「协议/公开契约变化」).Premises re-run in this act — objectstack
origin/main043100210467, objectuiorigin/main90518cdb841a:view.zod.ts:1782–1790:enabled.default(true),position.default('bottom'),mode.default('inline'),formViewoptional, on astrictObject; the same schema is the pagelist-viewnode'saddRecord(page.zod.ts:1060);view.form.ts:178andpage.form.ts:165offer it to Studio. Holds.ListView.tsx:1688–1689and:717: Add draws only onenabled === true; an absentpositionmaps to top; no reader ofmodeorformViewanywhere underpackages/**except a type-alignment test asserting the default. Holds.active-projects.page.ts:36andcontact.view.ts:60(bothmode: 'form';formView'default' and 'create'), one lint fixture; hotcrm and cloud 0 by the card (unreachable from here). Holds.formView.content/docs/ui/create-vs-edit-form.mdx:88promises 「The binding isaddRecord.mode: 'form'+addRecord.formView: 'create'… NoformViews.create→ the create entry derives a default. Present → it wins for create.」 The showcasecontact.view.tsauthors a sparseformViews.createon that promise. objectui's create entry (app-shell/src/utils/recordFormNavigation.ts:218) readsobjectDef.form ?? objectDef.formViews?.defaultand neverformViews.createnoraddRecord.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.addRecord.modeas the add-record open-mode carrier; retiringmodetakes 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.createwhen present, else the default form), not a per-list selector; HOW it opens is the list's existingnavigation.modeif 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'oncontact) is honoured by convention, not by the key. ③addRecord: {}today draws nothing and says nothing; withenabledREQUIRED (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
enabledrequired and the create form chosen by convention. 口径:AddRecordConfigSchemakeepsenabled(required, no default) andposition(defaulttop;top/bottom/bothas the renderer draws them);modeandformViewretire through thespec-property-retirementkit 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 selectsformViews.createwhen the object declares it, else today'sform/formViews.default(one line inrecordFormNavigation.ts, pinned);create-vs-edit-form.mdx:88states 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 (plumbsmodeandformViewthrough 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) · objectuidomain: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 ofview-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 leavespm:blockedfor the one-line selection card with the ruled convention quoted; adomain:devxdocs card follows the spec landing.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Ruling: batch #374 item 1 · letter B′ · maintainer 「同意」 2026-10-20T02:21Z
Director seat, summon #45,
session_01Lg6GQ4xjqmvEzYv78d6H7i(GitHubos-justin; written asobjectstack-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
enabledrequired and the create form chosen by convention):AddRecordConfigSchema(packages/spec/src/ui/view.zod.ts, the same schema on the pagelist-viewnode) keeps two keys:enabled, REQUIRED with no default, soaddRecord: {}is refused at authoring and at publish instead of drawing nothing; andposition, defaulttop, valuestop/bottom/bothas the renderer draws them.modeandformViewretire through thespec-property-retirementkit: 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.active-projects.page.ts:36,contact.view.ts:60and the lint fixtureshowcase-shape.fixtures.ts:414losemode/formView;content/docs/ui/create-vs-edit-form.mdx:88states 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.formViews.createwhen the object declares it, else today'sform/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, themodedefault) changes when objectui's pin takes the spec release.addRecord; how the create form opens stays the renderer's, and a per-list open mode, if ever wanted, is the list's existingnavigation.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.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/formViewplumbed through the renderer for zero authored demand).Workload of the letter:
domain:spec· 1 PR, S–M (precedent: the ADR-0049 retirements ofview-strictness-batch18.test.ts) · objectuidomain:ui· 1 PR, S (objectstack-ai/objectui#13099) · ADR-0050 note, S.Execution:
needs-user-decision→pm:queuein 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 movespm:blocked→pm:queuein this act with the ruled convention quoted — the selection line does not wait on the spec PR.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Seat hold ·
domain:specseat 2 (#18549) · sessionsession_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 inpm:queue, and its item 6 binds the timing: "not before 18.0 GA".mainexited Changesets pre mode atc46b5f14cf, so anything that lands now ships in 18.0.0. Apm:queuecard is dispatchable by definition, so this card can only wait honestly aspm: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 is18.0.0-next.5.On restart, the dispatch shape is the ruling's items 1–5, quoted in the PR body:
AddRecordConfigSchema.enabledbecomes REQUIRED with no default, andpositiondefaults totop;modeandformViewretire through thespec-property-retirementkit (ADR-0087 drop conversions,retiredKey()tombstones, the two form composites, regenerated artefacts, the liveness ledger),Clause-②: yes (narrowing), breaking;active-projects.page.ts:36andcontact.view.ts:60, the lint fixtureshowcase-shape.fixtures.ts:414, andcontent/docs/ui/create-vs-edit-form.mdx:88;objectstack-ai/objectui#13099 (the renderer's create-form selection) does not wait on this card, per the ruling.
Generated by Claude Code