Give the transcript its own frame instead of parsing it out of her prose #56
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#56
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 transcript of what you said should travel as its own frame, instead of being recovered by pattern-matching her reply.
Split from #55 so it is not held behind the on-device-whisper decision. This is the piece that answers "what is actually being transmitted", and it needs no model and no new dependency.
What happens today
Hermes owns the ASR —
#21stripped the go-between of it, andhermes_plugin/denpa/adapter.py:432sends voice up as aMessageType.VOICE.wav. The transcript only comes back if she echoes it in prose, wherehermes_plugin/denpa/protocol.py:175regex-matches it out:So whether the operator can see what was heard depends on her choosing to repeat it, in that exact shape, with that exact emoji. If she paraphrases, or the platform hint's "answer first" instruction wins, the transcript never appears — and nothing reports that it did not.
This is the same failure class ADR-0011 removed from pairing: something load-bearing recovered by parsing her prose. Every authentication defect in this project came out of that pattern. It is smaller here — a missing transcript is not a security hole — but it is the same shape, and it is the last place the pattern survives.
What is needed
FRAME_TRANSCRIPTIONalready exists as a name; it needs a real producer rather than a regex._TRANSCRIPT_ECHOand the prose branch inclassify_outboundonce the frame exists. Leaving both means two sources for one fact, and they will disagree.#17owns the row design, and a transcript is a row about what you said rather than what she did.Acceptance
Related
#55— on-device whisper, which would change where the transcript comes from but not that it needs a frame#17— the log and its row design#23(ollvt-hermes-bridge) — the other classifier that guesses intent from her text; being deleted under ADR-0011The transcript travels as its own frame now, and the prose parse is gone.
Go-between —
ollvt-hermes-bridge@16fb05d(merge ofe3de73c)_TRANSCRIPT_ECHOand its branch inclassify_outboundare deleted (hermes_plugin/denpa/protocol.py). A reply of hers that happens to be one quoted sentence is spoken, which is what the regex got wrong._install_transcript_relay()(hermes_plugin/denpa/adapter.py:822) wrapstools.transcription_tools.transcribe_audioatregister()time; the adapter recorded which device each wav belongs to when it wrote it (_dispatch_media->remember_voice), and the path travels unchanged to the ASR (gateway/run.py:12665-12680), so the frame is keyed to the turn without guessing.FRAME_TRANSCRIPTIONfinally has a real producer.pre_gateway_dispatchfires before transcription (gateway/run.py:11018) andpre_llm_callis handed the already-enriched user message (agent/turn_context.py:1054), not the transcript.hermes-agentis read-only, so the call site is the only seam. Other platforms are unaffected: a clip no adapter owns emits nothing, and the ASR's result is returned untouched.text: ""rather than nothing, so absence is a row instead of silence.stt_echo_transcriptsis gateway-wide (gateway/run.py:15813) and cannot be turned off for one platform; with the regex gone,🎙️ "..."would classify as speech and be synthesised.send()drops it by identity against a transcript this adapter emitted (protocol.stt_echo), never by shape — that is the trap the regex was.Client —
denpa@cdc719a(merge ofb936bf7)user-input-transcriptionwas aconsole.logplus an append only when text was present. It now always draws a 自分 row in 受信記録: the words when the ASR made them out,聞き取れず(faint) when it did not. Theunheardflag is client-side only.adapter_handler.py:482already forwardsdenpa.transcriptionverbatim, empty text included; a test now pins that.Gates
236 passed(uv run python -m pytest tests/ -q), 6 new intests/test_transcript_frame.pyplus 1 intest_adapter_frames.py.55 files, 799 passed(npm test), 4 new intranscript-row.test.tsx;23 passedfor Rust;npx tsc --noEmitadds no error in the touched files.What I did not do
The acceptance asks for verification by speaking, and I did not speak to the stack — no audio in this session. I synced
hermes_plugin/denpainto%LOCALAPPDATA%\hermes\plugins\denpa(it was one commit stale) so the wrap is installed, but the gateway has to be restarted before it takes effect. Until someone speaks a turn, the frame is proven by tests and by readinggateway/run.py, not by a transcript on screen. If it does not appear, the first thing to check is thatregister()ran after the sync — the wrap is installed there and nothing else reports it.Closing on the merges above; reopen if speaking a turn draws no row.