# Agent-Employee RPA 迁入指南 V2(基于双侧真实源码核查) > 文档性质:对 `docs/rpa-core-migration-guide.md`(V1)的全面修订版。 > 核查基线:2026-11-06,双侧**真实工作区源码**(非快照 ZIP、非审查报告转述)—— > RPA 侧 `D:/code/PRA-only-demo`(main,工作区干净)、宿主侧 `D:/code/Agent-Employee`。 > 与 V1 的逐条差异及审查报告修正记录见 `docs/rpa-core-migration-guide-v2-diff.md`。 > 状态标记约定:**已实现**(代码在库)/ **部分实现** / **仅契约**(有类型无实现)/ **设计中** / **未实现** / **待确认**(不允许猜测)。 --- ## 0. V2 核心结论(先读这个) 1. **宿主底座已大变,V1 的"空壳契约"叙事大部分失效。** V1 说对面 7 个契约包每个只有 1-9 个声明文件、windows-runner 是 0 源文件空壳。实测(2026-11-06):7 个包中 5 个已有实质实现(workflow-engine 25 文件、capability-gateway 321 行、browser-plugin 已接 Playwright、windows-plugin 新增原生观察适配器、runtime-governance 有 readiness 投影),windows-runner 有真实 C# 原生实现(.NET 10 + FlaUI UIA3,observe-only)。**仍无实现的只剩两处:computer-control 的 Runner、windows-plugin 的 WindowsRunner.click/type。** → 迁入的本质从 V1 的"拿实现去填契约"变为**"接底座 + 给已有实现让路"**:不重复造 workflow 状态机、不重复造 Playwright 浏览器、不重复造 UIA 观察。 2. **RPA 侧此轮整改完成了一部分**:平台标记单一源(PLATFORM_GROUPS 34 域 + 守卫测试)、驱动按平台自动选择(platform_unsupported)、catalog platformTag 687 项首次生效、5 个真桌面测试补平台守卫、`driver/platform.ts` 收拢。**但接入前 P0 大部分未解决**:`createEngine()` 仍无注入参数、Registry 仍是进程级全局、超时不中止底层操作、取消被标为 failed、5 处动态 `import("electron")` 残留、包依赖缺 3 项。 3. **迁入位置与名称维持 V1 结论**:`code/backend/packages/rpa-core` → `@agent-worker/rpa-core`,backend workspace(bun@1.4.3,workspaces 含 `packages/*`)放进去即生效,backend 全家统一 `@agent-worker/*` 前缀、`workspace:*` 源码消费。 4. **两条硬边界不变且加严**(用户红线): - 所有带副作用的能力必须经 capability-gateway(授权→租约→幂等→执行→审计),**不得绕行**; - rpa-core **不得依赖 Electron 主进程**(当前仍有 5 处动态 import,是接入阻塞项)。 5. **6 项 ADR 全部拍板(2026-11-06)**,仅剩 2 个小问题(Q1/Q2)需对面口头确认,详见 §10。已定基调: - **R3 桌面执行**:C# 路线——五域执行逻辑移植进 windows-runner 原生进程,PowerShell 通道仅限本 demo。 - **R6 部署拓扑**:按能力域拆分——纯 Node 域进 backend plugin-worker,桌面/视觉/弹窗域装用户电脑 Electron 宿主,同一包按分组加载。 - **R1 能力清单**:全局一份,权限隔离全交对面网关按租户管。 - **R4 浏览器**:按场景分工——RPA 场景用咱们 CDP 接管(复用登录态/真实页面),对面 Playwright 留给 AI 智能体;白名单与证据共用对面一套。 - **R5 消费方式**:源码 git subtree 并入对面仓库统一编译,Bun 锁 1.4.3。 --- ## 1. 核查方法与证据基线 - 双侧源码逐文件核查(两个独立探查通道 + 关键点人工复核),关键结论均带 `文件:行号` 证据。 - 实测过的事实:`import("electron")` 逃过 check-deps 正则(构造用例 0 匹配);catalog.json platformTag 分布(null=326 / win32=687 / 数字 1=3);capabilityCount()=719;对面 capability-gateway 租约 TTL=60s、幂等表上限 4096。 - 未验证(不写"通过"):Windows 实机 E2E、Bun 环境 test、对面真实链路联调。 - 审查报告(`docs/RPA-Review-Full.md`)与真实源码不一致处,以源码为准并记录修正理由(见 diff 文档第 2 节)。 --- ## 2. RPA 侧现状事实清单(2026-11-06 实测) | # | 事项 | 状态 | 证据 | |---|---|---|---| | 1 | Driver 惰性 getter + 非 win32 抛 `platform_unsupported` | 已实现 | engine.ts:47-61;error-codes.ts:43;engine-driver.test.ts | | 2 | **Driver 可注入** | **未实现** | `createEngine()` 无参数(engine.ts:64-66);desktop.ts:9 等在模块加载时捕获 `defaultEngine.driver` | | 3 | Registry 全局 Map、last-wins、runtime 读全局 getHandler | 属实(未改) | registry.ts:36-45;runtime.ts:260 | | 4 | PLATFORM_GROUPS 单一源(34 域全 win32)+ buildDomainPlatformMap 真实实现 + 守卫测试 | 已实现 | register-all.ts:16-50,98-127;platform-groups.test.ts | | 5 | withTimeout 监听 signal 但无 AbortController——超时不中止底层 | 属实(未修) | runtime.ts:33-56 | | 6 | NodeState 类型含 cancelled,但 executeNode catch 把取消标成 failed | 属实(未修) | types.ts:142;runtime.ts:334-339 | | 7 | 重试上限 100、黑名单式 isRetryable | 属实(未修) | runtime.ts:58-60,276 | | 8 | Graph Validator | 未实现 | 全仓无 validateFlowGraph | | 9 | 动态 `import("electron")` 5 处(vision.ts×3、cv-vision.ts×2) | 属实(未修) | vision.ts:18,66,432;cv-vision.ts:51,213 | | 10 | check-deps.mjs 对 `import("electron")` 零匹配(盲区实测) | 属实 | check-deps.mjs:20 正则要求 `import\s+` | | 11 | 包依赖缺 3 项:@napi-rs/canvas、pdfjs-dist、@cantoo/pdf-lib | 属实(未修) | rpa-core/package.json:17-32 对比 pdf.ts/vision.ts import | | 12 | main/exports 直指 src 源码、private | 属实(决策项) | rpa-core/package.json:4-11 | | 13 | rpa-cli 副作用全量 import + 全局 getHandler | 属实(未改) | scripts/rpa-cli.ts:25,53-59 | | 14 | CDP transport 单命令无超时/无 AbortSignal/pending 仅断连清理 | 属实(未修) | transport.ts:96-118 | | 15 | 两段式元素定位(当前页优先,失败才跟前台)| 已实现 | session.ts:296-307,518-523 | | 16 | locate() 不支持 xpath / Shadow DOM(与 withElement() 不一致)| 属实(未修) | session.ts:465-517 对比 252-287 | | 17 | HostBridge/SubflowSource 模块级单例 | 属实(未改) | host-bridge.ts:16-24,61-69 | | 18 | AI ChatCompletionOptions 无 signal 参数 | 属实(未修) | ai-service.ts:39-48 | | 19 | 桌面拾取无 AbortSignal(热键+轮询+deadline 自有机制)| 属实(未修) | desktop-pick.ts 全文零 signal 命中 | | 20 | catalog platformTag:win32=687 / null=326 / **数字 1=3(脏值未清洗)** | 部分实现 | build-catalog.mjs:245-246 对 truthy 旧值透传 | | 21 | catalog overrides(fields/removeFields/addFields) | 已实现 | catalog-overrides.mjs:6-24 | | 22 | 能力 719 个 / 目录组件 1016(vendor 997 + native 16 + trigger 3)/ fields 4299 / 34 域 | 实测 | platform-groups.test.ts;catalog.json counts | | 23 | 平台守卫测试 5 文件 + driver/platform.ts 唯一入口 | 已实现 | capabilities/*.test.ts;driver/platform.ts | | 24 | Driver 五域方法均无 AbortSignal 参数 | 属实(未修) | driver/types.ts:87-119 | --- ## 3. 宿主侧(Agent-Employee)现状事实清单 | 契约包/服务 | V1 描述 | 2026-11-06 实测 | 状态 | |---|---|---|---| | workflow-engine | 9 个声明文件,空壳 | **25 文件完整实现**:WorkflowEngine 接口(create/start/beginStep/executeStep(runner)/completeStep/pause/resume/cancel/requestApproval/decideApproval)、状态机迁移表、Memory+PostgreSQL 双存储、recovery、REST API、worker(并发上限/取消/排空) | 已实现 | | capability-gateway | 空壳契约 | **321 行完整实现**:`authorize(ref, subjectId, policy) → CapabilityLease`(TTL 60s)、`execute(lease, runner)`、幂等键预占/结算(上限 4096)、高影响审批精确 actionId 放行、结果 leaseId/actionId 回显校验 | 已实现 | | browser-plugin | 纯契约 | **已接 playwright-core ^1.64.1**:PlaywrightBrowserRunner 358 行(navigate/click/type/snapshot),域名白名单三重复检(导航前/落点后/动作前),证据 SHA-256 落盘;定位仅 css/aria/text(无 xpath) | 已实现 | | windows-plugin | 纯契约 | 契约 + **新增 native-observer.ts(292 行受信宿主适配器)**:spawn C# 观察进程、证据 realpath/SHA-256/PNG 魔数校验;`WindowsRunner{click;type;readText;snapshot}` 接口仍无实现;manifest `rpa.windows`:type=highImpact,全部 idempotencyRequired | 部分实现 | | computer-control | 纯契约 | **未变**:纯类型 + 3 纯函数(selectPreferredTarget 降级链、assertComputerActionAllowed、assertComputerResultEvidence);5 种 target kind、6 种 action、CoordinateSpace(DPI/缩放契约已就绪) | 仅契约 | | runtime-governance | 空壳 | readiness 投影实现(readiness.ts 117 行),无插件生命周期契约 | 部分实现 | | plugin-contract | 纯类型 | 类型底座 + `assertPluginManifest` 校验实现;**PermissionScope 13 项**(browser.domain/storage、desktop.window/input/process、filesystem.workspace/download、network.http、office.document、messaging.send/read、media.generate、monitoring.capture);CapabilityLease/ActionResult/CapabilityRef(`pluginId:capabilityId`) | 部分实现 | | services/windows-runner | 0 源文件空壳 | **17 文件真实 C# 实现**(.NET 10 + FlaUI UIA3 + PrintWindow,stdin/stdout JSON 协议,**只认 observe**,click/type 未实现);TS 宿主适配器校验证据 | 部分实现(观察半边) | | plugin-registry / plugin-worker | (V1 未提) | registry=清单登记+版本链校验(无动态 loader);plugin-worker=常驻执行进程,PG LISTEN/NOTIFY 认领 workflow/session 动作、租约续期、跨进程取消传播、崩溃接管→unknown。**这就是对面当前的插件宿主** | 已实现 | | model-gateway | (V1 未提) | 21 文件实现包:ModelGateway.stream 流式调用 + ModelControlPlane(每次物理调用向 Java 控制面重新授权,短授权 60s) | 已实现 | | Java 控制面 | (V1 未提) | `code/backend/control-plane/`:Spring Boot 4.1.1 / Java 21 / 454 个 Java 文件 / 9 Maven 模块;与 TS 面经 OpenAPI + Outbox + 短授权 grant 通信;端口 8887(Java)/8881(Admin)/8880(TS 执行面) | 已实现 | | frontend/apps/desktop | Electron+SolidJS | 确认。**无 RPA 宿主桥**,但有等价物:identity-login-window(弹窗)、execution-context.ts(grant 桥)、zoom.ts(缩放);DPI/坐标契约在 computer-control CoordinateSpace 与 C# Protocol.cs | 部分实现 | 对面安全模型要点(直接影响 RPA 桌面路线):windows-plugin 策略校验只允许 `*.exe` 进程名、不允许路径;native-observer.ts 设计约束明言"不执行任意 PowerShell";桌面交互 Runner 留宿主、不进 Linux 容器。 --- ## 4. 原指南(V1)内容分类 | V1 内容 | 分类 | 处理 | |---|---|---| | 包现状描述(719 能力、34 域、宿主桥 4 方法、Driver 五域) | **保留**(微调) | 仍准确;宿主桥维持 4 方法不变 | | "完全不依赖 Electron、check:deps 天天检查" | **过时/不实** | 5 处动态 import 逃过护栏;改为"静态依赖已清、动态残留待清",护栏必须升级 | | 第 -1 步对面契约包全部空壳的叙事 | **过时** | 按 §3 改写:5/7 已实现,"填契约"变"接底座" | | 第 0 步三件作业(bun 冒烟 / catalog 重生成 / 注册方式决策) | **部分保留** | catalog 重生成已完成(platformTag 687 生效,3 个脏值待清洗);bun 冒烟仍未做;注册方式决策并入 ADR-R1 | | 第 1 步搬包(git subtree → code/backend/packages/rpa-core、改名 @agent-worker/rpa-core、demo 侧不双活) | **保留** | 双侧命名与 workspace 布局核实无误 | | 第 2 步 A 类契约对齐表 | **需要修改** | capability-gateway/workflow-engine 从"对照后改对面"变"按已实现接口写 adapter";新增 plugin-contract/registry/worker 三层对接 | | 第 2 步 B 类宿主注入表(浏览器=最大变数) | **需要修改** | 浏览器变数已收敛:对面有 Playwright 实现;变数改为"双路径取舍"(ADR-R4) | | 第 3 步 7 条验收 | **需要修改** | 扩充为 §9 验收标准(加 gateway 零调用、取消传播、双 Engine 隔离等) | | 三端计划(PLATFORM_GROUPS 单一源、驱动自动选、分组核查、测试守卫、平台判断收拢) | **已完成,从"待办"改"现状"** | 五件小事全部落地;平台硬约束一节保留为长期规范 | | 附:10 个关键决策 | **大部分保留** | 决策 2"保留全局注册表"与决策 9"双入口"需按 ADR-R1 重新确认;其余不变 | --- ## 5. 接入目标架构 ```text ┌─ Agent-Employee(宿主:权威状态与治理的唯一来源)──────────────────────┐ │ │ │ Java 控制面 control-plane(:8887) ──OpenAPI/Outbox/短授权 grant──┐ │ │ │ │ │ TS 执行面 apps/api(:8880, Bun) │ │ │ ├─ workflow-engine ← Run/Step 权威状态机(PG 存储+recovery) │ │ │ ├─ capability-gateway← 授权→租约(60s)→幂等→执行→审计【唯一入口】│ │ │ ├─ plugin-registry ← 清单登记 + 版本链校验(无动态 loader) │ │ │ ├─ model-gateway ← AI 流式调用 + 每次调用控制面授权 │ │ │ └─ services/plugin-worker ← 常驻执行进程(LISTEN/NOTIFY 认领) │ │ │ ├─ browser-plugin → PlaywrightBrowserRunner(已实现) │ │ │ └─ windows-plugin → windows-runner(C# FlaUI, observe-only)│ │ │ │ │ frontend/apps/desktop(Electron+SolidJS,用户桌面宿主) │ │ │ └─ RPA 宿主桥实现落点(弹窗/DPI/AI 配置/子流程仓库) │ │ └────────────────────────────────────────────────────────────────┘ ▲ │ CapabilityRunner(gateway 包皮,唯一执行通道) │ Run/Step 事件回传(RPA 不建第二套状态) ┌─ RPA 迁入物(执行器与能力供给方)──────────────────────────────────────┐ │ @agent-worker/rpa-core(packages/rpa-core 迁入,Bun 源码消费) │ │ ├─ Flow Runtime(作为 workflow-engine 的执行引擎候选 / 步骤级 runner)│ │ ├─ 719 能力 handler(纯 Node 部分可在 plugin-worker 服务器侧跑; │ │ │ 桌面/视觉部分只能跑在用户桌面宿主进程——见 ADR-R6) │ │ ├─ WindowsDriver(补齐对面 WindowsRunner.click/type 执行缺口,ADR-R3)│ │ └─ CDP 外部浏览器会话(与 PlaywrightBrowserRunner 的取舍,ADR-R4) │ │ @agent-worker/rpa-adapter(新增薄适配层) │ │ ├─ CapabilityRunner:authorize/execute 包裹 → ref↔componentId 映射 │ │ ├─ RunResult/NodeState ↔ WorkflowStatus/StepStatus 映射表 │ │ └─ 宿主注入装配:HostBridge(4) + SubflowSource(2) + ScreenCaptureHost│ └────────────────────────────────────────────────────────────────────────┘ ``` **权责原则(沿审查报告,逐条可执行):** - workflow-engine 是 Run/Step 状态唯一权威;RPA Runtime 只回传事件,不落第二份终态。 - capability-gateway 是唯一授权入口;RPA 侧 `getHandler()` **不对 adapter 之外暴露**(rpa-cli 顺手重写以作表率)。 - computer-control 是桌面契约对齐对象;RPA 不新造并行的桌面抽象。 - 宿主服务一律注入,禁用模块级 setter 承载多会话状态(现状 HostBridge 单例是过渡,见 ADR-R1)。 --- ## 6. 模块对应关系表 | RPA 侧(packages/rpa-core) | Agent-Employee 侧 | 关系 | 现状 | |---|---|---|---| | `engine/runtime.ts` 流程执行 | `workflow-engine` WorkflowEngine/StepRun | RPA=执行算法候选,AE=权威状态 | 已拍板方案 A(ADR-R2) | | `engine/registry.ts` 全局注册表 | `plugin-registry` + `capability-gateway` CapabilityRef | ref↔componentId 映射层(rpa-adapter) | 映射待建 | | 719 能力 handler | `plugin-contract` CapabilityDefinition + PermissionScope 13 项 | 能力清单生成 + 权限映射 | 待建(脚本生成) | | `RunContext.signal` | `CapabilityExecutionContext.signal` | 均 AbortSignal,直通 | 兼容 | | `NodeState`(idle/running/succeeded/failed/skipped/cancelled) | `StepStatus`(+waiting_user/unknown/pending) | 映射表;RPA 缺 waiting_user/unknown | 需补 | | `human-dialog` 审批弹窗 | `WorkflowApprovalRequest`/decideApproval | 人审节点挂宿主 approval 流 | 需 adapter | | `driver/windows/*`(PowerShell 五域) | `windows-runner` C#(observe-only)+ `WindowsRunner{click,type}` 契约 | RPA 补执行半边;安全模型冲突 | ADR-R3 | | `browser/*` CDP 会话(BrowserLike) | `browser-plugin` PlaywrightBrowserRunner | 双路径取舍 | ADR-R4 | | `ai-service.ts` loadAiConfig | `model-gateway`(ModelGateway.stream + ModelControlPlane) | RPA AI 能力改走宿主网关 | 需改造 | | `host-bridge.ts` 4 方法 | frontend desktop main 进程(弹窗/坐标/AI 配置等价物已有) | 参考实现照抄本仓库 src/main/index.ts | 落点明确 | | `SubflowSource` 2 方法 | 对面流程存储 | 包一层 | 小 | | vision/cv-vision 截图+DPI | `computer-control` CoordinateSpace + C# PrintWindow | 宿主注入 ScreenCaptureHost | 待建 | | 运行证据/截图 | `evidence-store`(S3) + `monitoring.capture` 权限 | 证据统一落对面 | 待接 | | `check-deps.mjs` 依赖护栏 | backend 包边界 | 保留并升级(动态 import) | 需增强 | --- ## 7. 逐接入点详单 每项按固定七要素:RPA 位置 / AE 位置 / 兼容性 / 问题 / 改哪侧 / 方案 / 验收。 ### A1 Engine 与 Driver 注入 - **RPA 位置**:`packages/rpa-core/src/engine/engine.ts:47-66`(惰性 getter + `createEngine()` 无参);`capabilities/desktop.ts:9`、`common-final.ts:11`、`system-extended.ts`、`window-extended.ts`、`office.ts:15`、`ftp.ts`、`ocr-caps.ts:11` 捕获 `defaultEngine.*`(其中 desktop.ts:9 在**模块加载时**取 `.driver`,非 win32 下 import 即抛错)。 - **AE 位置**:对面不关心 driver 细节;对齐契约是 `computer-control` 的 `ComputerRunner{observe;execute}`(computer-control/src/index.ts:99-102)与 `windows-plugin` 的 `WindowsRunner`。 - **兼容性**:部分。平台错误语义(platform_unsupported)已就绪;注入面缺失。 - **问题**:宿主无法注入测试替身或 computer-control 适配器;能力文件模块级捕获引擎状态(excelHandles/ftpClient/ocrInstance/driver),多会话共享。 - **改哪侧**:RPA。 - **方案**:`createEngine(options?: { driver?, hostBridge?, subflowSource?, registry? })`,全部可选、缺省保持现行为;能力文件改为经 RunContext/engine 参数取 driver 与资源表(模块级捕获改为首用时向 engine 取);幂等句柄表(excelHandles/ftpClient/ocrInstance)迁入 engine 实例字段(部分已是)。 - **验收**:FakeDriver 注入测试覆盖五域;两个 Engine 各注入不同 FakeDriver 并行执行互不串用;非 win32 上 import 全部 34 域不抛错、调用桌面能力时才抛 platform_unsupported。 ### A2 Registry 注册机制与实例隔离 - **RPA 位置**:`engine/registry.ts:36-45`(模块级 Map、last-wins、meta 可残留旧值);`runtime.ts:260`(全局 getHandler);`register-all.ts`(34 域 DOMAINS + PLATFORM_GROUPS + buildDomainPlatformMap)。 - **AE 位置**:`plugin-registry`(清单登记+版本链,无动态 loader)、`capability-gateway` CapabilityRef(`pluginId:capabilityId` + version)。 - **兼容性**:结构性错位。对面一切能力调用都带 CapabilityRef 与版本;RPA 是字符串 id 全局表。 - **问题**:进程级注册在对面"多租户 + plugin-worker 常驻进程"模型下无法按租户隔离;componentId 与 CapabilityRef 无映射;同 id 覆盖无审计。 - **改哪侧**:短期 RPA 侧固化 ADR + 新建 adapter 映射;长期 RPA 侧 engine-scoped registry。 - **方案**:①ADR-R1 先定部署模型(单后端单能力集 → 全局表合法,把 `registerAll` 文档语义改为"加载到进程注册表",不假装实例隔离);②rpa-adapter 维护 `componentId ↔ (pluginId="rpa", capabilityId=componentId, version=catalog 版本)` 映射,由 catalog.json 生成并做完整性测试;③重复注册策略定为"显式覆盖 + 输出 warn 审计行"。 - **验收**:映射表覆盖 719 能力(或明确排除清单);gateway 侧按 ref 解析到正确 handler;重复注册产生可审计日志。 ### A3 Runtime 执行、超时、取消、重试 - **RPA 位置**:`runtime.ts:33-56`(withTimeout 只 reject 外层)、`runtime.ts:334-339`(取消标 failed)、`runtime.ts:58-60,276`(isRetryable 黑名单、retryCount≤100)、`driver/types.ts:87-119`(五域方法无 signal)。 - **AE 位置**:`workflow-engine` StepRun.attempt/leaseEpoch/idempotencyKey、`workflow-worker` 跨进程取消传播与崩溃接管→unknown、`capability-gateway` execute 的 `ctx.signal?`。 - **兼容性**:不兼容。对面以幂等键 + 租约纪元管理副作用安全;RPA 超时/取消/重试语义与它冲突。 - **问题**:超时后底层 PowerShell/HTTP/CDP 仍执行(重复副作用);取消状态不一致;非幂等能力可被重试 100 次。**这是接入的第一阻塞项。** - **改哪侧**:RPA。 - **方案**:①节点尝试创建独立 AbortController,合并 Run 级 signal 与节点 timeout,贯通 handler→driver→PowerShell 子进程/HTTP/CDP(driver 五域方法加可选 `signal` 参数);②executeNode catch 优先映射 cancelled → `state.status="cancelled"`,不走 skipOnError/error route/retry;③重试改元数据驱动:CapabilityMeta 增 `idempotent`/`sideEffect`/`retryPolicy`,非幂等默认 0 次重试;④新增 `validateFlowGraph`(ID 唯一、边合法、入口/出口基数、环、悬空边)。 - **验收**:构造 5 秒 Fake Handler + 100ms 超时,断言 handler 收到 abort 并停止、无并发重入;执行中取消后 Run 与 NodeState 均为 cancelled;对 File 写入/点击类能力验证"超时不自动重试";非法图执行前得到稳定错误码。 ### A4 Capability Gateway(能力注册与权限治理) - **RPA 位置**:`registry.ts`(handler + meta 无权限字段);`resources/catalog.json`(仅 `risk: low|high`)。 - **AE 位置**:`capability-gateway/src/index.ts:75-252`(已实现 authorize/execute/租约 60s/幂等/高影响审批);`plugin-contract` PermissionScope 13 项。 - **兼容性**:接口契合度高——`CapabilityRunner = (input, ctx{lease,capability,signal?}) => Promise`,RPA handler `(ctx, node, args, component)` 包一层即可;ActionResult 需回显 leaseId/actionId(adapter 统一填)。 - **问题**:①719 能力 ↔ 13 项 PermissionScope 无映射;②CapabilityMeta 无 sideEffect/idempotent/permission/approvalRequired 字段;③存在绕行面(rpa-cli、子流程直接 getHandler)。 - **改哪侧**:新建 adapter(AE 仓库内包)+ RPA 补元数据。 - **方案**:①rpa-adapter 实现 CapabilityRunner:gateway.execute(lease, runner) → ref→componentId → 构造 RunContext(signal 直通)→ handler → 结果包装 ActionResult;②权限映射表按 34 域 × PermissionScope 初稿生成(files→filesystem.workspace、http→network.http、desktop/windowExtended→desktop.input/window、utilityExtended→独立高影响 scope【待确认:现表无 process 执行域对应,需对面确认】、message→messaging.send);③高风险域标 highImpact 走审批(System_ExecuteCommand、键鼠、文件删除/覆盖、发消息);④meta 增治理字段(与对面 CapabilityDefinition 字段对齐)。 - **验收**:审批拒绝/租约过期/权限不在白名单时 handler **零调用**(gateway 已有测试语义,adapter 层加 719 全量冒烟:未经 authorize 不得触达 handler);审计可关联 Agent/Run/Capability/审批结果。 ### A5 Workflow Engine 执行契约 - **RPA 位置**:`engine/runtime.ts`(RunResult/NodeState)、`engine/types.ts:142`、human-dialog 审批弹窗、SubflowSource。 - **AE 位置**:`workflow-engine/src/index.ts:278-311`(WorkflowEngine 接口)、`workflow-runtime.ts`、`workflow-worker.ts`、`approval-policy.ts`;`executeStep(..., runner)` 的 runner 类型即 `Parameters[1]`。 - **兼容性**:状态映射大体可行;RPA 缺 `waiting_user`/`unknown` 两态;对面 StepStatus 无 RPA 的 `idle`。 - **问题**:两套状态权威冲突风险;集成形态二选一未定(整体作为一个 capability vs 节点级映射为 step)。 - **改哪侧**:adapter + 双侧小改。 - **方案**:**已拍板(ADR-R2)方案 A + 两补丁**——整个 RPA 流程注册为**一个** capability(`rpa.flow.execute`),workflow-engine 的一个 step 调它,RunResult→ActionResult、节点级事件→event-bus 事件流(旁路,不进权威账本)、human-dialog→requestApproval 挂对面 approval 流、取消→signal 直通。补丁 1:节点事件流保透明;补丁 2:人审/高危节点照常升级对面审批。方案 B(节点=step 1:1)的触发条件留档:仅当对面产品确认需要"逐步控制 RPA"(单步执行/任意步回退)时局部启用,届时事件流已备好数据不返工。NodeState 增 `waiting_user`/`unknown` 两态(unknown 用于崩溃恢复对齐)。 - **验收**:状态映射契约测试(含 waiting_user/unknown/cancelled 全分支);一次含审批节点、一次执行中取消、一次进程崩溃恢复的端到端演练;对面 Run 状态终态与 RPA RunResult 永远一致。 ### A6 Computer Control 与 Windows 桌面执行 - **RPA 位置**:`driver/windows/*`(PowerShell 封装五域)、`capabilities/desktop-uia.ts`、`element.ts`。 - **AE 位置**:`computer-control`(仅契约+3 纯函数)、`windows-plugin`(WindowsRunner{click;type;readText;snapshot} 无实现、native-observer.ts observe-only)、`services/windows-runner/native/*.cs`(FlaUI UIA3 observe-only)。 - **兼容性**:**安全模型冲突**——RPA 驱动 spawn 任意 PowerShell;对面白名单只许 `*.exe`、明文"不执行任意 PowerShell"、证据要求 SHA-256。 - **问题**:RPA 的执行半边(click/type)正是对面缺口,但实现方式过不了对面安全门。 - **改哪侧**:双侧(ADR-R3 已拍板:C# 扩展 actuate,见 §10)。 - **方案**:推荐——把 RPA WindowsDriver 的五域执行逻辑**移植进 windows-runner 的 C# 原生进程**( FlaUI/CGEvent 等价实现 + 现成协议加 actuate 操作),RPA 侧 driver 抽象保留、Windows 实现改为可指向"原生进程通道"或"本地 PowerShell 通道"(后者仅 demo 使用,明确标注不走宿主治理);策略校验/证据断言复用对面 `assertComputerActionAllowed`/`assertComputerResultEvidence`。 - **验收**:click/type 经策略校验(白名单进程/窗口、allowInput)+ 证据落盘;宿主拒绝时零副作用;同目标 observe→actuate→observe 闭环一致。 ### A7 浏览器(Browser Plugin vs RPA CDP 会话) - **RPA 位置**:`packages/rpa-core/src/browser/*`(transport/external,进包部分)+ `src/main/browser/session.ts`(接管/拾取,留守部分);已知缺陷:transport 单命令无超时(:96-118)、locate 不支持 xpath/Shadow DOM、evaluate 默认 follow=true。 - **AE 位置**:`browser-plugin`(PlaywrightBrowserRunner 已实现:白名单三重检、AbortSignal 透传、证据 SHA-256;定位 css/aria/text,无 xpath)。 - **兼容性**:双实现并行,语义不同(Playwright 自管浏览器 vs RPA 接管用户已开浏览器/复用登录态)。 - **问题**:重复投资;RPA CDP 链路自身有 P1 缺陷;对面定位器无 xpath(RPA 拾取器产出 xpath/css/aria/text 混合 selector)。 - **改哪侧**:ADR-R4 已拍板(按场景分工):RPA 场景走咱们 CDP 接管(主力),对面 Playwright 留给 AI 智能体场景。 - **方案**:①RPA 浏览器能力迁前先修 transport 单命令超时 + 统一 resolveElement(一次修复覆盖 locate/click/type/getText);②CDP 接管路线接对面 BrowserContextPolicy 白名单与证据体系(不自建白名单);③与对面确认 rpa.browser 插件清单承载咱们的 runner;④PlaywrightBrowserRunner 保持现状服务 AI 智能体场景,双方不重复投资。 - **验收**:同一定位用例集(css/aria/text/xpath)在咱们 CDP 路径全部通过;白名单拒绝 URL 时导航前即拦截(走对面策略对象);证据落 evidence-store。 ### A8 平台适配(Windows / Linux / macOS) - **RPA 位置**:`register-all.ts` PLATFORM_GROUPS(34 域全 win32)、`driver/platform.ts`、`engine/engine.ts:47-61`、5 个 skipIf 测试;catalog 687 win32 / 326 null / **3 个数字 1 脏值**。 - **AE 位置**:`plugin-contract` Platform 类型;windows-runner 明确"留在宿主、不进 Linux 容器"(README)。 - **兼容性**:兼容(两边都是 win32-first 务实路线)。 - **问题**:①catalog 3 个 `platformTag: 1` 脏值透传(build-catalog.mjs:246 对 truthy 不清洗);②对面 CapabilityDefinition 未见 platform 字段(**待确认**:插件清单如何表达平台限制)。 - **改哪侧**:RPA(清洗);对面(清单平台字段,待确认后)。 - **方案**:build-catalog 归一化——源值不在 `win32|darwin|linux|null` 白名单的一律重派生;三端扩展节奏沿用 V1 第三节(Linux xdotool/AT-SPI、Mac AX/CGEvent/TCC、Office 分端实现),驱动实现统一走 ADR-R3 的原生进程通道。 - **验收**:catalog 全量过 schema 校验(1016/1016);非 win32 上 Core 可加载、桌面能力明确报 platform_unsupported;Mac/Linux CI 跑纯逻辑子集。 ### A9 Electron 依赖与 Core 独立性(含包闭包) - **RPA 位置**:vision.ts:18,66,432、cv-vision.ts:51,213(动态 `import("electron")`);check-deps.mjs:20(正则盲区实测);rpa-core/package.json:17-32(缺 @napi-rs/canvas、pdfjs-dist、@cantoo/pdf-lib;main 直指 src、private)。 - **AE 位置**:backend 执行面是 Bun(无 Electron);Electron 只在 frontend/apps/desktop;截图/坐标对面等价物是 C# PrintWindow + CoordinateSpace 契约。 - **兼容性**:不兼容。视觉能力在对面 backend 进程必然失败。 - **问题**:Core 不是 Electron-free;护栏查不出动态 import;单包安装缺 3 个依赖。 - **改哪侧**:RPA。 - **方案**:①抽 `ScreenCaptureHost`/`DisplayCoordinateService` 接口并入 HostBridge 注入面(弹窗/DPI×2/AI 配置 4 方法 → 增至 6 方法,或独立 host services 包——实现期定,倾向并入 HostBridge 减少 API 面);vision/cv-vision 只依赖接口,宿主未注入时抛 `host_service_unavailable`;②check-deps 升级为覆盖 `import()`/`require()`/`createRequire()`(先补正则,中期 AST);③补齐 3 个依赖声明(pdf.js 与 canvas 为原生/大件,评估 optionalDependencies + 能力级降级);④消费方式锁定 **Bun 源码消费**(对面全家 workspace:* 源码依赖,与现状一致),锁 bun@1.4.3 做 CI 冒烟。 - **验收**:无可解析 electron 的纯净 Node/Bun 环境 Core 全量 import 成功;视觉能力未注入 Host 时返回 host_service_unavailable、注入 Fake Host 后可测;隔离目录仅按包声明装依赖跑通 PDF/OCR 代表能力。 ### A10 插件生命周期、异常隔离与资源清理 - **RPA 位置**:无插件概念;资源清理散在能力内(PowerShell 子进程、ws、FTP/OCR 句柄);历史上有 catch{} 吞错模式(已部分修复)。 - **AE 位置**:`plugin-contract` PluginManifest(apiVersion/minCoreVersion/entrypoint/rollbackVersion)+ assertPluginManifest;`plugin-registry` 版本链校验;`plugin-worker`(崩溃接管→unknown、租约续期、跨进程取消)。 - **兼容性**:RPA 需要一张插件"外壳"才能进对面宿主。 - **问题**:719 能力不可能逐个成插件;RPA 无崩溃恢复语义(对面 unknown 态)。 - **改哪侧**:adapter 为主。 - **方案**:RPA 以**单一插件**接入(manifest id 建议 `rpa.core`,能力按域分批暴露为 CapabilityDefinition 清单,随 catalog 生成);异常隔离靠节点级 try/catch + AbortSignal(A3);资源清理建统一 finally 清单(子进程 kill、ws close、临时文件删除)并纳入取消路径;崩溃恢复复用对面 workflow-recovery(NodeState.unknown 对齐)。 - **验收**:杀掉 plugin-worker 进程后 Run 转入 unknown 并可恢复;取消后无残留子进程/连接/临时文件;manifest 通过 assertPluginManifest 与 registry 版本链。 --- ## 8. 分阶段实施计划 > 原则:先 RPA 侧收口(便宜、不依赖对面),再垂直切片,再规模化。不为了架构统一搞大重构;每阶段有硬验收门。 | 阶段 | 内容 | 前置 | 验收门 | |---|---|---|---| | **0 事实确认**(双侧,1 次评审会) | 向对面同步 6 项已拍板结论(R1-R6)并预估 C# actuate 扩展量;确认 2 个小问题(Q1 platform 字段 / Q2 utilityExtended 权限归属);确认事件流接口与 rpa.browser 清单备案 | 无 | Q 有书面结论 | | **1 RPA 侧收口**(本仓库) | A3 四件(取消贯通/状态映射/重试元数据/Graph Validator)+ A1 注入参数 + A9(Electron 残留、check-deps 升级、依赖闭包)+ A2 的 ADR 固化 + catalog 脏值清洗 + rpa-cli 重写(显式注册、经 engine 取 handler) | 无 | 审查报告 §7 第一/二阶段清单全绿;纯 Node 环境 Core 全量加载 | | **2 迁入与 adapter 骨架** | git subtree 迁包改名 @agent-worker/rpa-core;bun@1.4.3 test 冒烟(exceljs/pdf/PowerShell 编码);新建 @agent-worker/rpa-adapter(CapabilityRunner + ref 映射 + 状态映射表);demo 侧冻结 | 阶段 1 + ADR-R1/R2 | bun test 纯逻辑全绿;未经 gateway 不可达 handler;719 映射完整性测试 | | **3 垂直切片** | 一个文件能力 + 一个 HTTP 能力走通:workflow-engine create/start → gateway authorize → adapter → rpa-core handler → 事件/证据回传 → cancel 中途取消;方案 A(rpa.flow.execute 整体注册) | 阶段 2 | 取消/审批/审计全链有证据;对面 Run 终态与 RunResult 一致 | | **4 浏览器与桌面双 ADR 落地** | ADR-R4(已拍板):RPA 浏览器能力修完 transport/resolver,接对面白名单与证据体系后作为 RPA 场景主力 runner;ADR-R3:windows-runner C# 扩展 actuate(RPA 五域逻辑移植) | 阶段 3 | §7-A6/A7 验收条目 | | **5 能力规模化** | 34 域按风险分批:files/data/http/ftp → office/excel/word(COM 仅 win32)→ desktop/utility 高影响(末批+审批);CapabilityDefinition 与权限映射随批生成 | 阶段 4 | 每批过 gateway 全量冒烟 + 审批矩阵抽查 | | **6 平台扩展** | V1 第三节三端计划原样生效(Linux/macOS 驱动按 ADR-R3 原生通道) | 阶段 5 | 三平台 CI 矩阵;产品按 platformTag 置灰 | **不搬的东西**(维持 V1 清单):界面渲染层、悬浮框/取色器、本地视觉 onnxruntime、流程存储、内置浏览器编排——由宿主提供或对面重做;其中"本地视觉"明确**不进 backend**(原生依赖 + 桌面截图依赖),留在宿主桌面进程。 --- ## 9. 风险清单与总验收标准 ### 风险清单 | # | 风险 | 等级 | 缓解 | |---|---|---|---| | R1 | ~~桌面安全模型冲突~~ → **已缓解(ADR-R3 拍板 C# 路线)**:残余风险转为 C# 移植工作量与工期 | 中 | 阶段 0 与对面确认 actuate 扩展量;RPA 五域逻辑先行整理成移植清单 | | R2 | ~~部署拓扑错配~~ → **已缓解(ADR-R6 拍板按域拆分)**:残余风险为宿主进程加载子集的工程实现 | 中 | 阶段 2 按 PLATFORM_GROUPS 分组做宿主子集加载验证 | | R3 | Registry 全局单例在多租户 backend 的隔离缺陷 | 高 | 短期按 ADR-R1 限定部署模型;长期 engine-scoped registry 列入 backlog | | R4 | 浏览器双路径重复投资 | 低(已缓解) | R4 已拍板按场景分工(RPA=CDP 接管,AI 智能体=Playwright),白名单与证据共用一套,无重复投资 | | R5 | 719 能力的治理映射与元数据补齐工作量失控 | 中 | 脚本从 catalog 生成初稿 + 人工只审高风险域;分批(阶段 5) | | R6 | Bun 与 Node 行为差异(exceljs/pdf-lib/PowerShell 编码) | 中 | 阶段 2 bun 冒烟前置,差异清单化 | | R7 | demo 侧与 backend 双活跃漂移 | 中 | git subtree + "迁移后 demo 冻结"纪律(V1 决策 3) | | R8 | 两套状态机语义漂移(NodeState vs StepStatus) | 中 | 映射表 + 契约测试常驻 CI | | R9 | catalog 源数据(shizai)上游已删,重生成受阻 | 低 | 已从对面历史恢复至 temp/catalog-source;计划快照入库 | | R10 | 对面底座继续快速演进,本文行号/接口过期 | 中 | 本文标注核查日期;联调前对关键接口做增量 diff | ### 总验收标准(迁移完成的定义) 1. Bun@1.4.3 下包 typecheck/test 全绿(不以 Node 测试替代)。 2. FakeDriver/Host 注入可用,双 Engine 隔离行为符合 ADR-R1。 3. 全部已暴露能力经 capability-gateway:审批拒绝/租约过期/无权限时 handler 零调用,审计四元组(Agent/Run/Capability/审批)可追踪。 4. 取消/超时/重试测试证明:超时即中止底层、取消不进 error route、非幂等零自动重试、无并发重入。 5. Graph Validator 拒绝非法流程图于执行前。 6. 纯 Node/Bun 环境(无 electron 可解析)Core 全量加载;视觉路径 Host Mock 可测。 7. 隔离目录按包声明安装依赖,代表能力(文件/Excel/HTTP/PDF)可跑。 8. 垂直切片端到端演练通过:含一次审批、一次中途取消、一次进程崩溃恢复(unknown→恢复)。 9. Windows 10/11 实机回归:UIA/浏览器/Office/DPI/多屏/安装包资源 + 取消场景。 10. catalog 1016 项全过平台 schema 校验;能力平台范围与真实实现一致。 --- ## 10. 决策与待确认清单 ### 已拍板(2026-11-06,本方负责人确认) | ADR | 问题 | 决定 | |---|---|---| | R1 | Registry 作用域:backend 是否多租户并存 | **全局一份能力清单**(菜单所有租户共用),权限隔离完全由 capability-gateway 按租户管;长期将清单挂到 engine 实例(已从对面源码确认 WorkflowIdentity 带 tenantId,但清单本身无需按租户复制) | | R3 | 桌面执行安全模型:RPA PowerShell 驱动 vs 对面"受信 C# 原生进程"红线 | **C# 扩展 actuate**:把 RPA 五域执行逻辑移植进 windows-runner 原生进程;PowerShell 通道仅限本 demo,不进宿主 | | R4 | 浏览器双路径 | **按场景分工**:RPA 场景走咱们的 CDP 接管路线(复用用户登录态/真实页面——RPA 核心价值);对面 PlaywrightBrowserRunner 留给 AI 智能体场景(无头自管浏览器)。约束:①咱们 CDP 路线必须接对面 BrowserContextPolicy 白名单与证据体系,不自建;②迁移前修完 transport 超时与定位器不统一两缺陷;③需对面在插件清单给咱们的 runner 备案(rpa.browser) | | R5 | 包消费方式 | **源码并入 + 锁版本**:git subtree 进对面仓库统一编译,Bun 锁 1.4.3(与对面全家 workspace:* 源码消费现状一致) | | R6 | 部署拓扑:rpa-core 各域跑在哪 | **按能力域拆分部署**:纯 Node 域→backend plugin-worker;桌面/视觉/弹窗域→用户电脑 Electron 宿主;同一包按 PLATFORM_GROUPS 分组加载,不维护两份代码 | | R2 | 集成形态:RPA 流程=单个 capability(方案 A)还是节点=step 映射(方案 B) | **方案 A + 两补丁**:RPA 流程=`rpa.flow.execute` 单能力,对面一个 step 一次租约一次结算;节点级事件走 event-bus 旁路(保透明、不进权威账本);人审/高危节点照常升级对面审批。**不用 B 的理由**(记录在案):双账本一致性(崩溃窗口两边分歧、破坏对面 recovery 的单账本假设)、控制流节点无副作用无法映射 CapabilityRef、审批/重试粒度与业务语义错位。**B 的触发条件**:对面产品确认需要"逐步控制 RPA"(单步执行/任意步回退)时局部启用,事件流已备好数据不返工 | ### 待对面对确认(仅剩小问题,不猜测) | Q# | 问题 | 评审要点 | |---|---|---| | Q1 | CapabilityDefinition 是否需要 platform 字段(对面清单未见) | 建议对面补字段或约定由 catalog platformTag 承载 | | Q2 | utilityExtended(命令执行)对应哪个 PermissionScope | 13 项中 desktop.process 是候选,需对面确认语义(backend 无桌面,进程执行属哪域) | > 已回答:Q3(human-dialog 弹窗落点)已由 R6 回答——用户电脑 Electron 宿主窗口;仅样式/交互细节与对面 UI 对齐。 --- ## 11. 本指南边界 - 全部结论基于 2026-11-06 双侧工作区源码静态核查 + 少量脚本实测(正则盲区、catalog 统计、capabilityCount);未执行 Windows 实机 E2E 与对面联调,未运行的测试不写成通过。 - 行号会随代码演进过期,以函数/接口名为准。 - 本轮只改文档,不改业务源码(用户指令);阶段 1 起的代码改动另行排期。