# LazyBoy:共用/私人 Computer、混合工具與可安裝連接器實作計劃 - 文件版本:3.0(2026-09-10;保留共用/私人主機,新增逐項優化、TigerVNC 與外部工具安裝) - 對象:接手 LazyBoy 的 coding agent 與 reviewer。 - 審查基準:`igs170911/LazyBoy`,`e6afa324530e19922909d4692c28fb005cc05a7a`;沿用前次已核對的基準;本次另讀此 commit 的 display 啟動與 MCP 程式,未聲稱本機或最新遠端 HEAD 已改好。 - 文件性質:實作規格與驗收計劃;不是已套用的 patch、不是已通過的測試報告,也沒有實測提速倍數。 - 建議在 repository 內保存於 `docs/agent-computer-implementation-plan.md`。 > 最終目標:**共用主機(Team Computer)與私人主機(Dedicated Computer)都是正式、長期支援的產品模式。** 每個 agent 綁定自己獲准使用的持久 Computer 與工具;可以多個 agent 共用一台 Computer,也可以一個 agent 使用私人 Computer。實際任務與檔案操作在綁定的 Computer 內完成,不必每步在桌面演出,但必須有操作紀錄與結果驗證。工具可安裝、授權、更新與移除。 > **取代舊版:不要執行 2.0 中「移除 Team 模式、所有 agent 強制獨立容器、全面遷移 shared → dedicated」的要求。** 本版已直接修正架構、資料約束、PR、測試與啟動指令,不只是附加例外。不要刪除既有共用 Computer 或使用者資料。 本版閱讀順序:第 0–3 節為產品與執行邊界;第 15 節為實作依賴;第 18 節為 48 項改善清單;第 19 節是 TigerVNC;第 20–21 節是外掛安裝與 Outlook;第 16 節含 64 個測試案例。 ## 0. 給 coding agent 的執行指令 直接依本文件修改既有程式,不要只重新產生另一份計劃。先確認本地 HEAD、工作目錄與既有測試,再依第 15 節的 PR 順序逐段實作。不得覆蓋使用者未提交的修改。每個階段均須附上實際 diff、測試結果、已知限制及回滾方式。 本文件優先於先前健檢文件中以下已變更的假設: 1. **不再要求所有動作在 VNC 或可見終端機演出。** 正確的結構化紀錄即可;桌面是需要時可觀看、可接管的執行介面。 2. **保留 shared 與 dedicated 兩種模式,禁止強制轉換或取消 Team Computer。** shared 允許多 agent 對一個 Computer,沿用 per-agent workspace/display/profile 與 shared/;dedicated 才要求獨立 Computer。共享資源與私人授權分開,不能把不同資料夾/DISPLAY 宣稱為惡意程式隔離。 3. 不把「用 API/CLI 加速」解讀為在 LazyBoy API 主機上執行 agent 工作。連接器、MCP 子程序、檔案工具、命令與瀏覽器控制的實際執行端都在指定 Computer。 4. 保留現有 Rust harness、Cua、Supervisor、SandboxProvider、React/noVNC、Vault、記憶、排程及 checkpoint;不做全面改寫。 5. 自動操作的範圍是使用者授權、該 Computer 能提供的能力。不得將「任何事情」翻譯成繞過 CAPTCHA/2FA、任意取用其他 agent/主機資料,或免除高風險操作核准。 遇到外部 OAuth、GPU、GUI 或付費模型環境缺失時,完成能完成的程式、fixture、mock 與單元測試;對受影響整合項目記錄 `BLOCKED_EXTERNAL` 和精確缺項。不得把 mock 成功寫成真實服務已驗證;也不得為完成測試而操作真實主信箱。 --- ## 1. 必須成立的產品契約 ### 1.1 不可違反的條件 | ID | 條件 | 必要驗收證據 | |---|---|---| | I01 | agent 的 shared/dedicated 綁定正確;私人 Computer 不與其他 agent 隱式共用,共用 Computer 明確列 membership 與 per-agent 執行 scope | 兩模式建立/恢復測試;membership、slot、profile 與文件 scope 驗證 | | I02 | 所有 agent 命令、任務檔案操作、連接器與本地 MCP 在該 Computer 執行 | API 與 Computer 放入不同 sentinel;程序/namespace 與 server-bound computer identity | | I03 | agent 任意程式不能在 API/Supervisor 主機執行 | 偽造 target、host fallback、MCP spawn 測試;只保留可信任管理操作 | | I04 | 工具是否可用取決於 agent grant、Computer 健康、account、scope 與 resource policy | 未授權、已撤銷、錯帳號與跨 agent 測試 | | I05 | 每次工具呼叫可追蹤,包含失敗、拒絕、取消與結果未知 | operation ledger、UI timeline、outbox 重播/斷線測試 | | I06 | 原生檔案與命令不需要 screenshot 或 vision 模型 | text-only 模型與 screenshot counter 測試 | | I07 | 同一資源的寫入不競爭;不同 agent 不被全域鎖拖住 | 兩 agent 併行、慢 MCP、同頁雙寫測試 | | I08 | 不確定的副作用不盲目重播 | 逾時但伺服器已執行、重送相同 operation、取消競爭測試 | | I09 | 最終成功必須有任務層驗證證據 | file hash、表單確認值、讀回 label;工具 200 不足以完成 | | I10 | 暫停、接管、取消與恢復涵蓋背景工具,不只涵蓋滑鼠 | barrier/fencing、background job、in-flight API 測試 | | I11 | 密碼、token、broker key 不進一般 prompt、tool args、trace 或記憶 | secret canary、log/checkpoint/錯誤回應掃描 | | I12 | 失敗、重啟或升級不得默默換電腦、換帳號或遺失產物 | container recreation、binding generation、artifact checksum 測試 | | I13 | shared 與 dedicated 都支援原生工具加速;共用模式不得被降級成 GUI-only 或待淘汰模式 | shared 原生 file/exec/connector 與雙 display 並行測試 | | I14 | 安裝套件、授權工具、綁定帳號是三個不同動作 | 共用安裝一次,未授權 agent 仍不能透過 broker 使用別人的帳號 | | I15 | 任務執行、agent 截圖、人類桌面串流各自可量測,不混為一種延遲 | noVNC 關閉時 native 任務仍成功;VNC 與模型 critical path 分開 | | I16 | 對「應用層 scope」與「OS 強隔離」誠實標示,不能用 prompt 承諾未知程式的安全 | 同 UID/任意 shell/第三方 MCP 的 threat-model 測試與限制說明 | ### 1.2 「檔案都在 Computer 內」的精確定義 **任務檔案**包含原始附件、下載檔、repo checkout、暫存檔、CSV、報表、程式輸出、完整工具輸出與任務執行產物。其讀寫、解析、壓縮、轉檔與掃描程序都必須在對應 Computer 執行。 允許持久 volume 的實體 bytes 由 Docker 管理並儲存在宿主機磁碟;這不等於 agent 可以直接讀寫宿主機路徑。不得把 API 主機的 `/`、任意 home 或 Docker socket 掛入 Computer。 **控制面資料**仍可保留在既有 PostgreSQL:agent 設定、授權 metadata、run/checkpoint、經脫敏的工具摘要、artifact reference、hash、耗時與事件狀態。API 可串流附件進 Computer、串流工具結果/下載給使用者、轉送模型需要的內容,但不得在主機暫存並處理任務檔案。大型原始輸出與 artifact 正本留在 Computer,API 只保存有權限的 reference。 使用外部模型或 SaaS API 仍會傳送必要資料;「在 Computer 執行」不是離線或零資料外送的承諾。模型推論及編排可在控制面;對 Gmail 等目標服務的工具請求由 Computer 內的連接器發出。 ### 1.3 能力與安全邊界 「能做各種電腦工作」以能力可擴充為目標,不限定 Gmail 或某個網站。但容器中的硬體、GPU、音訊、USB、kernel、特定 GUI 或企業 SSO 是否可用,必須由 capability probe 回報,不能偽造已支援。 一般命令以非 root 使用者執行。額外套件優先裝在使用者環境;需系統權限的安裝由受控、可稽核的管理流程核准。不可為了可操作性讓 LLM 自行取得 Docker daemon、host root 或修改 Runner 的權限設定。 --- ## 2. 現況與重用範圍 下列 F01、F03 於本次再次讀取原始碼確認;其餘為同一 commit 的前次健檢發現,coding agent 開始時仍須核對現行實作。來源見附錄 A。 | ID | 基準版本發現 | 修改方向 | |---|---|---| | F01 | `tools.rs::pack_observation()` 在 vision + 非 Identical 時回傳 None,條件反轉 | 先補紅燈測試,修正截圖交付;區分捕獲與交付狀態 [R1] | | F02 | agent-facing `shell/read_file/write_file/list_files` 透過可見終端機與截圖 | 改接真正原生工具;GUI 終端機保留給 TUI/協作 [R1] | | F03 | `SandboxProvider` **已存在** `execute/list_files/read_file/write_file`;Supervisor 已有容器內 exec 與檔案路徑 | 優先重用與強化,不必另造平行 sandbox 架構 [R2–R4] | | F04 | `runs.rs` 將 email 歸 browser-first,MCP 另列,優先級重疊 | capability-aware routing;prompt 只是配套 [R5] | | F05 | DOM browser 與 saved login 被 `vision_guard()` 一併限制 | 分 semantic、visual 與 credential capability [R1] | | F06 | browser 宣稱 CSS selector/waitMs,但 adapter 能力與使用方式不一致 | 修契約、型別化錯誤、fixture;不假設 driver 自動實作 [R6] | | F07 | `policy.rs` 重複 wait/shell 可刷新進度,災難上限不能當短任務預算 | 驗證 milestone、時間預算、有限恢復 [R7] | | F08 | API 的 `mcp.rs` 啟動 stdio 子程序;hub 的全域鎖跨遠端 await | MCP runtime 搬進 Computer,授權隔離、局部鎖 [R8] | | F09 | `crates/sandbox/src/docker.rs` 部分檔案通道以文字 JSON/lossy conversion 處理 bytes | 補 byte-safe 傳輸、大小限制、錯誤狀態與雜湊 [R3] | | F10 | `lazyboy-screen` 已有 slot→display/VNC/websockify 對應、per-display Cua/DBus、獨立 profile;x11vnc 使用 `-noxdamage` | 保留既有多 display 語意;以可切換 Xvnc backend 測試,不把 Team 視為單一桌面 [R9] | | F11 | `lazyboy-screen` 已用 `xfwm4 --compositor=off`;ensure_slot 會串行啟動桌面/VNC/Cua/終端機等 | 關 compositor 是現況,不是尚未做的新提速;按需拆 readiness 與修啟動 dependencies [R9] | 特別注意:F03 代表原生執行「有底層基礎」,不代表既有實作已完整提供取消、持續 session、原子寫入、byte-safe 傳輸、授權隔離或任務稽核。不可只把 `shell()` 改呼叫 `execute()` 就宣布整個計劃完成。 ### 2.1 檔案落點 | 現有位置 | 主要修改 | |---|---| | `crates/contracts/src/` | tool capability、operation、job、artifact、typed error 等可序列化契約 | | `crates/control/src/sandbox.rs` | 重用/擴充原生方法、job lifecycle、串流及限制 | | `crates/controld/src/` | Computer 內 Tool Runner 的路由、job 管理、檔案、browser adapter、local MCP/connectors | | `crates/sandbox/src/docker.rs` | Rust API 到指定 Computer 的 transport;不得對錯誤回傳空成功 | | `crates/supervisor/src/` | provisioning、Computer 身分綁定、受控 transport、資源/lifecycle;不執行 agent 任意主機程式 | | `crates/api/src/tools.rs` | agent-facing schema、具 grant 的 dispatch、structured outcome;拆出子模組避免繼續膨脹 | | `crates/api/src/runs.rs` | tool discovery、執行路由、checkpoint、結果與驗證、operation ID | | `crates/harness/src/policy.rs` | milestone/預算/loop guard 與 typed recovery | | `crates/api/src/mcp.rs` | control-plane 設定與 runtime directory;不再在 API spawn agent MCP | | `crates/api/src/monitor.rs`、`apps/web/src/run-monitor.tsx` | activity timeline、耗時分解、job/artifact 狀態 | | `crates/api/src/computer.rs`、`vault.rs`、`workspace.rs`、`attachments.rs` | 雙模式 Computer assignment/membership、scope、safe streaming、credential broker 整合 | | `image/computer/`、Compose、`migrations/`、`tests/` | runtime 啟動、版本固定、漸進遷移、測試與部署 | 新 module 名稱可依現有慣例調整;不得在 Rust 核心外再加一個完整 Python agent orchestrator。必要的 Node browser worker 可以是受控執行器,不是第二套總指揮。 --- ## 3. 目標架構與責任分離 ```text LazyBoy API + Rust Harness [控制面] ├─ 任務/模型/工具路由/grants/驗證 ├─ Computer assignments + memberships └─ PostgreSQL:操作紀錄、經脫敏 metadata、設定 ↓ 受控 transport Supervisor / SandboxProvider [管理面:生命週期、資源限制、身份驗證] ┌──────────┴────────────────┐ ▼ ▼ Team Computer T [共用] Dedicated Computer P [私人] ├─ agent A context └─ agent C context │ ├─ bots/A/ ├─ 私人持久 home/workspace │ └─ display/profile A └─ 私人 display/profile C ├─ agent B context │ ├─ bots/B/ │ └─ display/profile B ├─ shared/ [成員依 grant 存取] └─ 版本化工具套件 [可共用程式,不隱含共用帳號] │ │ └─ 各 Computer 內的 Runner/jobs/fs/MCP/connectors/Cua 工具資料、下載、暫存、完整輸出與執行產物留在該 Computer ``` ### 3.1 執行位置 擴充既有 `controld`/SandboxProvider,不重建另一套總指揮。API 只管編排、授權與紀錄;Supervisor 可透過 Docker exec 啟動 Computer 內可信任 helper,不能把 LLM 指令放到自己的 shell。附件與產物允許受控串流,不在 API 主機暫存解析。remote SaaS 是獲准的目標服務,不是遠端檔案處理或遠端 code-interpreter fallback。 MCP/連接器的本地 client、下載、解壓、SDK 與檔案程序皆在目標 Computer。遠端 MCP 的伺服器程式仍在遠端,不能宣稱都在本機;只有使用者准許的遠端 SaaS 存取可啟用,會代處理本機 task files/代跑 shell 的遠端工具預設拒絕。 ### 3.2 兩模式與資料約束 - `ComputerMode` 的既有 enum/儲存值先核對並保持相容;本文件用 shared/dedicated 表示產品語意,不要求隨意改資料庫字串。 - `computer_id` 為邏輯電腦;provider_ref 可變。container 重建增加 `computer_generation`。display/browser 重啟另有 session generation,不需連帶使所有原生 job 失效。 - 每個 agent 同時有一個 active assignment。**shared Computer 的 computer_id 可被多個 agent 參照**;不能替此欄位無條件加 UNIQUE。 - dedicated 的排他性用對應 owner/部分約束/transaction enforce;shared 用明確 membership(相同核准 space/team)、display slot、workspace scope 與 grants。 - 保留使用者既有選擇和建立 agent 時的共用/私人選項;新的 hybrid executor 不應改變 ComputerMode 的預設或現有 assignment。 - provisioning/screen 啟動做 per-computer/per-slot single-flight;刪除 agent 只移除自己的 assignment 和資源。Team 仍有其他成員、job 或 viewer 時不得 stop/destroy 整台 Computer。 - Computer idle 由全部成員的 jobs、MCP、screens、writers、outbox 共同判斷;不能因 A 閒置就凍結 B。 - `runner_ready`、`browser_ready(profile)`、`desktop_ready(display)`、`viewer_ready(display)` 拆開。原生工作不等 XFCE/VNC;查看桌面也不能變成業務工作存活的必要條件。 ### 3.3 共用的範圍,不等於什麼都共享 | 資源 | shared 模式預設 | dedicated 模式預設 | |---|---|---| | 容器與總 CPU/RAM | 同 Team Computer 共用、配額與公平排程 | 私人 Computer 的配額 | | agent 工作目錄與 job 歸屬 | bots// 和 own jobs,tool API scope 分開 | 私人 workspace 和 own jobs | | shared/ | 經 membership/read/write grant 分享 | 可保留本機 shared/ 名稱,但不自動跨 Computer | | 瀏覽器、DISPLAY、DBus/AT-SPI session | 沿用各 agent 的 slot/profile,不能任意拿別人的 ref | 私人 slot/profile | | 套件 bytes | 同版本可共用受保護唯讀 package store | 此 Computer 的 package store | | 工具 instance/設定/OAuth | 依 agent/grant/account 分開;明確允許才共用 instance | 私人 agent scope | | 記憶/run/操作紀錄 | agent 身份不合併;shared 檔案事件可依 membership 顯示 | agent scope | `shared/` 路徑需依既有 `resolve_bot_workspace_path`/scope 處理,不要直接重寫一套忽略舊路徑的 resolver。shared 寫入使用 canonical resource key 與版本衝突檢查,兩個 agent 看到的是同一份真正的檔案,不是各自副本卻叫 shared。 ### 3.4 誠實的信任邊界 shared 是受信任團隊的協作 Computer。**同容器、同 UID、可執行任意 shell 時,資料夾 scope 與不同 DISPLAY 不構成對惡意程式的強隔離。** 不可宣稱 tool grant 能阻止所有自行寫腳本讀其他可讀檔案/X11 session 的行為。 保留 shared 的原生能力,但敏感 broker/Runner metadata 必須與 task user 分離保護;僅向批准的 connector instance 提供 scoped credential。對需要跨 agent 機密性的工作,使用 private Computer 或新增經測試的 per-agent OS user/工作沙盒;此選項不能變成刪除 shared 的理由。 同一共用主機安裝未受信任套件等於引入可執行程式,必須顯示受影響 Team/檔案/session 範圍;沒有可驗證的 sandbox 就不能宣稱只影響某一 agent。強化模式僅在對應 OS 行為真的測過後才能標為安全隔離。容器對宿主機的邊界仍依 Docker 權限/mount/network 實作 [E4]。 ### 3.5 持久化與升級 兩模式都保留資料與 browser profile。user-space 工具使用版本化目錄與 lock manifest;OS 套件採 image/受控 recipe 重建,不承諾任意 apt 安裝跨 recreate 永久保留。 shared 和 private 都原地升級 schema/Runner,不做強制模式遷移。使用者日後明確要求換模式時,才啟動 dry-run、停止點、授權 copy、checksum、衝突處理與可回滾的 assignment 切換。 --- ## 4. 契約:身份、工具結果與 operation ledger 以下為**建議新增契約**,不是現有 API。欄位命名可調整,但語意不能消失。 ### 4.1 可信任執行 context ```json { "space_id": "space-A", "user_id": "user-A", "bot_id": "bot-A", "computer_id": "computer-A", "computer_generation": 3, "assignment_id": "assignment-A", "computer_mode": "shared", "display_session_id": "screen-A", "workspace_scope_id": "scope-A-and-shared", "run_id": "run-42", "step_id": "step-3", "operation_id": "op-17", "attempt_id": "attempt-1", "grant_id": "grant-9", "control_epoch": 8, "deadline_at": "2026-09-10T08:00:00Z" } ``` 這些身份由伺服器按登入 actor 與 run 綁定,**LLM 不得填寫或更換 computer_id、grant、account mapping 或 filesystem 根目錄**。工具參數只能是任務需要的業務參數。到 Runner 時再次驗證 token audience、agent、電腦 generation、grant、到期與 control epoch。 Supervisor shared token 不得進入 agent 的 env、home 或 prompt。每個 Computer 使用短效、限範圍認證;不要認為服務藏在 Docker 內網就等於有授權。 ### 4.2 Capability descriptor ```yaml name: gmail.labels.apply_plan version: "1" execution_plane: computer requires_vision: false required_grants: [gmail.labels.write] required_scopes: ["https://www.googleapis.com/auth/gmail.modify"] side_effect: reversible_write supports_batch: true retry_mode: verify_before_retry resource_key_template: "gmail:{account_ref}:mailbox" result_schema: ToolResultV1 ``` capability 必須區分:installed、runtime_connected、authenticated、authorized、healthy。MCP annotations、tool description、模型自評或網頁內容都不是可信任授權來源。registry 僅向模型暴露此 run 真正能用的少量工具。 ### 4.3 Structured ToolResult ```json { "schema_version": 1, "operation_id": "op-17", "status": "succeeded", "effect": "confirmed", "execution": { "computer_id": "computer-A", "computer_generation": 3, "executor": "native_process", "job_id": "job-7" }, "data": { "stdout": "12 files processed\n", "stderr": "", "exit_code": 0, "signal": null, "truncated": false, "output_artifact_id": null }, "artifacts": [], "evidence": [{"kind": "process_exit", "exit_code": 0}], "timing": {"queue_ms": 4, "execution_ms": 31}, "error": null } ``` - `status`:accepted、running、succeeded、failed、cancelled、timed_out、needs_auth、needs_approval、needs_human、policy_denied、unknown。 - `effect`:none、confirmed、partial、unknown。`succeeded` 只表示該工具契約完成,**不自動代表整個 task 完成**。 - `exit_code` 在未結束時為 null;因 signal 結束另記 signal。不得把 timeout 或空輸出視為 exit 0。 - 所有結果共用 envelope;不能再讓任意錯誤文字看起來像正常 `text_outcome`。 - wrapper 外層 HTTP 非 2xx、解析失敗、schema mismatch 必須保留錯誤;不能回傳空 file list/空 file contents 冒充成功。 ### 4.4 Operation identity、重送與恢復 `operation_id` 代表一次具體意圖,由 harness 產生並在網路重送時保持相同。`attempt_id` 區分傳輸嘗試。不可只 hash 相同 args 作 dedupe:使用者可能真的要求合法重做同一動作。 Runner 在副作用前,先將 accepted intent 寫入受保護的 durable journal;其後記錄 started、結果與驗證。控制面先記錄 dispatch intent,再傳送;UI 訂閱中央事件。中央斷線時由本地 outbox 補送,透過唯一 event key 去重。journal 無法可靠寫入時,不開始新的有副作用工作。 同一 operation 重送:running 回原 job,finished 回既有結果;never blindly rerun。Runner/容器崩潰或外部 API 回應丟失時,狀態可為 unknown,交給 verifier 做 read-back。沒有第三方 idempotency 或可觀察後置條件時,不可宣稱 exactly-once;需人工判斷或停止。 同一 operation ID 搭配不同 payload hash、帳號或 grant 必須拒絕。舊 computer_generation/control_epoch 的動作不得在新容器或相應接管 scope 後繼續執行。shared 模式使用 computer、agent 與 display 的分層 epoch,不能 A 接管就無條件使 B 的獨立工作失效。 --- ## 5. 原生命令、檔案與背景工作 ### 5.1 最小工具集合 | 工具群(建議名稱) | 行為 | 截圖需求 | |---|---|---| | `exec.run` | argv 或明確 shell mode,短作業直接回結果,長作業回 job_id | 無 | | `exec.status/output/cancel` | 查工作狀態、依 cursor 取輸出、確認取消 | 無 | | `terminal.start/interact` | 真正需要 PTY/TUI/持續互動的程序 | 文字優先,必要時 GUI | | `fs.list/stat/read/write/patch/move` | 原生 file API,byte-safe、有限讀取、原子變更 | 無 | | `fs.search` | 在 Computer 搜尋;binary/巨大資料有界處理 | 無 | | `artifact.list/export` | 回傳 Computer 內 artifact reference;下載串流 | 無 | | `browser.*` | 同一 Chromium 的 DOM/語意操作 | 按需 | | `computer.observe/act` | AT-SPI/視覺桌面操作 | 視覺動作必需 | | `account.*`、`gmail.*`、`mcp.*` | 受控 account handle 與 per-agent grant | 通常無 | 既有工具名稱可保留為 versioned alias,以免破壞 skills。alias 亦須經同一 policy、audit 與 Computer dispatch;不能留下可繞過的新舊兩套入口。 ### 5.2 Exec 與 session 的正確語意 - 一般命令優先 argv array,避免重新插入 host shell;需要 pipeline 時顯式 `mode=shell`,只在 Computer 內解譯。 - `cwd`、HOME、PATH、locale、環境變數與 session scope 由 Computer runtime 管理。不自動繼承 API 的雲端金鑰、DB URL、Supervisor token。 - `exec.run` 的 stdout、stderr、exit status 來自實際程序,不從 screenshot 或文字 prompt 猜測。 - 預設 subprocess 非互動且不維持前次 `export/cd`。需要持續環境時顯式使用 scoped session;不得讓 UI 宣稱持續,實際卻每次新 shell。 - PTY 可能合併 stdout/stderr,需在 schema 註明。任意互動 shell 的 command completion 不可靠時回 `running/unknown`,不得用尾端 `$` 字元當完成證據。 - 背景 job 由 Runner 擁有 lifecycle。HTTP request 結束不是 job 結束;回傳 job_id,保留 stdout cursor、deadline、PID/starttime/process group identity。 - 使用 bounded streaming、背壓與磁碟 quota。模型預設只收到摘要/頭尾片段,完整輸出放 Computer artifact。 - 取消必須處理 process group/subprocess tree:TERM → grace → KILL,確認狀態後才回 cancelled。不要誤殺整個 desktop、其他 job 或 PID 回收後的新程序。 - request deadline 與 job runtime timeout 分離;達 runtime timeout 後依明確 policy 停止工作。transient network timeout 不等於工作已停止。 - API restart 可找回同一 Runner job;container recreate 後原程序不再存在,要標記 interrupted/unknown 並驗證產物,不得假裝還在 running。 - 對未知 arbitrary shell,`changes_state=unknown`,不能因命令開頭是 `cat` 就假設無副作用;shell、子程序、網路都可能改變狀態。 ### 5.3 原生檔案與產物 檔案工具在 Computer 的 filesystem namespace 內執行,不能由 API 直接打開 volume 對應的主機路徑。 預設任務可寫 root 為 assignment 對應 workspace 與專屬 tmp;shared 模式再加入明確授權的 shared/ 子樹。其他 Computer 內路徑依 OS 權限與 grant 開放,並遵守第 3.4 節的 shared 信任邊界。此限制不要求 agent 只能處理某個固定副檔名,也不禁止在自己的電腦使用已安裝的系統工具。 必要實作: - Unicode、空白、引號、`$()`、反引號、換行檔名都須以資料而非 shell 程式碼處理。 - byte-safe 讀寫;UTF-8 text API 與 binary API 分離。禁止 `from_utf8_lossy` 無聲毀損 binary。小 binary 可用受限 base64,大型檔案用串流;不要將整份內容放 argv。 - `fs.read` 支援 line/byte range、最大回傳量與 continuation;二進位回 metadata/reference,不交模型亂解碼。 - `fs.write/patch` 支援 expected version/hash、目標資源鎖、temporary file + same-filesystem atomic rename;需要 durability 的操作同步資料與目錄,讀回核對 hash。 - 不存在檔案、權限不足、編碼錯誤、磁碟滿、大小超限必須各自回 typed error,不得變空字串成功。 - 路徑驗證須處理 `..`、symlink、TOCTOU、mount boundary。不要只做字串 prefix 或先 canonicalize 再無鎖 open;使用 descriptor-relative/capability-based 安全打開方式,依平台選受支援方案並測試。 - 對同一檔案的 read-modify-write,要用該次讀取的 version/hash 做 optimistic check;不同 run 並行修改會 conflict,不可覆蓋人類更新。 - `artifact_id` server 產生並綁 creator_bot/computer、visibility_scope、相對路徑、media type、size、hash、來源 operation、retention;記錄生成時 generation 作 provenance。持久檔案在重建後經重新核對 hash/scope 可重新解析,不能永久因 generation 變動而失聯。下載 API 不接受任意 host path。 - 附件入站、UI 下載、connector attachment、browser download 都必須走 Computer 內串流路徑,帶大小/quota/雜湊驗證。不得把 task bytes 放 API `/tmp` 再處理。 - destructive file operation 額外依風險核准;一般使用者已明確要求且可逆的本機整理可在 run grant 內批次執行,不必每個檔案再問一次。 ### 5.4 保留 GUI 能力但不再把 GUI 當萬用資料通道 移除「所有 shell/file output 都一定是 screenshot」的 system prompt。原生工具結果直接進模型;不為了視覺展示自動開 terminal、不重演指令、不額外截圖。 需要真正 TUI、GUI 終端機協作或使用者指定觀看時,才使用 `terminal.*`/Cua。相同 job output 可另做 UI viewer;不要求第一版將每個背景命令鏡像到桌面。 --- ## 6. Capability-aware routing 與模型迴圈 ### 6.1 工具選擇規則 在權限、資料位置與帳號已匹配的前提下,優先順序是: ```text 服務提供的結構化 API(適用於該任務) → Computer 內原生程式/檔案/已安裝 CLI → 同一 browser 的 DOM/accessibility → Cua 原生 accessibility → 新鮮截圖 + 視覺座標 → 需要人類協助 ``` 這是依任務的偏好,不是要求每件事逐層嘗試。例如讀本機 CSV 直接 fs/exec,無需先找 SaaS API;登入後操作 canvas 可直接進視覺路徑。路由針對每個子任務重算,不能整個 run 一次選 browser 後鎖死。 **授權拒絕、帳號不符、缺少 capability scope 不是換另一工具繞過政策的理由。** 同一服務操作的 policy 必須套用到 connector、browser、shell HTTP 與 MCP 等路徑。無 API 但使用者確實授權該網站的 GUI 操作,可在明確 GUI grant 下執行;不可把 `POLICY_DENIED` 當成這種情況。 ### 6.2 小任務不要多套一圈 planner - 簡單明確的 file/exec 任務,用既有模型回合或 deterministic intent-to-tool route,不再額外呼叫大模型做一份長計劃。 - 多步任務才持久化 `TaskPlan{goal,steps,dependencies,success_checks,budget}`。 - 每一步保存 input references、採用 route、已驗證 milestone、產物與 blockers。checkpoint 不只是聊天文字摘要。 - 工具 discovery 依任務載入;不要把所有 agent 的所有 MCP schema 塞進每次 prompt。 - schema cache 依 version/grant scope 快取;授權撤銷必須立即失效,不得因快取繼續使用。 - 分類、格式轉換、批次檔案處理在一次受控工具工作中完成;不是每一列、每個字、每個 click 都呼叫模型。 - 已知確定步驟可 executor-side macro,但需有限步數、每步 evidence/trace 與失敗即停;不是任意舊座標重播。 ### 6.3 Typed errors 與處理規則 | Error | 行為 | |---|---| | `AUTH_REQUIRED`/`TOKEN_REVOKED` | 進 NEEDS_AUTH,保留 task;停止有副作用請求 | | `POLICY_DENIED`/`SCOPE_DENIED`/`ACCOUNT_MISMATCH` | 明確拒絕此路徑;不改用 UI/shell 繞過 | | `TARGET_STALE` | 重新 snapshot/定位一次;只對尚未執行的操作重建動作 | | `TARGET_NOT_FOUND` | 有界重新觀察/定位;視覺 fallback 需新鮮截圖 | | `SELECTOR_UNSUPPORTED` | 換成受支援語意 locator;不再重送同一不支援 selector | | `TARGET_DISABLED` | 檢查可觀察的前置條件;僅有已知等待條件才 wait | | `RATE_LIMITED`/暫時服務錯誤 | 本地 bounded backoff + jitter/Retry-After;不由 LLM 空轉 | | `TIMEOUT_EFFECT_UNKNOWN` | 先 read-back;不能 blindly retry mutation | | `COMPUTER_UNAVAILABLE` | 恢復原 Computer,驗證 generation;不換 host 或另一 bot | | `CONFLICT` | 重新讀最新狀態,重規劃/重新核准差異 | | `CAPABILITY_UNSUPPORTED` | 回報缺少套件/裝置/模型能力;不宣稱已操作 | | `CANCELLED`/`STALE_CONTROL_EPOCH` | 不再派送;保留真實已發生效果 | ### 6.4 Model 使用策略 初版保留現有模型供應商與選模 UI,不綁定特定商業模型。原生/DOM 工具允許通過契約測試的 text-only 模型;視覺座標需要具有經驗證 vision 能力的模型。 優先減少模型回合與多餘圖片,再測模型速度。可選的高難度模型升級最多有界觸發;不能讓不同 agent 彼此委派形成無限 nested harness。 若模型不支援所需能力,誠實回 `MODEL_CAPABILITY_MISMATCH`;不得把 `vision=true` 假裝打開。prompt、schema 與 provider request 三者須有整合測試。 --- ## 7. Browser 與 Cua:保留、修正、再測另一 backend ### 7.1 預設決策 先保留 Cua driver 與既有 Cua semantic browser,修好 screenshot、schema 與 stale refs。把 browser 操作抽成受控 `BrowserExecutor` 介面,供未來替換,不先承諾換 driver 一定更快。 可選對照方案固定為 **Computer 內的 Playwright worker,連接該 Computer 現有 Chromium**,避免第一版同時引入 agent-browser、Browser Use、Hermes 三套。需要比較其他方案時另外開 ADR/實驗,不能耽誤核心原生工具交付。 Playwright 官方支援 CDP attach 到既有 Chromium,但明確指出相較原生 Playwright protocol 功能完整度較低,必須對實際 browser launch flags、frames、downloads 與 input 做相容性測試 [E3]。若對照 backend 未通過 fixture,繼續用修好的 Cua,不擴大替換。 ### 7.2 同一 browser/session 的規範 - 不要求使用者保持 VNC 開啟;但 agent 使用的 browser 必須屬於其 Computer,之後能在該桌面檢查及接管。 - 優先 attach 現有 browser instance;不得另啟程序同時占用同一份 profile。保存 computer-local session identity 與明確 tab/frame ref。 - Cua 與 Playwright **不得同時寫同一分頁/桌面**,必須共享 lease。driver 換手後清掉舊 references 並重新觀察。 - CDP 與 Runner 不對主機公網發布,不交 LLM 任意 URL;由可信任 runtime 對指定 browser 建立連線。 - 不把 headless/remote browser 當作無提示替代登入狀態的方法。 - 登入、導航、frame 切換、人工接管與 browser restart 皆是 refs invalidation boundary。 ### 7.3 修正截圖條件與交付狀態 基準版本 `pack_observation()` 修正為 vision 且畫面非 Identical 時才產生 image;純文字模型永不接收 image [R1]。 進一步拆開 `last_captured_frame`、`last_delivered_frame`、model/history identity。首次需要視覺、人工接管恢復、換 vision model、圖片歷史壓縮後,即使畫面 bytes 未變,也必須允許 force delivery。 只有圖片真正加入模型 request 後才更新 delivered 狀態。不可因背景監控抓過圖,就以為模型看過。沒有最新視覺依據時,不准猜座標。 ### 7.4 語意與座標能力分開 DOM/accessibility 操作檢查有效語意 target、權限、origin、lease,不要求 vision。pixel-only 操作檢查 vision、最新 observation identity、viewport 尺寸與 control epoch。 browser locator 使用 tagged type,例如 `snapshot_ref`、`role_name`、`css`;只有 backend 真實支援的類型才暴露。不要在名稱相近時偷偷做模糊匹配。 `wait_until` 由 executor 觀察明確條件,設 deadline;避免所有工具固定 sleep 一秒。元素 disabled 的原因可能是缺欄位,不是時間到了就好。 可新增 bounded `browser.fill_form`:每欄重新定位並驗證,按鈕提交前驗證前置條件,提交後讀回確認。不可把五個會失效的數字 id 一次盲送。 ### 7.5 底層可擴充,不預設全面操作保證 支援 normal click、type、scroll、drag、key、window focus、file upload/download、dialogs,以及 Cua 已提供的桌面能力。每一項提供 capability probe 與 fixture;不支援的 widget 明確回 unsupported。GPU、硬體或系統管理另外加受控 capability,不以一個 `run_anything_as_root` 代替設計。 --- ## 8. Concurrency、Pause、Takeover 與 Cancel ### 8.1 按真實資源上鎖,不按整台共用主機一律上鎖 | 資源 | 建議 lock key/規則 | |---|---| | GUI/native input | `(computer_id, display_session_id)` 的 writer lease;同 display 排他、不同 display 可並行 | | Browser | profile/session 對應 writer lease;涉及 OS focus/clipboard/upload dialog 時一併取 display lease | | 檔案 | canonical resource identity/重疊 subtree;shared/ 同檔必須命中同一 lock,配合 expected hash | | 信箱與連接器副作用 | provider + canonical account/tenant/mailbox;跨 Computer/agent 的同帳號亦要協調 | | MCP client | instance + grant + account 的有限 semaphore,不跨 network await 持有全域 hub lock | | 套件安裝/升級 | Computer/package/version;同包原子切換,active instance pin 原版本 | | container stop/recreate | Computer lifecycle barrier,等待所有成員 writer/job 安全停下 | 同 display 的 Cua 與 DOM 不同時 mutation;不同 display 的 DOM 可以並行,不能因同 Computer 就全部串行。browser context 不可共享 mutable singleton。多資源依固定順序取鎖、設 deadline、避免 deadlock,長等待不占用無關 lease。 受控 file 工具與已驗證 scoped jobs 可按不重疊資源並行。**任意 shell 不能靠 LLM 宣稱的路徑或 read_only 取得並行保證**:有 OS sandbox 證據才降到 scope 鎖;無界且可能影響全 Computer 的腳本/系統安裝保守取得 Computer-wide lease。這是高權限工作例外,不是讓所有 shared 工作都上全域鎖。 初始併發為可調試驗:每 agent native jobs 2、service reads 4、每 display GUI writer 1,同時設定 per-Computer/provider 上限與公平排程。不可各 agent 自行放大到壓垮共用 Computer。 ### 8.2 觀看、接管與暫停的不同 scope - Watching 不暫停,也不授予寫入;noVNC 客戶端 viewOnly 只是 UI,伺服器仍須依 lease 拒絕未授權鍵鼠/resize/clipboard。 - **接管某 agent**:保守暫停該 agent 的新 mutation 與 jobs,取得它的 display;其他 agent 的獨立 display/無衝突資源可繼續。 - **只接管某 display**:暫停所有正在寫該 display 的工作,不偷偷取得其他 display;涉及相同帳號/共享檔案時透過資源衝突顯示等待。 - **暫停整台 Computer**:對所有成員、jobs、MCP 與 display 建立 barrier;UI 顯示受影響 agents。只有具 Computer 管理權限的人能做。 - 人類若要在 shared Computer 任意改系統/全域檔案,應先選整台接管;不能保證其他 agent 不受無界人類 shell 影響。 ### 8.3 Scope-aware pause barrier 與恢復 使用 `(computer_epoch, agent_epoch, display_epoch)` 的 scope-aware fencing 或等價機制;API 和 Runner 各驗證。對該 scope 停派新 mutation、取消未執行項,對 job 採已宣告且驗證過的 cancel/suspend policy。 已送出的 SaaS mutation 無法因斷線就撤銷;持續顯示 in-flight/unknown,read-back reconciliation 後才宣稱已完成接管。取消不是 rollback。不能 SIGSTOP 整台共用容器來模擬「暫停 A」。 恢復沿用原 run/step,重新檢查 assignment、membership、grants、generation、session 與未知效果;只做未完成步驟。共享檔案與 browser state 可能已變,重新讀回,禁止沿用舊 refs 或覆蓋 B/人類修改。 觀察、核准與安全 reconciliation 可走受限恢復路徑,不讓原模型繼續無界派工。 --- ### 8.4 arbitrary code 與可觀察性的實際邊界 本計劃保證的是**經過 LazyBoy 工具閘道的每次呼叫、受控子動作及 job lifecycle 有紀錄**;不宣稱等同完整 kernel syscall 或每個應用內部操作稽核。任意 exec 內部腳本仍可能連網、啟動程序與寫檔。 因此 arbitrary exec 的 scope、網路與 OS 權限必須保守;需要逐 syscall/所有子程序網路行為的強制稽核時,另做 OS 級監控與測試。不能只改 prompt 就承諾「所有低階行為零漏記」。 --- ## 9. 紀錄、Activity UI 與資料保護 ### 9.1 必須記錄的事件 `run.started`、`step.routed`、`tool.accepted`、`tool.started`、`tool.progress`、`tool.completed`、`tool.failed`、`tool.cancel_requested`、`tool.cancelled`、`tool.effect_unknown`、`verification.completed`、`artifact.created`、`authorization.required`、`takeover.requested/acquired/released`、`run.completed/partial/failed`。 事件至少帶 server-bound identity、operation/attempt ID、tool/version、route、開始結束時間、resource scope、經脫敏 args summary、outcome、typed error、output reference、驗證證據與重試理由。 不保存模型隱藏推理;只記可稽核的 route rationale,例如「已有 Gmail labels scope,採批次 API」,不是整段思考鏈。 ### 9.2 UI 顯示 在現有 run monitor 擴充,不重做整個前端: ```text 14:20:10 原生檔案 讀取 orders.csv 成功 18 ms 14:20:10 原生命令 依規則整理 500 列 執行中 job-7 14:20:11 結果驗證 輸出列數與檔案 hash 符合 通過 14:20:12 Gmail 標籤修改預覽 80 封 等待核准 ``` 以上僅為 UI 示例,不是效能實測。 每個項目可展開看脫敏輸入、輸出摘要、差異、執行電腦、job、產物與驗證;不能只顯示「我正在努力」。背景 job 可取消;artifact 可從該 Computer 串流下載。觀看紀錄不要求開桌面。 ### 9.3 稽核安全與 durable outbox - 中央 ledger 存 metadata;原始 output/artifact 在 Computer。flush 有背壓、quota 和 retention;避免無上限 screenshot、base64 或郵件內容進 DB。 - secret redaction 在寫入 trace、logger、exception、MCP debug、checkpoint、UI 之前執行。secret type 使用 opaque handle;不靠事後 regex 當唯一防線。 - Runner 的 journal/outbox、broker keys 和管理憑證,必須置於 task shell 不可任意改寫的權限區域;中央 accepted intent 可協助查出本地結果缺口。 - 限制任務使用者對 broker/Runner proc env、memory、socket 與管理檔案存取;不能只因非 root 就假設同 UID 程序完全隔離。 - Browser 已登入狀態代表具有該帳號的存取權。若一般程式可以讀相同使用者的 browser profile/session 或控制 X11,就不能聲稱能抵抗惡意程式對所有 session 資料的窺探。部署要明確記錄此 threat model;更強隔離需 OS user/sandbox 與實測,不得僅用文案保證。 - 不記錄原始密碼、OAuth token、Authorization header、secret query、剪貼簿 secret。密碼相關操作停用或遮蔽自動 screenshot/recording;不可先拍下再只遮 log 字串。 - 檔案與郵件正文可能是敏感資料,依最小必要送模型,並提供 retention;secret canary 要掃所有正常與錯誤路徑。 --- ## 10. MCP、帳號與憑證 ### 10.1 MCP 在 Computer 執行與隔離 API 的 MCP 模組僅保存設定/授權 metadata 和 UI 狀態;stdio MCP 子程序與 remote MCP client 均由 Computer Runner 管理。兩模式都以 agent/grant 管理 MCP instance、env、working dir、account binding 與 capability set。shared 可重用唯讀套件 bytes;有狀態且含私人憑證的 instance 預設分開,明確授權且支援 request-level scope 的服務才共用 instance。安裝流程見第 20 節。 runtime key 至少包含 `(space,user,bot,computer,generation,server_instance)`,tool 名稱只是顯示名稱,不可只靠 slug 找工具而跨 agent 命中同名 server。 - 只讓授權工具進 registry,dispatch 再檢查一次;`definitions()` 不合併全域所有人的工具。 - 在短臨界區取得 client handle,釋放 hub lock 再 await。必要 semaphore 只限制該 server,不堵住別的 agent。 - 持續連線與 schema cache;restart/reconnect 清掉舊 generation 的 handles。 - stdio 套件及版本固定,不在每次 tool call 執行不固定版本的 `npx -y latest`。首次安裝是獨立、有紀錄的準備工作。 - raw MCP 結果要映射成共用 envelope,保留 `isError`、typed output、截斷與 resource references;不可只當 pretty JSON 文字認為成功。 - 處理跨 agent server alias 碰撞、404、401、timeout、schema 變動。拒絕 connector 自己要求開放更多權限或修改控制面設定。 - unknown/未受稽核的 MCP 可執行任意程式時,視同 unknown exec scope,不相信它宣稱 read-only。 ### 10.2 Credential broker 保留 Vault 的加密儲存與管理介面,但新增 per-agent/account grant。模型只取得 opaque handle。需要使用時,由可信任 broker 透過受保護 channel 交給 Computer 的受控 connector/欄位填入器;token 不暴露給 generic exec 或其他 MCP 的 env。經審查的第三方 MCP 若只支援環境變數認證,需明確批准其讀取該 token,以該 instance 的受保護 runtime 注入,記錄安全降級;無法阻止共用 task user 讀取時拒絕敏感 token 注入並回報原因,不假裝有 broker handle 即相容。 broker/trusted connector 應使用與 task shell 分離的 OS 權限(共享/私人皆適用),不放在任意工作程式可讀的 home、environment、debug output 或 task 可寫 journal。OAuth callback 可以由控制面接收與交換/安全保存授權憑證;之後真正的 Gmail 工具操作由 Computer connector 發出。不得為「全部在電腦內」而把長期 secret 塞給任意 shell。 原始密碼填入前檢查 HTTPS、精確核准 origin、frame、form target 與當前 control epoch;導航之後重新驗證。不要自動放寬成任意 Google 子網域。欄位辨識可用 input type/autocomplete/label/表單關聯,不只中文字串搜尋。 登入狀態要區分 `ORIGIN_MISMATCH`、`FIELD_NOT_FOUND`、`AMBIGUOUS_FIELD`、`AUTH_REJECTED`、`NEEDS_HUMAN`。密碼被拒不連續重送;2FA/Passkey/CAPTCHA 進人工接管。此專案不實作驗證繞過服務。 ### 10.3 授權與便利性 使用者明確要求的低風險工作可以取得 run-scope grant,不要每個讀檔、click 都重新核准。敏感外送、寄信、付款、刪除、改帳號設定或大批外部寫入要有清楚 scope 與 policy;可設定長期授權,但必須有範圍、到期、撤銷與事件紀錄。 核准綁 plan hash、account、目標資源、允許的變更與期限;修改內容變了必須重新核准。generic shell、browser 和 MCP 不得成為其他工具 policy 的繞過通道。 **重要實際限制:**對具任意本機程式、已登入 browser、直接網路權限的工作者,只做工具層 allowlist 無法證明所有出站行為都受限。需以 OS 使用者、broker 隔離、網路 egress/proxy policy 實際限制敏感服務憑證與目標;對無法強制的 generic browser/exec 高權限能力明確標示並要求額外授權,不能虛稱與 narrow Gmail tool 同等安全。 --- ## 11. Gmail:第一個端到端業務驗收案例 ### 11.1 範圍 Gmail 只是驗證新架構的第一個 connector,不將 router 寫成 Gmail 特判,其他服務應能使用相同 grants、operation、audit 與 verifier。 第一版只做使用者自訂 labels 的預覽、核准、套用與讀回;不自動寄信、不刪除、不封存、不改已讀、不改系統分類分頁/企業 Classification Labels。Gmail labels 與 Inbox categories、Google Workspace 的 Classification Labels 是不同範圍。 使用使用者 OAuth,不假設 browser cookie 等於 API token。優先實作必要範圍的授權,使用 `gmail.modify` 時在產品層限制具體操作;該 scope 不只是標籤修改,`gmail.labels` 也不能替代套用郵件標籤所需權限 [E1–E2]。不要要求個人 Gmail 使用 Workspace domain-wide delegation。 公開分發/多人部署前檢查 Google 對 restricted scope 與資料處理的要求;開發 fixture 不代表真實 OAuth 發布審核完成 [E2]。 ### 11.2 正確流程 ```text 確認 account 與 capability → search 指定 query/時間範圍,完整處理 pagination → 受限並行取得 headers;必要時才取得 snippet/body → 確定規則先分類,模糊案例送模型分批輸出 label enum → schema validation + 固定測試集校準 + 待確認類別 → 保存不可變 label plan,顯示預覽 → run grant 或使用者明確核准 plan hash → 依相同 add/remove label 組合分組 → connector 在 Computer 內 batchModify → 逐筆 read-back 驗證,記錄 partial/unknown → 回報真實完成數、未處理數、例外與可用撤銷範圍 ``` Google 官方 `messages.batchModify` 單次最多 1,000 個 message IDs,同一批使用同一組 add/remove label;成功回應為空,不帶每封郵件的完整結果,因此仍須另行讀回驗證 [E1]。 範例驗收採 100 封 fixture mail,不代表使用者授權處理整個真實信箱。生產查詢必須有明確範圍、結果上限、排除條件、pagination 與 preview。 ### 11.3 權限、模型與準確度 郵件正文是**不可信任資料**。分類模型只回傳固定 schema 與允許 labels,不可直接 dispatch tools;正文要求轉寄/改系統規則/下載執行程式一律不構成授權。 不要只依 LLM 自報 confidence。建立含繁體中文、英文、帳單、廣告、工作與模糊內容的人工標註測試集;報告 precision、recall、coverage、abstention,避免把所有信放「待確認」就宣稱 100% 準確。 初始 target:自動套用類別 precision ≥ 95%,同時公布 coverage/recall;模型不達標時採 preview-only,而不是偷偷降低正確性門檻。此為驗收目標,不是目前已測結果。 ### 11.4 Retry 與 Undo 的限制 每個 plan 包含 message IDs、account reference、原先 labels、requested delta、rule version、hash、到期與 grant。分批有 child operation ID,保存實際套用/驗證的狀態。 429/暫時錯誤採有界 backoff;回應丟失先 read-back,只執行仍缺少的核准 delta。token 撤銷停在 NEEDS_AUTH,不轉 GUI 硬闖。 撤銷只考慮本次實際新增/移除的 labels,不覆寫整個 label set。若使用者並行修改同一 label 或狀態/history 不清楚,標記 conflict,顯示預覽再核准;**沒有原子 compare-and-swap/明確來源資訊時,不能保證任意並行情況下完全無損的一鍵 undo**。 ### 11.5 外部環境缺失 coding agent 使用本地 fake Gmail HTTP server 完成 pagination、batch、token revoked、rate limit、response lost、partial verification、concurrent change 與 prompt-injection tests。真實帳號測試單獨列為 opt-in integration,不要求密碼/token 貼到聊天,也不自行建立或刪除真實郵件。 --- ## 12. Verifier、進度、有限恢復與預算 ### 12.1 三層完成狀態 1. **Transport**:呼叫是否收到合法回應。 2. **Operation effect**:程序退出、欄位值改變、檔案 hash 符合、label 實際存在。 3. **Task success**:使用者要求的所有必要結果與限制是否達成。 只有第 3 層完成才回 run.completed。部分成果回 partial,明確列已完成/未完成/阻礙,不用最後一句自然語言假裝通過。 ### 12.2 Evidence-based progress - file:輸入/輸出 hash、筆數、schema、測試結果。 - browser:特定欄位、URL/目標記錄、確認頁中的對應值;只有頁面換網址不足以驗證交易成功。 - Gmail/Outlook:已讀回 verified 的 message 數、仍待處理/待確認數;不能混用兩者批次/標籤模型。 - build:實際 job status、exit code、test summary;仍在輸出 log 不等於任務持續前進。 - wait/poll:heartbeat 可表示 worker 活著,但不刷新 milestone progress。 像畫面時鐘、游標閃爍或工具 args 換了,也不算任務進展。對沒有 deterministic verifier 的模糊視覺任務,可使用受限視覺驗證或人類確認,但標示證據較弱,不能當確定完成。 ### 12.3 起始預算(新設定,可調整) ```yaml interactive: max_llm_turns: 20 max_no_progress_seconds: 60 max_semantic_recovery_attempts: 2 max_route_switches_per_step: 2 wall_budget_seconds: 180 batch: bounded_chunk_size: 100 max_semantic_recovery_attempts: 2 progress_source: verified_items long_job: lifecycle_owner: runner completion_source: job_event runtime_deadline: required ``` 這些值是合理起始實驗,不是已測最佳設定。正式 task budget 與保險上限分離。長工作依 task 明確 deadline,不用 180 秒把正常編譯截斷;human_wait 另計。interactive 沒進度時重新路由一次,仍卡住就清楚暫停,不能把上限調回四小時當修復。 watchdog 必須能在慢模型/工具 await 期間運作,不只在下一輪才檢查。等待已知條件採本地事件/bounded polling,不反覆付費請 LLM 決定再等一秒。 --- ## 13. 效能與正確性量測 ### 13.1 必要指標 - `run/step/operation/model/tool_version/backend/computer_generation/mode/assignment/display_session`。 - cold/warm,queue、model TTFT/total、tool execute、observation、recovery、human wait。 - model input/output tokens(provider 沒回則標 unavailable)、schema 大小、LLM turns、tool calls、retry/route switches。 - screenshot count/bytes、artifact bytes、verified items/milestones、success/partial/failure rate。 - native CPU/memory/disk、每 agent/Computer 並行數、MCP server latency、display capture 與 VNC viewer latency。 並行存在時,不可把所有 span duration 相加當 run wall time;同時報 wall time、exclusive spans 與 critical path,避免重複計算 tool 與其內部 observe 的時間。 ### 13.2 Benchmark gates 以下為**待實測驗收 target**,不是完成時間承諾。先固定 reference host、container quotas、CPU architecture、模型版本、網路條件及冷暖狀態,提交 baseline,再進行比較。 | Case | 正確性 gate | 效能/迴圈 gate | |---|---|---| | 1 MiB 本地讀寫/hash | byte-for-byte 正確;private 不跨 Computer,shared 按授權共享而非混用 | warm tool-only P95 target ≤ 500 ms;0 screenshot | | 短命令 `printf`/非零退出 | 真實 stdout/stderr/status | warm tool-only P95 target ≤ 1,000 ms;0 screenshot | | 500 列 CSV 整理 | deterministic expected output/schema/hash 通過 | 不逐列 LLM;同條件已驗證完成 median target ≤ baseline 50% | | 本地五欄表單 | 每欄正確+提交確認 | bounded macro;模型決策回合 target ≤ 3,不含登入 | | Gmail 100 封 fixture | requested label delta 逐筆驗證、不做額外修改 | 0 GUI;label write call 按組合/batch,而非每封一次 | | 兩 agent 同時工作 | 結果分離、沒有 credential 或 artifact 混用 | 慢 A MCP 不阻塞 B client/registry;非全域串行 | | 長命令與 reconnect | 狀態可找回,取消不留未知子程序 | 無需 LLM 忙碌 polling;模型次數不隨等待秒數增長 | 每一候選設定先固定種子/fixture 重跑至少 30 次;正式以 P95 當門檻前建議至少 100 次並附樣本數。少量樣本只作探索;有延遲或 rate limit 不隱藏。舊路徑若無法完成並驗證該任務,其相對提速列為 N/A,改報新路徑絕對耗時與成功率,不捏造 baseline 倍數。 只比較成功且驗證過的同一工作,**同時列所有任務成功率與失敗耗時**,避免只挑成功樣本或「更快失敗」造成假提速。未達 target 就提交 profiling、差距與修正項,不改 fixture 偷渡。 --- ## 14. 持久化、設定與雙模式相容升級 ### 14.1 資料模型 沿用既有表、ID 與 enum,migration 採 repository 下一號。不重命名既有 shared/team mode 就讓舊資料無法載入。 - Computers:mode/owner_team/generation/provider_ref/backend/readiness。 - Assignments/memberships:每 bot 一個 active assignment;shared computer 可多 bot,dedicated 有條件排他約束。保存 workspace scope、display slot、profile id。 - Grants:bot/team membership/Computer/account/operation/expiry;同 Computer 不等於同 grant。 - Package installations:Computer/package/version/digest/source/trust/status。Binding:安裝包 → agent(s)/server instance/account/capabilities;套件與認證分表。 - Jobs/operations/events:保留第 4 節與原有 schema,加入 assignment、display/resource scope 和版本 provenance。 - Artifacts:creator bot、visibility、relative path、hash、source op;重建後核對,不讓永續檔案被 generation 永久孤立。 - Display sessions:每 slot 的 display/backend/epoch、profile 和 lifecycle。MCP、package 與 desktop 各可單獨健康檢查和恢復。 ### 14.2 設定 以下是新增設定的建議命名;必須實作 parser/validation/`.env.example`,不是當成目前已可用的環境變數: ```text LAZYBOY_EXECUTION_PROFILE=legacy|hybrid LAZYBOY_DISPLAY_BACKEND=xvfb_x11vnc|tigervnc_xvnc LAZYBOY_BROWSER_BACKEND=cua|playwright LAZYBOY_TOOL_AUDIT_REQUIRED=true LAZYBOY_NATIVE_JOB_CONCURRENCY=2 LAZYBOY_SERVICE_READ_CONCURRENCY=4 LAZYBOY_TOOL_INSTALL_ENABLED=true LAZYBOY_TOOL_INSTALL_REQUIRE_APPROVAL=true ``` Computer mode 保留既有 UI/API 選擇與預設值;不加強制 dedicated 的 rollout。legacy/hybrid 是 executor 路徑版本,**不是 shared/private 的替代名稱**。 雙模式皆先 opt-in 測試,再 canary。不能用 feature flag 恢復截圖錯誤、secret 洩露或 host task fallback。 ### 14.3 原地升級與可選模式切換 預設原地升級 shared 與 dedicated,保留 bot assignment、shared/、private workspace、登入、skills、排程和群聊。既有 Team 不標為待淘汰、migration_required,也不自動拆成多台私人電腦。 只對需要調整的 metadata/工作檔路徑做有測試的相容 migration,保留回滾資料。使用者明確要求換模式時才執行:dry-run → manifest → 停止相關 writers → 在來源 Computer 匯出/目標 Computer 匯入 → hash/permissions check → 原子切換 assignment → 恢復。共享 profile/credential 歸屬不明時列衝突,不複製給所有人。 共用 package 更新或整台 image recreate 必須先列出所有受影響 members/jobs;不要為單 agent 升級重啟別人的工作。移除一個 agent 不刪共享資料或共享安裝包;最後一個 reference 消失後仍需 retention/管理政策決定 GC。 --- ## 15. 實作順序:可分段提交的 PR 不做「一次替換全部底層」的大型 PR。核心正確性先落地;TigerVNC 和第二 browser adapter 都有獨立開關,不把它們的相容性問題混入原生工具改動。 | PR | 實作與主要落點 | 依賴 | Gate/產出 | |---|---|---|---| | PR-00 | 核對 HEAD/git status/AGENTS.md/工具鏈;建立 shared/private baseline、紅燈 fixtures | 無 | 記錄原有失敗、可重現截圖/工具契約問題;不覆蓋未提交修改 | | PR-01 | 修 `tools.rs` 截圖與 semantic/vision guard、browser contracts、typed result | 00 | 新圖交付、text-only DOM、unsupported/stale/disabled 正確區分 | | PR-02 | 保留兩模式;assignment/membership/Runner identity/per-display context/protected broker boundary | 01 | shared A/B 仍同 Computer、private C 獨立;不能偽造 scope;沒強制模式轉換 | | PR-03 | operation ledger/Computer outbox/Activity UI/事件與秘密脫敏 | 02 | 斷線補送/去重、rejected/partial/unknown 可見;失去 audit 不開始 mutation | | PR-04 | 原生 exec/files/jobs/range & binary/artifact streaming/scope-aware cancel | 03 | 兩模式都能 text-only CSV 工作、0 screenshot、真 exit code、取消子程序;第一個核心可交付階段 | | PR-05 | 可安裝 Tool Manager、Computer 內 MCP/連接器、版本 pin/grants/OAuth broker/hot reload | 04 | 本機 sample MCP 實際安裝可用;共用套件不共享帳號;更新回滾不重啟整台 Computer | | PR-06 | per-step capability router、少量 schemas、milestone verifier/watchdog/有界恢復 | 05 | wait 不算進度、無 planner 套娃、policy denied 不繞路、未知副作用先讀回 | | PR-07 | Browser session/profile/display leases、form macro、人類接管与恢復 | 06 | 同 display 排他、不同 display 可並行;接管 A 不凍結無衝突 B;resume 不重做 | | PR-08A | Gmail labels adapter 作業務基準;沿用第 11 節 | 07 | fixture 預覽/核准/apply/read-back/衝突測試;不操作主信箱 | | PR-08B | **Outlook 外掛作擴充性驗收**;走第 20 節安裝契約與 Graph adapter | 05;業務 E2E 需 07 | 不改核心 dispatch 也能載入外掛;read/categories/分頁/batch/401/429/共用模式授權測試 | | PR-09 | DisplayBackend 介面+TigerVNC Xvnc 候選+舊 backend rollback;第 19 節 | 02/03 可先開始;整合 gate 需 07 | Cua/AT-SPI/X11/中文/多 display/noVNC 相容;benchmark 不退步才考慮 default | | PR-10 | 雙模式原地升級、完整測試/效能與部署文件/rollout | 08A/08B/09 | 第 1 節契約與第 16 節測試有證據;Outlook 真實帳號或 GUI 缺環境須明確 blocked | | PR-11(可選) | Playwright worker 對照;Selkies/Xpra/Wayland 分別另開 ADR | 核心不需等待 | 一次只換一層、無證據不採用;不能為完成清單全部安裝 | 每個 PR 可以拆小,但不可依賴尚不存在的安全邊界就先打開高權限工具。PR-04 的必要 job cancel/audit 不拖到 PR-07。PR-05 即使外部 OAuth 不可用,也必須能安裝並執行本機測試 MCP,證明「外部工具能加入」不是只有 UI。 ### 15.1 Coding agent 執行方式 先建立進度檔,以 `NOT_STARTED / IMPLEMENTED / PARTIAL / BLOCKED_EXTERNAL / VERIFIED / DEFERRED` 表示真實狀態。先完成 PR-00/01 的程式與測試,再依 DAG 推進;不是再交一份更長的計劃。 逐項更新第 18 節的 O01–O48:採用/保留現況/實驗/延期/阻礙、實際 diff、測試命令與結果。標「已實作」不等於「已驗收」。有互斥候選時,只實作滿足目標的最小方案;不能同時把所有替代框架塞進主線。 --- ## 16. 最小測試矩陣與 Definition of Done | Test ID | 場景 | 必須證明 | |---|---|---| | T01 | vision × Changed/Similar/Identical | image 交付真值表正確 | | T02 | 首次畫面/換模型/壓縮歷史/takeover resume | 未變但模型沒看過的圖仍交付 | | T03 | 純文字模型 DOM/native tool | 可用語意工具、不收到圖、不猜座標 | | T04 | selector unsupported/stale/disabled | 正確錯誤、有限恢復、無盲點 | | T05 | private A/B 同路徑與 shared A/B 相同相對路徑 | 私人互隔離;共用 own workspace 不誤取,shared/ 依授權真共享 | | T06 | 偽造 bot/computer/grant/generation | API 及 Runner 都拒絕 | | T07 | host sentinel/Docker socket/管理 API | task 不可讀取或操作 | | T08 | `..`/symlink race/奇異 Unicode 檔名 | 不逃逸/不 command injection | | T09 | binary 含無效 UTF-8 與 1 MiB 檔案 | byte-for-byte 正確 | | T10 | 權限不足/磁碟滿/HTTP 403/解析失敗 | 不回空成功 | | T11 | 同檔並寫、expected hash 不符 | conflict 而非覆蓋 | | T12 | stdout/stderr/非零退出/signal | 真實程序狀態 | | T13 | timeout/子程序/cancel 競爭 | 停止程序樹,誠實回 pending/unknown | | T14 | API restart/Runner reconnect | 原 job 不重做、output cursor 可續 | | T15 | container recreation | generation 失效,舊 job 不假裝存活 | | T16 | 同 operation 重送/相同 ID 不同 args | 去重;不同 payload 被拒絕 | | T17 | central DB/網路中斷 | durable outbox 最終補送,不重做副作用 | | T18 | journal 不可寫/quota 用盡 | 不開始新的 untracked mutation | | T19 | 同名 MCP/慢 server | namespacing 正確,沒有全域 await lock | | T20 | token revoked/wrong account/grant expiry | 停止並回 NEEDS_AUTH/denied | | T21 | secret canary 在成功及 exception 路徑 | prompt/log/checkpoint/UI 無 secret | | T22 | website/email/MCP prompt injection | 不把外部內容當授權與工具指令 | | T23 | 同一 page 的 Cua+browser worker | mutation 排他,refs 不混用 | | T24 | takeover 時 background job+HTTP in flight | barrier 真實,顯示未確定效果 | | T25 | screenshot clock/重複 wait | 不刷新 milestone、不無限 loop | | T26 | fake Gmail pagination/batch limits | 沒漏信、label 組合分批正確 | | T27 | Gmail response lost/429/partial verify | bounded retry、read-back、如實 partial | | T28 | Gmail concurrent same-label change/undo | conflict-aware,不宣稱無損無條件撤銷 | | T29 | 兩模式原地升級;使用者要求模式切換的 dry-run | shared 不被強制拆開,原資料/profile/排程保留 | | T30 | noVNC 關閉/desktop 未啟動 | native 工作仍完成且有紀錄 | | T31 | 兩 agent/多 run 壓力 | 可量測並行、資源受控、結果不交叉 | | T32 | 分類測試集含模糊郵件 | precision/recall/coverage/abstention 全部報告 | | T33 | arbitrary exec 讀 broker env/socket/journal | 保護區不可見,不靠 prompt 擋 | | T34 | UI download/附件串流 | 不使用 API host 暫存任務檔案 | | T35 | 取消後 resume | 已驗證操作不重播;grant/ref 重新檢查 | | T36 | 所有 aliases/native/MCP/browser 入口 | 都經統一 policy、operation、audit | | T37 | 建立/恢復 shared 與 private agent | 兩模式維持原選擇;shared 允許多 assignment,不誤套 UNIQUE | | T38 | shared A/B own workspace 相同檔名 | 透過受控 fs/exec context 正確命中,不因 cwd singleton 混用 | | T39 | shared/ 同一檔案協作與未授權會員 | 成員獲准則可見;同檔 CAS/conflict,未授權工具請求被拒 | | T40 | Team 不同 DISPLAY 的兩個 browser writer | 可並行;profile、DBus、AT-SPI、Cua socket 與截圖不串台 | | T41 | 同一 DISPLAY/profile 的 browser/Cua/人類 | 排他 writer 與 server-side control epoch,有界排隊 | | T42 | 暫停/接管 shared agent A | 無衝突 B 的 native/job/display 不被凍結;A 不再派送 | | T43 | 整台 Team pause/recreate | 所有 members/jobs 被追蹤;無假暫停/孤兒 writer | | T44 | 兩 agent 同時首次 provision/ensure screen | single-flight、slot 配置唯一、只有一個合法 instance | | T45 | 刪除 Team 的一位成員 | 其他人的 Computer/shared files/package/jobs 不被刪 | | T46 | 本機測試 MCP 匯入+實際安裝+執行 | 安裝程序和 bytes 在 Computer;有版本/hash/audit | | T47 | 共用安裝包+不同 agent 帳號 grant | 只重用唯讀程式;未授權 agent 無 broker token/tool capability | | T48 | 錯誤 digest/路徑逃逸/擴權 manifest | 啟用前拒絕,existing tool 不受影響,套件 hooks 無無界權限 | | T49 | 安裝新版本時有 active jobs | active pin 舊版、新 run 用驗證新版;可 rollback、不全機 restart | | T50 | 移除/撤銷一個 connector binding | 只停止相應授權;共用套件/其他 agent bindings 仍運作 | | T51 | Outlook fake messages/categories adapter | 安裝後能 read/preview/apply/verify;未授權 send/delete 不可用 | | T52 | Graph $batch HTTP 200 但子項 429/401/5xx | 逐子項結果/Retry-After/未知 read-back;不全批重做 | | T53 | Outlook nextLink/deltaLink/token revoke | 完整分頁;delta 依 folder 綁定,失效需安全重同步/授權 | | T54 | Outlook categories 並行修改/未支援 If-Match | 不假稱 CAS;偵測可見衝突、回報限制,不盲覆蓋 | | T55 | TigerVNC Xvnc × Cua × XFCE fixture | 截圖/XTEST/AT-SPI/中文/鍵鼠/clipboard/視窗辨識通過 | | T56 | X server restart/backend 切換 | 舊 refs、display epoch 失效;既有 GUI sessions 不宣稱無縫存活 | | T57 | slot 0/1 的 DISPLAY 與 VNC port | 明確保留 :1→5900/:2→5901 對應,不依 Xvnc 預設推算 | | T58 | noVNC CSS scaling/resize/高 DPI | 座標 transform/實際尺寸正確、文字可讀,不拿 viewer 有損畫面做驗證 | | T59 | 未授權 VNC keyboard/resize/clipboard | 伺服器拒絕;不只靠客戶端 viewOnly;Xauthority 配置驗證 | | T60 | 無人觀看、VNC proxy 未啟動 | native 與必要 browser 工作仍可做;不被 viewer readiness 阻塞 | | T61 | 第三方 MCP 僅能接受 env token | 明確 trust review/保護 process env;不能保護就拒絕敏感注入 | | T62 | shared 同 UID 無界 shell 的 threat model | 不把目錄 scope/tool annotations 宣稱強隔離;core secrets 不可讀 | | T63 | 慢 agent/資源不足/renderer crash | 公平隊列/總配額;不因 A 閒置或 OOM 自動破壞 B 狀態 | | T64 | Computer recreation 後套件與 artifact | manifest 可重建;persistent artifact 校驗後可取;不重用舊 jobs | 測試層次:unit → fake Runner/fake model/fake SaaS → disposable real Computer integration → explicit opt-in external account/model E2E。fixture 真實 GUI 測試無 display 時標 blocked,不改成假 assertions。 第一輪先從 repository 查實際工具鏈與 scripts。可用時執行: ```bash cargo fmt --all -- --check cargo clippy --workspace --all-targets -- -D warnings cargo test --workspace ``` 前端依 `apps/web/package.json` 已存在 scripts 跑 typecheck/build/tests;不要宣稱不存在的 npm/Make target 已通過。需要的 `test-agent-computer`、`bench-agent-computer` 等新入口必須在此實作中真的加入。 ### 16.1 全案完成的最低定義 - shared Computer 上 A/B 協作、private Computer 上 C 獨立,兩模式關閉桌面仍可做工具工作。 - 檔案、exec、MCP、connector 在正確 Computer;不存在 host task fallback。 - API/工具/UI 的成功、失敗、partial、unknown、cancel、needs_auth 語意一致。 - Activity 看得到操作摘要、結果、耗時、電腦、job/artifact 與驗證。 - 原生檔案/命令能由 text-only 模型完成且不產生截圖。 - Cua 仍可處理必要桌面操作;語意和視覺工具的 boundary 正確。 - Gmail 與 Outlook fixture 預覽→核准→套用→驗證完成;Outlook 走可安裝外掛契約;外部帳號測試誠實標示。 - 核准、secret、timeout、並行、接管、重啟與撤銷都有測試,不以功能展示代替。 - TigerVNC 以候選 backend 通過兩模式相容性/readiness/noVNC 測試;是否切為預設依結果,不宣稱保證提速。 - 外部 MCP 安裝、授權、更新、撤銷、移除可在 UI/API 操作,active job 不被靜默換版本。 - O01–O48 逐項有 disposition/理由/證據;P2/P3 可有合理延期,不要求全部換掉。 - 實際 benchmark 附環境與成功率;沒有未測的速度倍數或「全網站皆可操作」宣稱。 --- ## 17. Coding agent 的交付格式與停止點 每個 PR 更新 `docs/agent-computer-progress.md`: ```markdown ## PR-XX:名稱 狀態:IMPLEMENTED / PARTIAL / BLOCKED_EXTERNAL 基準 commit:... 修改檔案與設計差異:... 新增/修改測試:... 實際執行命令與結果:... 未執行測試及原因:... 效能結果與樣本數:... 安全/相容性/雙模式/migration 影響:... 對應 Oxx/Txx 與 disposition:... 回滾方式:... 下一個可執行步驟:... ``` 不要把「已寫測試」與「已執行且通過」混為一談。不要透過刪測試、跳過 auth、放大 retry budget、強制 vision 或把未知效果標成功來完成 gate。 沒有外部憑證時完成內部必要範圍,精確列出 integration blocker;不向聊天索取密碼。沒有使用者授權,不對真實信箱做寫入、不刪除 legacy 資料、不正式部署或 force push。 需要決策但沒有資料時,選擇符合本文件不變條件的最小改動;只有不可逆資料遷移/真實帳號核准等真正需要使用者的步驟才暫停。不要因架構工作較大就只交另一份計劃。 --- ## 18. 逐項改善清單:48 項,不等於 48 項全部替換 P0:正確性/產品邊界;P1:核心交付;P2:量測後採用;P3:可選/延後。以下是本案的待辦與候選,沒有實測提速倍數。每項在進度檔有 disposition、證據和回滾;已存在的優化要標「保留」,不要再次算成新成果。 ### A. 原生執行與工作流程 | ID | 項目 | 優先級 | 具體改動 | 要改善的問題 | 驗收/限制 | |---|---|---|---|---|---| | O01 | 修正新圖交付 | P0/必做 | 修反轉條件,分 captured/delivered,接管/換模型強制交付 | 無圖硬做造成的錯誤與重試 | 真值表+模型 request fixture;[R1] | | O02 | 原生 exec | P1/必做 | 命令在綁定 Computer 執行,直接取 stdout/stderr/exit | 消除終端機打字與讀圖 | 兩模式 text-only 命令 0 screenshot | | O03 | 原生 files | P1/必做 | 重用並強化 SandboxProvider,不透過 sed 畫面讀檔 | 減少回合/避免 binary 毀損 | range、Unicode、binary、shared 路徑;[R2–R4] | | O04 | 持續 jobs 與 PTY | P1/必做 | 短命令直接返回,長作業由 Runner 管理、事件通知/真取消 | 不請 LLM 反覆看是否做完 | API 重啟可追 job;process-tree cancel | | O05 | 批次程序/form macro | P1/必做 | 已知步驟在受控 executor 內完成,有 pre/post checks | 不逐列/逐 click 呼叫模型 | 每個子動作有 trace;失敗即停 | | O06 | 套件/連線常駐 | P1/必做 | 暖 MCP instance、HTTP pooling、版本化 cache | 降低啟動與重複連線成本 | warm/cold 分測;不共享私人 env | | O07 | 穩定 Runner transport | P2/量測 | 優先現有安全 transport;高 overhead 才改持續 UDS/HTTP 通道 | 減少每次 docker exec 的啟動成本 | 實測 RPC 分解;不能公開 root socket | | O08 | readiness 分層 | P1/必做 | Runner、browser、desktop、viewer 各自 ready,按需啟動 | 讀 CSV 不先等整個桌面 | no viewer/no desktop 的 native fixture | ### B. 模型與瀏覽器 | ID | 項目 | 優先級 | 具體改動 | 要改善的問題 | 驗收/限制 | |---|---|---|---|---|---| | O09 | 按能力路由 | P1/必做 | 原生/已授權 API 優先,DOM 次之,必要時視覺 | 避免 Gmail/Outlook 走慢 UI | route rationale+權限拒絕不繞過 | | O10 | 工具 schema 按需載入 | P1/必做 | 僅帶此 run 可用能力,版本/grant cache | 縮短 context、避免選錯工具 | revoke 後立即失效;記 schema tokens | | O11 | 簡單任務不加 planner | P1/必做 | 用既有一輪決策,複雜任務才 TaskPlan | 避免多 agent/planner 套娃 | 記模型回合、TTFT、正確完成 | | O12 | 條件等待 | P1/必做 | wait_until/job events 有 deadline,替代固定 sleep | 消除空等與毫無進度輪詢 | 未知 disabled 原因不無限等 | | O13 | DOM snapshot 限量與增量 | P2/量測 | 聚焦相關區域,revision 與失效 refs 完整處理 | 減少重傳巨大 page text | 錯 revision 回 full;不能漏關鍵元素 | | O14 | agent 圖片和 viewer 串流分離 | P1/必做 | 高可讀截圖按需取,不把 VNC frame 全塞模型 | 減少模型圖片成本且維持辨識 | 縮放映射/force image/小字 fixture | | O15 | 既有 browser/session 穩定 attach | P1/必做 | profile/tab/frame 明確綁定,禁止亂開替代瀏覽器 | 減少重登入與 stale reference | 同 profile 不雙開;重啟正確失效 | | O16 | 驗證、有限恢復與模型升級 | P1/必做 | 進度看 milestone;兩次同義錯誤換策略,難題才升級模型 | 停止二十分鐘空轉 | 未知副作用先讀回;無固定提速保證 | ### C. 顯示與遠端桌面 | ID | 項目 | 優先級 | 具體改動 | 要改善的問題 | 驗收/限制 | |---|---|---|---|---|---| | O17 | Xvfb+x11vnc → TigerVNC Xvnc | P2/必做候選測試 | 一個 backend 同時提供 X server 與 VNC,保留 rollback | 可能減少顯示匯出層與維護負擔 | Cua/a11y/中文字/多 display/CPU/latency;[E5] | | O18 | Xvfb+x0vncserver 備選 | P3/保留替代 | 只換 VNC 匯出層,不替換 X server | Xvnc 相容性卡住時較小改動 | 不能說已移除 Xvfb;[E6] | | O19 | 檢查 -noxdamage | P2/對照 | 現有 x11vnc 關閉 XDamage;測啟用是否有重繪瑕疵 | 判斷掃描負擔能否降低 | 靜態/捲動/遮擋/影片測試;不可直接刪旗標;[R9] | | O20 | noVNC/websockify 與畫質檔 | P2/調校 | 先保留;viewer FPS/壓縮可調,無 viewer 減少服務負載 | 改善觀看/頻寬,不假稱模型更快 | 文字清晰、輸入延遲、resize、proxy auth;[E7] | | O21 | 精簡桌面而非先換 OS | P2/調校 | 保留 XFCE/a11y;已 compositor=off,評估不必要 autostart | 降低多 slot CPU/RAM | 不重做既有優化;不破壞 DBus/a11y;[R9] | | O22 | Selkies 替代 viewer | P3/可選 | 有高幀率/音訊需求才測;目前有 WebSocket 與選用 WebRTC | 影音觀看可能較適合 | 硬體 encoder 實測、網路與前端成本;[E8] | | O23 | Xpra 替代 viewer | P3/可選 | 需要單視窗發布/session forwarding 時測 | 另一路 remote app 體驗 | 非 noVNC drop-in;額外 client/輸入整合;[E9] | | O24 | Wayland/全面換桌面 | P3/延後 | 保留 X11 driver 路徑,未有需求不全面搬遷 | 避免同時引入 capture/input 相容性變動 | 獨立 ADR/fixtures;不是目前速度主解法 | ### D. 共用/私人與資源協調 | ID | 項目 | 優先級 | 具體改動 | 要改善的問題 | 驗收/限制 | |---|---|---|---|---|---| | O25 | 雙模式正式保留 | P0/必做 | shared 多 bot→同 Computer;private 排他;不強制遷移 | 符合產品且避免破壞資料 | assignment/member/slot/重建測試 | | O26 | 按 display/檔案/account 鎖 | P1/必做 | 同資源排他、不同 display 與受控 job 並行 | 避免共用主機整機串行 | Cua/DOM/human 同鎖;canonical shared key | | O27 | scope-aware pause | P1/必做 | 接管 A、接管 display、暫停整機分開 | B 不被 A 的無關操作凍結 | 真 barrier/fencing;HTTP unknown 誠實顯示 | | O28 | 共享 lifecycle/single-flight | P1/必做 | 啟動、刪除、idle reaper 看全部 member/jobs | 避免重複建立與誤停他人工作 | member refcount、job/viewer 活性聚合 | | O29 | 程式共享與帳號授權分離 | P0/必做 | 共享唯讀 package,per-agent runtime/bindings/grants | 省重複安裝、不共享私人帳號 | 未知程式不能靠 annotations 保證安全 | | O30 | 公平排程與總配額 | P1/必做 | 每 agent/Computer 的 CPU/RAM/jobs/requests 有界 | 抑制單 agent 拖慢所有人 | 壓力/OOM/慢 MCP;不無界並行 | | O31 | Chromium /dev/shm 與程序回收 | P2/量測 | 調 per-Computer shm、init/reaper、renderer 健康 | 減少可避免的崩潰與孤兒程序 | 不能盲開 ipc=host/SYS_ADMIN/no-sandbox;[E10] | | O32 | X11/DBus/profile 權限與 session | P1/必做 | per-slot identity,評估 Xauthority,系統安裝有管理鎖 | 避免串台與共用 session 風險 | 同 UID 非強隔離;Xvnc :1 port 對應測試 | ### E. 可安裝外部工具/Outlook | ID | 項目 | 優先級 | 具體改動 | 要改善的問題 | 驗收/限制 | |---|---|---|---|---|---| | O33 | Tool Manager 安裝入口 | P1/必做 | catalog、manifest/受控 package URL、本地上傳三種入口 | 新增工具不改核心 dispatch | 實際 sample MCP 安裝,不只是設定畫面 | | O34 | 來源版本與完整性 | P1/必做 | pin digest/version,審核 hooks,安全解壓與 quota | 更新可重現、防無界安裝 | 拒絕未審核 URL、路徑逃逸、錯 digest | | O35 | 安裝/啟動/認證/授權分開 | P1/必做 | 每階段顯示狀態、failure reason 和 scope | 不再「裝好了卻不能用」 | installed ≠ connected ≠ authenticated ≠ authorized | | O36 | 熱啟用與 registry 更新 | P1/必做 | health/schema 驗證,原子登錄能力;grant 撤銷失效 | 不為加工具重啟整個 LazyBoy | 正在執行 run 的能力版本與安全點更新 | | O37 | 版本更新/回滾/移除 | P1/必做 | 新版本旁置,active job pin 舊版,bindings/reference GC | 共用主機其他 agent 不受破壞 | 新增權限重新核准;共享套件引用仍存活 | | O38 | OAuth/token broker | P1/必做 | Microsoft/Google 正規授權,scoped token、refresh single-flight | 減少重登入與憑證混用 | MFA/admin policy 正常接管;secret canary;[E11] | | O39 | Outlook Graph 外掛 | P1/必做驗收 | 讀信→categories preview/apply/verify;寄信另授權 | 驗證架構不只 Gmail 特判 | 個人/工作帳號對應 scopes;[E12–E14] | | O40 | Outlook 批次/增量同步 | P1/P2 | Graph 20 子請求/逐項狀態;需要時 folder delta | 減少網路回合及每次全信箱掃描 | 429/Retry-After/分頁/ImmutableId;[E15–E18] | ### F. 正確性、紀錄與可維護性 | ID | 項目 | 優先級 | 具體改動 | 要改善的問題 | 驗收/限制 | |---|---|---|---|---|---| | O41 | operation journal/outbox | P0/P1 | 副作用前記 intent;斷線 durable 補送與去重 | 避免掉紀錄與重做工作 | journal 故障不開始 mutation | | O42 | 活動紀錄串流而非桌面演出 | P1/必做 | 工具與 job 的結構化事件、實際耗時/結果 | 人可追查、不逼每步打字 | noVNC 關閉仍可看進度 | | O43 | artifact 存 Computer+脫敏 | P1/必做 | 全文输出在 Computer,API 存摘要/reference,限量保留 | 避免 DB/context 被圖片/日誌塞滿 | secret/大檔/retention/串流授權測試 | | O44 | Task 驗證與郵件分類品質 | P1/必做 | API 200 不等於任務完成;測 precision/coverage/abstention | 速度與正確性一起看 | read-back/真實 fixture、失敗也計入 | | O45 | 衝突與冪等/未知效果 | P1/必做 | 同 operation 不重做;same-file CAS;未知 API 先回讀 | 降低重送/覆蓋/重複外部副作用 | 不假稱通用 exactly-once/無損 undo | | O46 | 部件健康與版本相容矩陣 | P1/P2 | Runner/display/Cua/browser/plugin 個別 probe/recover | 失敗不用重啟整台 Computer | 不影響其他成員;pin 上游版本 | | O47 | 已驗證 skill/流程重用 | P2/後續 | 將常用流程保存語意步驟與 checks,環境變更可失效 | 降低每次從零探索 | 不保存密碼/舊座標;profile/版本變更重驗 | | O48 | 端到端+viewer 雙 benchmark | P1/必做 | 分模型、工具、snapshot、queue、viewer,固定環境兩模式 | 找真瓶頸,不憑工具名字換底層 | 成功率/median/P95/CPU/RAM/可讀性;一項一改 | --- ## 19. TigerVNC 與桌面後端:實作規格 ### 19.1 明確的兩條路 **候選 A:Xvnc 取代 Xvfb+x11vnc。** TigerVNC 的 Xvnc 同時提供 X server 與 VNC server [E5]。此案希望減少虛擬顯示再由另一程序匯出的層次;收益是待測假設,不保證 agent 推理更快。 **候選 B:保留 Xvfb,只用 x0vncserver 取代 x11vnc。** x0vncserver 是匯出既有 X display,不建立新的 display [E6]。它不是「Xvfb 一起換掉」。只有候選 A 遇相容性阻礙時再測 B,避免一次三套都當主線。 noVNC 是 viewer;websockify 是 WebSocket 到 VNC 的橋接。換 Xvnc 不代表可以直接刪掉這兩層;第一版保留既有 authenticated screen proxy 與 noVNC UI [E7]。 ### 19.2 原始碼落點 - `image/computer/Dockerfile`:加入發行版可用且 pin 的 TigerVNC 套件,保留 baseline fallback。安裝後記錄實際 binary 名稱/版本(不同套件可能叫 Xvnc 或 Xtigervnc),不是假設名字一定相同。 - `image/computer/lazyboy-screen`:將 start_xvfb/start_vnc 抽成 DisplayBackend,沿用 ensure_slot 和 per-slot identity/locking。保留顏色、中文、DBus/AT-SPI、Cua socket、profile、日誌。 - `image/computer/start.sh`/`crates/controld`:分 runner/display/viewer readiness;按需啟動而非工具讀檔前全部 boot。 - `crates/control/src/screen.rs`/supervisor:保留 slot→display/view port 契約,增加 backend/session epoch 與 capabilities。实际檔案/函式存在與否先核對,不盲插模板。 - `screen_proxy.rs`/noVNC UI:保留 server-side auth/membership/control lease、斷線恢復與鍵鼠權限;不要只有 viewOnly 前端旗標。 ### 19.3 最容易踩錯的地方 1. 基準 slot 0 是 DISPLAY `:1`、RFB `5900`、web `6080`;slot 1 是 `:2`、`5901`、`6081`。Xvnc 常用預設是 5900+display-number,**不得拿預設值默默改掉既有對應**;明確設定 rfbport,寫契約測試 [R9][E5]。 2. 每 slot 的 X11、Cua、DBus、AT-SPI、XDG_RUNTIME_DIR 與 browser profile 一起綁定,不用全域可變 DISPLAY。不能以「共用主機」為由退回所有 agent 同一滑鼠。 3. Cua 的 X11 截圖/輸入、XTEST、RANDR、clipboard、視窗 enumerations 需要在選定套件實際 probe;AT-SPI 是桌面/應用和 bus 的能力,不是 Xvnc 自動提供。 4. 先固定現有 1280×800/24-bit 並保持一致 DPI/scale,避免把 backend 差異和解析度差異混在 benchmark。viewer 可 CSS fit,但座標需轉成實際 display pixels;resize 成功後 invalidate refs。 5. human viewer 的有損壓縮/FPS 調整不能降低 agent 驗證圖的可讀性。模型 observation 仍由明確的高可讀 capture 路徑取得。 6. X11/RFB 僅在受控邊界可達;不裸露公網的 5900/6080/CDP。評估移除 `-ac` 需要同步實作 Xauthority/client credentials,不能只删旗標導致 Cua 壞掉。 7. 現有 `-noxdamage` 可能是舊相容性 workaround,只有在重繪 fixture 過關後才能改。`xfwm4 --compositor=off` 已經存在,不能重複列提速成果 [R9]。 8. Xvnc 是 X server,殺掉它就會中斷使用它的 X clients;無 viewer 時可以停/降頻 viewer bridge,但不能因此殺死仍在工作的 display。stop/recreate/backend 切換需受控停止點,**不是無縫熱切 X server**。 9. 清理 stale pidfile/X lock/Chromium SingletonLock 前先確認對應程序與 profile ownership;不以 pgrep 字串近似或一律 rm lock 把活躍 session 搞壞。 10. 大版本更換仍可能影響 Unicode clipboard、快捷鍵、drag、輸入焦點;測手機/桌面 reconnect、human takeover、雙 viewer read-only 與 writer。 ### 19.4 對照測試與採用門檻 固定模型、任務、容器資源、Cua/Chromium/noVNC 版本、screen size 與 LAN/WAN 條件。至少含空桌面、靜態網頁、捲動、輸入表單、對話框、影片、兩個 Team displays 同時操作。 分開量測: - **Agent path**:model time、工具時間、Cua snapshot latency、action→verified effect、完成率、重試數。 - **Viewer path**:input-to-present latency、frame update interval、重繪完整性、小字可讀性、reconnect、網路 bytes。 - **資源**:每 display/整台 Computer CPU、RSS、程序數;有 viewer 與無 viewer 各測。 硬 gate 是既有 GUI/輸入/a11y 正確性不退步,不能用更模糊畫面換好看的 FPS。採用預設前提出量測理由;只有 viewer 變順時,報告 viewer 改善,不宣稱整個 agent 任務提速。無 GUI 環境則標 BLOCKED_EXTERNAL 並保留 baseline default。 ### 19.5 不建議同時改的東西 Selkies、Xpra、Wayland、換整個 Linux 發行版是不同級別的變更。Selkies 目前官方文件列 WebSocket 為預設、WebRTC 為選用,不能只照舊 README 說一定需要 WebRTC/TURN;硬體編碼可用與否也要 probe [E8]。Xpra 有自己的 HTML5/session forwarding 架構,不是改一個 VNC executable 就完成 [E9]。沒有影音/單應用發布需求時,先保留 noVNC。 --- ## 20. 可安裝外部工具:Tool Manager 與擴充契約 ### 20.1 三種形式與真正的執行位置 | 形式 | 實作方式 | 限制 | |---|---|---| | stdio MCP | Computer 內啟動經審查的 Node/Python/Rust executable,generic MCP adapter 載入 schemas | MCP package 可執行程式;固定版本與 runtime grants;API 不 spawn | | CLI/自製本機工具 | 套件裝在 Computer,manifest 把 argv/stdin/stdout/schema 接到受控 executor | 不能直接把任意 shell 字串當受信任 metadata;binary 必須在 scope 中 | | HTTP MCP/SaaS connector | client 在 Computer;呼叫批准的外部服務,artifact/download 落在 Computer | remote MCP server 仍在遠端;不能外包本機任務檔案處理/code execution | 普通 REST SDK 不會自動變成 agent tool;需要一層 adapter/MCP server/manifest wrapper。完成通用載入後,新 MCP 不應每次修改 Rust 核心 dispatch;新 provider 的特殊 API 語意仍可能需要寫 adapter。 先支援手動來源與小型內建 catalog,不以「先蓋完整 marketplace」阻擋交付。來源可為受控 manifest URL、上傳套件、已知 catalog;下載與解包在指定 Computer。公開 registry 只協助 discovery,不等於套件已審核安全。 ### 20.2 必須分開的四個層次 ```text Package:程式、來源、版本、hash、相依 Installation:安裝在哪個 Computer、狀態、可重建資料 Binding:哪個 agent 可以看見/呼叫哪些 capabilities Connection:哪個真實帳號、OAuth/secret grant、允許操作 ``` shared Computer 可以一份唯讀 package 供 A/B 用;A 的 Outlook grant 不會因此授給 B。相同套件可有兩個私人 server instances/設定。shared/ 是否可讀寫另外核准,不因已安裝就自動全開。 ### 20.3 安裝與啟用流程 1. **選來源與目標**:顯示 shared/private Computer、受影響 agent、package publisher、版本、雜湊、平台/CPU 架構需求。 2. **驗 manifest**:schema version、entrypoint、dependency lock、network/service domains、filesystem scope、工具名衝突、requested permissions。 3. **核准安裝**:套件程式執行與資料存取風險分開。不能由模型、網頁、郵件或外掛自己的提示自動授權。 4. **Computer 內 staging install**:versioned 目錄、受限網路/CPU/磁碟、safe archive extraction,防 traversal/symlink/hardlink 逃逸和解壓炸彈;package install hooks 同樣受控。 5. **健康/契約測試**:啟動、tools/list、schema validation、read-only mock call、version/compatibility。不能在 healthcheck 時默默寄信或修改真實帳號。 6. **登錄 registry**:安裝及 schema 成功後原子啟用 binding。顯示 INSTALLED/CONNECTED/AUTH_REQUIRED/READY/DEGRADED,不用單一「成功」。 7. **使用者 OAuth**:核對 account/tenant/scopes;同意後 token 保存在 broker 保護區,模型只見 opaque handle;新增寫入權限再核准。 8. **實際測試與紀錄**:每次 tool call 綁 agent/computer/package version/account,透過統一 policy/audit/result;外掛失敗不讓整個 harness 崩潰。 工具入站權限、網路 egress 與 OS sandbox 由 host/runtime 強制;不能信 MCP annotations 的 `readOnlyHint` 就斷定沒有副作用 [E19–E20]。支援標準 MCP 不等於支援任意 auth 形態:HTTP OAuth discovery/PKCE 與 stdio 的本機憑證配置是不同流程;不把標示 SSE 的 server 當成一定可用 Streamable HTTP,按 negotiated transport 實测 [E20]。 ### 20.4 狀態、更新與安全點 安裝狀態與連線狀態分開:`PENDING_APPROVAL → INSTALLING → INSTALLED`;instance 為 `STARTING → CONNECTED → AUTH_REQUIRED/AUTHENTICATED → READY/DEGRADED/DISABLED`。可用性是 installed + compatible + healthy + grant + account,不只 process alive。 更新採 staging → contract tests → permission diff → atomic activation。當前 operation 和長 job pin `package_digest + schema_version + connection`;新 run 才用新版,或在明確安全點重取 registry。外掛的 scope 變大或 tool schema 有 breaking change 要重新核准,不能默默延用舊 grant。 移除先撤銷 binding、阻止新呼叫、drain/cancel 對應 instance;其他 agent 使用的 package 不刪。若外掛持有 token,僅停止 process 不代表遠端 token 已撤銷;提供 provider logout/revoke 流程和殘留風險說明。 一般 user-space plugin 安裝/更新不重建 API image、不重啟整台 Computer。系統 package/顯示 driver/需 root 的改動另外走管理核准和 maintenance barrier,shared 時顯示全部受影響成員。 ### 20.5 範例 manifest(設計範例,不是已發佈 npm 套件) 以下示範的是 **要由 coding agent 實作/審查的本機 Outlook adapter**。空的 artifact/digest 必須拒絕安裝,不能填想像中的套件名稱或把此範例當已可直接安裝: ```yaml manifest_version: 1 id: lazyboy.example.outlook version: 0.0.0-example source: kind: reviewed_local_artifact artifact_ref: null # 實作完成後填實際來源 sha256: null # 安裝器不可接受空 hash runtime: kind: stdio_mcp execution_location: assigned_computer entrypoint: [./outlook-adapter] state_scope: agent_binding installation: supported_modes: [shared, dedicated] share_immutable_package: true permissions: filesystem: [own_workspace] shared_paths: [] network_services: [microsoft_graph, microsoft_identity] needs_host_access: false needs_root: false connection: provider: microsoft_graph credential_delivery: broker grant_scope: agent capabilities: - outlook.messages.list - outlook.messages.read - outlook.categories.preview - outlook.categories.apply_plan - outlook.categories.verify_plan ``` 名稱、路徑與 manifest API 都是新設計;Graph 的官方 API/OAuth 不等於存在官方同名 MCP package。第三方工具若僅接受 env token,按第 10.2 節顯示權限與相容限制,不把未實作 broker 相容性藏起來。 ### 20.6 MVP UI/API UI 在 Computer/Agent 的 Tools 頁:新增來源、選安裝目標、分配 agent、連接帳號、權限摘要、測試、啟用/停用、版本/更新/回滾/移除、活動紀錄。流程可以跨頁引導,不要求先設計大型商店。 建議的內部 API 職責:validate manifest、install job、read installation status、create/revoke binding、start OAuth、list effective capabilities、update/rollback、remove。這些路由需新的 typed contracts/auth/idempotency,不讓 LLM 呼叫安裝管理 API 自行批准。 Registry 改變以 event 通知 harness/UI,授權撤銷立即阻止新 dispatch;活躍 run 在下一安全點讀取版本化 registry。不要每回合重連全部 MCP,也不要讓一次安裝把所有工具 schema 全塞入 prompt。 --- ## 21. Outlook connector:第一個外部擴充驗收案例 ### 21.1 產品選擇與帳號範圍 建議以 **Microsoft Graph v1.0 + 使用者 delegated OAuth** 建立 Computer-local adapter;將它包成通用 loader 能安裝的 MCP/本機工具,證明外掛模型不是只支援 built-in Gmail。個人 Outlook.com 與 Microsoft 365/Exchange Online 工作/學校帳號各測;實際 tenant policy、admin consent、MFA 或授權限制正常顯示,不承諾公司帳號一定免審。 「Outlook connector」是泛稱。Power Automate/Logic Apps 的 Outlook connector 是其平台整合,不是通用 Linux binary 可直接下載進 LazyBoy [E21]。本計劃不採外部 Power Automate 作本機檔案處理或 workflow 執行的隱性替代。Outlook 桌面程式裡加入的任意 IMAP/本機 Exchange 帳號,也不能由名稱就推定支援 Graph;以 mailbox provider probe 為準。 ### 21.2 權限逐步增加 | 階段 | 權限/範圍 | 可用行為與限制 | |---|---|---| | 基本郵件列表 | 評估 Mail.ReadBasic 是否足夠 | headers/基本資料;不能假定包含分類所需正文/preview [E14] | | 需讀內容分類 | delegated Mail.Read 或較高已核准 scope | 只取必要欄位,必要正文才取,資料是 untrusted content | | 修改 message categories | delegated Mail.ReadWrite | tool 層只開放 categories,不因 broad scope 自動允許刪信/draft 等 [E12] | | 建立 master categories | MailboxSettings.ReadWrite | 額外權限;第一版可先用既有分類,避免未必要的 scope [E13] | | 寄信/搬資料夾/日曆 | 另外定義 capability 與核准 | 不列為郵件分類預設權限,不自動打開 | OAuth 採正式 authorization code + PKCE/適用的受支援 auth library;按 app 類型正確保護 client credential,state/nonce/redirect URI 核對;是否申請 offline_access 依 refresh 需求 [E11]。不從 browser cookie 抽 token、不讀使用者密碼、不略過 MFA。 ### 21.3 端到端流程 ```text 在指定 shared/private Computer 安裝 Outlook adapter → 對 agent 建 binding → 使用者授權 Microsoft 帳號 → 檢查 mailbox/account identity 與 operation grant → 取指定範圍郵件、完整處理分頁 → rule-first + model 批次分類、模糊結果留待確認 → 產生只含 categories 變更的 immutable plan → 核准 plan hash/account/message 範圍 → 執行 Graph 更新(有界批次) → 逐項讀回/驗證/記錄 changed/unchanged/failed/unknown ``` Graph 以 `PATCH /me/messages/{id}` 的 categories 屬性更新,這不是 Gmail label id 的 add/remove API [E12]。維持原有非本次變更分類,先讀當前 categories 計算目標;不要直接把固定分類陣列覆蓋其他人的分類。 對同 mailbox 使用 canonical account resource lock。若 API 支援可驗證的 conditional update,需實測其 If-Match/etag 語意;**本計劃不預設 Graph message PATCH 支援通用 CAS**。若無原子比較交換,外部 Outlook 客戶端仍有競爭窗口,必須標示 best-effort、遇可見衝突停止/重規劃;本地 lock/事後讀回不等於保證不丟失人類並行更新。 ### 21.4 批次、分頁與常駐同步 - Graph JSON `$batch` **最多 20 個子請求**,每個子項獨立狀態;batch HTTP 200 不代表全部成功。按子項處理 401/429/5xx 與 Retry-After;這與 Gmail 1,000 message IDs 的 batchModify 不同 [E15–E16]。 - `$select` 僅取必要欄位;完整跟隨 server 的 `@odata.nextLink`,不自行拼接 skip/把第一頁當全部 [E14]。驗證 continuation URL 仍是允許的 provider,防 SSRF/account confusion。 - 使用 `Prefer: IdType="ImmutableId"` 需在需要的每個 request/batch 子 request 保持一致;它在同信箱移動 folder 時穩定,但跨 archive mailbox/匯出再匯入仍有例外 [E17]。 - recurring sync 後續用 **每個 folder 的 message delta**,維護相應 nextLink/deltaLink;不是任意 search 的全信箱通用增量游標。token 失效時有安全重同步流程 [E18]。 - pending/unknown write 先回讀,不能全批盲重送;分類 cache 需包含 mailbox/message/content version/taxonomy version,不能拿另一帳號或舊內容結果套用。 - 附件下載到 Computer,掃描/解析/資料轉換也在 Computer;長期不需要的信件原文不存中央 DB。 ### 21.5 必需交付 fake Graph HTTP provider、固定測試 mailbox data、範例 package build、可安裝 manifest、read/preview/apply/verify tests、shared A 有權 B 無權的測試、版本更新/token 撤銷與恢復、完整 Activity 記錄。 真實 OAuth 不可用不阻擋上述內部實作,但必須將真實帳號 E2E 標 BLOCKED_EXTERNAL。不得把 fixture 的分類數字寫成真的已替使用者整理 Outlook。 --- ## 附錄 A:依據與查核來源 以下是本計劃使用的基準原始碼與官方規格。coding agent 必須以其開始實作時的 HEAD 核對,不盲套行號;新設計與 target 不是上游已具備的功能。 ### Repository 與前次健檢 - 基準 repository:`https://github.com/igs170911/LazyBoy` - Commit:`e6afa324530e19922909d4692c28fb005cc05a7a` - [R1] 工具與截圖:`https://github.com/igs170911/LazyBoy/blob/e6afa324530e19922909d4692c28fb005cc05a7a/crates/api/src/tools.rs` - [R2] SandboxProvider/原生契約:`https://github.com/igs170911/LazyBoy/blob/e6afa324530e19922909d4692c28fb005cc05a7a/crates/control/src/sandbox.rs` - [R3] Sandbox transport/檔案 bytes:`https://github.com/igs170911/LazyBoy/blob/e6afa324530e19922909d4692c28fb005cc05a7a/crates/sandbox/src/docker.rs` - [R4] Supervisor 容器內執行:`https://github.com/igs170911/LazyBoy/blob/e6afa324530e19922909d4692c28fb005cc05a7a/crates/supervisor/src/docker.rs`;routes:`https://github.com/igs170911/LazyBoy/blob/e6afa324530e19922909d4692c28fb005cc05a7a/crates/supervisor/src/main.rs` - [R5] Harness loop/prompt:`https://github.com/igs170911/LazyBoy/blob/e6afa324530e19922909d4692c28fb005cc05a7a/crates/api/src/runs.rs` - [R6] Browser adapter:`https://github.com/igs170911/LazyBoy/blob/e6afa324530e19922909d4692c28fb005cc05a7a/crates/control/src/cua/browser.rs` - [R7] Run policy:`https://github.com/igs170911/LazyBoy/blob/e6afa324530e19922909d4692c28fb005cc05a7a/crates/harness/src/policy.rs` - [R8] MCP:`https://github.com/igs170911/LazyBoy/blob/e6afa324530e19922909d4692c28fb005cc05a7a/crates/api/src/mcp.rs` - 前次本對話產物:`LazyBoy_Computer_Use_Healthcheck_2026-09-10.md`。本文件已包含必要內容,可獨立交付;若與舊文件的 GUI 可見性或 Team 共用假設不一致,以本文件第 0–1 節為準。 ### 官方外部文件(2026-09-10 查閱) - [E1] Gmail batchModify/最大 1,000 IDs/空成功回應:`https://developers.google.com/workspace/gmail/api/reference/rest/v1/users.messages/batchModify` - [E2] Gmail OAuth scopes 與受限資料說明:`https://developers.google.com/workspace/gmail/api/auth/scopes` - [E3] Playwright connectOverCDP/現有 browser context/相容性限制:`https://playwright.dev/docs/api/class-browsertype` - [E4] Docker isolation、安全邊界與 daemon 權限參考:`https://docs.docker.com/engine/security/` Docker 容器隔離不是不需測試的安全保證;應依威脅模型與官方指引配置權限、network、mounts、resource limits,並以本文件的跨 Computer 測試驗證 [E4]。 ### 本版新增來源(2026-09-10 查閱;不是把官方支援當成 LazyBoy 已整合) - [R9] LazyBoy display 啟動/Team slots/Xvfb/x11vnc/XFCE/Cua:`https://github.com/igs170911/LazyBoy/blob/e6afa324530e19922909d4692c28fb005cc05a7a/image/computer/lazyboy-screen` - [E5] TigerVNC Xvnc:`https://tigervnc.org/doc/Xvnc.html` - [E6] TigerVNC x0vncserver:`https://tigervnc.org/doc/x0vncserver.html` - [E7] noVNC 與 WebSocket proxy:`https://novnc.com/info.html` - [E8] Selkies 現行設計/transport/encoder:`https://docs.selkies.io/design`;`https://selkies-project.github.io/selkies/component` - [E9] Xpra 應用與桌面轉送/HTML5:`https://xpra.org/index.html` - [E10] Playwright Docker 與 Chromium/程序回收注意事項:`https://playwright.dev/docs/docker`。本案不直接採測試容器常見的 host IPC/SYS_ADMIN 放寬,保留產品隔離要求。 - [E11] Microsoft authorization code/PKCE:`https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow` - [E12] Graph message update/categories/Mail.ReadWrite:`https://learn.microsoft.com/en-us/graph/api/message-update?view=graph-rest-1.0` - [E13] Graph master categories 建立/MailboxSettings.ReadWrite:`https://learn.microsoft.com/en-us/graph/api/outlookuser-post-mastercategories?view=graph-rest-1.0` - [E14] Graph messages 列表/$select/分頁/permissions:`https://learn.microsoft.com/en-us/graph/api/user-list-messages?view=graph-rest-1.0` - [E15] Graph JSON batching/20 子請求:`https://learn.microsoft.com/en-us/graph/json-batching` - [E16] Graph throttling/子請求失敗:`https://learn.microsoft.com/en-us/graph/throttling` - [E17] Outlook immutable IDs 的範圍與例外:`https://learn.microsoft.com/en-us/graph/outlook-immutable-id` - [E18] Graph folder message delta:`https://learn.microsoft.com/en-us/graph/api/message-delta?view=graph-rest-1.0` - [E19] MCP tools/annotations 信任限制:`https://modelcontextprotocol.io/specification/2025-11-25/server/tools` - [E20] MCP HTTP authorization/transport:`https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization` - [E21] Microsoft Office 365 Outlook 平台 connector:`https://learn.microsoft.com/en-us/connectors/office365/` 研究只證明上游文件與基準程式呈現的行為;本機 Docker/GUI/企業帳號、實際效能及完整威脅邊界仍須 coding agent 按測試矩陣驗證。不存在單純換 VNC 就保證所有 agent 任務提速的證據。