feat(approvals): enhance approval model with task titles and confidence as float

This commit is contained in:
Abhimanyu Saharan
2026-02-12 19:57:04 +05:30
parent 8bd606a8dc
commit 032b77afb8
13 changed files with 370 additions and 40 deletions

View File

@@ -51,22 +51,25 @@ async def test_create_approval_rejects_duplicate_pending_for_same_task() -> None
async with await _make_session(engine) as session:
board, task_ids = await _seed_board_with_tasks(session, task_count=1)
task_id = task_ids[0]
await approvals_api.create_approval(
created = await approvals_api.create_approval(
payload=ApprovalCreate(
action_type="task.execute",
task_id=task_id,
payload={"reason": "Initial execution needs confirmation."},
confidence=80,
status="pending",
),
board=board,
session=session,
)
assert created.task_titles == [f"task-{task_id}"]
with pytest.raises(HTTPException) as exc:
await approvals_api.create_approval(
payload=ApprovalCreate(
action_type="task.retry",
task_id=task_id,
payload={"reason": "Retry should still be gated."},
confidence=77,
status="pending",
),
@@ -91,22 +94,25 @@ async def test_create_approval_rejects_pending_conflict_from_linked_task_ids() -
async with await _make_session(engine) as session:
board, task_ids = await _seed_board_with_tasks(session, task_count=2)
task_a, task_b = task_ids
await approvals_api.create_approval(
created = await approvals_api.create_approval(
payload=ApprovalCreate(
action_type="task.batch_execute",
task_ids=[task_a, task_b],
payload={"reason": "Batch operation requires sign-off."},
confidence=85,
status="pending",
),
board=board,
session=session,
)
assert created.task_titles == [f"task-{task_a}", f"task-{task_b}"]
with pytest.raises(HTTPException) as exc:
await approvals_api.create_approval(
payload=ApprovalCreate(
action_type="task.execute",
task_id=task_b,
payload={"reason": "Single task overlaps with pending batch."},
confidence=70,
status="pending",
),
@@ -135,6 +141,7 @@ async def test_update_approval_rejects_reopening_to_pending_with_existing_pendin
payload=ApprovalCreate(
action_type="task.execute",
task_id=task_id,
payload={"reason": "Primary pending approval is active."},
confidence=83,
status="pending",
),
@@ -145,6 +152,7 @@ async def test_update_approval_rejects_reopening_to_pending_with_existing_pendin
payload=ApprovalCreate(
action_type="task.review",
task_id=task_id,
payload={"reason": "Review decision completed earlier."},
confidence=90,
status="approved",
),

View File

@@ -0,0 +1,60 @@
from __future__ import annotations
import pytest
from pydantic import ValidationError
from app.schemas.approvals import ApprovalCreate
def test_approval_create_requires_confidence_score() -> None:
with pytest.raises(ValidationError, match="confidence"):
ApprovalCreate.model_validate(
{
"action_type": "task.update",
"payload": {"reason": "Missing confidence should fail."},
},
)
@pytest.mark.parametrize("confidence", [-1.0, 101.0])
def test_approval_create_rejects_out_of_range_confidence(confidence: float) -> None:
with pytest.raises(ValidationError, match="confidence"):
ApprovalCreate.model_validate(
{
"action_type": "task.update",
"payload": {"reason": "Confidence must be in range."},
"confidence": confidence,
},
)
def test_approval_create_requires_lead_reasoning() -> None:
with pytest.raises(ValidationError, match="lead reasoning is required"):
ApprovalCreate.model_validate(
{
"action_type": "task.update",
"confidence": 80,
},
)
def test_approval_create_accepts_nested_decision_reason() -> None:
model = ApprovalCreate.model_validate(
{
"action_type": "task.update",
"confidence": 80,
"payload": {"decision": {"reason": "Needs manual approval."}},
},
)
assert model.payload == {"decision": {"reason": "Needs manual approval."}}
def test_approval_create_accepts_float_confidence() -> None:
model = ApprovalCreate.model_validate(
{
"action_type": "task.update",
"confidence": 88.75,
"payload": {"reason": "Fractional confidence should be preserved."},
},
)
assert model.confidence == 88.75