FlyingNunchucks's picture
Add typed auction contracts and validation tests
d41192b
Raw History Blame Contribute Delete
6.65 kB
"""Validation tests for Agent 11 auction contracts."""
from datetime import datetime, timezone
import pytest
from pydantic import ValidationError
from auction_coordination.models import (
AbstentionReason,
AuctionState,
AuctionStatus,
Bid,
BidAbstention,
CapabilityProfile,
FailureClass,
RegisteredCapability,
TaskAnnouncement,
TaskAward,
TaskFailure,
)
NOW = datetime(2026, 9, 11, 22, 0, tzinfo=timezone.utc)
def capability_profile() -> CapabilityProfile:
return CapabilityProfile(
agent_id="peer.atlas",
display_name="Atlas Research",
capabilities=(
RegisteredCapability(capability="market_research", score=0.92),
RegisteredCapability(capability="source_research", score=0.86),
),
)
def task_announcement(**overrides) -> TaskAnnouncement:
values = {
"task_id": "task.market",
"auction_id": "auction.market.1",
"auction_round": 1,
"requested_capability": "market_research",
"summary": "Assess the fictional target market and competitive environment.",
"minimum_capability_score": 0.70,
"maximum_cost": 100.0,
"required_input_ids": (),
"max_auction_rounds": 2,
"opened_at": NOW,
}
values.update(overrides)
return TaskAnnouncement(**values)
def valid_bid(**overrides) -> Bid:
values = {
"bid_id": "bid.atlas.market.1",
"auction_id": "auction.market.1",
"task_id": "task.market",
"auction_round": 1,
"bidder_id": "peer.atlas",
"capability": "market_research",
"confidence": 0.88,
"availability": 0.75,
"estimated_cost": 60.0,
"submitted_at": NOW,
}
values.update(overrides)
return Bid(**values)
def test_capability_profile_preserves_registered_scores() -> None:
profile = capability_profile()
assert profile.score_for("market_research") == pytest.approx(0.92)
assert profile.score_for("financial_analysis") is None
def test_capability_profile_rejects_duplicate_capability_names() -> None:
with pytest.raises(ValidationError):
CapabilityProfile(
agent_id="peer.atlas",
display_name="Atlas Research",
capabilities=(
RegisteredCapability(capability="market_research", score=0.92),
RegisteredCapability(capability="market_research", score=0.80),
),
)
def test_registered_capability_score_must_be_normalized() -> None:
with pytest.raises(ValidationError):
RegisteredCapability(capability="market_research", score=1.01)
def test_task_announcement_rejects_duplicate_inputs() -> None:
with pytest.raises(ValidationError):
task_announcement(required_input_ids=("work.1", "work.1"))
def test_task_announcement_rejects_round_beyond_configured_limit() -> None:
with pytest.raises(ValidationError):
task_announcement(auction_round=3, max_auction_rounds=2)
def test_task_announcement_requires_timezone_aware_timestamp() -> None:
with pytest.raises(ValidationError):
task_announcement(opened_at=datetime(2026, 9, 11, 22, 0))
def test_bid_rejects_self_declared_capability_score() -> None:
with pytest.raises(ValidationError):
Bid(
**valid_bid().model_dump(),
capability_score=0.99,
)
def test_bid_rejects_out_of_range_confidence() -> None:
with pytest.raises(ValidationError):
valid_bid(confidence=1.10)
def test_bid_rejects_non_positive_cost() -> None:
with pytest.raises(ValidationError):
valid_bid(estimated_cost=0.0)
def test_abstention_is_explicit_and_auditable() -> None:
abstention = BidAbstention(
abstention_id="abstain.mosaic.market.1",
auction_id="auction.market.1",
task_id="task.market",
auction_round=1,
bidder_id="peer.mosaic",
reason=AbstentionReason.LOW_CONFIDENCE,
detail="Current evidence coverage is below the local bidding threshold.",
submitted_at=NOW,
)
assert abstention.reason is AbstentionReason.LOW_CONFIDENCE
def test_awarded_state_requires_winner_fields() -> None:
with pytest.raises(ValidationError):
AuctionState(
auction_id="auction.market.1",
task_id="task.market",
auction_round=1,
status=AuctionStatus.AWARDED,
valid_bid_ids=("bid.atlas.market.1",),
)
def test_winning_bid_must_be_one_of_valid_bids() -> None:
with pytest.raises(ValidationError):
AuctionState(
auction_id="auction.market.1",
task_id="task.market",
auction_round=1,
status=AuctionStatus.AWARDED,
valid_bid_ids=("bid.atlas.market.1",),
winning_bid_id="bid.ledger.market.1",
awarded_agent_id="peer.ledger",
)
def test_failed_state_requires_failure_record() -> None:
with pytest.raises(ValidationError):
AuctionState(
auction_id="auction.market.1",
task_id="task.market",
auction_round=1,
status=AuctionStatus.FAILED,
valid_bid_ids=("bid.atlas.market.1",),
winning_bid_id="bid.atlas.market.1",
awarded_agent_id="peer.atlas",
)
def test_no_valid_bids_state_cannot_contain_valid_bids() -> None:
with pytest.raises(ValidationError):
AuctionState(
auction_id="auction.market.1",
task_id="task.market",
auction_round=1,
status=AuctionStatus.NO_VALID_BIDS,
valid_bid_ids=("bid.atlas.market.1",),
)
def test_task_award_records_normalized_winning_score() -> None:
award = TaskAward(
award_id="award.market.1",
auction_id="auction.market.1",
task_id="task.market",
auction_round=1,
winning_bid_id="bid.atlas.market.1",
awarded_agent_id="peer.atlas",
winning_score=0.84,
awarded_at=NOW,
)
assert award.winning_score == pytest.approx(0.84)
def test_task_failure_records_failure_class_without_deciding_reauction_policy() -> None:
failure = TaskFailure(
failure_id="failure.market.1",
award_id="award.market.1",
auction_id="auction.market.1",
task_id="task.market",
auction_round=1,
agent_id="peer.atlas",
failure_class=FailureClass.EXECUTION_ERROR,
detail="Synthetic handler failed before producing a valid work product.",
failed_at=NOW,
)
assert failure.failure_class is FailureClass.EXECUTION_ERROR