clearAllModels() clears only the global-id half of the selection state. The EntityRef-keyed half survives, still naming models that no longer exist.
resetViewerState() clears both halves, so the asymmetry only shows on a path that calls clearAllModels() without resetViewerState().
The failing case
GeoreferencingPanel's reloadModelsForAlignment calls clearAllModels() and reloads, without resetViewerState(). After it runs, selectedEntity, selectedEntities, selectedEntitiesSet, activeStorey and selectedModelId still hold refs into models that were just removed. The properties panel stays bound to a model that is gone.
Where it is
On refactor/store-teardown-seam the asymmetry is explicit, in apps/viewer/src/store/slices/selectionSlice.teardown.ts's all-models-cleared arm:
// Only the global-id half, which is what `clearAllModels` has always
// written. The `EntityRef`-keyed half is deliberately absent: adding it
// here would be a behaviour change, not a restructuring, and this
// refactor is not the place to make one.
return {
selectedEntityId: null,
selectedEntityIds: new Set<number>(),
selectedStoreys: new Set<number>(),
};
Before that branch, the same gap lived inside clearAllModels's hand-written payload without being named anywhere. The refactor did not create it and deliberately did not fix it; it made it visible.
Fix
Add the EntityRef-keyed fields to the all-models-cleared arm. It is a behaviour change, so it wants its own test: clear all models with an entity selected and assert the properties panel has nothing bound, driven through the georeference reload path rather than by calling the action directly.
Note for whoever picks this up: the branch's teardown-registry.test.ts pins the emitted key set per scope and fails in both directions, so adding keys to that arm will fail the pin until the pinned list is updated in the same commit. That is intended.
How this was found
During a code review of the store teardown refactor. No code change for it has been made.
clearAllModels()clears only the global-id half of the selection state. TheEntityRef-keyed half survives, still naming models that no longer exist.resetViewerState()clears both halves, so the asymmetry only shows on a path that callsclearAllModels()withoutresetViewerState().The failing case
GeoreferencingPanel'sreloadModelsForAlignmentcallsclearAllModels()and reloads, withoutresetViewerState(). After it runs,selectedEntity,selectedEntities,selectedEntitiesSet,activeStoreyandselectedModelIdstill hold refs into models that were just removed. The properties panel stays bound to a model that is gone.Where it is
On
refactor/store-teardown-seamthe asymmetry is explicit, inapps/viewer/src/store/slices/selectionSlice.teardown.ts'sall-models-clearedarm:Before that branch, the same gap lived inside
clearAllModels's hand-written payload without being named anywhere. The refactor did not create it and deliberately did not fix it; it made it visible.Fix
Add the
EntityRef-keyed fields to theall-models-clearedarm. It is a behaviour change, so it wants its own test: clear all models with an entity selected and assert the properties panel has nothing bound, driven through the georeference reload path rather than by calling the action directly.Note for whoever picks this up: the branch's
teardown-registry.test.tspins the emitted key set per scope and fails in both directions, so adding keys to that arm will fail the pin until the pinned list is updated in the same commit. That is intended.How this was found
During a code review of the store teardown refactor. No code change for it has been made.