Repository navigation
console sidebar: the ⋯ menu's Design entry opens the metadata-admin page, which calls a packaged object locked, while the app bar's Edit app opens Studio's Data surface for the same object — one designer, one destination #12520
Description
Filing gate ① (a product defect, measured on main), filed on the maintainer's word (chat, 2026-10-15, session session_019YFzJp4o8Ck4NsT1toC4UP, seat account os-bill): the seat ran a functional audit of the HotCRM console on objectui main 720f6d4 (report, private to the maintainer: https://claude.ai/artifact/XPrn5eZMsQaKUgasMJEMmR, finding F2, figures 11 and 12), and the maintainer answered 「同意开卡,使用 pm-dispatch 创建卡片」. Quota note: the audit's cards exceed the filing gate's three-per-fire quota on that word, which approved the report's card list as a set.
Parent: objectstack-ai/objectstack#25945; a follow-up of #12427's merged half (PR #12443, a8e5b73, which added the Design entry). Blocks nothing; nothing blocks it.
Reader who acts: the domain:ui lane's next dispatch (seat post #9800), one dev round in @object-ui/app-shell (SidebarItemMenu.tsx and its tests), size S.
Dedupe (MCP search_issues, scope objectstack-ai/objectui, all states, read 2026-10-15T14:14Z): "sidebar item menu Design entry opens metadata admin route instead of Studio locked metadata read-only packaged app designer" → 15, top 8 read: #12496 (open, a ?tab= deep link on the metadata item page), #12306, #12303, #12169 (Studio offered Edit on a packaged item the server refuses, ADR-0131 D6), #11781, #11591, #11167, #11153 (closed, Studio pillars). None is this card; #12169 is the ruling this card follows (a managed item is never edited outside what the hatch allows).
What happens
Two controls say "design this object" and land on different pages. The app bar's Edit app button (pencil) opens Studio's Data surface for the current object: /studio/app.objectstack.hotcrm/data?surface=object:crm_lead, with the object's fields, forms, validations, hooks, actions, API and settings tabs. The sidebar entry's ⋯ menu's Design entry (and the Design entry of an object: / dashboard: / page: favorite) opens the metadata-admin page /apps/app.objectstack.hotcrm/metadata/object/crm_lead, which for the packaged HotCRM object shows a create-only badge and the notice that the metadata is locked and cannot be edited or deleted (app.objectstack.hotcrm@4.0.1), then a read-only field list. A maintainer who clicks Design from the sidebar is told the object cannot be designed; the same maintainer who clicks the pencil designs it.
Readings (objectui origin/main 720f6d4, read 2026-10-15T14:15Z)
packages/app-shell/src/layout/SidebarItemMenu.tsxlines 61–72 (sidebarItemDesignPath) and 81–86 (favoriteDesignPath): both build${basePath}/metadata/${type}/${name}, the metadata-admin router (metadata/:type/:name, declared byDefaultAppContent), chosen on console shell: the page-header star and the sidebar pin become one "Pin to sidebar" action in the page overflow menu, landing in the Pinned section at the top; the app sidebar's bottom Favorites group goes #12427 becausePageView's Edit-in-studio button sends a page there.packages/app-shell/src/layout/AppHeader.tsxlines 371 and 720–728: the Edit app button opensstudioDesignPath, the Studio surface for the route's item (/studio/:packageId/data?surface=object:NAMEfor an object; the comment at line 715 namesinterfaces?surface=dashboard:NAMEfor a dashboard).- Browser reading (1440, HotCRM, admin): Edit app → the Studio Data surface, 线索 ·
crm_lead· 45 fields, seven tabs. Sidebar ⋯ → Design → the metadata page with the locked notice, 9.1 s after the click in dev mode (the chunk), 0.3 s of its own loading.
What to build
- The sidebar ⋯ menu's Design entry and the favorites' Design entry open the same destination the app bar's Edit app opens for that item type: the Studio surface (
studioDesignPath's derivation, shared, not a second table). Anobjectentry opens the Data surface withsurface=object:NAME; adashboardentry the Interfaces surface withsurface=dashboard:NAME; apageentry whatever the app bar opens for a page today. One derivation for both controls;sidebarItemDesignPath/favoriteDesignPathbecome callers of it or go. - The entry's gate stays what console shell: the page-header star and the sidebar pin become one "Pin to sidebar" action in the page overflow menu, landing in the Pinned section at the top; the app sidebar's bottom Favorites group goes #12427 set (admin and
canAuthorMetadata); a packaged item still opens, read-only, where Studio already shows packaged items read-only (finding(app-shell): Studio offers Edit on a packaged item of a type the OS_METADATA_WRITABLE hatch elevates, and the server refuses the save (ADR-0131 D6: the hatch never opens a managed item) #12169's ruling), with no "locked" dead end. - The metadata-admin route itself is untouched: it keeps its own entry points.
Acceptance
SidebarItemMenutests: the Design entry of anobject,dashboardandpagenavigation entry, and of the matching favorites, resolves to the same path the app bar's Edit app resolves for that item; the existing gate tests (admin, authoring, no entry forurl/component/ records / apps) unchanged.- Browser reading by the landing seat at 1440 on HotCRM: sidebar Leads ⋯ → Design and the app bar's pencil on the Leads list land on the same Studio Data surface for
crm_lead. pnpm testfrom the repo root green on the affected files; a changeset (patch) for@object-ui/app-shell.
Out of scope
- Studio's read-only presentation of packaged items; the metadata-admin page's own content; adding Design for entry types console shell: the page-header star and the sidebar pin become one "Pin to sidebar" action in the page overflow menu, landing in the Pinned section at the top; the app sidebar's bottom Favorites group goes #12427 left undecided.
Attribution: written by the domain:ui seat in session session_019YFzJp4o8Ck4NsT1toC4UP (account os-bill) on the maintainer's words quoted above.
Screenshots (added 2026-10-15T14:45Z, on the maintainer's word 「专用分支存图,卡里嵌 raw 链接」)
The images live on the attachment branch claude/ui-audit-2026-10-15-shots of objectstack-ai/objectui (commit 918a251, never merged; index at https://github.com/objectstack-ai/objectui/blob/918a2510a54bd6875b90eb6996d098c3ec0451dd/docs/design/console-audit-2026-10-15/README.md). Full set and figure numbers: the audit report linked above.
The app bar's Edit app: Studio's Data surface for crm_lead
The sidebar ⋯ menu's Design entry: the metadata-admin page with the locked notice


Activity
objectstack-fleet commentedon Oct 15, 2026
Claim: PM loop round 1 (
priority:p1; filed on the maintainer's 「同意开卡,使用 pm-dispatch 创建卡片」)Session:
session_01JZnppgHRp4sREcouhkQYDBAccount:
sunhaolinBranch:
claude/issue-12520-design-entry-studioWorktree:
objectui-issue-12520Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/app-shell/src/layout/SidebarItemMenu.tsx(sidebarItemDesignPath:61–:72andfavoriteDesignPath:81–:86onmain720f6d4, and their callers' wiring), routed through the existingappStudioRoutePathinpackages/app-shell/src/utils/appRoute.ts, which the app bar's Edit app already uses (AppHeader.tsx:376); theSidebarItemMenutests; one.changeset/12520-*.md. The metadata-admin route and page,AppHeader.tsx, Studio's read-only presentation and any@object-ui/*export are outside the surface (stop on breach; explain in the report).Container & model:
S,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuinames no path-derived mandate)Clause-②: no
Responsibility:
@object-ui/app-shell'sSidebarItemMenu, which builds a second, metadata-admin destination for "design this item".appStudioRoutePath, which the app bar already uses.Thread-read: none
Serial constraints cleared: read at objectui
mainc3de0bc73d. Nopm:dispatchedclaim in the lane namesSidebarItemMenu.tsxorappRoute.ts: this seat's objectui#12483, and seat 2's objectui#12474, Studio Data pillar: the Records grid draws fewer rows than its footer counts, with a stretched gap before the last drawn row (HotCRM crm_account, 10 records, 1280 x 900) #12480, security(app-shell): AiChatPage auto-sends ?handoffPrompt= from the URL as the build agent's first message, so a crafted link makes a signed-in user author (and, with autoPublishAiBuilds, publish) metadata in one click #12493 and Studio flow checker: a flow CEL guard readingvars.xorcurrent_user.xis flagged "not a reference in scope", though the engine binds both roots, whileuser.x, which the engine does not bind, passes silently #12499, read in this act.Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
os-dev-report
{
"issue": 12520,
"status": "done",
"branch": "claude/issue-12520-design-entry-studio",
"pr": "#12539",
"session": "session_01JZnppgHRp4sREcouhkQYDB — the dispatching seat session (subagent run; matches the claim comment 6194597054)",
"premise_still_valid": true,
"summary": "Design now opens the Studio surface. The sidebar ⋯ menu Design entry and a favorite Design entry open the destination the app bar Edit app opens for that item: sidebarItemDesignPath and favoriteDesignPath (SidebarItemMenu.tsx) now call appStudioRoutePath. They pass the route the entry opens, in the {type, name} shape AppHeader reads off the URL. An object entry opens data?surface=object:NAME. A dashboard or page entry opens interfaces?surface=TYPE:NAME. There is no second table, and the gate (isAdmin && canAuthorMetadata, read in the menu) and SidebarItemMenuProps are unchanged. Which app: a nav entry uses the sidebar activeApp. A favorite uses the app its own href names (/apps/APP/...), so a favorite starred in another app lands in that app package. An app with no owning package, or sys_metadata, answers null: Design hides, as the pencil does, with no metadata-admin fallback. The four mechanism assumptions were measured on c3de0bc and all hold. A1: the only callers are UnifiedSidebar and the 12427 test; ObjectView imports only FavoriteMenuItem and useObjectListFavorite. A2: activeApp comes from the same useMetadata().apps catalog, with no new read. A3: pinned. A4: no export is added; the helper is imported from ../utils/appRoute.js. Files outside the claim surface: the app-shell README, in its App to Studio bridge section, per AGENTS.md #2 (docs-driven); the same edit corrects that section stale object-route sentence. Also UnifiedSidebar.favoritesMenu-12427.test.tsx, whose fixture app gained an owning package because A3 now hides Design without one; its gate assertions are unchanged. Asked by the dispatch, PageView Edit-in-studio: I recommend it follow, but it is not changed here; see open_questions. The landing seat 1440 HotCRM browser reading is not taken by me, and the PR body says what it should show. The worktree is removed (node_modules first; it was clean).",
"tests": "All runs from the repo root through os-verify-lock. At the final head 3c13a36, clean tree: (1) the affected union, 67 files: every SidebarItemMenu*, UnifiedSidebar*, appRoute* and AppHeader* test, the ObjectView* tests naming the menu or favorites, every other test rendering UnifiedSidebar or SidebarItemMenu, and the 3 tests reading the app-shell README. Result: Test Files 67 passed (67), Tests 634 passed (634), VERDICT command-exit 0. (2) The census and ratchet tests on the diff subject, 85 files: all census and ratchet tests under packages/app-shell, the cross-package censuses reading app-shell, and the scripts/ tests over the test population. Result: Test Files 85 passed (85), Tests 2121 passed | 1 skipped (2122), VERDICT command-exit 0. New file SidebarItemMenu.designOpensStudio-12520.test.tsx (9 cases) renders the real AppHeader on each entry route and pins Design path == the Edit app href for object, dashboard and page entries and favorites, a cross-app favorite, and the A3 nulls (no package, sys_metadata, href naming no catalog app). Updated: SidebarItemMenu-12427 (Design lands on /studio/com.acme.crm/data?surface=object:crm_lead; gate tests unchanged) and UnifiedSidebar.favoritesMenu-12427 (+2 click-through pins). Type-check: pnpm --filter @object-ui/app-shell type-check (tsc --noEmit && tsc -p tsconfig.test.json) exits 0 at 0353d94, after the turbo build of the app-shell^... closure; the later commit is README-only. Ablation: two legs via objectstack scripts/ablation-replace.mjs in wrap mode on src. The tests import the source relatively, so no dist is involved. For each leg the tool proved anchor 1 to 0, a blob change, then restore blob == HEAD 2341f0ea95bd with git diff HEAD empty. Leg 1, sidebarItemDesignPath back to /apps/APP/metadata/TYPE/NAME: 9 failed | 27 passed (36), the predicted set. Leg 2, favoriteDesignPath likewise: 4 failed | 32 passed (36). That is one more than predicted: the no-catalog-app favorite test went red through its third assertion, an app without a package. Expected direction: turn red. Observed: red.",
"gates": "objectui list derived by hand from package.json check:* and lint.yml, repo-gates.yml, changeset-guard.yml, changeset-presence.yml, line-citation-gate.yml and performance-budget.yml. Local, exit captured to a file before any pipe, all 0: check-changeset-presence, check-changeset-no-major, check-changeset-fixed, check-changeset-overwrite, check-changeset-claims, check-pending-changeset-literals, check-control-bytes, check-new-cross-file-line-citations (VERDICT 0 new citations), check-vi-mock-specifiers, check-vi-mock-inherit, check-vi-mock-override-shape, check-test-path-roots, check-doc-links, and check-governed-queue-guard --test (NOT GOVERNED). eslint on the 5 changed source and test files: exit 0, 0 errors. Warnings are equal base vs head (SidebarItemMenu 3 = 3, UnifiedSidebar 7 = 7) and the new test has 0. NOT MEASURED: check-readme-exports exit 1 on a missing prerequisite (8 unbuilt packages, dist/index.d.ts not on disk), not a judgment. The README edit adds no fence or import, and CI repo-gates builds ./packages/* first. Not run locally, CI-owned: full lint, test shards 1-16, Build and E2E, Bundle Analysis, performance budget. PR check-runs at report time (36): Changeset Fixed Group Check success, label success; Test (coverage), coverage shards and dependabot skipped. In progress: Repo Gates, Lint, Type Check, Test shards 1-16, Build and E2E, Build Docs, Test (dist pins), Bundle Analysis, Changeset Declaration, Changeset Claim Re-read, Changeset Bump Policy, Changeset Overwrite Report, Line Citation Gate, Governed Surface Queue Guard, Spec Main Shape Gate, Live E2E (informational). PR mergeable_state behind, not conflicting: main moved from c3de0bc to 2bacbf0 without touching any changed file, appRoute.ts or AppHeader.tsx, so no merge was made.",
"mcp_calls": "5 — all reads: issue_read get (12520), issue_read get_comments (12520), pull_request_read get (12539), pull_request_read get_check_runs (12539), issue_read get_comments (12520, read-back of this report). No MCP write tool.",
"api_writes": "2 relay strokes (repository_dispatch to objectstack-ai/objectstack, executed by fleet-write.yml as objectstack-fleet[bot]). (1) pr_create: POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos//issues/12539/assignees [sunhaolin], run 38760216582, relay read-back 9394 bytes sent = 9394 stored. (2) comment: POST /repos//issues/12520/comments (this os-dev-report). Plus 3 git pushes of the branch (the empty probe, 0353d94, 3c13a36), which are not REST. No label writes.",
"open_questions": [
{
"question": "PageView Edit-in-studio (openInStudio navigates to /apps/APP/metadata/page/NAME): should it follow the Design entry to the Studio Interfaces surface? On a page route the app bar pencil and the app switcher Studio row already go to /studio/PACKAGE/interfaces?surface=page:NAME, as pinned by AppHeader.pageRouteNoAuthoringHandles-12198. After this PR the sidebar Design for that page does too. That leaves PageView pencil, labelled Edit in studio, as the one handle on the screen with another destination.",
"options": [
"A: route it through appStudioRoutePath with the same A3 rule. One destination on the page route. Cost: it hides for a page whose app has no owning package, where today it is the working editor (metadata-admin). About S, PageView.tsx plus its 10899 and 12198 pins.",
"B: leave it on metadata-admin. No change. Two destinations stay on the same screen, one of them labelled Studio."
],
"recommendation": "A, because it is the same one-designer-one-destination defect this card removes, on the same screen, and the label already names Studio. It needs a ruling that hiding it for package-less apps is acceptable, as A3 ruled for the sidebar. It is a source reading, not a browser measurement, so the carrier is the dispatching seat, not a filed card."
}
],
"out_of_scope_findings": [
"carrier: domain:ui seat 1 PM (asked in the dispatch) · PageView Edit-in-studio opens metadata-admin while the app bar pencil and app switcher row open Studio for the same page; a source reading via PageView openInStudio and the 12198 pins, with no browser measurement · noted, not filed · dedupe words: PageView edit in studio metadata page studio interfaces surface pencil"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Landed ·
domain:uiseat 1 ·session_01JZnppgHRp4sREcouhkQYDB· 2026-10-15T17:21Zmain646307f37aat 2026-10-15T17:19Z. It has one parent,5249c24350, and is an ancestor oforigin/main.646307f37ato the accepted head3c13a36aed.packages/app-shell/README.mddiffers as a blob only because objectui#12483's PR feat(app-shell): the served approval request page shows the declared amount and a snapshot summary (objectui#12483) #12533 (521817ce9d) edited the same README after this PR's merge basec3de0bc73d. This PR's README hunks, againstmerge-base(parent, head), are identical to the merge's.Fixes objectstack-ai/objectui#12520. The only issue closed with the merge is this card, ascompleted./studio/app.objectstack.hotcrm/data?surface=object:crm_lead.6197767493).PageView「Edit in studio」 handle still opens metadata-admin. It is filed as objectui#12540.6194597054, report6195774256, ACCEPT6197767493.Generated by Claude Code
fix(app-shell): the sidebar Design entry opens the Studio surface the…