Repository navigation
Description
Observation-class finding, filed from #7221 as the consequence that card's bare-key ruling deliberately left open. Unassigned, deliberately not queued.
Where it comes from
#7221 added SchemaRegistry.unregisterItemsByPackage(packageId) — the package-addressed removal verb for the generic metadata map — and wired it into MetadataFacade.unregisterPackage and SchemaRegistry.uninstallPackage.
The ruling applied there was the non-destructive branch, made by the engine-core seat and carried into dispatch: scope the removal to composite ${packageId}:${name} keys only, and leave ADR-0005 bare-key runtime/DB overlays untouched. The reasoning stands and this card does not re-open it — a bare key carries no package provenance and is the runtime face of a tenant-authored sys_metadata row, so an uninstall deleting it would take a tenant's own customization along with the package it merely overlaid. Nobody authorised that delete.
The consequence that ruling leaves
An overlay whose base has just been uninstalled now layers over nothing.
unregisterItemsByPackage makes this LOUD rather than silent — the house pattern from ADR-0029 D9.5's orphan-overlay violation ("re-install the package that owns it, or delete the sys_metadata row") and from unregisterObjectsByPackage's refusal. It console.warns naming every orphaned overlay and returns them as orphanedOverlays so a caller can act.
But nothing acts on them today:
- Neither caller reads the returned
orphanedOverlays.uninstallPackagereturnsboolean;MetadataFacade.unregisterPackagereturnsvoid(itsIMetadataServicesignature). - The warning goes to
console, so in a server process it lands in logs an operator may never correlate with the uninstall. - The orphaned bare-key item stays fully resolvable through
getItem/listItems— which is correct (it is the tenant's data), but it now presents as a first-class item of a type whose package is gone, with no marker saying so.
Note the asymmetry with the object side, which is deliberate and is not the thing to copy: ADR-0029 D9.7 has an object overlay layer leave with the base it layers over, and that is safe precisely because the layer is a runtime projection of a sys_metadata row the removal does not touch — a re-install re-hydrates it. A bare-key generic entry is the other way round: it is the runtime face of that row, with no separate contributor list holding a durable copy, so the same rule applied here would lose the edit.
What is actually undecided
Not "delete or keep" — that is settled. The open question is what the platform owes the operator afterwards:
- Surface it in the uninstall envelope. Package disable and uninstall never reach the metadata/data layer: a disabled package's objects still serve rows, and uninstall leaves 7 orphaned
sys_metadatarows #7557 landed an honest uninstall envelope; orphaned overlays are exactly the kind of thing it exists to report. Needs a path from the registry return value up to whatever composes that envelope. - Mark the orphan on the item. A
_diagnostics-style badge (the read path already carries one for spec-invalid rows) so Studio can show "the package that owned this is no longer installed". - A bootstrap assertion, mirroring
assertSingleOwnerPerObject, that names generic-map orphans at boot rather than only at uninstall time. - Nothing beyond the warning — accept it as an operator-log concern. Cheapest, and defensible if orphaned generic overlays turn out to be rare in practice; that is a measurement nobody has made.
Option 1 is the one that touches the persisted/data-plane faces of uninstall, so it wants sequencing against that family rather than being folded into a registry-only change.
Adjacency
The three faces of uninstall, all landed or in flight: #7557 (registry/data-plane enforcement + the honest envelope), #7705 (persisted sys_metadata rows), #7221 (this one's parent — the in-memory registry). ⛔ Distinct mechanisms; this card should not reach into them without a ruling on which face owns the orphan report.
Activity
hotlong commentedon Aug 12, 2026
Triage:
finding(held), routeddomain:metadata(the likely owner is the uninstall envelope face —MetadataFacade/ #7557's family — and the uninstall-consequence cards #7780 / #7932 live in this lane), type Task.sys_metadatarows #7557 /protocol.deletePackagefinds zerosys_metadatarows the data plane finds 3 of — uninstall leaves orphaned rows (persistence half of #7557) #7705 family, ⛔ not be folded into a registry-only change.uninstallPackageunregisters the namespace BEFORE the verb that can refuse — a rejected uninstall leaves the package half-mutated #7970 (refusal-path ordering, engine-core) is adjacent and can batch with the same family — noted on both cards.本评论来自分诊座位(scheduled session
session_0199Rq2oEnNNRmdhmWwqUwvQ),不构成认领。Generated by Claude Code
hotlong commentedon Aug 12, 2026
Findings-round disposition: hold as
findingkept; re-routeddomain:metadata→domain:engine-core(anchoring rule: every candidate landing surface ispackages/objectql—registry.ts:2141/:2607,metadata-facade.ts:287; the two sibling cards on this exact file, #7221 and #7970, are both engine-core).Premise re-verified end-to-end on
origin/main:unregisterItemsByPackagereturns{removed, orphanedOverlays}and console.warns, and BOTH callers discard the value. Sequencing context has shifted: the uninstall family has now LANDED (#7705 via PR #7771, #7557 closed, parent #7221 closed via PR #7961), so nothing upstream blocks — what still holds this card is its own open half ("what does the platform owe the operator", with a candid do-nothing option) and zero occurrence data.Restart condition: #7970 (promoted this round, same file) — its dev may surface the orphan report as a cheap declared rider, which would supply the shape; or the first measured/reported occurrence of an orphaned bare-key overlay in practice.
本评论来自分诊座位(scheduled session
session_01DLzE5XVRASxFotEU1h9cjH),不构成认领。Generated by Claude Code
hotlong commentedon Aug 12, 2026
Finding-grading round: closed, not planned.
The card's own re-grade trigger fired and produced nothing: #7970 landed (PR #8105) without picking up the orphan report, and the whole uninstall family (#7557/#7705/#7221) is landed, so there is no event left to wait for. The
console.warn+ returnedorphanedOverlayslist stay onmain, so the information has a durable home. Re-file on the first measured orphaned bare-key overlay, or fold into a future uninstall-envelope card.Generated by Claude Code
fix(objectql): uninstalling a package removes the non-object metadata…