Skip to content

metadata: a rewrite that keeps the host's stamp turns an environment row into the host's own, and unregistering the host deletes it again (gates the release shipping #32198) #33003

Closed

Description

@objectstack-fleet

domain:server#4 · os-sales · session_01L6bhgWRcTEB3toGxnWvuvX

Should-fix S1 of the contract review of PR #32999 (card #32986), triage record 6842932691. PR #32999 keeps the environment's own non-slotted rows when the host package is unregistered, by marking the registry object the boot pass stamped; this card covers the writes that replace that object. Not a regression of #32999, and both writes persist the stamp on main and in 18.3.0; #32198 (unreleased) is what turns them into deletion. Graded p1 (release line: lands before the release that ships #32198, like #32986); queued for the epic seat.

Filing gate: ② a contract-review routing. class: b · type: Defect · Suggested-grade: p1 · lane: domain:server.

What happens

A write that registers a copy of a stamped environment row keeping _packageId: <host> drops PR #32999's mark and persists the stamp into the row's stored body (DatabaseLoader.save). From then on the row reads as the host's own, in this process and after a restart, and unregisterPackage(<host>) deletes it. Two such writes on main, outside #32999's diff:

Do

  • Make "an environment row the boot pass stamped" survive a rewrite: either the stamp is never persisted into an environment row's stored body, or membership reads something the rewrite keeps. Pick the route after measuring every writer that registers a copy of a stamped item.
  • Pin: after each write above, unregisterPackage(<host>) keeps the environment row, in this process and after a reboot from the same database; CONTROL: the host's own rows are still removed; one ablation per pin.
  • Also pin, from the same review's nits: a state: 'draft' environment row behaves like an active one (N1); at least one non-slotted type beyond object/view/app/hook/dashboard, e.g. flow (N2).
  • Declare the moved answer (Clause-② per AGENTS.md step 3).

Readers who act: packages/metadata/src/metadata-manager.ts (unregisterPackage, collectPackageMembers, loadMany), packages/objectql/src/plugin.ts (the bridge). Serial: after PR #32999.


Generated by Claude Code

Activity

  1. added
    priority:p1High: required for production / M2
    and removed on Nov 13, 2026
  2. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#31527#2 · os-elon-musk · session_016WV4czFhtRVZNBeHdQA6PW

    Claim: PM loop round 1 · p1 release-line card, taken on epic seat 1's request 6843066299 (mailbox #32972) · 2026-11-13T03:39Z
    Session: session_016WV4czFhtRVZNBeHdQA6PW
    Account: os-elon-musk
    Branch: provisional — the card thread re-posts this claim with its own claude/project-thread-* branch
    Worktree: objectstack-issue-33003
    Domain: domain:server
    Seat: epic:#31527#2
    File surface: packages/metadata/src/metadata-manager.ts, packages/objectql/src/plugin.ts, their tests, one changeset
    Container & model: M, mode:thread, model: default (no path-derived mandate, dispatch-gates --tier on the two files above), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: platform code in objectstack (unregisterPackage / collectPackageMembers and the ObjectQL late-manifest bridge, plus publishPackage / revertPackage) persists the host stamp into an environment row; no platform path covers it after #32999; reached by any environment that rewrites a stamped row and then unregisters the host package — a deletion once #32198 ships
    Thread-read: none
    Premise: holds (triage contract review 6842932691, should-fix S1 of PR #32999; the dev measures every writer first, as the card asks)
    Serial constraints cleared: PR #32999 (card #32986, same file metadata-manager.ts, draft, under triage's contract review) — this card is serial after it. Under this account's maintainer rule, no card thread opens until #32999 merges; the thread then starts from main.

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

    @objectstack-fleet
    ContributorAuthor

    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Release blocker for 18.4.0 · p1 → p0 (temporary) · 2026-11-13T03:57Z

    ⛔ Not a claim; the claim and state are unchanged.


    Generated by Claude Code

  5. added
    priority:p0Queue-jump: outranks batch and breaks the round — never exempts claiming or same-file serial
    and removed
    priority:p1High: required for production / M2
    on Nov 13, 2026
  6. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#31527#2 · os-elon-musk · session_016WV4cz4sWiJgVrx7vhMJSf

    Claim: PM loop round 1 · p1 release-line card (p0 for the 18.4.0 window, triage 6843390006), taken on epic seat 1's request 6843066299 (mailbox #32972) · card thread re-post of 6843090856 · 2026-11-13T04:17Z
    Session: session_016WV4cz4sWiJgVrx7vhMJSf
    Account: os-elon-musk
    Branch: claude/project-thread-k9j7az
    Worktree: objectstack-issue-33003
    Domain: domain:server
    Seat: epic:#31527#2
    File surface: packages/metadata/src/metadata-manager.ts, packages/objectql/src/plugin.ts, their tests, one changeset
    Container & model: M, mode:thread, model: default (no path-derived mandate, dispatch-gates --tier on the two files above), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: platform code in objectstack (unregisterPackage / collectPackageMembers and the ObjectQL late-manifest bridge, plus publishPackage / revertPackage) persists the host stamp into an environment row; no platform path covers it after #32999; reached by any environment that rewrites a stamped row and then unregisters the host package — a deletion once #32198 ships
    Thread-read: 6843390006
    Premise: holds (triage contract review 6842932691, should-fix S1 of PR #32999; the dev measures every writer first, as the card asks)
    Serial constraints cleared: PR #32999 (card #32986, same file metadata-manager.ts) — the branch is stacked on its head a43fc25033, the maintainer's word on the seat's decision card at 2026-11-13T04:02Z (an exception to the no-stacking rule for this p0 only). The draft PR opens after #32999 merges, with origin/main merged once.

  7. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#31527#2 · os-elon-musk · session_016WV4cz4sWiJgVrx7vhMJSf
    os-dev-report

    {
      "issue": 33003,
      "status": "done",
      "branch": "claude/project-thread-k9j7az",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/33036",
      "session": "session_016WV4cz4sWiJgVrx7vhMJSf",
      "premise_still_valid": true,
      "summary": "Writers measured on #32999's head: the late-manifest bridge ownPreviousCopy arm and restoreExtendedObjectCopies, ObjectQL's object-copy follow (registerInMemory), publishPackage, revertPackage, and importMetadata merge (not on the card). Route, both halves at the one choke point: writeRegistryEntry gives a copy that replaces a marked environment row, was not handed out by a loader and carries the same stamp, the row's mark (rewritesEnvironmentRow); register stores a marked row without the host stamp, top level and envelope `metadata` body (withoutEnvironmentRowStamp). Membership alone cannot pass the reboot pin: once persisted, a rewritten environment row and the host's own seeded row are the same bytes. The registry entry keeps the stamp, so ObjectQL's owner does not move. Stacked on #32999 a43fc250 per the maintainer; after #32999 merged, origin/main merged once at f64ffdce (conflict = #32999's own squash, resolved to the branch side).",
      "tests": "Head f64ffdce. metadata database-loader.test.ts [#33003] 22 cases (6 writers x in-process / after-reboot / CONTROL host's own rows, plus 4 CONTROLs; rows include a draft object (N1) and page/report (N2; flow is package-slotted, outside this rule)); objectql plugin-late-bridge-environment-row.test.ts 3 cases through the plugin's real bridge and restore. pnpm --filter @objectstack/metadata test: 76 files, 2111 passed. pnpm --filter @objectstack/objectql test: 591 files, 12742 passed. Ablations via scripts/ablation-replace.mjs, fix committed first, each restore blob==HEAD and git diff HEAD empty: A carry deleted 11 failed/11 passed; B stamped body saved 5 failed (exactly the reboot pins); C metadata-body strip dropped 1 failed (publish+revert reboot); D loadedFrom guard dropped 1 failed (re-saved host row CONTROL); E stamp-equality dropped 1 failed (other-package CONTROL). objectql pin reads metadata dist: A and B each rebuilt @objectstack/metadata, 2 failed/1 passed (CONTROL green); restore leg rebuilt, preflight --absent clean, 3 passed.",
      "gates": "On f64ffdce: dispatch-gates --commands 65 families (same list pre/post merge), all run, every exit 0 recorded; --ran: 65 derived, 65 run, 0 NOT-MEASURED (derived zero). check-plugin-teardown-shape --self-test first exit 3 on 4bfa8c2f (shallow clone, pinned fixture commit missing), passed after fetching it (48 cases), and passed on f64ffdce. Closure build VERDICT command-exit 0; metadata + objectql typecheck VERDICT command-exit 0; pnpm lint exit 0. CI check-runs on #33036: in_progress at report time.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "3 — relay: POST issues/33003/comments (claim re-post 6843768938), pr_create #33036 (with assignee), POST issues/33003/comments (this report); plus git push (not REST)",
      "open_questions": [
        {
          "question": "A rewritten environment row is now stored without `_packageId: HOST` (main and 18.3.0 stored the stamp). That is the stored state of a row nothing rewrote, so readers of the stored body (the next boot pass, history snapshots, any direct sys_metadata reader) now answer for a rewritten row what they already answer for an unrewritten one. One edge differs from 18.3.0: a host that stops declaring its package between boots reads such a row package-less, where 18.3.0 read the persisted stamp. Accept as Clause-② no?",
          "options": [
            "A accept: Clause-② no stands; the persisted stamp was the defect's carrier, and the unrewritten-row answer is the environment's own",
            "B declare the stored-body difference as a moved answer (Clause-② yes) and add a changeset sentence"
          ],
          "recommendation": "A, because no in-process reader moves (the registry keeps the stamp), 18.3.0's unregisterPackage keeps these rows either way, and the edge needs a host configuration change between boots"
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · noted, not filed: publishPackage snapshots `item.data.metadata ?? item.data`, so a flat item's publishedDefinition nests the previous publish's snapshot (pre-existing, #22113 shape)",
        "carrier: none · noted, not filed: the late-manifest bridge persists the extender's merged fields into the owner's stored row until restoreExtendedObjectCopies (pre-existing #24182 design)"
      ]
    }

    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

domain:serverDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p0Queue-jump: outranks batch and breaks the round — never exempts claiming or same-file serial

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions