Skip to content

feat: Add the override marker to the models and mark evaluations - #526

Draft
kinyoklion wants to merge 1 commit into
rlamb/overrides-python-filedata-reloaderfrom
rlamb/overrides-python-model-marker
Draft

kinyoklion wants to merge 1 commit into
rlamb/overrides-python-filedata-reloaderfrom
rlamb/overrides-python-model-marker

Conversation

@kinyoklion

@kinyoklion kinyoklion commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

Summary

This is the second step of the flag overrides port described by the OVERRIDE specification. It is based on the shared file data branch because the phases are stacked; retarget to feat/overrides once that branch merges.

The FeatureFlag and Segment models gain an override marker, is_override. The SDK represents stored entities with typed model classes distinct from their JSON form, so the marker is carried on the type and never in the JSON: to_json_dict(), the data kind encoder, and ModelEncoder produce the same output for a marked and an unmarked entity, and a persistent store never sees it. with_override_marker() returns a marked shallow copy that shares the definition and leaves the source unmarked, so a source can retain and resupply its entities. Only the SDK components that manage override entries (added in the next step) set the marker.

The evaluator marks an evaluation as override-affected when any definition it reads carries the marker: the evaluated flag, a prerequisite flag at any depth, or a segment consulted during clause matching. A read counts whether or not the segment matches, including through a negated clause and through a segment referenced by another segment's rule. A definition that cannot be resolved contributes nothing, because nothing was read. The marking propagates upward only: a prerequisite is an evaluation in its own right, its record reflects only the definitions its own subtree read, so an unaffected prerequisite inside a marked evaluation stays unmarked and a marked prerequisite does not mark a sibling. An evaluation that fails with an error reason, including a prerequisite cycle, is still marked when it read an override definition.

The marking is reported in two places that always agree: the overrideAffected indicator on the evaluation reason, present only when true so an unaffected reason serializes exactly as before, and EvalResult.override_affected, which the client and event processing read in the following steps. The AsyncEvaluator receives the same changes.

Tests cover each marking condition for both evaluators (flag off, fallthrough, and rule match; plain evaluations; malformed flag and prerequisite cycle errors; prerequisite records at depth one and two; unaffected sibling and downward non-propagation; segment reads with and without a match, negated, nested, and through a prerequisite; missing definitions; scalar and indicator agreement) and the model marker (default, marked copy, never serialized, shared definition).

SDK-3250


Note

Overview
Adds experimental flag-override tracking on FeatureFlag and Segment via an in-memory is_override marker (with_override_marker() shallow copies; serialization unchanged).

Sync and async evaluators set EvalResult.override_affected when the evaluated flag, any prerequisite subtree, or any read segment definition is marked, including non-matching or negated segment clauses and error paths. Marking merges upward from prerequisites only; unaffected sibling prereq events stay unmarked. When true, evaluation reasons gain overrideAffected (omitted when false).

Public EvaluationDetail docs describe the new reason field. Tests cover model marker behavior and evaluator marking rules for both evaluators.

Reviewed by Cursor Bugbot for commit 0013c0e. Bugbot is set up for automated code reviews on this repo. Configure here.

@kinyoklion
kinyoklion force-pushed the rlamb/overrides-python-model-marker branch from 60d6f22 to 34322d8 Compare September 25, 2026 22:11
@kinyoklion
kinyoklion force-pushed the rlamb/overrides-python-filedata-reloader branch from c478bd1 to 7e64242 Compare September 28, 2026 20:28
@kinyoklion
kinyoklion force-pushed the rlamb/overrides-python-model-marker branch from 34322d8 to ee313c1 Compare September 28, 2026 20:28
@kinyoklion
kinyoklion force-pushed the rlamb/overrides-python-filedata-reloader branch from 7e64242 to ee3234c Compare September 30, 2026 20:31
@kinyoklion
kinyoklion force-pushed the rlamb/overrides-python-model-marker branch 2 times, most recently from 2c70075 to 5f738a6 Compare October 1, 2026 23:43
Adds an override marker to the FeatureFlag and Segment models. The marker is
an attribute of the model type, never part of the JSON representation, so
serializing an entity or writing it to a persistent store never carries it.
A marked shallow copy is produced with with_override_marker(), which leaves
the source entity unmarked and shares its definition.

The evaluator marks an evaluation as override-affected when any definition
it reads carries the marker: the evaluated flag, a prerequisite at any depth,
or a segment consulted during rule matching, including a segment that does
not match and a segment referenced by another segment. The marking propagates
upward only. A prerequisite's own record reflects the definitions its subtree
read, so an unaffected prerequisite inside a marked evaluation is not marked
and a marked prerequisite does not mark a sibling. An evaluation that fails
with an error reason is still marked when it read an override definition.

The marking appears on the evaluation reason as the overrideAffected
indicator, present only when true, and on EvalResult.override_affected for
the client and event processing. The async evaluator mirrors the sync one.
@kinyoklion
kinyoklion force-pushed the rlamb/overrides-python-model-marker branch from 5f738a6 to 0013c0e Compare October 3, 2026 01:18
@kinyoklion

Copy link
Copy Markdown
Member Author

bugbot review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 0013c0e. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant