Skip to main content
The soak harness covers two failure modes that the regular CI suite is too short to catch:
  • Voice realtime sessions — the OpenAI Realtime and Gemini Live WebSocket clients run for hours per session in production. A slow task / socket leak will not show up in a 30-second unit test, but pegs RSS within an hour of real traffic.
  • Channel adapters — Telegram, Slack, and Discord all have rate limits that only bite once you have been chatting for a while. A back-off bug that re-tries too aggressively will cascade into 429s.
Both harnesses are gated behind the --runsoak pytest flag and the @pytest.mark.soak marker, registered in feral-core/pyproject.toml and feral-core/tests/conftest.py.

When to run

Local smoke check

The harnesses respect a FERAL_SOAK_DURATION_MIN env var so you do not need to wait an hour to know they import cleanly:
A clean run prints a single summary line per test ([VOICE SOAK / openai] PASS: ...).

Expected metrics

Voice (tests/test_voice_soak.py / scripts/soak/voice.py)

Channels (tests/test_channels_soak.py / scripts/soak/channels.py)

Required env / secrets

Voice soak needs nothing — both peers are in-process fakes. Channel soak skips cleanly unless its env vars are set. In the nightly workflow these come from repo secrets: Use personal staging bots in dedicated channels — never point the soak at a production workspace, the 24-hour heartbeat will be very visible.

Escalation path

The nightly workflow runs with continue-on-error: true so a single red soak never blocks the morning’s regular CI on main. Triage steps:
  1. Pull the per-job artifact (voice-soak-logs or channels-soak-logs) from the failed run; the log contains the full pytest output and the one-line PASS/FAIL summary per test.
  2. Voice failures — if rss_growth_kb is the trigger, suspect a leaked task or unclosed WebSocket in the relevant client module (feral-core/voice/realtime_proxy.py or gemini_realtime.py). Check recent commits to those files first.
  3. Channel failures — if auth_failures > 0, the staging bot token was rotated or revoked; re-issue and update the secret. If rate_limited is the trigger, audit the adapter’s back-off logic in feral-core/channels/.
  4. Open a release-impact issue tagged release-impact:behavior and page the on-call maintainer.

Maintenance contract

This harness covers the voice + channel soak surface. It stays open as a maintenance gate: any future change to the watched modules must keep these tests green.