78 lines
4.5 KiB
Markdown
78 lines
4.5 KiB
Markdown
# 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. 验证状态与已知限制
|
||
|
||
- **语法级人工审查已完成;未编译**——本机无 .NET SDK,编译验证需在装 .NET 10 SDK 后进行(`dotnet build` native/csproj),或由对面侧首次合入时跑;
|
||
- `Clipboard.SetDataObject` 依赖 STA:对面 Main 已是 `[STAThread]`,满足;
|
||
- mouse_event → SendInput 为现代等价替换(标志位映射见 PORTING-MAP 第四节);如对面评审倾向零差异,可回退为 mouse_event P/Invoke,一行替换;
|
||
- 平滑移动公式中的伪随机抖动与 JS `%` 保号语义一致(C# `%` 对 double 同为保号),无漂移。
|