Files
2026-07-13 13:12:33 +08:00

116 lines
3.6 KiB
Python

"""Wire-contract freeze for streamed session event payloads.
``session.event.router_decision`` drives the router HUD (tier pill,
tier-shift highlight, scanner popover) and ``session.event`` ensemble
progress frames reveal ensemble members mid-turn, on every client surface.
Their key names are a public protocol contract (see CLAUDE.md: public RPC
field names are stable).
- Renaming or removing any frozen key is a contract break and must fail here.
- Adding a key requires deliberately extending the frozen sets in this file —
that friction is the point: wire additions should be a conscious decision.
The shapes are frozen at the pure payload builders in channel_dispatch
(``_router_decision_payload`` / ``_ensemble_progress_payload``) over fully
synthetic engine events — no gateway, channel, or network involved.
"""
from __future__ import annotations
from opensquilla.engine.types import EnsembleProgressEvent, RouterDecisionEvent
from opensquilla.gateway.channel_dispatch import (
_ensemble_progress_payload,
_router_decision_payload,
)
ROUTER_DECISION_KEYS = frozenset(
{
"tier",
"tier_index",
"model",
"baseline_model",
"source",
"confidence",
"probs",
"savings_pct",
"fallback",
"thinking_mode",
"prompt_policy",
"routing_applied",
"rollout_phase",
"context_window",
}
)
ENSEMBLE_PROGRESS_KEYS = frozenset(
{
"event_type",
"proposer_index",
"proposer_label",
"proposer_model",
"proposer_provider",
"sample_index",
"elapsed_ms",
"input_tokens",
"output_tokens",
"cost_usd",
"error",
}
)
def _synthetic_router_decision() -> RouterDecisionEvent:
return RouterDecisionEvent(
tier="c1",
tier_index=1,
model="test-provider/test-model",
baseline_model="test-provider/test-baseline",
source="classifier",
confidence=0.87,
probs=[0.05, 0.87, 0.06, 0.02],
savings_pct=0.42,
fallback=False,
thinking_mode="medium",
prompt_policy="tiered",
routing_applied=True,
rollout_phase="full",
context_window=128_000,
)
def test_router_decision_payload_keys_are_frozen() -> None:
payload = _router_decision_payload(_synthetic_router_decision())
assert set(payload) == ROUTER_DECISION_KEYS
def test_router_decision_payload_values_pass_through() -> None:
# Values must arrive verbatim; the HUD renders tier/model/probs raw and
# keys tier styling off the canonical c0-c3 strings.
payload = _router_decision_payload(_synthetic_router_decision())
assert payload["tier"] == "c1"
assert payload["tier_index"] == 1
assert payload["model"] == "test-provider/test-model"
assert payload["baseline_model"] == "test-provider/test-baseline"
assert payload["probs"] == [0.05, 0.87, 0.06, 0.02]
assert payload["context_window"] == 128_000
def test_ensemble_progress_payload_keys_are_frozen() -> None:
event = EnsembleProgressEvent(
event_type="proposer_done",
proposer_index=2,
proposer_label="proposer-3",
proposer_model="test-provider/test-model",
proposer_provider="test-provider",
sample_index=1,
elapsed_ms=1500,
input_tokens=1200,
output_tokens=340,
cost_usd=0.0021,
error="",
)
payload = _ensemble_progress_payload(event)
assert set(payload) == ENSEMBLE_PROGRESS_KEYS
assert payload["event_type"] == "proposer_done"
assert payload["proposer_model"] == "test-provider/test-model"