From 3e00fb3f63e9026e1bf494e61eea16a9077e2f09 Mon Sep 17 00:00:00 2001 From: Tyler Date: Sun, 21 Jun 2026 13:43:37 -0600 Subject: [PATCH] =?UTF-8?q?plan(SP22):=20Task=205=20=E2=80=94=20apply=20Ta?= =?UTF-8?q?sk=204=20fixes=20(4xx=20terminal,=20RuntimeError)=20to=20list?= =?UTF-8?q?=5Fclaims=20and=20parse=5F837?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-06-21-cyclone-pipeline-agent.md | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/superpowers/plans/2026-06-21-cyclone-pipeline-agent.md b/docs/superpowers/plans/2026-06-21-cyclone-pipeline-agent.md index 14cca1e..f468ea6 100644 --- a/docs/superpowers/plans/2026-06-21-cyclone-pipeline-agent.md +++ b/docs/superpowers/plans/2026-06-21-cyclone-pipeline-agent.md @@ -980,7 +980,8 @@ Add the methods to the `CycloneClient` class (below `scheduler_status`): params: dict[str, str] = {"limit": str(limit)} if since: params["since"] = since - assert self._http is not None + if self._http is None: + raise RuntimeError("use `async with CycloneClient(...)`") last_exc: Exception | None = None for attempt in range(MAX_RETRIES): try: @@ -992,10 +993,15 @@ Add the methods to the `CycloneClient` class (below `scheduler_status`): ClaimSummary.model_validate(c) for c in _extract_items(resp.json()) ] - except (httpx.HTTPStatusError, httpx.RequestError) as e: + except httpx.HTTPStatusError as e: + # 4xx is terminal — surface immediately, do not retry + if e.response is not None and e.response.status_code < 500: + raise last_exc = e - if attempt < MAX_RETRIES - 1: - await asyncio.sleep(BACKOFF_S[attempt]) + except httpx.RequestError as e: + last_exc = e + if attempt < MAX_RETRIES - 1: + await asyncio.sleep(BACKOFF_S[attempt]) assert last_exc is not None raise last_exc @@ -1003,11 +1009,13 @@ Add the methods to the `CycloneClient` class (below `scheduler_status`): self, file_path, payer: str = "co_medicaid" ) -> ParseSummary: """POST the .edi/.txt file to cyclone's parse endpoint. - Returns a typed summary. + Returns a typed summary. POSTs are not retried on transport + failures (caller is responsible for dedup). """ from pathlib import Path # local import keeps the top of the file lean path = Path(file_path) - assert self._http is not None + if self._http is None: + raise RuntimeError("use `async with CycloneClient(...)`") with path.open("rb") as f: resp = await self._http.post( "/api/parse-837",