Repository navigation
Studio home loop: Back to home returns to the Studio landing; the two Setup exits say so #12513
Description
Source
Measured on objectui main d4bc81eab, 2026-10-15. Inside a package the shell header's first button, "Back to home" (engine.studio.home, StudioDesignSurface.tsx), navigates to /home, the console home. The Studio landing (/studio, BuilderLanding.tsx: recently viewed, my packages, not in a package, installed) has no way back from inside a package: the package switcher lists packages, Organization flows, Package info & settings and New package, not the landing. On the landing, "Customize with an overlay" opens Setup › All Metadata Types (/apps/setup/metadata?package=…) and the Organization flows surface (/studio/~org/automations) tells an empty rail to "Clone a packaged flow in Setup › Packaged automation"; both leave Studio without saying so.
Target
- The header's first button returns to the Studio landing (
/studio); the console home stays one click away through the landing's own top bar (the ObjectOS mark already links to/home). - The package switcher's first row is "Studio home" (the landing), above the package list.
- The two Setup exits read "Open in Setup" with an outward icon, on the landing's installed cards and in the Organization flows empty state, the latter linking straight to the packaged-automation list it names.
File surface
packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (home button, package switcher), BuilderLanding.tsx, apps/console/src/components/StudioRoute.tsx if the route needs it, packages/app-shell/src/views/metadata-admin/i18n.ts, tests beside.
Acceptance
- A test asserts the home button navigates to
/studioand the switcher's first row to the landing. - Screenshots: the landing's installed card and the Organization flows empty state with the Setup labels, light and dark.
StudioDesignSurface.*.test.tsxgreen.
Constraints
- No change to Setup.
- Existing
data-testids and i18n keys stay; new keys in every locale.
Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff from the 2026-10-15 Studio test pass: objectui main d4bc81eab, HotCRM 63db83e2, the vite console on :5180 against objectstack serve --dev on :4001, viewport 1482 × 1119, dark theme with a light-theme check.
Evidence
Screenshots from the test pass, kept on the temporary branch claude/studio-test-pass-evidence-20261015 of objectstack-ai/objectui (commit 72115588c, never merged: the maintainer ruled that screenshots do not enter main, and asked for a temporary branch referenced from the card). The branch's docs/design/studio-redesign/findings/2026-10-15/README.md maps every file to its card. Pane captures, 800 × 604 of a 1482 × 1119 viewport, dark unless named light.

docs/design/studio-redesign/findings/2026-10-15/12513-back-to-home-lands-on-console-home.jpg — back to home lands on console home.

docs/design/studio-redesign/findings/2026-10-15/12513-organization-flows-empty.jpg — organization flows empty.

docs/design/studio-redesign/findings/2026-10-15/12513-overlay-link-opens-setup.jpg — overlay link opens setup.

