4 Commits

Author SHA1 Message Date
d946561362 fix(local-tool): Stage 順序亂跳修復 + 移除秒數顯示
兩個問題一次修:

1. Stage 順序亂跳 — 「Stage 1 等待中、Stage 2 完成、Stage 3 進行中」
   根因:Wails Webview JS load 需 1-3 秒(Windows 乾淨環境更慢),這段
   期間 Go 的 Pipeline.Start 已經 emit Stage 1 running event 甚至跑完
   Stage 1 / Stage 2,但前端 EventsOn 還沒掛上去,events 全被丟掉。前端
   接到的第一個 event 可能是 Stage 2 completed 或 Stage 3 running,
   stages[1].status 仍是初始 pending 值,UI 顯示亂序。

   修法:
   - 新增 Go binding GetStartupSnapshot() 回傳 pipeline 當前所有 stages
     狀態(含 current / startedAt / status)。
   - 前端 init 流程在 subscribeEvents 後立即拉一次 snapshot,補上漏掉
     的 stage 狀態。
   - updateStage 加 monotonic 模式:snapshot 補漏時不會用較舊狀態覆蓋
     已收到的較新狀態(避免 race condition 倒退)。
   - status 優先級 STAGE_STATUS_RANK = pending<running<{skipped,failed}<completed

2. 進度條已等待秒數顯示錯誤 — 「進度 3 / 6 · 已等待 20 秒」
   根因:pause 機制讓 elapsed 計算失準(pause 期間 wall clock 仍走但
   stages[i].startedAt 沒重設,會顯示明顯比真實還久的數字)。使用者
   覺得不需要顯示秒數。
   修法:
   - paintProgressBar 移除 elapsedText 邏輯,永遠顯示 progressLabel
   - i18n 文案移除 {elapsed} placeholder(zh-TW + en):
     stage.1.detail.seedSlow / stage.3.detail.waitHealth /
     stage.3.detail.waitHealthSlow 都改為固定文案
   - Go 端 emit 仍會傳 elapsed(waitProgress callback 不變),但前端
     i18n template 不再用該變數,自然就不顯示

驗證:
- visiona-local 套件 go build / vet / test -race 全綠
- macOS dmg 163MB 重 build OK
- Wails bindings 自動 regen 含 GetStartupSnapshot

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 01:14:21 +08:00
ff5cab6b0e feat(local-tool): hard timeout 180s + 全 stage 細步 detail emit + Stage1 seed pause
使用者回報 Windows 仍看到「啟動時間超過 60 秒」紅 banner,且要求每個
階段做什麼都印出來給使用者知道。三件事一次到位:

1. startupHardTimeout 60s → 180s(直接放寬到 3 分鐘)
   即使三段 pause 機制(Stage 1 seed / Stage 2 Python bootstrap / Stage 3
   waitHealthy)都生效,Windows 乾淨環境段落間累積延遲仍可能超過 60 秒。
   180s 給意料之外的延遲足夠 buffer,搭配 pause + 細步進度 emit 涵蓋
   99% 情境。日常啟動只要幾秒,放寬不影響正常情境。
   - 同步更新 i18n 紅 banner 文案 60 → 180
   - 同步更新 unit tests(HardTimeout 用 -185s、SkipBypass 用 -200s、
     PreventsHardTimeout 用 wall=-300/paused=-250 對應 effective=50s)

2. Stage 1 seedUserDataDir 包進 PauseHardTimeout
   Windows 乾淨環境首次跑會被 Defender real-time scan 對 8 個 nef 檔
   逐個掃 5-30 秒。屬一次性 bootstrap,和 Stage 2/3 同理應豁免 hard
   timeout。第二次啟動 fileExists 早 early return,pause 影響 0ms。
   配套:seed 期間每 5 秒 emit slow hint 帶 elapsed 秒數,避免使用者
   看 spinner 不動以為當機。

3. 全 stage 細步 detail emit
   原本只有 Stage 3 有 sub-step 文案(spawn / waitHealth / waitHealthSlow)。
   現在 Stage 1/2/4/5/6 都有:

   Stage 1: migrate / lock / ipc / seed / seedSlow
   Stage 2: detect / bootstrap / venv / pip / driver
   Stage 3: spawn / waitHealth / waitHealthSlow
   Stage 4: probe
   Stage 5: open
   Stage 6: wait

   每個 detail 對應一段使用者能讀懂的中英文文案(i18n.js zh-TW + en)。
   前端 startup-panel 收到 startup:stage-detail event 後在對應 stage 列
   下方顯示文案,比看著「進行中...」靜止文字直觀很多。

   Stage 2 driver install 因為發生在 CompleteStage(2) 之後 current=3,
   emit 到 stage 3 而非 stage 2,避免被前端忽略(detail 只在 stage
   running 時顯示)。

更新 fix marker 為「9c9e005+ (180s hard timeout + all-stage sub-step
detail + Stage1 seed pause)」讓使用者拉新版後能從 wails.log 確認版本。

驗證:
- visiona-local 套件 go build / vet / test -race 全綠
- macOS dmg 163MB 重 build OK

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:45:50 +08:00
9c9e005d33 feat(local-tool): Stage 3 sub-step 進度 + 啟動完成後面板可收合
回應使用者三項需求:
1. healthCheckTimeout 60s → 180s(涵蓋 Defender + EDR 串行延遲最壞情境)
2. Stage 3「啟動本機伺服器」期間顯示細步在做什麼,並在 15 秒後改為「首次
   啟動較久屬正常」slow hint,避免使用者看著 spinner 不動以為 app 掛了
3. 啟動完成後 6 階段面板自動收合成一行 summary,使用者點擊可展開檢視歷
   史紀錄;Restart / Retry 會重置並展開新一輪

實作:

Go 端
- healthCheckTimeout 60s → 180s(理由註解寫清楚 Defender + EDR 各自延遲)
- waitHealthy() 加 progress callback,每 5 秒呼叫一次傳入 elapsedSeconds
- StartupPipeline 加 StartupStageDetailEvent + EmitStageDetail() API
- startServerV2 在 spawn 前 emit detail.spawn,等 health check 期間 callback
  emit detail.waitHealth(< 15s)或 detail.waitHealthSlow(>= 15s)

前端
- 新訂 startup:stage-detail event → updateStageDetail() 把 i18n key 解析為
  文案存到 stages[n].detail,paintStageRow 優先顯示 detail(蓋過 slow hint)
- collapseStartupPanel() / expandStartupPanel() / resetStartupPanel() 三個新
  API 取代 hideStartupPanel;startup:ready 觸發 collapse、Retry/Restart 觸
  發 reset+expand
- collapsed CSS:保留 panel 但縮成一行 summary(標題改「啟動完成」+ ✓ +
  「點此展開檢視」hint),整個 panel 可點擊;hover 加亮
- i18n 加 6 個 keys(zh-TW + en)

驗證:
- visiona-local 套件 go build / vet / test -race 全綠
- macOS dmg 重 build 163MB OK
- 乾淨 dataDir 啟動 wails app:startup 1 秒內完成(macOS 已 cache binary
  + Python venv),server listen 3721,Chrome 自動連上 — 整條 cold start
  正常

Windows 首次安裝預期行為(修復後):
- Stage 1 → Stage 2(首次 bootstrap pause hard timeout,跑 1-3 分鐘)→ Stage
  3 spawn → 等 health check 30-90 秒(Defender 掃 binary)期間有「已等 N
  秒」即時更新 → ready → 自動 collapse → 瀏覽器自動開啟

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 00:17:37 +08:00
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