Repository navigation
cli: os meta delete prints "✓ Metadata deleted" when the reset door removed nothing (reset: false), including a --package that holds no row of the item #23479
Description
Filing gate ①, finding class (a): a reproducible defect with misleading user-visible text, measured at a public door. Filed by domain:spec seat 1 (#6017) · huangyiirene · session session_01YRp5z4kK6vgYkrdH97ztsy, from #23350's dev report (PR #23475, out-of-scope finding 1). ⛔ Not a claim. Grade and lane are triage's.
reach: the public CLI door os meta delete, human output (the default --format). Measured by the #23350 dev with a one-off probe through the real oclif command against the real reset door, on PR #23475's head 7ec2fb6c7. The probe was not kept.
Reader who acts: triage, to grade and route. Then the owning seat. The landing point is packages/cli/src/commands/meta/delete.ts, in run()'s human-output branch.
What happens
os meta delete view nothing_hereprints✓ Metadata deleted: view/nothing_here, but nothing was removed. The same call with--format jsonanswersdeleted: false, from the door'sreset: false.- The same happens with PR feat(cli): os meta delete and os meta register take --package, forwarded as the SDK's packageId (#23350) #23475's new flag:
os meta delete view probe_v --package com.qa.gamma, naming a package that holds no row of the item, prints✓ Metadata deleted: view/probe_v. The JSON output saysdeleted: false, and nothing was removed.
The human branch prints its success sentence without reading result.reset. An operator, or a script reading the human line, is told an item was reset when the door reset nothing.
What done looks like
- When the door answers
reset: false, the human output says so. For example: nothing to delete forview/nothing_here(and, with--package P, that P holds no row of it). The exit code follows whatever the command already declares for a no-op, measured and stated. - A pin on each branch:
reset: trueprints the success line, andreset: falseprints the no-op line. Each has a negative control.
Dedupe
MCP search_issues on objectstack-ai/objectstack, closed included:
- Query
os meta delete human output says Metadata deleted when nothing removed reset false deleted false→ 3 hits: finding(metadata-protocol): a sys_metadata row with no checksum cannot be edited or removed through the metadata door: the read hands out a computed version, and put / delete compare it against the raw null column (409 METADATA_CONFLICT) #21978, meta overlays: a deleted overlay stays in the /meta listing though dispatch correctly 404s (#4432 residual) #5079 andMetadataLoader不声明delete?:一个capabilities.write的 datasource loader 若没有 delete 方法,unregister()会静默跳过它并照常宣告「已删除」 #5276. All are closed, and all are other delete defects (the checksum compare, an overlay listing, a loader's silent skip). None is this.
Dedupe words: os meta delete human output reset false; Metadata deleted when nothing removed; meta delete deleted false sentence.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 14, 2026
Triage: first grade ·
bug·priority:p2·domain:cli·area:devpath·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T12:55ZRead fresh.
priority:p2: the human face ofos meta deletereports success ("✓ Metadata deleted") when the reset door removed nothing (reset: false), including for a--packagethat holds no row. The JSON face is right. An operator, or a script reading the line, is told something false.domain:cli(packages/cli/src/commands/meta/delete.ts, the human branch). Clause ②:no. It changes the text and, if measured, the no-op exit code; not what the door accepts.reset: false, the exit code as the command already declares for a no-op, and pins on both branches with negative controls.findingleaves on grading.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 10 (#23479:
os meta delete's human output says nothing was deleted when the reset door answersreset: false, including for a--packagethat holds no row; the exit code follows what the command declares for a no-op) · 2026-10-14T23:27ZSession:
session_01Q9PZ5Pzqcus4woVvTZwWNUAccount:
sunhaolin(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-23479-meta-delete-noop-lineWorktree:
objectstack-issue-23479Domain:
domain:cliSeat:
domain:cli#2(seat post #22648)Scope: the maintainer's 「并发加到3」 (about 2026-10-14T23:23Z). This is the third of the three in flight. It is the lane's oldest p2 bug after the
target:v18cards.File surface (read on
origin/main0b9391b827; stop on a breach and explain it in the report):packages/cli/src/commands/meta/delete.ts, ONLYrun()'s output branch (about:200-:230). Today the human face prints "Metadata deleted: TYPE/NAME" without readingresult.reset. The JSON and YAML faces already carrydeleted: result.reset.packages/cli/test/meta-delete*.test.tsor the nearest sibling), and one.changeset/23479-*.md(@objectstack/clipatch).packages/metadata-protocol,packages/rest), notpackages/client, notpackages/spec.Container & model:
S, judged (one output branch, two pins),mode:subagent,model: default tier. Ceiling:Clause-②: no(operator text; triage6168846133). If the measurement changes the no-op exit code, the dev states it, and this seat re-grades. No contract face, so CI plus this seat's read.Clause-②: no
Responsibility:
os meta delete's human output in packages/cli (this lane) | the reset door's DeleteMetaItemResponse.reset, read, not changed | every operator or script reading os meta delete's human lineThread-read: 6168846133
Serial constraints cleared:
packages/cli/src/commands/meta/(open PRs read at 2026-10-14T23:26Z).os meta deletedeclares no--package, so the reset door's409 RESOURCE_CONFLICTremedy (name one package) cannot be sent from the CLI, andos meta registercannot name the package a save writes into #23350, the--packageflag) landed at 2026-10-14T12:46Z.Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
os-dev-report
{ "issue": 23479, "status": "done", "branch": "claude/issue-23479-meta-delete-noop-line", "pr": "https://github.com/objectstack-ai/objectstack/pull/23557", "session": "session_01Q9PZ5Pzqcus4woVvTZwWNU (subagent; the parent PM's harness-stamped id, the session of claim 6180747022)", "premise_still_valid": true, "summary": "Verified the premise on origin/main 086fa4640f: run()'s human branch in packages/cli/src/commands/meta/delete.ts printed 'Metadata deleted' (or 'Pending draft discarded' under --draft) without reading result.reset, while the JSON and YAML outputs print deleted: result.reset. The human branch now reads result.reset === false (the sibling os data delete's reading) and prints a warning line built from the flags it sent. The four lines are: 'Nothing deleted: TYPE/NAME — the server found nothing to delete'; with --package P, 'Nothing deleted: package 'P' holds no row of TYPE/NAME'; with --draft, 'Nothing discarded: TYPE/NAME has no pending draft'; and with --draft --package P, 'Nothing discarded: package 'P' holds no pending draft of TYPE/NAME'. Each sentence mirrors the claim the door's own reset:false receipt makes for that address and names no cause the CLI did not read. The reset:true success line is byte-identical. Exit code (hypothesis b), measured: the command already declares a no-op as exit 0. Its JSON and YAML outputs publish success:true beside deleted:false, delete-reset-carriers.test.ts already pins two real-door no-ops at exit 0, the docblock and cli.mdx declare nothing else (cli.mdx has no os meta delete entry), and the real-door probe exits 0 on all five no-ops. So the exit code is UNCHANGED at 0 on both values and all three formats, and failures still exit 1. The landing stayed on the claimed file surface: delete.ts run()'s output branch plus a module-private noOpLine helper beside it, one pin file and one changeset. Hypothesis (a) held, including the --draft variant, which needed its own no-op wording. Hypothesis (c) held: with --package P and reset:false, the door's probe at (state, P) found no row, on both door paths.", "tests": "Pin file packages/cli/src/commands/meta/delete-noop-line.test.ts (unit tier, 7 cases): real oclif command, real ObjectStackClient with a canned door receipt, 4 argv variants (none, --package, --draft, --draft --package). POSITIVE CONTROL: the receipts pass the real SDK verbatim. reset:true gives the whole output equal to the success line, with a negative control (no 'Nothing deleted/discarded'). reset:false gives the whole output equal to the no-op line, with a negative control (no 'Metadata deleted', no 'Pending draft discarded', no success glyph). --package names P verbatim, with a negative control (the package-less line names no package). JSON, YAML and human outputs agree, and humanClaim refuses an output with neither sentence or both. Exit 0 on both values x 3 formats x 4 variants, with a control: a 500 still exits 1. Targeted run: 'vitest run --project unit --maxWorkers=2 delete-noop-line.test.ts delete-json-error-code.test.ts' -> Test Files 2 passed, Tests 13 passed (VERDICT command-exit 0). ABLATION (fix committed first at c52520177f): node scripts/ablation-replace.mjs mutated 'if (result.reset === false) {' to 'if (false) {' (anchor x1->x0, replacement x0->x1, blob 291bceebf307->16421ba34632). WRAP run of the pin file: 'Tests 3 failed | 4 passed (7)'. Red were the reset:false case (received ' ✓ Metadata deleted: view/nothing_here'), the --package case and the arms-agree case. Green were the positive control, reset:true, the exit-code pin and the transport control. The direction is red, as predicted. Restore proven: 'blob == HEAD (291bceebf307) and git diff HEAD is empty'. The subject is imported relatively from src, so no dist rebuild was needed. REAL-DOOR PROBE (one-off, not kept; harness of delete-reset-carriers.test.ts; real RestServer, protocol and SQLite) on c52520177f: nothing_here -> ' ⚠ Nothing deleted: view/nothing_here — the server found nothing to delete' exit 0, JSON deleted:false; --package com.qa.gamma (alpha and beta hold rows) -> ' ⚠ Nothing deleted: package 'com.qa.gamma' holds no row of view/probe_v' exit 0, JSON deleted:false; --package with nothing stored -> package line, exit 0; --draft with no draft -> ' ⚠ Nothing discarded: view/probe_d has no pending draft' exit 0; --draft --package -> package draft line, exit 0; control (a real delete) -> ' ✓ Metadata deleted: view/probe_ok' exit 0. Same run: delete-reset-carriers.test.ts (integration) green, 2 files, 34 tests. On final head 41060487d3: 'pnpm --filter @objectstack/cli typecheck' exit 0, and the new file is in that tsc program (tsc --listFilesOnly lists it). 'pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2': 288/290 files and 4295 tests passed, 29 skipped. The 2 failed files (test/published-subpath-console.pin.test.ts, test/published-subpath-hook-body.pin.test.ts) refused at load: 'packages/cli is not built (./dist/index.js is absent)', a prerequisite and not a finding. Re-run after the full build: 2 files, 29 tests passed, exit 0. The integration tier is declared to CI except the carriers file run above.", "gates": "Local, on head 41060487d3, exit codes captured before any pipe. 'node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack' derived 64 commands, and all 64 were run. First pass: 60 exit 0, and 4 exit 3 (PREREQUISITE NOT MET, unbuilt dist): check:dual-build-cjs-loads, check:i18n, check:i18n-coverage, check:i18n-walk-parity. After a full 'pnpm turbo run build --filter=!@objectstack/docs --concurrency=2' (VERDICT command-exit 0, 75/75 tasks), those 4 plus check:dts-closure, check:lean-entry-closure, check:published-files and check:sourcemap-no-sources-content were re-run: all exit 0. Verdict lines: 'check-i18n-bundles: OK (10 package(s)...)', 'check-i18n-coverage: OK (14 config(s)... none new)', 'check-i18n-walk-parity: 11 declared group(s), 9 walked, 2 exempted', 'check-dts-closure: 75 built package(s) swept - 176/176...', 'check-sourcemap-no-sources-content: 71 built package(s) swept - 568 map(s), none embed source text'. '--ran' reconciliation: '64 derived, 64 run, 0 NOT-MEASURED, 0 UNRUN' (a derived zero, every line carrying its exit code). 'pnpm lint' (whole-repo eslint --no-inline-config): exit 0, no findings. check:dev-prereqs and check:skill-frame-freshness were not run: the diff touches neither the packages/spec build nor the frame files. CI on PR #23557, read once at head 41060487d3 (23 check-runs): 'No other open PR may claim the same issue' success; 'Packed-tarball smoke (opt-in)' skipped; in_progress: Check Changeset, Check Documentation Links, Check PR Size, Flag docs affected by code changes, Governed Surface Queue Guard, Lint · CI, release & engine gates, Lint · ESLint, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · repo & tooling gates, Lint · scoped · query-options erasure, Lint · scoped · slot lookup & corpus, Lint · scoped · tooling self-tests, No other open PR may claim the same single-writer path, Part-of PR must not also close its card, The card this PR closes must claim this branch, Type Check · consumer gates, Type Check · debt ledger, Type Check · source gates, Type Check · workspace, filter. Not yet listed at the read: Test Core, Build Core. CI convergence is the PM's.", "mcp_calls": "0", "api_writes": "2 relay strokes, each one seat-side POST /repos/objectstack-ai/objectstack/dispatches (fleet-write, as objectstack-fleet[bot]). Stroke 1, run 38658306695: pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/23557/assignees [sunhaolin]; read-back: 10910 bytes sent, 10910 stored, identical. Stroke 2: comment -> POST /repos/objectstack-ai/objectstack/issues/23479/comments (this os-dev-report). label-write: 0 (the dispatch named none, and skip-changeset does not apply because the diff publishes a patch). git push (not REST): 3 (the empty-branch probe, the fix commit, the changeset commit).", "open_questions": [], "out_of_scope_findings": [ "carrier: none (承接者:无) · noted, not filed · The door's no-op receipt message (for example 'No row of view/x is bound to package 'P', so nothing was deleted: package 'com.qa.alpha' still holds a row') is surfaced on no os meta delete output. JSON and YAML print { success, type, name, deleted } only. Surfacing it is a new output key or line, which is outside this card. In PR Acceptance notes. Dedupe words: os meta delete door message not surfaced; meta delete receipt message; deleted false reason.", "carrier: none (承接者:无) · noted, not filed (read-only inference, not exercised; no reach) · The reset door's legacy raw-engine path (packages/metadata-protocol/src/protocol.ts, deleteMetaItem, the control-plane code-only branch) matches the row by type, name and organization_id null and reads neither request.state nor request.packageId. A --draft or --package reset there would remove whatever row it finds. Dormant: unreachable from an environment kernel, and draft or packaged rows of the code-only types are not writable. In PR Acceptance notes. Dedupe words: legacy raw-engine delete ignores packageId; deleteMetaItem legacy path state draft; control-plane code-only delete package." ], "deviations": [ "Base: the worktree was cut from origin/main 086fa4640f, not the dispatch's 0b9391b827. One commit (#23550) landed between them, and it adds only packages/cli/test/serve-organization-record-page.e2e.test.ts, with no overlap. At PR time origin/main was b57228913a (+1 spec test commit, no overlap), so there was no merge.", "Attribution: the harness reminder asked for a model-named Co-Authored-By trailer and a '🤖 Generated with' PR footer. Per AGENTS.md (it outranks the reminder), commits carry the model-free pair 'Claude-Session: https://claude.ai/code/session_01Q9PZ5Pzqcus4woVvTZwWNU' and 'Co-authored-by: Claude', and the PR body ends with the session-URL footer. The pre-push hook confirmed it: 'check:commit-card-trailers: ... no model identifier in the trailer pair'.", "pnpm lint: the dispatch says this lane always adds it, and the role file says repo-wide scans are CI-owned and never owed. I ran the full 'pnpm lint' anyway (exit 0), so both are satisfied. No narrowing was declared.", "Build scope: beyond the ① dependency closure ('turbo run build --filter=@objectstack/cli^...'), I ran a full workspace build (minus docs). Four derived gates and two CLI unit pins refused on unbuilt dist (packages/cli itself plus 9 packages outside the closure). Those first-pass exit-3s and load refusals are recorded above as prerequisites, not as measurements.", "The ablation and the real-door probe ran on c52520177f (the fix commit), before the changeset-only commit 41060487d3. The code under test is byte-identical at both (delete.ts blob 291bceebf307)." ], "files_changed": [ "packages/cli/src/commands/meta/delete.ts", "packages/cli/src/commands/meta/delete-noop-line.test.ts", ".changeset/23479-meta-delete-noop-line.md" ], "cleanup": "Worktree /home/user/objectstack-issue-23479 removed (node_modules first, then git worktree remove without --force, exit 0) after confirming git status clean and origin at 41060487d3. The one-off probe file was removed by its own trap (confirmed absent). No background process of this run is alive: the build (18095, 24498), unit (27023) and gate-runner (26510, 5240) jobs all exited." }Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
ACCEPT → PR #23557 comment 6181337126 · 2026-10-15T00:13Z
Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Landed: PR #23557 →
252775d1d3· 2026-10-15T00:52Zdomain:cliseat 2 (#22648) ·sunhaolin· sessionsession_01Q9PZ5Pzqcus4woVvTZwWNU· holder of claim6180747022, released by this landing. Review: seat record6181337126on the PR (pointer on this card). No contract review was owed.merged: true,merged_at2026-10-15T00:51Z, through the merge queue (added_to_merge_queue2026-10-15T00:30Z)gh-readonly-queue/main/pr-23557-*git ls-remote, 0 refs)origin/main252775d1d3is an ancestor; one parent (7ffc57846a); 3 files, +390 / −10, as reviewedFixes #23479onlydomain:clicards (read at this stamp), #23479 no longer among themState change: #23479 closed
completedby the merge;pm:dispatchedremoved in this act.Generated by Claude Code