docs/design/studio-redesign/findings/2026-10-15/12513-studio-landing.jpg — studio landing.
Parent: #12446
Body refreshed 2026-10-15T15:19Z by the epic PM session: an Evidence section with the test-pass screenshots added.
Activity
objectstack-fleet commentedon Oct 15, 2026
Claim: PM loop round 1 (domain:ui lane queue; an objectui#12446 test-pass card)
Session:
session_01SJn1GEkrbbBQkhGC26wEDwAccount:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-12513-studio-home-loopWorktree:
objectui-issue-12513(in the cloud session's own container)Domain:
domain:uiSeat:
domain:ui#4File surface:
packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx(the shell header's home button,PackageSwitcher, and theAutomationsPillarpackage-less empty block'sactionprop only),studio-design/BuilderLanding.tsx(the installed cards' Setup link),apps/console/src/components/StudioRoute.tsx(only if the/studioroute needs it),metadata-admin/i18n.ts(new keys, or reworded values ofengine.studio.landing.overlay/engine.studio.org.none), new tests beside them, one.changeset/12513-*.md(stop on breach; explain in the report)Container & model:
M,mode:cloud,model: opus(cloud on the maintainer's stance 「可以的话,ui 后续开发尽量用云 session,并且要求截图给我看」; lane scope on 「你也可以接ui车道的卡」; batch 5 on 「上限提到 5,提速」, this session's chat, 2026-10-15)Clause-②: no
Responsibility:
n/a — not a defect cardThread-read: none
Serial constraints cleared: objectui#12510 (its
BuilderLanding.accessibleNames-12510pin on this card'sBuilderLanding.tsx) landed as PR objectui#12580 (3e09c1e). objectui#12514 (f23eb01) moved the Organization flows empty sentence into the sharedStudioEmptyStateblock, which this card's Setup link joins. In flight onStudioDesignSurface.tsx, this seat: objectui#12517 (the Publish and Changes triggers in the same shell header, and the sheet), objectui#12524 (the four item headers) and objectui#12516 (theDataPillaradd-field handler). Any textual overlap is resolved by mergingorigin/main.objectstack-fleet commentedon Oct 16, 2026
os-dev-report
{
"issue": 12513,
"status": "done",
"branch": "claude/issue-12513-studio-home-loop",
"pr": null,
"session": "session_01Li9iYX6uAhVZJgyCfJ1Maz",
"premise_still_valid": true,
"summary": "All three targets are built on 385fa92 (base origin/main 3e09c1e, which had not moved when I last fetched). (1) The shell header's first button now goes to /studio, the Studio landing. It is titled 'Studio home', has the new testid studio-home, and still asks before leaving unsaved pillar edits. (2) PackageSwitcher has a new first row, 'Studio home' (testid studio-switcher-home), above the package list, gated by beforeNavigate like the other rows. (3) The installed card's link (testid studio-landing-overlay unchanged) reads 'Open in Setup' with an ArrowUpRight icon. The empty Organization flows block now has an 'Open in Setup' link (testid auto-empty-open-setup) to /apps/setup/component/automation/packaged. All four PM mechanism assumptions held when measured. Assumption 4's route: objectstack platform-objects setup-nav.contributions.ts declares nav_packaged_automation with componentRef 'automation:packaged'; app-shell registers that ref in builtinComponents and turns it into a URL with componentRefToUrlSegments, read by the console's /apps/:appName/component/:ns/:name route. The link builds the URL from the ref and does not hard-code it. In a live check, clicking it opened the Setup page headed 'Packaged automation'. StudioRoute.tsx needed no change, because /studio already renders BuilderLanding. The claim on the card names this branch. I did not write the card assignee. This container cannot write to GitHub except by git push, so I opened no PR and posted no card comment (see open_questions).",
"tests": "All runs on HEAD 385fa92, through the os-verify-lock. (a) The two new files:
pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/views/studio-design/StudioDesignSurface.homeLoop-12513.test.tsx packages/app-shell/src/views/studio-design/BuilderLanding.setupExit-12513.test.tsxgave VERDICT command-exit 0, 'Test Files 2 passed (2) / Tests 6 passed (6)'. (b) Every StudioDesignSurface..test.tsx plus every BuilderLanding..test.tsx, including BuilderLanding.accessibleNames-12510 and the updated pillarNavGuard: 88 files, VERDICT command-exit 0, 'Test Files 88 passed (88) / Tests 587 passed (587)'. (c) The full package once,pnpm --filter @object-ui/app-shell test, in the foreground via nohup plus tail --pid: VERDICT command-exit 0, 'Test Files 1427 passed | 1 skipped (1428) / Tests 13550 passed | 9 skipped (13559)'. Ablations: each mutation was run through objectstack scripts/ablation-replace.mjs in wrap mode. Each one landed (anchor count went 1 to 0, blob changed), turned the run red, and was restored by blob hash. Results: 1. header shellNavigate(STUDIO_LANDING_PATH) changed to '/home' made 'the header's first button returns to the Studio landing' fail. 2. the switcher row's navigate(STUDIO_LANDING_PATH) changed to '/home' made the switcher test fail. 3. the package-less arm disabled ('packageId === null' changed to 'false') made the Organization flows link test fail. 4. the en value of engine.studio.landing.overlay reverted to 'Customize with an overlay' made the landing label test fail. 5. the route spelled without the 'component/' segment made 2 tests fail. After the restores,git diff HEADandgit status --shortprinted nothing. No dist build is involved: the tests import app-shell source by relative path. Live check on the console (vite :5613, proxied to HotCRM 63db83e underobjectstack dev --freshon :4613, 1280 px): the overlay link text and href, the org link href, the landing after following it ('Packaged automation'), the header title 'Studio home', and both the header button and the switcher row landing on /studio.","gates": "Every exit code below was captured before any pipe, with output redirected to a log.
pnpm --filter '@object-ui/app-shell^...' build(the dependency closure, workspace-concurrency 2): exit 0.pnpm --filter @object-ui/app-shell type-check: exit 0. It runs tsc --noEmit and tsconfig.test.json, which compiles the tests.pnpm --filter @object-ui/app-shell build: exit 0, with '✓ dist completeness: 1 package(s) complete'.pnpm exec eslinton the 6 touched source and test files: exit 0, 0 errors and 22 warnings. All but one warning are pre-existing classes in StudioDesignSurface.tsx and pillarNavGuard. The new one is react-refresh/only-export-components on the exportedpackagedAutomationPath, the same class as the existingoverlayPathexport beside it.pnpm check:i18n-keys: exit 0.pnpm check:i18n-drift: exit 0 ('Every changed designer-table en value was followed by its zh row').pnpm check:i18n-designer-parity: exit 0.pnpm check:i18n-dead-keys: exit 0. That gate is report-only; it now lists engine.studio.home (see open_questions).node scripts/check-changeset-presence.mjs: exit 0 ('4 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)').pnpm check:new-line-citations: exit 0 ('0 new citation(s)'). Control-byte scan of the changed files: no hits. objectui has no scripts/pm/dispatch-gates.mjs, so I derived the gate list by hand from the dispatch; there was no --ran reconciliation. CI check-runs: NOT MEASURED, because no PR is open yet and the PM opens it.","mcp_calls": "8 calls, none of them writes. claude-code-remote add_repo x2: objectstack and hotcrm, access read; both answered read_available and attached nothing. ToolSearch x1. GitHub, read only: mcp__github__issue_read x3 (get #12513, get_comments #12513, get_comments #12446). No GitHub MCP write tool was used.",
"api_writes": "0 REST writes. The only writes are git pushes: claude/issue-12513-studio-home-loop (the empty branch first, then 385fa92) and claude/issue-12513-evidence (bb89675). No PR, no comment, no label write, no assignee write.",
"open_questions": [
{
"question": "The header button now reads a new key, engine.studio.landingHome ('Studio home' / 'Studio 首页'). The old 'Back to home' wording would mislabel a button that goes to the Studio landing. After this change nothing reads engine.studio.home, and the report-only check:i18n-dead-keys lists it. The card's constraint says existing i18n keys stay; the dispatch's assumption 1 would allow retiring a key nothing reads. I followed the ruling and kept the key. Retire it now?",
"options": [
"A: retire engine.studio.home (en and zh rows) in a one-line follow-up once the maintainer agrees",
"B: keep it as an unread row"
],
"recommendation": "A. On the four axes: real business need is zero, since nothing reads it (measured by the dead-keys sweep); long-term soundness and the startup-stage rule both favour retiring a dead declaration at once rather than in stages; no AI-mistake risk either way. I did not do it here because the card's constraint is a ruling."
},
{
"question": "Contract conflict, recorded as the os-dev contract asks. objectstack .claude/agents/os-dev.md says the dev opens the draft PR and posts the os-dev-report comment, and that the file wins where it and the dispatch disagree. The dispatch's degraded channel says not to, because this container's fleet-write relay is refused with a 403. I followed the dispatch: this is a capability gap, not a disagreement on rules. The PM should open the PR from pr_body_draft with assignee os-sales and post this report.",
"options": [
"A: the PM opens the PR and posts the comment (as dispatched)",
"B: the dev retries the write path"
],
"recommendation": "A, because the relay's 403 is outside this session's control, and a retry loop on a 403 is barred by os-dev rule 1."
},
{
"question": "Choices I made within the rulings. (a) Commit trailers: I used the model-free pair that objectui AGENTS.md requires (Claude-Session plus 'Co-authored-by: Claude'), not the harness's model-named trailer. AGENTS.md says the harness reminder yields to it. (b) The Organization flows link is an outline Button asChild wrapping a router Link, not the block's primary create button, so it reads as a way out, not 'create'. It is not gated by confirmLeavePillar: the block shows only when no flow is open, so there is no edit to lose. That matches the landing's own overlay link, which is also ungated.",
"options": [
"A: keep as built",
"B: primary variant, or add a gate"
],
"recommendation": "A. On the four axes: it follows the ruling ('a link, not a create button') and adds no gate with nothing to protect."
}
],
"out_of_scope_findings": [
"class: polish (not filed) · reach: live console on :5613, HotCRM package, Data pillar item header · The in-package read-only link (testid studio-readonly-link, key engine.studio.pkg.readonlyLink, reading 'Read-only · Customize with an overlay') also goes to /apps/setup/metadata?package=… through overlayPath, a third Setup exit that does not say it leaves Studio. The card names two exits and the dispatch's file surface excludes it, so I left it. It is visible in 12513-switcher-studio-home-row-dark.png. · dedupe words: readonlyLink, Customize with an overlay, Open in Setup, studio-readonly-link · carrier: none; listed under Acceptance notes only"
],
"deviations": [
"I edited an existing test outside the dispatch's 'new tests beside them' wording: StudioDesignSurface.pillarNavGuard.test.tsx. Its 'gates the Home button' case clicked title 'Back to home' and expected /home. Target 1 changes both, so the test now clicks 'Studio home' and expects the /studio landing. The confirm and cancel gate assertions are unchanged.",
"Added new data-testids: studio-home, studio-switcher-home, auto-empty-open-setup. No existing testid changed.",
"i18n: reworded the en and zh values of engine.studio.landing.overlay to 'Open in Setup' / '在设置中打开', which the dispatch allows. Added engine.studio.landingHome and engine.studio.org.openSetup in en and zh. That table is the metadata-admin designer table and has no other locales; designer-parity and drift are green. engine.studio.org.none is unchanged, because its sentence still names the list the new link opens.",
"BuilderLanding.tsx imports componentRefToUrlSegments from services/componentRegistry.js. That module's only import is a type import from react.",
"Lock path: AGENTS.md names /home/user/objectstack/scripts/pm/os-verify-lock.sh. In this container the read-only clone lives at /home/user/objectstack-ai/objectstack, so I used the script from there."
],
"files_changed": [
".changeset/12513-studio-home-loop.md",
"packages/app-shell/src/views/metadata-admin/i18n.ts",
"packages/app-shell/src/views/studio-design/BuilderLanding.tsx",
"packages/app-shell/src/views/studio-design/BuilderLanding.setupExit-12513.test.tsx",
"packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx",
"packages/app-shell/src/views/studio-design/StudioDesignSurface.homeLoop-12513.test.tsx",
"packages/app-shell/src/views/studio-design/StudioDesignSurface.pillarNavGuard.test.tsx"
],
"screenshots": [
"https://github.com/objectstack-ai/objectui/blob/bb89675168aad3acdc5241c999965bb6fe72f269/docs/design/studio-redesign/findings/12513/12513-landing-installed-card-light.png?raw=true",
"https://github.com/objectstack-ai/objectui/blob/bb89675168aad3acdc5241c999965bb6fe72f269/docs/design/studio-redesign/findings/12513/12513-landing-installed-card-dark.png?raw=true",
"https://github.com/objectstack-ai/objectui/blob/bb89675168aad3acdc5241c999965bb6fe72f269/docs/design/studio-redesign/findings/12513/12513-org-flows-empty-light.png?raw=true",
"https://github.com/objectstack-ai/objectui/blob/bb89675168aad3acdc5241c999965bb6fe72f269/docs/design/studio-redesign/findings/12513/12513-org-flows-empty-dark.png?raw=true",
"https://github.com/objectstack-ai/objectui/blob/bb89675168aad3acdc5241c999965bb6fe72f269/docs/design/studio-redesign/findings/12513/12513-switcher-studio-home-row-dark.png?raw=true",
"https://github.com/objectstack-ai/objectui/blob/bb89675168aad3acdc5241c999965bb6fe72f269/docs/design/studio-redesign/findings/12513/12513-org-link-lands-on-packaged-automation-dark.png?raw=true"
],
"line_budget": "n/a",
"cleanup": "Stopped the HotCRM backend (:4613) and the vite console (:5613) by the PIDs I started, and confirmed both ports are closed. Removed both worktrees without --force after checking that local HEADs equal the remote branch SHAs (385fa92, bb89675). The read-only clones of objectstack and hotcrm remain under /home/user/objectstack-ai.",
"pr_title_draft": "feat(app-shell): Studio home returns to the Studio landing; the two Setup exits say so",
"pr_body_draft": "(elided by the seat: opened verbatim as the body of PR #12590, read back identical)"
}
Relayed verbatim by seat
domain:ui#4(sessionsession_01SJn1GEkrbbBQkhGC26wEDw) from the cloud session's final message, the degraded write channel. The seat opened the draft PR #12590 frompr_title_draftandpr_body_draft, with assigneeos-sales."pr": nullabove is the session's own value at report time.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Landed · PR #12590 merged as
f5eec63onmain· read 2026-10-16T01:56Zorigin/mainf5eec63data-testid="studio-home"/studio-switcher-homeinStudioDesignSurface.tsx/studioexport const packagedAutomationPathinBuilderLanding.tsx'engine.studio.home'rows inmetadata-admin/i18n.tsStudioDesignSurface.homeLoop-12513.test.tsx,BuilderLanding.setupExit-12513.test.tsx,.changeset/12513-studio-home-loop.mdState change: the card closed as completed through
Fixes #12513, andpm:dispatchedis removed in this act. The cloud sessionsession_01Li9iYX6uAhVZJgyCfJ1Mazis archived.Generated by Claude Code