Split out of review on #5231, where it was flagged but is pre-existing and affects the shipped cost path, so it did not belong in that PR.
createStoreAdapter's per-call resolution returns the caller's raw model id:
return { modelId: requested, store: dataStore, editor, mutationView, ownerHistoryId };
while addEntity and buildElement return normalizeMutationModelId(...) — __legacy__ for a legacy public id. entityRefToString serializes modelId unchanged, so the same entity can receive different serialized keys depending on which store method created its ref.
This is verbatim from main before #5231 (git show <pre-5231>:apps/viewer/src/sdk/adapters/store-adapter.ts, the createCostStoreBackend closure); #5231 only extracted that closure so cost and structural share one resolver, which is what made the inconsistency visible.
Fixing it changes the ref identity bim.store.addCost* hands back today, so it wants its own change where it can be reviewed against the cost tests and any consumer that keys off EntityRef.modelId — not a drive-by in a structural PR.
Suggested fix: return normalized from the shared resolver, and check store-adapter-cost-undo.test.ts plus anything comparing entityRefToString output.
Split out of review on #5231, where it was flagged but is pre-existing and affects the shipped cost path, so it did not belong in that PR.
createStoreAdapter's per-call resolution returns the caller's raw model id:while
addEntityandbuildElementreturnnormalizeMutationModelId(...)—__legacy__for a legacy public id.entityRefToStringserializesmodelIdunchanged, so the same entity can receive different serialized keys depending on which store method created its ref.This is verbatim from
mainbefore #5231 (git show <pre-5231>:apps/viewer/src/sdk/adapters/store-adapter.ts, thecreateCostStoreBackendclosure); #5231 only extracted that closure so cost and structural share one resolver, which is what made the inconsistency visible.Fixing it changes the ref identity
bim.store.addCost*hands back today, so it wants its own change where it can be reviewed against the cost tests and any consumer that keys offEntityRef.modelId— not a drive-by in a structural PR.Suggested fix: return
normalizedfrom the shared resolver, and checkstore-adapter-cost-undo.test.tsplus anything comparingentityRefToStringoutput.