v0.38.0
thevoiceguy/siphon-aiv0.38.0Jul 21, 2026by github-actions[bot]
Upgrading?
AI Summary
Adds TX-side packet counters to quality telemetry to complete the sent/received data picture and fixes documentation errors regarding packet loss ratio.
Key Highlights
- Added TX-side counters: `tx_packets_sent`, `tx_octets_sent`, and `tx_packets_lost_reported`.
- Fixed `packet_loss_ratio` documentation to clarify it is a per-interval figure.
- Improved SIPp harness `run-all.sh` to preflight the echo WS server.
- Added new columns to CSV CDR output for quality metrics.
New Features
- TX-side packet counters for quality telemetry
- CSV CDR file format option
- JSON config printer (`print-config --format json`)
Full Release Notes
### Added - **TX-side packet counters across the quality telemetry** (issue #320; requires the forge-media pin bump to `f6151edf2724` = [forge-media#93](https://github.com/thevoiceguy/forge-media/pull/93), which publishes the underlying numbers on the `ForgeEvent` bus). Every quality surface was `rx_*` only, so an operator could see what SiphonAI *received* but never what it *sent* — "the outbound leg was clean" was a ratio with no denominator behind it. Three fields close the gap: `tx_packets_sent` and `tx_octets_sent` (locally measured on the SiphonAI→caller stream, cumulative since call start; octets are RTP payload only, the same basis as an RTCP SR's sender octet count), and `tx_packets_lost_reported` (the far end's own **absolute** count of packets it lost on that stream, from the latest RR's cumulative-lost field). Together they express the sentence operators actually ask for after a bad call: *"we sent 1,914 packets; the far end reported 12 lost."* `tx_packets_lost_reported` is **signed** — RFC 3550 §6.4.1 defines it that way because duplicates can push the peer's packets-received past packets-expected, so consumers must parse it as a signed integer and not clamp; a negative value is real information (a duplicating path). Surfaces: the `rtp_stats` WS event (additive optional fields, **protocol stays v1** as with the 0.30.0 `rx_*` addition), the CDR `quality` block, `/admin/v1/calls/:id/stats`, and the `[quality]` history records. CDR schema **stays at version 4** — additive optional fields within an existing block, per CLAUDE.md §7.7 and the `verstat_attest` / `recording_id` precedent (the v4 bump was for introducing the block itself). CSV gains three append-only columns (`quality_tx_packets_sent`, `quality_tx_octets_sent`, `quality_tx_packets_lost_reported`) at the end of the header, so position-keyed ingestors are unaffected. Motivated by a real 0.37.3 outbound call over a Twilio Secure trunk where `rx_packets_lost` 115 / `rx_packets_received` 1914 was visible but the clean TX direction could not be quantified in packets. Docs: `PROTOCOL.md` §3.8, `DEPLOY.md`; schema regenerated; both server SDKs updated in lockstep. ### Changed - **SIPp harness**: `run-all.sh` now preflights the echo WS server the same way it already preflights `sipp` and the daemon binary, exiting `2` with start-up instructions instead of running the suite without it. Previously a missing server produced eight scenario failures scattered across five phases (`basic_call_then_bye`, `session_timer_echo`, `reinvite_hold_resume`, `reinvite_unsupported_codec_488`, `session_progress_then_answer`, `stir_shaken_attestation_pass`, `digest_auth_caller`, `recording_writes_valid_wav`) — every scenario whose call must reach ACTIVE aborts on an unexpected BYE when the daemon tears the call down after the bridge can't connect, while scenarios that reject before bridging (488 / 428 / 403 / 503, CANCEL) still pass. The split reads like a signalling regression rather than a missing prerequisite, and a baseline-vs-branch comparison reproduces it identically on both sides, which makes the wrong conclusion look confirmed. CI was already immune — `.github/workflows/test.yml` starts the server and waits for the bind before invoking the script — so this closes the gap for local runs only; the check is a no-op in CI. The shared echo-server port is now a single `ECHO_WS_PORT` constant interpolated into the six generated configs that use it, matching the `*_WS_PORT` convention the private-echo-server phases already follow (it stays pinned to 8765 by `configs/local-dev.toml`, which the main phase runs against). ### Fixed - **`packet_loss_ratio` is documented correctly: it is a per-interval figure, not a cumulative one** (issue #320, secondary item). The CDR `quality` block's `avg/max_packet_loss_ratio` (`crates/cdr/src/schema.rs`), `PROTOCOL.md` §3.8, and `DEPLOY.md` all described these as the "RR-reported **cumulative**-loss ratio". They are derived from the RR's `fraction_lost` field, which measures loss over the interval since the *previous* report (RFC 3550 §6.4.1) — so `avg_packet_loss_ratio` is a mean of interval fractions, and an operator reconciling it against a carrier's cumulative figure would never get matching numbers. **The emitted values are unchanged**; only the descriptions were wrong. The field was deliberately *not* recomputed from the newly available cumulative counter — that would silently change a published number for existing consumers. Use `tx_packets_lost_reported / tx_packets_sent` for a true whole-call loss rate. --- **Artifacts** - Static musl binaries for `x86_64` and `aarch64` (`.tar.gz`). - Debian packages (`.deb`) for `amd64` and `arm64` — `apt install ./siphon-ai_*_amd64.deb`. - `SHA256SUMS` — verify with `sha256sum -c SHA256SUMS`. - `*-sbom.cdx.json` — CycloneDX SBOM. - `SHA256SUMS.cosign.bundle` — cosign keyless signature over the checksums. - Container: `ghcr.io/thevoiceguy/siphon-ai:v0.38.0` (multi-arch, cosign-signed). Verify the checksums signature: ``` cosign verify-blob --bundle SHA256SUMS.cosign.bundle \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ --certificate-identity-regexp 'release.yml@' SHA256SUMS ```
Related Repositories
A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io
An open-source remote desktop application designed for self-hosting, as an alternative to TeamViewer.
Build smaller, faster, and more secure desktop and mobile applications with a web frontend.
π RuView turns commodity WiFi signals into real-time spatial intelligence, vital sign monitoring, and presence detection — all without a single pixel of video.
Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one