From 1467f98c964dc74fb8bfeef66b5136a0b004feee Mon Sep 17 00:00:00 2001 From: Valentin Haudiquet Date: Thu, 5 Nov 2026 19:12:18 +0100 Subject: [PATCH] docs: the phone reports are state, not conversation The claw README claimed the phone ingest dispatches battery, network, and DND flips to the agent; the ingest door stores topic-keyed payloads and answers "observed", and the Android worker posts nothing but topic keys. The README now says state-only with the bare phone: key as the dispatch path, and the worker's comment matches what it actually posts. --- .../java/rs/rhema/phone/work/PhoneStatusWorker.kt | 12 ++++++------ crates/rhema-claw/README.md | 9 ++++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/android/app/src/main/java/rs/rhema/phone/work/PhoneStatusWorker.kt b/android/app/src/main/java/rs/rhema/phone/work/PhoneStatusWorker.kt index 334e068..25f4061 100644 --- a/android/app/src/main/java/rs/rhema/phone/work/PhoneStatusWorker.kt +++ b/android/app/src/main/java/rs/rhema/phone/work/PhoneStatusWorker.kt @@ -29,12 +29,12 @@ import kotlinx.serialization.json.put // WorkManager's exponential backoff (up to hours), the exact silence the // fleet reads as "last seen hours ago". // -// Two kinds of topic leave this worker. Battery, network, and DND posts are -// conversation: the claw dispatches them and the agent hears the flip. The -// rest — location, app, device, wifi, alarm, heartbeat — are snapshot-only on -// the claw -// (its ingest door answers "observed" and never runs a turn), so their rules -// only bound write traffic, not model traffic. +// Every post here is topic-keyed (`phone::`), so every +// post is snapshot-only on the claw: the payload lands in the phone +// tables, the ingest door answers "observed", and no turn runs — the +// topic rate rules only bound write traffic, not model traffic. A +// dispatch to a device goes through its bare `phone:` key, +// which this worker never posts to. class PhoneStatusWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { override suspend fun doWork(): Result = try { diff --git a/crates/rhema-claw/README.md b/crates/rhema-claw/README.md index e91507e..614b54c 100644 --- a/crates/rhema-claw/README.md +++ b/crates/rhema-claw/README.md @@ -235,10 +235,13 @@ reaches the chat as something to view or download rather than a truncated snippet. The phone is reachable too. Its status reports (`/v1/ingest`, source -`phone`, keys `phone::`) are conversation *and* state: -the payload lands in the phone tables, so the `phone` tool's +`phone`, keys `phone::`) are state, not conversation: +the payload lands in the phone tables and stops there — no turn runs, +no push notification goes out per flip — so the `phone` tool's `status`/`devices` actions read the latest battery, charging, network, -and DND observations without asking anyone. Acting on the phone — +and DND observations without asking anyone. A bare `phone:` +key is the device's resident dispatch key: a message posted to it runs +a turn like any resident key's. Acting on the phone — `dnd_on`, `dnd_off`, `alert` — is consent-gated end to end: the tool raises a consent card, the human approves or denies, and only then does the command join `GET /v1/phone/commands?device=`, the poll list the