ec43c0e0d1
Three real defects flagged in the post-merge review of #616, plus one cheap hardening: 1. OpenCode `limit.output` override was a silent no-op on opencode-ai@1.1.56. Top-level `limit.output` has no read site in OpenCode (verified against the v1.1.56 source: `OUTPUT_TOKEN_MAX = Flag.OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX || 32_000` in session/llm.ts; per-model `model.limit.output` has its own scope). Plumbed via `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX=5000` env var on the OpenCode spawn instead. Drops dead `OpenCodeConfig.limit?` type field and the corresponding config write in `buildSecurityConfig`. This was the headline mechanism of #616 — without the env var, the upfront `max_tokens` reservation stayed at 32_000 and low-wallet runs continued failing the way #616 was supposed to prevent. 2. Phantom auto-reload buffer for detached-card accounts. DELETE /payment-method clears `stripeCustomerId` but leaves `autoReloadEnabled` intact, so an account with welcome-credit residue and a detached card could mint a key with `keyLimitCents = balance + autoReloadAmountCents` ($50 default, schema-cap $100K) of free spend headroom we have no way to bill. Conjunctive `account.autoReloadEnabled && hasCard` in the buffer selection closes this. Defense-in-depth follow-up worth doing: clear `autoReloadEnabled` in the card-detach handler. 3. The autoReloadEnabled 402 branch fired for phase-1 noop paths (`!stripeCustomerId`, `reloadAmountCents < 50`, `balance >= threshold`) where `result.failure == null`, returning `"insufficient balance"` with no actionable code. Gated on `result.status === "failed"` so non-charge paths fall through to the `hasCard` / no-card branches and emit `router_balance_exhausted` / `router_requires_card` instead. 4. (cheap) `ROUTER_KEYLIMIT_EXHAUSTED_PATTERN` now uses `/is` instead of `/i` so `.*?` crosses newlines. Defends the BillingError reclassification against any upstream layer that wraps the OpenRouter error onto multiple lines. Trivial. Test plan: 488/488 unit tests pass (1 new test for newline regex behavior).