Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

console(grid): on an object with no list views, the density toggle PUTs /api/v1/meta/view/all with no viewKind — 422 INVALID_METADATA, and the density reverts #11643

Closed

Description

@objectstack-fleet

Filing gate: ① a product defect with a named site and a live reproduction (reach: public door, the console UI). Filed by the objectui domain:ui execution seat 1 (session_015W8GBu6sBiqus2L2xjMsAL) at the review of PR objectui#11639 (Fixes #11625), from the dev's out-of-scope findings. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.

Who acts: triage grades it. A domain:ui seat then fixes it in packages/app-shell/src/views/ObjectView.tsx, where the fallback tab's save is built.

Reproduction (measured by the dev, objectstack main 045f764c showcase)

  1. Open an object with no list views, e.g. showcase_account. The console shows its fallback tab, whose id is all.
  2. Toggle density.
  3. Wire: PUT /api/v1/meta/view/all with { rowHeight, object, name: 'all', _isOverride: true } and no viewKind.
  4. Answer: 422 INVALID_METADATA, "Unrecognized key(s) on this view container: rowHeight, _isOverride".
  5. Reload. Expected: the chosen density. Actual: "Density: Compact".

Mechanism

  • The fallback tab is a console-made tab, not a served view, and its id all is used as the metadata name.
  • The overlay branch writes the patch with no viewKind, so the door judges the body by a member that does not declare these keys, and refuses it.

Done when

A density (and any other toolbar) change on an object with no list views is either stored and survives a reload, or not offered. It is never sent as a body the door refuses. Pinned.

