WAITING has no treatment, and it happens in every successful turn #58

Closed
opened 2026-07-30 16:53:15 +00:00 by aiko · 1 comment
Owner

WAITING (7d) has no treatment. Split from #15 because it is not a failure at all — it is an ordinary state in the normal run of a turn, and it is the smallest independent piece of that issue.

What the design says

docs/design/denpa-receiver/README.md:158:

| WAITING | 入力中 | WAITING | Not drawn. Use the IDLE floor with the PTT key dimmed; auto-returns to IDLE after 2s per existing context logic. |

And #15's own description: "the meter holds the idle floor, the PTT key goes dark reading 受け取った, 割り込み dims because there is nothing yet to interrupt."

The design's longer note calls it "the state I left undrawn" — she has your words and has not started, so the meter holds its floor while the key goes dark.

Why it is separable

It depends on nothing. It is not keyed off connection state like the five fault screens, it needs no 詳細 reveal, no hop reasoning, and no error text. It is a state treatment in the transmission band and the faceplate, both of which already exist and already switch on AiState.

It is also the one piece of #15 that shows up in every successful turn rather than only when something breaks — so it is the piece most likely to be noticed, and the least likely to be reached if it stays bundled with a taxonomy that is out of v1.

Acceptance

  • After a turn is sent and before she begins, the meter holds the idle floor rather than going dead or continuing to track.
  • The PTT key dims and reads 受け取った.
  • 割り込み dims, because there is nothing yet to interrupt.
  • It auto-returns to IDLE after 2s via the existing context logic, rather than a new timer.
  • #15 — the five fault screens and the reconnect toast
  • #10 — the faceplate and the meter treatments per state
`WAITING` (7d) has no treatment. Split from `#15` because it is not a failure at all — it is an ordinary state in the normal run of a turn, and it is the smallest independent piece of that issue. ## What the design says `docs/design/denpa-receiver/README.md:158`: > | `WAITING` | 入力中 | WAITING | **Not drawn.** Use the IDLE floor with the PTT key dimmed; auto-returns to IDLE after 2s per existing context logic. | And `#15`'s own description: *"the meter holds the idle floor, the PTT key goes dark reading 受け取った, 割り込み dims because there is nothing yet to interrupt."* The design's longer note calls it "the state I left undrawn" — she has your words and has not started, so the meter holds its floor while the key goes dark. ## Why it is separable It depends on nothing. It is not keyed off connection state like the five fault screens, it needs no `詳細` reveal, no hop reasoning, and no error text. It is a state treatment in the transmission band and the faceplate, both of which already exist and already switch on `AiState`. It is also the one piece of `#15` that shows up in **every** successful turn rather than only when something breaks — so it is the piece most likely to be noticed, and the least likely to be reached if it stays bundled with a taxonomy that is out of v1. ## Acceptance - After a turn is sent and before she begins, the meter holds the idle floor rather than going dead or continuing to track. - The PTT key dims and reads 受け取った. - 割り込み dims, because there is nothing yet to interrupt. - It auto-returns to IDLE after 2s via the existing context logic, rather than a new timer. ## Related - `#15` — the five fault screens and the reconnect toast - `#10` — the faceplate and the meter treatments per state
Author
Owner

Done in 3f9fd61 (implementation 376bd0c), merged to main, alongside #59.

What was actually missing

The treatment already existed — faceplate-spec.ts had 入力中 / WAITING with the idle floor, the dark key and 受け取った since #10. What was missing was that nothing entered the state on a turn. It was set only on a keystroke into the old footer (use-input-subtitle.ts:42, use-footer.ts:28), and a PTT release went straight to 送信中, which drew the halate band for the whole of the upstream's think time. So the state that "happens in every successful turn" happened in none of them.

  • transmission.ts pttUp now returns WAITING.
  • use-text-input.tsx handleSend sets WAITING — the one place every typed surface goes through (pal composer, dock composer, pet-mode subtitle bar, footer).
  • 割り込み now dims to rgba(234,255,60,.2) / #5f5a3a per § 7d, and is disabled: a key that looks stood down but still fires would send an interrupt for a turn Hermes has not been handed yet.

