Say /new to her: the command surface in 文 compose #85
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#85
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?
The client half of denpatou#30, split out because the acceptance there spans both repos and neither half can be branched or reviewed cleanly as one diff.
Blocked on the go-between half: the catalogue frame has to exist and be named in
hermes_plugin/denpa/protocol.pybefore this can read it. Nothing here invents a frame name.What this is
Everything the operator touches. Today 文 compose sends whatever is typed as speech, so there is no way to say
/new— everything goes to the agent as prose and hopes it lands as a tool call./in 文 compose is sent as a command, not as speech./opens autocomplete over the catalogue the go-between sends: filters as you type, completes on selection.Decided already, do not relitigate
_check_slash_accesswill refuse (decided 2026-08-01 ondenpatou#30). One operator on their own hardware: a refusal is nearly always a misconfiguration, and a command missing from the menu is indistinguishable from Hermes not having it. The refusal speaks instead. Commands filtered out upstream by_is_gateway_availablenever reach the catalogue at all and are a different case — those genuinely cannot run here.Design first
docs/design/denpa-receiver/has nothing for a command surface. The autocomplete's shape at both dock and pal widths wants deciding before it is built —denpatou#30's original open questions named exactly this, and the compose surface itself (denpa#53) is recent enough that its treatment is the thing to build on.Acceptance
/-prefixed text in 文 compose is sent as a command rather than as speech/opens autocomplete over the catalogue frame; it filters as you type and completes on selectiondocs/design/denpa-receiver/before it is built/stoptyped mid-turn actually interrupts her — the end-to-end proof, and the go-between'sbusy_policypass-through is what makes it possibleRelated
denpatou#30(the wire, and every decision behind this),denpa#53(the compose surface this extends),denpatou#32(mismatch 6:slash-confirmreaches no consumer, so an autocompleted command that needs confirming stops silently)Constraint added by the operator, 2026-08-01: only typed text may launch a command. Never speech.
Everything above talks about "text beginning with
/", which is ambiguous in exactly the wrong place. A transcript is also text arriving from a device — Hermes transcribes voice and the result comes back down the same route. So the rule is on the input's provenance, not on its first character:/, or a spoken "slash" that STT renders as one, is speech and is handled exactly as it is today.Why it matters: a spoken
/stopthat really stops her is a microphone that can be triggered by a podcast, a housemate, or her own audio bleeding into an open mic. Commands are deliberate acts, and typing is what makes them deliberate. This is the same family as ADR-0004's asks suspending a turn — a thing that changes state should not be reachable by accident.Added to the acceptance:
/is spoken about, not executed — pinned by a testThe wire landed (
denpatou#30, merged locally as341e43b), and it added a requirement to this ticket.FRAME_TEXT_INnow carriestyped, and the command gate reads that rather than the frame type. The reason is ondenpatou#30: the frame type was evidence of a keyboard only by accident, sinceconversation_handler.pymints one for anytext-input,live/bilibili_live.pymints one from a stranger's chat message, anddenpa#55would mint one from a transcript.So: 文 compose must set
typed: trueon thetext-inputit sends, or no command will ever fire. Absent or false is speech, deliberately — a client that has not learned to say it loses commands rather than gaining a microphone that can run them.Added to the acceptance:
typedon the text-input it sends, and nothing else in the client does