Dedupe: the same 1200-item REST listing (back to #6900). meta/view/all hits only PR objectui#11639, and fallback tab hits only PR objectui#11639. INVALID_METADATA hits 14, none on a view toolbar save. The control rowHeight hits 21.

Dedupe words: fallback tab all · PUT meta/view/all 422 · view-less object density · overlay without viewKind


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: views to see the data | records-forms.grid-personalization | P2

    Triage: first grade — bug · priority:p3 · domain:ui · area:records · pm:queue. The fallback tab sends no metadata write; its toolbar changes are session-only

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-05T04:53Z. ⛔ Not a claim, ⛔ not a dispatch.

    Triage: lands in packages/app-shell/src/views/ObjectView.tsx (where the fallback tab's save is built) ⇒ domain:ui; rationale: the fallback tab is made by the console, not served, so there is no view row to save into.

    • Direction: the Done-when's "not offered as saved", not "stored".
      • The fallback tab's toolbar changes apply for the session and send no PUT /meta/view/….
      • ⛔ No view is created to hold them. The tab's id all is not a view name: a bare all would collide across objects, and storing it would mint a metadata row nobody authored.
      • An object that wants saved personalization declares a list view, and the served-view path then applies.
    • Why p3. Only objects with no list views are hit. Nothing wrong is stored, because the door refuses the body with 422; the choice is lost on reload.
    • Pins: on a view-less object, a density change sends no metadata write and raises no error. On an object with a served view, the save path is unchanged.
    • Serial: objectui#11625 (PR objectui#11639) and objectui#11642, on the same file.

    Generated by Claude Code

  2. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 5, 2026
  3. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2
    Session: session_015W8GBu6sBiqus2L2xjMsAL
    Account: os-steve
    Branch: claude/issue-11643-fallback-tab-session-only
    Worktree: objectui-issue-11643
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: packages/app-shell/src/views/ObjectView.tsx (where the fallback tab's toolbar save is built: persistViewPatch and its callers), the tests beside it, and .changeset/11643-*.md (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus (dispatch-gates --tier: no path-derived mandate; default tier)
    Clause-②: no
    Thread-read: 5988346142
    Serial constraints cleared: objectui#11625 landed (PR objectui#11639, 59917c4) and objectui#11642 landed (PR objectui#11646, 531b26c), both on this file. No open PR and no in-flight claim touches packages/app-shell/src/views/ObjectView.tsx. Read 2026-10-05T08:07Z.

    Why Clause-②: no: the fallback tab's toolbar changes stay session-only and send no metadata write (triage 5988346142). A refused request stops being sent. No export, prop, type member or i18n key is added, and nothing in a published accept set or public surface widens.

  4. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 11643,
    "status": "done",
    "branch": "claude/issue-11643-fallback-tab-session-only",
    "pr": "#11654",
    "session": "session_015W8GBu6sBiqus2L2xjMsAL",
    "premise_still_valid": true,
    "summary": "The console-made fallback tab (id all) of an object that declares no list view now keeps its toolbar changes for the session and sends no metadata write, as triage ruled (comment 5988346142). In packages/app-shell/src/views/ObjectView.tsx the views memo marks the tab where it builds it (fallbackTab) with a module-local symbol CONSOLE_MADE_TAB (not exported), and persistViewPatch returns before it schedules anything (no read, no PUT, no toast) when the tab carries the mark and no stored row backs it (isSavedViewId). One rule covers every control that reaches persistViewPatch: density, sort, hidden fields, column state and inline edit. Provenance decides, not the id: a served view whose tab id is all, a saved view beside the fallback tab, and a stored row named all that shadows it keep their save paths. These are pinned with the objectui#11642 real-adapter harness and shown with a live before/after against objectstack main.",
    "files_changed": [
    "packages/app-shell/src/views/ObjectView.tsx (+51/-0)",
    "packages/app-shell/src/views/ObjectView.fallbackTabSessionOnly-11643.test.tsx (new, +402)",
    ".changeset/11643-fallback-tab-session-only.md (new, @object-ui/app-shell patch)"
    ],
    "gates": [
    "HEAD bd7343f (80b203a fix + 04a70d5 test-header + merge of origin/main 0baf86f; the merge does not touch ObjectView.tsx)",
    "pnpm exec vitest run packages/app-shell/ (repo root, under os-verify-lock): exit 0; Test Files 1005 passed | 1 skipped (1006); Tests 9979 passed | 9 skipped (9988); vitest list --filesOnly = 1006 files, the new one among them",
    "pnpm turbo run build --filter='@object-ui/app-shell^...' --concurrency=2: exit 0 (28/28, restored from turbo cache)",
    "pnpm --filter @object-ui/app-shell type-check: exit 0 (script echoed: tsc --noEmit && tsc -p tsconfig.test.json; tsc -p tsconfig.test.json --listFilesOnly includes the new test). The first attempt was a queue-timeout (exit 99, NOT MEASURED) and the retry measured it",
    "pnpm --filter @object-ui/app-shell lint: exit 0 (0 errors; warnings are all no-explicit-any, the new test's follow the 11642 harness)",
    "node scripts/check-object-metadata-write-doors.mjs: exit 0 (OK 17 doors, 3 object-capable, 3 reach assertObjectMetadataWritable)",
    "node scripts/check-new-cross-file-line-citations.mjs: exit 0 (VERDICT 0 new citation(s))",
    "node scripts/check-control-bytes.mjs: exit 0; grep -naP control-byte self-scan of the 3 files: 0 hits",
    "node scripts/check-changeset-presence.mjs: exit 0 (2 source files of 1 released package, 1 changeset declared)",
    "check-changeset-no-major / -fixed / -claims / -overwrite / check-pending-changeset-literals: exit 0 each",
    "check-vi-mock-specifiers / -inherit / -override-shape, check-test-path-roots, check-type-check-coverage, check-unreferenced-sources, check-i18n-call-site-keys, check-handler-key-read-sites: exit 0 each",
    "CI runs the full farm; this list is the diff-touched subset (hand-derived: dispatch-gates.mjs derives only objectstack's tree)"
    ],
    "line_budget": "not applicable: no skills/** and no governed ledger touched. Diff vs base 531b26c on own files: ObjectView.tsx +51/-0, new test +402, changeset +11",
    "deviations": [
    "Resumption: resumed from branch head 531b26c (= origin/main 531b26c at dispatch; the lost run left no commits of its own), so nothing in the lost run's commits was changed. Every reading in this report was taken in this run.",
    "origin/main moved again after my one merge (0baf86f, then f1a177c: objectui#11633 and #11634, auth and console files only, no overlap with ObjectView.tsx). Per the dispatch's merge-once rule it was not merged a second time, and the merge queue rebuilds on main.",
    "The live before/after and the three ablations ran on 80b203a, the committed fix, before the merge. The gates ran on the final head bd7343f. The merge does not touch ObjectView.tsx.",
    "Cleanup: after the PR opened, all three worktrees I used were removed (node_modules first, no --force): the main worktree /home/user/objectui-issue-11643 (clean, at remote head bd7343f, which can be re-created from origin), the base console worktree /home/user/objectui-issue-11643-base, and the objectstack backend worktree /home/user/objectstack-issue-11643-live. My backend (port 4643) and the two consoles (5643, 5644) were stopped by their recorded PIDs and process groups.",
    "PR footer: the os-dev session-URL footer form was used. The harness attribution reminder's alternative form was not used, because os-dev.md takes precedence over it."
    ],
    "tests": "NEW ObjectView.fallbackTabSessionOnly-11643.test.tsx (4 cases, real ObjectView + real persistViewPatch + real ObjectStackAdapter over a store that judges each PUT with ViewMetadataSchema): (1) on the console-made tab of a view-less object, all 8 callbacks reaching persistViewPatch (schema onDensityChange/onSortChange/onHiddenFieldsChange/onColumnStateChange; list props onSortChange/onHiddenFieldsChange/onInlineEditChange/onColumnStateChange) send no updateViewConfig, no saveItem and no getItem, and raise no toast and no persist error; (2) a saved view beside it still writes (isSavedView true) and survives a reload, while the fallback tab sends nothing; (3) a served view whose tab id is all keeps the overlay path (isSavedView false) and survives a reload; (4) a stored row named all shadowing the fallback tab keeps the saved path. Run: 4 passed. ABLATION on committed 80b203a via objectstack scripts/ablation-replace.mjs (anchor 1 to 0, blob changed, restore blob == HEAD 42a96556327a with git diff HEAD empty, after every leg): A guard removed: cases 1 and 2 red, 3 and 4 green. The prediction named case 1 only; case 2 is red because its first half drives the fallback tab. The test header now records the measured direction. Case 1's failure caught updateViewConfig('track_note','all',{columnState,inlineEdit,rowHeight:'medium',sort},{isSavedView:false}), and hiddenFields was absent because persistHiddenFields already gated it. B keyed on viewIdLocal === 'all': cases 3 and 4 red, 1 and 2 green, as predicted. C isSavedViewId clause dropped: case 4 red only, as predicted. LIVE (objectstack main 27991556 showcase, --fresh, own worktree; consoles from base 531b26c and branch 80b203a on one backend; headless Chromium; showcase_account has GET /meta/view?object=showcase_account items [] and no listViews/list, so its only tab is All Records). BASE: the Density click sent PUT /api/v1/meta/view/all body {rowHeight:'medium',object:'showcase_account',name:'all',_isOverride:true}, answered 422 INVALID_METADATA 'Unrecognized key(s) on this view container: rowHeight, _isOverride'; toast 'Failed to save view/all failed spec validation'; console '[ObjectView] Failed to persist view config'; after reload Density: Compact. BRANCH: Density: Comfortable, row 41 to 45 px; writes to /meta/view: [] ; toasts: [] ; persist console errors: [] ; after reload Density: Compact (session-only, as ruled). Served view showcase_task.default on BRANCH: PUT /api/v1/meta/view/showcase_task.default answered 200, and after reload Density: Comfortable (45 px). BASE did the same (200, survived reload).",
    "mcp_calls": "0 — no MCP GitHub tool called",
    "api_writes": "3, each one repository_dispatch to objectstack-ai/objectstack (POST /repos/objectstack-ai/objectstack/dispatches) run as objectstack-fleet[bot]: (1) pr_create, i.e. POST /repos/objectstack-ai/objectui/pulls (draft), giving #11654 (read-back: 8335 bytes sent, 8335 stored, identical); (2) label-write assign, i.e. POST /repos//issues/11654/assignees os-steve (read-back MATCHES); (3) this os-dev-report comment, i.e. POST /repos//issues/11643/comments. git push to the branch is not counted (not REST).",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: 承接者:无 · noted, not filed (measured from code, NOT measured live; no class established): a served tab built from a bare key in an object document's OWN listViews carries no viewKind, so its first overlay PUT relies on the door inheriting viewKind from a registry entry of the same name (normalizeViewMetadata / viewIdentityPatch in objectstack metadata-protocol). No example declares such an object: CRM's listViews.all compose to crm_lead.all etc. via expandViewContainer, and ViewItemNameSchema requires a dotted name. In PR Acceptance notes. Dedupe words: bare listViews key overlay viewKind · view container 422 served tab",
    "carrier: 承接者:无 · noted, not filed (observation, not judged): live on BOTH base and branch, the served-view density PUT body for showcase_task.default carried read decorations from the read-back row (_packageId, _provenance, _diagnostics, order, scope) beside name/object/viewKind/label/config. The door answered 200. Whether it stores them was not measured. This is outside this card's path (objectui#11642's read-back base) and is not in the PR Acceptance notes because the PR body is written once. Dedupe words: toolbar PUT read decorations _diagnostics _provenance overlay body"
    ]
    }

  5. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR objectui#11654 → main 4367146, verified by content

    domain:ui execution seat 1 @ objectui · session_015W8GBu6sBiqus2L2xjMsAL (os-steve) · 2026-10-05T10:25Z.

    • Merged through the merge queue as squash commit 4367146 (one parent, f1a177c), an ancestor of origin/main. Its +/- lines are identical to the PR head bd7343f diffed from its merge base: 3 files, +464/−0.

    • Content check against the first parent:

      reading f1a177c 4367146
      CONSOLE_MADE_TAB in app-shell views/ObjectView.tsx 0 6
      isConsoleMadeTab(baseViewDef) && !isSavedViewId (the guard in persistViewPatch) 0 1
      ObjectView.fallbackTabSessionOnly-11643.test.tsx exists no yes
      async function toolbarWriteInputs (control: objectui#11642's save path) 1 1
    • The card closed completed through the PR's Fixes line. It was the only issue closed in that window. pm:dispatched is removed in this stroke.

    • Serial note: objectui#11629's patch round on kanbanViewOptions in the same file now merges on top of this.


    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

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions