| 02-P-NBL/round-2/logs/go-test-all-20260603-2.1.20.log | ●●●●● patch | view | raw | blame | history | |
| 02-P-NBL/round-2/logs/npm-run-build-20260603-2.1.20.log | ●●●●● patch | view | raw | blame | history | |
| 02-P-NBL/round-2/qa-report-current.md | ●●●●● patch | view | raw | blame | history | |
| 02-P-NBL/round-2/todo-list.md | ●●●●● patch | view | raw | blame | history | |
| CHANGELOG.md | ●●●●● patch | view | raw | blame | history | |
| privatevoice.src/app.go | ●●●●● patch | view | raw | blame | history | |
| privatevoice.src/build/config.yml | ●●●●● patch | view | raw | blame | history | |
| privatevoice.src/build/darwin/Info.plist | ●●●●● patch | view | raw | blame | history | |
| privatevoice.src/build/windows/wails.exe.manifest | ●●●●● patch | view | raw | blame | history | |
| privatevoice.src/frontend/package-lock.json | ●●●●● patch | view | raw | blame | history | |
| privatevoice.src/frontend/package.json | ●●●●● patch | view | raw | blame | history |
02-P-NBL/round-2/logs/go-test-all-20260603-2.1.20.log
New file @@ -0,0 +1,22 @@ ? voicesnap [no test files] ? voicesnap/internal/audio [no test files] ok voicesnap/internal/config 1.315s ok voicesnap/internal/correctioncsv 3.369s ? voicesnap/internal/dock [no test files] ? voicesnap/internal/engine [no test files] ok voicesnap/internal/history 2.037s ? voicesnap/internal/hotkey [no test files] ? voicesnap/internal/input [no test files] ok voicesnap/internal/language 2.710s ? voicesnap/internal/logger [no test files] ok voicesnap/internal/model 4.887s ? voicesnap/internal/overlay [no test files] ? voicesnap/internal/paths [no test files] ? voicesnap/internal/permissions [no test files] ? voicesnap/internal/singleinstance [no test files] ? voicesnap/internal/sound [no test files] ? voicesnap/internal/startup [no test files] ? voicesnap/internal/textproc [no test files] ? voicesnap/internal/updater [no test files] ok voicesnap/internal/userdict 4.164s ? voicesnap/services [no test files] 02-P-NBL/round-2/logs/npm-run-build-20260603-2.1.20.log
New file @@ -0,0 +1,38 @@ > privatevoice-input-frontend@2.1.20 build > vite build vite v6.4.1 building for production... transforming... 11:46:45 AM [vite-plugin-svelte] src/components/update/UpdateDialog.svelte:28:0 Elements with the 'dialog' interactive role must have a tabindex value https://svelte.dev/e/a11y_interactive_supports_focus 26: 27: <!-- svelte-ignore a11y_click_events_have_key_events --> 28: <div class="overlay" onclick={onclose} role="dialog"> ^ 29: <!-- svelte-ignore a11y_click_events_have_key_events --> 30: <div class="dialog" onclick={(e) => e.stopPropagation()} role="document"> 11:46:45 AM [vite-plugin-svelte] src/components/update/UpdateDialog.svelte:30:2 Non-interactive element `<div>` should not be assigned mouse or keyboard event listeners https://svelte.dev/e/a11y_no_noninteractive_element_interactions 28: <div class="overlay" onclick={onclose} role="dialog"> 29: <!-- svelte-ignore a11y_click_events_have_key_events --> 30: <div class="dialog" onclick={(e) => e.stopPropagation()} role="document"> ^ 31: <h2 class="title">{t('update.title')}</h2> 32: <p class="version">{t('update.version', { version: info.version })}</p> 11:46:45 AM [vite-plugin-svelte] src/components/shared/ToggleSwitch.svelte:17:0 Buttons and links should either contain text or have an `aria-label`, `aria-labelledby` or `title` attribute https://svelte.dev/e/a11y_consider_explicit_label 15: </script> 16: 17: <button ^ 18: class="toggle" 19: class:active={checked} ✓ 163 modules transformed. rendering chunks... computing gzip size... dist/index.html 0.41 kB │ gzip: 0.28 kB dist/assets/app-icon-Bs-pS5hx.png 400.98 kB dist/assets/index-p3GQqwqB.css 33.39 kB │ gzip: 5.73 kB dist/assets/index-yZ25Q-mY.js 137.08 kB │ gzip: 45.83 kB ✓ built in 783ms 02-P-NBL/round-2/qa-report-current.md
New file @@ -0,0 +1,121 @@ # Round 2 QA 报告:语言检测与语言版本设置 状态:功能性 QA PASS,可进入下一步交付门禁 日期:2026-06-03 测试人:Codex ## 1. 测试对象 | 项目 | 内容 | |---|---| | worktree | `/Users/ar/Projects/VoiceSnap-2.1.1-Round2` | | branch | `codex/round2-language-settings` | | 实现基线 commit | `516375d` | | 最终测试包 commit | 以 `RELEASE_MANIFEST.md` 为准 | | version | `2.1.20` | | build | `20260603.1145` | | 本地 App | `privatevoice.src/build/local/arm64/PrivateVoice Input.app` | | 本地 DMG | 最终路径以 `RELEASE_MANIFEST.md` 为准 | | DMG SHA256 | 最终 SHA256 以 `RELEASE_MANIFEST.md` 为准 | ## 2. 自动化与构建结果 | 项目 | 结果 | 证据 | |---|---|---| | `npm run build` | PASS | `logs/npm-run-build-20260603.log` | | `go test ./... -count=1` | PASS | `logs/go-test-all-20260603.log` | | 本地 App 构建与签名 | PASS | `logs/qa-runtime/build-local-round2-20260603.014931.log` | | 本地 DMG verify | PASS | `logs/qa-runtime/build-local-round2-20260603.014931.log` | 说明:前端构建仍有既有 Svelte a11y warning,来源为旧组件 `UpdateDialog.svelte`、`ToggleSwitch.svelte`,本轮未新增阻断。 ## 3. 真机测试结果 | ID | 场景 | 结果 | 证据 | |---|---|---|---| | R2-QA-001 | 老配置升级,无 `LanguageMode` / `LanguageID` | PASS | baseline config 无语言字段;Round 2 App 正常启动 | | R2-QA-002 | 中文系统 auto | PASS | `config.json` 默认 `LanguageMode=auto`、`LanguageID=zh-CN` | | R2-QA-003 | English 系统 auto | PASS by automated test | `go test ./...` 覆盖 detector normalize | | R2-QA-004 | 其他系统语言 auto fallback | PASS by automated test | `go test ./...` 覆盖 fallback 到 English | | R2-QA-005 | 手动中文 | PASS | `round2-screen-20260603.014931-zh-manual.png`;配置写入 `manual/zh-CN` | | R2-QA-006 | 手动 English | PASS | `round2-screen-20260603.014931-english6.png`;配置写入 `manual/en` | | R2-QA-007 | 切回自动 | PASS | `round2-screen-20260603.014931-chinese.png`;配置写入 `auto/zh-CN` | | R2-QA-008 | 重启持久化 | PASS | 重启后配置仍为 `manual/zh-CN` | | R2-QA-009 | 非法 LanguageMode fallback | PASS by automated test | `go test ./...` | | R2-QA-010 | 非法 LanguageID fallback | PASS by automated test | `go test ./...` | | R2-QA-011 | 语言切换不改模型 | PASS | `SelectedModelID` 始终为 `sensevoice-zh` | | R2-QA-012 | 已有模型时语言切换不下载模型 | PASS | 真实用户模型 hash 不变;日志未出现因语言切换触发下载 | | R2-QA-013 | 语言切换不删模型 | PASS | `model.int8.onnx`、`tokens.txt` hash 与 baseline 一致 | | R2-QA-014 | 词库保留 | PASS | `userdict.json` hash 与 baseline 一致;replacement 数量 149 | | R2-QA-015 | 历史保留 | PASS | `history.json` hash 与 baseline 一致;entries 数量 1708 | | R2-QA-016 | 热键保留 | PASS | config 热键字段未丢失;断网真实语音输入已用 `R-Alt` 触发成功 | | R2-QA-017 | 断网已有模型识别 | PASS | `logs/qa-runtime/offline-voice-final-20260603.014931.log`;断网期间识别并写入 history | | R2-QA-018 | UI 不暴露新模型 | PASS | 设置页只显示现有 SenseVoice 引擎 | | R2-QA-019 | English UI 文案 | PASS | `round2-screen-20260603.014931-english6.png` | | R2-QA-020 | 中文 UI 文案 | PASS | `round2-screen-20260603.014931-zh-manual.png` | ## 4. 数据完整性 测试前已备份真实用户数据: `/Users/ar/Projects/VoiceSnap-2.1.1-Round2/QA-backups/round2-pre-qa-20260603.014931` 语言切换阶段完成后,以下文件与 baseline SHA256 完全一致: - `userdict.json` - `history.json` - `models/sensevoice/model.int8.onnx` - `models/sensevoice/tokens.txt` `config.json` 有预期变化:新增/写入 `LanguageMode`、`LanguageID`、`SelectedModelID`。 断网真实语音输入复测后,`history.json` 出现预期变化:新增一条识别记录。 ## 5. 新用户测试 使用临时 HOME 启动本地 App,未挪动真实 App Support: `logs/qa-runtime/new-user-home-20260603.014931` 结果: - 新用户默认配置为 `LanguageMode=auto`、`LanguageID=zh-CN`、`SelectedModelID=sensevoice-zh`。 - 干净用户首次启动会自动下载 SenseVoice;下载发生在临时 QA 目录,不影响真实用户模型目录。 - 下载完成后 ASR engine ready。 ## 6. 断网启动检查 证据:`logs/qa-runtime/offline-start-check-20260603.014931.log` 结果: - Wi-Fi 从 On 切到 Off。 - `curl https://www.apple.com` 返回 `Could not resolve host`,确认断网。 - 断网状态下重启本地 App。 - App 使用已有真实 SenseVoice 模型启动,日志显示 `ASR engine ready: SenseVoice · CoreML (Apple Neural Engine)`。 - Wi-Fi 已恢复为 On。 ## 7. 断网真实语音输入复测 证据:`logs/qa-runtime/offline-voice-final-20260603.014931.log` 结果: - Wi-Fi 从 On 切到 Off。 - 断网探测返回 `Could not resolve host: www.apple.com`。 - 用户在断网窗口内按住 `R-Alt` 说测试句。 - 日志显示 2026-06-03 11:40:36 开始录音,2026-06-03 11:40:41 停止录音并完成识别。 - 识别文本:`这是 mac 电脑用 SenseVoice 做离线识别。` - `history.json` 条目数从 1710 增加到 1711。 - `history.json` 最新条目 `entries[0]` 为:`这是 mac 电脑用 SenseVoice 做离线识别。` - Wi-Fi 已恢复为 On,并通过联网探测。 ## 8. 阻断项 无。 ## 9. 当前结论 Round 2 的语言设置、i18n 切换、持久化、新用户默认值、老用户数据保护、模型不破坏、断网启动均通过。 Round 2 功能性 QA PASS。 02-P-NBL/round-2/todo-list.md
@@ -1,6 +1,6 @@ # Round 2 To Do List 状态:待启动 状态:功能性 QA PASS;等待交付门禁/测试包流程 所属子项目:`02-P-NBL` Round:Round 2 日期:2026-06-03 @@ -30,24 +30,24 @@ ## 3. QA 准备 - [ ] 准备老用户升级测试数据。 - [ ] 准备新用户干净安装测试数据。 - [ ] 准备 detector mock 或测试开关。 - [ ] 准备非法 config 测试样本。 - [ ] 准备断网识别回归步骤。 - [x] 准备老用户升级测试数据。 - [x] 准备新用户干净安装测试数据。 - [x] 准备 detector mock 或测试开关。 - [x] 准备非法 config 测试样本。 - [x] 准备断网识别回归步骤。 - [x] 准备 QA 预检记录。 - [ ] 准备 QA 报告模板。 - [x] 准备 QA 报告模板。 ## 4. 验收 - [ ] 中文系统 auto 解析为中文。 - [ ] English 系统 auto 解析为 English。 - [ ] 其他系统语言 auto 解析为 English。 - [ ] 手动中文持久化。 - [ ] 手动 English 持久化。 - [ ] 语言切换不触发模型下载。 - [ ] 语言切换不破坏 SenseVoice 模型。 - [ ] 语言切换不破坏词库。 - [ ] 语言切换不破坏历史。 - [ ] 断网识别回归通过。 - [ ] QA 报告确认功能性 PASS。 - [x] 中文系统 auto 解析为中文。 - [x] English 系统 auto 解析为 English。 - [x] 其他系统语言 auto 解析为 English。 - [x] 手动中文持久化。 - [x] 手动 English 持久化。 - [x] 语言切换不触发模型下载。 - [x] 语言切换不破坏 SenseVoice 模型。 - [x] 语言切换不破坏词库。 - [x] 语言切换不破坏历史。 - [x] 断网识别回归通过。 - [x] QA 报告确认功能性 PASS。 CHANGELOG.md
@@ -1,5 +1,23 @@ # Changelog ## v2.1.20 (2026-06-03) ### QA 候选包 - **Round 2 语言版本设置**:设置页新增“语言版本”,支持自动、中文、English 三种模式。 - **系统语言解析**:新增语言 profile 和 resolver,中文系统默认中文,English 系统默认 English,其他语言默认 English。 - **前端 i18n 切换**:语言切换后设置页、侧边栏、关于页等关键文案立即切换。 - **老用户兼容**:旧 `config.json` 缺少 `LanguageMode` / `LanguageID` 时可正常启动,并自动 fallback。 - **模型隔离**:本轮语言切换不引入 Moonshine / Parakeet / Qwen3-ASR,不改写或删除 SenseVoice 模型。 - **QA 资料**:新增 `02-P-NBL/round-2` 下 PRD、研发拆解、QA 计划、QA 报告和验收记录。 ### 构建 - build: `20260603.1145` - 说明: 本版本为 Round 2 QA 通过后的测试包候选,已完成老用户升级、新用户临时 HOME、语言切换、重启持久化、断网启动和断网真实语音输入复测。 --- ## v2.1.19 (2026-06-02) ### QA 候选包 privatevoice.src/app.go
@@ -27,8 +27,8 @@ ) const ( appVersion = "2.1.19" appBuild = "20260602.2022" appVersion = "2.1.20" appBuild = "20260603.1145" appDisplayVersion = appVersion + " (build " + appBuild + ")" appName = "PrivateVoice Input" privatevoice.src/build/config.yml
@@ -7,7 +7,7 @@ description: "Private offline voice input tool" copyright: "(c) 2026, PrivateVoice" comments: "Private.Offline" version: "2.1.19" version: "2.1.20" dev_mode: root_path: . privatevoice.src/build/darwin/Info.plist
@@ -15,9 +15,9 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>2.1.19</string> <string>2.1.20</string> <key>CFBundleVersion</key> <string>20260602.2022</string> <string>20260603.1145</string> <key>LSMinimumSystemVersion</key> <string>11.0</string> <key>NSMicrophoneUsageDescription</key> privatevoice.src/build/windows/wails.exe.manifest
@@ -3,7 +3,7 @@ <assemblyIdentity type="win32" name="PrivateVoice.Input" version="2.1.19.0" version="2.1.20.0" processorArchitecture="*"/> <dependency> <dependentAssembly> privatevoice.src/frontend/package-lock.json
@@ -1,12 +1,12 @@ { "name": "privatevoice-input-frontend", "version": "2.1.19", "version": "2.1.20", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "privatevoice-input-frontend", "version": "2.1.19", "version": "2.1.20", "dependencies": { "@wailsio/runtime": "latest" }, privatevoice.src/frontend/package.json
@@ -1,7 +1,7 @@ { "name": "privatevoice-input-frontend", "private": true, "version": "2.1.19", "version": "2.1.20", "type": "module", "scripts": { "dev": "vite dev",