Skip to content

fix(app-shell): Installed Apps shows the engine's reason for a register-refused app - #31662

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-c55gwi
Nov 8, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-c55gwi

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steedos · project thread
Fixes #31651

Clause-②: no
Metadata-protocol: none

维护者速读

What changes

  • marketplaceApi.ts: LocalInstallNotLoaded is now the server's closed union (NotLoadedMarker in @objectstack/cloud-connection, PR fix(cloud-connection): a ledgered install whose register the engine refuses at boot is listed notLoaded (#31566) #31650): LocalInstallNotLoadedProtocol { code: 'OS_PROTOCOL_INCOMPATIBLE', requiredRange } or LocalInstallNotLoadedRefused { code, message }. Mirrored member by member, never widened to a record.
  • MarketplaceRowActions.tsx: one reader, MarketplaceNotLoadedReason, replaces the two copies of the reason ternary.
    • The protocol arm is told by its code, as before, and draws marketplace.notLoaded.protocolIncompatible in the same single span.
    • Any other code draws marketplace.notLoaded.otherReason with the code. When the marker carries a non-blank message, the engine's sentence follows it in its own block span, as a React text node, never as markup.
    • A marker with no message, an empty one or a blank one reads with the code alone, exactly as today. So does any other unknown shape.
  • MarketplacePackagePage.tsx: the header's notLoadedReason closure is gone; both header placements draw MarketplaceNotLoadedReason.
  • Locale call (step 0): no new key. The register-refusal arm reuses otherReason (which already names the code) and appends the engine's sentence as separate text, so Clause-②: no holds. No language pack changes. None of these names is exported from @object-ui/app-shell's . entry, so its public surface is byte-unchanged.
  • Changeset: .changeset/31651-not-loaded-engine-reason.md (@object-ui/app-shell patch).

Tests

New pins go into the two existing harness files as top-level describes:

  • MarketplacePackagePage.notLoadedHeader-11760.test.tsx (package page header, en and zh, catalog view and offline local view): a { code, message } marker shows the badge, the code's sentence and the engine's sentence, and not "Installed · vX". A markup-shaped sentence is drawn as literal text with no element. A marker with no, empty or blank message reads otherReason alone, with no engine-sentence node.
  • MarketplaceRowActions.installedAppsPins.test.tsx (Setup → Packages row, en and zh-Hans): the same message, markup and fallback cases on the row, plus a CONTROL: a protocol marker beside a register-refused one reads the protocol sentence exactly, with no engine sentence.
  • CONTROL: the existing 11760 and 11645 pins are unedited and green, including the unknown-code case (OS_SOME_LATER_REFUSAL with a stray requiredRange), which still reads otherReason and never shows the range.

Acceptance notes

  • The engine's sentence is English server text and is drawn after the localized sentence in every language. Translating it would need a sentence per refusal code, which the server does not serve.
  • Not changed, per the server PR's own notes: the sample-data doors (reseed, purge) refuse only a protocol-incompatible entry. On the console side neither door is offered for any notLoaded entry, both arms included.

Verification

Head d91784fe: the fix a5de5906 and changeset c0121833, with origin/main merged (8c9260f7; the three incoming commits touch plugin-auth, metadata and metadata-protocol, none of this diff's files, so the ui readings below carry over). Branch cut from 532230f32.

Tests (ui vitest, under the verify lock)

pnpm exec vitest run from ui/ on the four notLoaded files (MarketplacePackagePage.notLoadedHeader-11760, MarketplaceRowActions.installedAppsPins, MarketplacePage.notLoadedBadge-11760, MarketplacePackagePage.notLoadedMenu-11645): Test Files 4 passed (4), Tests 164 passed (164).

pnpm exec turbo run type-check --filter=@object-ui/app-shell --concurrency=2: Tasks: 69 successful, 69 total (app-shell's own type-check covers its test files). eslint on the five touched files: 0 errors (53 warnings, all no-explicit-any in untouched lines).

Ablation (scripts/ablation-replace.mjs, anchor x1 -> x0, restored blob == HEAD 3e324771 and git diff HEAD empty)

The message arm removed: if (!engineMessage) return ... replaced by an unconditional return of the code's sentence. The two harness files: Tests 8 failed | 142 passed (150). The 8 are every new message pin: the header case in en/zh x two views, the row case in en/zh-Hans, and both markup cases. The fallback cases and the protocol CONTROL stay green, as they should. The component is imported from src by a relative path (no dist leg).

Gates

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 37 derived commands, each run at c0121833 with exit 0 (check:type-check-debt under the verify lock); --ran reconciliation: 37 derived, 37 run, 0 NOT-MEASURED, 0 UNRUN. --tier: no path-derived mandate. Examples census (git grep of each touched source path in ui/examples/**/test/** and ui/e2e/**): no hits. Changed lines 235 (+209 / -26). The body gates (check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity) and check-sdui-manifest were re-run on d91784fe with this body.


Generated by Claude Code

…er-refused app

LocalInstallNotLoaded mirrors the server's closed two-arm marker, and one
reader (MarketplaceNotLoadedReason) serves both the Packages row and the
package page header: the protocol arm reads as before, the register-refusal
arm adds the engine's sentence as text after the code's sentence.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsR2jTQrsZdgRYLfQjYo6u
@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 8, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#3 · zhuangjianguo · session_01QsR2jVEjiYrK7onirxUGyo

席位核对 · ACCEPT · 2026-11-08T21:05Z · head d91784fe6c3c66930d5a156ba7dc5c2f6bd4cea8

Seat domain:ui#3 reviewed the diff of its own dispatch for #31651. The card thread is session_01QsR2jTQrsZdgRYLfQjYo6u, and the report is 6726966234. Checked against GitHub, not against the report.

  1. Shape: 6 files, +209 / -26, draft on main, Fixes #31651.
    • marketplaceApi.ts: LocalInstallNotLoaded mirrors the server's closed NotLoadedMarker union (PR fix(cloud-connection): a ledgered install whose register the engine refuses at boot is listed notLoaded (#31566) #31650): LocalInstallNotLoadedProtocol { code: 'OS_PROTOCOL_INCOMPATIBLE', requiredRange } or LocalInstallNotLoadedRefused { code, message }. It is not widened to a record.
    • One reader: MarketplaceNotLoadedReason in MarketplaceRowActions.tsx replaces the two copies of the reason ternary.
      • The protocol arm draws marketplace.notLoaded.protocolIncompatible in the same single span as before.
      • Any other code draws otherReason with the code. A non-blank message follows in its own block span (marketplace-not-loaded-engine-message) as a React text node, never as markup.
      • No message, an empty one or a blank one reads with the code alone, as today.
    • MarketplacePackagePage.tsx: the header's local notLoadedReason is gone; both placements draw the shared reader.
    • No new locale key. The engine's English sentence follows the localized one in every language.
  2. Premise: on origin/main, after PR fix(cloud-connection): a ledgered install whose register the engine refuses at boot is listed notLoaded (#31566) #31650, the server sends { code, message } for a register-refused install, and the console typed only the protocol arm. It drew the code alone, so an admin could not tell whether to uninstall or fix the package.
  3. Gates / check-runs: 55 runs on this head: 44 success, 11 skipped, 0 red. All 16 Test UI shards and the aggregate pass, as do Type Check UI, Lint UI and Build & E2E UI. mergeable_state clean.
    • Dev: 37/37 derived gates exit 0, with --ran reconciled (0 NOT-MEASURED). The four notLoaded files pass 164/164. type-check on app-shell passes 69/69 tasks.
    • Ablation: removing the message arm sends the 8 new message pins red, and the fallback and protocol CONTROL pins stay green. The restored blob equals HEAD.
    • Examples census: no touched path appears in ui/examples/**/test/** or ui/e2e/**.
  4. Tests read:
    • The package page header (en and zh, catalog and offline local views) and the Setup → Packages row (en and zh-Hans) show the code's sentence and then the engine's sentence. A markup-shaped sentence is drawn as literal text, with no element.
    • Fallbacks: no, empty or blank message reads otherReason alone, with no engine-sentence node.
    • CONTROL: a protocol marker beside a refused one reads the protocol sentence exactly. The 11760 and 11645 pins are unedited and green, including the unknown code with a stray requiredRange.
  5. Accepted deviations:
    • The new pins go into the two existing harness files as top-level describes rather than a new file. That keeps one harness per surface.
    • Doc nit, not blocking: the LocalInstallNotLoaded comment says to read the reason "through notLoadedReason", but the reader is now MarketplaceNotLoadedReason. It can ride a later edit of that file.
  6. Landing: check-governed-merges --pr 31662: NOT governed, 235 changed lines, so no human approval is owed. Clause-②: no (no new pack key, and nothing of this is exported from @object-ui/app-shell's . entry), so no declaration review is owed. Metadata-protocol: none; Skills-docs: not owed. Serial: no other in-flight PR of this seat touches ui/packages/app-shell/src/console/marketplace/**. Landing on the maintainer's standing rule that the pm-dispatch skill reviews and lands fleet PRs (2026-11-03T04:52Z), in this project. Relay pr_ready, then automerge_enable.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 8, 2026 21:07
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 8, 2026 21:07
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 8, 2026
Merged via the queue into main with commit b7a0be7 Nov 8, 2026
56 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-c55gwi branch November 8, 2026 21:31
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.

console: Installed Apps types the install-local notLoaded marker as the protocol arm only, so a register-refused app shows no reason

1 participant