407 lines
56 KiB
Markdown
407 lines
56 KiB
Markdown
# 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 侧接入前 P0 整改已于 2026-11-06 完成(迁移阶段 1 收口)**:节点尝试级 AbortController(超时即真中止底层操作)、取消映射 cancelled 不走 error route、重试改 `idempotent` 元数据门控、图校验器执行前拒非法流程图、`createEngine(options)` 注入参数(driver/hostBridge/subflowSource/registry)、视觉能力 5 处动态 `import("electron")` 清零改走 HostBridge.screen 注入、check-deps 覆盖动态 import、catalog 脏值修复、rpa-cli 显式注册重写。★ 标记明细见 §2/§7/§8。**接入前本仓库代码活已全部完成(2026-11-06)**:①NodeState 补 `waiting_user`/`unknown` 两态 + `toStepStatus` 全量映射表(与对面 StepStatus 8 态同构,含契约测试);②A++ 事件负载字段定稿——`node.finished` 增 `checkpointId`/`resumable`/`idempotencyKey`(幂等键=runId:nodeId 跨重入稳定,非幂等能力不作为续跑锚点),契约测试覆盖。附带:补 sm-crypto 类型声明(typecheck 归零)。**对接面工作全部在对面仓库**:rpa-adapter、subtree 迁包、垂直切片;本方仅待对面答复 Q1/Q2 与 rpa.browser 备案。PowerShell 编码差异验证留待阶段 2 迁包后(bun 本机冒烟已于 2026-11-06 完成:bun 1.4.4,engine 37/37 全绿,exceljs/pdf 行为无差异;对面锁 1.4.3 为 patch 级差异)。
|
||
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。
|
||
- **R2 集成形态(含 A++ 补记)**:方案 A——整个 RPA 流程注册为 `rpa.flow.execute` 单能力,事件流旁路+人审升级两补丁;事件流再升级为检查点协议(崩溃后带 resumeToken 断点续跑),权威账本始终单 step。两侧改动清单见 §7-A5。
|
||
|
||
---
|
||
|
||
## 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 已于当日修复)
|
||
|
||
| # | 事项 | 状态 | 证据 |
|
||
|---|---|---|---|
|
||
| 1 | Driver 惰性 getter + 非 win32 抛 `platform_unsupported` | 已实现 | engine.ts;error-codes.ts:43;engine-driver.test.ts |
|
||
| 2 | **Driver 可注入** | ★已实现 | `createEngine({driver})` + `engine.setDriver()`;desktop/common-final/system-extended/window-extended 的模块级捕获改惰性 `getDriver()` |
|
||
| 3 | Registry 全局 Map、last-wins、runtime 读全局 getHandler | 属实(ADR-R1 短期形态固化;新增 `engine.execute` 语义真实入口) | registry.ts;engine.ts execute() |
|
||
| 4 | PLATFORM_GROUPS 单一源(34 域全 win32)+ buildDomainPlatformMap 真实实现 + 守卫测试 | 已实现 | register-all.ts;platform-groups.test.ts |
|
||
| 5 | withTimeout 监听 signal 但无 AbortController——超时不中止底层 | ★已修复 | 尝试级 AbortController 汇聚 run 取消+节点超时,handler 收到的 ctx.signal 即尝试信号 |
|
||
| 6 | NodeState 类型含 cancelled,但 executeNode catch 把取消标成 failed | ★已修复 | 取消映射 cancelled(不适用 skipOnError、不进异常分支);runtime.cancel.test.ts |
|
||
| 7 | 重试上限 100、黑名单式 isRetryable | ★已门控 | CapabilityMeta.idempotent===false 时无视 retryCount |
|
||
| 8 | Graph Validator | ★已实现 | engine/graph-validator.ts(重复ID/悬空边/自环/环/孤儿/不可达),runFlow 前置校验 |
|
||
| 9 | 动态 `import("electron")` 5 处(vision.ts×3、cv-vision.ts×2) | ★已修复 | HostBridge.screen 服务注入(requireScreenService),Core 恢复零 Electron |
|
||
| 10 | check-deps.mjs 对 `import("electron")` 零匹配(盲区实测) | ★已修复 | 新增动态 import()/require() 扫描;合成用例命中=1,真实源码 0 违规 |
|
||
| 11 | 包依赖缺 3 项:@napi-rs/canvas、pdfjs-dist、@cantoo/pdf-lib | ★已修复 | rpa-core/package.json dependencies 补齐 |
|
||
| 12 | main/exports 直指 src 源码、private | 属实(决策项,与对面源码消费一致) | rpa-core/package.json |
|
||
| 13 | rpa-cli 副作用全量 import + 全局 getHandler | ★已重写 | 显式按域注册(5 域)+ engine.execute |
|
||
| 14 | CDP transport 单命令无超时/无 AbortSignal/pending 仅断连清理 | 属实(未修,A7 迁移前修) | transport.ts:96-118 |
|
||
| 15 | 两段式元素定位(当前页优先,失败才跟前台)| 已实现 | session.ts |
|
||
| 16 | locate() 不支持 xpath / Shadow DOM(与 withElement() 不一致)| 属实(未修,A7 迁移前修) | session.ts |
|
||
| 17 | HostBridge/SubflowSource 模块级单例 | 属实(ADR-R1 范畴;screen 服务已并入 HostBridge) | host-bridge.ts |
|
||
| 18 | AI ChatCompletionOptions 无 signal 参数 | 属实(未修,P2) | ai-service.ts |
|
||
| 19 | 桌面拾取无 AbortSignal(热键+轮询+deadline 自有机制)| 属实(未修,P1) | desktop-pick.ts |
|
||
| 20 | catalog platformTag:win32=687 / null=326 / 数字 1=3(脏值未清洗) | ✅ 已清洗(2026-11-06) | build-catalog.mjs 增白名单归一化(非 win32/darwin/linux 字符串一律重派生),3 条脏值重派生为 win32,全字段 diff 仅 3 条变化 |
|
||
| 21 | catalog overrides(fields/removeFields/addFields) | 已实现(+782 个 options 收割修复重生成回归) | catalog-overrides.mjs |
|
||
| 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 参数 | 属实(未修;运行时取消已能中止监听 signal 的能力内部操作) | driver/types.ts |
|
||
|
||
---
|
||
|
||
## 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 容器。
|
||
|
||
**对面协作门禁(2026-11-06 新增,本项目补丁必须遵守)**:对面已建立代码与文档事实一致性门禁——`code/tooling/document-facts.mjs` + `项目资料/开发方案/当前事实.json`(factRevision 2026-11-06.1)。规则:代码、迁移、合同、端口、运行事实的任何变化,必须与事实文件、README 机器生成区块**同一提交**;CI 的 `document-facts --check` / `ci-gate.mjs` 会重扫源码输入并阻断漂移。**因此本项目未来合入对面仓库的任何补丁(含 C# actuate 补丁包、subtree 迁包)须:①同一提交内更新 `当前事实.json` 与相关 README 区块;②提交前跑 `node code/tooling/document-facts.mjs --check` 与 `node code/tooling/ci-gate.mjs --mode fast`。** 另:对面 backend/README Windows 行已明确下一步为"click/type、视觉/OCR 或随本轮客户端交付"——R3 C# actuate 路线与其路线图一致,可据此作为提案依据。
|
||
|
||
---
|
||
|
||
## 4. 原指南(V1)内容分类
|
||
|
||
| V1 内容 | 分类 | 处理 |
|
||
|---|---|---|
|
||
| 包现状描述(719 能力、34 域、宿主桥 4 方法、Driver 五域) | **保留**(微调) | 仍准确;宿主桥维持 4 方法不变 |
|
||
| "完全不依赖 Electron、check:deps 天天检查" | **过时/不实** | 5 处动态 import 逃过护栏;改为"静态依赖已清、动态残留待清",护栏必须升级 |
|
||
| 第 -1 步对面契约包全部空壳的叙事 | **过时** | 按 §3 改写:5/7 已实现,"填契约"变"接底座" |
|
||
| 第 0 步三件作业(bun 冒烟 / catalog 重生成 / 注册方式决策) | ✅ 全部完成 | catalog 重生成完成且脏值已清洗(platformTag win32=690 / null=326,数字脏值归零);bun 1.4.4 本机冒烟 37/37;注册方式决策并入 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。
|
||
- **方案(★ 已实现,2026-11-06 阶段 1-A1)**:`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。
|
||
- **方案(★ 已实现,2026-11-06 阶段 1-A3)**:①节点尝试创建独立 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<ActionResult>`,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/审批结果。
|
||
- **租约粒度拍板(2026-11-06 用户拍板:每个节点执行都要慎重)**:gateway 租约 TTL=60s(index.ts:124),而方案 A 整条流程可达数分钟——**解法定为"外层一个 step、内层每节点一次授权"**:流程内每个节点执行前由 adapter 单独走一次 authorize+execute(60s/节点绰绰有余),高危节点逐节点审批。与 A++ 检查点协议天配:事件负载的 `nodeId + idempotencyKey(runId:nodeId)` 正好构成 gateway 幂等键所需的作用域材料(workflow 来源要求 run+step+attempt,adapter 以 nodeId 充当 step 定位)。每节点授权同时天然实现"慎重"语义:任何节点执行前都过权限白名单+审批门,无绕行。
|
||
- **版本管理设计提案(2026-11-06,adapter 层落地,不改引擎)**:对面版本约束为硬性三处——①每次调用必带 `capabilityVersion`,与注册表不符直接拒绝(gateway index.ts:171);②幂等键含能力版本与配置版本;③插件 manifest 强制三段 semver(plugin-contract index.ts:277,`v1.0`/四段式均不通过)。我方现状:catalog 997/1016 项带上游四段版本(如 `App_Run@3.3.5.0`),但注册表无版本机制、包版本 0.1.0 从未随能力变化推进。提案:①对外能力 version = rpa-core 包 semver(0.1.0 起,仅对外行为变化才升版);②catalog 四段版本归一化为三段后进 CapabilityDefinition(版本仅作标识,行为一致性由同包源码保证);③configVersion 用 catalog+overrides 内容哈希(与幂等键 configVersion 段正好衔接)。**对迁包零影响**:catalog 版本字段原样迁移,归一化发生在 adapter 生成清单时。
|
||
|
||
### 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<CapabilityGateway["execute"]>[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 用于崩溃恢复对齐)。
|
||
- **A++ 检查点补记(2026-11-06,本方负责人确认)**:在方案 A 骨架内将节点事件流升级为检查点协议(决策全文见 §10-R2)。
|
||
- **RPA 侧改动**:①事件负载增 `nodeId`/`status`/`checkpointId`/`idempotencyKey`/`resumable` 字段;②`rpa.flow.execute` 接受可选 `resumeToken`,重入时从最近检查点续跑(幂等句柄表已迁 engine 实例字段,地基现成);③幂等键生成与传递贯通(复用 A3 的 `idempotent` 门控,仅补 key 生成与透传)。
|
||
- **对面侧改动**:①workflow-engine 对 `rpa.flow.execute` 所在 step 的重试/恢复策略允许带 resumeToken 重入(不新建 step、不改租约语义);②event-bus 消费端识别检查点事件并入审计链;③崩溃恢复时把 resumeToken 经 adapter 回传(复用 workflow-recovery 的 unknown→恢复路径)。
|
||
- **落地节奏**:阶段 2 只做事件负载字段设计定稿(payload 预留,近零成本);阶段 3 垂直切片做最小验证(崩溃→重入续跑);阶段 4/5 规模化时强制执行。
|
||
- **验收**:状态映射契约测试(含 waiting_user/unknown/cancelled 全分支);一次含审批节点、一次执行中取消、一次进程崩溃恢复的端到端演练;对面 Run 状态终态与 RPA RunResult 永远一致;崩溃重入演练——杀掉执行进程后带 resumeToken 续跑,已完成节点不重复执行、幂等键防重复副作用。
|
||
|
||
### 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 **win32=690 / null=326,数字脏值已归零(2026-11-06 白名单归一化)**。
|
||
- **AE 位置**:`plugin-contract` Platform 类型;windows-runner 明确"留在宿主、不进 Linux 容器"(README)。
|
||
- **兼容性**:兼容(两边都是 win32-first 务实路线)。
|
||
- **问题**:①~~catalog 3 个 `platformTag: 1` 脏值透传~~ **已修复(2026-11-06)**:build-catalog.mjs 白名单归一化,上游 shizai 的数字 1 重派生为 win32(三条均为包内真实现,语义正确);②对面 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。
|
||
- **方案(★ 已实现,2026-11-06 阶段 1-A9)**:①抽 `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 侧收口**(本仓库)✅ **已完成(2026-11-06,提交 9b76dc6/1da0082/1a20dd7/5e8fc96)** | 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 映射 + 状态映射表);A++ 事件负载字段设计定稿(nodeId/检查点/幂等键,见 §7-A5);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 整体注册)+ A++ 检查点续跑最小验证(崩溃→resumeToken 重入,见 §7-A5) | 阶段 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 编码) | 中(部分缓解) | exceljs/pdf 已于 2026-11-06 本机 bun 1.4.4 冒烟通过(37/37);PowerShell 编码差异留待阶段 2 迁包后清单化 |
|
||
| R7 | demo 侧与 backend 双活跃漂移 | 中 | git subtree + "迁移后 demo 冻结"纪律(V1 决策 3) |
|
||
| R8 | 两套状态机语义漂移(NodeState vs StepStatus) | 中 | 映射表 + 契约测试常驻 CI;A++ 检查点协议(ADR-R2 补记)统一崩溃恢复语义 |
|
||
| 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,不进宿主。**原型已产出并编译验证(2026-11-06)**:`contrib/windows-runner-actuate/` 补丁包(协议扩展 + NativeInput + ActuateService + 逐原语移植对照表 + 合入指引含门禁合规清单);对面 csproj 原样合编 0 警告 0 错误(.NET 10.0.403),协议冒烟 5 例通过(安全门错误码/双路分发/observe 无回归);对面 README Windows 行"click/type 或随本轮交付"与该路线吻合 |
|
||
| 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 分组加载,不维护两份代码。**补记(2026-11-06 用户拍板:双端并存+透明调度)**——同一能力本地/后端两驻地并存,SaaS 与本地部署两形态通用,用户无感知;防乱设计见下方专条 |
|
||
| R2 | 集成形态:RPA 流程=单个 capability(方案 A)还是节点=step 映射(方案 B) | **方案 A + 两补丁**:RPA 流程=`rpa.flow.execute` 单能力,对面一个 step 一次租约一次结算;节点级事件走 event-bus 旁路(保透明、不进权威账本);人审/高危节点照常升级对面审批。**不用 B 的理由**(记录在案):双账本一致性(崩溃窗口两边分歧、破坏对面 recovery 的单账本假设)、控制流节点无副作用无法映射 CapabilityRef、审批/重试粒度与业务语义错位。**B 的触发条件**:对面产品确认需要"逐步控制 RPA"(单步执行/任意步回退)时局部启用,事件流已备好数据不返工。**A++ 补记(2026-11-06 二次拍板)**:方案 A 骨架不变,节点事件流从"透明度日志"升级为**检查点协议**(nodeId+状态+幂等键+可恢复标记),崩溃后 `rpa.flow.execute` 带 resumeToken 重入、从最近检查点续跑,权威账本仍为单 step、无双账本;B 的隐藏触发条件(长流程断点续跑,RPA 桌面场景高发)由此覆盖而无需节点=step。业界对照:UiPath Orchestrator=Job 黑盒+日志旁路(≈A);Camunda/Zeebe External Task 的"单引擎假设"不适用于双引擎集成;AWS Step Functions callback≈补丁 2。两侧改动清单与落地节奏见 §7-A5。**租约粒度三次拍板(2026-11-06:每个节点执行都要慎重)**:外层单 step 不变,内层**每节点执行前单独 authorize+execute**(60s 租约/节点),高危节点逐节点审批——节点级治理粒度 + step 级账本粒度两全,实现方式见 §7-A4 |
|
||
| V1 | 能力版本管理 | **adapter 层承接对面硬约束(2026-11-06 设计定稿)**:对面三处硬约束(调用必带 capabilityVersion 且不符即拒 / 幂等键含版本 / manifest 强制三段 semver);我方 catalog 997 项带四段版本但注册表无版本机制。定案:对外能力 version=rpa-core 包 semver(仅对外行为变化才升版);catalog 四段版本归一化三段;configVersion=catalog+overrides 内容哈希。详见 §7-A4;对迁包零影响 |
|
||
|
||
### 待对面对确认(仅剩小问题,不猜测)
|
||
|
||
| Q# | 问题 | 评审要点 |
|
||
|---|---|---|
|
||
| Q1 | CapabilityDefinition 是否需要 platform 字段(对面清单未见) | **本方设计提案(2026-11-06)**:对面 plugin-contract 增可选 `platforms?: readonly ("win32"\|"darwin"\|"linux")[]`,缺省=全平台(旧清单零破坏);registry 的 `assertPluginManifest` 校验值域;plugin-worker 认领动作时按宿主 `process.platform` 过滤。RPA 侧清单由 rpa-adapter 从 catalog `platformTag` 自动生成,不手工维护第二份。与对面确认后照此实现 |
|
||
| Q2 | utilityExtended(命令执行)对应哪个 PermissionScope | **本方设计提案(2026-11-06)**:utilityExtended 域在对面源码无同名物,属纯 RPA 侧概念。提案映射到 `desktop.process`——RPA 命令执行发生在用户电脑 Electron 宿主内,宿主即桌面进程,语义吻合;该域标 highImpact + idempotencyRequired 走审批。若对面认为 desktop.process 严格指"桌面进程管理",备选新增 `desktop.command` scope。13 项 PermissionScope 其余映射维持 §7-A4 初稿 |
|
||
| Q4 | 高危审批的"上游服务"成熟度 | gateway 只按 actionId 精确放行,注释明言"审批有效性判定(是否过期、是否本人审批)由上游负责"(capability-gateway index.ts:13-14),但该上游服务的实现与闭环未见。RPA 人审弹窗方案(human-dialog→requestApproval→绑定 actionId)依赖它,须确认其签发/过期/防代批机制现状。**源码核查(2026-11-06):上游已实现非设计**——即服务端 workflow-engine 包:approval-policy 纯函数(actionId=runId:stepId:attempt 重试不被旧审批放行 / expiresAt 过期判定 / 仅 high 风险可发起)+ workflow-api 路由(request_approval / decide_approval,403 发起人不能审批自己=防代批、409 缺审批、410 已过期)+ Postgres 持久化;桥=plugin-worker 取 approvedActionIds 喂 gateway。缺口:审批人身份仍为开发态 token(PRODUCT_APPROVER_TOKEN,生产形态未接完);RPA 挂接的对齐点见下方"审批对象三层"专条 |
|
||
| Q5 | 租户权限配置面 | 每租户/员工的 `allowedPermissions` 白名单由谁配置、走哪条链路(entitlement-contract / identity-store 成熟度),adapter 对接前须核一眼 |
|
||
|
||
> 已回答:Q3(human-dialog 弹窗落点)已由 R6 回答——用户电脑 Electron 宿主窗口;仅样式/交互细节与对面 UI 对齐。
|
||
|
||
### 审批对象三层设计(2026-11-06 设计思考,待与上游对齐)
|
||
|
||
"审批什么、谁来批"须拆三层,混用会导致对面防代批机制(403)误伤合法场景:
|
||
|
||
| 层 | 对象 | 谁来批/定 | 时机与频率 | 载体 |
|
||
|---|---|---|---|---|
|
||
| ① 能力白名单 | 租户/员工能用哪类能力 | 管理员配置 | 事前一次,长期生效 |对面 Q5 链路(entitlement),**不产生审批单** |
|
||
| ② 流程上架 | 流程定义版本 + 它声明的能力清单 | 上游审批人 | 事前一次,多次运行复用 | 审批单(或管理端流程发布流程,待对齐用哪个) |
|
||
| ③ 单次高危动作 | 某次运行中的具体高危节点 | **分两种**:有人值守=用户知情同意;无人值守=上游审批人 | 事中,逐动作 | 有人值守=human-dialog 弹窗(consent,**不走审批单**,否则"自己批自己"被对面 403 挡死);无人值守=workflow-engine 审批单,运行暂停等批 |
|
||
|
||
推论(修正此前对齐清单):
|
||
- **actionId 粒度问题(attempt 维度)只存在于无人值守路径**;有人值守路径由"租约 60s + 每节点弹窗"兑现(§R2 三次拍板),与审批单无关。
|
||
- 日常有人值守运行**不需要**每次调 workflow-api;只有定时/远程触发的无人值守高危动作才走 request_approval 暂停等批——这正面回答了"发起方通道"问题。
|
||
- 对上游的对齐问题收敛为:②流程上架审批放哪个系统;③无人值守路径复用 workflow-engine 时 actionId(runId:stepId:attempt)与 rpa-core 幂等键(runId:nodeId)的映射(nodeId:attempt 是否补入 RunEvent);审批人身份生产化(trusted-gateway-headers / 管理端账号)。
|
||
|
||
### R6 补记:双端透明调度设计(2026-11-06 用户拍板:前端留、后端也留)
|
||
|
||
同一能力允许本地(用户电脑宿主)与后端(plugin-worker)两驻地并存,调度对用户无感知,SaaS 与本地部署两形态通用(本地部署时"后端"即客户自有机房,规则不变)。防乱靠三条纪律与一张确定性路由表:
|
||
|
||
**三条纪律:**
|
||
|
||
1. **一个脑决策**:路由只在宿主侧 Resolver 一处发生(本质是 A1 注入机制的扩展——registry 条目的 handler 绑定二选一:本地实现 or 自动生成的远端代理,远端代理走对面 gateway 授权/租约/审计,不绕行)。能力代码与流程定义里**禁止**出现任何驻地 if-else,规则全部来自 catalog 元数据。
|
||
2. **一份契约两处实现**:能力签名/参数/返回/错误码同一套(catalog 单一源已保证);本地与远端实现跑同一套契约测试;远端代理自动生成而非手写第二份逻辑,杜绝漂移。
|
||
3. **数据不动原则**:能力在哪个驻地执行由"数据已经在哪里"决定(代码就数据,不搬数据)。需要搬数据时必须是流程中的显式节点(上传/下载),**路由器不得隐式搬运用户本地文件到后端**——用户无感知的是"在哪算",不是"数据去哪"(隐私红线)。
|
||
|
||
**路由规则表(按序匹配,确定性,不留裁量空间):**
|
||
|
||
| 序 | 条件 | 执行驻地 |
|
||
|---|---|---|
|
||
| 1 | platformTag 限宿主平台 / 需要桌面会话 / 弹窗人审 | 仅本地(无远端选项) |
|
||
| 2 | 输入数据在本地(本地文件路径) | 本地 |
|
||
| 3 | 输入数据在云端(对面 tenant-files 等) | 后端 |
|
||
| 4 | 数据两驻地均有副本 | 默认本地(隐私+省带宽);流程可显式声明 `prefer: backend`(如夜间批量) |
|
||
| 5 | 本地不可用(宿主离线)且能力无本地数据依赖且标可远端 | 后端兜底 |
|
||
| 6 | 均不可用 | 节点失败,错误码 `location_unavailable` |
|
||
|
||
**用户无感知 ≠ 审计无感知**:`node.finished` 事件携带 `executor: "local" | "backend"` 字段(已定稿进 RunEvent 并有契约测试,当前恒为 `local`,远端代理落地后由代理覆盖)——用户界面不展示,审计与排障必须可分辨。该字段同时是对面 event-bus 入审计链的取用点。
|
||
|
||
---
|
||
|
||
## 11. 本指南边界
|
||
|
||
- 全部结论基于 2026-11-06 双侧工作区源码静态核查 + 少量脚本实测(正则盲区、catalog 统计、capabilityCount);未执行 Windows 实机 E2E 与对面联调,未运行的测试不写成通过。
|
||
- 行号会随代码演进过期,以函数/接口名为准。
|
||
- 本轮只改文档,不改业务源码(用户指令);阶段 1 起的代码改动另行排期。
|