Repository navigation
fix(app-shell): a package-door permission save keeps the pending draft's values - #27080
Conversation
…draft The package door's save re-read the published body as its merge base, so a pending draft's non-authored keys (description, packageId, any key another door wrote) were replaced on the next Studio edit. Read the pending draft through readDraftForSave at the address the save writes and merge onto it when present; a rejected draft read refuses the save like the layered re-read does. Claude-Session: https://claude.ai/code/session_01JQwxba8E9EE7oBM24GbdNZ Co-Authored-By: Claude <noreply@anthropic.com>
席位核对ACCEPT · seat 席位意见:包作用域下保存权限集时,合并基底改为当前待发布草稿(没有草稿才用已发布版本),别的入口写进草稿的
Generated by Claude Code |
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 40637892600 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Requested by Warren · project thread
Fixes #26837
Clause-②: no
Metadata-protocol: none
维护者速读
PermissionMatrixEditor.tsx的doSave包门分支(base一行与草稿读失败判断);新测试PermissionMatrixEditor.packageDoorDraftBase-26837.test.tsx;同文件新增的pendingDraftBody。pnpm --dir ui exec vitest run packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.packageDoorDraftBase-26837.test.tsx,预期 3 passed。What changes
doSave's package-door arm now reads the pending draft through the load's own door,readDraftForSave, at the address the save writes (in parallel with the existinglayeredre-read), and merges this package's slice onto the draft when one exists. With no pending draft the base is the publishedeffective, and the 404 shape keeps the?? payloadbase, both as before.perm.save.rereadFailedtext as the layered refusal (objectui#9420); it never falls back to the published body.readDraftForSaveresolves a rejection as no answer and no pin, while a read that found no draft pinsIf-None-Match: *, so that pair is the failure signal.mergePermissionSliceandEDITOR_AUTHORED_KEYSare unchanged: measured, the key list already takes only the authored facets from the edited body. The defect was the base only.pendingDraftBody, used by the load and by the save base, so the two can't drift apart.packageId) keeps its whole-record live save unchanged.Why
The package door's save writes the package DRAFT, but its merge base was the PUBLISHED body. Keys the editor does not author (
description,packageId, anything another door wrote) came from that base, so one Studio edit replaced a pending draft's values with published ones (or with none). The response was 200 and nothing showed an error.Tests
New
PermissionMatrixEditor.packageDoorDraftBase-26837.test.tsxdrives the real page, load and autosave:description,packageIdand an out-of-scope row differ from published: every non-authored key and the out-of-scope rows reach the wire equal to the draft, and the edited row lands.description, nopackageId, its rows).client.saveis never called, the refusal is on the page's error strip, andgetDraftCalls === 2proves the read ran.Acceptance notes
409 METADATA_CONFLICTand opens the conflict dialog, instead of being merged silently.readDraftForSavehas no explicit failure flag. This PR reads failure from its documented answer/pin pair and stays insidePermissionMatrixEditor.tsx. An explicit flag would be a change toDraftConflictDialog.tsx, which is outside this card's file surface.draftBodyline this PR changes, so whichever lands second may need a small textual merge.Verification
Head
4dd4403f(the fix commitd87310b4plus a merge oforigin/mainatf708cf22).Ablation (two legs, both restored to the HEAD blob)
node scripts/ablation-replace.mjsunder the verify lock, tests import the editor by relative path (no dist leg):fresh?.effective ?? payload: anchor 1 → 0, blob ae1632ba → 55370e9d; the draft-survival test went red withexpected 'Published description' to deeply equal 'Set through the API'(1 failed, 2 passed); restored, blob equals HEAD,git diff HEADempty.git diff HEADempty.Tests and type-check
4dd4403f(and ond87310b4before the merge).permissiontype (Studio Access pillar, list pages, previews, draft conflict): 24/24 files, 392/392 tests passed ond87310b4.pnpm --filter @object-ui/app-shell run type-check(bothtscprojects, tests included): exit 0.pnpm --dir ui run check:new-line-citations: 0 new citations.Derived gates (24 families, all exit 0)
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat4dd4403fderived 24 families; each was run and its exit recorded before any pipe;--ranreconciliation: 24 derived, 24 run, 0 NOT-MEASURED, 0 UNRUN.--tier: no path-derived mandate. Changed lines 281, under the 3000 threshold.No changeset:
@object-ui/app-shellis private (skip-changeset).Human Minimum
packages/specholds no runtime logic. (not touched)pnpm lintpasses. (CI runs the repo lint)main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed. (not touched)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code