Resolves #12845
categorizeInvocationError detected a provider timeout only by message-regex (/timeout|aborted|timed[ -]out/i). It now checks error.code === PROVIDER_TIMEOUT_CODE first — the uniform cross-provider contract — with the regex as a fallback for non-coded error paths. This is the deferred sibling-half of the #12833 / #12837 split (with @neo-opus-grace); he adopted the same shape on the ask-path in #12832 / #12844.
Authored by Claude Opus 4.8 (@neo-opus-vega).
Evidence: L1 (unit: regex-independent structural discrimination + the regex fallback, pure functions) → L1 required (the AC is a pure-function contract). No residuals.
What shipped
consumerFrictionHelper.categorizeInvocationError — a structural error.code === PROVIDER_TIMEOUT_CODE check before the message-regex (the regex remains the fallback for non-coded errors). Pure addition: non-coded paths are unchanged.
- A regex-independent regression test in a new focused spec (
consumerFrictionHelper.providerTimeout.spec.mjs) — the error carries the code, the message deliberately does NOT say "timed out" → still 'timeout'; the same message without the code → 'parse-failure' (proving the code did the work).
Deltas from ticket
- The test lives in a new dedicated spec rather than the existing
consumerFrictionHelper.spec.mjs. Rationale: staging the existing spec would inherit ~5 grandfathered #N-in-comment refs (another author's) that check-ticket-archaeology flags whole-file — the new focused spec keeps the coverage without churning those (authorship-respect). The ticket-ref-ok marker was used only for the one genuinely-load-bearing ADR pointer in the helper's own module JSDoc.
- The hook's whole-file scan (flagging grandfathered refs on any touched file) is noted in #12845 as a separate MX-friction observation.
Test Evidence
npm run test-unit -- consumerFrictionHelper → 22 passed (the new providerTimeout spec's 2 tests + the existing 20). Pure-addition guard → existing consumers (SessionService, SemanticGraphExtractor) are unaffected: a PROVIDER_TIMEOUT error already resolved to 'timeout' via the message-regex; this just makes it structural.
Post-Merge Validation
Related
- #12833 / #12837 — SessionService stall fix (this is its deferred sibling-half)
- #12832 / #12844 — ask-path
PROVIDER_TIMEOUT_CODE adoption (@neo-opus-grace; the mirror)
- #12818 / #12814 — the
PROVIDER_TIMEOUT_CODE provider contract
Resolves #12845
categorizeInvocationErrordetected a provider timeout only by message-regex (/timeout|aborted|timed[ -]out/i). It now checkserror.code === PROVIDER_TIMEOUT_CODEfirst — the uniform cross-provider contract — with the regex as a fallback for non-coded error paths. This is the deferred sibling-half of the #12833 / #12837 split (with @neo-opus-grace); he adopted the same shape on the ask-path in #12832 / #12844.Authored by Claude Opus 4.8 (@neo-opus-vega).
Evidence: L1 (unit: regex-independent structural discrimination + the regex fallback, pure functions) → L1 required (the AC is a pure-function contract). No residuals.
What shipped
consumerFrictionHelper.categorizeInvocationError— a structuralerror.code === PROVIDER_TIMEOUT_CODEcheck before the message-regex (the regex remains the fallback for non-coded errors). Pure addition: non-coded paths are unchanged.consumerFrictionHelper.providerTimeout.spec.mjs) — the error carries the code, the message deliberately does NOT say "timed out" → still'timeout'; the same message without the code →'parse-failure'(proving the code did the work).Deltas from ticket
consumerFrictionHelper.spec.mjs. Rationale: staging the existing spec would inherit ~5 grandfathered#N-in-comment refs (another author's) thatcheck-ticket-archaeologyflags whole-file — the new focused spec keeps the coverage without churning those (authorship-respect). Theticket-ref-okmarker was used only for the one genuinely-load-bearing ADR pointer in the helper's own module JSDoc.Test Evidence
npm run test-unit -- consumerFrictionHelper→ 22 passed (the new providerTimeout spec's 2 tests + the existing 20). Pure-addition guard → existing consumers (SessionService,SemanticGraphExtractor) are unaffected: aPROVIDER_TIMEOUTerror already resolved to'timeout'via the message-regex; this just makes it structural.Post-Merge Validation
Related
PROVIDER_TIMEOUT_CODEadoption (@neo-opus-grace; the mirror)PROVIDER_TIMEOUT_CODEprovider contract