4.5 KiB
4.5 KiB
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 分发:
// 原: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 已保证):
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.windowsmanifest 已是type=highImpact + idempotencyRequired,capability-gateway 的精确 actionId 放行与租约语义直接适用,无需改 gateway; - 超时:宿主杀进程超时须覆盖 mouse_move_smooth 最坏路径(≈4s)+ 两次截图(≈2s),建议 ≥15s。
4. 验证计划(用对面现成夹具)
test/fixture/(AgentWorker.WindowsFixture):仿照native-observer.integration.test.ts增加 actuate 集成测试:mouse_move→ GetCursorPos 断言落点;mouse_click(无桌面断言,仅断言 ok + 证据 SHA 与文件存在);keyboard_send(chars 模式)→ UIA 读回文本;window_activate→ GetForegroundWindow 断言;- 反向用例:越权窗口 →
window_not_allowed;Session 不匹配 →desktop_session_mismatch;非法 Kind →action_invalid。
- 兼容性矩阵(微信/Office/UWP)按对面既有测试纪律单独排期,不在本补丁范围。
5. 门禁合规清单(对面 2026-11-06 新规,硬性)
合入提交必须同一提交内包含:
项目资料/开发方案/当前事实.json:factRevision 递增,trackedInputs 如受影响同步更新;- 相关 README 的机器生成区块(
node code/tooling/document-facts.mjs --write重新生成); code/backend/README.mdWindows 行状态更新("click/type" 从"或随本轮交付"改为已实现口径);- 提交前本地跑:
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 buildnative/csproj),或由对面侧首次合入时跑; Clipboard.SetDataObject依赖 STA:对面 Main 已是[STAThread],满足;- mouse_event → SendInput 为现代等价替换(标志位映射见 PORTING-MAP 第四节);如对面评审倾向零差异,可回退为 mouse_event P/Invoke,一行替换;
- 平滑移动公式中的伪随机抖动与 JS
%保号语义一致(C#%对 double 同为保号),无漂移。