@@ -959,10 +959,9 @@ def update_parameter(self, param_name: str, value: Any) -> set[str]:
959959 changed_semantic_params ,
960960 pending_parameters ,
961961 )
962- value_change_notification_fields = self .notification_fields_for_value_changes (
963- changed_param_values ,
964- )
965-
962+ # Establish the pre-mutation resolved authority even for a state that
963+ # has not yet been displayed. Raw edits can preserve the resolved value.
964+ self ._ensure_live_resolved (notify_flash = False )
966965 ObjectStateRegistry .ensure_baseline_snapshot ()
967966
968967 # Update state directly (no type conversion - that's VIEW responsibility)
@@ -1063,14 +1062,11 @@ def update_parameter(self, param_name: str, value: Any) -> set[str]:
10631062 # Increment global token for LiveContextService.collect() cache invalidation
10641063 ObjectStateRegistry .increment_token (notify = False )
10651064
1066- # Recompute live cache, then notify once from the materialized sync layer.
1067- # First-populate states have no prior resolved cache to diff against, so
1068- # raw changed child paths are the notification/navigation authority for
1069- # inline dataclass editors.
1065+ # Raw edits own history/navigation; the resolved delta owns value flashes.
10701066 self ._set_last_changed_values (changed_param_values )
10711067 # Sync materialized state (single point for dirty/sig_diff update + notification)
10721068 self ._sync_materialized_state (
1073- changed_value_fields = changed_paths | value_change_notification_fields
1069+ changed_value_fields = changed_paths
10741070 )
10751071
10761072 # Record snapshot for time-travel (registry-level for coherent system history)
@@ -1091,7 +1087,7 @@ def update_parameter(self, param_name: str, value: Any) -> set[str]:
10911087 if snapshot_field :
10921088 ObjectStateRegistry .record_snapshot (f"edit { snapshot_field } " , self .scope_id )
10931089
1094- return changed_paths | value_change_notification_fields
1090+ return changed_paths
10951091
10961092 def get_resolved_value (self , param_name : str ) -> Any :
10971093 """Get resolved value for a field from the bulk snapshot.
@@ -1975,16 +1971,18 @@ def _sync_materialized_state(
19751971
19761972 Correctness guarantee: All mutation paths call this ONE method.
19771973
1978- Flash behavior: Fires on_resolved_changed for fields that changed value
1979- and fields that changed dirty status. This ensures flash animation
1980- triggers for edits within an already-dirty value, not just clean/dirty
1981- transitions.
1974+ Resolved-value subscribers receive only value changes. Materialized
1975+ state subscribers also receive dirty/signature transitions, including
1976+ saving or changing explicitness without changing the resolved value.
19821977 """
19831978 raw_dirty_changed = self ._update_raw_dirty ()
19841979 dirty_status_changed_fields = self ._update_dirty_fields ()
19851980 sig_diff_changed = self ._update_signature_diff_fields ()
1981+ value_notification_fields = self ._most_specific_notification_fields (
1982+ changed_value_fields or set ()
1983+ )
19861984 notification_fields = self ._most_specific_notification_fields (
1987- dirty_status_changed_fields | ( changed_value_fields or set ())
1985+ dirty_status_changed_fields | value_notification_fields
19881986 )
19891987
19901988 materialized_changed = raw_dirty_changed or bool (notification_fields ) or sig_diff_changed
@@ -1993,7 +1991,7 @@ def _sync_materialized_state(
19931991
19941992 if emit_notifications :
19951993 self ._notify_resolved_changed (
1996- notification_fields ,
1994+ value_notification_fields ,
19971995 context = "_sync_materialized_state" ,
19981996 )
19991997
0 commit comments