Repository navigation
marketplace: the catalog's org install, on a cloud-managed environment, pulses a metadata refresh the moment the install answers, inside the runtime's stale-while-rebuild window (the sibling of objectui#12087) #12097
Description
Activity
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsTriage: first grade,
bug·priority:p2·domain:ui·area:studio·pm:blockedon #12096. The catalog page's org-install button has #12087's defectTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-10T15:54Z. ⛔ Not a claim, ⛔ not a dispatch.- Re-read on
mainde302c7315:MarketplacePage.tsx:204isdoOrgInstall.- On a cloud-managed environment,
:211callsinstallPackage(…), and:218callsemitMetadataRefresh()once it answers. - The
installLocalbranch (:209) hot-registers before it answers. - The filed reading holds.
- Why p2: it is marketplace: after a successful install, the console refreshes the app list while the runtime still serves the pre-install kernel (stale-while-rebuild, ~60 s) and caches it — the installed app does not appear #12087's defect (p2), at the same grade, on a second button.
- Why blocked: the fix reuses
waitForServedAppfrom PR fix(console): after an install into this environment, wait until its app is served before refreshing the app list (objectui#12087) #12096, which is not onmainuntil that PR lands. ⛔ No second copy of the wait. - Scope, as filed:
- Before the pulse, the org install waits on
waitForServedAppwithpkg.manifest_id. marketplace.org.installedgains the deploying, served and timeout states that PR fix(console): after an install into this environment, wait until its app is served before refreshing the app list (objectui#12087) #12096 adds to the package page.- A test on the virtual clock:
- no refresh while the stale list is served;
- a refresh once the app is served;
- an honest timeout when the wait expires.
- CONTROL: the
installLocalbranch refreshes at once, as today.
- Before the pulse, the org install waits on
- Order with console: install answers say what the runtime served —
hotLoaded: falsereads "installed, loads at the next restart", and an upgrade waits for the new version's app #12098: both wait on PR fix(console): after an install into this environment, wait until its app is served before refreshing the app list (objectui#12087) #12096. If console: install answers say what the runtime served —hotLoaded: falsereads "installed, loads at the next restart", and an upgrade waits for the new version's app #12098's version-aware predicate lives inwaitForServedApp, this page inherits it. Whichever lands second re-reads the other.
Blocked-by: #12096
- Re-read on
- addedarea:studioChanging a running app without code — authoring, publish, docs and the portalChanging a running app without code — authoring, publish, docs and the portalbugSomething isn't workingSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seat
on Oct 10, 2026 objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsUnlock scan: the blocker objectui#12096 has landed (
3c0f8069), sopm:blocked→pm:queue·domain:uiseat 3,session_01B1gHb9baeX7oioD5sHVm7z, 2026-10-10T20:19Z- The blocker named by triage
6099367789: PR objectui#12096. It merged through the queue as3c0f8069, an ancestor oforigin/main. - What triage was waiting for:
waitForServedApp, which is now onmain(packages/app-shell/src/console/marketplace/waitForServedApp.ts,export async function waitForServedApp). - No claim is made here. This seat is clocking out on the maintainer's word, so the card waits in
pm:queuefor the next seat. Triage's grade and scope stand as written.
Generated by Claude Code
- The blocker named by triage
objectstack-fleet commented
on Oct 11, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 · 2026-10-11T02:19Z
Session:session_01AswpQDLCKiZos2jCXknwKz
Account:os-zhuang
Branch:claude/issue-12097-org-install-wait-served
Worktree:objectui-issue-12097
Domain:domain:ui
Seat:domain:ui#1
File surface:packages/app-shell/src/console/marketplace/MarketplacePage.tsx(doOrgInstalland its success text);packages/app-shell/src/console/marketplace/waitForServedApp.ts(reused as is; edited only if the catalog page cannot call it unchanged); locale entries inpackages/i18n/src/locales/for themarketplace.org.*deploying, served and timeout states (all ten packs); their tests;.changeset/12097-org-install-wait-served.md(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default tier — dispatch-gates --tier --repo objectstack-ai/objectui: "no path-derived mandate"
Clause-②: yes
Responsibility:objectui's app-shell MarketplacePage.tsx doOrgInstall, which pulses emitMetadataRefresh the moment a cloud-managed install answers, inside the runtime's stale-while-rebuild window | waitForServedApp (objectui#12096, 3c0f8069) already covers the package page; the catalog page does not call it | every administrator who org-installs from the catalog page on a cloud-managed environment (code read on main; the package-page sibling objectui#12087 was measured by the maintainer on staging)
Thread-read: 6101786288
Serial constraints cleared: none in flight on these files. Read at 2026-10-11T02:19Z: the only open non-bot PR is objectui#12089 (the objectui#7611 epic), and it touches neither file. objectui#12098 serializes with this card onwaitForServedApp.ts(triage6102113934); it is not dispatched, so this card goes first, and objectui#12098 re-reads this PR when it is taken.Why
Clause-②: yes: the deploying, served and timeout states add published locale keys, which widensTranslationKeys, as on the sibling PR objectui#12096.
Generated by Claude Code
objectstack-fleet commented
on Oct 11, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 12097, "status": "done", "branch": "claude/issue-12097-org-install-wait-served", "pr": "https://github.com/objectstack-ai/objectui/pull/12115", "session": "session_01AswpQDLCKiZos2jCXknwKz", "premise_still_valid": true, "summary": "MarketplacePage doOrgInstall, cloud branch: after installPackage answers it now runs the one waitForServedApp (objectui#12096, called unchanged, default interval and bound) on the row manifest_id and sends emitMetadataRefresh only once an app whose _packageId is that manifest id is served; the strip shows a named status box with the package page's deploying / served (+ Open app) / timeout (+ Check again) states, no success claimed before served, nothing refreshed on expiry; the installLocal branch is byte-unchanged (Installed NAME + pulse at once). Assumptions measured: (1) confirmed red on main, the pulse fires at virtual t=0 with the app not served; (2) confirmed at the producer, cloud GET /cloud/org-packages emits manifest_id from sys_package.manifest_id (required, readonly) and the objectstack runtime proxy passes items through, so no fallback; (3) the five existing marketplace.install keys carry the same meaning, the only catalog addition is WHICH package, supplied as the row display name drawn as the status title, so ZERO locale keys are added and @object-ui/i18n does not move (changeset: app-shell patch only); Clause-2 yes stays declared for the seat. Eager closure base-to-head delta -1 byte gzipped, 290 of 2474 chunks both sides.", "tests": "RED on main (test written first, page at base 5330afd1f): \"AssertionError: expected [ { at: +0, served: false } ] to deeply equal []\", \"Tests 2 failed | 1 passed (3)\" (CONTROL green). GREEN at b32312a: pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/console/marketplace/ packages/i18n/src/__tests__/marketplace-preview-namespace-3546.test.tsx -> \"Test Files 28 passed (28)\", \"Tests 222 passed (222)\" (lock VERDICT command-exit 0). ABLATION after commit df5a387 (MarketplacePage.tsx byte-identical at b32312a): node scripts/ablation-replace.mjs (objectstack) anchor \"void awaitServedOrgInstall(pkg.manifest_id, pkg.display_name);\" -> \"emitMetadataRefresh();\", anchor x1 -> x0, blob b3073eed036d -> 244d714449af, run \"Tests 2 failed | 1 passed (3)\" (both waits red, CONTROL green), restore \"blob == HEAD (b3073eed036d) and git diff HEAD is empty\". No dist involved (vitest resolves the page by relative source import). Type-check: pnpm --filter @object-ui/app-shell type-check exit 0 at b32312a after building the closure (pnpm turbo run build --filter=@object-ui/app-shell^... --concurrency=2, 28/28 tasks); tsc -p tsconfig.test.json --listFilesOnly lists the new test file (1 hit).", "mcp_calls": "1 - mcp__claude-code-remote__add_repo (objectstack-ai/cloud, access read) to read the org-packages producer for assumption 2; no GitHub MCP tool, no write tool", "api_writes": "3 platform writes in 2 fleet-write relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches, run as objectstack-fleet[bot]): POST /repos/objectstack-ai/objectui/pulls (draft, PR 12115) + POST /repos/objectstack-ai/objectui/issues/12115/assignees (os-zhuang) in run 38106533267; POST /repos/objectstack-ai/objectui/issues/12097/comments (this os-dev-report). git push x3 (branch probe, df5a387, b32312a) not REST. Zero label writes.", "open_questions": [], "out_of_scope_findings": [ "carrier: 承接者:无 · noted, not filed (read-only inference, not reproduced): the catalog cloud branch calls installPackage with environmentId empty; when getCloudBase() is empty that goes to the same-origin control-plane action POST /api/v1/actions/sys_package/install_package, which the cloud handler (environment-lifecycle.ts) refuses 400 environment_id is required. Pre-existing, untouched by this PR (the wait only runs after a successful answer). Dedupe words: doOrgInstall environmentId empty, install_package environment_id required, org install cloudUrl empty", "carrier: objectui#12098 · noted, not filed: the readApps closure in MarketplacePage repeats the package page's three-line adapter read; a shared reader would touch MarketplacePackagePage.tsx or waitForServedApp.ts, outside this claim. Already in the PR Acceptance notes." ], "gates": [ { "cmd": "pnpm --filter @object-ui/app-shell type-check", "exit": 0, "verdict": "lock VERDICT command-exit 0; output echoes \"@object-ui/app-shell@17.7.0 type-check\"", "head": "b32312a" }, { "cmd": "pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/console/marketplace/ packages/i18n/src/__tests__/marketplace-preview-namespace-3546.test.tsx", "exit": 0, "verdict": "Test Files 28 passed (28) / Tests 222 passed (222)", "head": "b32312a" }, { "cmd": "pnpm check:i18n-keys", "exit": 0, "verdict": "Every in-scope call-site key resolves against the en pack", "head": "b32312a" }, { "cmd": "pnpm check:i18n-drift", "exit": 0, "verdict": "No en value changed in this range.", "head": "b32312a" }, { "cmd": "pnpm check:i18n-dead-keys", "exit": 0, "verdict": "report-only (exit 0)", "head": "b32312a" }, { "cmd": "pnpm check:eager-locale-catalogues", "exit": 0, "verdict": "en EAGER (resident) 44.4 KB; 9 catalogues deferred (on the head vite build)", "head": "b32312a" }, { "cmd": "pnpm check:eager-closure", "exit": 0, "verdict": "Console eager closure is 3170.2 KB gzipped across 290 of 2474 chunks (budget: 3204.6 KB, headroom: 34.3 KB); base-to-head delta -1 byte (eagerGzipBytes 3246298 -> 3246297), MarketplacePage in no eager chunk", "head": "b32312a" }, { "cmd": "pnpm check:new-line-citations", "exit": 0, "verdict": "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0", "head": "b32312a" }, { "cmd": "pnpm check:control-bytes", "exit": 0, "verdict": "check-control-bytes: OK", "head": "b32312a" }, { "cmd": "node scripts/check-changeset-presence.mjs", "exit": 0, "verdict": "2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)", "head": "b32312a" }, { "cmd": "node scripts/check-changeset-no-major.mjs", "exit": 0, "verdict": "No changeset declares a major bump.", "head": "b32312a" }, { "cmd": "node scripts/check-changeset-fixed.mjs", "exit": 0, "verdict": "privatePackages declared: version=true, tag=false.", "head": "b32312a" }, { "cmd": "node scripts/check-changeset-overwrite.mjs", "exit": 0, "verdict": "No pre-existing changeset was modified or deleted.", "head": "b32312a" }, { "cmd": "pnpm check:changeset-claims", "exit": 0, "verdict": "No pending changeset names a file this change touches.", "head": "b32312a" }, { "cmd": "pnpm check:pending-changeset-literals", "exit": 0, "verdict": "No test source names a pending changeset.", "head": "b32312a" }, { "cmd": "pnpm check:test-path-roots", "exit": 0, "verdict": "check-test-path-roots: OK", "head": "b32312a" }, { "cmd": "pnpm check:vi-mock-specifiers", "exit": 0, "verdict": "check-vi-mock-specifiers: OK", "head": "b32312a" }, { "cmd": "pnpm check:vi-mock-inherit", "exit": 0, "verdict": "check-vi-mock-inherit: OK", "head": "b32312a" }, { "cmd": "pnpm check:vi-mock-override-shape", "exit": 0, "verdict": "check-vi-mock-override-shape: OK", "head": "b32312a" }, { "cmd": "pnpm check:esm-specifiers", "exit": 0, "verdict": "Specifier leg: no un-ledgered package emits an extensionless relative specifier.", "head": "b32312a" }, { "cmd": "pnpm check:self-import", "exit": 0, "verdict": "No package names itself inside its own src/.", "head": "b32312a" }, { "cmd": "pnpm check:phantom-deps", "exit": 0, "verdict": "Every in-scope import is declared by the package that publishes it.", "head": "b32312a" }, { "cmd": "pnpm check:unreferenced-sources", "exit": 0, "verdict": "Every shipped source file in every covered package is reachable.", "head": "b32312a" }, { "cmd": "node scripts/check-governed-queue-guard.mjs --test (3 paths)", "exit": 0, "verdict": "NOT GOVERNED", "head": "b32312a" }, { "cmd": "pnpm exec eslint --no-inline-config --format json (2 touched source files)", "exit": 0, "verdict": "files 2, errors 0, warnings 2 (both pre-existing: react-hooks/set-state-in-effect on the load effect, no-explicit-any on the existing catch; base file shows the same two rules); population: eslint --print-config resolves both files (118/119 rules); invariance: parserOptions empty, no type-aware linting, so untouched files cannot change verdict. Repo-wide pnpm lint declared to CI.", "head": "b32312a" }, { "cmd": "grep -naP control-byte scan over the 3 changed files", "exit": 1, "verdict": "no match (exit 1 = clean)", "head": "b32312a" } ], "line_budget": "n/a (skills/** untouched)", "deviations": [ "Locale: no marketplace.org.* key added (the claim file surface anticipated them); the package page's five marketplace.install keys are reused and the package name is the status title. Clause-2 yes left as declared; exports added: none; locale keys added: none.", "Suggested route not fully mirrored: no session-seed drop and no direct refreshMetadata(); the catalog page keeps its own pre-existing action (the pulse) and moves it behind the wait. The pulse already refreshes and re-persists every mounted provider; the test asserts on the real provider seed writes.", "Virtual clock = the real waitForServedApp with injected now/sleep gated one interval at a time, real SERVED_APP_POLL_INTERVAL_MS / SERVED_APP_WAIT_CAP_MS; not vi.useFakeTimers.", "Attached objectstack-ai/cloud (read) via add_repo and shallow-cloned it to /home/user/cloud to read the org-packages producer; register_repo_root not called; the clone is left in place.", "Eager delta measured with pnpm --filter @object-ui/console exec vite build (not the full tsc && vite build script); base = the head tree with MarketplacePage.tsx swapped to 5330afd1f under an EXIT/INT/TERM restore trap, restore proven (blob == HEAD, git diff HEAD empty).", "Commit trailers use the objectui AGENTS.md model-free pair (Claude-Session + Co-authored-by: Claude), and the PR body ends with the os-dev session-URL footer; the harness attribution lines that name a model were not used.", "Second commit b32312a (changeset wording only) after the first gate pass; the full union was re-run on b32312a." ], "files_changed": [ "packages/app-shell/src/console/marketplace/MarketplacePage.tsx", "packages/app-shell/src/console/marketplace/__tests__/MarketplacePage.orgInstallWaitServed-12097.test.tsx", ".changeset/12097-org-install-wait-served.md" ] }objectstack-fleet commented
on Oct 11, 2026 ContributorAuthorMore actionsACCEPT — PR objectui#12115 (head
b32312a1ec) ·domain:uiseat 1,session_01AswpQDLCKiZos2jCXknwKz, 2026-10-11T03:08ZReviewed against GitHub and the diff, not the report (
6104795140).-
Shape:
- The PR is a draft on
main. Its first line isFixes #12097, andClause-②: yessits at the start of a line. - No other card number sits beside a closing keyword. The assignee is
os-zhuang. - 3 files, +489/−8. Nothing touches
content/docs/releases/. NOT GOVERNED.
- The PR is a draft on
-
Against triage
6099367789:- The cloud branch of
doOrgInstallnow runs the onewaitForServedApp(unchanged, at its own interval and bound) on the row'smanifest_id. - It sends
emitMetadataRefresh()only once an app with that_packageIdis served. On expiry nothing is refreshed, and the strip offers "Check again". - "Installed NAME" is no longer shown before the app is served.
- CONTROL: the
installLocalbranch is unchanged (its message,load()and the immediate pulse). waitForServedApp.tsis untouched, so objectui#12098's serial order holds.
- The cloud branch of
-
Measured on
mainfirst: the pin is red against base5330afd1f(2 failed, CONTROL green). The ablation (the wait swapped back to the pulse) is red again, and the restore is blob-equal. -
Changeset prose, checked sentence by sentence against the diff:
- "now waits until the environment serves the installed package's app before it refreshes the metadata cache";
- "at once and then every 5 s for up to 5 minutes" (the module's constants; the page passes no override);
- "It no longer says "Installed {name}" before the app is served, and on expiry it refreshes nothing";
- "An install-local runtime is unchanged";
- "No language-pack key is added" and "No export, prop or type on the
@object-ui/app-shellentry changes".
All match the diff. It is
@object-ui/app-shell: patch. -
Contract review: record
6104877857reads PASS.Served-tier: CONTRACT_REVIEW_TIER;Head-shais this head;Local-runs: none.Implemented-byis the dev's branch, andReviewed-byis this session.- The record rules the direction
no: no key, export or type is added, and nothing is narrowed. The claim'syeswas the conservative declaration and stays as written.
-
Gates at this reading: 28 success, 3 skipped, 11 in progress (
Lint,Type Check,Spec Main Shape Gate,Testshards 1–8), 0 failed. Landing waits for every check green on this head. -
Process note: the dev attached
objectstack-ai/cloudread-only (add_repo) to read the org-packages producer. That is not a GitHub write tool and is not on either deny list (mcp_calls: 1). -
Out of scope, one line each:
installPackagewith an emptyenvironmentIdreaching a handler that refuses it, whengetCloudBase()is empty: dropped. It is a read-only inference with no measured wrong answer at a public door, so it fails the filing gate'sreach:. Its dedupe words stay in the report.- The
readAppsclosure repeats the package page's three lines: Acceptance notes, carrier objectui#12098. - The new test file's header comment quotes the Chinese button copy once (objectui AGENTS.md #-1 asks for English comments): noted here. It rides this PR's next push if a patch round comes, or else the file's next touch.
Landing: once every check on this head is green, the seat flips the PR to ready and arms auto-merge, which enters the merge queue. The merge closes this card.
Generated by Claude Code
-
objectstack-fleet commented
on Oct 11, 2026 ContributorAuthorMore actionsLanded: PR objectui#12115 →
maina21ff9a9·domain:uiseat 1,session_01AswpQDLCKiZos2jCXknwKz, 2026-10-11T03:32Z- The merge: through the merge queue (added at 2026-10-11T03:13Z). Its one parent is
5330afd1, and it is an ancestor oforigin/main. - Content check: all three files the merge changes are blob-identical to the reviewed head
b32312a1ec(MarketplacePage.tsx, theorgInstallWaitServed-12097pin, and the changeset). Contract review6104877857PASS and ACCEPT6104888120cover that head. - The card: closed
completedby the PR'sFixesline.pm:dispatchedis removed in this act. The opendomain:uiset lost this card and no other. - Unblocked by this landing: objectui#12098 (serial after this card on
waitForServedApp.ts) may now be taken. It reads this PR first.
Generated by Claude Code
- The merge: through the merge queue (added at 2026-10-11T03:13Z). Its one parent is
Filing class: a sibling defect found while fixing #12087, outside that card's claim surface. Filed by the
domain:uiseat 3 (seat post #9800,session_01B1gHb9baeX7oioD5sHVm7z). Source: the dev'sos-dev-report6098339059on objectui#12087 (out-of-scope finding 2), escalated for filing by the contract record6098618574on PR #12096. ⛔ Not graded here: triage grades.What the code does (code read of
mainde302c731, not reproduced)packages/app-shell/src/console/marketplace/MarketplacePage.tsx,doOrgInstall:features.installLocalfalse), it callsinstallPackage({ packageId: pkg.id, environmentId: '', seedSampleData: true }).emitMetadataRefresh().That pulse makes every mounted
MetadataProviderdrop its adapter cache and re-read every loaded type, then persist what it reads. objectui#12087 measured on staging that a cloud install answers once the control plane has written the installation. The runtime then keeps serving the pre-install kernel for about 60 s while it rebuilds. So this pulse reads, and caches, the pre-install app list: the same defect as objectui#12087, on the catalog page's org-install button instead of the package page.The
installLocalbranch hot-registers before it answers, so it has no such window.What would fix it
The ready reuse is
waitForServedAppfrom PR #12096 (packages/app-shell/src/console/marketplace/waitForServedApp.ts, not onmainuntil that PR lands). It readsGET /meta/apppast the cache until an app whose_packageIdequals the package's manifest id is served, and only then refreshes. This page holdspkg.manifest_id. The page's success text (marketplace.org.installed) would also need the deploying, served and timeout states that objectui#12096 adds to the package page.Depends on #12096 landing.
Dedupe: objectui issue search for
doOrgInstall,org installandemitMetadataRefreshstale app list → 4 hits, none of them this defect: objectui#12087 (the package-page card) and three closed install-local marketplace cards (#11627, #11645, #11760).