fix(meetings): strip the chat marker from the translation source (#6763) - #6927
Conversation
Design Review (Fable 5) — ✅ PASSDesign-level review of Design-Verdict: PASS One anchored strip at the single enqueue seam, agent/transcript bytes untouched, spec updated in-commit — real harm, minimal and proportionate fix. [DESIGN-REVIEWED] 9ca42c7 |
Opus 4.8 Review — ✅ no blocking findingsReviewed Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
GPT 5.6 Review — ✅ no blocking findingsGPT 5.6 completed its review of This comment is updated in place on each push. Review detailsNo findings. False positive or not applicable? A repository writer can comment: |
First Principles Review (Fable 5) — ✅ PASSPremise-level review of All claims verified. The change is fully declared, the single First-Principles-Verdict: PASS A reported defect fixed at its mechanism, in the one call site that has it, with the residual cause named and deferred rather than hidden. What this change shipsIntent: typed meeting-chat lines stop showing the internal
WatchThe strip is a parse-back heuristic only because chat-ness is flattened into the string at [FIRST-PRINCIPLES-REVIEWED] 9ca42c7 |
Typed/chat lines are broadcast with the internal [chat] marker prepended so
the meeting agents can tell typed input from speech. The same prefixed line
flowed into TranslationQueue.enqueue, so the literal marker was spent as
translation-prompt tokens and surfaced in the TranslationSidebar's source
column. The stored transcript was never affected.
MeetingSession.broadcast now derives the translation source from the raw
line with a leading, whitespace-bounded CHAT_PREFIX stripped BEFORE
dictionary correction and the transcript-length cap run, so a max-length
typed message is capped on its payload rather than losing its tail to the
marker's characters. This also makes the code match what its own comment
and the module spec already documented (translation from the corrected
text). The agent-broadcast line and the stored transcript are
byte-identical to before. One consequence: typed filler ("ok") now falls
under the same noise gate as spoken filler and is dropped from the
translation panel only.
Closes #6763
23ea2a1 to
9ca42c7
Compare
|
Disposition of the GPT 5.6 blocking finding on 23ea2a1 (max-length typed lines lose their final seven characters in translation): FIXED in 9ca42c7, using the finding's own remedy -- the marker is now stripped from the raw line before dictionary correction and the transcript-length cap, so the cap is charged against the payload. New regression test test_a_max_length_typed_line_keeps_its_full_payload_in_translation is red on the strip-after-clamp variant and green on this head. All review lanes re-run on the new head. |
|
Disposition of the First Principles Watch note (thread is_chat out-of-band through broadcast's single caller instead of the parse-back heuristic): accepted-and-deferred into the same tracked follow-up as the dictionary-mangles-the-marker class -- the FP observation that one is_chat parameter retires the heuristic, the dictionary sibling, and the agent-line clamp charge together is recorded with it. Kept out of this PR because it changes agent-visible bytes this PR deliberately freezes. Review-ready summary for head 9ca42c7: all CI checks green (flaky test_cli_logging shard rerun green, zero overlap with this diff), CodeQL success, PR Readiness success, and all five review lanes clean on this head (GPT + Opus no blocking, Design PASS, First Principles PASS, UX pass). One fix round: GPT's blocking max-length-tail-loss finding on the first head was fixed with its own remedy (strip before correct/clamp) plus a mutation-verified ceiling test. Merge is the maintainer's call. |
bolichen97
left a comment
There was a problem hiding this comment.
Tier 1 auto-approve: fix (3 files). Criteria: no conflict, no requested changes, security path denylist clean, design-doc gate clean, SAST annotations clean, security checklist all-NO, AI reviewers green. Category: strips the [chat] agent-context marker from the translation source before enqueue so it is not translated or surfaced in the panel source column (clear root cause). Spec files changed as a ride-along (a minority of the diff on both file count and changed lines), not reviewed as a design decision: docs/system-specs/modules/meetings.md.
iamwhatever
left a comment
There was a problem hiding this comment.
Tier 1 auto-approve: fix (3 files). Criteria: no conflict, no requested changes, security path denylist clean, design-doc gate clean, SAST annotations clean, security checklist all-NO, AI reviewers green. Category: single root cause -- the CHAT_PREFIX marker is agent context rather than speech, so enqueueing the raw line sent it to translation and surfaced the literal marker in the source column; the fix strips the marker from the raw line before correction and the length cap. Spec files changed as a ride-along (a minority of the diff on both file count and changed lines), not reviewed as a design decision: docs/system-specs/modules/meetings.md.
bolichen97
left a comment
There was a problem hiding this comment.
Tier 1 auto-approve: fix (3 files). Criteria: no conflict, no requested changes, security path denylist clean, design-doc gate clean, SAST annotations clean, security checklist all-NO, AI reviewers green. Category: clear root cause -- MeetingSession.broadcast passed the [chat]-prefixed line to TranslationQueue.enqueue, persisting the internal marker into translations; the fix strips it at the enqueue boundary. Spec files changed as a ride-along (a minority of the diff on both file count and changed lines), not reviewed as a design decision: docs/system-specs/modules/meetings.md. [Note: the auto-merge arm is denied by this cron agent's permission posture; merge deferred to a human maintainer.]
What is the problem?
In the Meetings app, typed/chat lines are dispatched with the internal
[chat]marker prepended (handle_dispatch_textbuildsline = f"{k.CHAT_PREFIX} {transcript_text}"for typed input) so the meeting agents can tell typed input from speech.MeetingSession.broadcastpassed that same prefixed line toTranslationQueue.enqueue, so the literal[chat]marker was persisted as the translationsourceand interpolated into the translation prompt. Flagged as a real, observable advisory by the Opus review of #5739.Why this issue matters to the user
The TranslationSidebar's source column shows the raw internal marker in front of every typed line, and the marker is spent as translation-prompt tokens -- the model can echo it into the translated line. Separately, the code contradicted its own documentation: the in-code comment and
docs/system-specs/modules/meetings.mdboth said translation happens from the dictionary-corrected text, but the code enqueued the raw line.What changed
One call site,
MeetingSession.broadcast(the app's onlytranslations.enqueuecaller): the translation source now strips a leading, whitespace-boundedCHAT_PREFIXfrom the RAW line first, then runs the same dictionary-correct/clamp/noise pipeline the agents get (_prepare_line). Stripping before the clamp means a max-length typed message is capped on its payload rather than losing its final characters to the marker (found by the GPT review lane on the first head).[chat] ...counts as agent context. A mid-line occurrence (quoted speech) and marker-like speech ([chat]room availability...) reach translation verbatim.docs/system-specs/modules/meetings.md, Live translation section).Tests
test_broadcast_strips_chat_prefix_from_the_translation_source: a[chat]-prefixed dispatch produces a clean translation source while the note-taker queue keeps the prefixed line. Mutation-verified: red on base behavior, green with the fix.test_broadcast_strips_only_the_anchored_marker: mid-line marker survives, glued marker-like speech survives, a bare marker strips to empty (dropped by the queue's blank filter, no empty translation row).test_broadcast_translates_the_dictionary_corrected_speech_line: a speech line's translation source is the corrected text. Also red on base (base enqueued the raw line).test_a_max_length_typed_line_keeps_its_full_payload_in_translation: aMAX_TRANSCRIPT_CHARStyped payload survives intact -- red on the strip-after-clamp variant.test_artifact_source.pyproven env-owned (identical failures on clean baseba65da1e8-- host home-dir layout).Any other suggestions on the work
Pre-existing, out of scope here: a domain-dictionary term with alias "chat" can rewrite the marker itself (e.g.
[chat]->[Chat]) before the strip runs -- on base the same rewrite already corrupts the marker on the agent line, which is the larger half of that problem. Tracked locally for its own issue; the fix belongs at_prepare_line(correct only the payload).Closes #6763