Skip to content

Studio home loop: Back to home returns to the Studio landing; the two Setup exits say so #12513

Closed

Description

@objectstack-fleet

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

  1. 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).
  2. The package switcher's first row is "Studio home" (the landing), above the package list.
  3. 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

  1. A test asserts the home button navigates to /studio and the switcher's first row to the landing.
  2. Screenshots: the landing's installed card and the Organization flows empty state with the Setup labels, light and dark.
  3. StudioDesignSurface.*.test.tsx green.

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.

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

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

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

studio landing
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

  1. added
    enhancementNew feature or request
    pm:epicParent delegated to a dedicated epic PM — other PMs never dispatch into its subtree
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    on Oct 15, 2026
  2. added and removed
    pm:epicParent delegated to a dedicated epic PM — other PMs never dispatch into its subtree
    on Oct 15, 2026
  3. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (domain:ui lane queue; an objectui#12446 test-pass card)
    Session: session_01SJn1GEkrbbBQkhGC26wEDw
    Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12513-studio-home-loop
    Worktree: objectui-issue-12513 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (the shell header's home button, PackageSwitcher, and the AutomationsPillar package-less empty block's action prop only), studio-design/BuilderLanding.tsx (the installed cards' Setup link), apps/console/src/components/StudioRoute.tsx (only if the /studio route needs it), metadata-admin/i18n.ts (new keys, or reworded values of engine.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 card
    Thread-read: none
    Serial constraints cleared: objectui#12510 (its BuilderLanding.accessibleNames-12510 pin on this card's BuilderLanding.tsx) landed as PR objectui#12580 (3e09c1e). objectui#12514 (f23eb01) moved the Organization flows empty sentence into the shared StudioEmptyState block, which this card's Setup link joins. In flight on StudioDesignSurface.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 (the DataPillar add-field handler). Any textual overlap is resolved by merging origin/main.

  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    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.tsx gave 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 HEAD and git status --short printed 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 under objectstack dev --fresh on :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 eslint on 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 exported packagedAutomationPath, the same class as the existing overlayPath export 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 (session session_01SJn1GEkrbbBQkhGC26wEDw) from the cloud session's final message, the degraded write channel. The seat opened the draft PR #12590 from pr_title_draft and pr_body_draft, with assignee os-sales. "pr": null above is the session's own value at report time.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #12590 merged as f5eec63 on main · read 2026-10-16T01:56Z

    probe on origin/main f5eec63 reading control
    data-testid="studio-home" / studio-switcher-home in StudioDesignSurface.tsx 1; 1 the header button and the switcher row lead to /studio
    export const packagedAutomationPath in BuilderLanding.tsx 1 the Setup link built from its component ref
    'engine.studio.home' rows in metadata-admin/i18n.ts 0 retired per ACCEPT ruling 1
    StudioDesignSurface.homeLoop-12513.test.tsx, BuilderLanding.setupExit-12513.test.tsx, .changeset/12513-studio-home-loop.md present —

    State change: the card closed as completed through Fixes #12513, and pm:dispatched is removed in this act. The cloud session session_01Li9iYX6uAhVZJgyCfJ1Maz is archived.


    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:studioChanging a running app without code — authoring, publish, docs and the portaldomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions