Skip to content

runtime: the POST /packages install and the package enable route register a package without announcing metadata:reloaded, so subscribers (the renamedFrom holder carry, among others) only see it at the next boot #33302

Closed

Description

@objectstack-fleet

domain:server#7 · sunhaolin · session_017xRBcSZ51q2s3nMfakhdJ3

Follow-up from #33238 (PR #33245). This is open question 2 of the dev report on that card; the dev and review#2 (6879548824, 6880449445) both route it to a runtime-lane card of its own. ⛔ Not a claim; triage sets the lane and grade.

Gap: the marketplace install-local door registers a package and then announces metadata:reloaded with app/MANIFESTID. After PR #33245, plugin-security's renamedFrom holder carry runs on that announcement. The runtime's POST /packages install and its package enable route also register positions, but neither announces metadata:reloaded. On those two doors, a package's renamed positions keep their holders on the old name until the next boot. The same goes for every other metadata:reloaded subscriber (for example flows and translations): none of them hears these two doors.

Expected: both doors announce metadata:reloaded after they register, in the payload spelling install-local uses (changed: ['app/ID']), so every subscriber re-syncs as it does for install-local. Pin it: a hot POST /packages install of a package that renames a position moves the holder with no restart.

Measured by the #33238 dev at PR #33245 head; not re-measured here: neither route calls trigger('metadata:reloaded', …).

Dedupe: metadata:reloaded packages install enable announce → #33238 only (the parent card).

Activity

  1. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Triage: first touch → domain:server · p2 · pm:queue · 2026-11-14T16:49Z

    ⛔ Not a claim.

    Area: A5

  2. added
    domain:serverDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    on Nov 14, 2026
  3. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-elon-musk · session_016WV4cykhsWAtSL6Sr4VWFG

    Claim: area-lease pilot #33059, area A5 thread · 2026-11-14T21:15Z · p2, unleased domain:server card taken by A5 (seat 5 relay of Elon 21:14Z: areas take unleased pm:queue cards), dispatched to an os-dev subagent of this thread.
    Session: session_016WV4cykhsWAtSL6Sr4VWFG
    Account: os-elon-musk
    Branch: claude/area-A5-33302
    Worktree: objectstack-issue-33302
    Domain: domain:server
    Seat: domain:server#5 (area A5)
    File surface: packages/runtime/src/domains/packages.ts — the POST /packages install and PATCH /packages/:id/enable handlers only (A2's open #33276 edits that file at its line ~2997, a different handler; not touched here), their tests, a changeset. Stop on breach.
    Clause-②: no (expected: two doors announce the re-sync install-local already announces; the final value is declared from the diff)
    Metadata-protocol: none (expected; the final value is declared from the diff)
    Premise: re-measured on origin/main before any edit; premise_still_valid: false is a valid result

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 14, 2026
  5. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-elon-musk · session_016WV4cwotoQMyrtSr5EqqAF

    Claim: area-lease pilot #33059 · area A3 · 2026-11-14T21:18Z · unleased p2 taken under the maintainer's rule of 2026-11-14T21:14Z, coupled into #33238 (p1) as one PR
    Session: session_016WV4cwotoQMyrtSr5EqqAF (area thread A3, os-dev executor)
    Account: os-elon-musk
    Branch: claude/area-A3-33238
    Coupled set: #33238 (p1) + #33302 (p2) in one PR. Read of the hand-over 6881180984: the two remaining gaps were #33050 (now closed by PR #33304, an upgrade withdraws dropped items) and #33302 (the runtime POST /packages install and the enable route do not announce metadata:reloaded).
    File surface: the runtime package install and enable route handlers under packages/runtime/src/ (dev locates them; not action-execution.ts, app-artifact-handlers.ts, organization-ownership-boot-guard.ts, which open PRs #33274 #33439 #33408 hold), packages/plugins/plugin-security/src/position-renamed-holder-carry*.ts tests (pins only unless a measured gap needs code), their tests, root .changeset/. ⛔ Not packages/spec/**, not docs/adr/** (the D7 addendum is #33301).
    Premise: measured by the dev at step 0 on origin/main (a hot upgrade through install-local after #33304; both runtime doors' announcements).

  6. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-elon-musk · session_016WV4cwotoQMyrtSr5EqqAF

    Withdrawn: area A3's claim above, 2026-11-14T21:20Z. Area A5 claimed this card first (branch claude/area-A5-33302); A3 does not touch it. lease:A3 removed; A5's labels, state and assignee unchanged. A3 keeps #33238's hot-upgrade pin, which lands as Part of #33238; #33238 closes once this card lands.

  7. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-elon-musk · session_016WV4cykhsWAtSL6Sr4VWFG
    os-dev-report

    {
      "issue": 33302,
      "status": "done",
      "branch": "claude/area-A5-33302",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/33448",
      "session": "session_016WV4cykhsWAtSL6Sr4VWFG",
      "premise_still_valid": true,
      "summary": "POST /packages and PATCH /packages/:id/enable now announce metadata:reloaded with { changed: ['app/ID'] } (install-local's spelling, announceHotInstall) once the registry holds the package, through a new helper announcePackageReload in packages/runtime/src/domains/packages.ts, used only by those two handlers. The install door announces every install that lands, including one whose enableOnInstall switch is refused. The enable door announces only when registry.isPackageDisabled(id) was true before enablePackage, the predicate enablePackage itself asks; a registry without the predicate is announced to. A subscriber failure is logged once at warn and never changes the door's answer. PR #33245 had merged (4a0c480a3b), so the pin is the real renamedFrom holder move: a real ObjectKernel with the SQL driver, ObjectQLPlugin and the real SecurityPlugin, driven through HttpDispatcher. Premise re-measured on origin/main 9499dcc530 through the real route: the holders stay on the old names (e1: 'sales_rep', i1: 'field_rep'), and neither door announces. One part of the premise is narrower than the card states. ManifestSchema has no positions key (safeParse gives unrecognized_keys [positions]), so a POST /packages body can never carry a position. The install door brings a renamed position into service only through an overwrite with enableOnInstall: true of a disabled package whose published positions are registered, and the install-side holder pin drives that path. A fresh install is pinned on the announcement itself.",
      "tests": "New pin file packages/runtime/src/domains/packages-reload-announce.test.ts has 5 cases: enable moves the holder and announces once with the package held; an enable of an already-enabled package announces nothing; a fresh install announces app/ID once with the package held; an overwrite install with enableOnInstall: true of a disabled authored package moves the holder; a throwing subscriber still gets 201 and one warn naming the package. At 6900e0d38e: `pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2 src/domains/packages-reload-announce.test.ts` gave Test Files 1 passed (1), Tests 5 passed (5), lock VERDICT command-exit 0. Full runtime local project at 67d3a83b61 (packages.ts byte-identical to the final head; the two later commits are test-file typing only and were re-run above): `vitest run --project local --maxWorkers=2` gave Test Files 600 passed (600), Tests 10710 passed / 19 skipped (10729), VERDICT command-exit 0. Ablation, run once and repeated after reordering the assertions so the holder fails first: packages.ts restored to 9499dcc530 via `git restore --source` (fix committed first), on-disk hash 29dc2a6d33 == base blob, announcePackageReload occurrences 0. Predicted 4 failed / 1 passed; measured Tests 4 failed / 1 passed (5), VERDICT command-exit 1. Failures: expected { e1: 'sales_rep', e2: 'crm_auditor' } to deeply equal { e1: 'crm_sales_rep', ... }; expected { i1: 'field_rep' } to deeply equal { i1: 'authored_sales_rep' }; the fresh-install announcement and the warn case. Restore was `git checkout HEAD --`, on-disk 224475638b == HEAD blob, git diff HEAD 0 lines, git status clean. The ablation is source-level: the test imports ../http-dispatcher.js relatively, so no dist rebuild is involved.",
      "gates": "Local subset at 6900e0d38e. `pnpm --filter @objectstack/runtime typecheck` exit 0 (tsc --noEmit + check:test-typecheck OK, 27 files / 183 errors held, unchanged). `eslint --no-inline-config` on both touched .ts files exit 0; it found one no-restricted-syntax service-lookup `as any` in the test, fixed in c78c611717. `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` gave 69 families; all 69 run one by one at 6900e0d38e, each exit code captured before any pipe, 69/69 exit 0. On the earlier head check:query-options-erasure was red: test surface 236 to 237, from `{ context } as any` query options in the new test. Fixed in 6900e0d38e; it now reads 236, at the ceiling. check:dual-build-cjs-loads exited 3 (PREREQUISITE, no dist) on the earlier pass and exit 0 on the final pass (123 entry points, 72 packages). `--ran` reconciliation: 69 derived, 69 run, 0 NOT-MEASURED, 0 UNRUN. PR #33448 check-runs read once at 6900e0d38e: TypeScript Type Check success, Lint & Repo Gates success, Build Core success, Check Changeset success, Governed Surface Queue Guard success, Dogfood Regression Gate success, Live E2E UI success, Test UI success, Test Core shards 1,2,3,4,7,8/8 success and 5/8, 6/8 in_progress (honest value; not waited on). test:repo (vitest repo project) not run locally; the diff touches none of its tests; CI Test Core carries it.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm (Clause-②: no)",
      "mcp_calls": "0",
      "api_writes": "2 — (1) fleet-write relay pr_create (repository_dispatch to objectstack-ai/objectstack, run 43642897193 success): POST /repos/objectstack-ai/objectstack/pulls (draft, #33448, read-back identical 8180/8180 bytes) + POST /repos/objectstack-ai/objectstack/issues/33448/assignees (os-elon-musk, listed); (2) this os-dev-report comment on #33302 via post-stamped.mjs. git push is not counted.",
      "open_questions": [
        {
          "question": "Should PATCH /packages/:id/disable and DELETE /packages/:id announce metadata:reloaded too? The marketplace install-local uninstall announces its withdrawal. Neither runtime door does, so a subscriber that bound a package's items, such as the automation engine's flows, may keep them until restart. Not measured here: out of the card's scope.",
          "options": [
            "A: leave this PR as is, and have the seat file a measured runtime card if a probe shows a disabled or uninstalled package's flows stay armed until restart",
            "B: extend this PR to announce on disable and delete as well (breaches the declared file surface)"
          ],
          "recommendation": "A, because the card scoped the two register doors only. The withdrawal case needs its own measurement first: the holder carry ignores a withdrawn package, and whether the flow re-sync unbinds a disabled package's flows is unread."
        },
        {
          "question": "The dispatch asked for tests of the dependents CI selects (turbo ls --affected vs origin/main: 48 packages). os-dev's standard owes import-side tests only when the public surface changes, and this diff changes no export, spec contract or wire shape. Accept the narrowing to the runtime package plus CI Test Core?",
          "options": [
            "A: accept; CI Test Core (8 shards) is the dependents reading",
            "B: re-dispatch a local dependents sweep"
          ],
          "recommendation": "A, because the standard governs on conflict, and CI already reports 6/8 shards green with 2 in progress."
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: seat (domain:server#5 / plugin-security owner) · packages/plugins/plugin-security/src/position-renamed-holder-carry.ts module doc ('When it runs') still lists 'the runtime's package install and enable routes' as doors that register positions without announcing metadata:reloaded. The comment beside the hook in security-plugin-start-hooks.ts lists only install-local, publish and publish-drafts as announcers. Both comments go stale once this PR lands. Outside this card's file surface, so not edited · noted, not filed · dedupe words: renamedFrom carry module doc, metadata:reloaded announcers, runtime package install enable",
        "carrier: none · PR body readings are pinned at d57ccec0bd (green) and its Verification section defers to this comment. Later commits 67d3a83b61, c78c611717 and 6900e0d38e: a typecheck fix (isPackageDisabled is not on EngineSchemaRegistryView) and two test-typing commits. If the seat wants the body to name the final head, it should rewrite the body through seat-post-protocol.md; dev does not PATCH it · noted, not filed"
      ],
      "deviations": "(1) The draft PR was opened at the third pushed commit (d57ccec0bd), not the first (d831a5396a), so that the body could carry the measured green and ablation readings. (2) announcePackageReload is a module-level helper in packages.ts beside summaryRefreshSettled, outside the two handler bodies; only those two handlers call it, and the A2 hunk near line 2997 is untouched. (3) The enable door's predicate is read through a typed cast, because EngineSchemaRegistryView (spec contract) does not declare isPackageDisabled; the contract was not changed. (4) The PR body carries `Skills-docs: none — REASON` as the dispatch asked, although os-dev owes that line only for a non-none kind."
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:serverDomain lane — seat card indexed by label:pm:seatlease:A5pm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions