PRA-only-demo/contrib/windows-runner-actuate/PATCH-NOTES.md

82 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# PATCH-NOTES:合入对面 windows-runner 的集成指引
本目录是 **本地原型补丁包**,不改动对面仓库。合入时按以下步骤执行。
## 1. 文件落点
| 本目录文件 | 落到对面仓库 | 说明 |
|---|---|---|
| `native/ActuateProtocol.cs` | `code/backend/services/windows-runner/native/` | 新增类型,不动现有文件 |
| `native/ActuateService.cs` | 同上 | 新增类型,不动现有文件 |
| `native/NativeInput.cs` | 同上 | 新增类型;**NativeWindows.cs 保持只读边界原样不动**(对面注释明言该层无输入接口,编译边界得以保全) |
csproj 无需改动:`UseWindowsForms` 已启用(SendKeys/Clipboard/Screen 可用),FlaUI 引用与本补丁无关。
## 2. Program.cs 分发改造(最小 diff)
现有 Main 只认 `observe`。改造为按 Operation 分发:
```csharp
// 原:if (request.ProtocolVersion != 1 || request.Operation != "observe" || ...)
// 改为先解公共头再分发(保持 64KiB/UTF-8/UUID 校验全部不变):
if (request.ProtocolVersion != 1 || !Guid.TryParse(requestId, out _))
throw new RunnerException("request_invalid");
switch (request.Operation)
{
case "observe": { /* 原 observe 路径逐字保留 */ }
case "actuate":
{
var actuate = JsonSerializer.Deserialize<ActuateRequest>(line, JsonOptions)
?? throw new RunnerException("request_invalid");
var result = ActuateService.Actuate(actuate, evidenceRoot);
Write(new RunnerResponse(1, requestId, true, null, null, result));
return 0;
}
default: throw new RunnerException("request_invalid");
}
```
RunnerResponse 需加一个可选字段(observe 的线上形状不变,`WhenWritingNull` 已保证):
```csharp
internal sealed record RunnerResponse(int ProtocolVersion, string RequestId, bool Ok,
ComputerObservation? Data, string? ErrorCode, ActuateResult? ActuateData = null);
```
## 3. TS 宿主侧(native-observer.ts → actuate 适配器,属后续工作)
- 请求侧:actuate 前先用 observe 解析**精确**窗口标题与进程名(RPA 侧"标题包含匹配"的语义在宿主层弥合,见 PORTING-MAP 第二节);
- 响应侧:对 ActuateData.Evidence 逐项复核(realpath 归属证据根目录、SHA-256、PNG 魔数——复用 native-observer.ts 现成校验);
- 高影响审批:`rpa.windows` manifest 已是 `type=highImpact + idempotencyRequired`,capability-gateway 的精确 actionId 放行与租约语义直接适用,**无需改 gateway**;
- 超时:宿主杀进程超时须覆盖 mouse_move_smooth 最坏路径(≈4s)+ 两次截图(≈2s),建议 ≥15s。
## 4. 验证计划(用对面现成夹具)
- `test/fixture/`(AgentWorker.WindowsFixture):仿照 `native-observer.integration.test.ts` 增加 actuate 集成测试:
1. `mouse_move` → GetCursorPos 断言落点;
2. `mouse_click`(无桌面断言,仅断言 ok + 证据 SHA 与文件存在);
3. `keyboard_send`(chars 模式)→ UIA 读回文本;
4. `window_activate` → GetForegroundWindow 断言;
5. 反向用例:越权窗口 → `window_not_allowed`;Session 不匹配 → `desktop_session_mismatch`;非法 Kind → `action_invalid`。
- 兼容性矩阵(微信/Office/UWP)按对面既有测试纪律单独排期,不在本补丁范围。
## 5. 门禁合规清单(对面 2026-11-06 新规,硬性)
合入提交必须**同一提交内**包含:
1. `项目资料/开发方案/当前事实.json`:factRevision 递增,trackedInputs 如受影响同步更新;
2. 相关 README 的机器生成区块(`node code/tooling/document-facts.mjs --write` 重新生成);
3. `code/backend/README.md` Windows 行状态更新("click/type" 从"或随本轮交付"改为已实现口径);
4. 提交前本地跑:`node code/tooling/document-facts.mjs --check` && `node code/tooling/ci-gate.mjs --mode fast` && `git diff --check`。
## 6. 验证状态与已知限制
- **已编译通过 + 协议冒烟通过(2026-11-06,.NET SDK 10.0.403)**:
- `dotnet build`(对面 csproj 原样 + 本补丁三文件 + §2 最小 diff):**0 警告 0 错误**(TreatWarningsAsErrors 开启,直接达到对面合入标准);
- 编译修正两处:`NativeInput.Point` 由 private 改 internal(CS0050 可访问性)、`ActuateService.cs` 补 `using System.Diagnostics;`(CS0103);
- 零桌面交互协议冒烟 5 例:`policy_invalid` ✅ / `desktop_session_mismatch` ✅ / observe 老路径无回归 ✅ / requestId 逐字回显 ✅;另 2 例(越权窗口/非法动作)因**窗口选择先于动作校验**的既有顺序先报 `window_not_found`——顺序与对面 observe 一致,属预期行为,用例已按此修正理解;
- 需要真实窗口的用例(click/type/window_activate/action_invalid 路径)留待对面 `test/fixture` 集成测试(第 4 节),避免占用用户桌面。
- `Clipboard.SetDataObject` 依赖 STA:对面 Main 已是 `[STAThread]`,满足;
- mouse_event → SendInput 为现代等价替换(标志位映射见 PORTING-MAP 第四节);如对面评审倾向零差异,可回退为 mouse_event P/Invoke,一行替换;
- 平滑移动公式中的伪随机抖动与 JS `%` 保号语义一致(C# `%` 对 double 同为保号),无漂移。