Two owner rulings, 2026-10-01 ('nothing gets lost' round):
1. SUBMIT FINISHES DICTATION FIRST. Every submit path — the dock's
answer (Enter/Cmd+Enter/button) and the composer's send — stops any
live run and lets Deepgram's last finals land in the target field
BEFORE building the payload. Dictation.finish() resolves at cleanup,
post-flush; a module finisher registry (same pattern as the question
target) hands it to the dock without a prop bridge. Field values are
read from REF MIRRORS (thinkingTextRef/answerTextRef, the composer's
textRef): the flush lands via setState after an await, invisible to
the closure. The quiz flow the owner described now holds: dictate
reasoning → pick answer → pick confidence → Enter → dictation ends,
reasoning saved into the thinking field, THEN the answer submits.
The composer stays sendable while a run is live (its spoken text is
deferred in the run's buffer) so Enter can trigger the finish-first
send at all; nothing said → the send no-ops.
2. RUN END FOCUSES THE BARE COMPOSER. The falling edge of
dictation.active focuses the composer's textarea — only when the
composer is mounted: a pending question unmounts it (ref null, no
focus), so the thinking field is deliberately left alone. Composer
gains an optional inputRef for the page's focus handle.