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
Filed from the #8284 implementation (PR #8454). #8284's ruling removed the i18n catalog as the thing that discarded a tenant's rename; this is what discards it underneath the catalog, and it is a decision the ruling did not make.
Mechanism
mergeObjectDefinitions (packages/objectql/src/registry.ts) applies an extender's scalars last, onto whatever base it is handed:
and ADR-0029 D9.2 makes the tenant's overlay the base of that fold — resolveObject picks contributors.find(c =%3E c.ownership === 'overlay') ?? ownerContrib and then folds every extend contributor on top. MetadataProtocol does the same on both read exits (foldObjectExtendersFromRegistry, applied to the overlay row in getMetaItem and to effectiveBase in getMetaItemLayered).
So for the showcase account, after a tenant renames the object through the ordinary Studio round-trip:
Layer
label
packaged owner declaration
Account
tenant overlay row (sys_metadata)
Customer ← what the tenant saved, and what ?layers=true shows under overlay
objectExtensions entry (priority: 210)
Account (Success Overlay)
resolved / effective / every read
Account (Success Overlay)
The tenant's value is not in the document any read serves — so no change at the localization layer can put it there. #8284's own table already recorded this without naming it: it measured layers.effective = "Account (Success Overlay)"after the rename, i.e. the extension had beaten the overlay before i18n ran at all.
The 2026-08-13 ruling on #8284 decided catalog vs explicitly-set scalar and was explicit about its mechanism (comparison against the packaged base, no provenance flags through the fold). Extension vs tenant overlay is a different precedence question, it changes ADR-0029 D9.2 behaviour, and Prime Directive #13 puts a recorded decision out of reach of a patch that quietly does the opposite. PR #8454 therefore leaves #8284's second it.fails pin exactly as written, so it flips to green the day this is ruled on, and adds a green case pinning what does hold today (all three reads now agree — on the extension's label, no longer on the packaged catalog string).
⛔ This is not arm B. Nothing here proposes that the fold stop carrying scalars; the question is only which of two authored scalars wins when both exist.
The decision needed
Should a code package's objectExtensions scalar outrank a tenant's own Studio rename of the same object?
A — tenant wins (recommended). Symmetric with the The i18n catalog is resolved ahead of the document, so a tenant's own Studio rename never reaches either /meta/object read — and neither do extension scalar overrides #8284 ruling one layer up, and reachable by the same comparison-based mechanism with no new flags: an extender's scalar applies only while the fold's base still carries the packaged owner's value; a base that has diverged has been authored by the tenant and the extender yields. Real business need: measured, current — the Studio rename answers 200 and is unobservable on every read a form derives from, the sixth "200 that means nothing happened" in this lane. Long-term soundness: one rule ("an explicit override beats a packaged default") at both layers, rather than two layers with opposite instincts. AI-error-resistance: an agent that renames an object and reads it back gets its own value instead of looping on a phantom failure. Cost: a package can no longer relabel an object a tenant has deliberately renamed — which is the point, not a regression.
C — refuse the write instead. Make PUT /meta/object/:name reject (or warn on) a scalar an extension is going to overwrite, so the 200 stops lying. Honest, and much smaller than A, but it removes a capability tenants have today rather than delivering it.
Recommendation: A, implemented as the same comparison the #8284 fix uses, so the two layers share one sentence instead of two rules.
Reproduction
packages/qa/dogfood/test/showcase-object-extension-scalar-divergence.dogfood.test.ts — the it.fails case "SHOULD: a tenant's own rename reaches the reads its forms derive from", on PR #8454's branch (where the catalog no longer interferes, so the case now isolates exactly this defect).
Related
#8284 (parent — the catalog half, ruled and implemented) · #8037 · #8027 / #8045 · ADR-0029 D9.2 / D9.6
Filed from the #8284 implementation (PR #8454). #8284's ruling removed the i18n catalog as the thing that discarded a tenant's rename; this is what discards it underneath the catalog, and it is a decision the ruling did not make.
Mechanism
mergeObjectDefinitions(packages/objectql/src/registry.ts) applies an extender's scalars last, onto whatever base it is handed:and ADR-0029 D9.2 makes the tenant's overlay the base of that fold —
resolveObjectpickscontributors.find(c =%3E c.ownership === 'overlay') ?? ownerContriband then folds everyextendcontributor on top.MetadataProtocoldoes the same on both read exits (foldObjectExtendersFromRegistry, applied to the overlay row ingetMetaItemand toeffectiveBaseingetMetaItemLayered).So for the showcase account, after a tenant renames the object through the ordinary Studio round-trip:
labelAccountsys_metadata)Customer← what the tenant saved, and what?layers=trueshows underoverlayobjectExtensionsentry (priority: 210)Account (Success Overlay)effective/ every readAccount (Success Overlay)The tenant's value is not in the document any read serves — so no change at the localization layer can put it there. #8284's own table already recorded this without naming it: it measured
layers.effective = "Account (Success Overlay)"after the rename, i.e. the extension had beaten the overlay before i18n ran at all.Why this is filed rather than fixed in PR #8454
The 2026-08-13 ruling on #8284 decided catalog vs explicitly-set scalar and was explicit about its mechanism (comparison against the packaged base, no provenance flags through the fold). Extension vs tenant overlay is a different precedence question, it changes ADR-0029 D9.2 behaviour, and Prime Directive #13 puts a recorded decision out of reach of a patch that quietly does the opposite. PR #8454 therefore leaves #8284's second
it.failspin exactly as written, so it flips to green the day this is ruled on, and adds a green case pinning what does hold today (all three reads now agree — on the extension's label, no longer on the packaged catalog string).⛔ This is not arm B. Nothing here proposes that the fold stop carrying scalars; the question is only which of two authored scalars wins when both exist.
The decision needed
Should a code package's
objectExtensionsscalar outrank a tenant's own Studio rename of the same object?/meta/objectread — and neither do extension scalar overrides #8284 ruling one layer up, and reachable by the same comparison-based mechanism with no new flags: an extender's scalar applies only while the fold's base still carries the packaged owner's value; a base that has diverged has been authored by the tenant and the extender yields. Real business need: measured, current — the Studio rename answers200and is unobservable on every read a form derives from, the sixth "200 that means nothing happened" in this lane. Long-term soundness: one rule ("an explicit override beats a packaged default") at both layers, rather than two layers with opposite instincts. AI-error-resistance: an agent that renames an object and reads it back gets its own value instead of looping on a phantom failure. Cost: a package can no longer relabel an object a tenant has deliberately renamed — which is the point, not a regression./meta/objectread — and neither do extension scalar overrides #8284 unfixed, and leaves?layers=truethe only surface that shows a tenant what they saved.PUT /meta/object/:namereject (or warn on) a scalar an extension is going to overwrite, so the200stops lying. Honest, and much smaller than A, but it removes a capability tenants have today rather than delivering it.Recommendation: A, implemented as the same comparison the #8284 fix uses, so the two layers share one sentence instead of two rules.
Reproduction
packages/qa/dogfood/test/showcase-object-extension-scalar-divergence.dogfood.test.ts— theit.failscase "SHOULD: a tenant's own rename reaches the reads its forms derive from", on PR #8454's branch (where the catalog no longer interferes, so the case now isolates exactly this defect).Related
#8284 (parent — the catalog half, ruled and implemented) · #8037 · #8027 / #8045 · ADR-0029 D9.2 / D9.6
Generated by Claude Code