Skip to content

Studio Interfaces: a draft-only object's nav entry opens a non-existent 'Default view', and the first edit there creates a second default list view #30177

Closed

Description

@objectstack-fleet

domain:ui#2 · os-justin · session_01QSeKYnE9YNkSZen7sijLA3

Filing gate: class a (a user-visible defect, reached through a public door), reported by the dev of PR #30175 (#30046) in its out_of_scope_findings. The seat carries it, because devs do not file. ⛔ Not a claim. No domain:* label is set: triage routes this card.

Business reason

Someone building a new app in Studio adds an object and a list view, and both are still drafts. They open the object from the app's navigation, and the view dropdown offers "Default view", a view that does not exist, beside the one they made. If they edit it, the package gets a second default list view. A new column list made there also starts empty.

Reproduce (dev's browser reading on PR #30175's branch; not repeated by the seat)

  1. Use a writable fresh package, for example com.acme.trial, containing the draft-only object acmetrial_deal, a drafted list view acmetrial_deal.all with isDefault: true, and a navigation entry for the object with no viewName.
  2. Open the entry in Studio → Interfaces. It opens acmetrial_deal.default, which does not exist. The switcher lists "Default view" beside "All deals".
  3. Make the first edit there. It would create a second default view.

Cause (dev's code reading, not seat-verified)

listViewTargetOf resolves the entry's view only from the shell's merged listViews (metadata.objects), and a draft-only object is absent from that. Related: Create View seeds zero columns there, because defaultListColumnsFromObject gets an undefined object definition. The dev reports the same behaviour with the old panel picker, so it predates #30175.

Dedupe (open and closed)

listViewTargetOf → 4 hits, none about this. defaultListColumnsFromObject → 1 hit (#30046). draft-only object default view → nearest is #29814 (a pending draft has no untranslated author-owned read), which is a different read path. New.

Re-check

git grep -n "function listViewTargetOf\|listViewTargetOf =" origin/main -- ui/packages/app-shell/src/views/studio-design

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Nov 4, 2026
  2. objectstack-fleet commented on Nov 4, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p2 · domain:ui · pm:queue · 2026-11-04T20:54Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. added
    bugSomething isn't working
    domain:uiDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    pm:queueReady for the PM dispatch loop
    on Nov 4, 2026
  4. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · os-support-ai · session_01WGufzinedUGSXteN45poyo

    Claim: PM loop round 3
    Session: session_01WGufzigMc8dMgZMjwQtjCq (card thread executor; seat session session_01WGufzinedUGSXteN45poyo)
    Account: os-support-ai
    Branch: claude/project-thread-ldhemo (harness-pinned card thread branch; the claude/issue-<n>-<slug> convention does not apply to a project card thread)
    Worktree: objectstack-issue-30177
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: ui/packages/app-shell/src/views/studio-design/ObjectListViewInspector.tsx (listViewTargetOf, view switcher, Create View column seed) and adjacent studio-design readers, their tests, root .changeset/
    Container & model: M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate; PM judgment call, default tier), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: listViewTargetOf reads only the shell's merged listViews, which omit a draft-only object (Studio code) | no platform path covers a draft-only object's default view | reached by anyone building a new app in Studio Interfaces before first publish
    Thread-read: 6641872582
    Premise: holds (seat read listViewTargetOf on origin/main 31260ca8e: no flagged view ⇒ <object>.default; reproduction owed by the dev first)
    Serial constraints cleared: PR #30175 (#30046, same switcher code) merged 2026-11-05T01:05Z. #30089 (same file) is held by this seat until this card lands.

  5. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · os-support-ai · session_01WGufzigMc8dMgZMjwQtjCq
    os-dev-report

    {
      "issue": 30177,
      "status": "done",
      "branch": "claude/project-thread-ldhemo",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30315",
      "session": "session_01WGufzigMc8dMgZMjwQtjCq",
      "premise_still_valid": true,
      "summary": "Reproduced on main 31260ca8 in the browser: a draft-only object's nav entry with no viewName opened acmetrial_deal.default, the switcher listed Default view beside All deals, and the first edit PUT acmetrial_deal.default with isDefault true, leaving two default list views drafted. useObjectListViewDraft now resolves the entry's default against the merged listViews plus this package's drafted list views (draftedListViewsOf, over the draft-overlaid view list the switcher already reads; no new request), for every object; until that read answers, an entry whose default no merged view flags is held (no buffer load, nothing listed). After the fix the entry opens acmetrial_deal.all, the switcher lists only it, and the first edit writes to it.",
      "tests": "New top-level describe in ObjectListViewInspector.draftOnlyObject-12508.test.tsx (4 pins: drafted default targeted+listed alone+first edit writes it; hold until drafts answer; CONTROL published object no flag targets OBJECT.default; CONTROL draft-only object with no drafted view targets OBJECT.default and the first edit creates it): file 8/8 at bfd2fbff. Ablation via scripts/ablation-replace.mjs, fix committed first, restore proved (blob == HEAD, git diff HEAD empty): draft read removed -> 2 failed 6 passed (viewId acmetrial_deal.default where .all expected); hold forced false -> 1 failed 7 passed (loadedFor listView:acmetrial_deal.default while drafts unread). No dist leg: ui aliases @object-ui to src. Sweep at d0d0f1e6: 210 app-shell test files importing ObjectListViewInspector or StudioDesignSurface, Test Files 210 passed, Tests 1344 passed, VERDICT 0. After merging main 959c26be (rebuilt, full turbo build VERDICT 0): 33 list-view/Interfaces/draft-only files, Tests 183 passed, VERDICT 0; pnpm --filter @object-ui/app-shell run type-check VERDICT 0; eslint on the 2 touched files 0 errors.",
      "gates": "dispatch-gates --commands at bfd2fbff (3 paths vs merge base 959c26be1): 35 commands, run serially under one lock (VERDICT command-exit 0), all exit 0, including check-sdui-manifest.mjs and ui vitest scripts/ (170 passed, 2 skipped files). --ran: 35 derived, 35 run, 0 NOT-MEASURED. Record: ui-orders/30177-gates-ran.list. CI check-runs on #30315: in_progress at report time.",
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "2 — issue_read get and get_comments on #30177 (reads only)",
      "api_writes": "2 — relay pr_create (objectstack-ai/objectstack#30315), and this os-dev-report comment via post-stamped.mjs; plus git push (not REST)",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "class: a · reach: Studio Interfaces on a dev boot, draft-only object acmetrial_deal with no seed source: the first edit of a not-yet-created default view and New view's fallback columns start from zero columns (before leg PUT acmetrial_deal.default with columns [amount] only) because seedColumns = defaultListColumnsFromObject(objectDef) and objectDef comes from the shell's merged objects, which omit a draft-only object · evidence: ui-orders/30177-shots/before-edited.png, before.json; the card's Related paragraph · dedupe words: defaultListColumnsFromObject, seedColumns, draft-only object, Create View columns · carrier: seat (needs its own card; #30177 closes with this PR)"
      ],
      "deviations": [
        "Harness session prompt asks to assign and request review on the new PR; skipped per os-dev rule 2 (pr_create carries no assignees, the seat sets people at hand-over).",
        "The 210-file sweep ran at d0d0f1e6, before the merge of main; after the merge only the 33 list-view/Interfaces/draft-only files were rerun (declared narrowing; CI Test UI runs the full suite). The pin file changed once during the sweep (lint-only refactor of the probe) and was rerun on the final head (8/8).",
        "Main moved 14 commits after the merge (only overlap: 4 added lines in StudioDesignSurface.tsx, a file this PR does not edit); not merged again."
      ]
    }
  6. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · os-support-ai · session_01WGufzinedUGSXteN45poyo

    Landed · PR #30315

    Reading Value
    PR #30315 state merged 2026-11-05T11:16Z via merge queue, head bfd2fbff (the ACCEPTed head)
    merge commit on main 1013ef11617b578c6525e50300f74f2e0b072b3c

    Status: card closed as completed by the merge; pm:dispatched removed.

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:uiDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions