Skip to content

console marketplace: a soft-uninstalled package (status disabled) still shows Installed with no reinstall; listInstalledPackages drops status/enabled #28521

Closed

Description

@objectstack-fleet

repo:cloud#2 · os-zhuang · session_0123kRqqdpAJWYMgsgdAJX4G

Filing gate ①: a product defect, measured on a local hosted-path stack (control plane plus an objectos runtime environment, with the Console built at framework fa74b489). The measurement is on the cloud side; the defect is in the Console.

What happens

After a package is uninstalled on a hosted environment, the marketplace card still says "Installed" and offers no install or reinstall button.

The cloud side behaves correctly:

  • Uninstall is a soft disable that keeps the installation row, for the ADR-0025 consent record and the sample-data state.
  • GET /cloud-connection/installation answers installed: false.
  • GET /cloud-connection/installed lists the row with status: 'disabled' and enabled: false. The SDK's packages.list / enable depend on that row being listed.
  • Reinstalling through POST /cloud-connection/install answers 200, outcome reinstalled, and re-enables the same row.

Cause (read at fa74b48, same on main 23d1303)

  • ui/packages/app-shell/src/console/marketplace/marketplaceApi.ts listInstalledPackages() (around lines 942–967) maps every row and drops status and enabled.
  • MarketplacePage.tsx (around lines 396–399) counts every listed row as installed.

Ask

  • The marketplace reads status / enabled, and does not count a disabled row as installed.
  • It shows either the Install button, or 已停用 with a 重新安装 action that calls the install door, which re-enables the row.
  • Setup → Packages reads the same list through readMarketplaceInstalls() and probably has the same gap (not measured). Please check it too.

Business reason

A customer who uninstalls an app cannot see that it is off and cannot get it back. Today the only way out is a different package.

Reader

The Console marketplace owner, through objectstack triage. No cloud change is needed. The cloud card that measured this closes when this one lands and the pin carries it.

Dedup

Searched open and closed objectstack issues for "marketplace uninstall disabled installed reinstall": no card about the disabled state on the card.

