lazyBoy/docs/agent-computer-progress.md

26 KiB
Raw Blame History

Agent Computer progress (V3)

基準 commit計劃e6afa324530e19922909d4692c28fb005cc05a7a
本機開始 HEAD79952b088b394e36d6c3db3952165f1c3fd59961
未覆蓋使用者未提交修改(docs/plan/ 仍未追蹤)。

驗證2026-09-10 複查見文末「複查Bug 修正」):cargo fmt --checkcargo clippy --workspace --all-targets -D warningscargo test --workspace(含 sqlx全綠make test-agent-computerapps/web npm run build 全部 exit 0。
sqlx 測試用拋棄式 pgvector/pgvector:pg16127.0.0.1:5434docker run --rm --name lazyboy-test-pg …),不重建正在服務的 lazyboy-postgres-1
真實 OAuth主信箱TigerVNC GUI fixtureBLOCKED_EXTERNAL
sample MCP 在真實 Computer 容器 lb-team-space-*python3 echo_server.py JSON-RPC 回 from-computer。外掛 UI 已 typecheck無瀏覽器工具未點擊。


PR-00 / PR-01

狀態IMPLEMENTED見前次。截圖交付、semantic/vision、原生 fs/exec 短路徑。


PR-02雙模式身份

狀態IMPLEMENTED資料契約idle沒有強制遷移

  • computers.generationdestroy/recreate generation + 1(舊 job 不可裝活)。
  • Team 多 bot 同 computer_idcomputer_scope_key(Team, space, bot-a) == bot-b。Dedicated 互斥 scope。
  • 沒有bots.computer_id 加 UNIQUE。
  • AdapterContext.computer_generation / control_epoch
  • Pause scopesPauseScope::{Agent,Display,Computer};停 A 不 bump B 的 display epoch。
  • idle reaper 把 computer_jobs running 算進活性。

回滾migration 022 + generation SELECT/UPDATE。


PR-03ledger / 脫敏 / activity

狀態IMPLEMENTEDPostgres 為 mutation 來源;本環境未跑 sqlx 整合測試)

  • dispatchmutating tool 先 beginjournal insert 失敗則 JOURNAL_UNAVAILABLE,不開做。
  • operationId + payload hash replay 已存結果;不同 hash → PAYLOAD_MISMATCH
  • operationId 不進入 payload hash。
  • finishcomputer_operations + operation_outboxworker_loop flush_outbox 只補尚未出現在 run_activityoperationId
  • 結果與 outbox payload 經過 redact_text / redact_json

PR-04jobs / cancel / CAS

狀態IMPLEMENTEDRunner 在 API 行程內container recreate 以 generation 中斷)

  • JobSupervisorprocess_group(0)cancel TERM→KILL process group。

  • execaction=run|status|cancelbackgroundjobId

  • write_file.expectedHashCONFLICT,不覆蓋。

  • 測試:/bin/true 真 exitsleep 30 可 cancel。

  • API 重啟:computer_jobs running/accepted → interrupted(不假裝收回 Docker PID

  • LAZYBOY_NATIVE_JOB_CONCURRENCY(預設 2超額 → QUOTA_EXCEEDED

  • Artifactwrite_file 成功寫 computer_artifactsGET /api/bots/{id}/artifacts 列表;下載從 Computer read_file 串回sha256 不符 → CONFLICT

O04 PTY terminal.*DEFERRED見文末。跨重啟回收仍在跑的容器 PID標 interrupted不是 resume。


PR-05Tool Manager / MCP

狀態IMPLEMENTEDstdio 不在 API spawnsample 在 Computer無第三方商店

  • Manifest空 digest / zip-slip / 空 entrypoint 拒絕。
  • 安裝≠ReadyAuthRequired ≠ 可用)。
  • scripts/sample-mcp/echo_server.py + manifest.yaml(本機範例,不是虛構 npm
  • RESTGET/POST /api/bots/{id}/toolsPOST .../tools/callPOST .../revoke
  • 安裝把 echo 寫進 ComputerDedicated tools/...Team shared/tools/...python3 在該容器執行 JSON-RPC。
  • Agent 工具 computer_mcp 走同一條路徑;未 bind → NOT_BOUND
  • 外掛頁「Computer 套件」可安裝/呼叫/撤銷 echo市集 MCP 文案不再假裝 stdio 都在 Computer。
  • MCP call_for 先複製 client 再 awaitdefinitions_for(actor) 不把別人的工具塞進這次 run。

未做任意第三方套件商店、OAuth broker。/api/mcp-servers stdio 不再 spawn 子行程,只存 metadata 並指向 Computer Tool Manager。HTTP/SSE 仍為遠端 client。真實 Microsoft/Google OAuthBLOCKED_EXTERNAL


PR-06路由 / verifier / wait

狀態IMPLEMENTED決策層

  • choose_route:有授權 API 不走 browserPOLICY_DENIED 不繞路。
  • CompletionLayertransport ≠ effect ≠ taskwait_counts_as_progress() == false
  • policywait 不再刷新無進展時鐘;exec 可。
  • wait_until 有 deadline未知 disabled 不空轉。
  • system promptGmail/Outlook 有 connector 走 API。

PR-07form / takeover scopes

狀態IMPLEMENTEDform 工具已註冊lease/pause 見 PR-02

  • run_form_macro 失敗即停、逐步 evidence。
  • Display writer lease 原本就有pause scope 見 PR-02。
  • Agent 工具 form_fill:用最新 snapshot locatorelement idrun_form_macro 先定位,第一個失敗就停;可選 submit click。

PR-08A Gmail fixture

狀態IMPLEMENTED純函式 fixture不碰真信箱

  • batchModify 同 delta 分組、1000 cap。
  • undo 只撤本 plan 的 delta。
  • 真實帳號:BLOCKED_EXTERNAL

PR-08B Outlook

狀態IMPLEMENTEDGraph 語意 fixture非官方 npm

  • $batch 最多 20子項 429/401 分開。
  • categories merge不覆蓋無關分類。
  • Mail.ReadWrite 不自動允許寄信。
  • 真實 Graph OAuthBLOCKED_EXTERNAL

PR-09 TigerVNC 候選

狀態IMPLEMENTEDopt-in預設仍 Xvfb+x11vnc

  • DisplayBackendslot 0 = :1 / 5900 / 6080T57
  • lazyboy-screenLAZYBOY_DISPLAY_BACKEND=tigervnc_xvnc
  • Dockerfile 加入 tigervnc-standalone-server,失敗則 script fallback Xvfb。
  • Cua/中文/a11y GUI 對照:BLOCKED_EXTERNAL未改 default

PR-10 設定 / 文件

狀態IMPLEMENTED

.env.exampleLAZYBOY_EXECUTION_PROFILELAZYBOY_DISPLAY_BACKENDLAZYBOY_BROWSER_BACKEND、concurrency、tool install flags。
migrations/022_agent_computer.sql


O01O48

ID 狀態
O01 IMPLEMENTED
O02 IMPLEMENTED短 exec長 job 見 O04
O03 IMPLEMENTED + CAS
O04 PARTIALComputer 內 background exec + cancelPTY terminal.* DEFERRED
O05 IMPLEMENTEDform macro + form_fill 工具)
O06 IMPLEMENTEDstdio 不在 API spawnHTTP/SSE 遠端echo 在 Computer
O07 DEFERRED未量測 docker exec 開銷)
O08 IMPLEMENTEDboot_for(need_gui=false) 不 ensure_screenLAZYBOY_RUNNER_ONLY 不 boot XFCE
O09 IMPLEMENTEDrouter
O10 IMPLEMENTEDrevoke 從下次 schema 拿掉 computer_mcpstdio 不再進 defs
O11 保留現況
O12 IMPLEMENTED
O13 DEFERRED
O14 IMPLEMENTEDPR-01
O15 保留現況(既有 profile bind
O16 PARTIALverifier 層 + wait 不算進度)
O17 實驗opt-in
O18 DEFERRED
O19 保留現況
O20 保留現況
O21 保留現況
O22O24 DEFERRED
O25 IMPLEMENTED保留
O26 PARTIAL既有 screen/profile lease
O27 IMPLEMENTEDepoch 函式)
O28 PARTIALidle 看 runs/skills/jobs2026-09-10 修正守門原本永遠回 false並在判斷前 reconcile job 狀態)
O29 IMPLEMENTEDpackage/binding 分離;共用 bytes 不共享帳號)
O30 IMPLEMENTEDLAZYBOY_NATIVE_JOB_CONCURRENCY,預設 2配額滿時先向 Computer reconcile 未 poll 的 job不會永久卡死
O31 DEFERRED
O32 DEFERREDT59保留 -ac 直到 Xauthority 接到 Cua/AT-SPIVNC 仍走認證 proxy
O33 IMPLEMENTEDsample MCP 安裝 REST + UI
O34 IMPLEMENTEDdigestzip-slipunpinned npx 拒絕)
O35 IMPLEMENTEDinstalled ≠ readyAuthRequired 不可用)
O36 PARTIAL熱啟用 bindings無獨立 schema cache 服務)
O37 IMPLEMENTED0.0.2 旁置、job pin 舊版、rollbackremove
O38 BLOCKED_EXTERNAL
O39O40 IMPLEMENTED fixture真實帳號 BLOCKED_EXTERNAL
O41 IMPLEMENTEDdispatch 寫 operations + outboxflush 補送)
O42 IMPLEMENTEDerrorCode/jobId/operationId
O43 IMPLEMENTED列表 + 下載;磁碟 hash 不符 CONFLICT
O44 PARTIALverifier 層)
O45 IMPLEMENTEDCAS + operation id
O46 IMPLEMENTEDGET /api/computer/{id}/healthdbsandboxdisplayjobsoperations
O47 DEFERRED
O48 DEFERRED無固定環境雙模式 P95不寫未測倍數

T01T64

ID 狀態 證據/理由
T01 IMPLEMENTED should_deliver_observation_image
T02 IMPLEMENTED 換模型takeover 強制交付(同真值表)
T03 IMPLEMENTED pixel_actions_need_visiontext-only 無圖
T04 IMPLEMENTED typed_browser_errors
T05 IMPLEMENTED Team/Dedicated path + echo 路徑測試
T06 PARTIAL generation 拒絕舊 job未覆蓋所有偽造 grant 變體
T07 保留現況 task 無 Docker socket未加新 sentinel fixture
T08 IMPLEMENTED zip-slip.. path 拒絕
T09 IMPLEMENTED invalid UTF-8 binary payload
T10 PARTIAL 工具錯誤非空成功;磁碟滿未測
T11 IMPLEMENTED stale_hash CAS CONFLICT
T12 IMPLEMENTED Supervisor /exec 回完整 CommandResultreap 讀 exit 檔,false/缺檔為 Failed/1
T13 IMPLEMENTED Computer-side job_op cancel 走 computer_cancel_scriptTERM→KILL 整個 process group驗證後才標 cancelled2026-09-10 修正 pid 錯誤status 缺欄位當 TRANSPORT不發明 running
T14 DEFERRED API 重啟標 interrupted不 resume 容器 PID
T15 IMPLEMENTED generation interrupt
T16 IMPLEMENTED operation_id hashmismatch2026-09-10 第二輪key 改 per-bot、in-flight 同 id 回 UNKNOWN_EFFECT、傳輸失敗不存成 succeededsqlx 測試 ledger_is_per_bot_and_does_not_rerun_in_flight_work
T17 IMPLEMENTED outbox flush 補送且不重複sqlx 測試 outbox_flush_does_not_duplicate_recorded_operations2026-09-10 修正 SELECT 1 解碼 bug
T18 IMPLEMENTED journal_failure 拒 mutation
T19 IMPLEMENTED actor-scoped MCPstdio 不在 API 持有 client
T20 PARTIAL NOT_BOUNDrevoke無真實 token revoke
T21 IMPLEMENTED canary_is_stripped2026-09-10 第二輪ledgersnippet 實際套用 redact_secret_patterns(之前傳空 canary 等於沒脫敏)
T22 保留現況 既有 prompt 邊界;無新 injection corpus
T23 PARTIAL 同 display lease 既有Cua+worker 未雙開 fixture
T24 PARTIAL pause/takeoverHTTP in-flight barrier 未單獨測
T25 IMPLEMENTED wait 不算 milestone
T26 IMPLEMENTED Gmail batchModify fixture
T27 IMPLEMENTED fixture 429/partial真實帳號 BLOCKED_EXTERNAL
T28 IMPLEMENTED undo 只撤本 plan
T29 IMPLEMENTED 無強制拆 Teammigration 不 UNIQUE computer_id
T30 IMPLEMENTED boot_for(need_gui=false)ensure_screenmaybe_ensure_screen + FakeSandbox native write/read/execstart.sh runner-only 不 boot XFCE
T31 PARTIAL job 配額;無壓力 bench
T32 DEFERRED 無郵件分類品質集
T33 PARTIAL broker 不進 generic env無任意 exec 讀 socket fixture
T34 IMPLEMENTED artifact 從 Computer 下載
T35 PARTIAL CASoperation replayresume 不重播未全測
T36 PARTIAL mutating tools 走 ledgerMCP stdio 不再是旁路 spawn
T37 IMPLEMENTED team_computers_sharemigration 註解+測試
T38 IMPLEMENTED Team bots/<id>/ 路徑
T39 IMPLEMENTED shared/ + CAS
T40 PARTIAL 多 slot 契約;無雙 writer GUI fixture
T41 PARTIAL display writer lease 既有
T42 IMPLEMENTED pause scope 停 A 不 bump B
T43 PARTIAL idle 看 jobs整機 pause 未單測 recreate 全集
T44 保留現況 既有 ensure-screen single-flight
T45 IMPLEMENTED Dedicated 刪 botTeam Computer 存活
T46 IMPLEMENTED echo 安裝/呼叫 executionLocation=assigned_computer
T47 IMPLEMENTED binding per bot套件 per computer
T48 IMPLEMENTED digestzip-slipunpinned npx
T49 IMPLEMENTED plan_version_switch job pin
T50 IMPLEMENTED revokeremoverevoke 掉 schema
T51 IMPLEMENTED Outlook fixture非官方 npm
T52 IMPLEMENTED Graph 子項 429/401
T53 PARTIAL fixture 分頁語意;真實 delta BLOCKED_EXTERNAL
T54 IMPLEMENTED categories merge 不盲覆蓋
T55 BLOCKED_EXTERNAL 無 Cua/中文/a11y GUI
T56 PARTIAL generation bumpbackend 熱切未做
T57 IMPLEMENTED slot 0 = :1/5900/6080
T58 保留現況 既有 noVNC無新 DPI fixture
T59 DEFERRED 保留 -acVNC 走認證 proxyXauthority 未接到 Cua
T60 IMPLEMENTED 同 T30native 路徑不 attach viewerGUI 之後才 lazyboy-screen ensure
T61 IMPLEMENTED 未審查 env tokenunpinned npx 拒絕
T62 保留現況 同 UID 不宣稱強隔離
T63 PARTIAL job 配額renderer OOM 未測
T64 PARTIAL 套件路徑可重建;舊 job 不裝活

2026-09-10 複查Bug 修正

本輪先跑計劃第 16 節的完整 gate再修實際發現的 bug未新增功能。

驗證命令與結果(本機,拋棄式 Postgres pgvector/pgvector:pg16127.0.0.1:5434

  • cargo fmt --all -- --check:原本有 diffartifacts.rscomputer.rs 等新檔未格式化)→ 已 cargo fmt --all,現在 exit 0。
  • cargo clippy --workspace --all-targets -- -D warningsexit 0。
  • DATABASE_URL=… cargo test --workspace全部通過api 157 passed / 3 ignoredcontrol 150harness 37contracts 7sandbox 7supervisor 2。前次紀錄的「sqlx 未連」現在已實跑14 個 sqlx 測試dbmemorymonitorrouting::fan_out全綠。
  • make test-agent-computerexit 0。
  • apps/webnpm run buildtsc --noEmit + vite通過。

修正:

  1. lazyboy-api 測試 binary 結束時 SIGABRTort Mutex poisonedrelease_env_on_exit 二次 panic。根因memory.rscatch_unwind 包住 TextEmbedding::try_new,但 ort 找不到 libonnxruntime.so 時是在持有全域鎖的情況下 expect panic鎖被 poison 後程序退出時 .fini_array hook 再 panic → abort。正式環境沒設 ORT_DYLIB_PATHAPI 正常關機也會變 exit 134。修法memory.rs 新增 preload_onnx_runtime(),先走 ort::init_from(path)(回 Result)預載 dylib失敗即標 Unavailable 不再進 fastembedcrates/api/Cargo.toml 直接依賴同版 ort ="=2.0.0-rc.13"lock 無新增 crate。測試 database_enforces_agent_scope_and_queries_do_not_leak 改成顯式 ModelState::Unavailable,不再靠環境缺 ONNX 來觸發;新增 a_missing_onnx_runtime_is_an_error_not_a_panic。反向驗證:ORT_DYLIB_PATH=/nonexistent cargo test -- --ignored memory_model_recovers_after_cache_failure 只因無模型 fail不再 abort
  2. Computer 內 background job 的 pid 是錯的T13 process-tree cancel 實際上沒生效)computer_background_launch 原本是 mkdir -p … && setsid nohup sh … & echo $!& 作用在整個 a && b list$! 是 bash 子 shell 的 pid不是 setsid 後的 session leader。後果status 只是碰巧能用(子 shell 會 waitcancel 只殺子 shell真正的 sh→子程序變孤兒繼續跑,之後 status 讀不到 exit 檔還會誤報 failed。修法:mkdir 獨立一行wrapper 先 printf %s "$$" > …/pidlauncher 等 pid 檔再輸出(setsid 若 fork 也正確)。新增 computer_cancel_script(pid)kill -TERM -- -pgid → 最多 1s 等待 → kill -KILL -- -pgid → 再驗證exit 0 才算整棵樹已消失。supervisor/docker.rs cancel 改用它,且只有樹確實消失才把 job 標 cancelled(否則維持 running,不假稱取消)。測試:computer_cancel_script_kills_the_whole_process_tree(本機真起 sh -c 'sleep 300; sleep 300',用 pgrep -g 驗證子 sleep 一起死);另在真實 Team 容器 lb-team-space-c7bace… 內手動跑 launchercancelpid=pgid=sidtree gone
  3. supervisor job_follow_up 沒檢查 job 屬於哪個容器:拿到別的 Computer 的 jobId 時會在自己容器對同號 pid 送 kill。現在 job.computer_id != container 一律回 unknown job
  4. Makefile help 目標壞掉:新增的 test-agent-computer 說明被塞進同一個 @echo "… 造成跨行未閉合字串,make helpUnterminated quoted string Error 2。已拆成兩行 @echo
  5. idle reaper 的「有工作就不暫停」守門一直是死的HEAD 既有 bugcomputer_has_active_workSELECT 1INT4解成 (i64,)sqlx 回 ColumnDecode mismatched types,被 matches!(Ok(Some(_))) 吞成 false → 只要 computers.updated_at 十分鐘沒動,正在跑 run 的 Computer 也會被 suspend。改成 sqlx::query(...).fetch_optional 只看有沒有列。sqlx 測試 idle_reaper_reconciles_unpolled_jobs_with_the_computer 同時覆蓋 run 與 job 兩種活性。
  6. flush_outbox 去重失效T17 宣稱的「不重做」實際沒生效):同樣的 SELECT 1i64 解碼錯誤讓 exists 永遠 None每筆 outbox 都再寫一次 run_activityActivity 出現重複 tool 事件。已改為列存在檢查;查詢出錯時保留 outbox 列到下一輪,不猜。新增 sqlx 測試 outbox_flush_does_not_duplicate_recorded_operations
  7. 背景 job 配額會永久卡死computer_jobs.status 只在 agent 呼叫 exec status 時更新;兩個跑完但沒人 poll 的 job 會讓該 Computer 之後永遠 QUOTA_EXCEEDEDidle reaper 也永遠以為有工作。修法:tools.rs 配額看起來滿時先 refresh_running_jobs(向 Computer 問最舊 16 筆 running 的真實狀態supervisor 回 unknown jobinterrupted)再重算;computer.rspause_idle_computers 在判斷活性前做同樣的 reconcilesuspended 容器無法問,stop_parked_computers 不做)。

未修、已知:

  • host 端 JobSupervisor::startcrates/control/src/jobs.rs)用 piped stdout 但只在子程序結束後 read_to_end;輸出超過 pipe buffer~64 KiB的子程序會永久阻塞。目前正式路徑不用它背景 job 全在 Computer 內,exec_background_does_not_spawn_on_the_api 有守門),僅測試使用;若之後要在 API 行程內跑 job 必須先改成邊跑邊 drain。
  • supervisor 的 ComputerJobTable 在記憶體supervisor 重啟後舊 jobId 回 unknown jobAPI 側已把 computer_jobs 標 interrupted屬同一限制T14 仍 DEFERRED

回滾:還原 crates/api/src/memory.rscrates/api/Cargo.tomlort 直接依賴)、crates/api/src/tools.rsrefresh_running_jobscrates/api/src/computer.rscrates/api/src/operations.rscrates/control/src/jobs.rscrates/supervisor/src/docker.rsMakefile 本節改動即可;無 migration 變動。

2026-09-10 複查(第二輪):三路平行 code review 後的修正

三個獨立 reviewledger/outbox/artifactsjobs/tool-manager/install雙模式/pause/前端)共回報 40 餘項重複、已在上一節修掉的略過。以下每項都有測試或反向驗證。gatecargo fmt --checkclippy -D warningscargo test --workspaceapi 162control 154harness 37tsc --noEmit 全綠。

