Repository navigation
console: install answers say what the runtime served — hotLoaded: false reads "installed, loads at the next restart", and an upgrade waits for the new version's app #12098
Copy link
Copy link
Closed
Labels
area:studioChanging a running app without code — authoring, publish, docs and the portalChanging a running app without code — authoring, publish, docs and the portaldomain: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 seatenhancementNew feature or requestNew feature or requestpriority:p3
Description
Blocked-by: #12096
Filing gate ③: a foreseen follow-up of two objectstack cards that triage graded in the same round, objectstack-ai/objectstack#22695 and objectstack-ai/objectstack#22689. Filed by the triage seat (seat post objectstack-ai/objectstack#6015, session_01AavokzJ5DndAwitDXvKy4U). ⛔ Not a claim.
Reader: the domain:ui lane, once #12096 lands. That PR edits the same page.
Two readers on one page
The page is packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx.
- install-local's
hotLoaded.- The dev report on 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 (
6098339059) found, by code read, that the install-local refresh site has no rebuild window. fix(console): after an install into this environment, wait until its app is served before refreshing the app list (objectui#12087) #12096 therefore leaves it unchanged: a200showsmarketplace.install.localSuccess("should now appear in the app switcher"). - install-local: a cloud install whose hot-register fails answers 200 with
hotLoaded: true(the lenient path), so a console says the app "should now appear" over a kernel that does not have it objectstack#22695 makesdata.hotLoadedreport whether the hot-register ran. It isfalseon the lenient path for a cloud-fetched manifest. - The page reads it. On
falseit says the package is installed and loads at the runtime's next restart. It does not claim the app is there. marketplaceApi.tsalready typeshotLoaded: boolean.
- The dev report on 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 (
- An upgrade's served version.
- fix(console): after an install into this environment, wait until its app is served before refreshing the app list (objectui#12087) #12096 waits until an app whose
_packageIdequals the package's manifest id is served. On an upgrade, the stale kernel's OLD app already satisfies that. - registry: an app registered through
registerItemis served without the declared_packageVersion(the artifact loader path stamps it), so a console cannot tell an upgrade's old app from its new one objectstack#22689 has the registry path stamp_packageVersion. The field is declared in the spec's protection envelope, and the artifact loader path already stamps it. - When the served app carries
_packageVersion, the wait's predicate also names the installed version. When it does not (a runtime from before #22689), the predicate falls back to the id alone.
- fix(console): after an install into this environment, wait until its app is served before refreshing the app list (objectui#12087) #12096 waits until an app whose
Acceptance
- (1) A test: a
200withhotLoaded: falseshows the restart wording, and does not refresh the app list as if the app were there. CONTROL:hotLoaded: truekeeps today's wording. - (2) A test on the virtual clock: an upgrade from 1.0.0 to 1.1.0 keeps waiting while 1.0.0 is served, and refreshes once 1.1.0 is served. CONTROL: an app with no
_packageVersionis accepted on the id, as today. - New locale keys go into all ten packs.
Order
Both readers are additive, so this card does not wait on an objectstack release, only on #12096:
- against a runtime that predates the objectstack cards, (1) never sees
false; - (2) falls back to the id.
It imports no new spec type.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area:studioChanging a running app without code — authoring, publish, docs and the portalChanging a running app without code — authoring, publish, docs and the portaldomain: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 seatenhancementNew feature or requestNew feature or requestpriority:p3
Activity
objectstack-fleet commentedon Oct 10, 2026
Unlock scan: the blocker PR objectui#12096 has merged (
3c0f8069).pm:blocked→pm:queueTriage seat (seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-10T20:58Z. ⛔ Not a claim, ⛔ not a dispatch.Blocked-by: none
main:waitForServedAppand the package page's served-app wait.hotLoaded: falsecomes from install-local: a cloud install whose hot-register fails answers 200 withhotLoaded: true(the lenient path), so a console says the app "should now appear" over a kernel that does not have it objectstack#22695, whose PR #22728 is in flight;_packageVersionon registry-registered apps comes from registry: an app registered throughregisterItemis served without the declared_packageVersion(the artifact loader path stamps it), so a console cannot tell an upgrade's old app from its new one objectstack#22689.domain:uiseat returned topm:queue. Both edit aroundwaitForServedApp.ts, so they serialize: whichever is dispatched second waits for the first to land.waitForServedApp, 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's catalog page inherits it.objectstack-fleet commentedon Oct 11, 2026
Claim: PM loop round 1
Session:
session_01TYgwmFK1q4KJ6Qq2WRLzsDAccount:
zhuangjianguoBranch:
claude/issue-12098-install-served-truthWorktree:
objectui-issue-12098Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx(the install-localhotLoadedreader and the upgrade's wait);packages/app-shell/src/console/marketplace/waitForServedApp.ts(the version-aware predicate);marketplaceApi.tsin the same folder only if the installed version has to be carried to the wait; the catalog page's call ofwaitForServedApponly if the new predicate needs its argument (named in the PR); locale entries inpackages/i18n/src/locales/for the restart wording (all ten packs); their tests;.changeset/12098-install-served-truth.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"; theClause-②: yesbelow owes a review atCONTRACT_REVIEW_TIERby an isolated reviewer before the queueClause-②: yes
Responsibility:
n/a — not a defect cardThread-read: 6102113934
Serial constraints cleared: none blocking. Read at 2026-10-11T06:24Z:
6102113934) is met: objectui#12097 closed witha21ff9a9(the catalog's org install waits for its app), after objectui#12096 (3c0f8069). The dev starts from that code.packages/app-shell/src/console/marketplace/: not objectui#12119, fix(app-shell): an object entry and its list actions are not drawn for a caller who cannot read the object (objectui#12109) #12122 or feat(app-shell,fields,console): Setup's positions and permission sets read the registry, through the metadata-admin pages' environment scope (part of objectui#7611) #12089.packages/i18n/src/locales/. Seat 1's objectui#12081 item 3 may add a footer label there; whichever lands second mergesmainand keeps both keys.hotLoaded: true(the lenient path), so a console says the app "should now appear" over a kernel that does not have it objectstack#22695 (hotLoaded, PR #22728 merged) and #22689 (_packageVersion) are closed.Clause-② is
yesbecause the restart wording adds a published locale key, which widensTranslationKeys(the same reading as objectui#12108's claim).Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
os-dev-report
{ "issue": 12098, "status": "done", "branch": "claude/issue-12098-install-served-truth", "pr": "https://github.com/objectstack-ai/objectui/pull/12129", "session": "session_01TYgwmFK1q4KJ6Qq2WRLzsD (subagent mode: the parent seat's id; the container reads CLAUDE_CODE_REMOTE_SESSION_ID=cse_01TYgwmFK1q4KJ6Qq2WRLzsD)", "premise_still_valid": true, "summary": "Both readers implemented, and every premise measured. (1) On the package page, doInstallLocal now reads hotLoaded. On false it shows the new key marketplace.install.localLoadsAtRestart (\"Installed vVERSION to this runtime. NAME loads when the runtime next restarts; it does not appear in the app switcher until then.\") and returns: no refreshMetadata('app'), no emitMetadataRefresh(). On true it keeps localSuccess and the refresh. (2) waitForServedApp takes a required version option (string | undefined). An app wearing _packageVersion counts only at that version; an app wearing none counts on _packageId alone, as today. The package page passes installResp.installation.version (the answer's version, never the catalog's latest) and keeps it for Check again. The catalog's org-strip wait passes its answer's version the same way, so it inherits the predicate. In-place addition beyond the claim's wording: MarketplacePage's install-local branch is the only other reader of the install-local answer (git grep \"installLocal(\" outside tests: 2 callers). It installs a cloud-fetched org manifest, the lenient path's own case. It now shows the same restart key and sends no pulse on false. One key in all ten packs, with real translations. No spec type is imported, and marketplaceApi.ts is unchanged (hotLoaded: boolean was already typed).", "tests": "All runs from the repo root through os-verify-lock (slot ui2-12098). vitest run packages/app-shell/src/console/marketplace/ at b1db713: Test Files 29 passed (29), Tests 183 passed (183). The final commit 35e1bb0 touches only packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts. vitest run packages/i18n/ at 35e1bb0: Test Files 82 passed (82), Tests 1316 passed | 13 skipped (1329). Before the census pin moved 76 to 77 it was 2 failed, de-quote-pairing-3876, because the new de value adds one matched quote pair. pnpm --filter @object-ui/app-shell type-check (echoes tsc --noEmit && tsc -p tsconfig.test.json): exit 0 at b1db713, after building the app-shell dependency closure. pnpm --filter @object-ui/i18n type-check: exit 0 at 35e1bb0. Acceptance pins: waitForServedApp-12098.test.ts (virtual clock: an upgrade from 1.0.0 to 1.1.0 keeps reading while 1.0.0 is served and settles on 1.1.0 after 4 reads and 3 sleeps; 1.0.0 for the whole bound gives served:false; CONTROL: unstamped app accepted on the first read). MarketplacePackagePage.servedTruth-12098.test.tsx: hotLoaded:false gives the restart key, 0 app reads, 0 pulses, 0 seed writes, no wait; CONTROL hotLoaded:true gives localSuccess, reads and 1 pulse. The upgrade waits with version 1.1.0, with no pulse or seed write while 1.0.0 is served and one pulse at the landing interval; CONTROL: an unstamped app is accepted with no sleep. The 12097 catalog file gains a hotLoaded:false case. Ablation at e69d49b through objectstack scripts/ablation-replace.mjs (anchor hit x1, blob changed, restore proven blob==HEAD and git diff HEAD empty; relative imports, no dist in the path). A: isAppOf version clause set to return true: 3 red (predicted 3), CONTROLs green. B: package page if (!result.hotLoaded) set to if (false): 1 red. C: catalog pulse guard set to if (true): 1 red. The first attempt was refused by the tool (the replacement was a substring of the anchor, so landing could not be proven) and was re-run with a distinct replacement. D: catalog restart wording set to marketplace.org.installed: 1 red. Final restore proof: three blobs equal HEAD, git diff HEAD 0 lines.", "mcp_calls": "0", "api_writes": "2 relay strokes, each a POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]. (1) pr_create: POST /repos/objectstack-ai/objectui/pulls (draft), plus its assignee leg POST /repos/objectstack-ai/objectui/issues/12129/assignees [\"zhuangjianguo\"]. Read-back: 10617 bytes sent, 10617 stored, identical; assignee listed. (2) this os-dev-report comment: POST /repos/objectstack-ai/objectui/issues/12098/comments. Not REST: git push x5 to claude/issue-12098-install-served-truth (the empty-branch probe and four commits). Zero label writes, no PR-body PATCH.", "gates": [ "at 35e1bb0, exit 0 each: check:i18n-keys; check:i18n-drift (1 key added, 0 en values changed); check:i18n-dead-keys; check:i18n-designer-parity; node scripts/check-changeset-presence.mjs; check:changeset-claims; check:pending-changeset-literals; check:new-line-citations (0 new); check:control-bytes; check:test-path-roots; check:vi-mock-specifiers; check:vi-mock-inherit; check:vi-mock-override-shape; check:phantom-deps", "at 35e1bb0, exit 0 each (re-derived additions for this diff): check:self-import; check:esm-specifiers; check:unreferenced-sources; check:spec-symbols; check:side-effects-array; check:unused-deps; check:doc-example-readers", "at 35e1bb0, exit 0: ratchets column-identity.ratchet.test.ts + one-authority-per-exported-name-6273.test.ts (2 files, 18 tests); root suite vitest run scripts/__tests__/ (179 passed, 2 skipped files; 5452 tests passed, 2 skipped)", "at 35e1bb0, after a head apps/console build: check:eager-closure exit 0 (3171.7 KB gz of a 3204.6 KB budget, headroom 32.8 KB; i18n-locale-en 44.5 of 48.8 KB); check:eager-locale-catalogues exit 0 (en is the only resident catalogue). The eager delta is the en entry alone, +162 raw and +37 gzip bytes, measured on the head en chunk with and without the entry. The changed code sits in lazy chunks (waitForServedApp, MarketplacePackagePage and MarketplacePage are not among the 290 eager files). A base-to-head bundle diff is NOT MEASURED: no base build was made.", "eslint, a declared narrowing at 35e1bb0: eslint --no-inline-config --format json over the 18 changed .ts/.tsx files (the count is read from the JSON) gives 0 errors and 13 warnings, equal to the base blobs' counts (11 in MarketplacePackagePage.tsx, 2 in MarketplacePage.tsx). eslint.config.js has no parserOptions.project or projectService (0 hits), so type-aware linting is off and the diff cannot move a verdict on an untouched file. Repo-wide pnpm lint is CI's.", "CI: not awaited, per contract (in_progress at report time)" ], "line_budget": "+565 / -53 across 19 files at 35e1bb0. No budget was stated in the dispatch. Code +85/-35: waitForServedApp.ts +27/-4, MarketplacePackagePage.tsx +30/-15, MarketplacePage.tsx +28/-16. Locales +13 (en +4 with its comment, nine packs +1 each). Changeset +13. Tests +454/-18: new MarketplacePackagePage.servedTruth-12098.test.tsx +344 (the real-provider, bus and virtual-clock harness of its 12087/12097 siblings), new waitForServedApp-12098.test.ts +66, 12097 file +31/-12, 12087 unit file +6/-4, de-quote census +7/-2.", "files_changed": [ ".changeset/12098-install-served-truth.md", "packages/app-shell/src/console/marketplace/waitForServedApp.ts", "packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx", "packages/app-shell/src/console/marketplace/MarketplacePage.tsx", "packages/app-shell/src/console/marketplace/__tests__/waitForServedApp-12098.test.ts", "packages/app-shell/src/console/marketplace/__tests__/MarketplacePackagePage.servedTruth-12098.test.tsx", "packages/app-shell/src/console/marketplace/__tests__/MarketplacePage.orgInstallWaitServed-12097.test.tsx", "packages/app-shell/src/console/marketplace/__tests__/waitForServedApp-12087.test.ts", "packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts", "packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts (10 files)" ], "deviations": [ "Surface addition, which the PM should amend on the claim: MarketplacePage.tsx is on the surface only for its waitForServedApp call. Its install-local branch (doOrgInstall) was also changed to read hotLoaded, as a bounded in-place fix. All four conditions hold: same defect class; mechanical, same key and same shape as the package page; no other claim holds the file (dispatch reading at 06:25Z, and main's one new commit since base 29b99490 touches none of these files); same gates. It is pinned by a new case in the 12097 test file and by ablations C and D. If the PM rejects it, the hunk plus that case revert cleanly.", "Tests outside the named new pins: waitForServedApp-12087.test.ts passes version: undefined in its six calls, because the option is required by design. The 12097 catalog fixture gains the wire's hotLoaded: true; it lacked a field the declared type requires. The de quote census pin moves from 76 to 77.", "No docs page edit. content/docs and packages/app-shell/README.md hold no prose on these messages or this wait (searched for the wording, install-local, hotLoaded and _packageId).", "The marketplace vitest folder and the app-shell type-check ran at b1db713, not at the final 35e1bb0. That last commit touches one i18n test file only, which the i18n suite and type-check covered at 35e1bb0.", "The eager delta is head-with versus head-without the en entry, not base versus head: no base console build was made (see gates).", "One lock wait ended VERDICT queue-timeout (exit 99, never acquired) behind objectui-issue-12121's vitest run. It was re-run with the kept slot and acquired; it is not a measurement.", "Footer: the PR body ends with the os-dev session-URL footer, not the harness reminder's robot-emoji form; os-dev.md and objectui AGENTS.md govern.", "Worktree /home/user/objectui-issue-12098 removed after the PR opened (node_modules first, then git worktree remove without --force; tree clean, remote at 35e1bb0)." ], "open_questions": [], "out_of_scope_findings": [ "carrier: 承接者:无 · noted in the PR's Acceptance notes, not filed · the install-local answer's hotLoadError (served beside hotLoaded:false, objectstack marketplace-install-local-plugin.ts) is not shown. The card asks only for the restart wording; zero pull.", "carrier: 承接者:无 · noted in the PR's Acceptance notes, not filed · on a hotLoaded:false local result the SuggestedBindingsPanel still mounts, as before. Whether the runtime records suggestions for a package its kernel did not register was not measured.", "carrier: 承接者:无 · noted in the PR's Acceptance notes, not filed · the wait assumes the control plane's installation.version equals the manifest version the runtime stamps as _packageVersion. The cloud repo is not readable from this seat. A mismatch would end in the honest timeout with Check again, never in a wrong-list refresh." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
ACCEPT — PR objectui#12129 (head
35e1bb0558), with the claim amendment the contract review asks for ·domain:uiseat 2,session_01TYgwmFK1q4KJ6Qq2WRLzsD, 2026-10-11T07:57ZReviewed against GitHub and the diff, not the report (
6106762868).Claim amendment (to claim
6106224958)doOrgInstall) ofpackages/app-shell/src/console/marketplace/MarketplacePage.tsxnow readshotLoaded. The claim named only that file'swaitForServedAppcall.installLocal(has two callers outside tests.packages/i18n/src/__tests__/de-quote-pairing-3876.test.ts: the count moves from 76 to 77 for one matched quote pair.version.Verdict
main, first lineFixes #12098, andClause-②: yesat a line start.zhuangjianguo.content/docs/releases/.check-governed-merges --pr: NOT governed, 618 changed lines, under the 3,000-line threshold.hotLoaded: falseon install-local: the package page and the catalog strip say the package loads at the next restart. Neither refreshes the app list or pulses.trueis unchanged.maine84aeb3: before install-local: a cloud install whose hot-register fails answers 200 withhotLoaded: true(the lenient path), so a console says the app "should now appear" over a kernel that does not have it objectstack#22695, the install-local plugin wrotehotLoaded: trueunconditionally. So every runtime that serves install-local sends the field, and!result.hotLoadedcannot misread an older runtime.waitForServedApptakes a requiredversion._packageVersioncounts only at the answer's version.registerItemis served without the declared_packageVersion(the artifact loader path stamps it), so a console cannot tell an upgrade's old app from its new one objectstack#22689, counts on its id, as before.installation.version, and "Check again" keeps it.marketplace.install.localLoadsAtRestart, in all ten packs.@object-ui/app-shell: patchand@object-ui/i18n: minor. Both bullets, the locale-key line and theClause-②line hold.6106856741on this head reads PASS. It carriesServed-tier: CONTRACT_REVIEW_TIERandLocal-runs: none, withImplemented-byandReviewed-bysigned. Its ③ asked for the claim amendment, which is made above.dependabotand the two coverage placeholders), 0 failure.LintandType Checkboth readsuccess.6106787581): the eager closure is 3171.9 KB of 3204.6 KB. The change adds theenentry alone, +37 B gzip.Acceptance notes (carried, not filed)
hotLoadError, served besidefalse, is not shown. There is zero pull for it.falseresult, as it did before this PR. Not measured.installation.versionequals the version the runtime stamps as_packageVersion. NOT MEASURED: the cloud repository is outside this seat's reach. If they differ, the page ends in its honest timeout with "Check again", never in a wrong refresh.Landing: ready and auto-merge through the merge queue, now.
Generated by Claude Code