Repository navigation
fix(metadata-protocol): the draft promotion answers NO_DRAFT before a permission-set name collision - #27825
Conversation
…on set with no draft over a held name Claude-Session: https://claude.ai/code/session_01L6bhgUCizoYWQVJWjhdR6F Co-authored-by: Claude <noreply@anthropic.com>
… only when a draft was read The name-collision judge at the draft promotion ran outside the draftForGate guard its sibling judges use, so a publish with no draft over a name another owner holds answered NAMESPACE_CONFLICT before the repository's NO_DRAFT. Also note on SchemaRegistry.packageHeldSecurityCatalogNames that metadata-protocol reads it by name. Claude-Session: https://claude.ai/code/session_01L6bhgUCizoYWQVJWjhdR6F Co-authored-by: Claude <noreply@anthropic.com>
…omotion-guard-order
📓 Docs Drift CheckThis PR changes 2 package(s): 5 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 25 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 36429185a802dfa0ed0bfad509def0b4b5a5d5b7 && git checkout 36429185a802dfa0ed0bfad509def0b4b5a5d5b7
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 359e935df26ddb067a9a60e2a7f81c5f80256bcb 98bfa9de317fa46d6f62ab3725c20c39e3808cb1 && git checkout -B drift-repro 359e935df26ddb067a9a60e2a7f81c5f80256bcb && git merge --no-ff 98bfa9de317fa46d6f62ab3725c20c39e3808cb1
node scripts/docs-audit/affected-docs.mjs --json 359e935df26ddb067a9a60e2a7f81c5f80256bcb
|
|
domain:server#2 · os-sales · session_01L6bhgUCizoYWQVJWjhdR6F 维护者速读(席位终稿)
席位意见: ACCEPT。按分诊把重名判断放进与兄弟一致的守卫;接受集不变。 席位核对ACCEPT · head
|
domain:server#2 · os-sales · session_01L6bhgUCizoYWQVJWjhdR6F
Requested by Sales · project thread
Fixes #27707
Clause-②: no
Metadata-protocol: none
Skills-docs: none — a refusal-order change with no new authorable capability; nothing in
skills/**teaches the promotion's refusal order.维护者速读
NAMESPACE_CONFLICT(别人的事),而不是NO_DRAFT(调用方自己没草稿);现在先告诉调用方它自己的状态。packages/metadata-protocol/src/protocol.ts(promotion 处if (draftForGate)一处);packages/metadata-protocol/src/protocol.permission-set-name-cross-package.test.ts(新增一条 pin);packages/objectql/src/registry.ts(仅注释)。pnpm --filter @objectstack/metadata-protocol exec vitest run --maxWorkers=2 src/protocol.permission-set-name-cross-package.test.ts,预期 18/18 通过。What changes
packages/metadata-protocol/src/protocol.ts, the draft promotion (publishMetaItem's promotion step, whichpublishPackageDraftsalso goes through): thepermissionSetNameCollisionRefusalcall now sits underif (draftForGate), like its siblingssavedItemNameRefusal,permissionSetOwnerBindingRefusal,defaultRecordPageSaveRefusalandexternalBindingSaveRefusal. Before, it ran in a bare block.NAMESPACE_CONFLICT/ 422 and is nowNO_DRAFT/ 404, the repository's answer fromrepo.promoteDraft.draftForGatenull,repo.promoteDraftgetsexpectedDraftHash: null. It then answersNO_DRAFTwhen no draft row exists, orDraftConflictErrorwhen a draft was saved after the gate read. A promotion with no judged draft never succeeds, before or after this change. With a draft, the same refusals run in the same order.packages/objectql/src/registry.ts: the doc comment of the privatepackageHeldSecurityCatalogNamesnow says thatprotocol-save-door-refusals.ts(registryPackageHoldersOf) reads it by name. Renaming the member means updating that caller andprotocol-permission-set-name-registry-reading.test.ts. This is a comment only.patchfor@objectstack/metadata-protocol. objectql gets none because its change is a comment, so nothing published changes.Tests
publishMetaItem, using the harness the PR harden(metadata): a permission set's name is unique across packages #27535 tests use): B holds the active name and A has no draft. Promoting as A answersNO_DRAFT/ 404 and leaves only B's active row stored.NAMESPACE_CONFLICT/ 422, for bothpublishMetaItemandpublishPackageDrafts.Acceptance notes
Verification
Red before the fix (test committed first, 83e4daa)
Ablation (scripts/ablation-replace.mjs) on the fix commit
Anchor
if (draftForGate) {+ newline +const nameCollisionwas replaced byif (true /* ablation: guard removed */) {, landing x1 to x0, blob 5fb0787b to 2d3ef72c.The first ablation attempt used a replacement that was a substring of the anchor. The tool refused it before running anything and restored the file (blob == HEAD), so that attempt was a no-op and is not counted as a reading.
Local gates at 98bfa9d (after merging origin/main 8f25cee)
@objectstack/metadata-protocoltest: 280 files passed, 4 skipped; 21803 tests passed, 26 skipped. Exit 0.@objectstack/objectqltest: 490/490 files, 9244/9244 tests. Exit 0.--no-inline-configonpackages/metadata-protocolandpackages/objectql: exit 0 each.dispatch-gates --commands: 63 families derived, and every one exits 0.check:dual-build-cjs-loadsandcheck:type-check-debtexited 3 (PREREQUISITE NOT MET) the first time and exited 0 when re-run after the build.--ranreconciliation: 63 run, 0 NOT-MEASURED (a derived zero).git merge-treeagainst fix(metadata-protocol): an object draft's verdict names the namespace-prefix refusal its publish gives (#27444) #27780 (the other open PR onprotocol.ts) is clean. No other open PR touches these files.!and there is no(narrowing)arm.Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_01L6bhgUCizoYWQVJWjhdR6F