From fdc5c43b2cf8ebc3d67099cfba9936c838281561 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Tue, 30 Jun 2026 03:36:45 +0800
Subject: [PATCH] Add Windows QA evidence verifier

---
 privatevoice.src/scripts/verify-windows-qa-evidence.sh |   96 ++++++++++++++++++++++++++++++++++++++++++++++++
 CHANGELOG.md                                           |    1 
 CODEGRAPH.md                                           |    3 +
 3 files changed, 100 insertions(+), 0 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1fd7ae3..e58c779 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@
 
 - **新增 Windows 预览构建脚本**:`privatevoice.src/scripts/build-windows-preview.sh` 可生成 Windows x64 预览目录和 zip。
 - **内置 Windows 真机 QA 采集脚本**:预览包包含 `QA-WINDOWS-PREVIEW.ps1`,用于启动 App、打开 Notepad 目标文件、提示完成一次听写,并收集日志和目标文本证据。
+- **新增 Windows QA 证据验证脚本**:`privatevoice.src/scripts/verify-windows-qa-evidence.sh` 可检查返回的 `qa-evidence-*.zip` 是否证明启动、引擎、录音、识别和上屏。
 - **预览版只开放 SenseVoice**:Windows build 中其他模型仍可见但置灰禁用,避免用户选择尚未验证的模型导致启动或识别失败。
 - **打包 sherpa/onnxruntime 运行时 DLL**:预览包包含 `onnxruntime.dll`、`sherpa-onnx-c-api.dll`、`sherpa-onnx-cxx-api.dll`。
 - **交付边界**:该产物是 Windows 技术预览,不是已签名安装器,也未完成 Windows 10/11 真机 QA。
diff --git a/CODEGRAPH.md b/CODEGRAPH.md
index 2bbef54..2493f99 100644
--- a/CODEGRAPH.md
+++ b/CODEGRAPH.md
@@ -36,6 +36,7 @@
 - Non-SenseVoice models remain visible in settings but are disabled through `model.IsModelSupportedInCurrentBuild`.
 - Windows unsupported reason: `windows_preview_unsupported`.
 - Build script: `privatevoice.src/scripts/build-windows-preview.sh`.
+- Evidence verifier: `privatevoice.src/scripts/verify-windows-qa-evidence.sh`.
 - Runtime package includes:
   - `PrivateVoice Dictation.exe`
   - `onnxruntime.dll`
@@ -53,11 +54,13 @@
 go test ./...
 GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go test -exec=/usr/bin/true ./...
 ./scripts/build-windows-preview.sh
+./scripts/verify-windows-qa-evidence.sh /path/to/qa-evidence-YYYYMMDD-HHMMSS.zip
 ```
 
 ## Known Gaps
 
 - Windows runtime QA must still be performed on Windows 10/11 hardware.
 - Run `QA-WINDOWS-PREVIEW.ps1` from the extracted preview package to collect startup, engine, recording, recognition, paste, and Notepad target text evidence.
+- After evidence is returned, run `verify-windows-qa-evidence.sh` and require `WINDOWS_QA_EVIDENCE_PASS` before claiming the goal complete.
 - The Windows preview zip is unsigned and not an installer.
 - SmartScreen / Defender prompts are expected for local testing.
diff --git a/privatevoice.src/scripts/verify-windows-qa-evidence.sh b/privatevoice.src/scripts/verify-windows-qa-evidence.sh
new file mode 100755
index 0000000..42140ca
--- /dev/null
+++ b/privatevoice.src/scripts/verify-windows-qa-evidence.sh
@@ -0,0 +1,96 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+if [[ $# -ne 1 ]]; then
+  echo "Usage: $0 /path/to/qa-evidence-YYYYMMDD-HHMMSS.zip" >&2
+  exit 2
+fi
+
+evidence_zip="$1"
+if [[ ! -f "$evidence_zip" ]]; then
+  echo "Evidence zip not found: $evidence_zip" >&2
+  exit 2
+fi
+
+workdir="$(mktemp -d)"
+cleanup() {
+  rm -rf "$workdir"
+}
+trap cleanup EXIT
+
+unzip -q "$evidence_zip" -d "$workdir"
+
+find_one() {
+  local name="$1"
+  find "$workdir" -type f -name "$name" -print -quit
+}
+
+require_file() {
+  local name="$1"
+  local path
+  path="$(find_one "$name")"
+  if [[ -z "$path" ]]; then
+    echo "FAIL missing $name" >&2
+    return 1
+  fi
+  echo "$path"
+}
+
+check_pattern() {
+  local label="$1"
+  local file="$2"
+  local pattern="$3"
+  if rg -q "$pattern" "$file"; then
+    echo "PASS $label"
+    return 0
+  fi
+  echo "FAIL $label"
+  return 1
+}
+
+failures=0
+
+qa_results="$(require_file "qa-results.tsv")" || failures=$((failures + 1))
+app_log="$(require_file "app.log")" || failures=$((failures + 1))
+target_text="$(require_file "qa-target-dictation-text.txt")" || failures=$((failures + 1))
+system_info="$(require_file "system-info.txt")" || failures=$((failures + 1))
+
+if [[ -n "${qa_results:-}" ]]; then
+  if rg -q '^NEEDS_EVIDENCE' "$qa_results"; then
+    echo "FAIL qa-results.tsv contains NEEDS_EVIDENCE"
+    rg '^NEEDS_EVIDENCE' "$qa_results" || true
+    failures=$((failures + 1))
+  else
+    echo "PASS qa-results.tsv has no NEEDS_EVIDENCE"
+  fi
+fi
+
+if [[ -n "${app_log:-}" ]]; then
+  check_pattern "startup log" "$app_log" 'PrivateVoice Dictation starting' || failures=$((failures + 1))
+  check_pattern "engine ready log" "$app_log" 'ASR engine ready|Engine initialized' || failures=$((failures + 1))
+  check_pattern "recording log" "$app_log" 'Recording started' || failures=$((failures + 1))
+  check_pattern "recognized text log" "$app_log" 'Recognized:' || failures=$((failures + 1))
+  check_pattern "paste success log" "$app_log" 'PERF paste_done.*result=success|PERF fallback_type_done.*result=success' || failures=$((failures + 1))
+fi
+
+if [[ -n "${target_text:-}" ]]; then
+  if [[ -s "$target_text" ]] && [[ -n "$(tr -d '[:space:]' < "$target_text")" ]]; then
+    echo "PASS Notepad target text captured"
+  else
+    echo "FAIL Notepad target text is empty"
+    failures=$((failures + 1))
+  fi
+fi
+
+if [[ -n "${system_info:-}" ]]; then
+  check_pattern "Windows system info" "$system_info" 'Windows|Microsoft|CsSystemType|WindowsProductName' || failures=$((failures + 1))
+fi
+
+echo
+if [[ "$failures" -eq 0 ]]; then
+  echo "WINDOWS_QA_EVIDENCE_PASS"
+  exit 0
+fi
+
+echo "WINDOWS_QA_EVIDENCE_FAIL failures=$failures"
+exit 1

--
Gitblit v1.9.3