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
Studio: the layered-view callers pass the owning package, since a package-less /layers read of a name two packages hold now answers 409 (#28337) #28584
Filing gate: ① consumer seam of the #28337 server change (PR #28583), named by its dev and by the CONTRACT_REVIEW_TIER review (comment 6554511214), which ruled it a ui follow-up and not in-PR. Filed by domain:server seat 2. ⛔ Not a claim. No grade: triage sets the lane and grade.
Reach: Studio, on a deployment where two packages ship an item with the same type and name (for example two dashboards called X).
Reader who acts: domain:ui (ui/packages/app-shell).
GET {metaPath}/:type/:name/layers and the deprecated ?layers=true read, with no ?package=, now refuse with 409 when two or more packages hold active rows of that name. This is the same refusal the package-less save and delete already answer, naming the holders with the ?package= prescription. With ?package=<id>, the read answers that holder's stack as before. Names with one holder are unchanged.
The callers (read by the review on main)
ResourceEditPage already passes ownerPackageId, so it is unaffected.
PermissionMatrixEditor (ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx) and ObjectListViewInspector read the layered view package-less. On an ambiguous name they will now get the 409, and the editor reads a failed layered read as "no artifact known".
Wanted
Those callers pass the owning package (?package=) they already know from the row or route they were opened from. Where no owner is known, show the server's refusal sentence rather than treating the 409 as "no artifact". ⛔ No client-side guess of which holder to read.
Read fresh. Since PR fix(meta)!: the layered view naming no package refuses a name two packages hold, as the package-less writes do #28583 (merged at 07:08Z, GitHub's clock), a package-less /layers read of a name that two packages hold answers 409. Studio's layered-view callers do not pass the owning package, so on such deployments the layered view now fails. That is a consumer regression of a merged server change, so p2. The fix passes ?package= from every caller, and a test pins the two-holder case.
Claim: PM loop round 3 · 2026-11-01T17:13Z
Session: session_01QsR2jQi39yrLXvXVSvoKfv (card thread, os-dev); dispatched by seat session session_01QsR2jUJ19MstFvFhjgiYTu
Account: zhuangjianguo
Branch: claude/project-thread-0h2wze (platform-assigned to the card thread; it can push only this branch)
Worktree: objectstack-issue-28584
Domain: domain:ui
Seat: domain:ui#1
File surface: every package-less client.layered(...) caller in ui/packages/app-shell (at least views/studio-design/ObjectListViewInspector.tsx :583-585 and views/metadata-admin/PermissionMatrixEditor.tsx; the dev enumerates the rest and names them in the report), their tests, and a root .changeset (stop on breach; explain in the report)
Container & model: S/M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: a package-less /layers read in Studio's layered-view callers | the server's 409 names the holders and the ?package= prescription (PR #28583) | an admin on a deployment where two packages ship an item of one type and name
Thread-read: 6561068138
Premise: holds (at origin/main7e6e8a46, ObjectListViewInspector.tsx:583-585 calls client.layered('view', viewId) with no packageId)
Serial constraints cleared: seat 4's #28572 (N-19) claims views/studio-design/**; if its PR touches ObjectListViewInspector.tsx, whichever lands later merges main.
Pass the owning package the caller already knows from its row or route; where none is known, show the server's refusal sentence instead of reading the 409 as "no artifact". ⛔ No client-side guess of the holder. A test pins the two-holder case.
{
"issue": 28584,
"status": "done",
"branch": "claude/project-thread-0h2wze",
"pr": "https://github.com/objectstack-ai/objectstack/pull/28825",
"head": "57d352cc",
"session": "session_01QsR2jQi39yrLXvXVSvoKfv",
"premise_still_valid": true,
"measured": "Premise held: package-less client.layered() callers in app-shell were ObjectListViewInspector (2 reads), StudioDesignSurface Interfaces app/leaf/dashboard-published, Data object, Automations flow, PackageOwdOverviewPanel readObjectBodies, PermissionMatrixEditor load + both re-reads, EmbeddedItemEditor parent read, ResourceEditPage reset/publish/discard re-reads. Already scoped: StudioItemTools, StudioCustomizeControls, StudioBundleItemEditor. ADR-0146 D8 is server-side, so a read naming a read-only base serves its declared override. After merging #28747 (merged first), Data and Automations already read at its item-level packageId; the Interfaces leaf read at the base and failed #28572's own 'an added item opens writable' case (save went to the base) until it read at current.addedIn. New on main (#28783): usePublishAllDrafts.holdsNoPublishedLayer reads only package-less drafts (no owner known) and already takes any refusal as 'holds a layer'; left unchanged.",
"summary": "Each caller names the package it already reads and saves at (pillar package, item addedIn, door packageId, edit URL ?package= with 'all' folded to none). With no owner known the read names none; PermissionMatrixEditor now rethrows 409 RESOURCE_CONFLICT to its load error strip (the server sentence) instead of catching it to null. No client-side holder guess. Root changeset: @object-ui/app-shell patch with the claim's declaration lines.",
"tests": "New: ObjectListViewInspector.twoHolders-28584 (2), PermissionMatrixEditor.twoHolders-28584 (3, incl. ?package=all shows the refusal sentence and no matrix), StudioDesignSurface.twoHolders-28584 (3); oneSurface-28572 +2 (pair-added object and dashboard read at the pair). railLabels and navDeepLink-11153 exact-arg asserts updated. Reverse: 3 sources restored to main -> 8/8 new fail; rethrow ablation -> 1 fail; Interfaces leaf put back to base -> 2/12 oneSurface fail; all restored green. Sweep of every test naming a touched module, locked batches of 60, --maxWorkers=2: 57d352cc 366 files / 2600 tests passed (also 1edfa495 365/2595, 99045462 364/2583, 797eb378 363/2571). app-shell type-check exit 0 at each head. ESLint 0 errors.",
"gates": "dispatch-gates --commands: 34 derived, same set at every head; 34/34 exit 0 at 57d352cc (type-check-debt under the lock), incl. check-sdui-manifest and ui scripts/; --ran: 34 run, 0 NOT-MEASURED. PR-body gates on the final body: changeset-no-major --base origin/main 0, adr-0087-registration 0, partof-closing-keyword 0, closing-keyword-parity --body exit 2 binding only 'Fixes #28584' (intended).",
"dogfood_battery": "not run: ui-only diff, no server or spec change",
"line_budget": "13 files, +699/-20 (most is tests)",
"files_changed": [
".changeset/28584-studio-layered-reads-name-owner.md",
"ui/packages/app-shell/src/views/metadata-admin/{EmbeddedItemEditor,PermissionMatrixEditor,ResourceEditPage}.tsx",
"ui/packages/app-shell/src/views/studio-design/{ObjectListViewInspector,PackageOwdOverviewPanel,StudioDesignSurface}.tsx",
"tests: 3 new twoHolders-28584 files; oneSurface-28572, railLabels, navDeepLink-11153 updated"
],
"deviations": [
"Merged main three times (706ac52d, 8afaf12d with #28747, c064d3a2); stopped at 57d352cc on the seat's order.",
"EmbeddedItemEditor reads the hosting page's ?package= from window.location (its tests mount no Router), as its save binding does.",
"Reviewer request left to the seat (pr_request_reviewers is the seat's hand-off); assignee zhuangjianguo set at pr_create."
],
"mcp_calls": "subscribe_pr_activity #28825 only; no GitHub MCP writes",
"api_writes": "fleet-write pr_create #28825 (read-back byte-identical, assignee zhuangjianguo); this report comment via post-stamped",
"open_questions": [],
"out_of_scope_findings": [
"PackageOwdOverviewPanel's getDraft still names no package. reach: a package-less draft read, not a layered read; card scope is /layers.",
"EmbeddedItemEditor's draft read and save name no package when the host URL has none. reach: a package-less save of a two-holder name is already refused 409 by the server and the editor shows it."
]
}
Landed · 2026-11-01T22:35Z · PR #28825 merged through the merge queue as 1caf6722 at 2026-11-01T22:35:11Z (GitHub's clock). ACCEPT 6564759380 at head 57d352cc.
Activity
objectstack-fleet commentedon Nov 1, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p2 ·
bug·domain:ui·area:studio·pm:queue· 2026-11-01T17:02Z⛔ Not a claim.
/layersread of a name that two packages hold answers 409. Studio's layered-view callers do not pass the owning package, so on such deployments the layered view now fails. That is a consumer regression of a merged server change, so p2. The fix passes?package=from every caller, and a test pins the two-holder case.Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim: PM loop round 3 · 2026-11-01T17:13Z
Session:
session_01QsR2jQi39yrLXvXVSvoKfv(card thread, os-dev); dispatched by seat sessionsession_01QsR2jUJ19MstFvFhjgiYTuAccount:
zhuangjianguoBranch:
claude/project-thread-0h2wze(platform-assigned to the card thread; it can push only this branch)Worktree:
objectstack-issue-28584Domain:
domain:uiSeat:
domain:ui#1File surface: every package-less
client.layered(...)caller inui/packages/app-shell(at leastviews/studio-design/ObjectListViewInspector.tsx:583-585 andviews/metadata-admin/PermissionMatrixEditor.tsx; the dev enumerates the rest and names them in the report), their tests, and a root.changeset(stop on breach; explain in the report)Container & model: S/M,
mode:thread,model: default tier (dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
a package-less /layers read in Studio's layered-view callers | the server's 409 names the holders and the ?package= prescription (PR #28583) | an admin on a deployment where two packages ship an item of one type and nameThread-read: 6561068138
Premise: holds (at
origin/main7e6e8a46,ObjectListViewInspector.tsx:583-585callsclient.layered('view', viewId)with nopackageId)Serial constraints cleared: seat 4's #28572 (N-19) claims
views/studio-design/**; if its PR touchesObjectListViewInspector.tsx, whichever lands later mergesmain.Pass the owning package the caller already knows from its row or route; where none is known, show the server's refusal sentence instead of reading the 409 as "no artifact". ⛔ No client-side guess of the holder. A test pins the two-holder case.
objectstack-fleet commentedon Nov 1, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jQi39yrLXvXVSvoKfv
os-dev-report
{ "issue": 28584, "status": "done", "branch": "claude/project-thread-0h2wze", "pr": "https://github.com/objectstack-ai/objectstack/pull/28825", "head": "57d352cc", "session": "session_01QsR2jQi39yrLXvXVSvoKfv", "premise_still_valid": true, "measured": "Premise held: package-less client.layered() callers in app-shell were ObjectListViewInspector (2 reads), StudioDesignSurface Interfaces app/leaf/dashboard-published, Data object, Automations flow, PackageOwdOverviewPanel readObjectBodies, PermissionMatrixEditor load + both re-reads, EmbeddedItemEditor parent read, ResourceEditPage reset/publish/discard re-reads. Already scoped: StudioItemTools, StudioCustomizeControls, StudioBundleItemEditor. ADR-0146 D8 is server-side, so a read naming a read-only base serves its declared override. After merging #28747 (merged first), Data and Automations already read at its item-level packageId; the Interfaces leaf read at the base and failed #28572's own 'an added item opens writable' case (save went to the base) until it read at current.addedIn. New on main (#28783): usePublishAllDrafts.holdsNoPublishedLayer reads only package-less drafts (no owner known) and already takes any refusal as 'holds a layer'; left unchanged.", "summary": "Each caller names the package it already reads and saves at (pillar package, item addedIn, door packageId, edit URL ?package= with 'all' folded to none). With no owner known the read names none; PermissionMatrixEditor now rethrows 409 RESOURCE_CONFLICT to its load error strip (the server sentence) instead of catching it to null. No client-side holder guess. Root changeset: @object-ui/app-shell patch with the claim's declaration lines.", "tests": "New: ObjectListViewInspector.twoHolders-28584 (2), PermissionMatrixEditor.twoHolders-28584 (3, incl. ?package=all shows the refusal sentence and no matrix), StudioDesignSurface.twoHolders-28584 (3); oneSurface-28572 +2 (pair-added object and dashboard read at the pair). railLabels and navDeepLink-11153 exact-arg asserts updated. Reverse: 3 sources restored to main -> 8/8 new fail; rethrow ablation -> 1 fail; Interfaces leaf put back to base -> 2/12 oneSurface fail; all restored green. Sweep of every test naming a touched module, locked batches of 60, --maxWorkers=2: 57d352cc 366 files / 2600 tests passed (also 1edfa495 365/2595, 99045462 364/2583, 797eb378 363/2571). app-shell type-check exit 0 at each head. ESLint 0 errors.", "gates": "dispatch-gates --commands: 34 derived, same set at every head; 34/34 exit 0 at 57d352cc (type-check-debt under the lock), incl. check-sdui-manifest and ui scripts/; --ran: 34 run, 0 NOT-MEASURED. PR-body gates on the final body: changeset-no-major --base origin/main 0, adr-0087-registration 0, partof-closing-keyword 0, closing-keyword-parity --body exit 2 binding only 'Fixes #28584' (intended).", "dogfood_battery": "not run: ui-only diff, no server or spec change", "line_budget": "13 files, +699/-20 (most is tests)", "files_changed": [ ".changeset/28584-studio-layered-reads-name-owner.md", "ui/packages/app-shell/src/views/metadata-admin/{EmbeddedItemEditor,PermissionMatrixEditor,ResourceEditPage}.tsx", "ui/packages/app-shell/src/views/studio-design/{ObjectListViewInspector,PackageOwdOverviewPanel,StudioDesignSurface}.tsx", "tests: 3 new twoHolders-28584 files; oneSurface-28572, railLabels, navDeepLink-11153 updated" ], "deviations": [ "Merged main three times (706ac52d, 8afaf12d with #28747, c064d3a2); stopped at 57d352cc on the seat's order.", "EmbeddedItemEditor reads the hosting page's ?package= from window.location (its tests mount no Router), as its save binding does.", "Reviewer request left to the seat (pr_request_reviewers is the seat's hand-off); assignee zhuangjianguo set at pr_create." ], "mcp_calls": "subscribe_pr_activity #28825 only; no GitHub MCP writes", "api_writes": "fleet-write pr_create #28825 (read-back byte-identical, assignee zhuangjianguo); this report comment via post-stamped", "open_questions": [], "out_of_scope_findings": [ "PackageOwdOverviewPanel's getDraft still names no package. reach: a package-less draft read, not a layered read; card scope is /layers.", "EmbeddedItemEditor's draft read and save name no package when the host URL has none. reach: a package-less save of a two-holder name is already refused 409 by the server and the editor shows it." ] }objectstack-fleet commentedon Nov 1, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Landed · 2026-11-01T22:35Z · PR #28825 merged through the merge queue as
1caf6722at 2026-11-01T22:35:11Z (GitHub's clock). ACCEPT 6564759380 at head57d352cc.1caf6722~1)origin/main)studio-design/ObjectListViewInspector.twoHolders-28584.test.tsxexistslayeredPackageIdinmetadata-admin/PermissionMatrixEditor.tsxFixes #28584closed this card;pm:dispatchedcomes off in the same stroke as this note.Generated by Claude Code