Repository navigation
spec: a slotted record page keeps six slots — header, actions, alerts, highlights, details, discussion — and the tabs slot is retired; a page that needs its own tab strip is a kind: full page #27053
Description
Part of the record-page-v3 epic #26676 (v3 child 4 of 8). Contract card (spec lane); claimed from the epic session on the maintainer's instruction in the footer.
Source (origin/main 7bb8084590)
packages/spec/src/ui/page.zod.ts slots (strict object, ~:2121) admits header, actions, alerts, highlights, details, tabs, discussion (aliases activity / chatter → discussion, related / relatedLists → tabs, fields / body → details); checkPageSlotPair (:1262, #22568) refuses details + tabs together. buildDefaultPageSchema.ts:~1130-1215 composes: a tabs slot replaces the whole synthesized strip (related / approvals / attachments / history included — the author must re-add them). With the column tiers (#26758) a tabs slot bypasses the tiers (RecordDetailView.tsx:825 pageColumnsEligible): the page is tabbed at every width. HotCRM uses slotted once (account: header + discussion), never tabs.
Target
slots.tabsis retired under thespec-property-retirementkit: tombstone viaretiredKey()with the prescription 「the record page composes its tabs / columns from the object's roles and relationship flags; to change which related lists appear or their order, setrelatedList/relatedList: 'primary'on the child's reference field; a page that needs its own strip iskind: 'full'」; therelated/relatedListsaliases go with it;checkPageSlotPairand its test retire with the pair; ADR-0087 disposition (D2 conversion that drops the slot and, when it was the only slot, leaves an empty slotted page = the synthesized default; D3 entry for the judgement the edit cannot make — whether that page should becomekind: full).- The synthesizer composes the strip / columns from the six remaining slots only;
RecordDetailView'spageColumnsEligibleno longer needs thetabsbranch. - Docs:
ui/content/docs/guide/slotted-pages.mdslot menu, the generated references, the skill bullet (skills/objectstack-ui/**— governed, Tier H).
File surface
packages/spec/src/ui/page.zod.ts + the retirement kit files, spec tests; ui/packages/plugin-detail/src/synth/buildDefaultPageSchema.ts, ui/packages/app-shell/src/views/RecordDetailView.tsx (one gate line), ui/content/docs/guide/slotted-pages.md, skills/objectstack-ui/rules/*.md (one bullet), changesets (narrowed, BREAKING with migration). Clause-②: no (narrowing); Metadata-protocol: narrowed.
Acceptance
safeParseofslots: { tabs: … },related,relatedListsfails with the prescription (code+status+ first sentence); the six live slots parse; a stored slotted page withtabsreplays through the conversion.- HotCRM account's slotted page still renders header + discussion overrides with the column tiers on.
- Tree-scoped absence pin: nothing in the repo authors a
tabsslot.
Rulings (maintainer, chat in the filing session, 2026-10-28 — verbatim, not re-decidable here)
- Record-page model (2026-10-27): 「1. 一个对象一个默认打开方式:默认抽屉(带展开整页),
page只给显式声明的对象,modal退役,split / popover 变成用户个人偏好;抽屉和整页是同一张页在两个宽度。」 - On the resident timeline column: 「时间线是不是太突出了,这个只适合部分对象吧?适合做所有业务对象的默认布局吗」 and then 「时间线是否显示,是否可以切换,比如当前版本的 Claude code,顶部有很多切换图标」 — the column's presence is a per-user toggle with an object-derived default, never metadata.
- On the related column's cost: 「关联都放在右侧,记录打开时是不是会很慢,因为需要加载所有的关联子表。」 — the related column loads counts first, rows on demand, and never blocks the details.
- On mobile: 「还要考虑手机端的效果。」
- On the definition surfaces: the PM's keep / narrow / retire table was put to the maintainer (keep object roles, relationship flags, six slotted slots and
kind: full; retire thetabsslot and the deadBuildPageOptionshints; fold the quick-look path into the one record page) and approved with the instruction in the footer.
Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff on 2026-10-28 under epic #26676 (record page v2 → v3), from the record-page definition-surface inventory on objectstack main 7bb8084590 and the maintainer's rulings in that session. The maintainer's instruction to file and dispatch, verbatim: 「同意,以上界面相关的需要我确认的你负责立卡派发,如果有可能可以启动云会话,开发完你来确认。」 Design evidence: the design canvas boards 「记录页 v3」 row (RecordPageV3, RecordPageV3NoTimeline, RecordPageRef, RecordDrawerV3, RecordMobile) — exported to the never-merged branch named in the epic parent once this batch is filed.
Activity
objectstack-fleet commentedon Oct 28, 2026
Claim: PM loop round 2 · 2026-10-28T09:09Z
Session:
session_01WGufzfhobWEgUUrjz4rrbhAccount:
os-support-aiBranch:
claude/project-thread-tc4fe5(card threadsession_01WGufzff3QiP6kmtajVnKnq. The platform assigns the thread's branch and the thread can push only that one, so the branch is written as measured instead ofclaude/issue-27053-<slug>.)Worktree:
objectstack-issue-27053Domain:
domain:specSeat:
domain:spec#1File surface:
packages/spec/src/ui/page.zod.ts:slots.tabsand itsrelated/relatedListsaliases becomeretiredKey()tombstones carrying the card's prescription.checkPageSlotPairand its test retire with the pair.spec-property-retirementkit files: an ADR-0087 D2 conversion that drops the slot (an emptied slotted page is the synthesized default) and a D3 entry for thekind: fulljudgement.ui/packages/plugin-detail/src/synth/buildDefaultPageSchema.ts(thetabsbranch) andui/packages/app-shell/src/views/RecordDetailView.tsx(thepageColumnsEligiblegate line).ui/content/docs/guide/slotted-pages.md, the generated references, and the oneskills/objectstack-ui/**bullet that names thetabsslot (Tier H). The wider skills and docs pass stays with skills(objectstack-ui) + docs: teach the record page as it is now — object roles produce the page, six slotted slots,kind: fullas the escape hatch, drawer default withpageby declaration, the column tiers and the reader's own toggles — and stop namingtabs,modal/split/popover#27059..changesetentries.Container & model:
M,mode:thread,model: TIER_DEFAULT,effort: highClause-②: no (narrowing). A slotted page's
tabsslot and its aliases are refused, with a conversion for stored pages.Metadata-protocol: narrowed
Responsibility: n/a. A child of the record-page v3 epic epic: record page v2 — one default open mode per object (drawer by default, page by declaration; modal / split / popover retired as metadata); the drawer and the page are one page at two widths; related records open in place #26676, filed by the epic PM under the maintainer's approval.
Thread-read: none
Premise: the card measured
7bb8084590; the dev re-measures onorigin/main0f1045bcbefore the first edit.Serial constraints cleared: yes. spec: an object declares the business order of its related lists —
relatedLists: ['task', 'event', …], an ordered list of child relationships likehighlightFieldsis of fields; unlisted ones follow the derived order; a name that matches no inbound relationship is refused #27069 (seat 1) runs in parallel and may touchbuildDefaultPageSchema.ts; whichever lands second mergesmain. skills(objectstack-ui) + docs: teach the record page as it is now — object roles produce the page, six slotted slots,kind: fullas the escape hatch, drawer default withpageby declaration, the column tiers and the reader's own toggles — and stop namingtabs,modal/split/popover#27059 (ui lane) is blocked by this card.Ruling-ref: the maintainer rulings quoted in the card, and epic round 3
6459899198(filed to the spec lane queue)objectstack-fleet commentedon Oct 28, 2026
os-dev-report
{ "issue": 27053, "status": "done", "branch": "claude/project-thread-tc4fe5", "pr": "https://github.com/objectstack-ai/objectstack/pull/27219", "session": "session_01WGufzff3QiP6kmtajVnKnq", "premise_still_valid": false, "summary": "Head ca5556e06, main merged at b322b5da. Re-measured on main 0f1045bc: the card's premise that no producer authors slots.tabs was wrong. Four in-repo pages did (sys_user_detail, sys_organization_detail, sys_approval_request_detail, showcase_project_detail). Seat 1 confirmed moving all four to kind: 'full' as faithful rebuilds, plus the ADR-0133 one-line amendment (comment 6465037594 claim). Done per the card Target: slots.tabs is a retiredKey tombstone with the card's prescription and the house migrate sentence; related / relatedLists aliases became strictObject guidance refusals; checkPageSlotPair and page-slot-pair.test.ts are removed, with its ui export and both objectui superRefine attachments. D2 page-slots-tabs-removed (order 78, retiredAfter 18.2.0) drops the slot and leaves an empty slotted page when it was the only slot. D3 page-slots-tabs-retired absorbs page-slots-details-beside-tabs-refused; its STEP18 fragment is at order 112; the retired-key entry is ui/Page:slots.tabs. The JOIN row, the liveness note and the regenerated api-surface/export-origins/references go with it. buildDefaultPageSchema loses the tabs branch, RecordDetailView pageColumnsEligible is one line, PageSlotMap.tabs is typed never, and the Studio SLOT_ORDER has six slots. slotted-pages.md, content/docs/ui/pages.mdx (merged from main) and one skills bullet in skills/objectstack-ui/rules/pages.md, paid by a deletion in the same file (5669/5692). ADR-0133 inline Amended line; identity-auth.json rev 6 and studio-authoring.json rev 4 pins moved. Changeset: Clause-② no (narrowing), Metadata-protocol narrowed, adr-0087 registered for both ids, BREAKING with FROM → TO, minor for spec, platform-objects, plugin-approvals, @object-ui/types, plugin-detail, app-shell and skills. PR body: /mnt/project-files/issue-27053/pr-body.md.", "tests": "Under the lock: spec local 22219 passed, and its 3 first-run reds fixed and re-run green (166). spec test:repo 82 files / 1343 passed. platform-objects 1377, plugin-approvals 1331, lint 7522, cli touched files 59, plugin-auth org-page 3. ui: plugin-detail 2941; 19 slot-map and served-approvals-page files 319; RecordDetailView tiers and named page 13; PagePreview 8. Typecheck 104/104 turbo tasks over the touched packages, including test-layer ledgers. New: page-slots-tabs-retirement.test.ts with 19 cases, including the tree-scoped absence pin. Moved fixtures and tests are listed in the PR body's acceptance notes.", "gates": "dispatch-gates --commands: 126 commands, 121 exit 0. check:role-word (the word 'roles' in the docs prose) and check:cross-package-test-inputs (the absence pin was not yet in vitest.repo-tests.json) were found and fixed, now exit 0. check-plugin-teardown-shape --self-test exit 3 on the shallow clone, then 48 cases pass after fetching its pinned commit. check:skill-examples and check:dual-build-cjs-loads exit 3: they need a full repo build, so nothing was measured. CI on the PR: not yet read at report time.", "dogfood_battery": "not run: no runtime path changed beyond the record page synthesizer's slot read; the four producer pages are covered by their package suites", "mcp_calls": "subscribe_pr_activity x1; issue_read earlier for #27053; 0 writes via MCP", "api_writes": "3 via the relay: pr_create (#27219, 12231 bytes read back identical, assignee os-support-ai), pr_request_reviewers (os-support-ai), and this os-dev-report comment", "open_questions": [ "HotCRM's account slotted page was not measured: the hotcrm repo is outside this session's scope. If it authors tabs, the D2 conversion converts its stored row on read and os migrate meta --from 17 lists the source edit." ], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 28, 2026
Seat ruling ·
domain:specseat 1 (#6017) · sessionsession_01WGufzfhobWEgUUrjz4rrbh· 2026-10-28T11:20ZThis records on the card a ruling the seat gave the dev thread while #27053 was in flight. The contract review on PR #27219 (
6467641976, should-fix ③) asked for it.Premise correction. The card says no producer authors
slots.tabs. The dev re-measured onorigin/main0f1045bcand found four in-repo pages that do:sys_organization_detailandsys_user_detail, in@objectstack/platform-objectssys_approval_request_detail, in@objectstack/plugin-approvalsshowcase_project_detail, inexamples/app-showcase(private)Ruling. All four move to
kind: 'full'in the same PR, with behaviour identical to what the synthesizer drew for them onmain:record_header/record_moreids, in declaration order;record:discussionis present exactly when the slotted page did not authordiscussion: [].Nothing is redesigned. ADR-0133 gets a dated inline amendment saying the slotted page no longer has a
tabsslot and that a page needing its own strip iskind: 'full'. This follows the card's own prescription. There is no new decision for the maintainer, because the maintainer's keep/narrow/retire ruling already retires the slot and nameskind: 'full'as the route.Measured. Contract review
6467641976judged the four rebuilds faithful node by node againstbuildDefaultPageSchemaonmain.objectstack-fleet commentedon Oct 28, 2026
Landed ·
domain:specseat 1 (#6017) · sessionsession_01WGufzfhobWEgUUrjz4rrbh· 2026-10-28T15:16ZPR #27219 merged through the queue at
6dbff8e2, which is an ancestor oforigin/main. On 65 of the 72 paths the PR touched, the merge tree matches the accepted head95738710byte for byte. On the other 7 paths, the PR's net hunks from the merge-basecdec7473are identical to6dbff8e2^1..6dbff8e2; the bytes differ only because other work landed onmainin between. Inregistry.ts.templatea moved unchangedtext:context line pairs out to nothing.The page
tabsslot is retired. D2page-slots-tabs-removed(idempotent, copy-on-write,retiredAfter 18.2.0) converts a stored page, and the D3 entry18.page-slots-tabs-retirednames that conversion. The four built-in record pages are rebuilt askind: 'full'pages that author their ownpage:tabs. A drift pin holds theirpage:headeractions equal to the object'srecord_header∪record_more. It landed with os-zhuang's governed approval (5684520620). The evals for the skills bullet live on #27059.The card closed through
Fixes #27053, and this seat removespm:dispatched.