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 editors still read a refused (403) draft as "no draft" and can save the published body over it: Interfaces app nav, ResourceEditPage, list view inspector, bundle item, permission matrix, hooks #29148
Filing gate: ② out-of-scope finding, class a, from #29015 (PR #29132; report /mnt/project-files/issue-29015/os-dev-report.json) · filed by domain:ui#1 · ⛔ Not a claim. No grade: triage sets it.
Business reason. A pending draft can carry an audience gate (requiredPermissions) that its author does not hold, for example one written over the API or MCP. The server refuses to read that draft (403), by design. #29015 fixes the Interfaces pillar's dashboard leaves, but every other Studio editor still takes the refusal for "no draft". It opens the published body instead, and its next save sends that body as the draft. That silently drops the gate and every other unpublished change, and publishing then serves the item to everyone.
Measured (code reading at origin/main; not run). After PR #29132, readDraftForSave (ui/packages/app-shell/src/views/metadata-admin/DraftConflictDialog.tsx) returns refused for a 403. Only the Interfaces leaf load reads it. These callers still treat a refusal as absence:
the Interfaces app nav load in StudioDesignSurface.tsx (the app arm refuses an app draft carrying requiredPermissions, the nav buffer seeds from the published layer, and the nav save goes unpinned);
ResourceEditPage;
ObjectListViewInspector (list views carry the same audience gate);
A leaf with no draft, or a readable draft, behaves as before.
Tests. Per caller: a refused draft read installs no buffer and sends no save, while a missing draft still opens the published body. One ablation per caller.
Reader.domain:ui (area:studio). Size M; the callers are disjoint, so triage may split it. Serialize after PR #29132 (#29015).
Dedupe. Searched readDraftForSave, refused 403 draft overwrite. #29113 is the Interfaces pillar's refused-save guard, a different door. No card for these callers.
Claim: PM loop round 2 · 2026-11-02T09:59Z
Session: session_01QsR2jTCMoEXh1SQzWaNp2v (card thread, os-dev); dispatched by seat session session_01QsR2jQjvWkZ7is6GXbC6DB
Account: zhuangjianguo
Branch: claude/project-thread-jr58yz (platform-assigned to the card thread; it can push only this branch)
Worktree: objectstack-issue-29148
Domain: domain:ui
Seat: domain:ui#5
File surface: the readDraftForSave callers in ui/packages/app-shell/src/views/: studio-design/StudioDesignSurface.tsx (Interfaces app nav load only), metadata-admin/ResourceEditPage.tsx, studio-design/ObjectListViewInspector.tsx, studio-design/StudioBundleItemEditor.tsx, metadata-admin/PermissionMatrixEditor.tsx, studio-design/ObjectHooksPanel.tsx; their new tests; a changeset. metadata-admin/DraftConflictDialog.tsx only for a shared helper, with the reason in the report (stop on breach; a split beyond one reviewable PR is proposed to the seat first)
Container & model: M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate; no Fable per the maintainer's standing rule), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: six Studio editors take readDraftForSave's refused (403) read for "no draft" and seed the published body | the platform covers the read (the server refuses it, by design) but not the write: their next save sends the published body as the draft | every author editing an item whose pending draft carries requiredPermissions they lack (API- or MCP-written); publishing then drops the audience gate
Thread-read: 6572677492
Premise: holds (at origin/main2f29c84d: readDraftForSave returns refused since PR #29132 / 3d2e8fd, and only the Interfaces leaf load reads it; callers at ResourceEditPage.tsx:1344,2250, ObjectListViewInspector.tsx:550, PermissionMatrixEditor.tsx:933,1492,1540, ObjectHooksPanel.tsx:238, StudioBundleItemEditor.tsx, and the nav load in StudioDesignSurface.tsx). Triage 6572677492 graded p2. Handed from seat 3 to seat 5 in the project, 09:55Z.
Serial constraints cleared: StudioDesignSurface.tsx is also in open PR #29224 (#29139, seat 3), seat 5's #29113 and seat 2's #28984. This PR opens after #29224 lands and merges main before it opens. ResourceEditPage.tsx is in open PR #29203 (#29079, seat 1, landing queued): no edit there until it lands and main is merged.
Claim amended · 2026-11-02T10:01Z · on the os-dev's measurement (/mnt/project-files/issue-29148/split-proposal.md), before code. This amends claim 6574269114: the split and the file surface. Branch, session, Clause-② and Metadata-protocol are unchanged.
Clause-②: no
Metadata-protocol: none
Split (seat ACCEPTs the proposal): ~1,100–1,500 changed lines over 8 buffer-installing sites is more than one reviewable PR.
Added to the surface (the os-dev's finding, same defect, same file):StudioDesignSurface.tsx object load :7899, object-extension load :7991 and flow load :10286 seed the published body on a 403. They go into PR 2 rather than onto a sibling card, so that the file takes one serial edit, not two. The verdict re-reads at :8239 and :10000 install nothing and stay unchanged.
{
"issue": 29148,
"status": "done",
"branch": "claude/project-thread-jr58yz",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29275",
"pr_part": "PR 1 of 2 (Part of #29148), per claim amendment 6574316242",
"head": "fc165c69",
"session": "session_01QsR2jTCMoEXh1SQzWaNp2v",
"premise_still_valid": true,
"summary": "ObjectListViewInspector, StudioBundleItemEditor, PermissionMatrixEditor (package door load at :933) and ObjectHooksPanel now act on readDraftForSave's refused (403) answer: no buffer is installed, the existing engine.studio.refusal.draftUnreadable key shows with formatMetadataError's text behind Details in each editor's own refusal host, and the autosave has nothing to send. ObjectHooksPanel holds only the refused hook (it stays listed by its published row and pins nothing); a hook known only by its refused draft stays unlisted, as before. PermissionMatrixEditor :1492 and :1540 unchanged per the amendment. No new i18n key, no DraftConflictDialog edit.",
"files_changed": [
".changeset/29148-refused-draft-four-editors.md",
"ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx",
"ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.draftUnreadable-29148.test.tsx",
"ui/packages/app-shell/src/views/studio-design/ObjectHooksPanel.tsx",
"ui/packages/app-shell/src/views/studio-design/ObjectHooksPanel.draftUnreadable-29148.test.tsx",
"ui/packages/app-shell/src/views/studio-design/ObjectListViewInspector.tsx",
"ui/packages/app-shell/src/views/studio-design/ObjectListViewInspector.draftUnreadable-29148.test.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioBundleItemEditor.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioBundleItemEditor.draftUnreadable-29148.test.tsx"
],
"line_budget": "843 changed lines (+826/-17): 162 in the four editors, 669 in four new test files, 12 changeset. Seat's PR 1 estimate was ~600-700; the overage is tests.",
"tests": "4 new files, 10 tests: green at b944048d and again at merged head fc165c69 (Test Files 4 passed (4), Tests 10 passed (10)). Ablation per editor via scripts/ablation-replace.mjs (guard to false and ...): bundle 1 failed/1 passed, listview 1 failed/1 passed, perm 2 failed/1 passed, hooks 1 failed/2 passed; every refused case red, every control green; each restore blob == HEAD, git diff HEAD empty. Nearby sweep: the 80 test files naming the four editors, 2 locked batches at maxWorkers 2: 40/40 files (279 tests) and 40/40 (236 tests). ui vitest run scripts/: 169 passed, 2 skipped files; 4900 passed, 2 skipped tests. app-shell type-check (tsc --noEmit and tsconfig.test.json): 65/65 turbo tasks exit 0 at b944048d and at fc165c69.",
"gates": "dispatch-gates --commands at b944048d: 34 families, all exit 0; --ran reconciliation: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. check-sdui-manifest exit 0 (and --self-test exit 0). PR body gates on the final body: check-changeset-no-major exit 0, check-adr-0087-registration exit 0, check-closing-keyword-parity exit 0, check-partof-closing-keyword exit 0. CI check-runs: in_progress at report time (re-runs are the seat's).",
"dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm",
"deviations": [
"Line count 843 is over the ~600 single-PR guide; tests are 669 of it.",
"Main 47ee57fe merged at fc165c69 before pr_create; incoming commits touch none of the four editors. Re-ran on fc165c69 only app-shell type-check and the 4 new test files; sweep, ui scripts and derived gates are b944048d readings."
],
"mcp_calls": "5 reads: issue_read get x1, issue_read get_comments x3 on #29148; get_session x1. No MCP write.",
"api_writes": "2: fleet-write relay pr_create (run 41432081875, read-back identical, 8106 bytes); this os-dev-report comment via post-stamped. git push is not a REST write.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: PR 2 of this card (seat amendment 6574316242) · StudioDesignSurface.tsx object load, object-extension load and flow load seed the published body on a 403; already added to PR 2's surface, not filed"
],
"next": "PR 2 on this branch after PR 1 lands and #29224 lands (#29203 already landed at 47ee57fe): StudioDesignSurface app nav, object, object-extension and flow loads, ResourceEditPage :1344 and :2250, and optionally StudioRefusalStrip moved to a shared module."
}
{
"issue": 29148,
"status": "done",
"branch": "claude/project-thread-jr58yz",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29380",
"pr_part": "PR 2 of 2 (Fixes #29148), per claim amendment 6574316242; PR 1 #29275 landed at 192c15cf",
"head": "816939aa",
"session": "session_01QsR2jTCMoEXh1SQzWaNp2v",
"premise_still_valid": true,
"summary": "StudioDesignSurface's Interfaces app nav load, Data object load, Data object-extension load (base pair) and Automations flow load, and ResourceEditPage's load (:1344) and post-publish re-read (:2250) now act on readDraftForSave's refused (403) answer: no buffer and no pin are installed, the existing engine.studio.refusal.draftUnreadable key shows with formatMetadataError's text behind Details, and nothing is sent. ResourceEditPage holds a draftRefused state that makes canWrite false (every write withheld) and renders StudioRefusalStrip in its shell in place of the editor. StudioRefusalStrip moved unchanged into its own module (StudioDesignSurface re-exports it). Verdict-only re-reads unchanged. No new i18n key.",
"files_changed": [
".changeset/29148-refused-draft-studio-pillars.md",
"ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx",
"ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.draftUnreadable-29148.test.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.draftUnreadable-29148.test.tsx",
"ui/packages/app-shell/src/views/studio-design/DataPillar.draftUnreadable-29148.test.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioRefusalStrip.tsx"
],
"line_budget": "972 changed lines (+907/-65): 239 source (SDS 118, mostly the strip move; StudioRefusalStrip.tsx 72 moved; ResourceEditPage 49), 721 in three new test files, 12 changeset.",
"tests": "3 new files, 11 tests (6 refused cases, 5 controls): green at bb4c4af9, ee8cf851 and 816939aa. Ablation per site via scripts/ablation-replace.mjs (guard to false and ...): app-nav, object, flow 1 failed/5 passed each; object-extension 1 failed/1 passed; rep-load and rep-publish 1 failed/2 passed each; each site's refused case red, all else green; every restore blob == HEAD. Nearby sweep: the 331 app-shell test files naming StudioDesignSurface, ResourceEditPage, StudioRefusalStrip or a pillar, 9 locked batches at bb4c4af9: 331/331 files, 2533 tests. At ee8cf851: app-shell type-check 65/65, 6 related files 20 tests, ui vitest run scripts/ 169 passed 2 skipped files, 4903 passed 2 skipped tests. eslint clean on new files.",
"gates": "dispatch-gates --commands at ee8cf851: 34 families, all exit 0; --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. check-sdui-manifest exit 0 (and --self-test). PR body gates on the final body: check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity, check-partof-closing-keyword all exit 0. CI: not yet reported at report time (re-runs are the seat's).",
"dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm",
"deviations": [
"Line count 972 is over the ~600 single-PR guide; tests are 721 of it.",
"Final merge 816939aa brought 11 main commits touching none of the changed files; only the 3 new test files were re-run on it. Sweep is a bb4c4af9 reading; type-check, gates and ui scripts are ee8cf851 readings.",
"The four PR 1 editors keep their own refusal hosts; only ResourceEditPage was moved onto the shared StudioRefusalStrip."
],
"mcp_calls": "1 read: pull_request_read get on #29380. No MCP write.",
"api_writes": "2: fleet-write relay pr_create (run 41453377449, read-back identical, 9292 bytes); this os-dev-report comment via post-stamped. git push is not a REST write.",
"open_questions": [],
"out_of_scope_findings": [],
"serial_note": "Seat note on #29311 (claude/project-thread-oritte): this PR's StudioDesignSurface hunks are the strip move (~L700), the app nav load effect (~L4831), the object/extension loads (~L7897, ~L7991) and the flow load (~L10294); none in the InterfacesPillar leaf load or the Preview element.",
"next": "Seat lands #29380; card closes on merge."
}
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p2 (priority added) · 2026-11-02T08:34Z
⛔ Not a claim.
ResourceEditPage, list view) read a refused (403) pending draft as "no draft", so they can save the published body over it. Sibling of Studio: a dashboard draft whose requiredPermissions the author does not hold reads 403, Studio treats that as "no draft", and the next autosave overwrites the draft without the key #29015, and the same class of silent overwrite. Not an authorization hole: the server still refuses the read. p2. Read Studio: a dashboard draft whose requiredPermissions the author does not hold reads 403, Studio treats that as "no draft", and the next autosave overwrites the draft without the key #29015's fix before claiming, so the editors share one refusal reading.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:ui#5 · zhuangjianguo · session_01QsR2jQjvWkZ7is6GXbC6DB
Claim: PM loop round 2 · 2026-11-02T09:59Z
Session:
session_01QsR2jTCMoEXh1SQzWaNp2v(card thread, os-dev); dispatched by seat sessionsession_01QsR2jQjvWkZ7is6GXbC6DBAccount:
zhuangjianguoBranch:
claude/project-thread-jr58yz(platform-assigned to the card thread; it can push only this branch)Worktree:
objectstack-issue-29148Domain:
domain:uiSeat:
domain:ui#5File surface: the
readDraftForSavecallers inui/packages/app-shell/src/views/:studio-design/StudioDesignSurface.tsx(Interfaces app nav load only),metadata-admin/ResourceEditPage.tsx,studio-design/ObjectListViewInspector.tsx,studio-design/StudioBundleItemEditor.tsx,metadata-admin/PermissionMatrixEditor.tsx,studio-design/ObjectHooksPanel.tsx; their new tests; a changeset.metadata-admin/DraftConflictDialog.tsxonly for a shared helper, with the reason in the report (stop on breach; a split beyond one reviewable PR is proposed to the seat first)Container & model: M,
mode:thread,model: default tier (dispatch-gates --tier: no path-derived mandate; no Fable per the maintainer's standing rule),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
six Studio editors take readDraftForSave's refused (403) read for "no draft" and seed the published body | the platform covers the read (the server refuses it, by design) but not the write: their next save sends the published body as the draft | every author editing an item whose pending draft carries requiredPermissions they lack (API- or MCP-written); publishing then drops the audience gateThread-read: 6572677492
Premise: holds (at
origin/main2f29c84d:readDraftForSavereturnsrefusedsince PR #29132 / 3d2e8fd, and only the Interfaces leaf load reads it; callers atResourceEditPage.tsx:1344,2250,ObjectListViewInspector.tsx:550,PermissionMatrixEditor.tsx:933,1492,1540,ObjectHooksPanel.tsx:238,StudioBundleItemEditor.tsx, and the nav load inStudioDesignSurface.tsx). Triage 6572677492 graded p2. Handed from seat 3 to seat 5 in the project, 09:55Z.Serial constraints cleared:
StudioDesignSurface.tsxis also in open PR #29224 (#29139, seat 3), seat 5's #29113 and seat 2's #28984. This PR opens after #29224 lands and merges main before it opens.ResourceEditPage.tsxis in open PR #29203 (#29079, seat 1, landing queued): no edit there until it lands and main is merged.objectstack-fleet commentedon Nov 2, 2026
domain:ui#5 · zhuangjianguo · session_01QsR2jQjvWkZ7is6GXbC6DB
Claim amended · 2026-11-02T10:01Z · on the os-dev's measurement (/mnt/project-files/issue-29148/split-proposal.md), before code. This amends claim 6574269114: the split and the file surface. Branch, session, Clause-② and Metadata-protocol are unchanged.
Clause-②: no
Metadata-protocol: none
ObjectListViewInspector.tsx,StudioBundleItemEditor.tsx,PermissionMatrixEditor.tsxload at :933,ObjectHooksPanel.tsx(a partial refusal holds only the refused hook).PermissionMatrixEditor:1492 already refuses the save, and :1540 is a verdict-only re-read, so both stay unchanged. Each editor shows the existingengine.studio.refusal.draftUnreadablekey in its own refusal host, with the server sentence behind Details. No new key.StudioDesignSurface.tsxInterfaces app nav load,ResourceEditPage.tsx:1344 and :2250, plus the three loads below. It may moveStudioRefusalStripout ofStudioDesignSurface.tsxinto a shared module, so all editors draw the one component.StudioDesignSurface.tsxobject load :7899, object-extension load :7991 and flow load :10286 seed the published body on a 403. They go into PR 2 rather than onto a sibling card, so that the file takes one serial edit, not two. The verdict re-reads at :8239 and :10000 install nothing and stay unchanged.objectstack-fleet commentedon Nov 2, 2026
domain:ui#5 · zhuangjianguo · session_01QsR2jTCMoEXh1SQzWaNp2v
os-dev-report
{ "issue": 29148, "status": "done", "branch": "claude/project-thread-jr58yz", "pr": "https://github.com/objectstack-ai/objectstack/pull/29275", "pr_part": "PR 1 of 2 (Part of #29148), per claim amendment 6574316242", "head": "fc165c69", "session": "session_01QsR2jTCMoEXh1SQzWaNp2v", "premise_still_valid": true, "summary": "ObjectListViewInspector, StudioBundleItemEditor, PermissionMatrixEditor (package door load at :933) and ObjectHooksPanel now act on readDraftForSave's refused (403) answer: no buffer is installed, the existing engine.studio.refusal.draftUnreadable key shows with formatMetadataError's text behind Details in each editor's own refusal host, and the autosave has nothing to send. ObjectHooksPanel holds only the refused hook (it stays listed by its published row and pins nothing); a hook known only by its refused draft stays unlisted, as before. PermissionMatrixEditor :1492 and :1540 unchanged per the amendment. No new i18n key, no DraftConflictDialog edit.", "files_changed": [ ".changeset/29148-refused-draft-four-editors.md", "ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx", "ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.draftUnreadable-29148.test.tsx", "ui/packages/app-shell/src/views/studio-design/ObjectHooksPanel.tsx", "ui/packages/app-shell/src/views/studio-design/ObjectHooksPanel.draftUnreadable-29148.test.tsx", "ui/packages/app-shell/src/views/studio-design/ObjectListViewInspector.tsx", "ui/packages/app-shell/src/views/studio-design/ObjectListViewInspector.draftUnreadable-29148.test.tsx", "ui/packages/app-shell/src/views/studio-design/StudioBundleItemEditor.tsx", "ui/packages/app-shell/src/views/studio-design/StudioBundleItemEditor.draftUnreadable-29148.test.tsx" ], "line_budget": "843 changed lines (+826/-17): 162 in the four editors, 669 in four new test files, 12 changeset. Seat's PR 1 estimate was ~600-700; the overage is tests.", "tests": "4 new files, 10 tests: green at b944048d and again at merged head fc165c69 (Test Files 4 passed (4), Tests 10 passed (10)). Ablation per editor via scripts/ablation-replace.mjs (guard to false and ...): bundle 1 failed/1 passed, listview 1 failed/1 passed, perm 2 failed/1 passed, hooks 1 failed/2 passed; every refused case red, every control green; each restore blob == HEAD, git diff HEAD empty. Nearby sweep: the 80 test files naming the four editors, 2 locked batches at maxWorkers 2: 40/40 files (279 tests) and 40/40 (236 tests). ui vitest run scripts/: 169 passed, 2 skipped files; 4900 passed, 2 skipped tests. app-shell type-check (tsc --noEmit and tsconfig.test.json): 65/65 turbo tasks exit 0 at b944048d and at fc165c69.", "gates": "dispatch-gates --commands at b944048d: 34 families, all exit 0; --ran reconciliation: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. check-sdui-manifest exit 0 (and --self-test exit 0). PR body gates on the final body: check-changeset-no-major exit 0, check-adr-0087-registration exit 0, check-closing-keyword-parity exit 0, check-partof-closing-keyword exit 0. CI check-runs: in_progress at report time (re-runs are the seat's).", "dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm", "deviations": [ "Line count 843 is over the ~600 single-PR guide; tests are 669 of it.", "Main 47ee57fe merged at fc165c69 before pr_create; incoming commits touch none of the four editors. Re-ran on fc165c69 only app-shell type-check and the 4 new test files; sweep, ui scripts and derived gates are b944048d readings." ], "mcp_calls": "5 reads: issue_read get x1, issue_read get_comments x3 on #29148; get_session x1. No MCP write.", "api_writes": "2: fleet-write relay pr_create (run 41432081875, read-back identical, 8106 bytes); this os-dev-report comment via post-stamped. git push is not a REST write.", "open_questions": [], "out_of_scope_findings": [ "carrier: PR 2 of this card (seat amendment 6574316242) · StudioDesignSurface.tsx object load, object-extension load and flow load seed the published body on a 403; already added to PR 2's surface, not filed" ], "next": "PR 2 on this branch after PR 1 lands and #29224 lands (#29203 already landed at 47ee57fe): StudioDesignSurface app nav, object, object-extension and flow loads, ResourceEditPage :1344 and :2250, and optionally StudioRefusalStrip moved to a shared module." }objectstack-fleet commentedon Nov 2, 2026
domain:ui#5 · zhuangjianguo · session_01QsR2jTCMoEXh1SQzWaNp2v
os-dev-report
{ "issue": 29148, "status": "done", "branch": "claude/project-thread-jr58yz", "pr": "https://github.com/objectstack-ai/objectstack/pull/29380", "pr_part": "PR 2 of 2 (Fixes #29148), per claim amendment 6574316242; PR 1 #29275 landed at 192c15cf", "head": "816939aa", "session": "session_01QsR2jTCMoEXh1SQzWaNp2v", "premise_still_valid": true, "summary": "StudioDesignSurface's Interfaces app nav load, Data object load, Data object-extension load (base pair) and Automations flow load, and ResourceEditPage's load (:1344) and post-publish re-read (:2250) now act on readDraftForSave's refused (403) answer: no buffer and no pin are installed, the existing engine.studio.refusal.draftUnreadable key shows with formatMetadataError's text behind Details, and nothing is sent. ResourceEditPage holds a draftRefused state that makes canWrite false (every write withheld) and renders StudioRefusalStrip in its shell in place of the editor. StudioRefusalStrip moved unchanged into its own module (StudioDesignSurface re-exports it). Verdict-only re-reads unchanged. No new i18n key.", "files_changed": [ ".changeset/29148-refused-draft-studio-pillars.md", "ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx", "ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.draftUnreadable-29148.test.tsx", "ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx", "ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.draftUnreadable-29148.test.tsx", "ui/packages/app-shell/src/views/studio-design/DataPillar.draftUnreadable-29148.test.tsx", "ui/packages/app-shell/src/views/studio-design/StudioRefusalStrip.tsx" ], "line_budget": "972 changed lines (+907/-65): 239 source (SDS 118, mostly the strip move; StudioRefusalStrip.tsx 72 moved; ResourceEditPage 49), 721 in three new test files, 12 changeset.", "tests": "3 new files, 11 tests (6 refused cases, 5 controls): green at bb4c4af9, ee8cf851 and 816939aa. Ablation per site via scripts/ablation-replace.mjs (guard to false and ...): app-nav, object, flow 1 failed/5 passed each; object-extension 1 failed/1 passed; rep-load and rep-publish 1 failed/2 passed each; each site's refused case red, all else green; every restore blob == HEAD. Nearby sweep: the 331 app-shell test files naming StudioDesignSurface, ResourceEditPage, StudioRefusalStrip or a pillar, 9 locked batches at bb4c4af9: 331/331 files, 2533 tests. At ee8cf851: app-shell type-check 65/65, 6 related files 20 tests, ui vitest run scripts/ 169 passed 2 skipped files, 4903 passed 2 skipped tests. eslint clean on new files.", "gates": "dispatch-gates --commands at ee8cf851: 34 families, all exit 0; --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. check-sdui-manifest exit 0 (and --self-test). PR body gates on the final body: check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity, check-partof-closing-keyword all exit 0. CI: not yet reported at report time (re-runs are the seat's).", "dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm", "deviations": [ "Line count 972 is over the ~600 single-PR guide; tests are 721 of it.", "Final merge 816939aa brought 11 main commits touching none of the changed files; only the 3 new test files were re-run on it. Sweep is a bb4c4af9 reading; type-check, gates and ui scripts are ee8cf851 readings.", "The four PR 1 editors keep their own refusal hosts; only ResourceEditPage was moved onto the shared StudioRefusalStrip." ], "mcp_calls": "1 read: pull_request_read get on #29380. No MCP write.", "api_writes": "2: fleet-write relay pr_create (run 41453377449, read-back identical, 9292 bytes); this os-dev-report comment via post-stamped. git push is not a REST write.", "open_questions": [], "out_of_scope_findings": [], "serial_note": "Seat note on #29311 (claude/project-thread-oritte): this PR's StudioDesignSurface hunks are the strip move (~L700), the app nav load effect (~L4831), the object/extension loads (~L7897, ~L7991) and the flow load (~L10294); none in the InterfacesPillar leaf load or the Preview element.", "next": "Seat lands #29380; card closes on merge." }