feat: carry the per-call tier down to the transport that must send it

The Transport port took the request apart into five arguments, so a tier
placed on ChatRequest could never reach _build_payload: the field was set,
read by nobody, and silently ignored - the exact shape of failure that sent
downstream to extra_body in the first place.

complete() now takes reasoning_effort with no default, matching the
TelemetryRecorder convention: a default would turn a missing hand-off into
a silent 'no opinion'. All four fakes move with it, since @runtime_checkable
checks method names and not signatures.

EmbeddingTransport and OcrTransport are deliberately left alone - they have
no reasoning semantics - and a test now holds that line.

_build_payload drops its inline sugar conversion for effective_effort(), so
the guard and the hot path share one judgement, and passes the source's
effort_fallback for the same reason.
This commit is contained in:
2026-09-05 02:28:24 -04:00
parent 1f13eb18ab
commit 80a8013642
11 changed files with 142 additions and 15 deletions
+32 -1
View File
@@ -1,15 +1,18 @@
"""ports.py 端口冻结测试(M1 设计 §4): Protocol 结构性检查 + Gate 快照校验。"""
import inspect
from typing import Any
import pytest
from polygateway.ports import (
CacheBackend,
EmbeddingTransport,
GateDecision,
GateState,
GateUpdate,
Middleware,
OcrTransport,
Permit,
ProviderGate,
RateLimiter,
@@ -69,7 +72,7 @@ class _DummyMw:
class _DummyTransport:
async def complete(self, *, messages, source, stream, overlay, call_id):
async def complete(self, *, messages, source, stream, overlay, call_id, reasoning_effort):
raise NotImplementedError
@@ -142,6 +145,34 @@ def test_protocols_are_runtime_checkable(impl, protocol):
assert isinstance(impl, protocol)
class TestReasoningTierIsOnlyOnTheChatPort:
"""档位属于 chat 端口,且**只属于**它(Task 5b)。
`@runtime_checkable` 只查方法名不查签名,故协议签名本身必须被显式断言——
否则实现漏改一个参数,要到运行期调用才会以 `TypeError` 现形,而那时的现场
离根因已经很远。
"""
def test_chat_transport_carries_the_per_call_tier(self):
params = inspect.signature(Transport.complete).parameters
assert "reasoning_effort" in params
# 不给默认值是有意的(与 TelemetryRecorder 同一既有约定): 库外无第三方
# 实现者,写全签名成本为零,而默认值会把"漏传"变成静默的"不表态"
assert params["reasoning_effort"].default is inspect.Parameter.empty
@pytest.mark.parametrize(
("protocol", "method"),
[
(EmbeddingTransport, "embed"),
(OcrTransport, "recognize_text"),
(OcrTransport, "parse_layout"),
],
)
def test_other_transports_have_no_reasoning_tier(self, protocol, method):
"""embedding 与 OCR 没有推理语义,给它们加档位只会静默无效(issue #4 同款决策)。"""
assert "reasoning_effort" not in inspect.signature(getattr(protocol, method)).parameters
class _DummyStatusProvider(_DummyRecorder):
@property
def telemetry_status(self) -> TelemetryStatus: