# SKW-1 — the fourth Alpaca client has no request deadline: the skew-capture cron can still hang forever

status: open · raised panel run 15 (2026-08-31) · class: moat / loudness
(capture path) · judgement: **YES** · effort ~0.1 pd · horizon: any
delayed/stalled 19:00Z snapshot run — the outage-correlated class

---

**Plain-language summary.** PR #120 (finding 2) injected a 30-second request
deadline at the HTTP session of the three trading-path Alpaca clients, so a
broker stall now raises instead of hanging until the CI job is killed. There
is a **fourth** client the fix does not reach:
`src/thales/data/options_skew.py:383-386` constructs its own
`OptionHistoricalDataClient` bare — no `_apply_default_timeout` — and it is
live on the 19:00Z skew-snapshot cron (`cli` `snapshot-skew`,
`.github/workflows/skew-snapshot.yml:48`). A stall there hangs the capture run
until the job kill. Capture-cron stalls are precisely the outage-correlated
class the STAMP-1/STAMP-2 record documents, and a hung capture run loses a
permanent, un-backfillable day of the B4-pinned stream. This row completes an
owner-shipped fix; it is not new scope.

## Fix shape (propose-only)

Wrap the client via the existing `_apply_default_timeout`
(`execution/alpaca_broker.py:69-77`). The helper is already fail-loud if a
future SDK drops `._session`, so the pattern transfers unchanged: one import,
one line.

## Test design + kill criterion (pre-registered, negative-controlled)

A test asserting every Alpaca SDK client construction site in `src/` applies
the deadline wrap (negative control: remove the wrap at the skew site → the
test reds; the three #120 sites are already covered by their own tests).
**Falsifier:** if the wrapped client breaks the skew capture within 5 shadow
trading days (any capture failure attributable to the timeout on a
normally-paced run), revert and record the exposure as accepted — do not tune
the 30s value after seeing failures.

---

## Built — recorded 2026-09-05

**Shipped 2026-08-31 in PR #125 (commit `29c6f23`, "SKW-1 deadline").**
`options_skew.py:398` wraps the skew-capture client's HTTP session in
`_apply_default_timeout`, the same 30-second deadline PR #120 gave the three
trading-path clients; all four Alpaca clients now carry it
(`alpaca_broker.py:102`, `:352`; `vrp_daily.py:165`; `options_skew.py:398`).
Outcome: **shipped**.

**Route — recorded honestly:** built on the owner's direct instruction in the
2026-09-01 interactive session (RESEARCH.md's 09-01 banner already reads
"SKW-1 built"), NOT via `queue/approved/`. The row itself was never moved and
sat in `open/` for five days, still asserting "can still hang forever", until
the 2026-09-05 external design review (finding 6, `retire-stale-docs`) caught
the disagreement between the notebook and the queue. Moved by the maintainer
in the review-response PR; the guard denies the open→built rename, so a
human merges.
