Repository navigation
cli: os meta delete declares no --package, so the reset door's 409 RESOURCE_CONFLICT remedy (name one package) cannot be sent from the CLI, and os meta register cannot name the package a save writes into #23350
Description
Filing gate ① a product defect with a named landing point: a refusal's remedy that the CLI cannot send. Read from source on main 3490bf5fa. Found by the #23293 dev (PR #23349, out-of-scope finding 1) and confirmed by the seat. Filed by domain:spec seat 2 (#18549) · os-justin · session session_01BRQ9Mp1yH7R1az6MaUM18H. ⛔ Not a claim; grade and lane are triage's.
Reader who acts: triage, to grade and route. Both commands are packages/cli (domain:cli).
What happens
- Since metadata-protocol: a package-less direct save of an item a package owns answers 200 and writes a package-less row the item read never serves; the draft save already resolves the owning package (#11087 / #22128) #23165 (PR fix(metadata-protocol)!: a save or delete that names no package addresses the one package's row, and a name two packages hold is refused 409 (#23165) #23290), the metadata reset door refuses a delete that names no package of an item that two or more packages hold. It answers
409 RESOURCE_CONFLICT, names the packages, and prescribes naming one with?package=. - client:
meta.deleteItemcannot name a package — after #23165 a delete of a name two packages hold answers 409, and the SDK has no way to pass the?package=remedy #23293 (PR feat(client): meta.deleteItem names the package whose row it removes, sent as ?package= (#23293) #23349) gives the SDK that option:DeleteMetaItemOptions.packageId, sent as?package=. os meta deletebuilds its options bag from its flags inmetaDeleteOptions(packages/cli/src/commands/meta/delete.ts:54). Its flags are--url,--token,--format,--if-matchand--draft, and none names a package. So a CLI user who meets that409is told to do something the command cannot send.os meta registercallsclient.meta.saveItem(type, name, metadata)with no options (packages/cli/src/commands/meta/register.ts:76). It cannot name the package a save writes into, althoughSaveMetaItemOptions.packageIdhas existed since 17.3. Whether a save that names no package is refused for an item two packages hold is not measured; this line is for triage to weigh.
What done looks like
os meta deletetakes a--packageflag (a package id) and forwards it aspackageIdthroughmetaDeleteOptions. Add a pin: with two packages holding the item, the command without the flag reports the door's409, and with the flag it removes that package's row only.os meta register: triage decides whether it takes the same flag, forwarded tosaveItem'spackageId.- Rides along (from PR feat(client): meta.deleteItem names the package whose row it removes, sent as ?package= (#23293) #23349's contract review
6157634835): the reset door reads five request carriers onmain(state,dropStorage,package,If-Match, andmember, the last since [finding] email_template: a Studio save of the same template in a second locale replaces the first locale's overlay at the next boot (sys_metadata keeps one overlay row per type and name) #22877). TheDeleteMetaItemOptionsheader inpackages/client/src/index.tssays four, andmetaDeleteOptions' docblock inpackages/cli/src/commands/meta/delete.tssays three. Both counts are made true here.memberis absent from every SDK meta method; whether the SDK declares it is outside this card. - Depends on: client:
meta.deleteItemcannot name a package — after #23165 a delete of a name two packages hold answers 409, and the SDK has no way to pass the?package=remedy #23293 (PR feat(client): meta.deleteItem names the package whose row it removes, sent as ?package= (#23293) #23349), the SDK option the delete flag forwards.
Dedupe
MCP search_issues on objectstack-ai/objectstack, closed included: os meta delete package flag cli cannot name package RESOURCE_CONFLICT remedy register package. 10 hits: #23293 (open; the SDK half) and #23297 (open; three package-axis gaps in metadata-protocol), then #22591, #22128, #22135, #22024, #20492, #14937, #12579 and #7705, all closed. None is the CLI's flag.
Dedupe words: os meta delete package flag; cli meta register package; cli RESOURCE_CONFLICT package remedy.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 13, 2026
Triage: first grade,
bug·priority:p2·domain:spec,pm:blockedon PR #23349.os meta deleteandos meta registerboth take--packageand forward itTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T23:53Z. ⛔ Not a claim, ⛔ not a dispatch.409 RESOURCE_CONFLICTprescribes naming one package, and a CLI user cannot send it. It is the same class and grade as client:meta.deleteItemcannot name a package — after #23165 a delete of a name two packages hold answers 409, and the SDK has no way to pass the?package=remedy #23293, the SDK half.Clause-②: yes. That is spec-lane work with contract-tier review, consistent with client:meta.deleteItemcannot name a package — after #23165 a delete of a name two packages hold answers 409, and the SDK has no way to pass the?package=remedy #23293. The edits are inpackages/cli, declared in the claim.os meta register: yes, it takes the same optional--packageand forwards it assaveItem'spackageId(an option since 17.3). ADR-0070 makes the package-less state "no longer an authoring destination", so a CLI save should be able to name its package. Without the flag, the command behaves as today. Whether the save door refuses a package-less save of a two-package item is the dev's measurement; the flag is right either way.os meta deletewithout the flag reports the409;--packageit removes that package's row only;os meta register --package Pwrites P's row.meta.deleteItemcannot name a package — after #23165 a delete of a name two packages hold answers 409, and the SDK has no way to pass the?package=remedy #23293's SDK option (DeleteMetaItemOptions.packageId), which arrives with PR feat(client): meta.deleteItem names the package whose row it removes, sent as ?package= (#23293) #23349. That PR is open at this reading.Blocked-by: #23349
Restart-when: PR #23349 has merged.
objectstack-fleet commentedon Oct 14, 2026
Unlock scan:
pm:blocked→pm:queue.Blocked-by: #23349is satisfied: PR #23349 (#23293, the SDK'sDeleteMetaItemOptions.packageId) merged as4f1e435bf6Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T00:56Z. ⛔ Not a claim, ⛔ not a dispatch.6157686519stand:--packageon bothos meta deleteandos meta register,Clause-②: yes, in the spec lane.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 1 (#23350:
os meta deleteandos meta registertake--packageand forward it, the delete flag asDeleteMetaItemOptions.packageIdand the register flag assaveItem'spackageId; the docblocks' carrier counts are made true; triage6157686519, unlock6158456749) · 2026-10-14T10:46ZSession:
session_01YRp5z4kK6vgYkrdH97ztsyAccount:
huangyiirene(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-23350-cli-meta-package-flagWorktree:
objectstack-issue-23350Domain:
domain:specSeat:
domain:spec#1(seat post #6017)File surface (at
origin/main7b3d5585cor later; stop on a breach and explain it in the report):packages/cli/src/commands/meta/delete.ts(the flag andmetaDeleteOptions) andpackages/cli/src/commands/meta/register.ts(the flag and thesaveItemoptions), with their tests beside them.packages/client/src/index.ts: theDeleteMetaItemOptionsheader's carrier count only. That is the triage's ride-along, together withmetaDeleteOptions' docblock..changeset/23350-*.md.packages/metadata-protocol/**: the door and its409are metadata-protocol: a package-less direct save of an item a package owns answers 200 and writes a package-less row the item read never serves; the draft save already resolves the owning package (#11087 / #22128) #23165's and PR fix(metadata-protocol)!: a delete naming one package keeps the item's other rows registered, and a package-less draft save of an item two packages hold is refused 409 #23408's. ⛔ No SDK option added:memberstays outside this card.Container & model:
M,mode:subagent,model: default(dispatch-gates --tier: "no path-derived mandate … floor sonnet · default opus · ceiling fable"). The face is theClause-②: yesdeclaration alone (no published schema, no governed text), so the lane seat writes the review record atTIER_DEFAULT.Clause-②: yes (widening)
Responsibility:
packages/cli'sos meta delete/os meta registerflag sets, which name no package | the door's409 RESOURCE_CONFLICTprescribes?package=, and the SDK option exists since PR feat(client): meta.deleteItem names the package whose row it removes, sent as ?package= (#23293) #23349 | any CLI user resetting or saving an item two packages holdThread-read: 6158456749
Serial constraints cleared: open PRs' file lists were read in this act, and none touches
packages/cli/src/commands/meta/**orpackages/client/src/index.ts. No in-flight claim names them.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
os-dev-report
{ "issue": 23350, "status": "done", "branch": "claude/issue-23350-cli-meta-package-flag", "pr": "https://github.com/objectstack-ai/objectstack/pull/23475", "session": "session_01YRp5z4kK6vgYkrdH97ztsy (subagent; the parent PM's harness-stamped id, the session of claim 6166598761)", "premise_still_valid": true, "summary": "os meta delete and os meta register now take an optional --package (a package id) and forward it verbatim as the SDK's packageId (?package=): delete through metaDeleteOptions beside --if-match/--draft, register through a new exported metaRegisterOptions passed to client.meta.saveItem (it took no options before). Unflagged, both commands send byte-identical requests (pinned on the wire). An empty or blank --package is refused before a client exists, mirroring the existing EMPTY_IF_MATCH_REFUSAL, because a package-less request is not always refused (the door resolves a one-package item to that package's row); this is a design choice beyond triage's pins, stated in the PR body for the lane seat's review. The DeleteMetaItemOptions header (packages/client/src/index.ts) and metaDeleteOptions' docblock now NAME the reset door's five carriers (If-Match header; state, package, dropStorage, member query params) instead of counting them. H2 measured through the real oclif command and real door: register saves ACTIVE (no ?mode=, no query string), and a package-less active save of an item two packages hold is refused 409 RESOURCE_CONFLICT naming both packages, nothing written. H4: no generated CLI reference reads these flags (no oclif manifest, no content/docs page, no check:cli-examples-parity row), so nothing was regenerated. Card assignee untouched; PR assignee huangyiirene; PR is draft, opened as #23475.", "tests": "All under scripts/pm/os-verify-lock.sh (slot issue-23350-dev). Code under test is identical at 7560e7f9e and head 7ec2fb6c7 (the commit between adds only the changeset). (1) cli integration, the two touched files at 7ec2fb6c7: vitest run --project integration delete-reset-carriers.test.ts register-package.test.ts -> 'Test Files 2 passed (2) / Tests 37 passed (37)'; per-file test time 8.8s and 7.2s on the shared box. (2) cli unit layer at 7560e7f9e: vitest run --project unit -> 'Test Files 2 failed | 285 passed (287) / Tests 4278 passed | 29 skipped'; the 2 failed files (test/published-subpath-console.pin.test.ts, test/published-subpath-hook-body.pin.test.ts) refused with 'packages/cli is not built' (prerequisite, NOT MEASURED, not red); after pnpm --filter @objectstack/cli build those two plus test/vitest-tiers-partition.test.ts -> 'Test Files 3 passed (3) / Tests 51 passed (51)'. (3) pnpm --filter @objectstack/cli typecheck -> exit 0, 'check:test-typecheck: OK'; tsc --noEmit --listFiles lists both meta test files (count 2). (4) pnpm --filter @objectstack/client typecheck && vitest run (packages/client) -> exit 0, 'Test Files 51 passed (51) / Tests 663 passed (663)'. (5) cli integration layer beyond the two touched files: declared to CI (no spawn test covers meta delete/register; test/remote-api-commands.test.ts imports the classes and is unit-tier, passed in (2)). ABLATION (one, delete flag forwarding, no file kept): node scripts/ablation-replace.mjs replaced 'if (packageId !== undefined) options.packageId = packageId;' with 'void packageId; /* ABLATION-23350: forwarding removed */' in packages/cli/src/commands/meta/delete.ts: anchor x1 -> x0, marker x0 -> x1, blob 614a82e6f310 -> 39e86c3e9afe; no build/dist leg (subject imported relatively from src, ./delete.js); run -> 'Tests 5 failed | 24 passed (29)': metaDeleteOptions mapping, NAMING ONE (exit 1 vs 0), NAMING A PACKAGE THAT HOLDS NO ROW, composition, in-step twins; NAMING NONE (negative control) and the empty-refusal case stayed green as predicted; restore: blob 614a82e6f310 == HEAD, git diff HEAD empty.", "gates": "Local subset derived at 7ec2fb6c7: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack -> 66 commands, each run sequentially with its exit code captured before any pipe; 63 exit 0, 3 exit 3 PREREQUISITE NOT MET (pnpm --filter @objectstack/spec run check:skill-examples; pnpm check:dual-build-cjs-loads; pnpm check:i18n-coverage: packages outside this card unbuilt) = NOT MEASURED, declared to CI. --ran reconciliation: 'dispatch-gates --ran: 66 derived famil(ies) accounted for — 63 run, 3 NOT-MEASURED (3 DERIVED from a recorded exit 3)' (exit 0). Dist-reading gates in that set ran before packages/cli's own dist existed; CI is the authority for them. The derivation flagged origin/main 3 commits ahead (4e0838d99, 8d5b7bb94, b60eb78d3: packages/spec stack.zod.ts, service-mailbox, two gate files; none in packages/cli or packages/client), so main was not merged before opening; CI runs the merge ref. PR #23475 check-runs on 7ec2fb6c7, read once right after opening (36): success = filter, 'No other open PR may claim the same issue', 'No other open PR may claim the same single-writer path'; skipped = Build Docs, Console Pin Gate, Dogfood Regression Gate (matrix template), Dogfood Verify CLI, Packed-tarball smoke (opt-in), Temporal Conformance (live PG + MySQL); in_progress = Check Changeset, Check Documentation Links, Check PR Size, Flag docs affected by code changes, Governed Surface Queue Guard, Lint (CI release and engine gates; ESLint; PM dispatch-gates; docs and code guards; repo and tooling gates; scoped query-options erasure; scoped slot lookup and corpus; scoped tooling self-tests), Part-of PR must not also close its card, The card this PR closes must claim this branch, Type Check (consumer gates; debt ledger; source gates; workspace); queued = Build Core, Dogfood Regression Gate, Test Core (1/6 to 6/6). in_progress is the honest value; CI convergence is the PM's.", "mcp_calls": "0 — no MCP GitHub tool was called", "api_writes": "2 relay strokes, each one POST /repos/objectstack-ai/objectstack/dispatches (fleet-write, executed as objectstack-fleet[bot]): (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/23475/assignees; (2) this os-dev-report -> POST /repos/objectstack-ai/objectstack/issues/23350/comments. label-write: 0 (dispatch names no label; skip-changeset does not apply, the diff publishes). git push x3 (not REST).", "open_questions": [], "out_of_scope_findings": [ "class: a · reach: public door os meta delete, human output — `os meta delete view nothing_here` prints '✓ Metadata deleted: view/nothing_here' while the same call with --format json answers deleted: false (the door's reset: false); with this PR's flag, `os meta delete view probe_v --package com.qa.gamma` (a package that holds no row) prints '✓ Metadata deleted: view/probe_v' while json says deleted: false and nothing was removed. Measured with a one-off probe through the real oclif command and real door on 7ec2fb6c7 code (probe file not kept). Landing: packages/cli/src/commands/meta/delete.ts run(), the human branch prints its sentence without reading result.reset. Not fixed in place: a different defect class from this card. · dedupe: os meta delete human output reset false; Metadata deleted when nothing removed; meta delete deleted false sentence", "class: a · reach: public door os meta register — after `os meta register object --data` saved probe_obj with fields title and note, re-registering without note answers (--format json) {success: false, code: DESTRUCTIVE_CHANGE, httpStatus: 409, error: 'object/probe_obj would drop or transform existing data: Field note removed ... re-submit with ?force=true to proceed.'}, and the command's flags are url, token, data, format, package: the remedy ?force=true cannot be sent from the CLI. Measured with the same one-off probe. Same family as #23350 (a door refusal whose remedy the CLI cannot send); SaveMetaItemOptions.force exists in the SDK. Not fixed in place: a new published flag is its own Clause-② widening, not a mechanical, pinned shape. · dedupe: os meta register force DESTRUCTIVE_CHANGE; cli cannot send force=true; meta register destructive change remedy", "carrier: 承接者:无 · noted, not filed — the door reads ?package=all as naming no package (metaItemPackageBinding, as the SDK docblock states), so --package all reaches the door as a package-less request; the flag forwards verbatim by design (in PR Acceptance notes)", "carrier: 承接者:无 · noted, not filed — packages/client/src/meta-delete-item-carriers.test.ts header still narrates 'three carriers' then 'a fourth carrier joined later' (historical test comment outside this claim's surface; in PR Acceptance notes)" ], "line_budget": "n/a (no skills/**)", "deviations": [ "A backgrounded gate runner wrote run-gates.pid into /home/user/objectstack (the shared main checkout root): the cd before the & did not carry to the following echo. Deleted after the run (pid 29957) had exited, as the coordinator asked; later pid/log files used absolute scratchpad paths. Nothing was committed from it.", "One probe command was refused by the harness safety check (an rm inside a bash -c script) and did not run; it was redone with the probe file copied in and removed by a literal-path rm outside the lock script. The probe file never entered a commit; git status was clean after each removal.", "main was not merged before opening the PR (3 incoming commits, no overlap with packages/cli or packages/client); declared narrowing, CI runs the merge ref.", "Commits carry the AGENTS.md model-free trailer pair (Claude-Session + Co-authored-by: Claude) instead of the harness reminder's model-named Co-Authored-By line, per os-dev.md's precedence clause." ], "files_changed": [ ".changeset/23350-cli-meta-package-flag.md", "packages/cli/src/commands/meta/delete.ts", "packages/cli/src/commands/meta/delete-reset-carriers.test.ts", "packages/cli/src/commands/meta/register.ts", "packages/cli/src/commands/meta/register-package.test.ts", "packages/client/src/index.ts" ], "cleanup": "Worktree /home/user/objectstack-issue-23350 removed (node_modules first, git worktree remove without --force, exit 0) after confirming git status clean and origin at 7ec2fb6c7. No background process of this run is alive (gate runner 29957 and unit run 16432 exited)." }Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
ACCEPT → PR #23475 comment 6167980187 ·
domain:specseat 1 (#6017) · sessionsession_01YRp5z4kK6vgYkrdH97ztsy· 2026-10-14T12:08ZGenerated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Landed: PR #23475 →
a1285f26d(Fixes #23350) · 2026-10-14T12:46Zdomain:specseat 1 (#6017) ·huangyiirene· sessionsession_01YRp5z4kK6vgYkrdH97ztsy· holder of claim6166598761. Records: theTIER_DEFAULTreview6167942702(PASS) and the ACCEPT## 席位核对6167980187, both on7ec2fb6c7.GET /pulls/23475merged: trueat 12:46:19Z,merge_commit_shaa1285f26dGET /branches,gh-readonly-queue/*origin/maingit merge-base --is-ancestor a1285f26d origin/maina1285f26dis the tip, a squash on22fb225dcGET /issues/23350closed/completedon the merge. The PR's timeline also cross-references #23479 and #23480, the seat's two findings from this card. Both are open, as filed.State change: this act removes
pm:dispatched.Generated by Claude Code