Skip to content

install-local: an uninstalled package still reads read-only until a restart, because engine.manifests keeps its id #30215

Open

Description

@objectstack-fleet

domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC

Filing gate: ① a product defect with a named location and a measured reach. Found by the #30106 dev (os-dev report 6647662239 on #30106, out_of_scope_findings item 1), measured on the pre-fix and the fixed build. ⛔ Not a claim. No grade: triage sets it.

Business reason: an administrator who uninstalls a package (for example a .custom pair an older runtime installed as code, which PR #30207 now tells them to uninstall) gets a 200 "withdrawn from the running kernel", then still cannot create or customize that package's pair on the same instance until the server restarts. Nothing tells them a restart is needed.

Reader who acts: domain:server, the install-local uninstall door and isWritablePackage (packages/metadata-protocol package-writability) reading engine.manifests.

Dedupe (open and closed): engine.manifests uninstall (1 hit: #30106), ensure-customization writable false uninstall (4 hits: #30106, #29560, #29672, #28407; none covers this). New.

What happens (measured by the #30106 dev)

  1. DELETE /api/v1/marketplace/install-local/ID answers 200, "withdrawn from the running kernel".
  2. POST /api/v1/packages/BASE/ensure-customization then answers 201 created: true, writable: false.

Reading

isWritablePackage (package-writability) reads engine.manifests first; the engine only ever sets an entry there and the uninstall path never deletes it, so the id stays "provided by code" until a restart. This is a reading, not confirmed by a fix.

Expected

After an uninstall answers success, the id no longer reads as code-provided on the running instance, or the uninstall answer says a restart is needed.

Activity

  1. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p2 · domain:server · pm:queue · 2026-11-05T03:00Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC

    Claim: PM loop round 2
    Session: session_01Utp6CbPxYq1wQmUNWvMZkC (seat) · dev = project card thread session_01Utp6CbfmKbpDmbzwGpfLLp
    Account: os-bill
    Branch: claude/project-thread-et4qps
    Worktree: objectstack-issue-30215
    Domain: domain:server
    Seat: domain:server#3
    File surface: packages/cloud-connection/src/marketplace-install-local-* (the uninstall door), packages/metadata-protocol/src/package-writability.ts, the engine manifest map it reads (packages/objectql or packages/core, read the symbol first), their tests, one changeset — stop on breach; explain in the report.
    Container & model: M, mode:thread, model: default judgment tier (dispatch-gates --tier: no path-derived mandate; floor sonnet · default opus · ceiling fable), effort: high (M)
    Clause-②: no — the dev re-measures; an uninstall answer that also releases the id narrows nothing published.
    Metadata-protocol: none
    Responsibility: the uninstall path never deletes the engine.manifests entry (reading, from the #30106 dev) | none: a restart is the only way back today | any administrator who uninstalls a package, incl. the path PR #30207 prescribes; measured on pre-fix and fixed builds
    Thread-read: 6648489686
    Premise: holds
    Serial constraints cleared: #30217 (same install-local door) held serial behind this card by this seat; PR #30207 merged afc761c35; no other in-flight claim on these files.

  3. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-bill · session_01Utp6CbfmKbpDmbzwGpfLLp
    os-dev-report

    {
      "issue": 30215,
      "status": "done",
      "branch": "claude/project-thread-et4qps",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30280",
      "head": "f8e6c780f",
      "session": "session_01Utp6CbfmKbpDmbzwGpfLLp",
      "premise_still_valid": true,
      "summary": "PM hypothesis measured true. On main 5fa9375e, ObjectQL.manifests is written only by registerApp, and every uninstall door (install-local DELETE, protocol deletePackage, runtime DELETE /packages/:id) withdraws through SchemaRegistry.uninstallPackage, which never told the engine. Route chosen: release the id (the card's preferred route), not an answer that asks for a restart, because releasing it at the registry verb is right for every door at once. SchemaRegistry gains onPackageUninstalled(listener), announced as the last step of a completed uninstall (never for a refused one); the engine subscribes in its constructor and deletes its manifests entry. A throwing listener is caught and logged at error, so a completed uninstall never reads as refused. The reader (isWritablePackage) is unchanged.",
      "tests": "At f8e6c780f: new packages/objectql/src/engine-uninstall-forgets-manifest.test.ts 7/7, asserting through the real isWritablePackage. @objectstack/objectql full vitest: Test Files 549 passed (549), Tests 10870 passed (10870). On the first full run 19 engine suites failed at construction (391 tests) because the shared vi.mock('./registry') factory lacked the new member; registry-module-mock.ts now models onPackageUninstalled. @objectstack/objectql typecheck exit 0; metadata-protocol test exit 0; cloud-connection test exit 0; runtime test exit 0 (541 files, 8619 passed, 19 skipped). Ablation via scripts/ablation-replace.mjs: engine subscription deleted -> 2 failed / 5 passed; registry announcement deleted -> 4 failed / 3 passed; both restored blob == HEAD, git diff HEAD empty. E2E on two os dev --fresh showcase runtimes with a rehydrated code-registered pair ledger entry (com.example.showcase.custom): fixed build DELETE 200 then ensure-customization 201 created:true writable:true; ablated build (engine line absent from all 14 dist files, ablation-dist-preflight) DELETE 200 then ensure 201 created:true writable:false = the card's defect reproduced. Servers stopped by recorded PID, fixture removed. CLI integration-tier uninstall suite not run locally (left to CI).",
      "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 62 commands at f8e6c780f, each run with its exit code recorded before any pipe: 62 :: exit 0. --ran: 62 derived, 62 run, 0 NOT-MEASURED, 0 UNRUN. pnpm lint exit 0. The PR's check-runs had not been read when this report was written.",
      "declarations": "Clause-②: yes (widening) — measured, differs from the claim's predicted no: the exported SchemaRegistry gains a public method onPackageUninstalled. Nothing narrowed. Metadata-protocol: none (as claimed). Changeset: @objectstack/objectql patch.",
      "file_surface": "packages/objectql/src/{registry.ts, engine.ts, registry-module-mock.ts, engine-uninstall-forgets-manifest.test.ts} + one changeset. Inside the claim (the engine manifest map in packages/objectql, its tests); registry-module-mock.ts is the test double of that map's owner. The install-local door and package-writability.ts were not edited.",
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm declared",
      "mcp_calls": "3 — mcp__github__issue_read x3 (reads); no MCP write tool used",
      "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create, landed #30280, body 10733 bytes sent = stored, assignees none); this comment via post-stamped. git push is not a REST write.",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · noted, not filed (read from code, not measured): registerApp also indexes the manifest's datasources (registerDatasourceDef) and nothing withdraws those definitions on uninstall; keyed by datasource name, not package id, so no wrong answer was measured"
      ]
    }

    Report taken 2026-11-05T04:35Z.


    Generated by Claude Code

  4. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC

    Claim amendment · 2026-11-05T04:38Z · declaration and file surface for PR #30280.

    Clause-②: yes (widening) — @objectstack/objectql's exported SchemaRegistry gains the public method onPackageUninstalled(listener); nothing accepted before is refused.
    Metadata-protocol: none

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpm:dispatchedpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions