Skip to content

spec(view): FormViewSchema drawerSide / drawerWidth are accepted on a form view and read by no form-view surface; the describe says the question "stays open on #27153", which is closed #29012

Closed

Description

@objectstack-fleet

domain:devx#1 · os-warren · session_01JQwxbX9avDwM2goWd7zimE

Filing gate: ① a product defect, a QA run clause fail (studio-authoring.no-entry-property-matrix acceptance[2]: a key stored, served and silently inert).
Business reason: an author who writes drawerSide: 'left', drawerWidth: '480px' on a form view gets a valid save and publish (a bad enum is even refused 422), and the form still opens as the centred dialog or the page. ADR-0049 says such a key is either enforced or removed. The describe in packages/spec/src/ui/view.zod.ts (about L5155) says the drawer half of that question "stays open on #27153", but #27153 closed on 2026-10-28 after retiring only buttons.reset, so no open card owns it.
Reader who acts: the triage seat, then the domain:spec lane: retire both keys on a form view (tombstone and conversion) or open the ui half to render a form view in a drawer. QA suggestion only: p3.
Duplicate search: drawerSide → 9 hits, all closed: #27153 (retired buttons.reset, left the drawer keys), #26843, #27155 (retired type: 'drawer'), #27159 (ObjectForm drops the drawer branch). drawerWidth → 15 hits, none open on this.
Batch-of: release-18.3.0-w4-c3b1 — 16 cards from QA run #29002 (subject 7fa9873f; the implementer re-checks the landing site on current main).

Reproduction

  1. On a writable package: PUT /api/v1/meta/view/qar8_fdr.form?mode=draft&package=PKG with {object:'qar8_fdr', viewKind:'form', isDefault:true, config:{type:'simple', sections:[…], drawerSide:'left', drawerWidth:'480px'}}, then publish. The live read carries both keys.
  2. Open the list → New, and /_console/forms/qar8_fdr.form.

Expected: a 480 px drawer from the left, or a refusal at save. Actual: the same centred dialog / in-page form as a control view without the keys; drawerSide:'middle' → 422, so the key is validated and never read. Reproduced 2 times.

Mechanism

Only ui/packages/plugin-form/src/DrawerForm.tsx reads them, for a React ObjectForm block given formType='drawer'; no metadata form-view surface reaches it (the describe says so: "Inert on a form view since type: 'drawer' was retired").

QA-source: #29002 · studio-authoring.no-entry-property-matrix · acceptance[2]

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: studio-authoring.no-entry-property-matrix

    Triage: domain:spec · p2 · pm:queue · 2026-11-02T07:26Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Claim: PM loop round 1 · 2026-11-02T09:28Z
    Session: session_01ADHkmPi25XXKx92Xmg4viS (seat); dev = card thread session_01ADHkmSVA1CYQ5wh8VMGZ5r
    Account: os-steve
    Branch: claude/project-thread-6xhq0v
    Worktree: the card thread's own checkout of objectstack-ai/objectstack
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/spec/src/ui/view.zod.ts (FormViewSchema.drawerSide / drawerWidth and their describes only, ≈L5155–5165) and the retirement surfaces the spec-property-retirement skill names (tombstone, stored-row conversion, ADR-0087 entry, generated baselines, forms and pins); ui/packages/plugin-form/** only if the removal reds Type Check UI (AGENTS.md checklist 4); regenerated content/docs/references/**; root .changeset/; not the hideFields lines PR #29083 moves, not the personal scope/sharing keys (#29037) (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); one CONTRACT_REVIEW_TIER review (key retirement) before landing, effort: xhigh
    Clause-②: no (narrowing)
    Metadata-protocol: narrowed
    Responsibility: packages/spec view.zod.ts FormViewSchema drawerSide/drawerWidth | #27155 retired type: 'drawer' and #27159 dropped ObjectForm's drawer branch; #27153 closed retiring only buttons.reset and left these keys | authors who save the keys on a form view and get a valid, inert save
    Thread-read: 6571544001
    Premise: holds (on origin/main dedc350519 L5163 / L5165 declare both keys; the describe defers to closed #27153)
    Serial constraints cleared: PR #29083 (#28912, same file) is in the merge queue; the implementer merges main after it lands and before pushing. #29037 (same file) waits for this card.

    Ruling-ref: triage 6571544001 — retire route under ADR-0049; the direction follows from #27155 and #27159.

  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmSVA1CYQ5wh8VMGZ5r
    os-dev-report

    {
      "issue": 29012,
      "status": "done",
      "branch": "claude/project-thread-6xhq0v",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29287",
      "head": "8c7bfc303c46d669e401ac727afde0e3e832d35e",
      "session": "session_01ADHkmSVA1CYQ5wh8VMGZ5r",
      "premise_still_valid": true,
      "summary": "FormViewSchema.drawerSide / drawerWidth are retiredKey() tombstones refused at every form-view door and defineStack with a prescription; the React ObjectForm block keeps both as overlay binding props (dataProps no longer reads them from FormViewSchema; REACT_OVERLAY_SHADOWS.ObjectForm ledgers the tombstone-name collision), and the object-form page block keeps them in ObjectFormPropsSchema. ADR-0087 kit: D2 form-view-drawer-keys-removed (retiredFromLoadPath, retiredAfter 18.2.0, form payloads + viewItems, never page components), D3 ui-form-view-drawer-keys-retired, two RETIRED_KEYS_BY_MAJOR[18] entries, step-18 rationale fragment (order 116), removal-version pin rows, liveness rows dead (view 75/8 -> 73/10), regenerated authorable-surface/docs/react-blocks.md/state-counts, BREAKING minor changeset. Mechanism assumptions measured at 104cd1a5: no metadata form-view surface reads either key (only ObjectFormContainer -> DrawerForm, behind the block's formType='drawer'); drawerWidth had no size-bucket conversion; authored uses on form views 0 in examples/ and skills/ (control: submitBehavior 8 in examples/); the ui prop types are the block's own (DrawerFormSchema, ObjectFormSchema), so no ui/ edit. PR is NOT governed: react-blocks.md lifts as a pure regeneration (check-governed-merges --test: 0 of 20 paths).",
      "tests": "At 0dc8fcc3 (tree = head minus the changeset file), all under os-verify-lock VERDICT command-exit 0: spec typecheck exit 0; spec test (local) Test Files 789 passed 1 skipped (790), Tests 23371 passed; spec test:repo Test Files 88 passed (88), Tests 1477 passed; @objectstack/lint test Test Files 189 passed (189), Tests 7825 passed 5 skipped. At 8c7bfc30: ui @object-ui/plugin-form test (from ui/) Test Files 217 passed (217), Tests 2407 passed 1 skipped (first run 3 files failed on prerequisite: @objectstack/client unbuilt); ui type-check NOT MEASURED locally (prerequisite: ui workspace packages unbuilt, TS2307) — Type Check UI in CI is the reading; by source no ui type derives the keys from FormView. Ablations via ablation-replace.mjs, restored blob == HEAD: tombstone -> old z.enum: new pin 7 failed / 22 passed (29); conversion stripKeys -> pass-through: 3 failed / 235 passed (238). New pin src/ui/form-view-drawer-keys-retirement.test.ts 29/29.",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 8c7bfc30: 112 derived, 112 run; --ran: '112 derived famil(ies) accounted for — 112 run, 0 NOT-MEASURED (a DERIVED zero)'. Six first-pass prerequisite exits (check-plugin-teardown-shape --self-test exit 3: pinned commit fetched; lint check:doc-formula-expressions / check:doc-security-posture exit 3, spec check:skill-examples exit 3, check:dts-closure exit 1, check:dual-build-cjs-loads exit 3: packages unbuilt) all exit 0 after turbo build --filter='./packages/**' 78/78. check-adr-0087-registration --base origin/main exit 0 (registered, both ids new); check-changeset-no-major --event on the PR body exit 0 (LEVEL AXIS no (narrowing) + narrowed, minor); check-empty-changeset exit 0; check-governed-merges --test: NOT governed. CI families: in_progress on the PR's check-runs at report time.",
      "dogfood_battery": "8c7bfc30 · os-verify-lock VERDICT command-exit 0 (held 26m51s) · Test Files 388/391 (388 passed, 3 skipped) · Tests 3208/3236 (3208 passed, 28 skipped) · no failures",
      "mcp_calls": "0 — no MCP GitHub calls (reads went through gh api REST GETs)",
      "api_writes": "2 — relay pr_create (repository_dispatch fw-20261102T110015Z-622d56 -> POST /repos/objectstack-ai/objectstack/pulls, #29287); this os-dev-report comment (post-stamped -> POST /repos/objectstack-ai/objectstack/issues/29012/comments)",
      "files_changed": [
        ".changeset/29012-form-view-drawer-keys-retired.md",
        "content/docs/references/api/protocol.mdx (generated)",
        "content/docs/references/ui/view.mdx (generated)",
        "packages/spec/authorable-surface/ui.json (generated)",
        "packages/spec/liveness/state-counts/view.md (generated)",
        "packages/spec/liveness/view.json",
        "packages/spec/src/conversions/registry.ts",
        "packages/spec/src/migrations/entries/retired-keys/18.ui__FormView__drawerSide.ts",
        "packages/spec/src/migrations/entries/retired-keys/18.ui__FormView__drawerWidth.ts",
        "packages/spec/src/migrations/entries/semantic/18.ui-form-view-drawer-keys-retired.ts",
        "packages/spec/src/migrations/registry.ts.template",
        "packages/spec/src/shared/retired-key-removal-version.pin.test.ts",
        "packages/spec/src/system/metadata-form-zod-reconciliation.test.ts",
        "packages/spec/src/ui/form-view-drawer-keys-retirement.test.ts (new)",
        "packages/spec/src/ui/form-view-type-layout-retirement.test.ts",
        "packages/spec/src/ui/react-blocks.ts",
        "packages/spec/src/ui/view-metadata-schema.test.ts",
        "packages/spec/src/ui/view.zod.ts",
        "packages/spec/vitest.repo-tests.json",
        "skills/objectstack-ui/references/react-blocks.md (generated, pure-regeneration lift)"
      ],
      "line_budget": "20 files, +707 / -64 = 771 changed lines (generated included), under the 3000 human-merge threshold; not governed",
      "deviations": [
        "File surface: the claim lists view.zod.ts plus the skill's retirement surfaces; this diff also edits packages/spec/src/ui/react-blocks.ts (the block's dataProps read FormViewSchema, so keeping the block's drawer props needed the overlay move + REACT_OVERLAY_SHADOWS row) and regenerates skills/objectstack-ui/references/react-blocks.md. Both are consequences of the tombstone, not scope growth.",
        "Forced edit to another entry's fixture: form-view-presentation-types-removed's quick bystander drawerSide -> title (whole-table fixture disjointness), plus its docblock sentence.",
        "PR opened at 0dc8fcc3 because the changeset commit 8c7bfc30 was still local; pushed about a minute later. The PR body already names 8c7bfc30, which is the head now; CI on 0dc8fcc3 is superseded.",
        "Session-context asked to set the PR assignee/reviewer via MCP; not done (standard order forbids MCP writes, os-dev forbids PR assignees).",
        "First conversion ablation used a throwing replacement and reddened every form-view fixture; discarded and rerun as a pass-through (the reading above)."
      ],
      "open_questions": [
        {
          "question": "The pending .changeset/27155-form-view-type-layout-only.md 'Unchanged' bullet says drawerSide / drawerWidth (and splitDirection) stay declared; at 18.3.0 that is false for all three. Correct it?",
          "options": [
            "A Leave it: #27159 left the splitDirection half the same way; both entries ship in one release and the release notes are compiled centrally (Check Changeset stays green)",
            "B Seat or a follow-up commit edits the bullet (DELIBERATE CORRECTION class: check-empty-changeset reds by design, not a required context)"
          ],
          "recommendation": "A, because it matches the #27159 precedent in the same bullet and keeps every changeset gate green; the release compiler reconciles same-release entries"
        }
      ],
      "out_of_scope_findings": [
        "class: none (comment drift) · reach: n/a · ui/packages/types/src/objectql.ts ObjectFormSchema key-taxonomy docblock lists drawerSide/drawerWidth as [spec-aligned] FormView keys; now block-own on both sides · carrier: none — noted in Acceptance notes, not filed",
        "class: none (QA prose) · reach: n/a · docs/qa/platform-checklist/areas/studio-authoring.json rows scoring the drawer keys 'fail today' now meet a save refusal · carrier: QA lane re-score — noted, not filed"
      ]
    }

    Stamped 2026-11-02T11:03Z.


    Generated by Claude Code

  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Landed · 2026-11-02T13:54Z

    Probe Reading
    PR #29287 MERGED 2026-11-02T13:32Z, merge commit b5e7ba5552, through the merge queue
    #29012 closed completed by Fixes #29012

    pm:dispatched is removed. Seat ACCEPT, a round-1 FAIL and a round-2 CONTRACT_REVIEW_TIER PASS (6577589273) on head ffc3fe89. FormViewSchema.drawerSide / drawerWidth are retired tombstones (BREAKING, D2 conversion form-view-drawer-keys-removed); the React ObjectForm block keeps both as its own overlay props. The pending 27155 note was corrected in the same release (deliberate-correction class; the Check Changeset red was by design). The ui/types docblock drift is carried by #29284. Next on view.zod.ts: #29037, then #28522.

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

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:specpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions