依 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>
163 lines
17 KiB
Markdown
163 lines
17 KiB
Markdown
# TDD v2 — visionA-local(Round-2 refactor 後)
|
||
|
||
> 作者:Architect Agent
|
||
> 版本:**v2.1**
|
||
> 日期:2026-04-14(v2.0 → v2.1 吸收 PM 審閱 + R5-D + R5-E)
|
||
> 狀態:Draft(v2.1 由 Architect 根據 PM 互審 + R5-D/E 新決策產出,待三方再次 cross-review + 使用者確認)
|
||
> 取代:`TDD.md` v1.0(2026-04-11,四輪修訂 + Plan B 補件)
|
||
> 決策來源:`progress.md` §「R5 第五輪使用者決策」+ 「R5-D 補充決策」+「R5-E 階段化啟動新指標」(2026-04-14)
|
||
|
||
---
|
||
|
||
## 0. 版本資訊與變更摘要
|
||
|
||
### 0.0 v2.0 → v2.1 差異速覽(2026-04-14 本次更新)
|
||
|
||
| # | 變更面向 | v2.0 | v2.1 | 觸發 |
|
||
|---|---------|------|------|------|
|
||
| 1 | **AC-1.3 啟動時間** | 10 秒硬指標 | **60 秒 + 6 階段進度顯示**(20 s soft timeout / 60 s hard timeout)| R5-E1~E6 |
|
||
| 2 | **自動開瀏覽器行為** | 首次啟動開一次(`autoOpenedThisSession` flag 控制 per-session-once)| **每次 Start/Restart 成功都開**(砍 flag;R5-D3)| R5-D3 |
|
||
| 3 | **AutoOpenBrowser 預設值** | 三平台統一 true | **macOS/Windows true、Linux false**(分平台 default)| R5-D2 |
|
||
| 4 | **Server 崩潰通知** | 僅控制台 Error banner | **Error banner + OS 原生通知並存**(`notify.go` 三平台實作)| R5-D1 |
|
||
| 5 | **Shutdown grace period** | 5 s → 10 s(Architect Q4 提議)| **7 s + 1 s 顯示「停止中…」modal**(PM Q4 定案)| PM Q4 |
|
||
| 6 | **Shutdown race condition** | 靠 polling 3 次失敗(0.5-15 s 後顯示 overlay) | **WebSocket `server:shutdown-imminent` 廣播**(秒內觸發 overlay)| PM Minor 4 |
|
||
| 7 | **Restart port 處理** | 允許 fallback(3721 → 3722 …)| **強制保留舊 port**,被佔用進 Error state | Architect F-2 |
|
||
| 8 | **Preferences 持久化** | 提及 atomic write 但未定位置 | **`<dataDir>/preferences.json` + write-rename**(完整 spec)| PM §11-1 |
|
||
| 9 | **`videoIsURL` field 處置** | 「視情況保留或刪除」 | **明確刪除**(grep 證實是 dead code)| PM Minor 5 |
|
||
| 10 | **idle RAM 450 MB 目標** | 未澄清範圍 | **澄清不含瀏覽器 tab**(只計 Wails + Go server + Python)| PM §11-3 |
|
||
| 11 | **日常啟動時間估算** | 無 | **新增估算 ~3.8 s**,符合 AC-2.1 ≤ 5 s | PM Minor 2 |
|
||
| 12 | **boot-id 生成方式** | 建議 google/uuid | **用 `crypto/rand` 16 bytes → hex**(不引依賴)| Architect Q3 |
|
||
| 13 | **navigator.language fallback** | 基本 startsWith('zh') | **強化:處理 C/POSIX/空字串 + hardcoded 英文 fallback** | Architect Q5 |
|
||
| 14 | **milestone 數量** | M8-1 ~ M8-10(10 個)| **+M8-4b 階段化啟動**(11 個) | R5-E |
|
||
| 15 | **總工時估算** | ~10 人天 | **~12 人天**(R5-E +1 天、R5-D1 +0.3 天、PM Q4 +0.2 天、Minor 4 +0.3 天 + 其他 0.2 天)| 以上 |
|
||
| 16 | **新增檔案** | — | **`v2/startup-pipeline.md`**(R5-E 實作細節) | R5-E |
|
||
|
||
**未變更**(v2.0 其餘設計保持不動):Wails 視窗 = 控制台 UI、瀏覽器 tab 載業務、yt-dlp/Mock 砍除、ffmpeg LGPL 方案 B、CORS 白名單、boot-id 機制、LogBuffer 2000 行 ring buffer、state machine 5 個狀態。
|
||
|
||
### 0.1 v1 → v2 差異速覽
|
||
|
||
| 面向 | v1(2026-04-11) | v2(2026-04-14) | 觸發決策 |
|
||
|------|-----------------|-----------------|---------|
|
||
| **Wails 視窗載入內容** | Splash → `window.location.replace` 跳到 Next.js 主 UI(M7-B)| Splash 路徑完全移除,Wails 永遠停在「控制台 UI」:server 狀態 / log panel / 啟停控制 / Open in Browser | R5-1 A+B+G |
|
||
| **使用者業務 UI 承載者** | Wails WebView(M7-B 是純 HTTP,但仍在 WebView 內)| **瀏覽器 tab**(Chrome / Safari / Edge)`http://127.0.0.1:<port>/` | R5-1 |
|
||
| **yt-dlp 全套** | 保留(M6 vendor 35 MB + handler + 前端 URL tab)| **完全砍除**(vendor + handler + frontend UI + i18n + bootstrap + installer payload) | R5-7 前置;M8-1 |
|
||
| **Mock 模式** | 保留(`--mock` flag + `VISIONA_MOCK` env + UI hint + 兩份 i18n) | **完全砍除**(Go mock driver / mock camera / env var / flag / UI 元件 / i18n keys) | R5-5a |
|
||
| **ffmpeg 授權** | GPL(evermeet / BtbN / johnvansickle),`VISIONA_ALLOW_GPL_FFMPEG=1` release blocker | **LGPL 方案 B(混合)**:Win/Linux 換 BtbN LGPL;macOS 自 build decoder-only ~20 MB,binary commit 到 `vendor/ffmpeg/macos/` | R5-6 / R5-6a / R5-6b |
|
||
| **ffprobe** | 未打包 | **三平台都一起包**(ffmpeg + ffprobe) | R5-6c |
|
||
| **Tray** | 第三輪 Q-A 砍掉 | 維持砍,不復議 | R5-3 |
|
||
| **關閉視窗行為** | Q7=B 傳統式(關 = 結束 app)| 維持 Q7=B,但新增:關閉前先 `StopServer()` 優雅結束;瀏覽器 tab 偵測 server 離線後顯示全域 Offline Overlay | R5-2 |
|
||
| **Server 控制 bindings** | 只有 `GetServerStatus` / `GetServerURL` / `OpenBrowser`(隱式 start)| 補齊 `StartServer` / `StopServer` / `RestartServer` / `GetRecentLogs` / `ClearLogs` / `GetSystemInfo` 及完整 state machine | R5-1 |
|
||
| **watchServer 失敗行為** | 3 次失敗 → `reportFatal` + `os.Exit(1)`(app 一起死) | 3 次失敗 → 切 `ServerStateError`,Wails app 保留讓使用者手動 Restart 或查 log | 三方共識 #10 |
|
||
| **自動開瀏覽器** | — | 首次 server 就緒自動開一次;Settings 的 `openBrowserOnStart` 可關 | R5-4 |
|
||
| **CORS 政策** | 寬鬆(`Access-Control-Allow-Origin: <任意 Origin>`)| 嚴格 whitelist `http://127.0.0.1:*` + `http://localhost:*`;其他 Origin → 不回 ACAO header / OPTIONS 405 | 三方共識 #5 |
|
||
| **綁定 interface** | `--host 127.0.0.1` | 維持不動(不做 LAN) | R5-1 |
|
||
| **上傳影片副檔名** | `.mp4 / .avi / .mov` | `.mp4 / .avi / .mov / .mpeg / .mpg`(瀏覽器能吃 + Kneron pipeline 吃得到的交集) | 三方共識 #11 |
|
||
| **Boot-ID 機制** | 無 | 新增 `GET /api/system/boot-id`,server 啟動時產生 UUID;瀏覽器每 5 s poll,boot-id 變更 → force reload | 三方共識 #14 |
|
||
| **控制台 UI 技術選型** | — | vanilla HTML/JS/CSS,從現有 `visiona-local/frontend/` splash 改寫 | 三方共識 #7 |
|
||
| **沿用率** | — | **85-95%**(詳見 `v2/code-reuse-v2.md`) | 三方共識 #1 |
|
||
| **總工時** | — | **~10 人天**,拆成 10 個 milestone(詳見 `v2/milestone-plan.md`) | 三方共識 #1 |
|
||
|
||
### 0.2 v1 未變的決策(v2 繼續沿用)
|
||
|
||
- 三層程序模型(Wails 殼 + Go server 子行程 + Python sidecar)— D1
|
||
- Python runtime 雙策略(bundled / system / auto)— D2
|
||
- 完全放棄程式碼簽章(macOS ad-hoc、Windows 無 Authenticode、Linux 無簽章)— D3
|
||
- x86_64 only,三平台都不做 ARM — D4
|
||
- 預置模型全部打包(~73 MB),不做 auto-update、不收 telemetry — D5
|
||
- 資料目錄位置、single-instance lock、舊資料目錄遷移、IPC raise 機制全部保留
|
||
- 首次安裝 ≤ 5 分鐘、首次推論 ≤ 30 s / 回訪 15 s 等 NFR 目標不變
|
||
- Ubuntu 與 Windows 打包流程(AppImage / Inno Setup)不變
|
||
- 中英雙語(前端)機制不變,控制台 UI 使用同一份 `en-US` / `zh-TW` JSON(詳見 `v2/control-panel.md`)
|
||
|
||
---
|
||
|
||
## 1. 新架構總覽
|
||
|
||
### 1.1 三層進程模型
|
||
|
||
```
|
||
Wails 殼(桌面控制台 UI)
|
||
└─spawn─▶ Go server 子行程(Gin HTTP + WebSocket on 127.0.0.1:random_port)
|
||
├─spawn─▶ python3 kneron_bridge.py(KneronPLUS SDK,sidecar)
|
||
└─spawn─▶ ffmpeg / ffprobe(on-demand 解碼)
|
||
|
||
Wails 殼 ←── IPC / Wails bindings ── Wails 視窗內的控制台 UI(vanilla HTML/JS/CSS)
|
||
Go server ←── HTTP / WebSocket over loopback ── 瀏覽器 tab(Next.js Web UI,業務操作全在這裡)
|
||
```
|
||
|
||
**關鍵差別於 v1**:Wails 視窗**不**載入業務 UI,它是獨立的控制台(status / log / start-stop / open-in-browser / preferences)。業務 UI 在瀏覽器 tab 跑 `http://127.0.0.1:<port>/` 的 Next.js SPA。
|
||
|
||
完整 ASCII 架構圖詳見:`v2/control-panel.md` §3(控制台 UI wireframe)、`architect-analysis-round2-refactor.md` §A1(v1→v2 資料流對照)。
|
||
|
||
### 1.2 ServerController State Machine
|
||
|
||
五個狀態:`Stopped / Starting / Running / Stopping / Error`。轉換由 `ServerController.txMu + mu` 雙 mutex 保護,不可跳過中間狀態。
|
||
|
||
- **Start**:`Stopped|Error → Starting → Running`(失敗走 Error)
|
||
- **Stop**:`Running → Stopping → Stopped`
|
||
- **Restart**:`Running → Stopping → Stopped → Starting → Running`
|
||
- **watchServer 3 次失敗**:`Running → Error`(v1 是 `os.Exit`,v2 改為 Error state 讓使用者手動復原)
|
||
|
||
完整細節見 `v2/server-lifecycle.md` §5。
|
||
|
||
### 1.3 資料流摘要
|
||
|
||
| 情境 | 簡述 |
|
||
|------|------|
|
||
| **冷啟動 + R5-4 自動開瀏覽器** | Wails `OnStartup` → 常規 seed / lock / IPC → `ServerController.Start()` → spawn server + logPump × 2 → 健康檢查 → `state = Running` → 若 `openBrowserOnStart` 且本 session 首次 → `OpenInBrowser("")` |
|
||
| **Log 推送到控制台** | server stdout/stderr → `cmd.StdoutPipe/StderrPipe` → `logPump` goroutine(bufio scanner + 10 ms micro-batch)→ 同時 (1) 寫 `logs/server.{stdout,stderr}.log` + (2) append 到 `LogBuffer`(ring 2000 行)+ (3) `EventsEmit("log:append", []LogLine)` → Wails JS 訂閱 `EventsOn('log:append', ...)` → log panel 增量 render |
|
||
| **Restart 期間瀏覽器 tab 自動重連** | 使用者按 Restart → Stop → Start → server 新 boot-id → 瀏覽器 polling `/api/system/boot-id`(5 s interval,Page Visibility API)偵測到 id 變 → `window.location.reload()` |
|
||
| **關 Wails 視窗 (R5-2)** | `OnBeforeClose` return false → `OnShutdown` → watchCancel → `ServerController.Stop()`(SIGTERM → 10 s → SIGKILL)→ releaseLock → Wails quit。瀏覽器 tab 的 polling 連續 3 次失敗(15 s)→ `<ServerOfflineOverlay>` 顯示「Server 已離線」 |
|
||
|
||
詳細時序與 Go 實作見 `v2/server-lifecycle.md` §2-9;瀏覽器端實作見 `v2/web-ui-offline-overlay.md`。
|
||
|
||
---
|
||
|
||
## 2. 子檔案地圖
|
||
|
||
| # | 子檔 | 目的 | 對應 R5 決策 / M8 milestone |
|
||
|---|------|------|-----------------------------|
|
||
| 2.1 | [`v2/control-panel.md`](./v2/control-panel.md) | Wails 控制台 UI + Go App bindings + LogBuffer + log pump + 狀態機 + Preferences(R5-D2/D3)+ OS 通知觸發點 | R5-1, R5-5, R5-D1/D2/D3, R5-E;M8-4, M8-4b, M8-5 |
|
||
| 2.2 | [`v2/ffmpeg-lgpl.md`](./v2/ffmpeg-lgpl.md) | 三平台 LGPL ffmpeg vendor 策略(Makefile patch + macOS build script + 授權檔管理) | R5-6, R5-6a, R5-6b, R5-6c;M8-3 |
|
||
| 2.3 | [`v2/server-lifecycle.md`](./v2/server-lifecycle.md) | Server 生命週期細節:state machine、port 分配(F-2 強制保留)、pipe 捕捉、7+1 秒 graceful shutdown、boot-id、OS 通知(§10)、Preferences 持久化(§11) | R5-2, R5-4, R5-D1, PM Q4, F-2, PM §11-1/11-3;M8-4, M8-9 |
|
||
| 2.4 | [`v2/cors-security.md`](./v2/cors-security.md) | CORS whitelist middleware、WS origin check、資料驗證邊界 | 三方共識 #5;M8-8 |
|
||
| 2.5 | [`v2/deletions.md`](./v2/deletions.md) | yt-dlp / Mock 模式全清單(檔案 / 函式 / 行號 / i18n key / vendor / installer);v2.1 修正 `videoIsURL` / `NewVideoSourceFromURL` 明確刪除 | R5-5a, R5-7, PM Minor 5;M8-1, M8-2 |
|
||
| 2.6 | [`v2/web-ui-offline-overlay.md`](./v2/web-ui-offline-overlay.md) | 瀏覽器 tab 的 `<ServerOfflineOverlay>` 實作:polling + **WebSocket shutdown-imminent** 雙管道、重試、SSR 相容 | R5-2 三方共識 #14, PM Minor 4;M8-7 |
|
||
| 2.7 | [`v2/milestone-plan.md`](./v2/milestone-plan.md) | M8-1 ~ M8-10 + **M8-4b 階段化啟動**;總工時 ~12 人天 | 整體;M8-* |
|
||
| 2.8 | [`v2/code-reuse-v2.md`](./v2/code-reuse-v2.md) | 逐模組沿用 / 改寫 / 新寫比例表 | 整體 |
|
||
| 2.9 | [`v2/startup-pipeline.md`](./v2/startup-pipeline.md) | **v2.1 新增**:R5-E 6 階段啟動管線實作(event schema、StartupPipeline struct、watcher goroutine、60 s hard timeout / 20 s soft timeout、前端 startup-panel.js)| R5-E1~E6;M8-4b |
|
||
|
||
---
|
||
|
||
## 3. 風險清單(v2 更新)
|
||
|
||
繼承 v1 `risks-and-mitigations.md` 全部風險,以下為 v2 新增或升級的條目:
|
||
|
||
| # | 風險 | 等級 | 新增/升級 | 緩解 |
|
||
|---|------|------|----------|------|
|
||
| R-v2-1 | **M7-B M1 驗收漏看 Wails 視窗** 的教訓 — v2 控制台是全新 UI,重複踩同樣坑的風險 | 🟠 中 | 新增 | M8-10 驗收 checklist 強制三個檢查:(1) 雙擊 .app / .exe / .AppImage 打開後 Wails 視窗顯示的是控制台 UI(不是 splash / wizard / 白畫面);(2) 點 Open in Browser 後瀏覽器確實載入 Next.js;(3) 點 Stop 後瀏覽器 tab 能看到 Offline Overlay。每個平台都要做 |
|
||
| R-v2-2 | **macOS 自 build ffmpeg 的可重現性** — LGPL 合規稽核時必須能證明 `vendor/ffmpeg/macos/ffmpeg` 是我們在特定 configure flags 下從特定 ffmpeg commit build 出來的 | 🔴 高 | 新增 | `vendor/ffmpeg/macos/BUILD.md` 必須記錄:ffmpeg release tag(如 `n7.1`)、source tarball sha256、完整 `./configure` line、build host(macOS version + Xcode CLT version)、build date、binary sha256。未來升級 ffmpeg 時要重跑並更新 BUILD.md,不能「手改一下再傳」。同步把 configure flags 寫進 `Makefile` 的 `vendor-ffmpeg-macos-build` target(而非埋在 BUILD.md 內)讓其可 reproduce |
|
||
| R-v2-3 | **Wails EventsEmit 在高頻 stdout 下丟事件或延遲** — server boot 時 Gin / logger 一次可能噴 200+ 行;推論 frame log 若誤進 stdout 會產生秒級 30-100 行 | 🟠 中 | 新增(v1 F-4 升級)| (1) logPump 加 micro-batch:緩存 10 ms window 內的行,一次 emit 一個 `log:append` event(payload 為陣列);(2) server 推論 frame 狀態禁止用 logger.Info,改用 debug level(line-rate 測試會檢查此條);(3) 若 LogBuffer 滿 > 80% 時 logPump 降為只寫檔不 emit event(控制台看到「…(skipped N events)…」提示,使用者可 Clear Logs)。實作細節見 `v2/control-panel.md` §4 |
|
||
| R-v2-4 | **Wails 關閉視窗 → StopServer 過程中瀏覽器 tab 的 race condition** — 使用者按 × → Wails OnBeforeClose → ServerController.Stop() → SIGTERM → wait → SIGKILL → Wails 退出,**整段 ~0.5-5s 內**瀏覽器 tab 的 polling 可能看到 ECONNREFUSED 但 Overlay 還沒觸發(需連續 3 次失敗,15 s 才顯示) | 🟡 低 | 新增 | 實務上:使用者關了 Wails 視窗通常也會關瀏覽器 tab,race 不構成實際問題。若使用者真的沒關瀏覽器,15 s 後 Overlay 會出現,使用者看到「Server 已離線」訊息即可理解。不做額外優化(例:Wails 關閉前主動告知瀏覽器 — 需要 Wails → Browser 的 push channel,成本太高) |
|
||
| R-v2-5 | **macOS 自 build 的 ffmpeg 需要 codesign** — Gatekeeper 會擋未簽章的執行檔 | 🟠 中 | 新增 | (1) 在 macOS build script 最後做 `codesign --force --sign - ...`(ad-hoc sign);(2) `wails-macos` target 的 `codesign --force --deep --sign - visiona-local.app` 已覆蓋 Resources/bin 下的執行檔,沿用即可;(3) 驗收時用 `spctl --assess --verbose vendor/ffmpeg/macos/ffmpeg` 確認不會被 Gatekeeper 拒絕 |
|
||
| R-v2-6 | **boot-id polling 對瀏覽器 tab 休眠的影響** — Chrome 會把背景 tab 的 setInterval 降頻到 1 次/分鐘,可能讓使用者切回 tab 時 60 s 才偵測到 server 重啟 | 🟡 低 | 新增 | 用 Page Visibility API:tab visible → 5 s interval;tab hidden → 停 polling;tab 再次 visible → 立即 probe 一次再恢復 5 s interval。實作細節見 `v2/web-ui-offline-overlay.md` §3 |
|
||
| R-v2-7 | **砍 Mock 後空白 UI 體驗** — 使用者第一次打開沒插硬體時,Devices 頁會是空的 | 🟡 低 | 新增 | (1) Devices 頁顯示友善 empty state:「未偵測到 Kneron 裝置。請連接 KL520/KL720 後按『掃描』。」附安裝 driver 按鈕(Windows);(2) 這是 R5-5a 明示接受的結果,PRD v2 也會記錄為預期行為 |
|
||
|
||
v1 已列、v2 解除的風險:
|
||
- **ffmpeg GPL release blocker(F-5, R9)** — R5-6 LGPL 方案 B 解除
|
||
- **F-1 Wails tray 在 Linux GNOME 可能壞掉** — R5-3 維持砍 tray,風險消失
|
||
- **F-3 使用者找不回 app** — R5-2 維持關閉 = 結束,風險消失
|
||
|
||
---
|
||
|
||
## 4. 審閱紀錄
|
||
|
||
| 日期 | 審閱者 | 結論 |
|
||
|------|-------|------|
|
||
| 2026-04-14 | Architect Agent | v2.0 Draft 產出 |
|
||
| 2026-04-14 | PM Agent | v2.0 互審完成(見 `reviews/pm-review-of-tdd-v2.md`)— Major × 4 / Minor × 5 |
|
||
| 2026-04-14 | Architect Agent | **v2.1** 產出:吸收 PM Major/Minor 修正 + R5-D 三條補充決策 + R5-E 階段化啟動 + Architect 自補清單(F-2 port 保留 / B-1 OS 通知 / Q1/Q3/Q5/Q7 自決)。新增 `v2/startup-pipeline.md`;總工時 ~10 → ~12 人天 |
|
||
| 2026-04-14 | PM Agent | v2.1 待再次審閱(確認 Major × 4 都已落地 + R5-D/E 理解一致)|
|
||
| 2026-04-14 | Design Agent | v2.1 待審(重點:R5-E5 啟動階段文案、7+1 秒 stopping modal 文案、startup-panel.js 視覺對齊 Design Spec v2.1)|
|
||
| 2026-04-14 | 使用者 | 待確認 |
|