Web Use 实施与验证记录
本页只记录 Web Use 目标设计 的实施任务、验证命令和 review 结论,不修改概念设计。第一项任务交付内置浏览器 Browser Agent 的低成本 baseline。
TASK 1 · COMPLETE TASK 2 · COMPLETE TASK 3 · COMPLETE / APP E2E PASSED TASK 4–5 · COMPLETE / APP E2E PASSED TASK 6 · COMPLETE / PUBLIC API WEB_USE任务 1:DOM-first Browser Agent baseline
批准的设计:docs/reference/design/integrations/web-use.html。
基线:717d4e17。实现从隔离 worktree 和分支 codex/browser-agent-20260814 开始。
生产文件:openprogram/programs/agentic_functions/browser_agent/__init__.py、openprogram/programs/_registry.py、openprogram/programs/__init__.py、openprogram/agent/authority.py。
测试文件:tests/unit/test_browser_agent.py。
行为契约
- 公开入口名为
browser_agent,只控制 OpenProgram 桌面端当前可见的内置 web tab;底层固定使用现有engine=app。 - 内部工具默认
observe,返回 URL、title、viewport、页面文本、ARIA snapshot 和当前 observation 有效的 element refs,不发送截图。 - 只有显式
screenshot才返回一张当前 viewport PNG,并通过当前模型原生 vision 处理;不调用image_analyze。 - 不导入或调用 OCR、YOLO、object detector、candidate boxes、zoom、component memory、vision memory、workflow replay 或自动学习。
- 每个会改变页面状态的动作必须携带最新
frame_id和 element ref;动作后立即使旧 observation 失效。下一次写动作前必须重新 observe。 - 公开结果中的
status=succeeded只在内部工具实际通过一次 DOM/URL assertion,且该 assertion 晚于最后一次写动作时产生。模型输出只提供 summary,不能决定 status。 - 不开放 JavaScript eval、cookie/storage、upload/download、sidecar、headless fallback 或用户 Chrome profile。
- 调用结束、取消、超时和异常均关闭本次 Playwright session;现有
playwright_browserAPI 保持不变。
Public-entry RED
python -m pytest -q tests/unit/test_browser_agent.py 必须先证明以下缺口:
browser_agent尚未注册。- 没有 DOM/ARIA/ref observation 与 viewport screenshot 的受限工具。
- 没有 stale frame 拒绝和动作后重新 observe 约束。
- 没有 Runtime 权威 completion,模型可以在无 verification 时声称成功。
安全、取消、错误与并发边界
- 读取与 screenshot 不请求额外授权;外部 origin 的 navigate/click/type/press/select 每次经过现有 approval 机制。本地项目页面仍受 frame freshness 和 cancel 检查。
- 首版每个
browser_agent调用只拥有一个 browser session。已有playwright_browsersession 不复用,避免跨任务 refs 和 verification 交叉。 - 首版不声称解决多窗口 responder 绑定;当桌面控制面无法唯一确认 tab 时返回
target_lost或底层错误,不选择其他页面。 - step limit、timeout、invalid structured reply、tool error 和 verification missing 都返回 failed/cancelled,不转换为 succeeded。
明确排除
桌面级 Computer Use、GUI Harness 视觉 pipeline、权限卡片新 UI、永久 origin grant、tab lease、多窗口路由重构、Windows、OS keychain/keyring、浏览器 profile 迁移均不属于任务 1。
Full gate manifest
python -m pytest -q tests/unit/test_browser_agent.py tests/unit/test_browser_tool.py tests/unit/test_webtab_control.pypython -m pytest -q tests/unit/test_session_config_tools_intent.py tests/unit/test_tool_expansion_deterministic.py tests/agentic_programming/test_self_recursion_guard.pypython -m tools.docs_site.checklinksgit diff --check
安装版 E2E 验证
测试对象:/Applications/OpenProgram.app 0.6.1。测试没有用 Electron 源码启动;桌面进程和 18101 worker 均来自应用包,worker Python 为 Contents/Resources/runtime/python/cpython-3.12.10-macos-aarch64-none/bin/python3.12。
隔离方式:使用 profile browser-agent-installed-20260814 和端口 18101,避免影响同时运行的其他 OpenProgram worker。模型配置来自该 profile 的本地副本。
| 场景 | 运行证据 | 结论 |
|---|---|---|
| DOM-first 表单 | Session local_38e090f085;输入 browser-agent-installed-final,点击 pushState,url_contains ?p=1 通过;2 次页面写动作,0 次 screenshot,0 个 tool error。 | PASS |
| 单图视觉输入 | Session local_7a8021f999;tool trace 为 observe → screenshot → verify;恰好 1 次 screenshot,返回 ImageContent 与 mime_type='image/png',无 validation error。 | PASS |
| 模型原生 vision 判断 | 模型基于该 screenshot 判断当前 viewport 含浅色紫色渐变区域。该项是模型语义判断,不是 DOM assertion。 | 已获得视觉结果 |
| 确定性完成判定 | 同一视觉 session 的 title_contains Desktop Transfer Acceptance 返回 passed=true,Runtime 因此输出 status=succeeded、reason_code=verified。该 assertion 只验证标题,不单独证明渐变判断正确。 | PASS,证据范围受限 |
安装版缺陷闭环
| 缺陷 | 修复 | 验证 |
|---|---|---|
ToolReturn 用 media_type 构造 provider 图片,截图调用触发缺少 mime_type 的 Pydantic validation error。 | 3c850a91 改为 provider 类型要求的 mime_type;screenshot 未传 frame ID 时复用最新 observation,并继续限制同一 frame 只截图一次。 | Browser/tool runtime 相关测试 74 passed;安装版视觉 trace 中 PNG image block 成功到达模型。 |
自动检测到 provider.json 提供的 minimax-cn-coding-plan 后,create_runtime() 仍直接索引六项内置表,抛出 KeyError。 | 2acf630b 将动态 provider 路由到通用 API Runtime,并规范化带 provider 前缀的 model。 | Provider routing 6 passed;安装版 session 成功创建 minimax-cn-coding-plan:MiniMax-M3 Runtime。 |
| 桌面内嵌 runtime 只安装基础 wheel,没有 Playwright Python 包,CDP session 无法创建。 | 334d0abc 让桌面 runtime 安装 wheel 的 [browser] extra,并在构建时导入检查 playwright.sync_api;不下载 Playwright Chromium。 | 发布回归测试、Bash 语法和 Ruff 通过;安装包内嵌 Python 导入通过;DOM 与视觉 E2E 均通过。 |
本地 macOS 构建未签名。依赖安装同时报告 Web 依赖 8 个 high severity、Desktop 依赖 2 个 moderate 与 5 个 high severity;本任务未执行会改写依赖树的 npm audit fix。
任务账本
| 项目 | 证据 | 状态 |
|---|---|---|
| Base commit | 717d4e17 | 记录完成 |
| RED | python -m pytest -q tests/unit/test_browser_agent.py:9 failed,缺失公开模块与全部约束。 | 记录完成 |
| GREEN / affected | Focused browser/browser-control group:51 passed;registry/tool-selection group:25 passed。 | 通过 |
| Specification review | 独立只读 review 对实现提交 37b2c37c 逐项核对 8 条行为契约与安全边界;zero remaining findings。 | PASS |
| Quality review | 首轮 CHANGES_REQUIRED 的取消、URL scheme、cleanup 三项已由 af33c608 修复。Fresh review 对候选 d0996f7b 复核全部 changed boundary,确认此前 KeyboardInterrupt 结论为误判;zero remaining findings。 | PASS |
| Full gate | Reviewed candidate:browser/browser-control 58 passed;registry/tool-selection 25 passed;Ruff passed;docs 0 broken links;diff check passed。 | 通过 |
任务 2:Turn-scoped Surface Awareness 与绑定式 Web Use
实现范围:chat turn 自动携带当前 split web surface;模型首轮上下文包含有界 DOM/ARIA preview;仅在有效 surface 存在时提供 web_use;读取和动作固定到 originating WebSocket 的 window_id + tab_id + target_id。
前台要求:没有。Electron 直接读取绑定 WebContents 并返回其 CDP target;activateView 不调用 BrowserWindow.focus() 或其他 OS focus API。目标 pane 不需要拥有键盘焦点,普通 DOM/ARIA action 不使用桌面坐标和 screenshot。
运行对象:默认 profile ~/.openprogram、端口 18100、/Applications/OpenProgram.app。没有从 Electron 源码启动第二个桌面进程或第二个可见 worker。
任务 2 实现分层
| 步骤 | 实现 | 边界 |
|---|---|---|
| 1. Turn surface reference | composer 从当前 compound group 生成 version/window/tab/region/access/focused/title/url 引用,并随 chat command 提交;region 按实际 pane 顺序区分 left、right 与 center,surface chip 显示当前绑定目标和位置。 | 关闭访问时只保留 disabled descriptor,不提供 preview 或执行工具。 |
| 2. Exact preview | 服务端只向发起 chat 的 WebSocket 请求 preview,并校验 exact window/tab/target;Electron 从当前 viewport 的 DOM、ARIA landmarks、title 与 URL 生成结果。 | 文本最多 2,000 字符,landmark 最多 12 项且 name 最多 160 字符;URL 只保留 origin,不包含 query value;不发送 screenshot。 |
| 3. Model context and tool schema | dispatcher 在首个模型调用前注入 Surface Context。web_use 是 resident tool,但仅在 surface binding 有效时进入 provider tool array;没有 surface 时主动移除。 | 模型不能提交 window/tab/CDP target,只能使用当前 turn 的 surface alias。 |
| 4. Bound execution | binding registry 保存 originating WebSocket、window、tab、target 与 expiry;subprocess bridge 只允许 exact binding 的 activate。Browser Agent 继续使用 DOM/ARIA refs 和 post-action observation。 | 不使用 OS 输入、桌面坐标、app window focus 或默认 active tab;binding 缺失、过期或 identity 不匹配时失败。 |
| 5. Approval and verification | 用户发送带 exact surface 的 turn 后,外层 web_use 不请求第二次通用 approval;hard constraints、authority 和显式 deny/ask rules仍先执行。Plan mode 不提供 web_use。父 turn 的 permission rules 以纯数据快照传入 agentic 子进程;内部 browser_page 只在该绑定调用期间使用 scoped bypass,结束后恢复。Runtime assertion 决定终态。 | 高风险 action 规则仍可 ask/deny;写动作继续要求新鲜 DOM frame。动态页面的 verification 读取同一 bound target 的当前 DOM,不因无关 mutation 永久 stale。 |
| 6. Cleanup ownership | chat query 从 surface capture 开始进入 try/finally,直接 owner 无条件幂等释放 binding;正常 dispatcher teardown 也执行相同释放。 | prepare_turn、TurnBindings.bind 或 provider 初始化在 context 建立前失败时,binding 不继续持有 originating WebSocket。 |
任务 2 安装版验收
| 场景 | 证据 | 结论 |
|---|---|---|
| 首轮页面感知 | 安装版 chat command 包含 exact surface;服务端向同一 originating WebSocket 发出 preview,provider 在首个回复前获得 Bilibili title、origin、DOM excerpt、ARIA landmarks 和 web_use schema。 | PASS,无 screenshot |
| 绑定页面点击 | Session local_340bc50ccd2c4eafb1fc12378e0489ab;模型调用 web_use,内部以 DOM ref 点击首页导航“番剧”。命令记录同时包含 exact window/tab 的 preview 和 activate。 | PASS |
| 确定性结果 | 目标变为 https://www.bilibili.com/anime/?spm_id_from=333.1007.0.0;title_contains=番剧 在 frame_6_a628e0d2 返回 passed=true。外层工具结果为 status=succeeded、reason_code=verified。 | PASS |
| 窗口状态不参与执行 | test_web_use_background_app.py 自行创建临时 Page 后立即切回原 tab,使目标 Page 成为 visible=false 的后台 WebContents。随后执行 list_pages → observe → viewport screenshot → DOM ref click → observe → verify → close;每个 Agent 动作后都要求原 tab 仍然可见。截图由 exact Page 的 CDP session 直接生成;Web Use 不读取系统屏幕,也不查询或改变系统窗口的层级、位置、遮挡、最小化或置顶状态,不调用 browser.close()、bringToFront()、窗口 focus、整屏截图或 OS input。 | 独立后台 Page 自动化 E2E |
任务 2 验证命令
python -m pytest -q tests/unit/agent/test_web_use_surface.py tests/unit/context/test_tool_defer.py tests/unit/security/test_permission_rules.py tests/component/programs/test_browser_agent.py tests/component/programs/test_web_use_runtime.py tests/component/programs/test_web_use_backend_threading.py tests/component/agent/test_process_runner_webtab_bridge.py tests/component/agent/test_dispatcher_tools.py tests/unit/security/test_process_runner_sandbox.py:199 passed。./web/node_modules/.bin/tsc --noEmit -p web/tsconfig.jsonnpm --prefix web run buildnode desktop/scripts/check-webtab-navigation.jsnode web/scripts/check-web-split.mjsOPENPROGRAM_TEST_LIVE=1 OPENPROGRAM_TEST_REAL_HOME=1 python -m pytest -q -m live tests/live/app/test_web_use_background_app.py:独立安装版后台 Page E2E;使用默认安装版 profile,自行构造后台 Page,不要求改变桌面窗口状态。python -m tools.docs_site.checklinks:当前仅报告未修改的chat-turn-visual-spec.raw.html中 4 个既有源码相对链接;本任务涉及页面没有新增失效链接。git diff --check
任务 2 当前范围与剩余项
当前实现支持 turn-scoped exact Page binding、server-owned connection/Page/access monotonic revision、renderer-owned monotonic geometry revision、基于 Page revision canonical key 的 WebSession 排他 lease,以及显式 screenshot 的单张当前 viewport 原生视觉输入。session 内 action、verify、observe 与 close 串行执行;首次 observe 以及后续每次 observe、act 和 verify 都在 backend 前重新验证 exact binding。Page capability 保存 page/access/geometry revision,agentic 子进程把期望值经父子进程 bridge 传回父 worker;父 worker 比较 Page/access revision,exact renderer 在 native preview/activate 前以及异步完成后复核应用内 pane 状态与 geometry revision。任一不一致即返回 page_context_stale,不进入 backend;异步完成后的过期结果不包含 preview 或 target。pane bounds 或应用内可见性变化只使旧 WebSession 失效,不重建 Page identity;后台 Page 通过 resolve 直接取得 exact target。macOS 窗口层级、遮挡、位置和最小化状态不进入 binding 或 screenshot 判断。close、首次 observe 失败、owner disconnect 或进程清理完成前 lease 不会提前释放。target replacement 会撤销旧 Page identity;owner WebSocket disconnect 会立即撤销该连接的全部 binding 并唤醒 pending exact-socket request。两个 connection、48 个 binding 的 component 并发验证确认命令只发送到 originating connection,断开其中一个不影响另一个。安装版双窗口 transfer/rollback、截图 artifact 临时保留策略与三个 backend 的统一 parity suite 已完成。专用 permission card 属于 UI 后续项,不在本次仅实现功能的范围内。
任务 2 审查记录
| 审查 | 发现与处理 | 结论 |
|---|---|---|
| Specification review | 首轮发现目标设计仍保留旧的“Surface Awareness 未实现”和“完整 registry 完成前不得向 provider 注入”表述。已改为当前 turn-scoped baseline 与后续完整架构分别记录;复核未发现新矛盾。 | PASS,zero findings |
| Quality review | 复核确认跨进程 revision 字段完整传递,并发现自定义一参数 binding_validator 的兼容回归。Runtime 现在只对默认生产 validator 传 revision 关键字,自定义 validator 继续使用原一参数契约;legacy 与 revision-aware 路径均有回归测试。 | PASS,zero findings |
| Geometry specification review | 对 47fad4a5、33dd8f75、d77a17c3、9c826f0c、4ac96a21 与 2b3dda2e 复核首次 observe、二次 attach、preview/activate Promise、revision 0 与真实 hide 生命周期;最终未发现剩余规格偏差。 | PASS |
| Geometry quality review | 独立复核先后复现激活期间 geometry 变化、首次 observe 缺少校验、preview 缓存旧 revision、revision 0 兼容偏差与应用内 pane 可见性误判;对应回归全部加入后 fresh review 通过。 | PASS |
| 视觉 artifact review | 截图只进入紧邻的一次 provider request;Runtime/DAG 文本仅保留 frame、viewport 与已附图标记。正常返回、provider error、timeout 与 cancel 都清除原始 image block、ToolReturn.images 和坐标权限。 | Specification 与 Quality 均 PASS |
任务 3:统一 command API 与三个 backend
| 交付 | 直接证据 | 状态 |
|---|---|---|
| 统一入口 | web_use(list_pages / observe / act / verify / close);OpenProgram MCP 同名第一方工具。 | 完成 |
| Session selector | observe 选择 playwright_mcp、chrome_devtools_mcp 或 open_claude_chrome;当前 session 禁止切换和自动 fallback。 | 完成 |
| Exact Page | Playwright MCP 通过官方 createConnection(contextGetter) 获得只含 exact target 的 BrowserContext 视图;Chrome DevTools MCP 使用一次性 marker 解析 pageId。Runtime 在首次 observe 及后续每次 observe、act 和 verify 前重新验证原绑定 target 的可见性、identity 与 Page/access/geometry revision;controller 的 app attach 继续携带同一 revision。revision、identity 或真实可见性变化时先清理 session,不进入 backend。三个 backend 均不选择或置前 tab。 | component 通过 |
| Direct MCP | 单一桌面控制连接时可获取当前 in-app Page;多个连接直接拒绝,不随机选择窗口。 | component 通过 |
| Backend parity | 真实 OfficialMCPPageBackend 与 ControllerBackend adapter 通过公共 WebUseSessionRegistry.execute() 运行同一矩阵;覆盖 observe、7 个 allowlisted action、stale/unsupported、backend error、内建及 Playwright timeout、verify、PNG screenshot 与 close。每个写动作只到达所选 backend 一次,失败不触发 fallback。 | Specification 与 Quality 均 PASS |
| 验证 | Surface、permission、跨进程 bridge、Backend parity、Runtime、threading、Browser Agent、MCP contract 与 route 相关测试 312 passed;完整 Web check、TypeScript、生产 build、WebTab navigation/zoom 与安装版 transfer client 检查通过。 | 通过 |
| 安装版 | ba665053 已刷新到 /Applications/OpenProgram.app,只使用默认 ~/.openprogram 与 18100 worker。三个 backend 依次绑定同一当前可见内置 Page,完成 list_pages → observe → scroll → observe → text_contains verify → close;每条路径只执行一次写动作并返回 passed=true。三个 backend 又各自返回恰好一张带 viewport 元数据的有效 PNG,验收过程不保存图片。真实双窗口 transfer/rollback 同时确认目标 renderer 已 stage、源状态未变化、目标窗口销毁且存储无残留。 | PASS |
任务 4:浏览器多 Page 与 popup handoff
Base:54c466e9。范围:当前 OpenProgram window 的 web Page inventory、background exact target、popup opener 归属,以及 browser_agent/gui_agent 的显式 Page 切换。
生产文件:desktop/main.js、desktop/preload.js、web/lib/desktop-bridge.ts、web/lib/state/center-tabs-store.ts、openprogram/webui/ws_actions/webtab.py、openprogram/agent/surface_context.py、agentic_functions/browser_agent/__init__.py。排除:桌面软件控制、跨窗口 inventory、OCR/YOLO/memory、自动 backend fallback。
RED:同窗口 A/B/popup C inventory;C 保存 opener=A;token 绑定 exact target;background B observe/act 不改变 visible/active/focus;GUI Agent 写动作后发现 C 并以 token 切换;没有已挂载 native Page 时返回空 inventory;close/target replacement/disconnect 撤销能力。Gate:相关 Python tests、desktop navigation check、Web split/compound checks、TypeScript、生产 Web build、docs build/links、安装版 18100 E2E、diff/status。
| 状态 | 证据 |
|---|---|
| IMPLEMENTED · INSTALLED E2E PASS | fe35dddf 实现同窗口 Page inventory、background exact binding、popup opener 与 GUI Agent 显式切换;67a65e2a 让 inventory 从 native WebContents 读取实时 URL/title,后台导航后不再返回旧 tab metadata;没有已挂载 native Page 时返回 ok: true, pages: [],不再转换成 HTTP 500。 |
| 自动验证 | Browser Agent、Web Use Runtime、backend parity/threading、Page binding 与 HTTP route 相关测试 123 passed;WebTab navigation、Web split/compound、TypeScript 与生产 Web build 通过。行为测试确认 resolve/inspect background Page 不调用 show、focus 或 bringToFront()。 |
| 安装版验证 | 只使用默认 ~/.openprogram、18100 与 /Applications/OpenProgram.app。inventory 同时返回前台 Grammarly 与后台 Example;open_claude_chrome 在后台 Example 上执行 observe → click Learn more → observe → close,真实 Page 进入 IANA,前台始终保持 Grammarly;下一次 inventory 实时返回后台 Example Domains / https://www.iana.org。旧安装包已删除。 |
| GROUP-AWARE INVENTORY · INSTALLED E2E PASS | browserPageInventory() 与 list_pages 现在返回 tab_entries + pages、active/focused identity、pane placement 和单调 inventory_revision。pane 顺序跟随实际 visibleIds;Page capability 独立释放,关闭一个 session 不影响同一 inventory 中的其他 Page。自动测试覆盖 3 个 tab entry、4 个 Page、成员重排、并发 revision 和 sibling session 生命周期;安装版在真实 split entry 的 left Page 完成 list_pages → observe → click → observe → restore → close,点击 Example 的 Learn more 后进入 IANA,再恢复原页。 |
| 保留范围 | 跨窗口 inventory 已在任务 5 实现。桌面软件控制、OCR/YOLO/memory 与自动 backend fallback 不属于 Web Use。popup opener、token handoff 与 stale/close 撤销已有 component 覆盖,尚未增加公开网站 popup 的安装版 fixture。 |
任务 5:跨窗口 Page inventory
范围:登记每个 Desktop renderer 的 window_id,让 list_pages 聚合所有已登记窗口,同时保留原 connection/window/tab/target binding。截图继续直接捕获 exact Page 的当前 viewport,不置前窗口,不读取桌面画面。
兼容:保留现有顶层 primary-window 字段;新增 windows[] 与 Page 级 window_id。不增加配置 ID、权限 UI、OCR、桌面控制或自动 backend fallback。
| 状态 | 证据 |
|---|---|
| IMPLEMENTED · INSTALLED E2E PASS | d2e9baa2 定义跨窗口数据模型;348e07f3 实现 Desktop window_id 登记和聚合;67e6ed09 以 window_id + tab_id 标记 GUI Agent 当前 Page;833c2314、1699fb03 保持窗口独立生命周期和 primary fail-closed;26c662e9、d4c4337e 以 connection revision CAS 拒绝断线后的延迟 binding。 |
| 自动验证与复核 | Browser Agent、Web Use Runtime、Page surface 和 process bridge 相关测试 123 passed;Ruff、Web split/compound/WS action、TypeScript 与生产 Web build 通过。Specification 与 Quality 独立复核均为 PASS,覆盖未登记客户端、跨窗口同名 tab_id、origin disconnect/timeout、materialization race 和 direct preview/active late result。 |
| 安装版验证 | 只使用默认 ~/.openprogram、18100 与当前主分支重新生成的 /Applications/OpenProgram.app。真实 list_pages 返回 main 和 detached window 两个 snapshot;选择 detached window 的 Microsoft Edge Add-ons Page 执行 observe → screenshot → close,得到一张 exact Page 的 image/png 当前 viewport。执行路径没有窗口 focus、bringToFront()、整屏截图或 OS input。 |
任务 6:公开名称与边界迁移
公开能力:Agent registry、GUI Agent Harness、OpenProgram MCP 与 canonical HTTP API 统一使用 web_use 和 web_session_id;模型工具列表不再公开 computer_use。
兼容边界:/api/computer-use 与旧请求字段 computer_session_id 只作为隐藏 HTTP 兼容入口保留,映射到同一个 Web Use Runtime,且不出现在 OpenAPI、Agent 或 MCP 工具列表中。
未来边界:Computer Use 名称只保留给未来桌面应用、应用窗口或整屏截图及 OS 输入能力;本次不增加桌面 adapter、配置或后台进程。
| 交付 | 直接证据 | 状态 |
|---|---|---|
| Runtime 与 session | web_use_runtime.py、WebUseSessionRegistry、web_session_id;三个 browser backend 和 exact Page 生命周期保持不变。 | 完成 |
| Agent / GUI Harness | Chat Agent 可直接调用 web_use;gui_agent 通过同一 Web Use adapter 使用相同命令和 session contract。 | 完成 |
| MCP / HTTP | MCP tools/list 与 tools/call 只公开 web_use;canonical route 为 /api/web-use。 | 完成 |
| 取消与连接清理 | 3a2e6baf 在 MCP 调用取消后关闭延迟返回的 WebSession;cbc24778 精确撤销取消的 list_pages 所签发且未消费的 Page capability,不清理同 owner 的其他 session 或 capability。 | 完成 |
| 自动验证与复核 | test_web_use_runtime.py、test_web_use_backend_parity.py、test_web_use_backend_threading.py、test_web_use_surface.py、test_web_use_route.py 与 MCP/Agent 相关组共 453 passed;Specification 与 Quality 独立复核均为 PASS。 | 通过 |
| 当前安装版 | 使用默认 ~/.openprogram、18100 和 /Applications/OpenProgram.app 验证:Agent registry 只返回 web_use;OpenAPI 公开 /api/web-use,隐藏 legacy /api/computer-use 与内部 capability release route;真实 list_pages 成功返回一个 window snapshot。验收时没有已登记 Page,因此本轮没有执行 observe 或网页动作,也没有为验收切换前台窗口。 | API PASS · PAGE E2E NOT RUN |