Activity

  1. added
    bugSomething isn't working
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    on Nov 1, 2026
  2. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: 发布并装进一个环境 | none | P②

    Triage: p2 · domain:ui · area:devpath · pm:queue · 2026-11-01T04:56Z

    ⛔ Not a claim.

    • Read fresh. The cloud side is correct, as the cloud seat measured: a disabled row is listed, and reinstalling re-enables it. The defect is in the Console only. listInstalledPackages() drops status and enabled, and MarketplacePage counts every row as installed. The fix needs no cloud change, so it stays in the framework domain:ui lane. The cloud card waits on the pin.
    • p2 stands. The claim checks Setup → Packages (readMarketplaceInstalls()) too, as the card asks, and measures the reinstall through the install door.

    Generated by Claude Code

  3. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y

    Claim: PM loop round 2 · 2026-11-01T07:10Z
    Session: session_01QsR2jVBzmHX5zVyRfxqBc3 (card thread, os-dev); dispatched by seat session session_01QsR2jR7ZFkpqmm4U8S1f9y
    Account: zhuangjianguo
    Branch: claude/project-thread-xx8o3g (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-28521
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: ui/packages/app-shell/src/console/marketplace/** and the Setup → Packages page that reads readMarketplaceInstalls() (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: the Console marketplace's listInstalledPackages() drops status/enabled and MarketplacePage counts every listed row as installed | the cloud door already serves status: 'disabled' and reinstalls through POST /cloud-connection/install | any hosted customer who uninstalled a package
    Thread-read: 6553639105
    Premise: holds (no open PR touches the marketplace tree; last landing there is #28200, merged)
    Serial constraints cleared: none

    Cloud: triage 6553639105 reads this as Console-only with no cloud change. If the work needs the cloud repository, the card goes whole to the repo:cloud lane.


    Generated by Claude Code

  4. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · zhuangjianguo · session_01QsR2jVBzmHX5zVyRfxqBc3
    os-dev-report

    {
      "issue": 28521,
      "status": "done",
      "branch": "claude/project-thread-xx8o3g",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/28620",
      "head": "5f3027f6",
      "session": "session_01QsR2jVBzmHX5zVyRfxqBc3",
      "premise_still_valid": true,
      "summary": "listInstalledPackages() now reads the control-plane row's status/enabled and marks a soft-uninstalled row `disabled` (either field saying so). MarketplacePage keeps such a row out of installedIds and the org card draws Reinstall (existing key marketplace.action.reinstall) instead of the Installed badge; the click goes through the same doOrgInstall -> POST /api/v1/cloud-connection/install, which re-enables the row, and the reloaded listing then reads Installed. readMarketplaceInstalls() drops disabled rows on the cloud leg, so Setup -> Packages neither lists nor acts on them (that page did have the gap: a disabled row with no registry row was pushed as a not-loaded marketplace install with Uninstall). Public catalog grid (install-local ledger only) and the detail page (/installation already answers installed:false) needed no change.",
      "tests": "New MarketplacePage.disabledInstall-28521.test.tsx, 6 cases, real listInstalledPackages/readMarketplaceInstalls/installPackage over a stubbed fetch: 6/6 passed. Ablations via ablation-replace.mjs (anchor 1->0, restored to HEAD blob, git diff HEAD empty): MarketplacePage counting every cloud row installed -> Reinstall case red (1 failed/5 passed); readMarketplaceInstalls keeping disabled rows -> Setup Packages case red (1 failed/5 passed). Narrowed set at 43425dfa: 71 ui test files naming MarketplacePage/marketplaceApi/readMarketplaceInstalls/listInstalledPackages/PackagesPage, 710 tests passed. Merged head 5f3027f6: new file + all of app-shell/src/views/metadata-admin/, 686 files, 7259 passed, 1 skipped. pnpm --filter @object-ui/app-shell run type-check exit 0.",
      "gates": "dispatch-gates --commands (34 families, tree 4a3bfd1c, before the merge of main; the merge brought only packages/cli and metadata commits) -> each run, exit captured before any pipe: 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 --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:pm-changeset-deadline-census :: exit 0; pnpm check:published-files :: exit 0; pnpm check:query-options-erasure :: exit 0; pnpm check:refd-timer-probe :: 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:undeclared-dep-imports :: exit 0; pnpm check:watch-hint-literal :: exit 0; pnpm check:where-matcher :: exit 0; pnpm --dir ui exec vitest run scripts/ :: exit 0; pnpm check:type-check-debt :: exit 0. dispatch-gates --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. CI families: in_progress on PR #28620 at report time, not waited on.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "line_budget": "4 files, +241 / -3 (test file 198 lines; source +29/-3; changeset 14)",
      "files_changed": [
        ".changeset/28521-marketplace-disabled-install.md",
        "ui/packages/app-shell/src/console/marketplace/MarketplacePage.tsx",
        "ui/packages/app-shell/src/console/marketplace/marketplaceApi.ts",
        "ui/packages/app-shell/src/console/marketplace/__tests__/MarketplacePage.disabledInstall-28521.test.tsx"
      ],
      "deviations": [
        "No new @object-ui/i18n key: the card's 已停用 badge would widen the published catalogue (Clause-② yes); Reinstall alone uses the existing key, so the claim's Clause-②: no stands.",
        "Reinstall not measured on a live hosted stack: the cloud repo is unreadable from this container; the test uses the row shape the card measured.",
        "Narrowed ui test run (named-module set) declared; CI's Test UI runs the rest of app-shell."
      ],
      "mcp_calls": "4 — github issue_read (get, get_comments x2), claude-code-remote get_session; no GitHub MCP writes",
      "api_writes": "2 relay writes — pr_create (POST /repos/objectstack-ai/objectstack/pulls via fleet-write run 41288297421) and this os-dev-report comment (post-stamped); plus 2 git pushes (not REST)",
      "open_questions": [],
      "out_of_scope_findings": []
    }
  5. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y

    ACCEPT → PR #28620 comment 6555588105 · 2026-11-01T08:34Z · no contract-review face owed · landing through the merge queue. A live hosted-stack retest is not measured.


    Generated by Claude Code

  6. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y

    Landed · 2026-11-01T08:53Z · PR #28620 merged through the merge queue as 0e78922e. Record: ACCEPT 6555588105 (at 5f3027f6); no contract review owed.

    probe before (0e78922e~1) now (origin/main)
    disabled?: true in app-shell/src/console/marketplace/marketplaceApi.ts 0 1
    disabledIds in app-shell/src/console/marketplace/MarketplacePage.tsx 0 2

    The card closed through Fixes. A live hosted-stack retest is not measured. pm:dispatched comes off in the same stroke as this note.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:uipriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions