← Choice Health 2026-06-29-space-channel-content-refresh-design.md raw .md

Space Channel Content Refresh Design

Date: 2026-06-29

Goal

Make the Space Channel phone number useful without depending on live page scraping or live Gemini speech for known content during a call.

The production phone path should:

Current Implementation

Refresh command:

.venv/bin/python scripts/space_channel_refresh.py --once

Long-running four-hour refresh loop:

.venv/bin/python scripts/space_channel_refresh.py --daemon --interval-hours 4

Cron-style four-hour schedule:

0 */4 * * * cd /Users/davidmar/src/riff && .venv/bin/python scripts/space_channel_refresh.py --once >> logs/space_channel_refresh.log 2>&1

Runtime cache:

data/space_channel/content_snapshot.json

That cache is generated runtime data and is ignored by git. If it is missing or expired, space_content_fetch attempts one refresh during the read-only act state before it speaks.

Data Sources

V1 uses two Space Channel-facing sources:

The homepage currently exposes widgets such as Launch Command, Daily Briefing, Cosmic Weather, Anomaly Division, Intelligence Feed, ISS Operations, Music, and Solar Operations. The phone briefing uses that catalog so callers can ask what is online, ask about Space Channel news, solar weather, UFO/UAP files, or radio status, and receive a real current dashboard briefing instead of a generic "queued" message.

Phone Flow

Production route:

+15122777311 -> space_channel_network_ops

Important states:

Terminal states keep entry.line for text-mode transcripts and evals. The phone path records and speaks the preceding play_audio.text, then transitions to the terminal and hangs up at a logical completion point.

Audio Learning Applied

The diagnostic calls showed that prerecorded audio was not sufficient by itself. The phone path became clear only when outbound Telnyx media was sent as:

For Space Channel V1, static prompts are still pre-rendered, but dynamic content uses full-buffer droid synthesis plus the same paced sender. This avoids the sentence-by-sentence choppiness that appeared when generation and sending were too tightly coupled.

Latency Learning

The 2026-06-29 phone export showed a separate problem from audio quality. After the caller asked for UFO files, user_transcription and update_slots landed within milliseconds, but the phone did not start the RIFF-owned content audio until about 11.9 seconds later. The intervening audio was Gemini Live output that the phone path suppressed because Space Channel owns those states.

The applied mitigation has three layers:

The deeper follow-up is to fast-forward RIFF-owned act and static chains immediately after a deterministic tool result instead of waiting for Gemini's suppressed turn to complete. That would remove the wait; the processing tone is the caller-facing fallback while that broader handoff is designed.

Next Data Connectors

The V1 cache provides current dashboard presence/status and launch data. The next connectors should deepen the summaries without changing the phone flow:

Those can all write into the same topics object in content_snapshot.json; the phone flow only needs space_content_summary.

Verification

Focused test command:

.venv/bin/python -m pytest \
  tests/test_space_channel_content.py \
  tests/test_space_channel_tools.py \
  tests/test_space_channel_flow.py

Live refresh smoke test:

.venv/bin/python scripts/space_channel_refresh.py --once --json

Static menu audio regeneration:

.venv/bin/python -m riff.static_audio generate \
  --flow space_channel_network_ops \
  --state suggestions_announce \
  --force