visionA/local-tool/.autoflow/03-design/v2/first-run-update.md
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

341 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.*`。**需要 rename**`firstRun.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