Skip to content

Commit 4cfbff8

Browse files
committed
feat(objectstate): add saved resolved accessor and raw-dirty flag
Expose get_saved_resolved_value() to read from the saved resolved snapshot (_saved_resolved) instead of the live resolved cache, so callers can make decisions based on the last committed baseline even when UI edits exist. Add is_raw_dirty as a fast raw-parameter dirty check (parameters vs _saved_parameters), and document the distinction between dirty_fields (resolved live vs saved) and raw dirty state.
1 parent 1d4bb8b commit 4cfbff8

2 files changed

Lines changed: 34 additions & 2 deletions

File tree

docs/state_management.rst

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,23 @@ Saved vs Live
2929
- ``_live_resolved`` represents "on screen" (after every edit and ancestor change).
3030
- ``mark_saved()`` updates saved baselines from current live values.
3131
- ``restore_saved()`` resets working values back to the saved snapshot.
32-
- ``is_dirty()`` compares current parameters to ``_saved_parameters`` to detect unsaved work.
32+
- ``dirty_fields`` tracks where ``_live_resolved`` differs from ``_saved_resolved`` (resolved / inherited view).
33+
- ``is_raw_dirty`` is a fast check for unsaved edits in raw parameters (``parameters`` vs ``_saved_parameters``).
34+
35+
Reading resolved values
36+
~~~~~~~~~~~~~~~~~~~~~~
37+
ObjectState keeps both a *live* resolved snapshot and a *saved* resolved snapshot.
38+
Use the appropriate accessor depending on whether you want to include unsaved edits:
39+
40+
- ``get_resolved_value(name)``: returns the live resolved value from ``_live_resolved`` (includes unsaved edits)
41+
- ``get_saved_resolved_value(name)``: returns the saved resolved value from ``_saved_resolved`` (excludes unsaved edits)
3342

3443
Key methods
3544
~~~~~~~~~~~
3645
- ``mark_saved()``: set current state as the new baseline
3746
- ``restore_saved()``: revert parameters/resolved values to saved baseline
38-
- ``is_dirty()``: true if parameters differ from saved parameters
47+
- ``dirty_fields``: resolved diffs (live vs saved) as a set of dotted field names
48+
- ``is_raw_dirty``: true if raw parameters differ from saved parameters
3949
- ``to_object()``: materialize a concrete object from the current parameters
4050

4151
Lifecycle

src/objectstate/object_state.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,6 +2167,23 @@ def get_resolved_value(self, param_name: str) -> Any:
21672167

21682168
return result
21692169

2170+
def get_saved_resolved_value(self, param_name: str) -> Any:
2171+
"""Get saved resolved value for a field from the saved snapshot.
2172+
2173+
Unlike get_resolved_value() which returns live values (including unsaved edits),
2174+
this returns the saved baseline with inheritance applied. This is useful for
2175+
compilation and other operations that should only consider saved state.
2176+
2177+
Args:
2178+
param_name: Field name to resolve (can be dotted path like 'path_planning_config.well_filter')
2179+
2180+
Returns:
2181+
Saved resolved value from _saved_resolved snapshot
2182+
"""
2183+
# Auto-detect delegate changes before resolving values
2184+
self._check_and_sync_delegate()
2185+
return self._saved_resolved.get(param_name)
2186+
21702187
def get_provenance(self, param_name: str) -> Optional[Tuple[str, type]]:
21712188
"""Get the source scope_id and type for an inherited field value.
21722189
@@ -2504,6 +2521,11 @@ def signature_diff_fields(self) -> Set[str]:
25042521
"""Fields where raw != signature_default."""
25052522
return self._signature_diff_fields
25062523

2524+
@property
2525+
def is_raw_dirty(self) -> bool:
2526+
"""Check if raw parameters differ from saved parameters (not resolved values)."""
2527+
return self.parameters != self._saved_parameters
2528+
25072529
def _compute_dirty_fields(self) -> Set[str]:
25082530
"""Compute dirty set from live vs saved caches."""
25092531
if self._live_resolved is None:

0 commit comments

Comments
 (0)