Onboarding — six steps gated on a real two-hop verify #13

Closed
opened 2026-07-29 17:32:07 +00:00 by aiko · 1 comment
Owner

What to build

Six screens (card 3a): 待受 → 周波数 → 集音 → 姿 → 重ねて表示 (Android only) → 開局.

周波数 is the only gate, and it gates on real responses from both hops, not on the address field being non-empty: ✓ 中継局 — socket open and ✓ 上流 HERMES — /health 200, joined by a dashed connector. Address plus an optional token (blank is fine on a LAN).

Steps 2–4 are all skippable and each states what you lose. 集音 previews the mic meter before asking for permission. 姿 lists models from the go-between with installed / downloading / not-fetched states. 重ねて表示 only appears on Android.

開局 ends live, with the first transmission on screen.

Design reference: docs/design/denpa-receiver/README.md (card ids 1a, 4a… index into Denpa Receiver.dc.html, openable in a browser).

Acceptance criteria

  • 周波数 will not advance until both hops respond
  • Steps 2–4 are skippable and each names the cost of skipping
  • Android-only step is hidden on other platforms
  • Mic permission is asked with the meter preview, not cold
  • Model list reflects real go-between state including download progress
  • Onboarding does not re-run once completed; reachable again via reset
  • Tests cover the gate logic for each hop-failure combination

Blocked by


Reality audit

Governing rule: build to reality, Hermes leads. Not doing something is acceptable if it does not break core functionality. Breaking the design is acceptable. Building UI that does nothing is not.

