jim800121chen 8cd5751ce3 feat(local-tool): M8 重構 — Wails 控制台 + 瀏覽器 Web UI(R5 決策)
依 R5 五輪決策把 visionA-local 從「Wails 內嵌 Next.js」重構為「Wails
本機伺服器控制台 + 瀏覽器 Web UI」模式(類比 Docker Desktop / Ollama)。

程式碼變動
  - M8-1 砍 yt-dlp 全套(後端 resolver / URL handler / 前端 URL tab /
    Makefile vendor / installer / bootstrap / CI workflow,-555 行)
  - M8-2 砍 Mock 模式全套(driver/mock、mock_camera、Settings runtimeMode、
    VISIONA_MOCK 環境變數,-528 行)
  - M8-3 ffmpeg 從 GPL 切換到 LGPL 混合方案:Windows/Linux 用 BtbN 現成
    LGPL binary,macOS 自 build minimal decoder-only 進 git
    (vendor/ffmpeg/macos/ffmpeg 5.7MB + ffprobe 5.6MB,比 GPL 版省 85% 空間)
  - M8-4 Wails Server Controller:state machine、log ring buffer 2000 行、
    preferences.json atomic write、boot-id、Gin SkipPaths、shutdown 7+1 秒、
    notify_*.go 三平台 OS 通知、watchServer 改 Error state 不 os.Exit
  - M8-4b 啟動階段管線 R5-E:6 階段進度 event、20s soft / 60s hard timeout、
    stage 5/6 skip 規則、sentinel file、RestartStartupSequence 5 步驟
  - M8-5 Wails 控制台 vanilla HTML/JS/CSS(9 檔 ~2012 行)取代 M7-B splash:
    state 視覺、log panel、startup progress panel、Stage 6 manual CTA
    pulse、shutdown modal、Settings、Dark Mode、i18n 中英雙語
  - M8-6 上傳影片副檔名擴充(mp4/avi/mov/mpeg/mpg)
  - M8-7 Web UI Server Offline Overlay(role=alertdialog + focus trap +
    wsEverConnected 容錯 + Page Visibility)
  - M8-8 CORS middleware(127.0.0.1/localhost only + suffix attack 防護)+
    ws/origin.go 獨立 WebSocket CheckOrigin 避 package cycle
  - MAJ-4 server:shutdown-imminent WebSocket broadcast 機制
    (/ws/system endpoint + notifyShutdownImminent helper)
  - M8-9 Boot-ID + 瀏覽器 tab 自動重連(sessionStorage loop guard)

品質
  - ~105+ 新 unit test + race detector (-count=2) 全綠
  - 10 個 milestone 全部通過 Reviewer 審查
  - 三方 v2 + v2.1 文件(PRD / Design Spec / TDD)+ 交叉互審紀錄
    收錄在 .autoflow/

交付前待處理(M8-10)
  - 重跑 make payload-macos 把舊 GPL 77MB binary 換成新 LGPL
  - 三平台 end-to-end build 驗證

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 17:57:54 +08:00

20 KiB
Raw Permalink Blame History

v2.4 — First-Run 流程重定義

本章對應 R5-4首次啟動自動開瀏覽器+ R5-5aMock 模式完全砍除)。 取代 v1 spec/04-first-run.md 的「歡迎 → 模式選擇 → 硬體偵測」三步流程。 上層索引:../design-spec-v2.md


1. 背景與變更點

v1 First-Run 流程:

