Repository navigation
fix(metadata-protocol)!: one sentence for every write over a sealed, package-held name; the inferred create remedy retires - #23626
Conversation
…ackage-held name Claude-Session: https://claude.ai/code/session_01M83DE8c8ySe7XfBTNTxzFd Co-authored-by: Claude <noreply@anthropic.com>
… lost race reads its name-taken refusal Claude-Session: https://claude.ai/code/session_01M83DE8c8ySe7XfBTNTxzFd Co-authored-by: Claude <noreply@anthropic.com>
…d-write sentence Claude-Session: https://claude.ai/code/session_01M83DE8c8ySe7XfBTNTxzFd Co-authored-by: Claude <noreply@anthropic.com>
…o the door's one catch; pin the new engine double Claude-Session: https://claude.ai/code/session_01M83DE8c8ySe7XfBTNTxzFd Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 3 package(s): 7 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 3 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 147 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 b80204e187d996f001fdd99c48d33074115fcafd && git checkout b80204e187d996f001fdd99c48d33074115fcafd
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e611e2bdae9c1adb3d28d0e6b8e0cb4cb2f77c2d 26a5eb92cc60a50d12b7b185ccfe536394d37f2c && git checkout -B drift-repro e611e2bdae9c1adb3d28d0e6b8e0cb4cb2f77c2d && git merge --no-ff 26a5eb92cc60a50d12b7b185ccfe536394d37f2c
node scripts/docs-audit/affected-docs.mjs --json e611e2bdae9c1adb3d28d0e6b8e0cb4cb2f77c2d
|
Claude-Session: https://claude.ai/code/session_01M83DE8c8ySe7XfBTNTxzFd Co-authored-by: Claude <noreply@anthropic.com>
…rue; the sealed-write entry drops its supersession note Claude-Session: https://claude.ai/code/session_01M83DE8c8ySe7XfBTNTxzFd Co-authored-by: Claude <noreply@anthropic.com>
席位核对 — ACCEPT ·
|
Pending release note corrected — maintainer confirmation needed ·
|
Contract reviewServed-tier: Rendered 2026-10-15T07:29Z by the contract reviewer for PR #23626 (card #23577, ruling 6184789291 letter B). Inputs: the card's body and its eleven comments, the PR's body and file list, the net diff of the head against its merge base Tier by face: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: FAIL on ② alone: the |
…ure narrowing BREAKING, with its ADR-0087 disposition Claude-Session: https://claude.ai/code/session_01M83DE8c8ySe7XfBTNTxzFd Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Rendered 2026-10-15T07:46Z by the contract reviewer for PR #23626 (card #23577, ruling 6184789291 letter B), on the head that answers record 6186902880's ② remedy. Inputs: the card's body and its twelve comments, the PR's body and file list, its four comments (record 6186902880 among them, read as an input and not inherited), the net diff of the head against its merge base Tier by face: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS. Every derived judgment is right; the changeset now declares the released public-input-surface narrowing in the form the repo's rule and gate require ( |
Maintainer confirmation recorded · batch #349, the PR line · director seat (summon #42,
|
Fixes #23577
Clause-②: no
Executes ruling
6184789291(batch #348 item 1, letter B) on this card.What changed
packages/metadata-protocol/src/packaged-base-regime.ts,managedItemSealedSentence). For a type with no regime row, every write reads: "'TYPE/NAME' is provided by a managed package and is sealed: it cannot be written here. GET /api/v1/meta/TYPE lists the names in use." This holds for every mode and pin: the console's generic create (mode: 'draft'+If-None-Match: *), a publish-mode*, and unpinned and pinned saves. It gives no create advice and no source-artifact advice. The repository's type door (draft promotion, restore, revert) builds the same sentence. CodeNOT_OVERRIDABLEand status403are unchanged.refusePackagedBaseOverrideasksisSealedManagedItem, a boolean, andisArtifactBackeddiscards thelookupArtifactItemresult.SysMetadataRepository.assertAllowedis told only the write intent. Per the ruling, no lookup is added.sealedWriteinsaveMetaItem; the'create'member ofpackagedBaseRefusal'soperation; thecreatearm ofSealedItemOperation;heldNameSentence; theoperationparameter ofrefusePackagedBaseOverrideand oftenantAuthoredWriteRefusal(it only ever carriedcreate).runtime/src/domains/automation.tspasses'save' | 'delete'and is untouched.## createsection ofpackagedBaseRefusal's docblock, which named the retired position write-through, is replaced by a short "onesave, whatever the write meant" note.GetMetaItemResponseSchema.versionandMetadataConflictErrorSchema.currentVersion(packages/spec/src/api/protocol.zod.ts) now say that anullbesideeditable: falsetakes no save and prescribe no pin for it. These are.describe()texts. The only generated output that moved iscontent/docs/references/api/protocol.mdx, written bycheck:generated --fix(gen:docs).metadataConflictRefusal, "Send that version as If-Match …"), which the clone door relayed througherrorFromThrown. The fix is in the clone door, the producer of the clone caller's response. AMETADATA_CONFLICTfrom its create-only save is rethrown as the door's own name-taken refusal: 409, default codeRESOURCE_CONFLICT, the same sentence a name the catalog already held reads. The/metadoor's conflict sentence is unchanged, so it stays correct for REST callers that sendIf-Match.scripts/engine-double-contract.pinned.json: the three rowscheck:engine-double-contract --writeadds for the newviewcontrol harness..changeset/23577-sealed-write-one-sentence.md(minor: metadata-protocol, with the BREAKING line and its ADR-0087 disposition; patch: runtime, spec)..changeset/23406-sealed-first-draft-remedy.md(unconsumed, the same release) is amended in place so it no longer states the draft/publish remedy split this PR retires; it keeps its first-write-pin409sentence. A falsified entry is corrected in the entry itself, never by an erratum in a later one (AGENTS.md, thepackages/*/CHANGELOG.mdrow), so this PR's changeset carries no "supersedes" line (f0761ed3, the seat's patch round).Pins (ruling item 4)
protocol.sealed-remedy-kind.test.tsis re-pointed. #23565's draft/publish block now asserts the one sentence. Onposition,objectandflow, on both kernel shapes, these five requests all read the identical refusal: console create (draft +*), publish*, unpinned draft, unpinned, pinned. Forpositionandobject, that refusal is the ruled sentence. The registry enumeration holds every row-less reachable type to the ruled sentence, under the 500-character bound with an 88-character name. An overlay control shows that aviewfirst write pinned*over a packaged view lands an overlay row (success: true, one row). The clone door has a new lost-race pin: 409RESOURCE_CONFLICT, the name-taken sentence, and noIf-Match. #23565's REST-door pinrest-meta-sealed-first-draft-remedy.test.tsis re-pointed to the one sentence for the same requests on both kernels (3f354c73).Verification
pnpm --filter '@objectstack/runtime^...' --filter @objectstack/runtime build: exit 0.pnpm --filter … run typecheckfor spec, metadata-protocol, runtime: exit 0.pnpm --filter @objectstack/metadata-protocol test: 236 files passed, 3 skipped; 28418 tests passed.pnpm --filter @objectstack/runtime test: 383 files, 5773 tests passed.pnpm --filter @objectstack/spec test: 678 files, 20728 tests passed.rest-meta-packaged-flow-refusal.test.tsandrest-meta-sealed-first-draft-remedy.test.tspassed 6/6;objectql protocol-commit-history.test.tspassed 30/30. CI Test Core 5/6 caughtrest-meta-sealed-first-draft-remedy.test.tsred at9ec5053e(it still pinned the retired split); it was re-pointed in3f354c73, and the fullrestrun at9ec5053ehad its 284 other files green.f0761ed3(changesets only):check-empty-changeset,check-changeset-no-major,check-adr-0087-registration,pnpm changeset status --since=origin/main,check-closing-keyword-parityandcheck-changeset-fixedexit 0.pnpm --filter @objectstack/spec check:generated: one stale artifact (check:docs); after--fix, re-check green.git diff HEAD(scripts/ablation-replace.mjs):METADATA_CONFLICTto a renamed code): 1 red / 22 green, predicted 1 red.savebranch disabled): 7 red / 6 green, predicted. The row-less pins went red; flow, reach, removal and theviewcontrol stayed green.dispatch-gates --commandslocal union (114 derived plus 5 roster families under my paths), first run at51f2e48b:9ec5053e:check:durability-log-level(the clone's new catch; it now rethrows to the door's oneerrorFromThrown) andcheck:engine-double-contract(ledger rows). Both re-run green.check-engine-split-ratioandcheck-plugin-teardown-shape --self-test(shallow clone);check:skill-examplesandcheck:dual-build-cjs-loads(whole-workspace build absent).Acceptance notes
flow,actionandpermissionkeep their regime sentence. ADR-0126 §2 requires a Regime C refusal to name its sanctioned path, and those sentences carry neither create advice nor source advice.datasourceis origin-gated: its items are code-defined, not package-held, and its sentence states the datasource-admin door's own verdict. The ruling's fact base is the row-less pairmanagedItemSealedSentencebuilt. Raised in the report'sopen_questions.ITEM_LOCKEDnamed-base limb unchanged. When a caller names a read-only base (readOnlyBaseOverrideError), the limb keeps its own code and its "Edit the source artifact and redeploy" remedy. The ruling binds the package-lessNOT_OVERRIDABLErefusal..changeset/23406-sealed-first-draft-remedy.mddescribed the split this PR retires. It is amended in place (see the What changed list), and theCheck Changesetstep-12 red that this produces is the gate's deliberate-correction class, carried to the maintainer byneeds-user-decision(comment 6186537521).'create'member ofpackagedBaseRefusal'soperationandtenantAuthoredWriteRefusal'soperationparameter are a released public input surface (18.0.0-next.0), so the@objectstack/metadata-protocolchangeset carries a**BREAKING**line, an ADR-0087 disposition and the launch-windowminorgrade (contract review 6186902880, ②).RESOURCE_CONFLICTinstead ofMETADATA_CONFLICT. That is the code the door already declares for a taken name.Generated by Claude Code