feat(tests): let managers escalate and directly resolve disputed tests
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled

Request Discussion only ever nudged the peer lead, and the one-time
manager notification when a dispute starts had no real follow-up
action attached to it — a manager could be told a dispute existed but
had no way to actually do anything about it. Adds:

- POST /tests/{id}/escalate-to-manager — either lead can explicitly
  ask managers to step in, distinct from the passive initial notice.
- POST /tests/{id}/manager-resolve-dispute — a manager decides the
  final outcome (validated/rejected) directly, bypassing both leads'
  votes entirely, reusing the same dual-validation event dispatch so
  Jira/notifications behave like any other resolution.

Both leads are notified of the manager's final call, win or lose.
This commit is contained in:
kitos
2026-07-15 13:03:01 +02:00
parent 32f4fd25bd
commit 3a01facd46
9 changed files with 444 additions and 1 deletions
+21
View File
@@ -672,6 +672,27 @@ class TestEntity:
self._events.append(DomainEvent("dispute_resolved_to_rework", {"target": target}))
def resolve_dispute_by_manager(self, outcome: str) -> None:
"""A manager makes the final call on a disputed test, ending the standoff.
Unlike ``resolve_dispute_reject`` (a lead flipping their own vote),
this bypasses both leads entirely — the manager's decision is final
and terminal, going straight to ``validated`` or the normal
``rejected`` dead-end (which any lead can later reopen via the
standard reopen-to-draft flow, same as any other rejection).
Args:
outcome (str): ``"validated"`` or ``"rejected"``.
"""
if outcome not in ("validated", "rejected"):
raise InvalidOperationError("outcome must be 'validated' or 'rejected'")
target_state = TestState.validated if outcome == "validated" else TestState.rejected
self._transition(target_state)
self._events.append(
DomainEvent("dual_validation_approved" if outcome == "validated" else "dual_validation_rejected")
)
# -- Private -------------------------------------------------------
def _auto_resume(self) -> int: