v0.47.0

thevoiceguy/siphon-aiv0.47.0Jul 29, 2026by github-actions[bot]

Upgrading?

AI Summary

Adds `offset_ms` to speech events and fixes sink reload reporting to properly indicate restart requirements.

Key Highlights

  • Added `offset_ms` to `speech_started` and `speech_stopped` events.
  • Fixed sink reload reporting to include `restart_required` for active durable spools.
  • Fixed documentation regarding speech event gating.

New Features

  • New `offset_ms` field for speech events
  • Improved reload audit trail for sink changes

Full Release Notes

### Added

- **`offset_ms` on `speech_started` / `speech_stopped` — monotonic milliseconds between `start` being sent and the VAD transition** (issue #394). `ts_ms` carries wall-clock epoch milliseconds (#389/#392), so placing a speech event on the media timeline meant subtracting wall-clock values across two hosts — exposed to clock skew, WS transit jitter on `start`, and NTP steps. The daemon now also stamps the transition against its own monotonic clock, anchored to the instant `start` was written to the socket (the same instant already used as the CDR `first_audio_out_ms` epoch). The stamp is taken when the transition comes off the detector — before any barge-in debounce or pause hold — so a held `speech_started` keeps its true timeline position; a transition detected before `start` hit the wire saturates to `0`. Additive within protocol v1 (optional field, no version bump), absent from older daemons; documented in PROTOCOL.md §3.2, typed in both server SDKs.

### Fixed

- **Sink changes downgraded to restart-required because their durable spool is active are now reported in the `config_reload` audit event's `restart_required` field and the summarizing reload warning** (issue #390). All three sink arms (`[webhooks]`, `[cdr]`, `[audit]`) logged their own specific journal warning but never added the section to the reload's `restart_required` list, so the machine-readable audit trail claimed a plain `"applied"` while deliveries kept going to the old target until a restart — and since a repeat SIGHUP with an unchanged file short-circuits as `no_change`, that one journal line was the only trace a restart was owed. The sections now surface as `"[webhooks] delivery"` / `"[cdr] delivery"` / `"[audit] delivery"` — distinct from the existing `"[audit]"` entry, which means "audit was disabled at startup and enabling it needs the process-global facade installed". Verified live on 0.46.1: an `[audit.webhook].url` edit under an active spool produced a bare-`applied` audit event while probe events and the drained spool kept POSTing to the old url. Sink fingerprints still advance only on a successful swap, so reverting a downgraded edit converges silently with no restart debt (covered by new tests).

### Documentation

- **PROTOCOL.md §3.2 now states that `ts_ms` on speech events is wall-clock Unix-epoch milliseconds, not a monotonic offset from `start`** (issue #389) — the ambiguity that motivated `offset_ms` above. Doc-comment and schema descriptions were corrected in the same pass.
- **The `speech_started` doc comment and schema description no longer claim the event is gated on a nonexistent `bridge.vad = true` flag** — speech events are always emitted; `[media].vad` selects the detection backend only.

---

**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.47.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