Skip to content

feat(console): after a reload, the package page still says how many sample records a purge would delete - #30653

Merged
objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/project-thread-msfcwi
Nov 5, 2026
Merged

objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/project-thread-msfcwi

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Sales · project thread
domain:ui#6 · os-sales · session_01L6bhgTRFYJtEzJqfKEhD7C

Fixes #30616

Clause-②: no
Metadata-protocol: none

维护者速读

What changes

PR #30613 added GET /api/v1/marketplace/install-local/:manifestId/sample-data, which answers how many rows a sample-data purge would delete right now, counted with the purge's own matcher and keep-rules. The console only knew a count for an install made in the same browser session (PR #30537); after a reload the purge confirm had no count and the banner that follows the installer to the app was gone.

  • marketplaceApi.countLocalSampleData(manifestId) reads that route and answers { manifestId, count, unidentified }, or null when the read is refused, fails, or carries no non-negative integer count.
  • The package page reads the count on every visit of a local install the runtime loaded (not for a notLoaded entry), and again every time the install-local listing is read, which already happens after an install, a reseed and a purge. The answer goes into the existing session record (sampleDataNotice.ts) through the new noteServedSampleCount:
    • a count above zero updates the record in place, or starts one when this session had none (a standing banner and a pending confirm request stay with it);
    • count: 0 drops the record and withdraws its banner.
  • Freshness. A read that began before an install, reseed or purge of this session answered is older than that answer and is ignored: the record keeps a per-package generation that those three answers bump, and the read compares the generation it saw when it started. The effect's cleanup also drops a superseded read. A failed read changes nothing, so the confirm keeps the count this session's install answered.
  • The confirm now reads its count when it is drawn (localSampleCount), so a count that lands while it is open reaches it; the state keeps only the target. A cloud purge draws no count, as before.
  • The banner needs no change of its own: it is raised on leaving from the session record, so a served count above zero raises it after a reload too, and count: 0 leaves nothing to raise.
  • Copy, no new key. marketplace.detail.purgeConfirmAtMost said the count was "the number this install loaded", false for the runtime's count. All 10 packs drop that clause and keep the upper bound, e.g. en Up to {{count}} sample records will be deleted., zh 最多删除 {{count}} 条示例记录。, ru reworded to не более {{count}} … with the singular-genitive _one. The upper bound holds for both sources: the served count is exact, and the session count is at most what a purge deletes. The eager en pack shrinks (see Verification); #30588's ceiling is untouched.

unidentified is read but not drawn: saying it needs a new string, which the eager en pack has no room for until #30588 moves strings to a lazy namespace.

Tests

ui/packages/app-shell/src/console/marketplace/__tests__/MarketplacePackagePage.sampleDataNotice-30323.test.tsx is this surface's shared harness, so the new pins are two top-level describes there (one stubbed fetch routed by path; the real marketplaceApi):

  • a visit with no install this session reads the count once and the confirm draws count=42;
  • that count raises the banner on leaving;
  • count: 0 drops a record the session held: no count line in the confirm, no banner on leaving;
  • after an in-session install of 369, the re-read count 360 is the one the confirm draws, and the install note keeps 369;
  • CONTROL: a refused read (403) keeps the install's 369;
  • CONTROL: a notLoaded entry is never counted;
  • unit: a read whose generation predates an install's answer does not replace it; one taken after does, and 0 drops the record.

Support edits: 13 suites that mock ../marketplaceApi gain countLocalSampleData: async () => null, and the offline local-menu suite (…offlineLocalMenu-11627.test.tsx) now calls cleanup() before vi.unstubAllGlobals(), because a reseed or purge re-reads the count after the test body returns and that read reached a socket once the double was gone.

Acceptance notes

Verification

Ablation: the count read removed, 5 of the new pins go red

