Skip to content

metadata-protocol: uninstalling a package that shares an object with another package now leaves a half-uninstalled package (sys_packages row gone, its row of the shared object stranded) after PR #23464's per-item 409 #23473

Closed

Description

@objectstack-fleet

Filing gate ①, class (a): a reproducible defect with a named producer.

  • reach: the uninstall door (deletePackage, served at DELETE /api/v1/packages/:id).
  • Measured in process on the real stack: real ObjectQL and protocol, better-sqlite3 tables.
  • Read through to the HTTP answer from source (400 PACKAGE_DELETE_PARTIAL), not driven over HTTP.

This card carries the uninstall half of #23415's family. #23415 (PR #23464) keeps the metadata delete door's 409 refusal, which stops the data loss on both doors.

Filed by domain:spec seat 4 (#18917) · sunhaolin · session session_0121ooBYRmS8ziFXm9ai5YHm. Sources: #23415's dev report (os-dev-report comment on #23415, open_questions[0]) and PR #23464's contract review (6167575307, ③, which escalated it to this seat). ⛔ Not a claim. Grade and lane are triage's.

What happens

deletePackage deletes each of the package's sys_metadata rows with packageId set and, unless keepData: true, with dropStorage: true. Take a package P whose object another package Q also holds.

What done looks like (the shape is the owner's call, possibly a decision)

Two shapes are in sight. They differ on a destructive default, so the claimant may need a ruling:

Either way: a real-stack pin of the two-package uninstall, and the unchanged single-package uninstall as the control.

Dedupe

MCP search_issues on this repo, closed included: deletePackage uninstall shared object another package row stranded sys_packages deleted partial uninstall dropStorage keepData → 11 hits.

None is this.

Dedupe words: deletePackage shared object partial uninstall; uninstall stranded row sys_packages gone; keepData shared table uninstall refusal.

Activity

  1. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: session_0121ooBYRmS8ziFXm9ai5YHm · domain:spec seat 4 (#18917) · sunhaolin · 2026-10-15T02:56Z

    Hand-off note for the seat that lands it. Guard: the next domain:spec seat.

    Decision: confirm the correction to a pending release note

    The problem in one line. The next release note would tell upgraders that an uninstall blocked by a shared object "leaves the object's row and table in place" and reports it in failed[]. After PR #23504 that is false, because the whole uninstall is refused before anything is removed. Only the maintainer's written word on the PR can correct someone else's pending note.

    Governing text: ruling D on #18375 (5729188290, 「同意」 2026-09-18), and route 0 of the Require a changeset step in .github/workflows/pr-automation.yml. A PR that edits another change's pending changeset takes no skip-changeset: "Write the confirmation on the PR — name the note and what changed under it, and get it confirmed there".
    Protocol change: none. The question is one sentence of release-note text. The refusal itself is PR #23504's reviewed change (6172644842).
    Premise, with its re-check: the 23415 note is on main and not yet released. Re-check: git cat-file -e origin/main:.changeset/23415-drop-storage-other-rows.md && echo pending.

    option what happens what the customer sees effort
    A. Confirm (recommended) The maintainer writes the confirmation on PR #23504, and a spec seat lands it The note says what the release does: the uninstall is refused whole with 409, and nothing is removed No dev. One seat landing act
    B. Reject the correction PR #23504 drops its edit to the 23415 note and lands without it The note describes a failed[] partial uninstall that the release no longer performs One text-only dev round, like PR #23504's own patch round
    C. Hold PR #23504 Nothing lands The release ships main's current behaviour: the package record is removed while its row of the shared object stays, listed in failed[]. That is the half-uninstall this card records None

    维护者速读

    os-decision-facets

  2. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Decision-box entry: passes · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-15T03:01Z

    Entry check on the release 6183361784. These are all present:

    It passes.

    The ask is a single written word on PR #23504: confirm the correction to the pending note .changeset/23415-drop-storage-other-rows.md. Under the fix, an uninstall blocked by a shared object is refused whole (409) before anything is removed. The pending note says it "leaves the object's row and table in place".

    The grade stays p1 + target:v18. The hand-off note names the next domain:spec seat for the landing steps.

  3. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: maintainer 「确认」 · letter A · 2026-10-15T04:15Z · said to domain:spec seat 4's session session_0121ooBYRmS8ziFXm9ai5YHm (sunhaolin) in its chat, in answer to the seat's explanation of PR #23504. Carried by that session with provenance under ruling D on #18375; not a director batch.

  4. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop, temporary re-seat · 2026-10-15T04:30Z · landing only: PR #23504, already reviewed and confirmed
    Session: session_0121ooBYRmS8ziFXm9ai5YHm
    Account: sunhaolin (the seat's linked user as GET /user answers it; this card's assignee)
    Branch: claude/issue-23473-uninstall-shared-object-refusal (head 7d36e8d205, unchanged since the seat record)
    Worktree: none. No dev is dispatched: the work is done.
    Domain: domain:spec
    Seat: domain:spec#4 (seat post #18917; re-seat marker 6184406254, on the maintainer's word 「临时回座把 #23504 落地」)
    File surface: none. This claim lands the reviewed head as it is. The merge queue builds the PR on current main and runs the full PR battery there. The seat reads deletePackage's pre-flight on that merged tree before arming. If that reading finds a break, the seat stops and the card goes back with the reading.
    Container & model: n/a. No dev and no reviewer is needed: the narrowing's CONTRACT_REVIEW_TIER review PASSed on this exact head (6172644842), and a base merge would move the head off that record.
    Clause-②: no
    Responsibility: unchanged from the first claim 6168221878.
    Thread-read: 6184273013
    Ruling-ref: 6184273013 (the maintainer's 「确认」, carried; on PR #23504 6184266311) under ruling D on #18375; lane decision 6168058499 (shape B).
    Serial constraints cleared: I read every open PR's file list in this act. Only PR #23469 (another lane, draft, marchtian; already named in the first claim 6168221878) touches packages/metadata-protocol/src/protocol.ts. Inside deletePackage it changes the step-2 row read (engine.find → findEnvironmentRows) and the per-item loop after step 4. Neither is the pre-flight that PR #23504 adds between steps 3 and 4, and git merge-tree of main + PR #23504 + PR #23469 is clean. PR #23504 lands first; PR #23469 merges main after it. The landing reading also covers the 9 main commits to that file since this PR's merge base.
    Resume-from: none (the newest Release:, 6183361784, carries none).

  5. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim amended · domain:spec seat 4 · session_0121ooBYRmS8ziFXm9ai5YHm · claim 6184449232 · 2026-10-15T05:05Z

    What happened. PR #23504 left the merge queue on a CI failure.

    • Run 38682506920 on the queue commit 5e97584201, which is main 8d05456cbe plus this PR.
    • Test Core (6/6) failed in packages/runtime (pnpm run test exited 1).
    • On 8d05456cbe alone the same shard is green, so the failure comes from this PR meeting main.
    • The job log cannot be read from a seat container (ci-failure.mjs: annotations only), so the failing test is not named yet.

    The landing claim becomes a dev round. Changes to 6184449232:

    • Worktree: objectstack-issue-23473.
    • File surface: deletePackage steps 1–4 in packages/metadata-protocol/src/protocol.ts, this PR's pin (packages/runtime/src/package-uninstall-shared-object.integration.test.ts), the two changesets, and a merge of main into the branch (merge commit, no rebase, no force). A test that main added is changed only if it asserts behaviour this PR deliberately replaces, and the report must name it.
    • Container & model: M, mode:subagent, default tier.

    Prime suspect. It is a reading, not yet a measurement. package-uninstall-store-refusal.integration.test.ts changed on main with PR #23522 (#23505). Its CONTROL case uninstalls the extending package through the same door. The new pre-flight may read the extending package's row of the extended object as a second holder, and refuse.

    Reviews owed. The merge moves the head, so the CONTRACT_REVIEW_TIER review and the seat record are re-done on the new head before the queue.

  6. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23473,
    "round": "merge round after merge-queue ejection (run 38682506920); claim 6184449232 amended by 6184860304",
    "status": "done",
    "branch": "claude/issue-23473-uninstall-shared-object-refusal",
    "pr": "#23504",
    "head": "addcca0cf5fc63ba01412d211c8c93dc8dbf8941",
    "merge_commit": "192d2051daaf74b40f9f5727449000f60c99646c (git merge origin/main at 8d05456; no conflict, protocol.ts auto-merged; no rebase, no amend, no force)",
    "session": "session_0121ooBYRmS8ziFXm9ai5YHm (subagent: the dispatching PM session)",
    "premise_still_valid": true,
    "summary": "The queue failure was the PR's own pin meeting main's #23510 (222293f, ADR-0029 D9.9), not the pre-flight: on the merge commit 192d205 the three P-and-Q cases of package-uninstall-shared-object.integration.test.ts ('without keepData: refused 409 ...', 'the way out, keepData: ...', 'the way out, P's own row first: ...') failed in setup at h.publish(Q, SHARED) with "Error: Cannot layer object 'probe_ticket': the overlay is bound to package 'com.probe.q', but the object is owned by package 'com.probe.p'. An object has exactly one registry entry ..." (OBJECT_OVERLAY_PACKAGE_MISMATCH / 422 at the save door). The prime suspect is falsified: package-uninstall-store-refusal.integration.test.ts, CONTROL included, passes on the merged tree. Premise measured: the shared state still arises, through today's doors (a draft saved into Q before P's row exists and promoted after it, by publishMetaItem or POST /packages/Q/publish-drafts: rows [P, Q], registry P; a package-less save first, then P and Q: rows [P, Q, package-less]) and as rows stored before D9.9, which boot leaves at rest; on each door-reached state the uninstall of P without keepData answered 409 RESOURCE_CONFLICT and removed nothing. Fix, inside the claim's surface: the pin's twoPackageObject saves P's row through the door and seeds Q's row straight into the store as a row stored before ADR-0029 D9.9 (the save's shape, checksum by hashSpec), as #23510 re-seeded its two sibling fixtures; every case assertion, the package-less case and the CONTROL are unchanged. protocol.ts and both changesets are byte-identical to the reviewed head's delta (the 23415 TO sentence untouched). I seeded rather than use the draft-promotion door because that door is a D9.9 gap and a fixture built on it would break again when the gap closes; the seat may prefer the door path.",
    "fix": "packages/runtime/src/package-uninstall-shared-object.integration.test.ts only (commit addcca0): new seedStoredRow(name, packageId) helper; seedUnboundRow now calls it (same id, label and body as before); twoPackageObject seeds Q's row instead of publish(Q). No protocol.ts change, no new error code, no route change, no Clause-② change.",
    "producers_measured": [
    "save door, P then Q: Q refused 422 OBJECT_OVERLAY_PACKAGE_MISMATCH; rows [P]",
    "save door, P then a save naming no package: addressed to P's row; rows [P]",
    "save door, a save naming no package first, then P, then Q: all succeed, registry owner the sys_metadata sentinel; rows [P, Q, package-less]; uninstall P without keepData 409, nothing removed",
    "Q draft saved before P's row, P publishes, Q promotes via publishMetaItem (package Q): success; rows [P, Q], registry P; uninstall P 409, nothing removed",
    "same, promoted via POST /api/v1/packages/com.probe.q/publish-drafts at HttpDispatcher.handlePackages: 200, outcome published, failed []; rows [P, Q], registry serves P",
    "same, via publishPackageDrafts in process: outcome published; rows [P, Q]",
    "duplicatePackage P to Q with targetNamespace qq: copy renamed qq_probe_ticket; rows [P] (the kept-name case is #23510's reading: failed with the D9.9 text; not re-measured here)",
    "installPackage writes no object sys_metadata row (code reading); importUnmanagedPackage refuses a name an environment row holds before writing (409, code reading); loadMetaFromDb counts a mismatched stored row in errors and leaves it stored (code reading)"
    ],
    "tests": "All at addcca0 unless named, --maxWorkers=2, each under scripts/pm/os-verify-lock.sh, verdict from its VERDICT command-exit line. RED BEFORE at 192d205: pin + two sibling uninstall integration files: 'Tests 3 failed | 13 passed (16)', VERDICT command-exit 1 (the three P-and-Q cases, setup error quoted in summary). AFTER: pin 'Tests 5 passed (5)' exit 0. Runtime uninstall sweep (every src/package-uninstall-.integration.test.ts + every src/domains/packages-.test.ts): 'Test Files 30 passed (30) / Tests 542 passed (542)' exit 0. Runtime local project whole: one-shot run hit the ~10 min foreground cap (exit 124, no verdict, not a measurement), then 4 vitest shards: 96/96/96/96 files passed, tests 1517 + 1234 (4 skipped) + 1694 (15 skipped) + 1332, all exit 0. Runtime typecheck (tsc --noEmit + check:test-typecheck) exit 0, 'OK — ... 27 file(s) / 190 error(s) / 68 pinned signature(s) held'. Metadata-protocol whole suite (3 shards): 80 + 78 (2 skipped) + 78 (1 skipped) files passed; tests 1483 + 25547 (12 skipped) + 1391 (7 skipped), all exit 0; typecheck exit 0. CLI (for the Test Core 2/6 reading): unit tier 2 shards 145 + 145 files, 2416 + 1908 tests, exit 0; integration tier 131 files in 9 slices, all exit 0 (one slice first killed by my own 290 s timeout, exit 124, re-run green); CI's exact slice OS_TEST_SHARD=1/3 both tiers: 'Test Files 141 passed (141) / Tests 1956 passed | 1 skipped', exit 0. ABLATION at addcca0 via scripts/ablation-replace.mjs WRAP mode: anchor 'if (others.length === 0 && !at.unbound) continue;' 1 -> 0, blob 04eee5b790 -> e70c5d7193, replacement adds a marker condition so no row refuses; metadata-protocol rebuilt; ablation-dist-preflight: marker in dist/index.js and dist/index.cjs; predicted 2 red / 3 green, observed 'Tests 2 failed | 3 passed (5)': cases 1 and 2 answered 400 PACKAGE_DELETE_PARTIAL, registryRemoved true, the object in failed[] with the per-item RESOURCE_CONFLICT text (so the pre-flight refuses the same rows the per-item delete refuses). Restore: blob == HEAD 04eee5b7906ebe40733101d3f8815a5b5ececa30, git diff HEAD empty, whole-tree git status --porcelain empty, rebuilt, --absent: marker in none of 24 built files, pin 5/5 green. A first mutation spelling was refused by the tool (replacement contained the anchor, count could not drop) and restored at once: a no-op, nothing measured. The red-before leg of 'revert the fix' is the merge-commit reading above, since the fix is fixture-only.",
    "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at addcca0: 65 commands (stderr: tree of objectstack-ai/objectstack at addcca0; 4 paths vs merge base 8d05456). Each run with its exit captured before any pipe: 63 exit 0; 'node scripts/check-empty-changeset.mjs --base origin/main' exit 1 on .changeset/23415-drop-storage-other-rows.md, the maintainer-confirmed deliberate correction (6184266311), red by design; 'pnpm check:dual-build-cjs-loads' first exit 3 (PREREQUISITE NOT MET, packages without dist/), re-run exit 0 ('110 published require entry point(s) across 68 package(s) load'). --ran: 'Run reconciliation — 65 derived, 65 run, 0 NOT-MEASURED, 0 UNRUN', exit 0. CI check-runs on addcca0: 31 success, 6 skipped, 3 failure. Green: Build Core, TypeScript Type Check (+ four Type Check lanes), Lint & Repo Gates (+ its lint lanes), Governed Surface Queue Guard, Dogfood Regression Gate, Test Core (1/6), (3/6), (4/6), (5/6), (6/6) (6/6 is runtime + metadata-protocol, the queue's failing shard). Failure: Check Changeset (same 23415 note, red on 7d36e8d too, expected); Test Core (2/6) (CLI slice 1/3, run 38686154595) and the Test Core rollup. Test Core (2/6) NOT REPRODUCED: the job log is unreadable from this container (gh run view --log-failed: run in progress then; the log download host productionresultssa10.blob.core.windows.net is refused by the egress proxy; ci-failure.mjs: annotations only, 'command (.../packages/cli) pnpm run test exited (1)'), so the failing test is not named. Evidence it is not this PR: CI's exact slice passes locally (above); the whole CLI suite passes locally; the same shard was green on 7d36e8d; the queue run on 5e97584 had Test Core (2/6) success, and 5e97584 differs from addcca0 only in the runtime pin file, which no CLI test reads (git grep: no hit); the locally computed PR partition puts '@objectstack/cli 1/3' on shard 2/6. Nothing was changed for it. Rerunning that failed job is a write outside my budget: left to the seat.",
    "mergeable_state": "blocked (read after the push: draft=false, mergeable=true, head addcca0)",
    "pr_body": "Not PATCHed. The current body is stale (its first acceptance note says the 23415 note is not edited; it is, with the maintainer's confirmation) and predates this round. Replacement body: /tmp/claude-0/-home-user/a2360ed0-e03c-558a-9d23-40c33afc0152/scratchpad/issue-23473/pr-body-replacement.md",
    "mcp_calls": "0",
    "api_writes": "1 — POST /repos//issues/23473/comments (this report, via scripts/pm/post-stamped.mjs). Plus two git pushes (not REST): 192d205, addcca0. No label write: the PR's labels were not in this dispatch's scope.",
    "deviations": [
    "Ablation target: the dispatch asked to revert the fix and see red. The fix is fixture-only, so that red is the merge-commit reproduction; the one ablation instead disabled the pre-flight to prove the re-seeded fixture still bites (os-dev: ablate only tested behaviour).",
    "origin/main moved to be48c5e after the merge; not merged again (AGENTS.md §10: merge only on conflict, main-caused red or queue removal).",
    "The re-review owed on the new head (claim amendment 6184860304) is the seat's; nothing was readied, queued or labelled."
    ],
    "open_questions": [
    {
    "question": "Fixture shape for the P-and-Q cases: seeded legacy row (as landed) or the door path that still reaches the state today (Q's draft saved before P's row, promoted after)?",
    "options": [
    "A keep the seeded row: robust to the D9.9 gap being closed, same as #23510's two sibling fixtures",
    "B build Q's row through draft-then-promote: a real door today, but the fixture breaks again when D9.9 closes that gap"
    ],
    "recommendation": "A, because the pin's subject is the uninstall, not how the row got in, and the door-reach is recorded in the PR body as a measurement"
    }
    ],
    "out_of_scope_findings": [
    "class: b · reach: public door — POST /api/v1/packages/com.probe.q/publish-drafts at HttpDispatcher.handlePackages answered 200 (outcome published, failed []) and stored an active row bound to com.probe.q of an object a runtime-authored row of com.probe.p owns; registry still serves P · evidence: draft saved into Q (saveMetaItem mode draft) before P's row existed, then P saved, then Q promoted; publishMetaItem with package Q does the same; the save door refuses that same row 422 OBJECT_OVERLAY_PACKAGE_MISMATCH · Seam: spec:ADR-0029 D9.9 overlayPackageMismatchError → runtime:promoteDraftForPublish / publishPackageDrafts (packages/metadata-protocol/src/protocol.ts), registry write-through then refused in applyObjectRegistryMutation · same family as the D9.9 close-out named in #23510's acceptance notes: fold into it, not a single-point card · dedupe words: D9.9 draft promote second package; publish-drafts OBJECT_OVERLAY_PACKAGE_MISMATCH; runtime-authored owner draft; promoteDraftForPublish classifyObjectContribution",
    "carrier: #23510's acceptance notes (D9.9 family close-out, the seat) · the package-less-owner case re-measured on 192d205: a save naming no package, then saves into P and Q, all succeed, rows [P, Q, package-less], registry owner sys_metadata · noted, not filed"
    ]
    }

  7. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23504 comment 6187493234 · domain:spec seat 4 (temporary re-seat) · session_0121ooBYRmS8ziFXm9ai5YHm · 2026-10-15T08:06Z

    This round was the queue failure. The PR's own fixture met main's ADR-0029 D9.9 refusal. The pre-flight did not cause it.

    The seat arms the PR now.

  8. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23473,
    "round": "second merge round after merge-queue ejection (queue run 38703520759, queue commit 75e7900); claim 6184449232 amended by 6184860304",
    "addendum_to": "6187145964",
    "status": "done",
    "branch": "claude/issue-23473-uninstall-shared-object-refusal",
    "pr": "#23504",
    "head": "4f639e56b06075f522098437d04b08dc06075c11",
    "merge_commit": "ce7a65df2c (git merge origin/main at 23e689d; no conflict; protocol.ts auto-merged; this PR's delta to protocol.ts byte-identical before and after the merge; no rebase, no amend, no force)",
    "session": "session_0121ooBYRmS8ziFXm9ai5YHm (subagent: the dispatching PM session)",
    "premise_still_valid": true,
    "summary": "Reproduced on merge commit ce7a65d: 4 of the pin's 5 cases failed in setup. These are every case that seeds a stored row: 'without keepData: refused 409 ...', 'a package-less row of the object counts as another holder', 'the way out, keepData: ...' and 'the way out, P's own row first: ...'. The error was "Error: Unknown field 'organization_id' on object 'sys_metadata'" at seedStoredRow (package-uninstall-shared-object.integration.test.ts:156). The CONTROL passed. Cause: #23469 (dd29bbe, ADR-0131 D6/D7) dropped the organization column from the sys_metadata family, and with it organization_id: null from the sibling pin's seed. Fix in commit 4f639e5: the pin's seed follows main's row shape (meta-delete-drop-storage-other-rows.test.ts on main) and no longer writes the column. Nothing else changed: the pre-flight, protocol.ts and both changesets are as reviewed, and the 23415 TO sentence is untouched. Address-read comparison on the merged tree: the pre-flight and deleteMetaItem both still call the one packagelessAddress. The pre-flight passes (type, name, undefined, 'active'); deleteMetaItem passes (singularTypeForRepo, name, member, targetState). #23469 changed only that function's body: its where clause was { type, name, state, organization_id: null, ...member } via engine.find, and is now { type, name, state, ...member } via findEnvironmentRows, the seam that drops a legacy organization's rows. Both callers therefore moved together. deletePackage's step-2 read now goes through the same seam, and its per-item loop lost the legacy-organization branch, so the pre-flight's input rows and the per-item delete's rows are the same set.",
    "fix": "packages/runtime/src/package-uninstall-shared-object.integration.test.ts only (commit 4f639e5): organization_id: null removed from seedStoredRow's insert. No protocol.ts change, no new error code, no route change, no Clause-② change.",
    "tests": "All at 4f639e5 unless named, --maxWorkers=2, each under scripts/pm/os-verify-lock.sh, verdict from its VERDICT command-exit line. RED BEFORE at ce7a65d: pin 'Tests 4 failed | 1 passed (5)', VERDICT command-exit 1 (error quoted in summary). AFTER: pin 'Tests 5 passed (5)', exit 0. Runtime uninstall sweep (every src/package-uninstall-.integration.test.ts + every src/domains/packages-.test.ts): 'Test Files 30 passed (30) / Tests 542 passed (542)', exit 0. Runtime local project, whole, in 4 vitest shards (the queue's failing package): 97/97/97/96 files passed; tests 1568 + 1247 (4 skipped) + 1696 (15 skipped) + 1332; all exit 0. Runtime typecheck (tsc --noEmit + check:test-typecheck) exit 0, 'OK — ... 27 file(s) / 190 error(s) / 68 pinned signature(s) held'. Metadata-protocol whole suite, 3 shards: 80 + 78 (2 skipped) + 78 (1 skipped) files passed; tests 1330 + 17832 (12 skipped) + 1388 (7 skipped); all exit 0. Metadata-protocol typecheck exit 0. ABLATION at 4f639e5, via scripts/ablation-replace.mjs WRAP mode: anchor 'if (others.length === 0 && !at.unbound) continue;' 1 -> 0, blob 498517e78a -> 4bee71e85b. A marker condition was added so no row refuses. Metadata-protocol was rebuilt; ablation-dist-preflight found the marker in dist/index.js and dist/index.cjs. Predicted 2 red / 3 green; observed 'Tests 2 failed | 3 passed (5)'. Cases 1 and 2 answered 400 PACKAGE_DELETE_PARTIAL, with the object in failed[] carrying the per-item RESOURCE_CONFLICT text. Restore: HEAD blob = disk blob = 498517e78a682bcb5a82432490f55bd39c91661c, git diff HEAD empty, whole-tree git status --porcelain empty; rebuilt; --absent found the marker in none of 24 built files; pin 5/5 green.",
    "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 4f639e5: 65 commands, the same 65 as at addcca0 (stderr: tree of objectstack-ai/objectstack at 4f639e5; 4 paths vs merge base 23e689d). Each ran with its exit code captured before any pipe; 63 exited 0. 'node scripts/check-empty-changeset.mjs --base origin/main' exited 1 on .changeset/23415-drop-storage-other-rows.md: the maintainer-confirmed deliberate correction (6184266311), red by design. 'pnpm check:dual-build-cjs-loads' first exited 3 (PREREQUISITE NOT MET: 40 packages without dist/ at that moment); after later gates had built them it re-ran with exit 0 ('110 published require entry point(s) across 68 package(s) load'). --ran: 'Run reconciliation — 65 derived, 65 run, 0 NOT-MEASURED, 0 UNRUN', exit 0. CI check-runs on 4f639e5, read once after the push: 33 success, 6 skipped, 1 failure. All five required contexts are green: Build Core, TypeScript Type Check, Lint & Repo Gates, Governed Surface Queue Guard, and Test Core with all six shards. That includes (6/6), the queue's failing shard, and (2/6), the CLI slice that failed once on addcca0. The one failure is Check Changeset (the 23415 note; expected, the same on every head of this PR).",
    "mergeable_state": "unstable (re-read after the push: draft=false, mergeable=true, auto_merge off, head 4f639e5; the first read right after the push answered unknown)",
    "pr_body": "Not PATCHed. Replacement body with a 'Second merge round' section, readings at 4f639e5, the address-read comparison and the new ablation: /tmp/claude-0/-home-user/a2360ed0-e03c-558a-9d23-40c33afc0152/scratchpad/issue-23473/pr-body-replacement.md",
    "mcp_calls": "0",
    "api_writes": "1 — POST /repos//issues/23473/comments (this report, via scripts/pm/post-stamped.mjs over the fleet-write relay). Also two git pushes, which are not REST writes: ce7a65d and 4f639e5.",
    "deviations": [
    "Beyond the dispatch's list, I also ran the whole runtime local project (4 shards), because the queue's failing package was packages/runtime.",
    "The re-review owed on the new head belongs to the seat. Nothing was readied, queued, armed or labelled."
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "unchanged from report 6187145964: the D9.9 draft-promotion gap (class b, public door POST /packages/:id/publish-drafts) and the package-less-owner case, both for the D9.9 family close-out; not re-measured on this head"
    ]
    }

  9. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23504 comment 6189155982 · domain:spec seat 4 (temporary re-seat) · session_0121ooBYRmS8ziFXm9ai5YHm · 2026-10-15T09:43Z

    The second queue ejection came from the PR's own pin meeting main's #23469: its seed still wrote the retired organization_id column. The dev's second round fixed it.

    • main was merged in, and the pin's seed now follows main's row shape; the pre-flight is unchanged.
    • The new head is 4f639e56b0. The CONTRACT_REVIEW_TIER review PASSed on it (6189137865).
    • Every check is green, skipped or red by design.

    #23641, the queue's anchor issue for this file, carries the diagnosis (6187991639). The seat arms the PR now.

  10. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23504 · domain:spec seat 4 (temporary re-seat 6184406254) · session_0121ooBYRmS8ziFXm9ai5YHm · 2026-10-15T10:10Z

    reading result
    PR #23504 merged 2026-10-15T10:09:53Z through the merge queue (armed by this seat), merge commit 7cb33cfefe, on the third enqueue
    origin/main tip 7cb33cfefe. deletePackage's shared-object pre-flight is in packages/metadata-protocol/src/protocol.ts there, and .changeset/23415-drop-storage-other-rows.md carries the confirmed TO sentence ("refused whole, 409 RESOURCE_CONFLICT")
    queue branches no gh-readonly-queue/main/pr-23504-* ref remains
    reviews CONTRACT_REVIEW_TIER PASS on the landed head 4f639e56b0 (6189137865); seat record 6189155982

    State change: Fixes #23473 closes this card as completed, and pm:dispatched is removed in this act.

    The two queue ejections, both the PR's own pin meeting a newer main, never the pre-flight:

    1. main's fix(metadata-protocol)!: a save into a second package of an object a runtime-authored row owns is refused (ADR-0029 D9.9) #23510 (ADR-0029 D9.9) refused the pin's door-saved second-package row. The row is now seeded as one stored before D9.9.
    2. main's feat(metadata-core,metadata-protocol)!: the sys_metadata family declares no organization column; indexes re-keyed (ADR-0131 D6/D7, C7b S2) #23469 retired organization_id from sys_metadata, and the pin's seed still wrote it. The seed now follows main's row shape.

    Diagnosis for the queue's anchor issue #23641: 6187991639. With the pin on main, that anchor has nothing left to count.

    Carried elsewhere:

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions