Skip to content

Commit 73a3ef9

Browse files
[maintainer] refactor(app-shell): move Studio's package switcher out of StudioDesignSurface.tsx (slice 2) (#30008)
<!-- claude-projects-attribution: {"github_login":"os-support-ai"} --> _Requested by **Yibo Wang** · [project thread](https://claude.ai/code/project/chan_01BVUyyPie8gHwoPM18iABwB?thread=cmsg_01BVUyyPie8gHwoPM18iABwBCE4YXYCrA6G1yrthEDVvNJ)_ Refs #29988 ## 维护者速读 - 改了什么:把 Studio 顶栏的「套件切换器」(套件列表、新建套件、套件详情、套件被删后的跳转)及它与主界面共用的两个常量(663 行)原样搬进同目录新文件 `PackageSwitcher.tsx`,主文件 11,884 → 11,205 行;顺带把 QA 清单里两处还指着旧文件的出处改指新文件。 - 为什么改:#29988 按裁定 #24586 A 逐片只搬不改,把这个文件拆到 1 万行以下;这是第 2 片(接缝表第 2 行),第 1 片是 #30002。 - 风险与回滚:无行为变化,搬走的两段代码逐字节一致,只多了 import 和三个 `export`;对外类型声明 700 个文件逐字节不变;回滚即 revert 本 PR。 - 先看:`StudioDesignSurface.tsx` 的 import 段;`PackageSwitcher.tsx` 的 import 段与三个 `export`;`studio-authoring.json` 两处出处改动与新加的 history 行。 - 两分钟验证:在本分支跑下方「Verification」里的两条 `cmp` 命令,预期都无任何输出(逐字节相同)。 - 需要你做的:无,席位落地。 Clause-②: no Metadata-protocol: none ## Seam table Carried forward from #30002. Base lines below are at `origin/main` `f7aab8958` (this PR's base, after slice 1), where `ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx` is 11,884 lines. "Left" is the file's line count after that row and every row above it: rows 1–2 are measured, the rest are estimates (lines removed, plus about two import lines per slice). Every seam is module-scope; no seam closes over another component's state. | # | Seam | Base lines | Size | Reads from the rest of the module · hooks it calls | Imported by | Risk | Left | |---|---|---|---|---|---|---|---| | 1 | Nav item inspector (`StudioNavItemInspector`, nav target helpers, `StudioPicker`) | landed | 978 | — | — | **landed in #30002** | 11,884 (measured) | | **2** | **`PackageSwitcher` with `PACKAGE_LIST_TOAST_ID` and `STUDIO_LANDING_PATH`** | 832–846, 897–1544 | **663** (15 + 648) | nothing · `useHomePath`, `useMetadataLocale`, `useNavigate` | `StudioDesignSurfaceBody` (all three); `DataPillar` (toast id) | low: self-contained, props only | **11,205** (measured, this PR) | | 3 | Interfaces nav tree rail: `NavTree`, `NavTreeGroup`, `ContributedNavRows`, `OffNavSections`, the two rail contexts, `navKindName`, `navOpenedItems`, with `KIND_ICON` / `navIcon` | 677–693, 2928–3352 | 442 | nothing · `useMetadataLocale`, `useNavTargetLabel`, `useOpenContributor` | `InterfacesPillar` only | low: self-contained | ≈ 10,765 | | 4 | Flow rail helpers: `FlowRuntimeState` … `readFlowCopiedArrival`, incl. `FlowStatusDot`, glyph tables, `pairIdOf` | 8740–9087 | 348 | nothing · no hooks | `AutomationsPillar`; `AccessPillar` (`pairIdOf`); 2 tests import `FlowStatusDot` | low: pure helpers plus one prop-only component; carries the spec-symbol ledger's `FlowRuntimeState` site | ≈ 10,419 | | 5 | Pillar kit: `useHeldEditReport`, `confirmDropUnsavedWork`, `findTakenIdentifier`, `CreateTakenNotice`, `StudioHeldNotice`, the "Show me" focus helpers, `announceDraftSaved`, `StudioReadOnlyLink`, `StudioBaseCustomization` | 522–661, 709–787, 800–830, 848–895, 3360–3385 | 320 | nothing · `useStudioTabRowFold` | all four pillars and `StudioDesignSurfaceBody` | low: five non-contiguous blocks; lets rows 7–10 move without an import cycle | ≈ 10,101 | | 6 | Data pillar helpers (`addedFieldName` … `formPreviewSource`, the OWD option keys) | 461–478, 6262–6502 | 259 | nothing · no hooks | `DataPillar` only; 1 test imports `renderStudioGridList` | low: pure helpers | ≈ 9,844 (under 10,000) | | 7 | `AccessPillar` with its arrival reader and `StudioNameLabel` | 2902–2926, 10941–11882 | 967 | rows 4, 5 · 11 hooks | `StudioDesignSurfaceBody`; 7 test files | medium: whole stateful component; after rows 4–5 | ≈ 8,879 | | 8 | `AutomationsPillar` | 9089–10939 | 1,851 | rows 4, 5 (and `StudioPicker`, row 1) · 21 hooks | `StudioDesignSurfaceBody`; 23+ test files | medium: after rows 4–5 | ≈ 7,030 | | 9 | `DataPillar` | 6506–8738 | 2,233 | rows 2, 5, 6 (and `StudioPicker`) · 17 hooks | `StudioDesignSurfaceBody`; 38+ test files | medium: holds three `clickableNonControlCensus-13461` rows keyed by this file | ≈ 4,799 | | 10 | `InterfacesPillar` with `interfacesSaveBody`, `leafKeyOf`, `customizeItemKey` | 502–520, 3357–3358, 3387–6260 | 2,895 | rows 1, 3, 5 · 23 hooks | `StudioDesignSurfaceBody`; 29+ test files | medium: close to the 3,000-line mark; holds one census row | ≈ 1,906 | | 11 | `StudioDesignSurface` / `StudioDesignSurfaceBody`, `PILLARS`, `METADATA_AREA_TAB`, `PILLAR_FOR_SURFACE_TYPE`, publish-refusal and backfill helpers | 437–460, 479–501, 663–675, 789–798, 1546–2900 | ≈ 1,425 | rows 2, 5, 7–10 · 11 hooks | `index.ts`, the console's lazy Studio route, 51 test files | stays: this is the file | — | Unchanged from #30002: nothing below the whole-component level of rows 7–11 moves without a logic change, and none of it is needed, because rows 3–6 bring the file under 10,000. Serial order: rows 3–6 in any order, then rows 7–10 only after row 5. ## What changes - `ui/packages/app-shell/src/views/studio-design/PackageSwitcher.tsx` (new): row 2, base lines 832–846 and 897–1544, each byte for byte, under a copyright line, a module comment and the imports the two blocks read. The block-level edits are `export` on `const PACKAGE_LIST_TOAST_ID`, `const STUDIO_LANDING_PATH` and `function PackageSwitcher(`, which the surface (all three) and `DataPillar` (the toast id) import back. The first block starts with the switcher's own doc comment, which at base sat stranded above the toast id's doc comment; it moved with that block unchanged. - `ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx`: both blocks are gone. It imports the three names from the new module beside the slice 1 import, and drops the import bindings only the switcher used (`AppMark`, `STUDIO_PKG_READONLY_WORD`, `Popover` / `PopoverTrigger` / `PopoverContent`, `AlertTriangle`, `Boxes`, `Building2`, `Settings`, `useHomePath`, `CreatePackageDialog` / `PackageDetailSheet` / `InstalledPackageRow`, `foldCustomizationPairs`); `AppMarkApp` stays as `import type`. Nothing was exported before, so there is no re-export. - By-path readers (ruling 6597555122 item 3): - `ui/packages/app-shell/src/__tests__/homeRecoveryRedirectsFollowDeclaration-7373.test.ts`: the Studio site's `alsoReads` gains `PackageSwitcher.tsx`. Its needle `const homePath = useHomePath()` moved with the switcher, so the site now holds only through this entry (ablation B1). - `ui/scripts/__tests__/spec-symbol-ledger-app-shell-7265.test.ts`: `SITES` gains `PackageSwitcher.tsx`. - `docs/qa/platform-checklist/areas/studio-authoring.json`, source re-points only, each with a revision bump and a history row (the area's convention; "No clause changed"): - `studio-authoring.app-and-nav-properties` r5 → r6: `source[2]` now cites `StudioNavItemInspector.tsx (the Studio menu-entry inspector)`, the slice 1 follow-up. - `studio-authoring.first-run-loop` r11 → r12: `acceptance[0].verify` named `StudioDesignSurface.tsx` as where the `studio-pkg-chip` testid is declared; that testid moved with the switcher, so it now names `PackageSwitcher.tsx`. The clause text is unchanged. - `.changeset/29988-studio-package-switcher-module.md`: `@object-ui/app-shell` patch, "internal: move-only". ## Tests No behaviour changes, so no new behaviour test. The existing suites run unchanged; results are in Verification. ## Acceptance notes - **Readers re-grepped.** `git grep` of `StudioDesignSurface.tsx` / `studio-design/StudioDesignSurface` over `scripts/**`, `ui/scripts/**` and every ui test file finds the same three by-path readers as slice 1. The two whole-text scanners gained the new module (above). `clickableNonControlCensus-13461` walks the tree itself, keys rows by file and handler, and none of its rows is a switcher handler, so it needs no edit. No gate under `scripts/**` names the file. - **Checklist rows re-read.** Every `StudioDesignSurface.tsx` citation under `docs/qa/` was read against the moved block: only the `studio-pkg-chip` declaration moved. The others cite the pillars, the publish flow and `pkgWritable`, which stay. - **Two test comments now name the old file for moved text** and are left as they are (prose in test files, outside this slice's file surface): `PackagesPage.confirmFlows-11784.test.tsx` ("`PackageSwitcher`'s eviction in `StudioDesignSurface.tsx`") and `packages-io.inflightShare-11797.test.tsx` ("the `PACKAGE_LIST_TOAST_ID` doc in `StudioDesignSurface.tsx`"). The seat can re-point them with the next touch of either file. - **Serial check.** No open PR touched `StudioDesignSurface.tsx`, either extended reader or `studio-authoring.json` when the seat claimed (02:34Z) or right before this push (see Verification). The branch was restarted from `origin/main` after #30002 merged and is rebased on `f19fbb8f`; nothing after `f7aab8958` touches `ui/` or `docs/qa/`. ## Verification <details><summary>Move-only proof: byte-compare and the moved-lines diff</summary> ``` B=ui/packages/app-shell/src/views/studio-design git show f7aab89:$B/StudioDesignSurface.tsx | sed -n 832,846p > /tmp/blockA git show f7aab89:$B/StudioDesignSurface.tsx | sed -n 897,1544p > /tmp/blockB sed -n 43,57p $B/PackageSwitcher.tsx | sed 's/^export const PACKAGE_LIST_TOAST_ID = /const PACKAGE_LIST_TOAST_ID = /' | cmp /tmp/blockA - tail -n +59 $B/PackageSwitcher.tsx | sed -e 's/^export const STUDIO_LANDING_PATH = /const STUDIO_LANDING_PATH = /' -e 's/^export function PackageSwitcher({/function PackageSwitcher({/' | cmp /tmp/blockB - ``` Both silent (identical): block A 15 lines, sha256 `aa1ecaea48757927…`; block B 648 lines, sha256 `e5c09d177d162507…`. `git diff --color=always --color-moved=zebra f7aab89 HEAD -- ui/packages/app-shell/src/views/studio-design/`: 664 lines removed and 664 added are coloured as moved (the 663 block lines plus import specifier lines). Apart from import lines and the new module's header comment, every line NOT coloured as moved: ``` +export const PACKAGE_LIST_TOAST_ID = 'studio-package-list'; +export const STUDIO_LANDING_PATH = '/studio'; +export function PackageSwitcher({ -const PACKAGE_LIST_TOAST_ID = 'studio-package-list'; - -const STUDIO_LANDING_PATH = '/studio'; - -function PackageSwitcher({ - ``` (the removed blank lines are the separators after each cut block). </details> <details><summary>Declaration files (ruling 6348891160's bar)</summary> Base declarations emitted from the base source into a scratch `outDir` under the lock, tree restored (`git diff HEAD` empty). All 700 base `.d.ts` files, `StudioDesignSurface.d.ts` included (sha256 `d0f9665b1e9ed6fc…`), are byte-identical at head: the switcher was never exported, so no declaration moved. The one addition is `views/studio-design/PackageSwitcher.d.ts` / `.js`, reachable from no entry in the package's `exports` map (`"."` only). Declared-surface digest of `dist/index.d.ts` plus `StudioDesignSurface.d.ts`: 245 exports, `53af282f1e0f28e8…` on both sides, the same digest slice 1 recorded. </details> <details><summary>Build, type-check, lint and tests (head ac845e5e; the rebased head 02c3a7f has a byte-identical ui/, docs/qa/ and changeset, checked with git diff --quiet)</summary> All under scripts/pm/os-verify-lock.sh, one locked chain: VERDICT command-exit 0. - npx turbo run build --filter='@object-ui/app-shell...' --concurrency=2: exit 0. - pnpm --dir ui --filter @object-ui/app-shell type-check (tsc --noEmit, then tsconfig.test.json): exit 0. - pnpm --dir ui run type-check:scripts: exit 0. - npx eslint on the two source files and the 7373 test, from packages/app-shell: exit 0. - pnpm --dir ui exec vitest run --maxWorkers=3 packages/app-shell/src/views/studio-design/ plus the 7373 test, PermissionMatrixEditor.saveSurface-12725, builtinDesigners.lateArrival-11939, observableRegistries-11939, PackagesPage.confirmFlows-11784, clickableNonControlCensus-13461 and spec-symbol-ledger-app-shell-7265: exit 0, Test Files 329 passed (329), Tests 2445 passed (2445). - Narrowed, and declared: the full @object-ui/app-shell suite does not finish locally on the shared box; the run covers every test in the moved file's directory and every test outside it that imports the file, reads it by path or names the switcher. CI's Test UI runs the rest. - node scripts/check-platform-checklist.mjs: exit 0 (16 areas, 359 items); with --changed-from origin/main: exit 0. </details> <details><summary>Ablation of the two extended readers (one-time, through scripts/ablation-replace.mjs; tree restored, git diff HEAD empty)</summary> | Leg | Mutation | Expected | Observed | |---|---|---|---| | B0 | none: the 7373 test as in this PR | green | exit 0: 15 passed | | B1 | the Studio site's alsoReads loses PackageSwitcher.tsx (the old file and the slice 1 module only) | red: the useHomePath needle moved | exit 1: "resolves its target through the policy" fails for the Studio site; 1 failed, 14 passed | | B2 | a local interface ObjectLike added to PackageSwitcher.tsx, SITES as in this PR | red | exit 1: "rule 1 finds no spec-named local declaration in ...PackageSwitcher.tsx" fails; 1 failed, 20 passed | | B2b | same mutation, the PackageSwitcher.tsx SITES row removed | green, i.e. blind | exit 0: 20 passed | Each mutation's landing was proven by the tool (anchor count 1 to 0, blob hashes) and by a grep count of the changed text. </details> <details><summary>Derived gates: node scripts/pm/dispatch-gates.mjs --commands on head 02c3a7f (42 commands)</summary> ``` node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0 node scripts/check-adr-0087-registration.mjs --self-test :: exit 0 node scripts/check-adr-links.mjs :: exit 0 node scripts/check-adr-links.mjs --self-test :: exit 0 node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0 node scripts/check-closing-keyword-parity.mjs :: exit 0 node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 node scripts/check-comment-mask-corpus.mjs :: exit 0 node scripts/check-empty-changeset.mjs --base origin/main :: exit 0 node scripts/check-empty-changeset.mjs --self-test :: exit 0 node scripts/check-sdui-manifest.mjs :: exit 0 node scripts/check-sdui-manifest.mjs --self-test :: exit 0 node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0 node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0 node scripts/release-pending-publish.mjs --self-test :: exit 0 pnpm --dir ui exec vitest run scripts/ :: exit 0 pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0 pnpm check:changeset-gate-self-tests :: exit 0 pnpm check:ci-filter-parity :: exit 0 pnpm check:closed-ceremony-text :: exit 0 pnpm check:cross-package-test-inputs :: exit 0 pnpm check:dispatcher-error-vocabulary :: exit 0 pnpm check:doc-authoring :: exit 0 pnpm check:driver-memory-census :: exit 0 pnpm check:engine-double-contract :: exit 0 pnpm check:gitlink-declared :: exit 0 pnpm check:nul-bytes :: exit 0 pnpm check:platform-checklist :: exit 0 pnpm check:published-files :: exit 0 pnpm check:query-options-erasure :: exit 0 pnpm check:refd-timer-probe :: exit 0 pnpm check:registry-log-declared :: exit 0 pnpm check:rest-log-spy-declared :: exit 0 pnpm check:skill-identifier-liveness :: exit 0 pnpm check:test-source-alias :: exit 0 pnpm check:tier-file-adoption :: exit 0 pnpm check:type-check-coverage :: exit 0 pnpm check:type-check-debt :: exit 0 pnpm check:undeclared-dep-imports :: exit 0 pnpm check:watch-hint-literal :: exit 0 pnpm check:where-matcher :: exit 0 ``` node scripts/pm/dispatch-gates.mjs --ran: "42 derived famil(ies) accounted for — 42 run, 0 NOT-MEASURED". The formula and lint dists were built first (cached), so check:doc-formula-expressions measured rather than exiting 3. </details> <details><summary>Serial check before push</summary> The 17 open PRs at 2026-11-04T03:22Z, each PR's full file list read page by page: none touches StudioDesignSurface.tsx, either extended reader or studio-authoring.json. </details> --- _Generated by [Claude Code](https://claude.ai/code/session_01WGufzedfGwVcebpN5t3ETE)_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01WGufzedfGwVcebpN5t3ETE Co-authored-by: Claude <noreply@anthropic.com>
1 parent 217ba78 commit 73a3ef9

6 files changed

Lines changed: 735 additions & 687 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
---
4+
5+
internal: move-only — Studio's top-bar package switcher moves out of `StudioDesignSurface.tsx` into its own module (#29988, slice 2)
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
No behaviour change. The package switcher in Studio's top bar (the package list, New package, the package detail sheet and the deleted-package eviction), with the package-list toast id and the Studio landing path it shares with the surface, now lives in `views/studio-design/PackageSwitcher.tsx`. The moved code is byte-identical apart from its imports and three `export`s; `StudioDesignSurface.tsx` imports it from there. The package's public exports are unchanged.

‎docs/qa/platform-checklist/areas/studio-authoring.json‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"title": "The first-run authoring loop closes: package → object → record → app → publish → end-user, zero code, zero restarts",
1010
"since": "v16",
1111
"status": "active",
12-
"revision": 11,
12+
"revision": 12,
1313
"priority": "P0",
1414
"surface": "mixed",
1515
"personas": ["admin (seeded admin@objectos.ai)", "end user (same account driving the published app)"],
@@ -40,7 +40,7 @@
4040
{
4141
"clause": "package create round-trips and the package switcher lists the new writable package without a page reload",
4242
"oracle": "network",
43-
"verify": "the create POST succeeds and the switcher shows the package in the same session. ui/e2e/live/studio-object-designer.spec.ts test F1 pins it (read in objectui at cf153eb2e535, blob 58a7f1cbf024, before the import under ui/): it creates a package through the switcher's New package dialog by the testids studio-pkg-chip, package-form-id-input and package-form-submit, all declared in ui/packages/app-shell (StudioDesignSurface.tsx, PackageFormDialog.tsx), and asserts that the surface moved into the new package and that the switcher lists it by name with no reload. Run F1 from ui/ with `pnpm test:e2e:live studio-object-designer.spec.ts` against a live boot (RUNNER, the objectui-pinned-automation fact) and cite its output naming the commit, or drive the clause by hand. Note the new-package wizard's own state, objectui#11327",
43+
"verify": "the create POST succeeds and the switcher shows the package in the same session. ui/e2e/live/studio-object-designer.spec.ts test F1 pins it (read in objectui at cf153eb2e535, blob 58a7f1cbf024, before the import under ui/): it creates a package through the switcher's New package dialog by the testids studio-pkg-chip, package-form-id-input and package-form-submit, all declared in ui/packages/app-shell (PackageSwitcher.tsx, PackageFormDialog.tsx), and asserts that the surface moved into the new package and that the switcher lists it by name with no reload. Run F1 from ui/ with `pnpm test:e2e:live studio-object-designer.spec.ts` against a live boot (RUNNER, the objectui-pinned-automation fact) and cite its output naming the commit, or drive the clause by hand. Note the new-package wizard's own state, objectui#11327",
4444
"evidence": "the create request/response + switcher screenshot"
4545
},
4646
{
@@ -97,7 +97,8 @@
9797
{ "revision": 8, "date": "2026-10-31", "change": "steps[1], [2] and [6] name the controls as the console draws them. steps[1]: Home's build chip reads 'New in Studio' and opens Studio with the New package dialog when the deployment has no agent catalog, which is what QA run #27481 met, and 'Build an app' (opening the Studio landing) only when it has one (ui/packages/app-shell/src/console/home/HomePage.tsx). steps[6]: the way from the Studio landing to the console Home is the top bar's product mark, a link named 'PRODUCT home' (data-testid app-bar-product-home, ui/packages/app-shell/src/layout/AppHeader.tsx), which is why the run found no control named 'Home'. steps[2] carries the same stale button name the run met elsewhere: the New object dialog confirms with 'Save as draft' (engine.studio.createDraft), not Create. Accuracy finding of QA run #27481. No clause changed. Wave anchor #27377, wave-3 accuracy slice S2; read at base a0f865491d", "ref": "#27481" },
9898
{ "revision": 9, "date": "2026-11-01", "change": "steps[3] quotes the publish toast as the console draws it. It still read 'Published 1 item in this package (one atomic release)', a wording retired when the walkthrough of #27521 (row 28) dropped 'atomic' from the publish title, toast and confirm note: the toast is now 'Published N items in this package' ('Published 1 item in this package' for one; engine.studio.publishedAllCount / publishedAllCountOne in ui/packages/i18n/src/namespaces/studio/en.ts), and a publish that puts an app or object live adds the permission-set hint and an 'Open Access' action (ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx). Wording only; no clause changed. Read at base efb1620c", "ref": "#27521" },
9999
{ "revision": 10, "date": "2026-11-01", "change": "QA run #28545 (W3-C1R) finding on steps[2]: the object surface opens on Records after a navigation, Add field is on the Form tab, and an option's stored value derives from its label ('In Repair' gives in_repair), so a run that wants wip must overwrite it. steps[2] now says so, read from source (StudioDesignSurface.tsx viewMode default 'grid'; OptionsEditor derives a new row's value with toFieldNameOrEmpty). The same card's steps[3] finding, the stale publish toast, was fixed upstream by revision 9 (#28526, after eeec88d1). No clause changed. Read from source at base 6b9c1ca991. Wave anchor #27377, wave-3 accuracy slice S9 (#28641); finding parked in anchor comment 6554042054", "ref": "#28545" },
100-
{ "revision": 11, "date": "2026-11-03", "change": "fixtures.requires[0], steps[0] and a new negative[2] name two locale legs, en and zh-CN, and a clause holds only on both; a new fixtures.knownGaps[3] records the zh-CN leg's open failure; steps[1]'s identifier note follows pinyin derivation. QA run #29672 found the item named no locale while steps[1] uses a Chinese display name: its en leg passed and its zh-CN leg failed acceptance[2] (#29673, extracted by the run), so a run that drove one locale could score the loop either way. Read at base 339f63da30: the registry judge and the swallowed registration are unchanged and #29673 is open; and since #29734 (11c4eb59dd) a Chinese display name derives a pinyin package id (deriveCreatePackageId), so steps[1]'s 'derives no package id' no longer held, while its instruction to type com.example.repairs stands. No clause text changed; each now holds per leg. Card #29679, from QA run #29672", "ref": "#29679" }
100+
{ "revision": 11, "date": "2026-11-03", "change": "fixtures.requires[0], steps[0] and a new negative[2] name two locale legs, en and zh-CN, and a clause holds only on both; a new fixtures.knownGaps[3] records the zh-CN leg's open failure; steps[1]'s identifier note follows pinyin derivation. QA run #29672 found the item named no locale while steps[1] uses a Chinese display name: its en leg passed and its zh-CN leg failed acceptance[2] (#29673, extracted by the run), so a run that drove one locale could score the loop either way. Read at base 339f63da30: the registry judge and the swallowed registration are unchanged and #29673 is open; and since #29734 (11c4eb59dd) a Chinese display name derives a pinyin package id (deriveCreatePackageId), so steps[1]'s 'derives no package id' no longer held, while its instruction to type com.example.repairs stands. No clause text changed; each now holds per leg. Card #29679, from QA run #29672", "ref": "#29679" },
101+
{ "revision": 12, "date": "2026-11-04", "change": "acceptance[0].verify re-pointed: the Studio package switcher, which declares the studio-pkg-chip testid, moved unchanged from ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx to PackageSwitcher.tsx beside it (#29988 slice 2, a move-only split). Re-read at base f7aab8958. No clause changed", "ref": "#29988" }
101102
]
102103
},
103104
{
@@ -3511,7 +3512,7 @@
35113512
"title": "App and menu-entry keys reach the running app: branding, areas and context selectors render; an entry's viewName, recordId / recordMode, filters, badge, requiresObject and visible each change what the entry does or who sees it; hidden takes an app off the switcher and nothing else — and Studio's menu-entry inspector edits them",
35123513
"since": "v18",
35133514
"status": "active",
3514-
"revision": 5,
3515+
"revision": 6,
35153516
"priority": "P2",
35163517
"surface": "mixed",
35173518
"personas": [
@@ -3586,7 +3587,7 @@
35863587
"source": [
35873588
"packages/spec/src/ui/app.zod.ts (branding: primaryColor / accentColor / logo / favicon; areas; contextSelectors; hidden — 'navigation only, never an access gate'; the nav item keys viewName, recordId, recordMode, filters, badge, badgeVariant, requiresObject, visible, order)",
35883589
"packages/metadata-core/src/artifact-forward-conversion.ts (where the retired app-hidden-to-unpublished conversion stood; dbf7e04a removed it from packages/spec/src/conversions/registry.ts, so a stored hidden: true round-trips — #26712, closed as fixed)",
3589-
"ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (the Studio menu-entry inspector)",
3590+
"ui/packages/app-shell/src/views/studio-design/StudioNavItemInspector.tsx (the Studio menu-entry inspector)",
35903591
"cross-ref: the doc-type menu entry is studio-authoring.doc-on-app-menu; nav rendering on the stock showcase is platform-core.nav-surfaces-render"
35913592
],
35923593
"history": [
@@ -3619,6 +3620,12 @@
36193620
"date": "2026-11-01",
36203621
"change": "QA run #28656 (W3-RT) finding: steps[0] says to give branding.logo a same-origin URL such as /_console/vite.svg (ui/apps/console/public/vite.svg ships in the console build). This is a runner-environment note: an external logo URL is blocked by the runner container's egress proxy and never renders, which is #28656's live reading at 6e11a929. No clause changed. Re-verified against source at base 1c5b1773ec. Wave anchor #27377, wave-3 accuracy slice S10 (#28701); finding parked in anchor comment 6557904764",
36213622
"ref": "#28656"
3623+
},
3624+
{
3625+
"revision": 6,
3626+
"date": "2026-11-04",
3627+
"change": "source[2] re-pointed: the Studio menu-entry inspector moved unchanged from ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx to StudioNavItemInspector.tsx beside it (#29988 slice 1, PR #30002, a move-only split). Re-read at base f7aab8958. No clause changed",
3628+
"ref": "#29988"
36223629
}
36233630
]
36243631
},

‎ui/packages/app-shell/src/__tests__/homeRecoveryRedirectsFollowDeclaration-7373.test.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,10 @@ const RECOVERY_SITES: ReadonlyArray<{
136136
},
137137
{
138138
file: 'packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx',
139-
alsoReads: ['packages/app-shell/src/views/studio-design/StudioNavItemInspector.tsx'],
139+
alsoReads: [
140+
'packages/app-shell/src/views/studio-design/StudioNavItemInspector.tsx',
141+
'packages/app-shell/src/views/studio-design/PackageSwitcher.tsx',
142+
],
140143
site: 'Studio: deleted-package eviction + header Home',
141144
expression: /const homePath = useHomePath\(\)/,
142145
},

0 commit comments

Comments
 (0)