Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
## Unreleased

### Added: Fish Audio voice/telephony is the 24th chat channel (2026-09-11)
- **Why:** people delegate to agents through chat, so a channel ClawMetry cannot see is a conversation that does not exist in the product — the shape of the original report, *"I message Diya on Telegram and ClawMetry shows nothing"* (#5045).
- **What:** `fish-audio` joins the channel catalogue, its transcripts ingest from `~/.openclaw/fish-audio/*.jsonl`, live events arrive over the gateway tap as `fishaudio`, and `/api/channel/*` serves the tab. The channel count is derived, not typed, so every surface quoting it moved to 24 together.
- **A chat channel is four independent lists, and one in three of them is broken.** `sync._CHANNEL_DIRS` (history ingests), `gateway_tap.CHANNEL_NAMES` (live events arrive), `entitlements.ALL_CHANNELS` + `CHANNEL_LABELS` (the UI and entitlement can see it), and `routes/channels.py` (the endpoint exists). Each omission is silent and looks like a different bug: miss the gateway list and live messages never arrive while historical transcripts ingest normally, which reads as an ingest fault rather than a missing subscription.
- **That rule is now a check, not a review item.** `tests/test_channel_four_lists.py` asserts every catalogued channel appears in both ingest lists, that neither carries an orphan the catalogue does not know, that each has a label, and that the three lists are the same size. Comparison is on a normalised form, because the disk name and the wire name legitimately differ (`fish-audio` on disk, `fishaudio` on the wire) and deriving one list from the other is exactly what the architecture forbids.
- **A comment that would have caused the next half-wired channel is corrected.** The note above `_CHANNEL_DIRS` said adding a directory needed "no further wiring required" — false in precisely the way above — and still claimed "21 adapter routes" when there are 24. It now names all four lists with the symptom for each.
- **Recorded in the product record.** Drift Bot's five findings were one omission: adding the 24th adapter exposed that the whole subsystem had no record. The Runtime and Session Observability blueprint now carries six contracts and an ADR for why these stay four explicit lists rather than one derived registry.
- **Verified:** the four-list guard proven red against a deliberately half-wired channel and green on the tree; `tests/test_entitlement_channel_catalog.py` (27 tests) and the count guard both pass, reading 24 across every surface. Carries #5055, closes #5045.

### Added: the onboarding strip can tell whether anything is actually reaching us (2026-09-11)
- **Why:** a new user wiring up their first runtime had no way to see whether it worked. `GET /api/onboarding/ingest-status` answers "is anything arriving yet?", polled every 2 seconds while the overlay is open (#5680).
- **What:** `LocalStore.query_ingest_status()` does two light passes over `events` — one aggregate (total, 24-hour bucket, first/last timestamps) and one `GROUP BY agent_type` for the per-source breakdown — plus the route in `routes/onboarding.py` and its entry on the daemon query surface in `routes/local_query.py`. No scan of `data` blobs; zone maps on `created_at` keep both passes fast on a large store. Rows written by ClawMetry's own daemon are excluded, so the strip cannot read its own heartbeat as the user's agent.
Expand Down
Loading