fix(domain): correct invariant precedence chain to include action scope #9240

Merged
HAL9000 merged 1 commits from fix/invariant-precedence-chain-action-scope into master 2026-06-03 03:04:49 +00:00
2 changed files with 29 additions and 10 deletions
+28 -10
View File
@@ -69,12 +69,13 @@ class MergeSmallSuite:
def setup(self) -> None:
"""Create small invariant lists."""
self.plan = _make_invariants(InvariantScope.PLAN, 3)
self.action = _make_invariants(InvariantScope.ACTION, 2)
self.project = _make_invariants(InvariantScope.PROJECT, 5)
self.global_invs = _make_invariants(InvariantScope.GLOBAL, 5)
def time_merge_small(self) -> None:
"""Benchmark merge with ~13 invariants."""
merge_invariants(self.plan, [], self.project, self.global_invs)
"""Benchmark merge with ~15 invariants."""
merge_invariants(self.plan, self.action, self.project, self.global_invs)
class MergeMediumSuite:
@@ -83,12 +84,13 @@ class MergeMediumSuite:
def setup(self) -> None:
"""Create medium invariant lists."""
self.plan = _make_invariants(InvariantScope.PLAN, 10)
self.action = _make_invariants(InvariantScope.ACTION, 5)
self.project = _make_invariants(InvariantScope.PROJECT, 20)
self.global_invs = _make_invariants(InvariantScope.GLOBAL, 20)
def time_merge_medium(self) -> None:
"""Benchmark merge with ~50 invariants."""
merge_invariants(self.plan, [], self.project, self.global_invs)
"""Benchmark merge with ~55 invariants."""
merge_invariants(self.plan, self.action, self.project, self.global_invs)
class MergeLargeSuite:
@@ -97,12 +99,13 @@ class MergeLargeSuite:
def setup(self) -> None:
"""Create large invariant lists."""
self.plan = _make_invariants(InvariantScope.PLAN, 50)
self.action = _make_invariants(InvariantScope.ACTION, 25)
self.project = _make_invariants(InvariantScope.PROJECT, 100)
self.global_invs = _make_invariants(InvariantScope.GLOBAL, 100)
def time_merge_large(self) -> None:
"""Benchmark merge with ~250 invariants."""
merge_invariants(self.plan, [], self.project, self.global_invs)
"""Benchmark merge with ~275 invariants."""
merge_invariants(self.plan, self.action, self.project, self.global_invs)
class MergeDeduplicationSuite:
@@ -118,6 +121,14 @@ class MergeDeduplicationSuite:
)
for i in range(20)
]
self.action = [
Invariant(
text=f"Shared constraint {i}",
scope=InvariantScope.ACTION,
source_name="action-001",
)
for i in range(20)
]
self.project = [
Invariant(
text=f"Shared constraint {i}",
@@ -136,8 +147,8 @@ class MergeDeduplicationSuite:
]
def time_merge_dedup(self) -> None:
"""Benchmark merge with 60 invariants, all duplicates."""
merge_invariants(self.plan, [], self.project, self.global_invs)
"""Benchmark merge with 80 invariants, all duplicates."""
merge_invariants(self.plan, self.action, self.project, self.global_invs)
class InvariantSetMergeSuite:
@@ -146,12 +157,13 @@ class InvariantSetMergeSuite:
def setup(self) -> None:
"""Create invariant lists."""
self.plan = _make_invariants(InvariantScope.PLAN, 5)
self.action = _make_invariants(InvariantScope.ACTION, 3)
self.project = _make_invariants(InvariantScope.PROJECT, 10)
self.global_invs = _make_invariants(InvariantScope.GLOBAL, 10)
def time_invariant_set_merge(self) -> None:
"""Benchmark InvariantSet.merge()."""
InvariantSet.merge(self.plan, [], self.project, self.global_invs)
InvariantSet.merge(self.plan, self.action, self.project, self.global_invs)
class ServiceEffectiveSuite:
@@ -164,9 +176,15 @@ class ServiceEffectiveSuite:
self.service.add_invariant(f"Global {i}", InvariantScope.GLOBAL, "system")
for i in range(10):
self.service.add_invariant(f"Project {i}", InvariantScope.PROJECT, "myapp")
for i in range(5):
self.service.add_invariant(
f"Action {i}", InvariantScope.ACTION, "action-001"
)
for i in range(5):
self.service.add_invariant(f"Plan {i}", InvariantScope.PLAN, "plan-001")
def time_get_effective(self) -> None:
"""Benchmark get_effective_invariants()."""
self.service.get_effective_invariants(plan_id="plan-001", project_name="myapp")
self.service.get_effective_invariants(
plan_id="plan-001", project_name="myapp", action_name="action-001"
)
+1
View File
1
@@ -430,6 +430,7 @@ def step_service_all_scopes(context):
context.service = InvariantService()
context.service.add_invariant("Global rule", InvariantScope.GLOBAL, "system")
context.service.add_invariant("Project rule", InvariantScope.PROJECT, "proj1")
context.service.add_invariant("Action rule", InvariantScope.ACTION, "action1")
context.service.add_invariant("Plan rule", InvariantScope.PLAN, "plan1")