Repository navigation
Commit 644883e
fix(studio): after Restore package original the rail's customized mark and "only customizations" count refresh without a reload (#30381)
<!-- claude-projects-attribution: {"github_login":"os-bill"} -->
_Requested by **Bill** · [project
thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wg4bKKModkHh9FMR76oxRgy1)_
domain:ui#2 · os-bill · session_01Utp6Cb5R6JDdfyvtj3dPR2
Fixes #30238
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:Studio 读取「本基础包有哪些定制」(`GET
/api/v1/packages/:id/customizations`)的时机,从「只在发布后」改为「每次元数据刷新脉冲」;恢复原版本来就会发这个脉冲,所以恢复后侧栏的定制标记和「仅看定制(n)」立即更新,不用刷新页面。
- 为什么改:管理员在 Studio
里对已安装应用的仪表盘、报表、视图、列表视图或页面按「恢复原版」后,内容回到出厂版,但侧栏还标着已定制、「仅看定制(1)」还在,看不出恢复是否生效,可能重复恢复或误以为定制仍在。
- 风险与回滚:只改 `StudioDesignSurface.tsx` 中一处读取的触发键(含注释 +13/-3 行),外加一个新测试文件和
changeset;不动 spec、服务端或元数据。发布照样只读一次(发布本来就同时发脉冲);AI 助手发布后也会重读。回滚即 revert 本
PR。
-
先看:`ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx`
约 836–849 行(`customizationsRefresh` 那一段)→ 新测试
`StudioDesignSurface.restoreMarks-30238.test.tsx`。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/app-shell/src/views/studio-design/StudioDesignSurface.restoreMarks-30238.test.tsx`,预期
2/2 通过(在 main 源码上两条都失败:恢复后定制读取没有再请求)。
- 需要你做的:无,席位落地。
## What changes
`StudioDesignSurface` reads the base's customizations once and hands
them to every pillar as `customization.marks`: every pillar rail's marks
and "only customizations" count come from that read. It was keyed on
`publishNonce`, so it was read again only after a publish. "Restore
package original" (`restoreOriginal` in the Interfaces pillar, the flow
restore in Automations, and the bundle item editor's restore) deletes
the pair's draft and row, then calls `emitMetadataRefresh()`, but never
moves `publishNonce`. So the shipped item read back while the rail kept
its mark and its count until a reload.
- The read is now keyed on `useMetadataRefreshNonce()`, the assistant
bus pulse that the restores already emit. Both publish paths
(`setPublishNonce` at the two publish sites) emit the same pulse in the
same handler, so a publish still reads once. Keying on both would read
twice per publish. A copilot publish from the right dock, which the old
key missed, now refreshes the marks too.
- No restore path changes, and no new fetch path. The hook
(`usePackageCustomizations`) is unchanged.
The card's mechanism held as written: `restoreOriginal` moves
`servedNonce`, the leaf or list-view or nav reload nonces, and emits the
pulse, but no key the customization read listened to. I confirmed it on
a second type: a dashboard opened from the navigation, besides the page
the card measured.
## Tests
- New
`ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.restoreMarks-30238.test.tsx`:
the REAL `StudioDesignSurface` and metadata client over a fetch stub
that serves a read-only base with its pair listed, the pair's rows
served over the base's items, the customization read (one override per
pair row) and the reset door (`DELETE`, which deletes the pair's row).
- A dashboard opened from the navigation: before the restore the rail
marks it `customized` and "only customizations" reads 1. After the
restore the read is asked again, the mark is gone, and so is the filter.
- A page listed under its type, with a second customized dashboard as
the CONTROL: after the page's restore the read is asked again, the
page's mark is gone, the count reads 1, and the dashboard keeps its
mark.
- Red first, on the commit before the fix (test only, `3e7cd7f5`):
`Tests 2 failed (2)`, both `expected 1 to be greater than 1` (the
customization read count did not move after the restore). Green after
the fix: `Tests 2 passed (2)`. The red-first run on the parent commit is
the ablation leg: the fix is the only source change.
- Every app-shell test file that renders the whole `StudioDesignSurface`
(60 files): `Test Files 60 passed (60)`, `Tests 372 passed (372)`. The
other test files that import the module render single pillars with a
host-built `customization`, which this change does not touch.
- `pnpm exec turbo run type-check --filter=@object-ui/app-shell
--concurrency=2`: `Tasks: 68 successful, 68 total`.
- `eslint` on the two changed ui files: 0 errors.
`StudioDesignSurface.tsx` has 36 warnings, the same count as on main.
The new test file has none.
## Acceptance notes
- The card's Expected also names the All metadata tile count. The All
metadata area's pages (`DirectoryPage`, `ResourceListPage`) make their
own customization read when each one mounts. The area mounts on its tab,
and its list and item pages are separate routes, so after a restore made
anywhere else they open on a fresh read. This PR does not change them.
- The card lists the app's navigation with the types that share the
path. The navigation's rail mark reads the served override
(`useServedOverride`, keyed on `servedNonce`, which `restoreOriginal`
moves), not the customization read, so it already cleared after a
restore. The count's navigation term is that same mark. The stale part
was the off-navigation items (page, dashboard, report, view) and the nav
entries' marks, which this PR fixes.
## Verification
<details><summary>Derived gates (dispatch-gates --commands, final tree
`bde46d2b`)</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-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/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/spec run check:duration-unit-keys` :: exit
0
- `pnpm check:changeset-gate-self-tests` :: 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: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: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`: 35 derived, 35 run, 0
NOT-MEASURED, 0 UNRUN. `check:type-check-debt` ran under the verify lock
(VERDICT command-exit 0). `check:sdui-manifest` (standing ui gate) is in
the list.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Utp6CYbJbcjB64iwnxmHBs)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 75a5c3e commit 644883e
3 files changed
Lines changed: 279 additions & 3 deletions
File tree
- .changeset
- ui/packages/app-shell/src/views/studio-design
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
854 | 854 | | |
855 | 855 | | |
856 | 856 | | |
857 | | - | |
858 | | - | |
859 | | - | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
860 | 870 | | |
861 | 871 | | |
862 | 872 | | |
| |||
0 commit comments