雙擊 app → Wails splash → Next.js 主 UI 打開 First-Run wizard
  Step 1: 歡迎 / 產品介紹
  Step 2: 模式選擇(真實硬體 / Mock
  Step 3: 硬體偵測
  → Dashboard

R5 兩個決策直接改寫這個流程:

  1. R5-5a 完全砍除 Mock 模式 → Step 2 整步消失
  2. R5-4 首次啟動自動開瀏覽器 → 雙擊 app 看到的是 Wails 控制台First-Run wizard 跑在瀏覽器裡(不是 Wails 裡)

結果First-Run wizard 從三步變成兩步且入口從「Wails splash」變成「瀏覽器」。


2. 新的 First-Run 流程圖

┌──────────────────────────────────────────────────────────────────┐
│                      新 First-Run 完整流程                         │
└──────────────────────────────────────────────────────────────────┘

  使用者雙擊 visionA-local.app
            │
            ▼
  ┌────────────────────────────┐
  │  Wails Server Control      │
  │  Panel 開啟                 │
  │  狀態: Starting...         │
  └────────────┬───────────────┘
               │ 內部自動 startServer()
               ▼
  ┌────────────────────────────┐
  │  Server ready              │
  │  狀態: Running             │
  └────────────┬───────────────┘
               │ [Settings.autoOpenBrowser === true]
               │ (預設 ON首次啟動一定 ON)
               ▼
  ┌────────────────────────────┐
  │  控制台呼叫 OS open         │
  │  http://127.0.0.1:3721/    │
  └────────────┬───────────────┘
               │
               ▼
  ┌────────────────────────────────────────────────────────────┐
  │  瀏覽器打開 → Next.js 啟動                                   │
  │  檢查 localStorage.firstRunCompleted                        │
  │                                                             │
  │  ├── false → 導向 /onboarding                              │
  │  └── true  → 導向 / (Dashboard)                            │
  └────────────────────────────────────────────────────────────┘
                        │ firstRunCompleted === false
                        ▼
  ┌────────────────────────────────────────────────────────────┐
  │                   First-Run Wizard                          │
  │                                                             │
  │   Step 1: 歡迎 ─────────────────────────┐                  │
  │   ┌──────────────────────────────────┐  │                  │
  │   │ 歡迎使用 visionA-local           │  │                  │
  │   │                                   │  │                  │
  │   │ 這是一個本機 Edge AI 推論工具    │  │                  │
  │   │ 你可以用它在自己的電腦上跑模型   │  │                  │
  │   │                                   │  │                  │
  │   │ [Gatekeeper 警告說明]             │  │                  │
  │   │                                   │  │                  │
  │   │                   [ 下一步 ]      │  │                  │
  │   │                   [ 略過 ]        │  │                  │
  │   └──────────────────────────────────┘  │                  │
  │                                          ▼                  │
  │   Step 2: 硬體偵測 ──────────────────                      │
  │   ┌──────────────────────────────────┐                     │
  │   │ 正在掃描 Kneron 裝置...          │                     │
  │   │                                   │                     │
  │   │ ┌─ 偵測結果 ────────────────┐   │                     │
  │   │ │ 情境 A: 找到 1+ 裝置       │   │                     │
  │   │ │   ✓ Kneron KL520 x1       │   │                     │
  │   │ │   [ 進入 Dashboard ]      │   │                     │
  │   │ │                             │   │                     │
  │   │ │ 情境 B: 未找到裝置          │   │                     │
  │   │ │   ⚠ 未偵測到 Kneron 裝置  │   │                     │
  │   │ │   請插入 Kneron 裝置後      │   │                     │
  │   │ │   重新整理,或略過直接進入  │   │                     │
  │   │ │   Dashboard可隨時重掃 │   │                     │
  │   │ │   [ 重新掃描 ] [ 略過 ]   │   │                     │
  │   │ └─────────────────────────────┘   │                     │
  │   └──────────────────────────────────┘                     │
  │                                          │                  │
  │                                          ▼                  │
  │                       firstRunCompleted = true              │
  │                                          │                  │
  │                                          ▼                  │
  │                                     Dashboard               │
  └────────────────────────────────────────────────────────────┘

3. Step-by-Step 規格

3.1 Step 1 — 歡迎

目的:介紹產品、安撫 Gatekeeper 警告焦慮、讓使用者按一個按鈕就進入下一步。

結構

┌──────────────────────────────────────────────────┐
│                                                    │
│              [LOGO]                                │
│                                                    │
│         歡迎使用 visionA-local                     │
│                                                    │
│   這是一個本機 Edge AI 推論工具,                  │
│   你可以在自己的電腦上跑模型,完全離線。            │
│                                                    │
│   ────────────────────────────────────            │
│                                                    │
│   🔒 你可能剛才看到系統安全性警告?                 │
│                                                    │
│   因為這是內部工具,未購買 Apple/Microsoft         │
│   憑證簽章。你看到的警告是正常的,                 │
│   我們已經驗證此版本的完整性。                     │
│                                                    │
│   [ 下一步 ]        [ 略過 Onboarding ]           │
│                                                    │
└──────────────────────────────────────────────────┘

元件

  • Logo80×80
  • 標題 <h1> 28 px Bold
  • 簡介 <p> 15 px
  • Gatekeeper 安撫段 <section>(灰底卡片 color.muted/40
  • [ 下一步 ] Button primary lg
  • [ 略過 Onboarding ] Button ghost sm右下角

「略過」行為:直接設 firstRunCompleted = true 並跳 Dashboard不經過 Step 2。

3.2 Step 2 — 硬體偵測

目的:掃描 Kneron 裝置,讓使用者知道硬體 ready 與否,但 不強迫 插裝置。

結構(含三種子狀態):

3.2.1 Scanning 子狀態(進入 Step 2 的首個瞬間)

┌──────────────────────────────────────────────────┐
│                                                    │
│              [LOGO]                                │
│                                                    │
│          硬體偵測                                  │
│                                                    │
│          ⟳ 正在掃描 Kneron 裝置...                │
│                                                    │
│          (平均 2-5 秒)                          │
│                                                    │
└──────────────────────────────────────────────────┘

3.2.2 Found 子狀態(找到 ≥ 1 個裝置)

┌──────────────────────────────────────────────────┐
│                                                    │
│          ✓ 偵測到 Kneron 裝置                     │
│                                                    │
│          ┌────────────────────────────┐          │
│          │ Kneron KL520 · USB 001     │          │
│          │ 韌體 v2.1.0                │          │
│          └────────────────────────────┘          │
│                                                    │
│          偵測到 1 個裝置,已就緒                   │
│                                                    │
│          [ 進入 Dashboard ]  [ 重新掃描 ]         │
│                                                    │
└──────────────────────────────────────────────────┘

3.2.3 Not Found 子狀態R5-5a 新行為:沒找到就空白)

┌──────────────────────────────────────────────────┐
│                                                    │
│          ⚠ 未偵測到 Kneron 裝置                   │
│                                                    │
│          ┌────────────────────────────────────┐  │
│          │ 可能的原因:                        │  │
│          │ • 裝置尚未插入 USB                  │  │
│          │ • 驅動程式未安裝                    │  │
│          │ • 裝置被其他程式占用                │  │
│          └────────────────────────────────────┘  │
│                                                    │
│          你可以現在插入裝置後「重新掃描」,        │
│          或略過直接進入 Dashboard稍後           │
│          從 Devices 頁面再掃描。                   │
│                                                    │
│          [ 重新掃描 ]    [ 略過並進入 Dashboard ] │
│                                                    │
└──────────────────────────────────────────────────┘

R5-5a 的關鍵決策:沒插硬體不會停在這個畫面逼使用者插,使用者可以按「略過並進入 Dashboard」Dashboard / Devices 頁面自己會顯示「無裝置」空狀態。

3.3 Step 2 的「進入 Dashboard」規則

情境 按鈕 行為
Found [ 進入 Dashboard ] primary firstRunCompleted = true → Dashboard
Not Found [ 略過並進入 Dashboard ] secondary 同上
Found但使用者按 [ 重新掃描 ] 重跑掃描,回到 Scanning 子狀態
Not Found使用者插入裝置後按 [ 重新掃描 ] 重跑掃描,成功的話進入 Found 子狀態

4. 「沒有 Mock 的替代心智模型」

R5-5a 砍掉 Mock 後,使用者如果沒插硬體就什麼都看不到推論結果。這對「想先玩玩看」的新手是個空狀態問題。

設計回應

  • Dashboard 空狀態:顯示「插入 Kneron 裝置開始推論」的友善引導,而不是冷冰冰的「無資料」
  • Devices 頁面空狀態:顯示「如何取得 Kneron 裝置」的連結 + 「重新掃描」按鈕
  • Workspace 入口如果沒有裝置sidebar 的 Workspace 項目 disabled 並 tooltip 請先在 Devices 頁面連接裝置

這些空狀態細節沿用 v1 spec/08-states.md,但把原本寫「或切換到 Mock 模式試用」的句子全部刪除


5. i18n key 變動

5.1 新增 keyzh-TW / en

Key zh-TW en
firstRun.step1.title 歡迎使用 visionA-local Welcome to visionA-local
firstRun.step1.description 這是一個本機 Edge AI 推論工具,你可以在自己的電腦上跑模型,完全離線。 A local edge AI inference tool. Run models on your own computer, fully offline.
firstRun.step1.gatekeeperTitle 你可能剛才看到系統安全性警告? Did you see a system security warning?
firstRun.step1.gatekeeperDescription 因為這是內部工具,未購買 Apple/Microsoft 憑證簽章。你看到的警告是正常的,我們已經驗證此版本的完整性。 This is an internal tool without Apple/Microsoft code signing certificates. The warning is expected, and this version has been verified for integrity.
firstRun.step1.next 下一步 Next
firstRun.step1.skip 略過 Onboarding Skip onboarding
firstRun.step2.title 硬體偵測 Hardware detection
firstRun.step2.scanning 正在掃描 Kneron 裝置... Scanning for Kneron devices...
firstRun.step2.found 偵測到 Kneron 裝置 Kneron device detected
firstRun.step2.foundSummary 偵測到 {count} 個裝置,已就緒 {count} device(s) detected and ready
firstRun.step2.notFound 未偵測到 Kneron 裝置 No Kneron device detected
firstRun.step2.notFoundReasons 可能的原因:• 裝置尚未插入 USB • 驅動程式未安裝 • 裝置被其他程式占用 Possible reasons: • Device not plugged in • Driver not installed • Device occupied by another app
firstRun.step2.notFoundHelp 你可以現在插入裝置後「重新掃描」,或略過直接進入 Dashboard稍後從 Devices 頁面再掃描。 Plug in a device and rescan, or skip to the Dashboard and scan later from Devices.
firstRun.step2.rescan 重新掃描 Rescan
firstRun.step2.enterDashboard 進入 Dashboard Enter Dashboard
firstRun.step2.skipToDashboard 略過並進入 Dashboard Skip to Dashboard

5.2 刪除 key原 Step 2「模式選擇」的 key 全砍)

