DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path change-requests/voice-listening-silence-submit-change-request-v0_2.md

Voice listening silence-submit change-request

Version. 0.2 Date. 2026-05-20 Author. Claude.ai (this conversation) Working machine. The Mac Mini, with Claude Code as the executor Repository. DUNIN7/loomworks-engine (substrate, small) and DUNIN7/loomworks (frontend, primary) Substrate baseline. loomworks-engine main at tag voice-provenance-v0_1 (assumed; the voice-provenance ship lands first). Frontend baseline. loomworks branch phase-60-operator-layer-upload-pathway-v1 at tag voice-provenance-v0_1 (assumed). Grounded in.


Plain-language summary

This change-request adds a silence-detection submit path to the voice listening hook, in addition to the existing explicit "say 'send' to submit" path.

Today, voice listening on the in-engagement surface (and on engagement-navigation, parallel) requires the Operator to say the word "send" at the end of their utterance to commit the transcript. Without "send", the Web Speech API's built-in silence timeout fires and the transcript is discarded (handled as a cancel).

This works well for deliberate dictation — long thoughts, multiple sentences, pauses for thinking, then explicit close with "send". It fails for short conversational utterances like "Companion, where did I park?" where the Operator's natural speech rhythm has them stop talking when they're done. Today they have to remember to say "send" or they lose the transcript.

After this ships:

What you (the Operator) see after this ships.

Open an engagement. Click the microphone. Say "Rico, where did I park?" (or "Companion, where did I park?" if you haven't renamed your Companion, or just "where did I park?" without addressing it at all) — stop talking. After ~2.5 seconds of silence, the panel closes, the transcript commits as your turn, the Companion replies. No need to say "send".

The voice infrastructure doesn't listen for the Companion's name — it captures whatever you say and routes it as a turn. Whether you address the Companion explicitly (by default name "Companion", or by whatever custom name you've given it like "Rico"), or just speak the question directly without an addressee, the transcript flows the same way.

For a longer dictation, say a paragraph, pause mid-thought (1 second is fine), continue, pause again, finish. Say "send" to explicitly close — that submits immediately, no waiting for the silence threshold. The "send" override still works.

For Operators who prefer the explicit-only model, say "don't wait, only send on 'send'" to the Companion — the silence_submit_seconds setting goes to 0, behavior reverts to today's.

For shorter or longer thresholds, say "wait three seconds before sending" (or any value in seconds between 0.5 and 10) — the setting tunes accordingly.

What this change-request does not do.

Estimated effort. Two checkpoints — Section A small substrate work (new setting key + tune_setting vocabulary extension), Section C primary frontend work (extend the useVoiceListening hook with silence detection + wire the threshold + update panel footer text).

Methodology inheritance. Companion-tunable-settings-as-Companion-said-not-menu-clicked — the silence threshold is adjusted by speaking to the Companion. Loomworks-pattern-over-imported-convention — voice as a thinking-surface interaction supports both deliberate-with-explicit-close and conversational-with-natural-close rhythms; the choice isn't imported from a specific assistant convention. Thinking-surface-not-messaging-surface — voice on a thinking surface needs to handle both rhythms because thinking spans them.


Step 0 — Codebase inspection block

Step 0.1 — Pre-flight


ls -la /Users/dunin7/loomworks-engine
ls -la /Users/dunin7/loomworks
cd /Users/dunin7/loomworks-engine && git status
cd /Users/dunin7/loomworks && git status
git -C /Users/dunin7/loomworks-engine log --oneline -3
git -C /Users/dunin7/loomworks log --oneline -3

Both working trees clean. Substrate at voice-provenance-v0_1 or later. Frontend at the same.

Step 0.2 — Existing voice listening hook shape

Confirm the current shape of the voice listening hook:


cd /Users/dunin7/loomworks
cat src/app/operator/engagement-navigation/useVoiceListening.ts | head -80

Report:

The silence-submit work hooks into the interim-transcript-update path — each interim transcript event resets a silence timer; when the timer fires without further interim events, silence-submit triggers.

Step 0.3 — tune_setting handler current shape

Confirm the handler's executor dispatch and existing setting keys:


cd /Users/dunin7/loomworks-engine
grep -n "_execute_enum_setting\|_execute_numeric_setting\|_execute_stepped_int_setting\|KNOWN_SETTINGS" src/loomworks/orchestration/tune_setting.py src/loomworks/preferences/person_settings.py | head -20

The handler currently has three executors:

The new setting voice.listening.silence_submit_seconds is a numeric float (similar shape to blur_intensity but with different bounds and a meaningful 0-value). Either reuse _execute_numeric_setting with appropriate spec parameters, or add a small dispatch branch. Claude Code's call at execution.

Step 0.4 — VoiceListeningPanel footer text

Confirm where the listening panel's footer text is rendered:


cd /Users/dunin7/loomworks
grep -n "say.*send.*submit\|esc to cancel" src/app/operator/engagement-navigation/VoiceListeningPanel.tsx

The footer text is a hardcoded string today. This ship makes it conditional on whether silence_submit_seconds > 0.

Step 0.5 — Halt-or-proceed

If any check surfaces drift (especially around the _execute_stepped_int_setting retire — if it was retired, this ship may need it re-introduced for numeric float settings with floor/ceiling like silence_submit_seconds), halt and report. If everything matches, proceed to Section A.


Section A — Substrate

A.1 — New setting key

KNOWN_SETTINGS in person_settings.py gains voice.listening.silence_submit_seconds:

A.2 — tune_setting handler vocabulary

_LABEL_TO_KEY gains:

Direction vocabulary on this setting:

The numeric-parsing branch is the new shape — prior settings (blur intensity, message order, banner duration) didn't accept arbitrary numeric values from the Operator; they used named direction tokens. Voice silence threshold benefits from explicit numeric input because Operators often have a specific feel for what duration works for them. The parser accepts patterns like "N seconds", "N second", "N.N seconds", "N", "N.N" — extracted from the operation_data direction string. If parsing fails or value is out of bounds, fall back to no-change with a Companion-spoken explanation.

A.3 — _value_in_plain_words extension

The plain-words renderer handles the new key:

A.4 — Tests

Per-write tests:

Approximately ten to fifteen new pytest tests.

A.5 — Intent classifier taxonomy update

intent_classifier.md gains:

A.6 — Responder template tightening

tune_setting.md adds the new setting's deterministic message templates (per the existing pattern):


Section B — Companion handler

No new Companion handler. The existing tune_setting handler's vocabulary extends in Section A. Section deliberately empty.


Section C — Frontend

C.1 — useVoiceListening hook silence detection

The hook extends with a silence-detection mechanism:

C.2 — Setting re-read on listen open

Each time the Operator opens the listening panel (microphone click → start listening), the hook re-reads the silence_submit_seconds setting. This matches the blur intensity pattern — the setting is read fresh on each open so Companion-spoken changes take effect on the next listening session.

C.3 — Panel footer text

VoiceListeningPanel.tsx's footer text becomes conditional:

The footer reads the current setting (passed as a prop from the hook) and renders accordingly.

C.4 — No visible countdown

The panel does not show a visible countdown of "submitting in 2.5s…". The silence-submit fires when the threshold elapses; the panel just closes. Operators who want explicit control use "send"; those who let silence resolve get a clean implicit close.

(Rationale: a visible countdown would clutter the panel and might invite the Operator to keep talking just to "reset the timer" mid-thought. The submit happens or it doesn't; if the Operator wants explicit control, "send" is always available.)

C.5 — Tests

Vitest unit tests cover:

Approximately ten to fifteen new vitest tests.


Section D — Verification

Checkpoint A — substrate setting key + handler extension.


cd /Users/dunin7/loomworks-engine
pytest tests/test_voice_tune_setting* tests/test_voice_silence* -v
pytest

New tests pass; full suite shows no regressions beyond the two pre-existing baseline failures.

Halt for Operator review.

Checkpoint C — frontend hook + panel.


cd /Users/dunin7/loomworks
npm test
npm run build

All existing vitest tests plus the new tests pass. Build succeeds.

Smoke test. Operator opens an engagement. Confirms:

  1. Default silence-submit behavior. Click the microphone, say "Companion, where did I park?" (or "Rico, where did I park?" if you've renamed the Companion, or just "where did I park?" without addressing it) — stop talking. Within 2.5 seconds of silence, the panel closes, the transcript appears as a turn, the Companion replies. No need to say "send". The behavior is the same regardless of whether the utterance addresses the Companion by name or not.
  1. Explicit "send" still works. Click the microphone, say a longer dictation with deliberate pauses, say "send" to close. Panel closes immediately on "send"; transcript routes; turn appears with voice glyph (from prior voice-provenance ship).
  1. Tune via Companion — disable. Say "don't wait, only send on send" to the Companion. Click microphone, speak, stop talking — wait 5+ seconds. Confirm the panel does NOT auto-close; only Cancel/Escape/explicit-"send" closes it.
  1. Tune via Companion — adjust. Say "wait five seconds before sending". Click microphone, speak, stop talking — confirm the silence-submit fires at ~5 seconds, not ~2.5.
  1. Reset. Say "reset wait time". Back to default 2.5 seconds.
  1. Audit ledger captures. Run:

``` psql -h localhost -U playground -d playground_dev -c "SELECT timestamp, payload->>'setting_key' AS key, payload->>'previous_value' AS prev, payload->>'new_value' AS new FROM audit.foray_events WHERE payload->>'setting_key' LIKE 'voice.listening.silence%' ORDER BY timestamp DESC LIMIT 5;" ``` Press q to exit pager. Recent silence-threshold changes should appear as audit rows.

Halt for Operator visual confirmation.


Section E — Acceptance criteria

  1. The voice listening hook detects silence after the Operator stops talking and submits the transcript when the configured threshold elapses.
  2. The "send" verb path remains unchanged — explicit submission still works immediately on "send".
  3. The Operator can adjust the silence threshold via Companion utterances (longer / shorter / specific seconds / disable / reset).
  4. Setting voice.listening.silence_submit_seconds persists in person_settings; default 2.5, special value 0 disables silence-submit.
  5. The listening panel's footer text reflects the active mode.
  6. Each setting change writes a FORAY audit row.
  7. All existing tests continue to pass; new tests cover the silence-submit mechanism and the threshold tuning.
  8. The Operator confirms by eye that a natural-ended utterance (whether addressed to the Companion by default name "Companion", by custom name like "Rico", or with no addressee at all) submits naturally without saying "send".

Section F — Out of scope


Section G — Methodology inheritance

G.1 — Companion-tunable-settings-as-Companion-said-not-menu-clicked

Honored. The silence threshold is adjusted by speaking to the Companion ("wait longer", "wait 3 seconds", etc.). No menu surface is added.

G.2 — Loomworks-pattern-over-imported-convention

Honored. Voice as a thinking-surface interaction supports both deliberate (explicit-send) and conversational (natural-silence) rhythms. The choice isn't imported from a specific assistant convention.

G.3 — Thinking-surface-not-messaging-surface

Honored. Voice on a thinking surface needs to handle both rhythms because thinking spans them — quick conversational asks ("Companion, where did I park?") and longer deliberate compositions both deserve clean submission paths.

G.4 — Operator-tunable defaults with sensible starting point

Honored. The default 2.5 seconds is a reasonable starting point that most Operators will accept; those who prefer different timing or the explicit-only model can tune via Companion.

G.5 — FORAY-audit-for-narrative-events

Honored. The new setting changes write FORAY audit rows via the existing _audit_setting_change mechanism. Adds another narrative event type to the substrate's audit ledger.


Operator approval


Approved for execution.
- Marvin Percival
- [timestamp]

Once approval is recorded, Claude Code executes end-to-end, halting at Checkpoints A and C.


Document trailer

DUNIN7 — Done In Seven LLC — Miami, Florida Voice listening silence-submit change-request — v0.2 — 2026-05-20 Grounded in the voice-listening-timeout-reset follow-on filed during the engagement-list scoping ship and the Companion-tunable-settings methodology candidate Builds on voice-provenance-v0_1 (assumed prior ship) Requires Operator approval before Claude Code begins execution.