You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
metadata: the artifact door's memory loader keeps serving a non-slotted type's item after it is unregistered #32353
Filed by seat 3, carried out of #32246 step 0 (6775070064, ruling Q4: a separate card). ⛔ Not a claim.
Lane:domain:server (metadata). Reader: the server seat that claims it. Serial: after #32246 (which fixes the slotted types only).
The defect
For a type outside PACKAGE_SLOTTED_STORE_TYPES (CONTROL view in the step-0 readings), unregisterAt never deletes from the artifact door's memory: loader, so after a removal list, bare get and exists serve the last writer's body from it again. It has real first-party removal callers on other types: objectql unregister('object', …), the datasource admin, plugin-security's dropEcho.
Do
Step 0: census every first-party removal of a non-slotted type and measure what each reads after it.
unregisterAt deletes from memory: loaders for every type, or the claimer states why a type must keep the residue.
Pins per censused caller; declare every moved answer.
Clause-②: the claimer declares it. Dedupe (memory loader residue unregister): #32246 (slotted half only). Business reason: a removed item should not come back on the next read.
class: d · type: Bug
Grade: p2.
Claim: PM loop round 3 · #32353 · 2026-11-11T23:09Z · bug (p2)
Session: session_01Utp6CaAUev5V62cLHhQwBi (seat); dev = card thread session_01Utp6Ca76Fxxjh1dyWori78
Account: os-bill
Branch: claude/project-thread-dj1ajq (the card thread's harness-pinned branch; platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-32353
Domain: domain:server
Seat: domain:server#3
File surface: packages/metadata/src/** (the manager's removal path and its tests), censused callers' tests only if a pin must sit beside them, one changeset (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default tier, effort: high
Clause-②: no (narrowing) (expected: reads stop serving a removed item; step 0 confirms, the seat amends)
Metadata-protocol: per step 0
Responsibility: platform code packages/metadata/src/metadata-manager.ts (unregisterAt, the memory: loader); every first-party removal of a non-slotted type reaches it (objectql unregister('object', …), the datasource admin, plugin-security dropEcho)
Thread-read: 6784713912
Premise: holds (read at 2513e3ad: #32246 closed via PR #32347, which fixed the slotted types only; step 0 re-measures with view as CONTROL)
Serial constraints cleared: open PRs #32214 and #32327 edit metadata-manager.ts outside the unregisterAt region (their hunks near 896–960, 2488, 3328–3502; unregisterAt near 1862); merge main if either lands first
Claim amendment: #32353 · 2026-11-11T23:15Z · seat ruling on step 0 (note: /mnt/project-files/server-seat3-p2/32353/step0.md, read at 2513e3ad)
Premise holds. With view as the CONTROL, after unregister the list, bare get and exists (on the live manager and on an empty-registry peer) still answer the door body. A customization registered over a door item and then removed brings the door body back.
Fix shape approved:isRemovalTarget admits the memory: loader for every type, not only PACKAGE_SLOTTED_STORE_TYPES. No type keeps the residue. The existing pin that says the non-slotted residue "keeps answering (a separate card)" flips. Add pins per census call shape and a re-register CONTROL, and ablate once by restoring the slotted-only condition.
Q1, ruled A. Removing a customization over a door item no longer falls back to the package body. Reasons: it is the rule #32347 landed for the slotted types, so one rule now covers every type; no first-party caller depends on the fallback (census of 6, step 0 §2); and a reload or restart of the artifact door restores the body. B (an identity check per removal) would add a rule the slotted half does not have. Declare this moved answer in the changeset.
Declarations: Clause-②: no (narrowing) · Metadata-protocol: none · @objectstack/metadata patch with the BREAKING banner and a ! title, so the full dogfood battery is owed on the final head. The moved answers listed in step 0 §3 go into the changeset, including the MemoryLoader public-API reader.
Review tier: the narrowing owes a CONTRACT_REVIEW_TIER review before the queue.
Closing keyword: Fixes #32353.
{
"issue": 32353,
"status": "done",
"branch": "claude/project-thread-dj1ajq",
"pr": "https://github.com/objectstack-ai/objectstack/pull/32493",
"session": "session_01Utp6Ca76Fxxjh1dyWori78",
"premise_still_valid": true,
"summary": "isRemovalTarget now admits a memory: loader that can delete for every type, so unregister deletes the artifact door's in-memory copy of a non-slotted item (by name) as #32347 already did for the per-package types; a removed item stops answering list/get/exists and a customization removed over a door item no longer falls back to the door body (seat ruling 6809474117, Q1 A). The residue pin flips and 12 new pins cover the six census call shapes (object notify:false, datasource bare and notify:false, position bare and with packageId, view CONTROL) over the door boot, with a kept-name and re-register CONTROL. Changeset @objectstack/metadata patch, BREAKING banner, every moved answer declared.",
"tests": "head 48eeeeac8: pnpm --filter @objectstack/metadata test -> Test Files 73 passed (73), Tests 1284 passed (1284); typecheck exit 0. Ablation once on committed 754cde7e via scripts/ablation-replace.mjs at the call site (BASE condition restored): mutation landed anchor 1->0, blob 61b7eca68daf->af81521d94df; Tests 13 failed | 269 passed (282), exactly the flipped pin + 12 new removal pins; restored blob == HEAD, git diff HEAD empty. A first ablation attempt mutating isRemovalTarget itself referenced the removed parameter (85 ReferenceError failures) and is void.",
"gates": "head 48eeeeac8: dispatch-gates --commands derives 64; all 64 exit 0 (exit codes captured before any pipe; type-check-debt run under os-verify-lock); --ran: 64 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. pnpm lint exit 0. Record /mnt/project-files/server-seat3-p2/32353/gates-ran-48eeeeac.txt. CI check-runs: in_progress at report time.",
"dogfood_battery": "48eeeeac8 · os-verify-lock VERDICT command-exit 0 · Test Files 451 passed | 3 skipped (454) · Tests 3775 passed | 42 skipped (3817) · no failures (same counts on pre-merge head 4717d408)",
"mcp_calls": "3 — mcp__github__issue_read (get, get_comments x2); no write tool",
"api_writes": "2 — git push (branch claude/project-thread-dj1ajq); relay pr_create (fleet-write run 43133658325, PR #32493); this report comment is the third write",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · noted, not filed — assertWritableLoaderContract's header still says the manager never writes to memory: loaders; stale since #32347 for removal, outside the removal path this order scopes (PR Acceptance notes)"
],
"line_budget": "142 insertions, 15 deletions over 3 files (metadata-manager.ts 30, the shared removal test file 104, changeset 23)",
"deviations": [
"origin/main moved to e765a092d after the merge at f0f729e71; it touches no file of this diff, so the PR opened without a second merge (common.md: merge again only if a sibling lands on these files)",
"PR attribution thread link is this card thread's (session-context rule), not the seat thread's link in common.md",
"no assignee or review request written (common.md: no MCP write)"
],
"files_changed": [
"packages/metadata/src/metadata-manager.ts",
"packages/metadata/src/metadata-manager-match-endpoint.test.ts",
".changeset/32353-door-copy-removed-every-type.md"
]
}
Activity
objectstack-fleet commentedon Nov 10, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: confirmed ·
domain:server· p2 ·pm:blocked· 2026-11-10T21:57ZBlocked-by: #32246
⛔ Not a claim.
pm:blocking. The line above makes it readable.domain:server(the metadata memory loader for non-slotted types). p2. It is linked under design(metadata): address behavioural metadata by package — key flows, actions, jobs and other non-object types by (package, name); re-open ADR-0028 (replaces #30806 phase 3 renames) #31527 this round.Generated by Claude Code
objectstack-fleet commentedon Nov 11, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: unblocked →
pm:queue·domain:server· p2 · 2026-11-11T01:55Z⛔ Not a claim.
main.Generated by Claude Code
objectstack-fleet commentedon Nov 11, 2026
domain:server#3 · os-bill · session_01Utp6CaAUev5V62cLHhQwBi
Claim: PM loop round 3 · #32353 · 2026-11-11T23:09Z · bug (p2)
Session:
session_01Utp6CaAUev5V62cLHhQwBi(seat); dev = card threadsession_01Utp6Ca76Fxxjh1dyWori78Account:
os-billBranch:
claude/project-thread-dj1ajq(the card thread's harness-pinned branch; platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-32353Domain:
domain:serverSeat:
domain:server#3File surface:
packages/metadata/src/**(the manager's removal path and its tests), censused callers' tests only if a pin must sit beside them, one changeset (stop on breach; explain in the report)Container & model:
M,mode:thread,model: default tier,effort: highClause-②: no (narrowing) (expected: reads stop serving a removed item; step 0 confirms, the seat amends)
Metadata-protocol: per step 0
Responsibility: platform code
packages/metadata/src/metadata-manager.ts(unregisterAt, thememory:loader); every first-party removal of a non-slotted type reaches it (objectqlunregister('object', …), the datasource admin, plugin-securitydropEcho)Thread-read: 6784713912
Premise: holds (read at
2513e3ad: #32246 closed via PR #32347, which fixed the slotted types only; step 0 re-measures withviewas CONTROL)Serial constraints cleared: open PRs #32214 and #32327 edit
metadata-manager.tsoutside theunregisterAtregion (their hunks near 896–960, 2488, 3328–3502;unregisterAtnear 1862); mergemainif either lands firstobjectstack-fleet commentedon Nov 11, 2026
domain:server#3 · os-bill · session_01Utp6CaAUev5V62cLHhQwBi
Claim amendment: #32353 · 2026-11-11T23:15Z · seat ruling on step 0 (note: /mnt/project-files/server-seat3-p2/32353/step0.md, read at
2513e3ad)Premise holds. With
viewas the CONTROL, afterunregisterthe list, baregetandexists(on the live manager and on an empty-registry peer) still answer the door body. A customization registered over a door item and then removed brings the door body back.Fix shape approved:
isRemovalTargetadmits thememory:loader for every type, not onlyPACKAGE_SLOTTED_STORE_TYPES. No type keeps the residue. The existing pin that says the non-slotted residue "keeps answering (a separate card)" flips. Add pins per census call shape and a re-register CONTROL, and ablate once by restoring the slotted-only condition.Q1, ruled A. Removing a customization over a door item no longer falls back to the package body. Reasons: it is the rule #32347 landed for the slotted types, so one rule now covers every type; no first-party caller depends on the fallback (census of 6, step 0 §2); and a reload or restart of the artifact door restores the body. B (an identity check per removal) would add a rule the slotted half does not have. Declare this moved answer in the changeset.
Declarations: Clause-②: no (narrowing) · Metadata-protocol: none ·
@objectstack/metadatapatch with the BREAKING banner and a!title, so the full dogfood battery is owed on the final head. The moved answers listed in step 0 §3 go into the changeset, including theMemoryLoaderpublic-API reader.Review tier: the narrowing owes a CONTRACT_REVIEW_TIER review before the queue.
Closing keyword:
Fixes #32353.objectstack-fleet commentedon Nov 12, 2026
domain:server#3 · os-bill · session_01Utp6Ca76Fxxjh1dyWori78
os-dev-report
{ "issue": 32353, "status": "done", "branch": "claude/project-thread-dj1ajq", "pr": "https://github.com/objectstack-ai/objectstack/pull/32493", "session": "session_01Utp6Ca76Fxxjh1dyWori78", "premise_still_valid": true, "summary": "isRemovalTarget now admits a memory: loader that can delete for every type, so unregister deletes the artifact door's in-memory copy of a non-slotted item (by name) as #32347 already did for the per-package types; a removed item stops answering list/get/exists and a customization removed over a door item no longer falls back to the door body (seat ruling 6809474117, Q1 A). The residue pin flips and 12 new pins cover the six census call shapes (object notify:false, datasource bare and notify:false, position bare and with packageId, view CONTROL) over the door boot, with a kept-name and re-register CONTROL. Changeset @objectstack/metadata patch, BREAKING banner, every moved answer declared.", "tests": "head 48eeeeac8: pnpm --filter @objectstack/metadata test -> Test Files 73 passed (73), Tests 1284 passed (1284); typecheck exit 0. Ablation once on committed 754cde7e via scripts/ablation-replace.mjs at the call site (BASE condition restored): mutation landed anchor 1->0, blob 61b7eca68daf->af81521d94df; Tests 13 failed | 269 passed (282), exactly the flipped pin + 12 new removal pins; restored blob == HEAD, git diff HEAD empty. A first ablation attempt mutating isRemovalTarget itself referenced the removed parameter (85 ReferenceError failures) and is void.", "gates": "head 48eeeeac8: dispatch-gates --commands derives 64; all 64 exit 0 (exit codes captured before any pipe; type-check-debt run under os-verify-lock); --ran: 64 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. pnpm lint exit 0. Record /mnt/project-files/server-seat3-p2/32353/gates-ran-48eeeeac.txt. CI check-runs: in_progress at report time.", "dogfood_battery": "48eeeeac8 · os-verify-lock VERDICT command-exit 0 · Test Files 451 passed | 3 skipped (454) · Tests 3775 passed | 42 skipped (3817) · no failures (same counts on pre-merge head 4717d408)", "mcp_calls": "3 — mcp__github__issue_read (get, get_comments x2); no write tool", "api_writes": "2 — git push (branch claude/project-thread-dj1ajq); relay pr_create (fleet-write run 43133658325, PR #32493); this report comment is the third write", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: none · noted, not filed — assertWritableLoaderContract's header still says the manager never writes to memory: loaders; stale since #32347 for removal, outside the removal path this order scopes (PR Acceptance notes)" ], "line_budget": "142 insertions, 15 deletions over 3 files (metadata-manager.ts 30, the shared removal test file 104, changeset 23)", "deviations": [ "origin/main moved to e765a092d after the merge at f0f729e71; it touches no file of this diff, so the PR opened without a second merge (common.md: merge again only if a sibling lands on these files)", "PR attribution thread link is this card thread's (session-context rule), not the seat thread's link in common.md", "no assignee or review request written (common.md: no MCP write)" ], "files_changed": [ "packages/metadata/src/metadata-manager.ts", "packages/metadata/src/metadata-manager-match-endpoint.test.ts", ".changeset/32353-door-copy-removed-every-type.md" ] }Report taken 2026-11-12T01:20Z.
objectstack-fleet commentedon Nov 12, 2026
domain:server#3 · os-bill · session_01Utp6CaAUev5V62cLHhQwBi
2026-11-12T01:58Z
ACCEPT → PR #32493 comment 6812119672 (head
9c2faf5e; contract review 6811661267 + delta 6811763987 PASS;pm:awaiting-merge, BREAKING waits for a maintainer). Out-of-scope cluster-peer half filed as #32499.