所有 firstRun.mode.* / firstRun.step2.*(若原 step2 = 模式選擇)相關 key 全部刪除。這包含但不限於:

Key 理由
firstRun.mode.title 模式選擇整步消失
firstRun.mode.real.title 同上
firstRun.mode.real.description 同上
firstRun.mode.mock.title 同上
firstRun.mode.mock.description 同上
firstRun.mode.recommend 同上
firstRun.mode.switchLater 同上

(實際 key 名以現有 i18n 檔為準grep firstRun.mode 全刪)

5.3 重編號注意

v1 的 firstRun.step2.*模式選擇被砍v1 的 firstRun.step3.*(硬體偵測)在 v2 變成 firstRun.step2.*需要 renamefirstRun.step3.*firstRun.step2.*,或者乾脆用意義化命名:firstRun.welcome.*firstRun.hardware.*。建議後者,後續維護更清楚。


6. 無障礙考量

項目 設計
步驟指示 Header 顯示 Step 1 of 2 / Step 2 of 2,對 screen reader friendly
Keyboard Tab 循序、Enter 觸發 primary button、Esc 不關閉(防止誤按)
Focus 初始 每步的 primary button 預設聚焦
ARIA <section role="region" aria-labelledby="step-title">;掃描 spinner <span role="status" aria-live="polite">
Reduced motion 關閉步驟間 slide transition

7. 與 v1 差異對照

面向 v1三步 v2兩步
入口 Wails splash → 跳 Next.js Wails 控制台 → 自動開瀏覽器 → Next.js
步驟數 3歡迎 / 模式選擇 / 硬體偵測) 2(歡迎 / 硬體偵測)
模式選擇 有(真實硬體 / Mock R5-5a 砍 Mock
硬體未偵測到的引導 「或切換到 Mock 模式試用」 「略過並進入 Dashboard稍後重掃」
略過按鈕位置 每步右上 Step 1 右下、Step 2 主按鈕之一
完成標記 localStorage.firstRunCompleted 同(不變)

8. 邊界情境

情境 處理
使用者在 Step 1 關閉瀏覽器 tab firstRunCompleted 不變,下次打開還是從 Step 1 開始
使用者在 Step 2 Scanning 中關閉 同上
使用者在 Step 2 按「略過」 firstRunCompleted = true,下次打開直達 Dashboard
使用者清 localStorage 後重開 重新跑 First-Run這是 feature 不是 bug
首次自動開瀏覽器失敗xdg-open 在極簡 Linux 瀏覽器沒開 → 使用者會看到控制台「Running · Browser opened」但瀏覽器沒動 → 使用者手動點 [Open in Browser] → 瀏覽器打開 → 進 First-Run
使用者在 Wails 控制台 Settings 關了 auto-open下次雙擊 進 Step 1 的前提需要使用者手動點 Open in Browser。控制台開著等使用者動作

9. 給 PM 的提醒

  • PRD 原本定義 First-Run 是 3 步,02-prd/ 子檔需要更新
  • Persona 流程描述 v1 寫「使用者被引導到模式選擇」,要改
  • 「Mock 模式是 MVP 功能」若曾寫進 PRD須移到「非目標 / removed features」
  • feature-inventory.md 若列出 Mock 模式為 feature需標記為 removed

下一步

  • 給 PM Agent 更新 PRD 對應段落Orchestrator 自行更新或轉交 PM
  • 給 Frontend Agent 按本 spec 實作 onboarding 頁面
  • 給 Testing Agent 設計 E2E雙擊 app → 看控制台 → 自動開瀏覽器 → 跑 First-Run → 進 Dashboard 的完整 flow