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

5.2 KiB
Raw Blame History

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.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 同为保号),无漂移。