LedgerT15T17operations.rs 重寫)

  1. operationId 全域命名空間 → 跨 bot replay拒絕ledger key 改為 {bot_id}:{operation_id},查詢加 bot_id 條件。Bot B 選到 Bot A 用過的 id不會拿到 A 的結果,也不會被 PAYLOAD_MISMATCH 擋。
  2. 記憶體 LEDGER 拆掉:與 DB 兩份狀態不一致(一邊 accepted 一邊沒列)、無上限增長(連非 mutating tool 都建列。Postgres 是唯一真相;OperationLedger 只留 control crate 單元測試用。
  3. bot_computer_id 查詢失敗被當「沒有 Computer → Proceed」:現在 DB 錯誤 = JOURNAL_UNAVAILABLE;不需要 Computer 的 mutationrememberschedulecomputer_id = NULL 入帳migration 023 放寬 NOT NULL
  4. 同 id 同 payload 的 accepted 列直接 Proceed → 崩潰後重試會做第二次:新增 Begin::InProgress → 工具回 UNKNOWN_EFFECT,要求先讀回狀態、換新 id 重試。
  5. finish 對非 mutating tool 也寫 DBoutbox:提早 return。exec status 改為非 mutatingexec run/cancel 仍是)。
  6. "xxx failed: …" 的傳輸失敗被存成 succeeded 並永遠 replayoutcome_status 辨識這類文字 → 刪除 accepted 列讓同 id 可重試;不寫入結果。
  7. replay 丟掉 pauseBegin::Replay 帶回 pause
  8. outbox 寫 run_activity 失敗仍標 delivered:新增 monitor::try_record_pool,只有成功才標;且只處理 created_at 早於 2 秒的列,避免與 runs.rs 的直接寫入賽跑而重複。
  9. redact_text(&text, &[]) 是 no-op:新增 redact_secret_patternsBearer、password=token:sk-ghp_AKIAxoxAIza、PEM 私鑰、JSON secret keyledger 結果與 activity snippet 都經過它。control crate 新增 regex 直接依賴lock 已有)。
  10. retention 新增 operation_outboxdelivered7 天)與 computer_operations(非 accepted90 天)。