Audited against the actual wire surface:

  • Hermes (hermes-agent 0.19.0, verified running): /health, /v1/models, /v1/runs, /v1/runs/{id}, /v1/runs/{id}/events, /v1/runs/{id}/stop, /v1/runs/{id}/approval
  • Run events: message.delta, tool.started, tool.completed, run.completed, run.cancelled, run.failed/run.errored, reasoning.available, approval.request (carries a per-request choices array and sets run status waiting_for_approval; the go-between discards it today — see #19)
  • Go-between → client: full-text, audio, control, error, set-model-and-conf, config-switched, config-files, background-files, history-list, history-data, new-history-created, history-deleted, user-input-transcription, backend-synth-complete, force-new-message, tool_call_status, interrupt-signal, heartbeat-ack, group-update
  • Client → go-between: text-input, mic-audio-data, mic-audio-end, raw-audio-data, ai-speak-signal, interrupt-signal, fetch-history-list, fetch-and-set-history, create-new-history, delete-history, fetch-configs, switch-config, fetch-backgrounds, audio-play-start, request-init-config, heartbeat

Rescoped: verify by transmission, not by health check

周波数 cannot verify the upstream before a turn happens — there is no health message. Gating on "both hops responded" is unbuildable as drawn.

Replace it with something better and real: send a test transmission. The probe is a real text-input round-trip. If a full-text reply comes back, both hops are proven — the socket opened and Hermes answered. That is a stronger guarantee than two status checks, and it is exactly the failure the current app hides.

Render it as the two-hop chain still: socket confirms immediately, upstream confirms when her reply arrives, with the probe visible as a real first transmission rather than a spinner.

Also cut: model download progress. 姿 lists what the go-between offers via config-files / set-model-and-conf. There is no download-progress message, so the "downloading, progress bar over tuning static" state is not buildable. Show installed and selectable only; drop the three-state card.

Everything else in this issue is unchanged. 集音 (mic permission) is real and client-side. The Android step depends on #23.

## What to build Six screens (card 3a): 待受 → 周波数 → 集音 → 姿 → 重ねて表示 (Android only) → 開局. **周波数 is the only gate**, and it gates on *real responses from both hops*, not on the address field being non-empty: `✓ 中継局 — socket open` and `✓ 上流 HERMES — /health 200`, joined by a dashed connector. Address plus an optional token (blank is fine on a LAN). **Steps 2–4 are all skippable and each states what you lose.** 集音 previews the mic meter before asking for permission. 姿 lists models from the go-between with installed / downloading / not-fetched states. 重ねて表示 only appears on Android. 開局 ends live, with the first transmission on screen. Design reference: `docs/design/denpa-receiver/README.md` (card ids `1a`, `4a`… index into `Denpa Receiver.dc.html`, openable in a browser). ## Acceptance criteria - [ ] 周波数 will not advance until both hops respond - [ ] Steps 2–4 are skippable and each names the cost of skipping - [ ] Android-only step is hidden on other platforms - [ ] Mic permission is asked with the meter preview, not cold - [ ] Model list reflects real go-between state including download progress - [ ] Onboarding does not re-run once completed; reachable again via reset - [ ] Tests cover the gate logic for each hop-failure combination ## Blocked by - #11 --- ## Reality audit Governing rule: **build to reality, Hermes leads. Not doing something is acceptable if it does not break core functionality. Breaking the design is acceptable. Building UI that does nothing is not.** Audited against the actual wire surface: - **Hermes** (`hermes-agent 0.19.0`, verified running): `/health`, `/v1/models`, `/v1/runs`, `/v1/runs/{id}`, `/v1/runs/{id}/events`, `/v1/runs/{id}/stop`, `/v1/runs/{id}/approval` - **Run events**: `message.delta`, `tool.started`, `tool.completed`, `run.completed`, `run.cancelled`, `run.failed`/`run.errored`, `reasoning.available`, `approval.request` (carries a per-request `choices` array and sets run status `waiting_for_approval`; the go-between discards it today — see #19) - **Go-between → client**: `full-text`, `audio`, `control`, `error`, `set-model-and-conf`, `config-switched`, `config-files`, `background-files`, `history-list`, `history-data`, `new-history-created`, `history-deleted`, `user-input-transcription`, `backend-synth-complete`, `force-new-message`, `tool_call_status`, `interrupt-signal`, `heartbeat-ack`, `group-update` - **Client → go-between**: `text-input`, `mic-audio-data`, `mic-audio-end`, `raw-audio-data`, `ai-speak-signal`, `interrupt-signal`, `fetch-history-list`, `fetch-and-set-history`, `create-new-history`, `delete-history`, `fetch-configs`, `switch-config`, `fetch-backgrounds`, `audio-play-start`, `request-init-config`, `heartbeat` ### Rescoped: verify by transmission, not by health check **周波数 cannot verify the upstream before a turn happens** — there is no health message. Gating on "both hops responded" is unbuildable as drawn. Replace it with something better and real: **send a test transmission.** The probe is a real `text-input` round-trip. If a `full-text` reply comes back, both hops are proven — the socket opened *and* Hermes answered. That is a stronger guarantee than two status checks, and it is exactly the failure the current app hides. Render it as the two-hop chain still: socket confirms immediately, upstream confirms when her reply arrives, with the probe visible as a real first transmission rather than a spinner. **Also cut: model download progress.** 姿 lists what the go-between offers via `config-files` / `set-model-and-conf`. There is no download-progress message, so the "downloading, progress bar over tuning static" state is not buildable. Show installed and selectable only; drop the three-state card. Everything else in this issue is unchanged. 集音 (mic permission) is real and client-side. The Android step depends on #23.
Author
Owner

Closing in favour of #28, rewritten against the ADRs.

This issue's premise changed with ADR-0001: Denpa is a Hermes gateway Platform adapter and the api_server HTTP surface is abandoned entirely. Patching the body would have left a trail of corrections on top of a stale audit block - the same pattern that got 承認 wrongly cut once already.

Decisions now live in docs/adr/ in the go-between repo (branch docs/hermes-platform-adrs). The replacement issue references them rather than restating them.

Closing in favour of #28, rewritten against the ADRs. This issue's premise changed with ADR-0001: Denpa is a Hermes gateway Platform adapter and the `api_server` HTTP surface is abandoned entirely. Patching the body would have left a trail of corrections on top of a stale audit block - the same pattern that got 承認 wrongly cut once already. Decisions now live in `docs/adr/` in the go-between repo (branch `docs/hermes-platform-adrs`). The replacement issue references them rather than restating them.
aiko closed this issue 2026-07-30 00:03:48 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiko/denpa#13
No description provided.