Skip to content

fix(media): transcript echo mangles $ sequences in transcribed audio#100181

Closed
UditDewan wants to merge 2 commits into
openclaw:mainfrom
UditDewan:fix/echo-transcript-dollar-substitution
Closed

fix(media): transcript echo mangles $ sequences in transcribed audio#100181
UditDewan wants to merge 2 commits into
openclaw:mainfrom
UditDewan:fix/echo-transcript-dollar-substitution

Conversation

@UditDewan

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes an issue where users with tools.media.audio.echoTranscript enabled receive a corrupted transcript echo when the transcribed speech contains $ sequences. Sending a voice note transcribed as tickets cost $$40, confirm with $& gets echoed back as:

📝 "tickets cost $40, confirm with {transcript}"

$$ collapses to $, $& is replaced with the {transcript} placeholder itself, and $` / $' splice in surrounding text from the echo format. The same defect exists in the Matrix plugin's preflight audio transcript echo.

Why This Change Was Made

Both echo paths insert the transcript into the format template via String.prototype.replace(pattern, string), which interprets JS substitution patterns ($$, $&, $`, $') in the replacement string. Switching to a function replacer (.replace("{transcript}", () => transcript)) inserts the transcript verbatim while keeping the existing replace-first-occurrence semantics. No config, API, or default changes.

Both sibling surfaces with this pattern are fixed in this PR (src/media-understanding/echo-transcript.ts and extensions/matrix/src/matrix/monitor/preflight-audio.ts); a repo-wide search for {transcript} replacement sites found no others.

User Impact

Voice-note transcript echoes now always show exactly what was transcribed, including dollar amounts and $ sequences, on all channels using the shared echo path and on Matrix preflight audio.

Evidence

Repro of the defect (Node REPL, before vs. after):

$ node -e "const f='📝 \"{transcript}\"', t='tickets cost \$\$40, wait for the deal & confirm with \$&';
console.log('before:', f.replace('{transcript}', t));
console.log('after :', f.replace('{transcript}', () => t));"
before: 📝 "tickets cost $40, wait for the deal & confirm with {transcript}"
after : 📝 "tickets cost $$40, wait for the deal & confirm with $&"

Regression tests added next to the existing echo tests in both files ("keeps dollar sequences in the transcript literal"). Verified they fail against the unfixed code and pass with the fix:

  • npx vitest run src/media-understanding/echo-transcript.test.ts → 8 passed (with fix); the new test fails with AssertionError when the fix is stashed.
  • npx vitest run extensions/matrix/src/matrix/monitor/preflight-audio.test.ts → 9 passed.
  • pnpm test:extension matrix: the touched test file passes; the lane reports failures only in unrelated matrix auth/crypto suites (e.g. legacy-crypto-restore.test.ts) that this diff does not touch and that correspond to lanes currently failing on main CI.
  • oxlint on the four touched files: clean.

This PR is AI-assisted.

sendTranscriptEcho and the Matrix preflight echo insert the transcript into
the echo format via String.prototype.replace with a plain string replacement,
so JS substitution patterns in the transcribed speech are interpreted instead
of echoed literally: $$ collapses to $, $& duplicates the {transcript}
placeholder, and $` / $' splice in surrounding format text.

Use a function replacer so the transcript is always inserted verbatim.
@openclaw-barnacle openclaw-barnacle Bot added channel: matrix Channel integration: matrix size: XS labels Jul 5, 2026
@clawsweeper

clawsweeper Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 5, 2026, 1:54 AM ET / 05:54 UTC.

Summary
The PR changes the shared media and Matrix preflight transcript echo formatters so transcribed text is inserted literally instead of being parsed as JavaScript replacement tokens.

PR surface: Source +4, Tests +32. Total +36 across 4 files.

Reproducibility: yes. Current main has direct string replacement in both echo formatters, and a local Node check reproduces the reported replacement-token behavior for $$ and $&.

Review metrics: none identified.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Resolve or rerun the failed CI shards before merge if they remain red on the current head.

Risk before merge

  • [P1] Live GitHub reports mergeStateStatus UNSTABLE with some failed CI shards, and this read-only review did not attribute those failures to the diff.

Maintainer options:

  1. Decide the mitigation before merge
    Land this narrow formatter fix once the current-head CI and normal maintainer merge gates are satisfied.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • No repair job is needed because the PR already contains a narrow code fix and regression tests; normal maintainer review and CI gates are the remaining path.

Security
Cleared: The diff changes only transcript string formatting and adjacent Vitest coverage; no security or supply-chain surface is touched.

Review details

Best possible solution:

Land this narrow formatter fix once the current-head CI and normal maintainer merge gates are satisfied.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main has direct string replacement in both echo formatters, and a local Node check reproduces the reported replacement-token behavior for $$ and $&.

Is this the best way to solve the issue?

Yes. A function replacer is the narrowest maintainable fix because it preserves first-placeholder replacement semantics while preventing JavaScript replacement-token parsing of transcript text.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 3cf0d00d90f9.

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied terminal output showing the before/after JavaScript replacement behavior that this formatter patch changes, plus targeted regression test results.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes copied terminal output showing the before/after JavaScript replacement behavior that this formatter patch changes, plus targeted regression test results.

Label justifications:

  • P2: The PR fixes a user-visible transcript echo corruption bug with limited channel/message formatting blast radius.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes copied terminal output showing the before/after JavaScript replacement behavior that this formatter patch changes, plus targeted regression test results.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied terminal output showing the before/after JavaScript replacement behavior that this formatter patch changes, plus targeted regression test results.
Evidence reviewed

PR surface:

Source +4, Tests +32. Total +36 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 6 2 +4
Tests 2 32 0 +32
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 38 2 +36

What I checked:

Likely related people:

  • AytuncYildizli: Merged PR feat(audio): auto-echo transcription to chat before agent processing #32150 added echoTranscript, echoFormat, sendTranscriptEcho behavior, and adjacent tests. (role: introduced shared echoTranscript behavior; confidence: high; commits: ad765098d9b4, 290f8d56227f; files: src/config/types.tools.ts, src/config/zod-schema.core.ts, src/media-understanding/apply.ts)
  • steipete: GitHub metadata shows steipete merged the original echoTranscript feature PR, and commit 6545317 split the current echo helper out of apply.ts. (role: merger and refactor author; confidence: high; commits: 6545317a2cb9, ad765098d9b4; files: src/media-understanding/echo-transcript.ts, src/media-understanding/apply.ts, src/media-understanding/audio-preflight.ts)
  • frankdierolf: PR feat(matrix): transcribe inbound voice notes before mention gate #78069 introduced the Matrix preflight audio module, tests, and handler wiring that current main now uses around this formatter path. (role: Matrix preflight feature contributor; confidence: medium; commits: d62859de7267, d8c5b1929253; files: extensions/matrix/src/matrix/monitor/preflight-audio.ts, extensions/matrix/src/matrix/monitor/preflight-audio.test.ts, extensions/matrix/src/matrix/monitor/handler.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (1 earlier review cycle)
  • reviewed 2026-07-05T05:23:38.455Z sha 04b307e :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. labels Jul 5, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 5, 2026
@steipete steipete self-assigned this Jul 5, 2026
@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Thank you for the contribution. This fix landed with contributor co-authorship preserved in #100258 (deac98eb7204fdb51589c5e369b95be128215e77).

I consolidated the source fixes into a maintainer takeover because the contributor branches were based on rewritten pre-main history; updating them directly would have pulled unrelated changes into the review surface. Closing this PR as superseded by the landed batch.

@steipete steipete closed this Jul 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: matrix Channel integration: matrix P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: XS status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants