Uh oh!
There was an error while loading. Please reload this page.
test(metadata-protocol): measure the object registry write-through plural — dormant, and pinned - #9008
Merged
os-zhuang merged 2 commits intoAug 16, 2026
Conversation
…ng (#8862) Measure the reachability question #8862 was filed with deliberately unanswered: can any `applyRegistryWriteThrough` caller deliver the plural `'objects'` that `applyObjectRegistryMutation` registers under? All four callers fold at the producer — `saveMetaItem` and `rollbackMetaItem` via `canonicalizeMetaRequestType`, `runPublishSideEffects` via `promoteDraftForPublish`'s `PLURAL_TO_SINGULAR` fold (which covers the batch caller that hands it a stored, unfolded type), and `revertCommit` at the call site. Both fold maps resolve `objects` to `object`, so the limb is dormant. The new file drives each of the four routes with a plural at the only place that route accepts one and asserts the spelling that reaches `registerItem`, pins the two fold maps the verdict depends on, and pins the call-site count so a fifth caller cannot be added without re-running the trace. No behaviour change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTKPDRoynY8i3HmdSFUxFj
…ect-registry-mutation-plural
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckNo hand-written docs reference the 0 changed package(s). ✅ |
os-zhuang
marked this pull request as ready for review
August 16, 2026 05:57
Uh oh!
There was an error while loading. Please reload this page.
os-zhuang
deleted the
claude/issue-8862-object-registry-mutation-plural
branch
August 16, 2026 06:15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #8862
Part of, notFixes, deliberately. The card's question is answered below; the card'sdisposition — whether the now-proven-dead tolerance should be deleted — is the PM's call
and is not in this PR. #8862 remains open for that decision.
The question
applyObjectRegistryMutationdoes not merely admit a plural type key, it registers under it:The spelling that arrives is the spelling the registry entry is minted under — the shape
canonicalMetaType's header blames for a real prior bug (one plural read minted a pluralregistry entry; the singular fallback supplying the code-authored items never ran again, so
one overlay row shadowed an entire code-authored listing and survived the DELETE meant to
lift it).
So the limb is either a live registry-shadowing defect or dead tolerance, and the card was
filed without that measurement on purpose: it came out of #8820, where an unmeasured
reachability claim was the whole defect.
The trace — all four producers fold. Verdict: DORMANT
applyObjectRegistryMutationhas exactly one caller (applyRegistryWriteThrough), which hasexactly four. Every one of them delivers an already-folded type:
typeis producedsaveMetaItem(:12625)singularTypeForRepo, aftercanonicalizeMetaRequestTypeat:11869runPublishSideEffects(:13506)args.singularTypefrompromoteDraftForPublish:13351revertCommit(:15673)PLURAL_TO_SINGULAR[it.type] ?? it.type, at the call siterollbackMetaItem(:16014)singularType = request.typeaftercanonicalizeMetaRequestTypeat:15932(#8819)Row 2 is the one #8820 flagged as the structural hazard:
publishPackageDraftsfeedsrunPublishSideEffectsthe draft row's stored type, whichlistDraftsdoes not fold. Thefold that saves it lives one level in, inside
promoteDraftForPublish, so both of thathelper's callers are covered.
Both fold maps resolve the plural, measured rather than read:
No route can deliver
'objects'. The limb is dormant.What this PR adds
packages/metadata-protocol/src/protocol.object-registry-write-through-spelling.test.ts—tests only, no behaviour change. It turns the trace above into a measurement and then into a
guard:
route accepts one (URL spelling for routes 1/2/4, a genuinely plural at-rest row for
revertCommit, whoseit.typeis read from the stored commit item) and assert the spellingthat actually reaches
registerItem;@objectstack/spec;trace, which is the guard the bare
type: stringparameter does not provide.Ablations (predicted before running, per the file header)
Run from the committed state;
protocol.tsrestored withgit checkout claude/issue-8862-object-registry-mutation-plural -- packages/metadata-protocol/src/protocol.tsand confirmed byte-identical (
git diff --exit-code, exit 0).'objects'limb deleted from bothapplyRegistryWriteThroughandapplyObjectRegistryMutationapplyObjectRegistryMutationguard inverted to accept ONLY'objects'Ablation 2 is the evidence that the limb is dead: removing it changes nothing observable.
Ablation 3 is the non-vacuity control, and it doubles as the coverage measurement — the
inverted guard breaks the object registry write-through on every write verb, and the other
106 test files in the package could not tell the two states apart. Only the new file notices.
That is the same gap #8820 measured one helper over.
Verification
All at merged head
b33753634(final commit,origin/mainmerged in first per theconcurrent-editor rule alongside the unmerged #8986).
pnpm --filter @objectstack/metadata-protocol test— 107 files passednode scripts/pm/dispatch-gates.mjs(which added five convention-triggered gates thedispatch list did not name, because the change adds a test file):
check:nul-bytes,check:cross-package-test-inputs(+ theci.ymlscript form),check:durability-log-level,check:filter-alias-parity,check:engine-double-contract,check:where-matcher,check:query-options-erasure,check:type-check-coverage,check:meta-type-normalized,check:stack-collection-maps— all PASSpnpm check:type-check-debt --re-measureon the fully built closure — OK, 33 ledger entriesre-measured, none above its recorded number. The new test file raises no debt.
The whole union was re-run after the
origin/mainmerge, because that merge changed the gatescripts themselves and
scripts/engine-double-contract.baseline.json.No changeset: tests only, nothing user-visible.
Open question for the PM
The tolerance is dead. Removing it is a separate, now-provable step — and #8820's own landed
test header already anticipates it ("the limb is dead ONCE the producer folds — this is what
licenses its removal as a separate, provable follow-up"). My recommendation is in the dev
report; the call is the PM's, and this PR does not pre-empt it.
Generated by Claude Code
Generated by Claude Code