Acceptance

  • After a turn is sent and before she begins, the meter holds the idle floor — WAITING's MeterSpec is IDLE's, asserted rather than duplicated
  • The PTT key dims and reads 受け取った (and is unpressable, per § 7d)
  • 割り込み dims, because there is nothing yet to interrupt
  • Auto-returns to IDLE after 2s via the existing context logic — no new timer, asserted

One consequence worth your call

conversation-chain-start is only sent once Hermes has produced the whole turn (denpa/src/open_llm_vtuber/conversations/single_conversation.py:37send_conversation_start_signals runs after the finished text arrives, not when the turn is accepted). So the gap between "sent" and "she begins" is the entire think time, and the 2s return means the dock reads:

入力中 (2s) → 待機 → 送信中

rather than staying at 入力中 until she starts. The meter is unchanged either way — 待機 and 入力中 share the floor — so what actually differs for those seconds is the word, the PTT key coming back to 押して送信, and 割り込み un-dimming.

I built it exactly as written because you asked for the existing 2s and no new timer, and 待機 is at least truthful (nothing is arriving). But if you would rather 入力中 held until she answers, the fix is not a timer — it is that the 2s exists to un-stick a typing debounce, and a sent turn does not need un-sticking. Say the word and I will split it.

Also: sending text while she is mid-sentence interrupts first, and setAiState's own guard (aiState !== THINKING_SPEAKING) may swallow the WAITING that follows within the same tick. Harmless — she is speaking again a moment later — but it means the barge-in path does not always show 入力中.

Gate: 801 vitest across 54 files, 18 Rust.

Done in `3f9fd61` (implementation `376bd0c`), merged to `main`, alongside [#59](https://git.aiko.works/aiko/denpa/issues/59). ## What was actually missing The treatment already existed — `faceplate-spec.ts` had 入力中 / WAITING with the idle floor, the dark key and 受け取った since `#10`. What was missing was that **nothing entered the state on a turn**. It was set only on a keystroke into the old footer (`use-input-subtitle.ts:42`, `use-footer.ts:28`), and a PTT release went straight to 送信中, which drew the halate band for the whole of the upstream's think time. So the state that "happens in every successful turn" happened in none of them. - `transmission.ts` `pttUp` now returns WAITING. - `use-text-input.tsx` `handleSend` sets WAITING — the one place every typed surface goes through (pal composer, dock composer, pet-mode subtitle bar, footer). - 割り込み now dims to `rgba(234,255,60,.2)` / `#5f5a3a` per § 7d, **and is disabled**: a key that looks stood down but still fires would send an interrupt for a turn Hermes has not been handed yet. ## Acceptance - [x] After a turn is sent and before she begins, the meter holds the idle floor — WAITING's `MeterSpec` *is* IDLE's, asserted rather than duplicated - [x] The PTT key dims and reads 受け取った (and is unpressable, per § 7d) - [x] 割り込み dims, because there is nothing yet to interrupt - [x] Auto-returns to IDLE after 2s via the existing context logic — no new timer, asserted ## One consequence worth your call `conversation-chain-start` is only sent once Hermes has produced the **whole** turn (`denpa/src/open_llm_vtuber/conversations/single_conversation.py:37` — `send_conversation_start_signals` runs after the finished text arrives, not when the turn is accepted). So the gap between "sent" and "she begins" is the entire think time, and the 2s return means the dock reads: > 入力中 (2s) → 待機 → 送信中 rather than staying at 入力中 until she starts. The meter is unchanged either way — 待機 and 入力中 share the floor — so what actually differs for those seconds is the word, the PTT key coming back to 押して送信, and 割り込み un-dimming. I built it exactly as written because you asked for the existing 2s and no new timer, and 待機 is at least truthful (nothing is arriving). But if you would rather 入力中 held until she answers, the fix is not a timer — it is that the 2s exists to un-stick a *typing* debounce, and a sent turn does not need un-sticking. Say the word and I will split it. Also: sending text while she is mid-sentence interrupts first, and `setAiState`'s own guard (`aiState !== THINKING_SPEAKING`) may swallow the WAITING that follows within the same tick. Harmless — she is speaking again a moment later — but it means the barge-in path does not always show 入力中. Gate: **801 vitest across 54 files**, **18 Rust**.
aiko closed this issue 2026-07-30 19:53:57 +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#58
No description provided.