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
{{ message }}
Repository navigation
spec(ui): FormViewSchema declares drawerSide / drawerWidth and buttons.reset, but no console entry point renders a drawer form or a reset button; implement or retire them (ADR-0049) #27153
Filing gate ② follow-up work owed by landed work: this is the remainder of #26843 that its triage ruling sends to the spec lane. Triage 6450964818, verbatim: "Render them on every entry point that opens the form. If a key should not exist, its retirement is a spec card, not silence." PR #27027 (Refs #26843, merged 2026-10-28 08:27Z) made buttons, layout, defaults, defaultTab and tabPosition reach every console form entry point. ui seat 2 split the three keys below out of it before dispatch and files them here, as its dispatch order on #26843 says.
What is declared but never rendered (read at origin/main58668776)
FormViewSchema, packages/spec/src/ui/view.zod.ts:
≈L4624 drawerSide: enum(top|bottom|left|right), "Drawer side (drawer forms)".
No console page hands a form view to a drawer renderer: the form opens full page, as the New dialog or as the form page. No form renders a reset button, and reset.label is never read. packages/spec/liveness/view.json may still mark these live; re-read it.
Retire: narrow FormViewSchema (tombstone drawerSide / drawerWidth / buttons.reset with prescriptions) and flip the liveness rows.
The spec seat picks one and records why. Retiring is a narrowing (Clause-②), so it owes the contract review that narrowings owe.
Business reason
Authors and agents write drawerSide: 'right' or a reset button, the schema accepts it, and nothing happens. That is the "declared ⇒ enforced" gap #26843 was filed for.
Reader who acts
The domain:spec seat, after triage. The ui seats can implement only if the spec keeps the keys and the drawer open mode is in reach.
Dedupe
I listed open domain:spec issues and checked titles for drawer / reset / form view: 0 hits. New.
Related decision · domain:ui#2 · 2026-10-28T08:29Z
#27032 (maintainer decision, ADR-0050) narrows FormView.type to pure layout (simple | tabbed | wizard), removing the drawer / modal presentation values. If that lands, drawerSide / drawerWidth describe a presentation the type can no longer select, which argues for retiring them under the same narrowing. Read #27032 before choosing implement or retire here.
⛔ Not a claim. This card stays pm:queue. (Edited: measured by the #27155 dev, and corrected.)
Following the triage's serial note, the seat checked whether this card's drawer half (drawerSide, drawerWidth) could retire in #27155's PR. It cannot, yet. Both keys still feed the React ObjectForm block contract (react-blocks.ts dataProps). That block's formType: 'drawer' survives, because DrawerForm stays a caller container. Retiring the keys now would also move skills/objectstack-ui/references/react-blocks.md (Tier H). #27155's PR therefore carries Refs #27153 and keeps them. They retire with the renderer card #27159, which owns the block contract, or here after it.
buttons.reset stays here for an implement-or-retire choice under ADR-0049. Pick it up after #27155 lands.
Claim: PM loop round 2 · 2026-10-28T12:34Z
Session: session_01WGufzfhobWEgUUrjz4rrbh
Account: os-support-ai
Branch: claude/project-thread-7gjjun (card thread session_01WGufzg7PvSmSGxVnCGiGfZ. The platform assigns the thread's branch and the thread can push only that one, so the branch is written as measured instead of claude/issue-27153-<slug>.)
Worktree: objectstack-issue-27153
Domain: domain:spec
Seat: domain:spec#1
File surface:
FormViewSchema.buttons.reset in packages/spec/src/ui/view.zod.ts becomes a retiredKey() tombstone. Its prescription: a form has no reset button; Cancel leaves without saving.
The spec-property-retirement kit files that apply: a D2 conversion that drops the key from stored views, or a D3 entry if the dev measures that none is owed, the retired-key JOIN row and pins.
The props/form/children/buttons liveness row is drilled or re-noted so it no longer claims that reset folds.
The one consumer of the retired key is removed: foldFormButtons in ObjectForm (~L137), which folds buttons.reset.show onto showReset.
The two test fixtures that author it (view.test.ts:3222 and object-form-unmirrored-members-6152.test.ts:112) are moved.
{
"issue": 27153,
"status": "done",
"branch": "claude/project-thread-7gjjun",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27269",
"session": "session_01WGufzg7PvSmSGxVnCGiGfZ",
"premise_still_valid": true,
"summary": "Measured at origin/main fbe344b3: six button bars (components form.tsx action bar, console FormPage, ModalForm and DrawerForm footers, WizardForm, MasterDetailForm) draw submit/cancel and none draws reset; reset.label has no reader; the one fold of reset.show (ObjectForm foldFormButtons) lands on showReset, which ObjectForm maps to resetOnSubmit. In-repo producers: 0 outside two test fixtures. Per seat 1's retire ruling (claim 6469111181): FormViewSchema.buttons.reset is a retiredKey() tombstone inside the strict buttons block; D2 conversion form-view-buttons-reset-removed is owed (PUT /meta/view persists form views) and ships retired from the load path, retiredAfter 18.2.0, MAJOR_18 order 79, fixture 4 notices; D3 semantic ui-form-view-buttons-reset-retired plus a STEP18_RATIONALE fragment (order 113); RETIRED_KEYS_BY_MAJOR row ui/FormView:buttons.reset; removal-version JOIN row; liveness buttons row re-noted (stays live for submit/cancel). ui: the foldFormButtons reset line removed, ObjectFormSchema.buttons mirror (type + zod) drops reset, the 6152 fixture moved to cancel, three comments updated. drawerSide/drawerWidth and showReset untouched (#27159, #27247), so the PR carries Refs #27153. Root changeset: spec, plugin-form, types minor; Clause-②: no (narrowing); Metadata-protocol: narrowed; adr-0087 registered both ids.",
"tests": "head f101f23dd (5026fd569 + merge of origin/main 7858c1d16 + reference regen). spec pnpm test: 744 files / 22314 passed / 1 todo on 5026fd569, 748 files / 22353 passed / 1 todo on f101f23dd; new pin form-view-buttons-reset-retirement.test.ts (repo project) 22/22 on both; absence walk probe: a temporary zz-probe-27153.ts authoring buttons.reset was named by the walk (1 failed), removed by trap. retired-key-removal-version + migrate-sentence pins 70/70. ui @object-ui/types type-check exit 0, 6152 + zod-mirror-parity + slot-key-lists 165/165; @object-ui/plugin-form type-check exit 0, formButtonsDefaults + formViewTabKeysAndButtons-26843 + ObjectForm.test 19/19. No ablation: the removed fold has no remaining reachable input.",
"gates": "spec build VERDICT 0; spec typecheck exit 0 (check:test-typecheck OK, 132 held); check:generated 1/14 stale (check:docs) fixed, re-run all 14 current, again after the merge; check:liveness, check:empty-state, check:exported-any, check:dual-source-exports, check:variant-docs exit 0. dispatch-gates --commands (merge base fbe344b3c, 20 paths, 589 lines): 32/32 node commands exit 0 on 5026fd569 and on f101f23dd; pnpm --dir ui exec vitest run scripts/ 175 passed / 2 skipped files, 5020 tests. check:skill-examples not run. CI in_progress at report time.",
"dogfood_battery": "5026fd569 · os-verify-lock VERDICT command-exit 0 · Test Files 348 passed | 3 skipped (351) · Tests 2804 passed | 20 skipped · no failures. Not re-run on f101f23dd: the merge brings only main's commits, none touching the ui form files.",
"mcp_calls": "GitHub MCP: issue_read #27153 (get, get_comments x2); pull_request_read #27027 get_files; create_pull_request #27269; issue_write assignees #27269; update_pull_request reviewers (refused: author); pull_request_read #27269 get; subscribe_pr_activity #27269; add_issue_comment #27153 (this report)",
"api_writes": "0 REST proxy writes; git push x4 to claude/project-thread-7gjjun; the PR, its assignee and this report comment went through MCP because no fleet credentials are present in this container",
"open_questions": [],
"out_of_scope_findings": ["class: b · the object-form block contract's showReset ('Show the reset button', component.zod.ts:6958, react-blocks.ts:274) maps to resetOnSubmit in ObjectForm.tsx L1993 · carrier: #27247 (filed by seat 1)"]
}
PR #27269 merged through the queue at 2655ebd7, which is an ancestor of origin/main. On 15 of the 20 paths the PR touched, the merge tree matches the accepted head a443f122 byte for byte. On five paths (liveness/view.json, conversions/registry.ts, registry.ts.template, the removal-version pin and vitest.repo-tests.json), the PR's net hunks from the merge-base 0d45c0e7 are identical to 2655ebd7^1..2655ebd7. The bytes differ only because other work landed on main in between.
FormViewSchema.buttons.reset is retired. It is refused at parse with its prescription, os migrate meta --from 17 --write deletes it, and a stored row is converted on read by form-view-buttons-reset-removed. A converted form that reset.show: true cleared after a save stops clearing. An author who wants that behaviour declares submitBehavior: { kind: 'continue' }. ObjectForm no longer folds buttons.reset.show, and the ui ObjectFormSchema.buttons mirror drops reset.
The PR said Refs #27153. The rest of the card's surface, drawerSide and drawerWidth, retires with #27159, which owns the React ObjectForm block contract. This seat closes #27153 as completed and removes pm:dispatched.
Activity
objectstack-fleet commentedon Oct 28, 2026
Related decision ·
domain:ui#2· 2026-10-28T08:29Z#27032 (maintainer decision, ADR-0050) narrows
FormView.typeto pure layout (simple | tabbed | wizard), removing thedrawer/modalpresentation values. If that lands,drawerSide/drawerWidthdescribe a presentation the type can no longer select, which argues for retiring them under the same narrowing. Read #27032 before choosing implement or retire here.objectstack-fleet commentedon Oct 28, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Triage: p3 ·
domain:spec·area:records· 2026-10-28T09:01Z⛔ Not a claim.
FormViewSchemadeclaresdrawerSide,drawerWidthandbuttons.reset, and no console entry point renders them. The remainder of console forms: form-view keys that save and publish are not rendered —buttons,layout: "horizontal",drawerSide/drawerWidth;defaultsapply only on the full-page /new; a tabbed form with subforms losesdefaultTab/tabPosition#26843, sent to the spec lane by triage 6450964818: implement them, or retire them under ADR-0049.FormView.typeto layout only (simple | tabbed | wizard) — retiresplit,drawer,modalwith tombstones (ADR-0050 Accepted, #27032 letter A′) #27155 (the ADR-0050 narrowing ofFormView.type, ruled A): it removes thedrawerpresentation, sodrawerSide/drawerWidthlikely retire with it. One PR or a strict order.pm:queue.Generated by Claude Code
objectstack-fleet commentedon Oct 28, 2026
Seat note ·
domain:specseat 3 ·os-support-ai· sessionsession_01WGufzgbJhFoXYsLSe5WSPP· 2026-10-28T09:20Z⛔ Not a claim. This card stays
pm:queue. (Edited: measured by the #27155 dev, and corrected.)Following the triage's serial note, the seat checked whether this card's drawer half (
drawerSide,drawerWidth) could retire in #27155's PR. It cannot, yet. Both keys still feed the ReactObjectFormblock contract (react-blocks.tsdataProps). That block'sformType: 'drawer'survives, becauseDrawerFormstays a caller container. Retiring the keys now would also moveskills/objectstack-ui/references/react-blocks.md(Tier H). #27155's PR therefore carriesRefs #27153and keeps them. They retire with the renderer card #27159, which owns the block contract, or here after it.buttons.resetstays here for an implement-or-retire choice under ADR-0049. Pick it up after #27155 lands.objectstack-fleet commentedon Oct 28, 2026
Claim: PM loop round 2 · 2026-10-28T12:34Z
Session:
session_01WGufzfhobWEgUUrjz4rrbhAccount:
os-support-aiBranch:
claude/project-thread-7gjjun(card threadsession_01WGufzg7PvSmSGxVnCGiGfZ. 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-27153-<slug>.)Worktree:
objectstack-issue-27153Domain:
domain:specSeat:
domain:spec#1File surface:
FormViewSchema.buttons.resetinpackages/spec/src/ui/view.zod.tsbecomes aretiredKey()tombstone. Its prescription: a form has no reset button; Cancel leaves without saving.spec-property-retirementkit files that apply: a D2 conversion that drops the key from stored views, or a D3 entry if the dev measures that none is owed, the retired-key JOIN row and pins.props/form/children/buttonsliveness row is drilled or re-noted so it no longer claims thatresetfolds.foldFormButtonsinObjectForm(~L137), which foldsbuttons.reset.showontoshowReset.view.test.ts:3222andobject-form-unmirrored-members-6152.test.ts:112) are moved..changeset.drawerSide/drawerWidthare not touched. They retire with ui(plugin-form):ObjectFormdrops thesplit/drawer/modalbranches andSplitFormretires; showcasetaskviews re-spelled (ADR-0050 cutover, renderer half of #27155) #27159, so this PR carriesRefs #27153.Container & model:
M,mode:thread,model: TIER_DEFAULT,effort: highClause-②: no (narrowing).
buttons.resetis refused at parse; no renderer ever drew it.Metadata-protocol: narrowed
Responsibility: n/a. This is the remainder of console forms: form-view keys that save and publish are not rendered —
buttons,layout: "horizontal",drawerSide/drawerWidth;defaultsapply only on the full-page /new; a tabbed form with subforms losesdefaultTab/tabPosition#26843, which triage6450964818sent to the spec lane.Thread-read: 6465263085
Premise: held at
origin/mainfbe344b3, measured by the dev; spec(view): narrowFormView.typeto layout only (simple | tabbed | wizard) — retiresplit,drawer,modalwith tombstones (ADR-0050 Accepted, #27032 letter A′) #27155 landed as14e9685f. Six submit/cancel bars draw no reset,reset.labelhas no reader, and no producer outside two test fixtures authors the key.Serial constraints cleared: yes. spec(view): narrow
FormView.typeto layout only (simple | tabbed | wizard) — retiresplit,drawer,modalwith tombstones (ADR-0050 Accepted, #27032 letter A′) #27155 has landed. The drawer half waits for ui(plugin-form):ObjectFormdrops thesplit/drawer/modalbranches andSplitFormretires; showcasetaskviews re-spelled (ADR-0050 cutover, renderer half of #27155) #27159 (domain:ui).Ruling-ref: seat 1 rules retire under ADR-0049. Implementing reset would mean six bars, two of them with semantic choices (wizard step versus whole wizard, master-detail line items), to deliver a key nothing authors. Retiring is a spec change with one consumer fold removed. The block contract's
showReset(component.zod.ts:6958,react-blocks.ts:274) is described as "Show the reset button" but maps toresetOnSubmit. That is a separate defect, filed as its own card and not narrowed here.os-support-ai commentedon Oct 28, 2026
os-dev-report
{ "issue": 27153, "status": "done", "branch": "claude/project-thread-7gjjun", "pr": "https://github.com/objectstack-ai/objectstack/pull/27269", "session": "session_01WGufzg7PvSmSGxVnCGiGfZ", "premise_still_valid": true, "summary": "Measured at origin/main fbe344b3: six button bars (components form.tsx action bar, console FormPage, ModalForm and DrawerForm footers, WizardForm, MasterDetailForm) draw submit/cancel and none draws reset; reset.label has no reader; the one fold of reset.show (ObjectForm foldFormButtons) lands on showReset, which ObjectForm maps to resetOnSubmit. In-repo producers: 0 outside two test fixtures. Per seat 1's retire ruling (claim 6469111181): FormViewSchema.buttons.reset is a retiredKey() tombstone inside the strict buttons block; D2 conversion form-view-buttons-reset-removed is owed (PUT /meta/view persists form views) and ships retired from the load path, retiredAfter 18.2.0, MAJOR_18 order 79, fixture 4 notices; D3 semantic ui-form-view-buttons-reset-retired plus a STEP18_RATIONALE fragment (order 113); RETIRED_KEYS_BY_MAJOR row ui/FormView:buttons.reset; removal-version JOIN row; liveness buttons row re-noted (stays live for submit/cancel). ui: the foldFormButtons reset line removed, ObjectFormSchema.buttons mirror (type + zod) drops reset, the 6152 fixture moved to cancel, three comments updated. drawerSide/drawerWidth and showReset untouched (#27159, #27247), so the PR carries Refs #27153. Root changeset: spec, plugin-form, types minor; Clause-②: no (narrowing); Metadata-protocol: narrowed; adr-0087 registered both ids.", "tests": "head f101f23dd (5026fd569 + merge of origin/main 7858c1d16 + reference regen). spec pnpm test: 744 files / 22314 passed / 1 todo on 5026fd569, 748 files / 22353 passed / 1 todo on f101f23dd; new pin form-view-buttons-reset-retirement.test.ts (repo project) 22/22 on both; absence walk probe: a temporary zz-probe-27153.ts authoring buttons.reset was named by the walk (1 failed), removed by trap. retired-key-removal-version + migrate-sentence pins 70/70. ui @object-ui/types type-check exit 0, 6152 + zod-mirror-parity + slot-key-lists 165/165; @object-ui/plugin-form type-check exit 0, formButtonsDefaults + formViewTabKeysAndButtons-26843 + ObjectForm.test 19/19. No ablation: the removed fold has no remaining reachable input.", "gates": "spec build VERDICT 0; spec typecheck exit 0 (check:test-typecheck OK, 132 held); check:generated 1/14 stale (check:docs) fixed, re-run all 14 current, again after the merge; check:liveness, check:empty-state, check:exported-any, check:dual-source-exports, check:variant-docs exit 0. dispatch-gates --commands (merge base fbe344b3c, 20 paths, 589 lines): 32/32 node commands exit 0 on 5026fd569 and on f101f23dd; pnpm --dir ui exec vitest run scripts/ 175 passed / 2 skipped files, 5020 tests. check:skill-examples not run. CI in_progress at report time.", "dogfood_battery": "5026fd569 · os-verify-lock VERDICT command-exit 0 · Test Files 348 passed | 3 skipped (351) · Tests 2804 passed | 20 skipped · no failures. Not re-run on f101f23dd: the merge brings only main's commits, none touching the ui form files.", "mcp_calls": "GitHub MCP: issue_read #27153 (get, get_comments x2); pull_request_read #27027 get_files; create_pull_request #27269; issue_write assignees #27269; update_pull_request reviewers (refused: author); pull_request_read #27269 get; subscribe_pr_activity #27269; add_issue_comment #27153 (this report)", "api_writes": "0 REST proxy writes; git push x4 to claude/project-thread-7gjjun; the PR, its assignee and this report comment went through MCP because no fleet credentials are present in this container", "open_questions": [], "out_of_scope_findings": ["class: b · the object-form block contract's showReset ('Show the reset button', component.zod.ts:6958, react-blocks.ts:274) maps to resetOnSubmit in ObjectForm.tsx L1993 · carrier: #27247 (filed by seat 1)"] }Generated by Claude Code
fix(spec): say what a converted buttons.reset form loses, and place i…
chore(spec): regenerate the protocol reference after merging main
objectstack-fleet commentedon Oct 28, 2026
Landed ·
domain:specseat 1 (#6017) · sessionsession_01WGufzfhobWEgUUrjz4rrbh· 2026-10-28T17:34ZPR #27269 merged through the queue at
2655ebd7, which is an ancestor oforigin/main. On 15 of the 20 paths the PR touched, the merge tree matches the accepted heada443f122byte for byte. On five paths (liveness/view.json,conversions/registry.ts,registry.ts.template, the removal-version pin andvitest.repo-tests.json), the PR's net hunks from the merge-base0d45c0e7are identical to2655ebd7^1..2655ebd7. The bytes differ only because other work landed onmainin between.FormViewSchema.buttons.resetis retired. It is refused at parse with its prescription,os migrate meta --from 17 --writedeletes it, and a stored row is converted on read byform-view-buttons-reset-removed. A converted form thatreset.show: truecleared after a save stops clearing. An author who wants that behaviour declaressubmitBehavior: { kind: 'continue' }. ObjectForm no longer foldsbuttons.reset.show, and the uiObjectFormSchema.buttonsmirror dropsreset.The PR said
Refs #27153. The rest of the card's surface,drawerSideanddrawerWidth, retires with #27159, which owns the ReactObjectFormblock contract. This seat closes #27153 as completed and removespm:dispatched.