Repository navigation
feat(app-shell): search on the Studio landing, the palette lists packages, objects and flows (objectui#11863, Q2) - #12044
Conversation
… the /studio landing (objectui#11863, Q2) `CommandPalette` takes `scope="studio"`, a frame outside every app: no app-scoped group, no full-search command (whose link starts with `/apps/APP`), and three Studio groups instead: the packages `fetchPackages` lists, their objects and their flows from the metadata cache, each opening its Studio page through the pillar's `?surface=` deep link; a package-less flow opens in the package-less scope. Nothing is read until the palette opens. `StudioLanding` mounts `CommandPaletteProvider` and the palette, so the `studio` header draws its search trigger under objectui#11912's rule and Ctrl+K opens it. Two pack rows, `console.commandPalette.packages` and `.flows`, in all ten packs. Claude-Session: https://claude.ai/code/session_01CijGnfWLxTLUFcJkY2ouUw Co-authored-by: Claude <noreply@anthropic.com>
…jectui#11863) Claude-Session: https://claude.ai/code/session_01CijGnfWLxTLUFcJkY2ouUw Co-authored-by: Claude <noreply@anthropic.com>
…ole guide and a changeset (objectui#11863, Q2) Claude-Session: https://claude.ai/code/session_01CijGnfWLxTLUFcJkY2ouUw Co-authored-by: Claude <noreply@anthropic.com>
… `any` (objectui#11863) Claude-Session: https://claude.ai/code/session_01CijGnfWLxTLUFcJkY2ouUw Co-authored-by: Claude <noreply@anthropic.com>
…nt (objectui#11863) Claude-Session: https://claude.ai/code/session_01CijGnfWLxTLUFcJkY2ouUw Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
…ette mount (objectui#11863, Q2) The pending `.changeset/11863-studio-header.md` ends its first paragraph with "No command palette is mounted on `/studio`, so the header shows no search trigger there." PR objectui#12044 makes that false. Append-only, in the objectui#6152 round-12 shape: the sentence stays, and one dated note after its paragraph says that from objectui#11863 Q2 the landing mounts the palette in its `studio` scope, so the header draws the trigger and ⌘K opens it. Claude-Session: https://claude.ai/code/session_01CijGnfWLxTLUFcJkY2ouUw Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Read: card objectui#11863 (body and all 22 comments, the retriage rulings Check-runs on this head, as last read in this act: 42 runs; 33 ① Derived judgments
② Semver level
③ Boundary flagsDev flags, report
Dev flags, report Acceptance notes in the PR body: the pillar builder mounting no palette is inside the claim ( Rulings: Q2 → A was conditioned on a cross-package flow read; it exists (① 3), so A with flows is the right build and C is not invoked. "Ordered after objectui#11912": that card closed through PR objectui#11987 before this claim, per the claim and the Q3 ACCEPT. The lane is Carried from the Q1 ACCEPT Closing keyword: the PR's first line closes this card on merge. Q1 and Q3 landed as Implemented-by: VERDICT: PASS |
Fixes #11863
Clause-②: yes
What this does
Q2 of objectui#11863, search on the Studio landing, as ruled in retriage
6054672824("Q2 → A, with C as the fallback if no read lists flows across packages"). A read that lists flows across packages exists, so this builds A with flows. Q1 (PR #12004) and Q3 (PR #11996) have landed; Q2 is the card's last ruled item.StudioLanding(apps/console/src/components/StudioRoute.tsx) mountsCommandPaletteProviderandCommandPalette scope="studio". Under the provider, thestudioheader draws its Search trigger through objectui#11912's existing rule, andCtrl+K/⌘Kopens the palette.AppHeader's rule is unchanged; only its comment now names the/studiomount.CommandPalettegets a declared second scope.scope="studio"takes no other prop: there is no active app, so the scope has no app navigation group, no record search, no app switching, and no full-search command (its link is/apps/APP/search). It lists three Studio groups instead:fetchPackages, the list the landing and its switcher read (kernel packages already left out). Each opens/studio/PKG/data, as a landing card does.useMetadata().objects, each under the package it declares (_packageId), opened at/studio/PKG/data?surface=object:NAME. An object whose package is not in the list, or that has no package, has no Studio page and is left out.flowlist, opened at/studio/PKG/automations?surface=flow:NAME. A flow that belongs to no package opens in the package-less scope,/studio/~org/automations?surface=flow:NAME(studioOrgScopePath, objectui#11553).matchesPaletteQuery, the rule the palette's other entries use (objectui#11812). An object or packaged flow shows its package's name on the right. Nothing is read until the palette opens. The theme commands and the recently viewed records stay.console.commandPalette.packagesandconsole.commandPalette.flows. The objects group reusesconsole.commandPalette.objects.packages/app-shell/README.md(the palette section) andcontent/docs/guide/console.md(a "Search in Studio" row). Changeset.changeset/11863-studio-search.md. The pending Q1 changeset.changeset/11863-studio-header.mdgains one append-only dated note (patch round 1, see Acceptance notes).Contract face (Clause-② yes, widening)
@object-ui/app-shell,CommandPaletteprops: a second form,scope="studio", which takes no other prop. The in-app form (apps,activeApp,objects,onAppChange, optionaldataSource) is unchanged and still required; it leavesscopeout. The props type is not exported by name. No export is added or removed. The scope is declared, not inferred from a missingactiveApp. A type pin in the new test holds both directions:CommandPalette scope="studio" activeApp=...and a bareCommandPaletteare compile errors. The pins are two@ts-expect-errorlines that the package'stype-check(tsc -p tsconfig.test.json) compiles.@object-ui/i18n: the exportedenpack andTranslationKeysgainconsole.commandPalette.packagesandconsole.commandPalette.flows. Nothing is removed.@object-ui/app-shellminor,@object-ui/i18npatch,@object-ui/consolepatch. That follows the Q3 changeset's precedent for added pack rows. No major.The PM hypotheses, measured
049012b.CommandPaletteProviderwas mounted only inConsoleLayout.AppHeaderasksuseCommandPaletteProviderMounted(). In the reverse leg below, baseStudioRoute.tsxgives "Unable to find an element by: [data-testid="action:command-palette:open"]" on/studio. So this card mounts the palette itself.StudioLandingonly, not above Home, Organizations or AI. In a real browser,/homestill draws 0 desktop and 0 compact triggers on this branch. Nothing was widened or narrowed silently.049012b. A scratch probe (deleted, never committed) put the baseCommandPalette(blob77b85897) at/studiowithappsempty andactiveAppnull. The querysearchrendered the full-search item, and picking it went to/apps/undefined/search: 1 passed. This branch drops that command and every app-scoped group in thestudioscope, by declaration.getItemsByType('flow')is the unscopedGET /api/v1/meta/flow. It is the same unscoped list thatloadPackageLessSurfacesnarrows, and that function's doc says "The unscoped list also carries every PACKAGED item". On the server,getMetaItems({ type })with no package returns every package's items. The URL shapes come fromStudioDesignSurface's routing onmain:PILLAR_FOR_SURFACE_TYPE(object todata, flow toautomations), the?surface=TYPE:NAMEdeep link (DESIGNER_SURFACE_PARAM,formatSurfaceParam) andstudioOrgScopePath. These were checked against a mocked API in the browser. I did not check them against a live objectstack server, because the sibling checkout is not installed or built in this container.049012bis 3,238,404 B ("3162.5 KB gzipped across 289 of 2474 chunks (budget: 3204.6 KB, headroom: 42.1 KB)"). Branchdbca37fis 3,239,095 B ("3163.2 KB gzipped across 289 of 2474 chunks (budget: 3204.6 KB, headroom: 41.4 KB)"). The delta is +691 B, under the 3,281,467 ceiling, which was not touched. The bytes land in theindexchunk (+770 B).packages-iowas already in the eagerPackagesPagechunk on base, sofetchPackagesadds no module.i18n-locale-engrows 45,231 to 45,241 B, under its own ceiling.b6a003echanges one test docstring afterdbca37f, with no source change.console.commandPalette.objectsfits the objects heading and is reused. No row inpackages/i18nfits "Packages" or "Flows" as a group heading:common.packageandpackagedAutomation.colFloware singular, andconsole.studio.titleis the product name. The designer table (metadata-admin/i18n.ts) hasengine.packages.title, but the palette reads onlypackages/i18nthroughuseObjectTranslation. So the PR adds two rows in all ten packs.Verification (head
b6a003e)Union, every test file that imports or names
CommandPalette,CommandPaletteProvider,AppHeader,StudioRouteorcommandPalette(git grep -l, 59 files), underos-verify-lock: "Test Files 59 passed (59)", "Tests 515 passed (515)".packages/i18n/: "Test Files 82 passed (82)", "Tests 1316 passed | 13 skipped (1329)".scripts/__tests__/: "Test Files 179 passed | 2 skipped (181)", "Tests 5452 passed | 2 skipped (5454)".Type-check:
pnpm --filter @object-ui/i18n --filter @object-ui/app-shell --filter @object-ui/console run type-check, all three script names echoed, exit 0. This ran afterturbo run build --filter='@object-ui/console^...'.New tests:
CommandPalette.studioScope-11863.test.tsxhas 10 cases: groups and exclusions, each target URL, matching, no app-scoped entry plus an app-scope CONTROL, nothing read while closed plus a CONTROL.StudioRoute.searchPalette-11863.test.tsxhas 4 cases through the realstudioRoutes: both triggers, click,Ctrl+K, and picking a package opens its builder. The 11912 pin's CONTROL now includesstudiounder a provider.Reverse verification, from committed
dbca37f.CommandPalette.tsxandStudioRoute.tsxwere swapped to their base blobs (77b85897,9e2098ca; anchorsuseStudioPaletteEntries1 to 0 andscope="studio"1 to 0). The run gave "Tests 13 failed | 8 passed (21)". Red: the 9 studio-scope cases (the base palette throws "Cannot read properties of undefined (reading 'filter')" with no app props) and the 4 route cases (no trigger). Green: the app-scope CONTROL and the 7 cases of the 11912 pin. The trap restored both files fromHEAD: blobs05643164,b314334dequalHEAD, andgit diff HEADis empty.Gates, exit 0 each:
check:i18n-keys("Every in-scope call-site key resolves against the en pack (3313 keys)"),check:i18n-drift,check:i18n-dead-keys(report-only; neither new key listed),check:eager-locale-catalogues,check:new-line-citations("0 new citation(s)"),check:control-bytes,check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shapeandcheck:test-path-roots. Also exit 0:check:changeset-claims(report-only;11806-login-server-unreachable.mdnamespackages/app-shell/README.mdfor its sign-up table, which this PR leaves alone),check:pending-changeset-literals,check:doc-fences,check:icon-record-names,check:shell-escape-residue,check:unreferenced-sources,check:readme-exports,check:doc-snippets,check-changeset-presence("17 source file(s) of 3 released package(s) changed, and this change declares 1 changeset(s)") andcheck-changeset-no-major.check-governed-queue-guard --testover the 20 paths says NOT GOVERNED.eslint:
--no-inline-config --format jsonover the 17 changed ts/tsx files gives 0 errors. Each of the 5 edited files has the same warning count as its base blob through--stdin: 2, 13, 22, 11 and 13. The two new test files have 0. The population is the config's**/*.{ts,tsx}and the file count comes from the JSON output. The config is not type-aware (noparserOptions.project/projectService), so this diff cannot move any untouched file's verdict. The repo-widepnpm lintis CI's.Patch round 1, head
12f3f09. One commit, changeset text only:.changeset/11863-studio-header.md, 2 lines added and 0 removed. At that head, exit 0 each:check-changeset-presence("17 source file(s) of 3 released package(s) changed, and this change declares 1 changeset(s)"),check-changeset-no-major,check:changeset-claims(report-only, the same 11806 reading as above),check:pending-changeset-literals,check:control-bytesandcheck:new-line-citations("0 new citation(s)"). The union, type-check, eslint, bundle and browser readings in this section are fromb6a003eanddbca37fand were not re-run: no source or test file changed. The two bot comments on this PR were read: the changeset-claim re-read (6077690455) names.changeset/11806-login-server-unreachable.mdforpackages/app-shell/README.md, and its paragraph is about the sign-up table, which this PR leaves alone, so it still holds; the CI Console Performance Budget onb6a003e(6077731629) reads PASS, 3163.4 KB against 3204.6 KB.Real browser (Chromium
/opt/pw-browsers/chromium, 1440x900,vite previewof thedbca37fbuild on a private port, API mocked withpage.route;pageErrorsempty)/studio/studio?palette=1sys_userand the kernel flow absentsearch/apps/employee, picked/studio/com.acme.hr/data?surface=object%3Ahr_employeeCtrl+Kon/studio, package-less flow picked/studio?palette=1, then/studio/~org/automations?surface=flow%3Aorg_cleanup/apps/crm_appsearchgives the full-search command/home(untouched frame)Acceptance notes
.changeset/11863-studio-header.md(Q1) ends its first paragraph with "No command palette is mounted on/studio, so the header shows no search trigger there." This PR makes that sentence false. Patch round 1 leaves the sentence as written and appends one dated note after its paragraph, in the objectui#6152 round-12 shape: from objectui#11863 Q2 (this PR) the landing mounts the command palette in itsstudioscope, so the header draws the search trigger and⌘Kopens it. This PR's own changeset also states the reversal in its first paragraph./studio/PKG/TAB) mounts no palette. It isStudioDesignSurface's full-screen frame, which this claim does not hold.Session:
https://claude.ai/code/session_01CijGnfWLxTLUFcJkY2ouUwGenerated by Claude Code