fix(#20): heid-bug-hunt fixups — open-world presenter degrade-not-crash (slice-4)
Panel (Gróa+Hulda+Regin, 5/5/5, no false positives) confirmed two 3/3 crash
sites where open-world dict reads violate the declared "degrade, never crash the
presenter" invariant — the wt adapter tests + the live smoke used full server
dicts, so partial/drifted wire responses were never exercised:
- FIX (tier3.py _run_define/_run_patch): the CLI hard-indexed the open-world
define/patch dicts (`info["agent_id"]` / `["role"]` / `["agent_name"]`), so a
partial 2xx → KeyError escaping main()'s exit matrix as a raw traceback (exit 1);
and `make_description(info.get("system_prompt", ""))` fed None to .splitlines()
on a present-but-null field → AttributeError. Now reads via `_str_field` (absent/
null/non-str → default), degrades role to '?', indexes only a well-formed identity,
and maps a no-usable-agent_id 2xx to [api_failed] exit 20 (controlled, not a crash).
- FIX (web/server.py _agents_endpoint): the upstream dedup hard-indexed each item
(`{a["agent_id"] for a in upstream}` + `_as_dict`), so a malformed item (`[{}]`,
`["str"]`, `{"name":…}`, non-str agent_id) or a non-list envelope → 500 before the
local fallback merged. Now filters to well-formed mappings first; a non-list
upstream degrades to the local-only list.
- FIX (wt.py _error_field_from_body): type-check the parsed `field` is a str (the
exception surface is `field: str | None`, the CLI prints it) — restores the retired
hand-rolled `_extract_error_field` isinstance guard.
Held (triaged, no change): the 429→Tier3QuotaExceeded / bare-404→Tier3AgentNotFound
maps are ungated-by-error_code BY CONTRACT DESIGN (§ Error map route+status rows; the
SDK's ApiError floor drops Retry-After, so retry_after=0 is canonical) — the arms
flagged them spec-free; Heid's source-check confirmed intended. Dual-keying define's
429 for full row consistency is an available tightening (contract amendment), surfaced
not applied. The persona-endpoint SessionApiFailed gap the arms also caught was
already closed in the prior code-review fixup (aed9429).
Suite 475 green (+5).
This commit is contained in:
@@ -705,6 +705,16 @@ class TestDefineAgent:
|
||||
await define_agent(_wta(fake), agent_name="wizard", system_prompt="x", role="m")
|
||||
assert ei.value.field == "valence"
|
||||
|
||||
async def test_layer_deferred_non_string_field_is_none(self) -> None:
|
||||
# A non-string `field` value collapses to None — the exception surface is
|
||||
# `field: str | None` and the CLI prints it (heid-bug-hunt hardening).
|
||||
fake = _FakeAgents(error=ApiError(
|
||||
"layer_deferred", "no", status=422, body='{"detail": {"field": {"x": 1}}}',
|
||||
))
|
||||
with pytest.raises(Tier3LayerDeferred) as ei:
|
||||
await define_agent(_wta(fake), agent_name="wizard", system_prompt="x", role="m")
|
||||
assert ei.value.field is None
|
||||
|
||||
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).
|
||||
|
||||
Reference in New Issue
Block a user