Skip to content

refactor(dictation): dictation.rs 2766→425 拆为 4 个子模块(机械式·零回归) - #619

Merged
appergb merged 6 commits into
betafrom
refactor/split-dictation
Jun 8, 2026
Merged

refactor(dictation): dictation.rs 2766→425 拆为 4 个子模块(机械式·零回归)#619
appergb merged 6 commits into
betafrom
refactor/split-dictation

Conversation

@appergb

@appergbappergb commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

User description

dictation.rs SRP 拆分(机械式·行为保持)

承接 #615 的重构主题,把 Less Computer 落地后第二大的文件 coordinator/dictation.rs(2766 行)按单一职责拆为同级子模块(与 #615 同款 glob 重导出契约,纯剪切+可见性提升,零逻辑改动)。

文件行数
coordinator/dictation.rs(保留 tests + 残留 helper)425(拆前 2766)
coordinator/dictation_streaming.rs(流式润色 + 插入缓冲)420
coordinator/dictation_voice_agent.rs(Less Computer 流程)456
coordinator/dictation_session.rs(会话生命周期 begin/start/cancel)702
coordinator/dictation_end.rsend_session 并发敏感整体搬785
  • coordinator.rs 加 4 个 mod + pub(crate) use dictation_*::* glob 重导出,所有 super::/裸名引用不变。
  • end_session(跨 await 持/放锁、与 ASR/polish/insert 交错)逐字搬,未动锁作用域/block_on/spawn/await 点。
  • 全部 #[cfg(...)]/中文注释/issue 号原样跟随。

验证cargo check 0 error(55 warning = 拆前基线)· cargo test --lib473 passed 无回归 · npm run build 绿。

base = fix/issue-609-security-audit(栈第 5 层;合并顺序 #597#615#616#617 → 本 PR)。本机仅 check macOS,Windows/Linux cfg 分支靠 CI。


PR Type

Enhancement


Description

  • Split coordinator/dictation.rs (2766→425 lines) into 4 submodules by responsibility

  • Extracted dictation_streaming, dictation_voice_agent, dictation_session, dictation_end

  • Glob re-exports preserve all existing references; no logic changes

  • All 473 lib tests pass with zero regression


Diagram Walkthrough

flowchart LR
dictation["dictation.rs"] --> streaming["dictation_streaming.rs (streaming polish)"]
dictation --> voice_agent["dictation_voice_agent.rs (Less Computer agent)"]
dictation --> session["dictation_session.rs (session lifecycle)"]
dictation --> end["dictation_end.rs (end_session concurrency-safe)"]
Loading

File Walkthrough

Relevant files
Refactoring
7 files
dictation.rs
Shrink from 2766 to 425 lines, retain core logic + tests
+6/-2347
coordinator.rs
Register new submodules and glob re-exports
+12/-6
tests.rs
Adjust import paths for extracted functions
+1/-1
dictation_streaming.rs (new)
Streaming insert and flush logic
dictation_voice_agent.rs (new)
Less Computer voice agent transcript handling
dictation_session.rs (new)
Session lifecycle management (begin/start/cancel)
dictation_end.rs (new)
End session with concurrency-sensitive logic
Additional files
4 files
dictation_end.rs+785/-0
dictation_session.rs+702/-0
dictation_streaming.rs+420/-0
dictation_voice_agent.rs+456/-0

吕柏青and others added 4 commits June 7, 2026 21:02
把流式润色与文本收尾相关函数从 coordinator/dictation.rs 机械式搬到
同级 coordinator/dictation_streaming.rs(行为保持):run_streaming_polish、
drain/flush streaming insert、finalize_polished_text、streaming_insert_eligible、
default_done_message、append_typed_prefix,以及 STREAMING_INSERT_FLUSH_INTERVAL。
coordinator.rs glob 重导出新模块,dictation.rs 测试改走 crate::coordinator:: 路径。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
把 Less Computer 语音 Agent 路径从 coordinator/dictation.rs 机械式搬到
同级 coordinator/dictation_voice_agent.rs(行为保持):less_computer_approvals、
resolve_less_computer_approval、emit_less_computer、run_voice_agent_transcript、
LessComputerOutcome、run_less_computer_once、maybe_request_approval、
coding_agent_mode_from_pref,以及 LESS_COMPUTER_EVENT/LESS_COMPUTER_APPROVALS。
coordinator.rs glob 重导出新模块并把 resolve_less_computer_approval 调用改到
dictation_voice_agent:: 路径;dictation.rs 去掉随之失用的 AtomicBool 导入。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
把会话生命周期函数从 coordinator/dictation.rs 机械式搬到同级
coordinator/dictation_session.rs(行为保持):request_stop_during_starting、
begin_session、start_recorder_for_starting、spawn_recorder_error_monitor、
abort_recording_with_error、start_recorder_and_enter_listening、
finish_starting_session、dictation_error_code、cancel_session、
eligible_polish_context_turns。新模块 use super::resources::* 取资源辅助函数。
coordinator.rs glob 重导出并把 begin_session/cancel_session/
request_stop_during_starting/dictation_error_code 的命名导入改到
dictation_session::;tests.rs 的 abort_recording_with_error 路径同步;
dictation.rs 去掉随之失用的 request_stop_during_starting_state 导入,
测试 eligible_polish_context_turns 改走 crate::coordinator:: 路径。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@appergb

Copy link
Copy Markdown
CollaboratorAuthor

@claude 复审这个纯机械式重构 PR(dictation.rs 2766→425 拆为 4 个同级子模块,与已批准的 #615 同款手法)。重点验证"机械式"成立:

  1. 行为保持:有无函数体被无意改动?特别是 dictation_end.rsend_session——它跨 await 持/放锁、与 ASR/polish/insert 交错,是全文件最并发敏感的函数。锁作用域/block_on/spawn/await 点是否逐字保留?
  2. glob 重导出契约:coordinator.rs 的 4 个 pub(crate) use dictation_*::* 是否完整覆盖,子模块间 + coordinator impl + qa_session 对这些函数的 super::/裸名引用是否仍解析(cargo check 0 error 佐证)?
  3. cfg 完整性(本机仅 check macOS)。

已验证:cargo check 0 error / cargo test --lib 473 passed / npm build 绿。可否合并?(base=fix/issue-609-security-audit,栈第 5 层)

@claude

claudeBot commented Jun 8, 2026

Copy link
Copy Markdown

Claude finished @appergb's task in 5m 57s —— View job


PR #619 机械式重构复审结论

  • 读取 diff(base = origin/fix/issue-609-security-audit
  • 验证 end_session 行为保持(锁作用域 / block_on / spawn / await 点逐字核对)
  • 验证 glob 重导出契约(coordinator.rs 4 个 pub(crate) use dictation_*::*
  • 验证 cfg 完整性(#[cfg(...)] 跟随情况)
  • 检查其余 3 个子模块函数体完整性
  • 汇总审查意见,给出合并建议

结论:机械式成立,可合并

以下逐项说明。


1. 行为保持 — end_sessiondictation_end.rs

函数体逐字对比通过。

  • dictation_end.rs 第 9–785 行 vs 原 dictation.rs 第 1593–2369 行,函数体完全等价,没有任何逻辑改动。
  • 唯一变化:可见性 pub(super)pub(crate),这是从 dictation.rs 子模块 移到 coordinator 同级子模块 后必要且正确的改动(glob 重导出要求)。
  • 全部 8 处 awaittokio::time::timeoutasr.send_last_frame().awaitasr.await_final_result().await、流式路径的 run_streaming_polish().awaitpolish_and_translate_or_passthrough().await 等 await 点位置不变。
  • 两处 lock guard 作用域(let current_session_id = { ... }let proceed_to_insert = { ... })和收尾 { let mut state = inner.state.lock(); ... } 均逐字保留,无扩展或收窄。
  • #[cfg(any(debug_assertions, test))] debug_transcript_override 分支原样跟随(dictation_end.rs:385)。

2. glob 重导出契约

coordinator.rs 变更正确:

新增 mod新增 pub(crate) use状态
mod dictation_end;pub(crate) use dictation_end::*;
mod dictation_session;pub(crate) use dictation_session::*;
mod dictation_streaming;pub(crate) use dictation_streaming::*;
mod dictation_voice_agent;pub(crate) use dictation_voice_agent::*;

交叉引用解析:

  • handle_pressed_edge / handle_released_edge 仍留在 dictation.rs,以 pub(super) + coordinator 直接 use dictation::{...} 引入,不走 glob,与拆前一致。
  • end_sessiondictation.rs 内部被 handle_pressed / handle_released 裸名调用,通过 use super::*dictation.rs 顶部)从 coordinator glob 链拿到 — 路径:dictation_end::end_session → coordinator 重导出 → dictation.rssuper::* — 解析正确。
  • dictation_error_code 移到 dictation_session.rsdictation_end.rs 内部通过 use super::* 同样经 coordinator glob 链解析,无歧义。
  • #[cfg(test)] use dictation_session::dictation_error_code;:diff 里的 #[cfg(test)] 行是未动的上下文行(无 -/+ 前缀),新文件 coordinator.rs 第 93–94 行确认保留,测试保护未破坏。
  • less_computer_approve 中的显式 dictation_voice_agent::resolve_less_computer_approval(...) 直接调用:符合 glob 契约外的精确路径,正确。
  • dictation.rs 测试新改为 use crate::coordinator::{append_typed_prefix, ...} 访问已移走的函数(通过 coordinator pub(crate) re-export),use super::batch_asr_chunk_limit_ms 仍指向 coordinator.rs 中的同名私有函数,行为与拆前一致。

3. cfg 完整性

文件cfg attrs 数量对应原行状态
dictation_end.rs8(windows×3, macos×1, not(windows)×1, linux×1, not(linux)×1, debug/test×1)原 1794, 1843, 1890, 1969, 2235, 2249, 2256, 2263
dictation_session.rs5(windows×3, macos×1, debug/test×1)原 1009, 1020, 1065, 1100, 1157
dictation_streaming.rs1(not(linux))原 233
dictation_voice_agent.rs0Voice agent 函数无平台分支
dictation.rs(残留)2 测试平台辅助(macos/windows/linux)原 2752, 2757, 2762

end_session 内的 #[cfg(target_os = "windows")] FoundryLocalWhisper、SherpaOnnxLocal 分支及 #[cfg(target_os = "macos")] Local 分支位置与原文完全对应。


无回归风险点

无发现实质性 bug 或行为变更。唯一的系统性变化是被拆出函数由 pub(super) 升为 pub(crate),这是符合 Rust 可见性规则的正确最小提权。cargo check 0 error / cargo test 473 passed 已在作者本机佐证,CI 应覆盖 Windows/Linux cfg 分支。

推荐合并。

@github-actions

github-actionsBot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

(Review updated until commit 2cc896f)

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis 🔶

615 - Partially compliant

Compliant requirements:

  • Split coordinator/dictation.rs into 4 submodules
  • Glob re-exports used (pub(crate) use dictation_::)
  • Concurrency-sensitive code moved verbatim
  • All tests pass, no build errors

Non-compliant requirements:

(empty)

Requires further human verification:

(empty)

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ No major issues detected

@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 3f22d2a

@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 2cc896f

@appergb

Copy link
Copy Markdown
CollaboratorAuthor

@claude 合并前最终复审(栈顶)。本 PR = dictation.rs(2766→425) 拆为 dictation_streaming/voice_agent/session/end 四子模块,机械式·end_session 并发敏感整体搬不动锁/await;并前向合并了 #617 的 SEC-001。最新 2cc896f,含全部栈工作。自审核对:每个 .await 前锁已 drop、parking_lot guard !Send 编译器兜底、cargo test 475 passed。请确认可合并。

@claude

claudeBot commented Jun 8, 2026

Copy link
Copy Markdown

Claude finished @appergb's task in 3m 21s —— View job


合并前最终复审 — PR #619


结论:机械式成立,可合并


1. end_session 并发安全逐项核查

通过 grep -n ".lock()\|.await" 列出全部 79 行 lock 访问与 16 处 .await 点,逐一确认:

关键结构结论
初始 current_session_id 块(第 10–16 行){...} 块内 lock,await 前已 drop ✓
每条 ASR arm 内的错误路径 inner.state.lock().phase = Idle均为点访问临时 guard,当前 arm return 前无 await ✓
FoundryLocal/Sherpa local.transcribe().await(第 215/264 行)之后的 .lock().cancelled 在 await 之后,不在 await 之前 ✓
cancel 检测块(第 373–377 行){let mut state = inner.state.lock(); ...} 块结束后无 await ✓
proceed_to_insert 块(第 617–626 行){...} 块内决策,drop 后才进入 insert .await
尾部 state.phase = Idle / focus_target = None(第 770–774 行)函数末尾,无后续 await ✓

parking_lot::Mutex guard 是 !Send,编译器静态拒绝跨 await 持锁——这是机械保障。cargo check 0 error 已在编译层确认。


2. glob 重导出契约完整性

coordinator.rs 第 67–70 行(mod)+ 第 83–86 行(pub(crate) use):

mod dictation_end;pub(crate)use dictation_end::*;mod dictation_session;pub(crate)use dictation_session::*;mod dictation_streaming;pub(crate)use dictation_streaming::*;mod dictation_voice_agent;pub(crate)use dictation_voice_agent::*;

四个模块的 top-level 公开函数可见性均已提升至 pub(crate),经代码搜索确认:

  • end_sessionpub(crate) ✓(dictation_end.rs:9)
  • begin_session / cancel_session / request_stop_during_starting / abort_recording_with_errorpub(crate) ✓(dictation_session.rs:9/638/548/20)
  • run_streaming_polish / finalize_polished_text / streaming_insert_eligible 等 — pub(crate)
  • resolve_less_computer_approval / run_voice_agent_transcriptpub(crate)

less_computer_approve 直接路径:第 821 行改为 dictation_voice_agent::resolve_less_computer_approval(...),函数已在该模块,路径正确。也可经 glob 裸名访问,两者等价。

tests.rs 一行改动use super::dictation::abort_recording_with_erroruse super::dictation_session::abort_recording_with_error,对应函数实际移动位置,正确 ✓


3. cfg 完整性

dictation_end.rs 内平台 cfg 分支(target_os = "windows" × 3、"macos" × 1、any(debug_assertions, test) × 1)与原 dictation.rs 对应行 1-to-1 匹配。dictation_session.rs / dictation_streaming.rs / dictation_voice_agent.rs 的 cfg 覆盖情况同上次审查一致。


4. 测试数 473 → 475 的说明

两次审查之间合并了 fix/issue-609-security-audit 栈(commit 0fd120a / 3f22d2a),安全修复带入 2 条新测试。dictation 拆分本身不增减测试,475 passed 符合预期。


无阻塞问题

本次最终复审无发现新问题。机械式成立,所有并发约束经编译器和运行时双重保障。

推荐合并。

@appergb
appergb changed the base branch from fix/issue-609-security-audit to betaJune 8, 2026 05:27
@appergb
appergb merged commit 9b14c03 into betaJun 8, 2026
1 check passed
@appergb
appergb deleted the refactor/split-dictation branch June 9, 2026 06:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@appergb