Repository navigation
metadata-client: reset() cannot name a package — after objectstack#23165 a console reset or discard of an item two packages hold answers 409, and the remedy ?package= is one the console cannot send #12335
Description
Blocked-by: #12370
Restart-when: npm view @objectstack/rest@next time --json lists a version published after 2026-10-13T15:54:13Z, the merge of objectstack 543b33dee, i.e. one whose DELETE /api/v1/meta/TYPE/NAME accepts ?package=
Filing gate: cross-repo rule 3. An accepted objectstack PR's product flows into this repo, and the accepting seat files the consumer's follow-up when it lands. This card is held (pm:on-hold) until the release is installable: against today's released server, a DELETE carrying ?package= is refused 400 as an unknown parameter, so sending it early would break every reset. The Restart-when: line above is the unlock criterion; #12030 (objectui onto the next prereleases) is the path by which it reaches this repo.
Filed by objectstack domain:spec seat 2 (objectstack-ai/objectstack#18549) · os-justin · session session_01BRQ9Mp1yH7R1az6MaUM18H. ⛔ Not a claim. Reader who acts: objectui triage, to route it. The upstream PR body named #12300 as this half's carrier, but #12300 closed at 07:26Z (PR #12313), before the upstream door existed, so this card carries it.
What landed upstream
- 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) objectstack#23165 (triage direction
6141939797, option B under ADR-0070) was carried by 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) objectstack#23290, merged as543b33deeat 2026-10-13T15:54Z. - A save or delete that names no package now addresses the one package that holds the item. When two or more packages hold the name, it is refused
409 RESOURCE_CONFLICT, naming them, with?package=as the remedy; nothing is written or deleted. DELETE /api/v1/meta/TYPE/NAME?package=PACKAGE_IDis new: before it, the delete door could not name a package at any layer. The delete receipt names the package it removed from, and names the row still stored when another one remains.
The reader here, measured at objectui origin/main 72594f29
packages/data-objectstack/src/metadata-client.ts,reset(): it sendsDELETEwith?state=draftat most, and never a package.save()andpublish()in the same file already send?package=when the item is package-bound, with one spelling for both.- Its callers:
packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx:1805(reset) and:1884(discard draft),packages/app-shell/src/views/runtime-metadata-persistence.ts:356(discard draft), andpackages/plugin-designer/src/MetadataObjectsPage.tsx:213(reset an object); plus Setup › Apps' delete, which console Setup › Apps: Delete and Disable report success for writes that changed nothing — handleDelete ignores reset:false, and handleToggleActive saves a package-owned app with no package scope #12300 made honest aboutreset: false. - So after the release, a console reset or discard of an item two packages hold answers 409 with a remedy the console cannot send.
Acceptance
Run on the installed release:
reset()takes apackageIdoption and sends?package=when it is set, omitted (never empty) when it is not, the spellingsave()andpublish()use.- Each caller above that knows the item's package binding passes it. A caller that does not know it keeps the package-less call, and a 409 from it is shown with its remedy, not swallowed.
- Pins: a reset of a package-bound item sends
?package=; a package-less reset sends none; a 409RESOURCE_CONFLICTreaches the user as an error. - The SDK side,
@objectstack/client'smeta.deleteItem, is 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 objectstack#23293 and is not this card.
Dedupe
MCP search_issues on objectstack-ai/objectui, closed included: metadata client reset delete package query parameter console discard draft two packages 409 → 6 hits, all closed: #12300 (the Setup › Apps half named above), #11784, #11797, #11203, #5359 and #2555, about other delete, discard and draft questions. None is this.
Dedupe words: metadata-client reset no package; DELETE meta package query; console discard draft two packages 409.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 14, 2026
Unlock scan:
Restart-when:met (18.0.0-next.1published 12:08Z) · first grade ·priority:p2·domain:ui·area:studio·target:v18·pm:on-hold→pm:blockedon #12370 · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T12:41ZRead fresh. The line's condition is a publication, and it holds:
npm view @objectstack/spec dist-tagsreadsnext: 18.0.0-next.1, built from objectstack0c52e43075, past this card's upstream commit.mainresolves18.0.0-next.0across the lockfile. The one bump card for this release is deps(v18): move objectui's @objectstack/* from 18.0.0-next.0 to 18.0.0-next.1 and follow its contract — the bump the held follow-ups wait on #12370 (p1), so this card waits on it rather than racing the lockfile in its own PR. The body now starts with the line below.Blocked-by: #12370
priority:p2: on next.1, resetting or discarding an item two packages hold answers409, and the console cannot send the?package=remedy. That breaks a narrow case (an item in two packages), not a whole surface.major, Changesets pre mode onnext, and the two gate edits (the maintainer's ruling on #12030), after #12030 lands #12334's pre-release list.objectstack-fleet commentedon Oct 14, 2026
Unlock scan:
pm:blocked→pm:queue· objectui now resolves18.0.0-next.1· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T20:03Zmainnow pins@objectstack/spec^18.0.0-next.1, and its lockfile resolves18.0.0-next.1.543b33deeis an ancestor of the18.0.0-next.1tag commit0c52e43075.@objectstack/rest@18.0.0-next.1was published at 2026-10-14T12:08Z, after the 2026-10-13T15:54Z merge. Both lines are met.target:v18. It is listed on objectui#12334.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 1
Session:
session_01JZnppgHRp4sREcouhkQYDBAccount:
sunhaolinBranch:
claude/issue-12335-reset-packageWorktree:
objectui-issue-12335Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/data-objectstack/src/metadata-client.ts(reset()only),packages/data-objectstack/src/index.ts(its view-deleteresetcalls only),packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx(the reset and discard-draft handlers only),packages/app-shell/src/views/runtime-metadata-persistence.ts(the discard-draft call only),packages/plugin-designer/src/MetadataObjectsPage.tsx(the object reset only), their tests, and a.changeset/entry (stop on breach; explain in the report)Container & model:
M,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuinames no path-derived mandate)Clause-②: no
Responsibility: the console's own client:
@object-ui/data-objectstack'sreset()never sends?package=| the server answers 409RESOURCE_CONFLICTand names the?package=remedy (objectstack PR #23290), which the console cannot send | a Studio author resetting or discarding an item two installed packages hold, reachable on the18.0.0-next.1objectui resolves todayThread-read: 6177240498
Serial constraints cleared: none in flight. Seat 2's claims touch other files: #12390 and #12349 (metadata-admin previews and inspectors,
StudioDesignSurface.tsx), #12375 and #11970 (plugin-grid). Queued sibling objectui#12271 (?member=on the draft panel) likely sharesmetadata-client.ts. Fold or serial: serial, #12335 first. Fold gate ① fails because #12271 is a different defect with a different fix.MetadataDeleteOptionsalready inheritspackageId?: stringfromMetadataClientSaveOptions(theexport interface MetadataDeleteOptions extends MetadataClientSaveOptionsline inmetadata-client.ts). Soreset()starts honouring an option its type already declares, and no exported type member is added. A route that would add one stops and reports.Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
os-dev-report
{
"issue": 12335,
"status": "done",
"branch": "claude/issue-12335-reset-package",
"pr": "#12396",
"session": "session_01JZnppgHRp4sREcouhkQYDB — subagent run; the id is the dispatching seat's (Claude-Session attribution of this conversation)",
"premise_still_valid": true,
"summary": "MetadataClient.reset() now sends ?package= when options.packageId is set (beside ?state=draft for a discard) and omits it otherwise, with the conditional and encodeURIComponent spelling save()/publish() use; A1 and A2 measured true at 28fb2a0 (reset sent ?state=draft at most; MetadataDeleteOptions extends MetadataClientSaveOptions, which declares packageId), so no exported type changes and Clause-② stays no. Callers re-derived (six reset( calls in five places): ResourceEditPage doReset and doDiscardDraft hold the binding (?package= on the editor URL via readActivePackageBinding(), the same source doSave/doPublish state) and now pass it; MetadataObjectsPage holds the listed row's served _packageId and now passes it (sys_metadata sentinel and absent read as no package, the reading AppManagementPage's owningPackage uses); the runtime seam (discardRuntimeDraft, RuntimePersistCtx carries no package) and ObjectStackAdapter.deleteView (published DataSource.deleteView?(objectName, viewName) carries none; threading one would widen an exported member, so index.ts is untouched) keep the package-less call, and their 409 is pinned to reach the caller (draft bar toast description; deleteView throws with code). A3's Setup › Apps' delete does not call reset(): AppManagementPage.handleDelete calls the SDK's meta.deleteItem('app', name), the side the card excludes (see findings). A4: @objectstack/rest is not installed in objectui; the wire shape (DELETE reads ?package=, 409 body error+code RESOURCE_CONFLICT) was read from objectstack source (rest-server.ts DELETE handler, packagelessAddressAmbiguityRefusal, handleRouteError); the installed @objectstack/client 18.0.0-next.1 d.ts already declares DeleteMetaItemOptions.packageId. A live run against a booted server is NOT MEASURED. PR #12396 is draft, assignee sunhaolin, CI in_progress at report time; worktree removed.",
"tests": "HEAD 2ae6f96, locked run: pnpm exec vitest run packages/data-objectstack/ packages/plugin-designer/src/MetadataObjectsPage packages/app-shell/src/views/metadata-admin/ResourceEditPage packages/app-shell/src/views/RuntimeDraftBar packages/app-shell/src/views/runtime-metadata-persistence packages/app-shell/src/views/writeRefusalCensus-11583 packages/app-shell/src/views/ObjectView.viewWriteRefusal-11583 -> 'Test Files 131 passed (131)' 'Tests 1384 passed (1384)', VERDICT command-exit 0. New pins: metadata-client.resetPackageBinding-12335.test.ts (7), ResourceEditPage.resetPackage-12335.test.tsx (5, real page + real MetadataClient over a two-package in-memory door), MetadataObjectsPage.resetPackage-12335.test.tsx (3), RuntimeDraftBar.resetPackage-12335.test.tsx (1), deleteView.resetPackage-12335.test.ts (2); ResourceEditPage.resetVerdict.test.tsx's two reset call pins now expect the options bag {} (no package key). Ablation (tested behaviour changed): reset() change reverted on disk via objectstack scripts/ablation-replace.mjs in WRAP mode, anchor x1 -> x0, blob ef1bc5196226 -> 6e7616d597a9; no build leg needed (vitest aliases @object-ui/data-objectstack to src, the client pin imports ./metadata-client). Predicted 7 red / 11 green; read 'Tests 7 failed | 11 passed (18)' (red: 4 bound client pins, 2 bound editor cases, the package-owned Objects-page case; green: unbound, 409, draft bar, deleteView). Restore proven: blob after restore == HEAD ef1bc5196226, git diff HEAD empty. Ablation ran at edb7705; metadata-client.ts is byte-identical at HEAD 2ae6f96.",
"gates": "Derived by hand (objectstack dispatch-gates refuses a sister repo) from objectui package.json check:* and lint.yml / repo-gates.yml / changeset-presence.yml / changeset-guard.yml / line-citation-gate.yml for the changed paths. Local at HEAD 2ae6f96, exit captured to file before any pipe: type-check @object-ui/data-objectstack 0, @object-ui/plugin-designer 0, @object-ui/app-shell 0 (after turbo build of each package's ^... closure, 28/28 tasks; new tests counted inside the programs with --listFilesOnly); eslint on the 9 changed ts/tsx files 0 (0 errors, 62 warnings all on untouched lines); check-changeset-presence 0, check-changeset-no-major 0, check-changeset-claims 0, check-changeset-overwrite 0, check-pending-changeset-literals 0, check-new-cross-file-line-citations 0 ('0 new citation(s)'), check-control-bytes 0, check-vi-mock-specifiers 0, check-vi-mock-inherit 0, check-vi-mock-override-shape 0, check-test-path-roots 0, check-object-metadata-write-doors 0; check-governed-queue-guard --test over the 10 paths: NOT GOVERNED. No --ran reconciliation (no dispatch-gates for objectui). CI on PR #12396 head 2ae6f96 at report time (32 check-runs): success = Changeset Fixed Group Check, Changeset Bump Policy, Changeset Overwrite Report, label; skipped = Test (coverage), Test (coverage shard matrix), dependabot; in_progress = Test (shard 1..12 of 12), Test (dist pins), Type Check, Lint, Build & E2E, Repo Gates, Line Citation Gate, Governed Surface Queue Guard, Changeset Declaration, Changeset Claim Re-read, Spec Main Shape Gate, Build Docs, Bundle Analysis, Live E2E (informational).",
"mcp_calls": "0 — no MCP GitHub calls; reads went through gh api REST GETs (issues/12335, issues/12335/comments, pulls/12396, commits/2ae6f96f8.../check-runs).",
"api_writes": "2 — relay dispatches POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]: (1) pr_create -> POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos//issues/12396/assignees [sunhaolin], read-back 10688 bytes identical; (2) comment -> POST /repos//issues/12335/comments (this report). No label writes. git push of the branch x4 (empty probe + 3 commits), not REST.",
"files_changed": [
"packages/data-objectstack/src/metadata-client.ts (reset() only)",
"packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx (doReset and doDiscardDraft only)",
"packages/plugin-designer/src/MetadataObjectsPage.tsx (object delete + a local owningPackage helper)",
"packages/data-objectstack/src/metadata-client.resetPackageBinding-12335.test.ts",
"packages/data-objectstack/src/deleteView.resetPackage-12335.test.ts",
"packages/app-shell/src/views/metadata-admin/ResourceEditPage.resetPackage-12335.test.tsx",
"packages/app-shell/src/views/metadata-admin/ResourceEditPage.resetVerdict.test.tsx",
"packages/app-shell/src/views/RuntimeDraftBar.resetPackage-12335.test.tsx",
"packages/plugin-designer/src/MetadataObjectsPage.resetPackage-12335.test.tsx",
".changeset/12335-reset-package.md (patch: data-objectstack, app-shell, plugin-designer)"
],
"line_budget": "n/a — no skills/** or governed ledger touched",
"deviations": [
"packages/data-objectstack/src/index.ts not edited although on the claimed surface: deleteView holds no binding, so its reset calls stay package-less by the card's rule.",
"runtime-metadata-persistence.ts not edited: the seam holds no binding; its package-less discard and 409 path are pinned through RuntimeDraftBar instead.",
"Ablation ran at edb7705, one commit before the final head; the only later change is the deleteView test harness's typing, and metadata-client.ts is byte-identical.",
"Commit trailers use the model-free pair objectui AGENTS.md prescribes, not the harness reminder's model-named Co-Authored-By; the PR footer uses the os-dev session-URL form.",
"Two temporary probe tests (ObjectView delete toast, AppManagementPage delete args) were written into the worktree, run once under the lock, and deleted; never committed.",
"Live run against a booted 18.0.0-next.1 server NOT MEASURED: the objectstack checkout here is not installed or built."
],
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: public door, console object page › view tab › Delete view: a refused delete toasts only the key objectViewActions.deleteFailed with no description, so the door's sentence (on 18.0.0-next.1 the 409 RESOURCE_CONFLICT remedy for a view two packages hold) reaches only console.error · evidence: uncommitted probe on the ObjectView.viewWriteRefusal-11583.test.tsx harness read toast.error title "objectViewActions.deleteFailed", options null (expected a description holding the refusal text); the objectui#11583 census row reads 'Delete: says objectViewActions.deleteFailed; predates this census' · Seam: renderer:ObjectView handleDeleteView · family: objectui#11583 write-refusal census (closed) · outside this claim's file surface · dedupe words: ObjectView delete view refusal toast no description; handleDeleteView deleteFailed door message; view delete 409 remedy swallowed",
"class: a · reach: public door, Setup › Apps › Delete on a package-owned app: handleDelete calls meta.deleteItem('app', name) with no options although the page names owningPackage(app) on every save and the installed @objectstack/client 18.0.0-next.1 declares DeleteMetaItemOptions.packageId (objectstack-ai/objectstack#23293); on an app two packages hold the delete answers 409 whose ?package= remedy the page could now send (the 409 itself is shown via reason(e), not swallowed; a live 409 NOT MEASURED) · evidence: uncommitted probe on the AppManagementPage.honestWrites-12300.test.tsx harness read deleteItem args ["app","lanebapp_app"] (expected a third argument naming com.qa.lanebapp); MetadataService's two meta.deleteItem calls have the same shape (not probed) · dedupe words: AppManagementPage delete package scope; meta.deleteItem packageId console; Setup Apps delete two packages 409",
"carrier: 承接者:无 · noted in PR #12396 Acceptance notes, not filed: the editor's post-reset/discard re-read client.layered(type, name) names no package (as doPublish does); S6 residue (a named delete of an item whose stored row is package-less answers nothing-deleted and neither page reads the receipt); MetadataObjectsPage keys rows by name so two same-name package rows collapse; second local copy of the sys_metadata fold; MetadataObjectsPage's save stays package-less"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
ACCEPT → PR #12396 comment 6181724148 ·
domain:uiseat 1 ·session_01JZnppgHRp4sREcouhkQYDB· 2026-10-15T00:44Z2ae6f96f8. All 33 check-runs completed: 30successand 3 expected skips.Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Landed: PR #12396 →
maind12bc5fe9(Fixes #12335) ·domain:uiseat 1 ·session_01JZnppgHRp4sREcouhkQYDB· 2026-10-15T00:59Zmergedd12bc5fe9compare d12bc5fe9...mainmaincontains itidentical, behind 0metadata-client.ts,ResourceEditPage.tsx,MetadataObjectsPage.tsxand.changeset/12335-reset-package.md:mainagainst the accepted head2ae6f96f8completed; nothing elsepm:dispatchedwas removed in this act (label write read back);domain:ui,area:studio,priority:p2andtarget:v18stay.Generated by Claude Code