JobsT13T14

  1. runner-only 容器 PID 1 是 sleep infinity,不收屍setsid 後的 wrapper 結束會變 zombiekill -0 仍成功 → job 永遠 running。修:HostConfig.init = truedocker-init 收屍);status 改先讀 exit 檔、再用 computer_alive_script(看 /proc/*/status StateZ/X 視為死)。測試 computer_alive_script_treats_a_zombie_as_dead 本機造真 zombie 驗證。
  2. launcher 沒吐出 pid 時仍登記 jobpid None→ 永遠 running、不能 cancel:現在直接回錯誤,不登記幽靈 job。
  3. exec status/cancel 不看歸屬與世代:新增 job_ownership:別的 bot 的 job → UNKNOWN_JOBgeneration 小於目前 Computer 世代或已 interrupted → 直接回 interrupted不去問新容器persist_job 的 upsert 不再把 interrupted 蓋回 running
  4. pin_running_jobs 把同 Computer 上其他 bot 的 job 也 pin 了:加 bot_id 條件。

Tool ManagerT18T21

  1. revoke 後重裝撞 UNIQUE(package_row_id, bot_id) → 500ON CONFLICT … DO UPDATE SET status='ready' RETURNING id;切版本走 switch_binding(同 tx 內先清掉同 (package_row, bot) 的非 ready 殘留)。
  2. rollback 會把 revoked binding 復活:非 ready → 409。
  3. 執行前不驗 digestverified_run_argv 在同一條命令內 sha256sum -c 通過才 exec python3;不符 exit 97 → PACKAGE_TAMPERED。測試 tampered_package_is_refused_before_it_runs 真改檔驗證。
  4. validate_manifest 只檢查非空:現要求 64 hexcompute-at-install 佔位會被拒。
  5. InstallBody 只吃 package_id、前端送 packageIdserde rename + alias 兩者皆收。
  6. refuse_unpinned_npx@scope/pkg@ 當版本 pin修為去掉 scope 前綴再判斷。

其他

  1. form_fill 靜默截斷>20 欄或欄位缺 namelocator → INVALID_ARGUMENT,不再填半張表回報成功。
  2. looks_like_css 誤判 v1.2 ReleaseC++ Guide 這種標題為 CSSclicktype 先做精確唯一標題比對;找不到才依 locator 形狀決定 SELECTOR_UNSUPPORTEDTARGET_NOT_FOUNDTARGET_STALE,並各給對應說明。
  3. computers.display_backend 從未寫入boot 轉 running 時寫入 DisplayBackend::from_env()health 不再永遠回欄位預設值。
  4. delete_bot 不清 tool_bindingscomputer_jobscomputer_operationscomputer_artifacts:同 tx 一起刪Team Computer 的配額不再被已刪 bot 佔用)。
  5. waitPROGRESS_WHEN_REPEATED與本文件「wait 不刷新無進展時鐘」相反:改成 heartbeat 語意 — wait 只更新 last_heartbeat_turn(不會被當 loop halt但 stale 教練訊息照常觸發;polling_a_build_or_a_queue_is_not_treated_as_spinning 同時鎖住兩半契約。
  6. Gmail fixture 沒有真的 undo:新增 undo_plan(before, batches),只還原本次計畫實際改動的 label原本就有的不拔、原本沒有的不補、人工新加的不動測試做 plan→undo 往返驗證。
  7. 前端:RunActivityEntry.operationId 補型別;runs.rs 從工具回傳 JSON 抽 jobId 寫進 activitymonitor 原有的 entry.jobId 顯示終於有值;並顯示 op <短 id>

Migration:新增 migrations/023_agent_computer_fixes.sqlcomputer_operations.computer_id DROP NOT NULL、移除多餘 computer_operations_id_hash、outbox pending 部分索引、computer_operations(bot_id, created_at) 索引)。不改 022已可能套用過

review 提到但本輪不動、記錄在此

  • Pause scopesresume_after_pauseroute_operation 有純函式與測試但沒接進 runs 主迴圈takeover 實際只有 GUI 全暫停,沒有 scope 級細分T22T24 應視為 PARTIAL不是 DONE
  • write_filebash -lc 字串插值路徑HEAD 既有);normalize_workspace_path 有限制字元,本輪未改成 argv。
  • supervisor ComputerJobTable 仍在記憶體T14 DEFERRED 不變)。

回滾:還原本節列出的檔案,並 DELETE FROM _sqlx_migrations WHERE version=23ALTER TABLE computer_operations ALTER COLUMN computer_id SET NOT NULL(若已無 NULL 列)。

誠實未完成

P0/P1 可在本環境落地的已接上。下面不是「做完」:

  1. 真實 Gmail/Outlook OAuth主信箱BLOCKED_EXTERNAL
  2. TigerVNC 當預設 + Cua/中文/a11y GUIBLOCKED_EXTERNAL;預設仍 Xvfb+x11vnc。
  3. Postgres sqlx 整合測試此環境未連。
  4. O04 PTY terminal.*DEFERRED — 非互動走 exec+jobs+process-tree cancelTUI 協作仍用 GUI shell。不假裝有 PTY。
  5. 跨重啟回收容器內仍在跑的 PID標 interrupted不是 resume。
  6. 任意第三方套件商店、完整 OAuth broker沒有憑證。
  7. O48 無未測速度倍數。
  8. 外掛 UI 未在瀏覽器點過(無瀏覽器工具);已 tsc --noEmit

雙模式Team/Dedicated 契約不變;沒有 UNIQUE bots.computer_id。stdio MCP 不是 API 子行程。

回滾:還原本輪 crate / migration 022 / lazyboy-screen -ac 註解 / sample-mcp / 前端 plugins+i18n。不要 force push。