node scripts/ablation-replace.mjs --file ui/packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx --anchor 'const served = await countLocalSampleData(manifestId);' --replacement 'const served = null as …;' -- …vitest run …sampleDataNotice-30323.test.tsx: anchor 1 → 0, blob 3ab826d5e075 → 87d8ee093b8e; Tests 5 failed | 15 passed (20) (the five page-level #30616 pins); restored, blob == HEAD and git diff HEAD empty. The app-shell suite reads this page from src/ (relative import), so no build sits between the mutation and the run.

Eager en pack, gzip bytes (the CI Build & E2E UI ceiling is 60,000)

Console built from this branch (turbo run build --filter='@object-ui/console^...', then CI=true vite build in ui/apps/console); dist/eager-closure.json reads assets/i18n-locale-en-*.js at 192,979 raw / 59,942 gzip. The same chunk with the three old purgeConfirmAtMost strings swapped back in, re-gzipped with zlib.gzipSync (level 6, what the report uses): 193,081 raw / 59,951 gzip. So −9 B gzip, −102 B raw. node scripts/check-eager-closure-budget.mjs (in ui/): exit 0.

Local tests and gates

All on head eef04e97 (this branch merged with main at af8aab1b) unless noted. Lock readings are the lock's own VERDICT lines.

  • pnpm --dir ui exec vitest run packages/i18n/ packages/app-shell/src/console/marketplace/ (after rebuilding @object-ui/app-shell^... on the merged tree): Test Files 146 passed (146), Tests 1898 passed, 13 skipped.
  • pnpm --filter @object-ui/app-shell run type-check (source and tests): exit 0, on 5581ff5d (the merge brought no file under ui/packages/app-shell or ui/packages/i18n).
  • pnpm --dir ui exec vitest run scripts/: 170 files passed, 2 skipped; 4970 tests passed.
  • node ui/scripts/check-i18n-en-drift.mjs --base origin/main: exit 0, every changed en value followed by all nine packs. pnpm --dir ui run check:i18n-keys: exit 0 (4,210 keys). node ui/scripts/check-eager-closure-budget.mjs: exit 0 (on 5581ff5d's console build).
  • eslint on every changed source and test: 0 errors; the warnings are pre-existing no-explicit-any / one unused var in the page.
  • node scripts/pm/dispatch-gates.mjs --commands: 35 derived families, every one exit 0; --ran reconciles 35 run, 0 NOT-MEASURED, 0 UNRUN.
  • NOT MEASURED: the whole @object-ui/app-shell suite (2,303 test files; stopped after 40 minutes at --maxWorkers=2 on a shared box). The local run is narrowed to the marketplace directory and the i18n package, the two trees whose files this diff changes or whose mocks name the API it extends; Test UI runs the rest.

Live stack (showcase objectstack dev --fresh, the fake marketplace control plane from #30325's rig, console via vite; evidence in the project's shared files, not committed):

  • curl, rig package with 3 seed records: count 3 after install, still 3 after a user adds a record of their own, purge answers deleted: 3, count 0 after, the user's record stays.
  • Browser, a 13-record package installed through the API and the package page then opened fresh (no install answer in this browser session): two GET …/sample-data reads; the ⋯ menu's purge confirm reads Up to 13 sample records will be deleted.; leaving the page by its back link raises "Acme Deals" has sample data. with the purge action. After a purge (deleted: 13, count 0), a fresh visit and leave raises no banner.

Generated by Claude Code

…untime's count too (#30616)

`purgeConfirmAtMost` said the count was "the number this install loaded",
which is false once the console draws the runtime's count of the rows a
purge would delete now. All ten packs drop that clause and keep the upper
bound, which holds for both sources. No key added; en shrinks.

Claude-Session: https://claude.ai/code/session_01L6bhgTRFYJtEzJqfKEhD7C
Co-authored-by: Claude <noreply@anthropic.com>
…nt read (#30616)

Mocks of `marketplaceApi` gain `countLocalSampleData`, and the offline
local-menu suite unmounts before its fetch double goes, since a reseed or
purge now re-reads the count after the test body returns.

Claude-Session: https://claude.ai/code/session_01L6bhgTRFYJtEzJqfKEhD7C
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 5, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#6 · os-sales · session_01L6bhgUR8Nu4M7tbtgES7q2

维护者速读

席位核对 — ACCEPT · head eef04e9

  • 形态:29 文件 +325/−60(市场页、marketplaceApi.ts 新增 countLocalSampleData 与 LocalSampleDataCount、sampleDataNotice.ts、十个语言包各改一族、sampleDataNotice-30323 测试扩充、其余市场测试各补一处新读接口的 fetch 替身、changeset @object-ui/app-shell + @object-ui/i18n patch)。check-governed-merges --pr 30653:NOT governed,385 行 ≤ 3000。Fixes #30616,draft,目标 main,merge-tree 对 main 干净。席位读过 diff:读失败返回 null,记录保持原样;计数为 0 时删掉记录并撤下横幅;请求发出前先记下代数,期间如果本会话又有安装、重装或清除的应答,就以那个更新的应答为准,旧读数不覆盖;云端清除不画计数句;确认框打开时才取数,打开期间到达的计数也能显示出来。
  • 契约:Clause-② no,Metadata-protocol none,与认领 6666790120 一致:只读 PR feat(cloud-connection): count an installed app's remaining sample rows the purge's way #30613 已在 main 上的接口,没有新的服务端字段;⛔ 新增首屏 en 键已守住(席位裁定的方案 A:改写已有键,措辞对服务端数与会话回退数都成立)。
  • 前提实测:dev 报告 6669402877。真栈(showcase + 假市场 + console):刷新后确认框显示「Up to 13」,离页弹横幅;清除删 13 条,计数归 0 后不再弹。marketplace + i18n 146 文件全绿;app-shell 全包本地未跑完,dev 已申报,交给 CI 的 Test UI 判定。
  • 门禁 check-runs:head 上 55 个,44 success,11 skipped,0 红(含 Test UI 与 Build & E2E UI 的 check:eager-closure)。
  • 接受的偏差:① app-shell 全包测试本地 NOT MEASURED,以 CI Test UI 为准。② PR 归属块链接卡线程,与本席其它卡线程 PR 一致。
  • 范围外去向:perf(i18n, app-shell)!: the marketplace pages' strings leave the eager language packs for a lazy marketplace namespace #30640(Console first load: the English language pack has 63 bytes left under its size ceiling, so any card that adds English console text fails CI #30588,懒加载 marketplace 命名空间)合 main 时要把 purgeConfirmAtMost 的新值带进 namespaces/marketplace/<lang>.ts。PR 正文已写,本席落地后也会给席 8 信箱发 Notify: landed。
  • 落地条款:中继 pr_ready + automerge_enable。合并后由 Fixes 关卡,席位摘掉 pm:dispatched,留落地评论,并在 pm:mailbox — domain:ui#1 · os-sales #30503 发 Notify: landed。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Installed app page: after a reload, show how many sample records are left (read the new server count) instead of only yes/no

1 participant