自発送信 — wire real Hermes-initiated turns to the break-in UI #22
Labels
No labels
needs-info
needs-triage
ready-for-agent
ready-for-human
v2
wayfinder:grilling
wayfinder:map
wayfinder:prototype
wayfinder:research
wayfinder:task
wayfinder:ticket
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
aiko/denpa#22
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What to build
HITL — blocked cross-repo. Hermes cannot push an unsolicited turn today (aiko/ollvt-hermes-bridge#16, filed as unscoped and needing its own design pass), and when it can, the trigger name has to reach the client (aiko/ollvt-hermes-bridge#17).
The UI was originally split into #24, which has since been folded back into this issue (see the decision below) — both halves land together here.
Open design questions that aiko/ollvt-hermes-bridge#16 must settle first, and which change client behaviour: does an unprompted turn interrupt an active conversation or queue behind it, and is there rate limiting? The break-in band assumes it can arrive at any time; if turns queue instead, the invocation line needs a pending count.
Design reference:
docs/design/denpa-receiver/README.md.Acceptance criteria
Blocked by
Decision — Hermes owns triggering entirely
All proactive-turn triggering is handled by Hermes. The client decides nothing about when she speaks unprompted.
That closes one of this issue''s two open questions and simplifies the client:
proactive_speak_promptin the go-between''sconf.yamlis a different mechanism — OLLVT prompting itself on an idle timer — and is not what this is.)Still open, and still owned by aiko/ollvt-hermes-bridge#16: whether a broadcast arriving mid-conversation interrupts or queues. If Hermes only ever sends when it decides the moment is right, the client needs no queue and the break-in band as drawn is correct. If turns can stack, the invocation line needs a pending count that nothing currently draws. Default to no queue unless #16 says otherwise.
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-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}/approvalmessage.delta,tool.started,tool.completed,run.completed,run.cancelled,run.failed/run.errored,reasoning.available,approval.request(carries a per-requestchoicesarray and sets run statuswaiting_for_approval; the go-between discards it today — see #19)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-updatetext-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#24 folded back in
The client-side break-in UI is no longer a separate issue. Nothing can trigger an unprompted turn today, so building the band, the invocation line and the parked-tab pulse against a dev-injected message would be UI that does nothing.
Both halves land together when aiko/ollvt-hermes-bridge#16 makes a Hermes-initiated turn possible: trigger attribution, the acid break-in band, the pal invocation line, the parked-tab pulse, and the acid reconnect toast variant for broadcasts missed while dark.
Note
ai-speak-signalalready exists client→server — that is the client asking her to speak, not Hermes initiating. Do not mistake one for the other.Decision — turns queue, and the invocation line draws a pending count
aiko/ollvt-hermes-bridge#16 has settled the second open question: an unprompted turn queues behind an active conversation rather than interrupting it. The "default to no queue" note above is superseded.
What this changes for the client:
backend-synth-complete. The client renders what arrives, when it arrives — that part of the earlier decision stands unchanged.The pending count and the job id arrive on a single new frame, specified as item 4 of aiko/ollvt-hermes-bridge#17.
Missed broadcasts get simpler. The queue is the recovery mechanism: Hermes coalesces per job id (a cron that fired twelve times while the client was dark surfaces once, marked
12x) and applies a per-job TTL to drop stale nudges, then drains on reconnect. The acid reconnect toast announces what is about to drain rather than reconstructing history. The "missed broadcasts are readable after a reconnect" criterion needs no separate machinery.Both open questions from this issue are now closed. It remains blocked on aiko/ollvt-hermes-bridge#16 for the inbound hook itself.
自発送信 — unprompted turns that name their triggerto 自発送信 — wire real Hermes-initiated turns to the break-in UITransport decided — Hermes Platform adapter, and this issue gains a second trigger path
ollvt-hermes-bridge#16settled how an unsolicited turn reaches the client: a real Hermes Platform adapter, built on the plugin path (~/.hermes/plugins/,register_platform()in aregister(ctx)entry point, zero changes to core Hermes). Not the go-between polling, which was briefly the plan.What this changes for this issue:
send_messagetool can target Denpa from any context — she can speak because the agent decided to, not merely because a schedule fired. The break-in UI must not assume ajob_idexists for every unsolicited turn.cron:morning.brief|webhook:github-pr. Webhook routes (gateway/platforms/webhook.py) are proactive from the client's view and identified by route name. Seeollvt-hermes-bridge#17item 4.deliver: denpabecomes a first-class cron delivery target viacron_deliver_env_var="DENPA_HOME_CHANNEL".standalone_sender_fntakes no metadata, so a job fired by a standalonehermes cron tickwith the gateway down arrives with no id. Degrade to a generic break-in; do not drop the turn.pendingno longer comes from counting unread output files. That derivation belonged to the withdrawn polling design. It now has to ride along from the Hermes-side queue — open sub-question onollvt-hermes-bridge#16.Unchanged: Hermes owns triggering and the queue, turns queue rather than interrupt, the client renders what arrives when it arrives.
Correction to this issue's Blocked-by list: 承認 is not part of what
ollvt-hermes-bridge#16unblocks, and never was — see #26. It has had a complete data path on/v1/runsall along.Blocked-by list is stale
#24is still listed as a blocker but is closed — folded back into this issue by the "#24 folded back in" decision above. Both halves land together here, so the entry should go.Remaining real blockers are
ollvt-hermes-bridge#16(the Platform adapter and the go-between's inbound receiver) andollvt-hermes-bridge#17item 4 (thetrigger+pendingframe).Also: the run-events list in this issue's reality audit omits
approval.request, which Hermes 0.19.0 does emit. It does not affect this issue's scope — 承認 is tracked at #19 — but the pasted audit block is a snapshot, not an authority, and it appears in several sibling issues with the same omission.Closing in favour of #32, rewritten against the ADRs.
This issue's premise changed with ADR-0001: Denpa is a Hermes gateway Platform adapter and the
api_serverHTTP 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 (branchdocs/hermes-platform-adrs). The replacement issue references them rather than restating them.