fix(#20): heid-code-review fixups — persona-endpoint SessionApiFailed parity (slice-4)
Panel (Gróa+Hulda+Regin) returned zero adapter / error-map / model→role drift; three actionable items triaged as genuine adds: - FIX: `_persona_state_endpoint` now catches `wt.SessionApiFailed` and returns the `session_api_failed` envelope with the upstream status, for parity with `_agents_endpoint` / session-create / admin (2/3 arms flagged it; it was the lone sibling letting an unmatched upstream ApiError escape as a raw 500). Confirmed NOT a slice-4 regression — the pre-cutover persona endpoint had the same latent gap — but closed here since the endpoint's error surface is already being hardened (it gained the ConnectFailed catch this slice). - TESTS: dual-key NEGATIVE rows — a wrong error_code at the same status defaults to SessionApiFailed for `define_agent` (403, 422) and `patch_agent` (422); plus the flat-`field` body-parse shape for `_error_field_from_body` (only the nested detail.field form was exercised). Closes the assertion-symmetry gap with the persona route's existing negative test. - AMEND: contract slice-4 notes document the intentional client-side `":" in agent_id` PRE on patch/delete (a Tier-3 id is always <user>:<name>, ADR-0019). Suite 470 green (+5).
This commit is contained in:
@@ -695,6 +695,31 @@ class TestDefineAgent:
|
||||
await define_agent(_wta(fake), agent_name="wizard", system_prompt="x", role="m")
|
||||
assert ei.value.field == "persona"
|
||||
|
||||
async def test_layer_deferred_flat_field_body(self) -> None:
|
||||
# _error_field_from_body also handles a flat top-level `field` (both-shape
|
||||
# unwrap) — locks the contract's "detail.field / flat field" claim.
|
||||
fake = _FakeAgents(error=ApiError(
|
||||
"layer_deferred", "no", status=422, body='{"field": "valence"}',
|
||||
))
|
||||
with pytest.raises(Tier3LayerDeferred) as ei:
|
||||
await define_agent(_wta(fake), agent_name="wizard", system_prompt="x", role="m")
|
||||
assert ei.value.field == "valence"
|
||||
|
||||
async def test_403_wrong_code_maps_to_default(self) -> None:
|
||||
# Dual-key negative: a 403 whose code is NOT tier3_user_id_unsupported →
|
||||
# generic default, not a spurious Tier3UserIdUnsupported (INV-CUT-2).
|
||||
fake = _FakeAgents(error=ApiError("auth_revoked", "no", status=403))
|
||||
with pytest.raises(SessionApiFailed) as ei:
|
||||
await define_agent(_wta(fake), agent_name="wizard", system_prompt="x", role="m")
|
||||
assert ei.value.status == 403
|
||||
|
||||
async def test_422_wrong_code_maps_to_default(self) -> None:
|
||||
# Dual-key negative: a 422 whose code is NOT layer_deferred → default.
|
||||
fake = _FakeAgents(error=ApiError("validation_failed", "no", status=422))
|
||||
with pytest.raises(SessionApiFailed) as ei:
|
||||
await define_agent(_wta(fake), agent_name="wizard", system_prompt="x", role="m")
|
||||
assert ei.value.status == 422
|
||||
|
||||
async def test_bad_slug_asserts_no_call(self) -> None:
|
||||
fake = _FakeAgents(result={})
|
||||
with pytest.raises(AssertionError):
|
||||
@@ -761,6 +786,14 @@ class TestPatchAgent:
|
||||
await patch_agent(_wta(fake), "ratatoskr:wizard", system_prompt="x")
|
||||
assert ei.value.field == "agent_name"
|
||||
|
||||
async def test_422_wrong_code_maps_to_default(self) -> None:
|
||||
# Dual-key negative: a 422 whose code is NOT field_not_mutable → default,
|
||||
# not a spurious Tier3FieldNotMutable (INV-CUT-2).
|
||||
fake = _FakeAgents(error=ApiError("validation_failed", "no", status=422))
|
||||
with pytest.raises(SessionApiFailed) as ei:
|
||||
await patch_agent(_wta(fake), "ratatoskr:wizard", system_prompt="x")
|
||||
assert ei.value.status == 422
|
||||
|
||||
async def test_no_fields_asserts_no_call(self) -> None:
|
||||
fake = _FakeAgents(result={})
|
||||
with pytest.raises(AssertionError):
|
||||
|
||||
Reference in New Issue
Block a user