fix(tests): fix veto bug preventing disputed state, add manager notification and dispute-resolution routing

This commit is contained in:
kitos
2026-07-06 12:40:05 +02:00
parent 388c9773ab
commit f53e124c50
7 changed files with 448 additions and 8 deletions
+72
View File
@@ -401,9 +401,32 @@ def test_dual_validation_red_rejects():
def test_dual_validation_blue_rejects():
"""Red already approved; Blue then rejects — a genuine conflict, not a veto."""
e = _entity("in_review")
e.validate_red("approved", by=uuid.uuid4())
e.validate_blue("rejected", by=uuid.uuid4())
assert e.state == TestState.disputed
assert any(ev.name == "dual_validation_disputed" for ev in e.events)
def test_dual_validation_blue_approved_then_red_rejects():
"""Blue already approved; Red then rejects — also a genuine conflict."""
e = _entity("in_review")
e.validate_blue("approved", by=uuid.uuid4())
e.validate_red("rejected", by=uuid.uuid4())
assert e.state == TestState.disputed
def test_dual_validation_both_rejected_from_disputed():
"""A disputed test where the approving lead flips to reject (via the
plain validate call, not resolve_dispute_reject) still lands on the
generic terminal 'rejected' state — both leads now agree it's bad."""
e = _entity(
"disputed",
red_validation_status="approved",
blue_validation_status="rejected",
)
e.validate_red("rejected", by=uuid.uuid4())
assert e.state == TestState.rejected
@@ -561,3 +584,52 @@ def test_is_terminal():
assert _entity("validated").is_terminal is True
assert _entity("rejected").is_terminal is False
assert _entity("draft").is_terminal is False
# ── 13. resolve_dispute_reject ──────────────────────────────────────
def test_resolve_dispute_reject_to_red():
e = _entity(
"disputed",
red_validation_status="approved",
red_validated_by=uuid.uuid4(),
red_validated_at=datetime.utcnow(),
blue_validation_status="rejected",
blue_validated_by=uuid.uuid4(),
blue_validated_at=datetime.utcnow(),
red_paused_seconds=50,
)
e.resolve_dispute_reject("red")
assert e.state == TestState.red_executing
assert e.red_validation_status is None
assert e.red_validated_by is None
assert e.blue_validation_status is None
assert e.blue_validated_by is None
assert e.red_started_at is not None
assert e.red_paused_seconds == 0
assert any(ev.name == "dispute_resolved_to_rework" and ev.payload["target"] == "red" for ev in e.events)
def test_resolve_dispute_reject_to_blue():
e = _entity(
"disputed",
blue_validation_status="approved",
blue_validated_by=uuid.uuid4(),
red_validation_status="rejected",
red_validated_by=uuid.uuid4(),
blue_paused_seconds=20,
)
e.resolve_dispute_reject("blue")
assert e.state == TestState.blue_evaluating
assert e.red_validation_status is None
assert e.blue_validation_status is None
assert e.blue_started_at is not None
assert e.blue_paused_seconds == 0
assert any(ev.name == "dispute_resolved_to_rework" and ev.payload["target"] == "blue" for ev in e.events)
def test_resolve_dispute_reject_wrong_state():
e = _entity("in_review")
with pytest.raises(InvalidStateTransition):
e.resolve_dispute_reject("red")