# zcbot Windows Node 技术方案

> 状态：方案设计，待云环境和 Origin 版本确认后实施
> 首期能力：Origin 科研绘图
> 云端：Ubuntu 上运行的 zcbot
> Windows 端：.NET 10 LTS / ASP.NET Core Worker Service
> 目标系统：Windows 11 Enterprise 优先；经兼容性验证并具备安全更新的 Windows 10 亦可

## 1. 决策摘要

Windows 端采用 **zcbot Windows Node**，由节点主动连接云端 zcbot。云端是唯一的用户入口、智能决策者和任务控制面；Windows Node 是受控执行节点，负责本机工业软件、交互式桌面、截图视频和产物回传。

Windows Node 不是完整的本地 zcbot：

- 不直接与用户对话；
- 不保存主会话和用户长期记忆；
- 不持有云端模型密钥；
- 不自主扩大任务范围；
- 不接受任意命令、任意脚本或任意桌面动作；
- 只执行云端下发且本地能力清单允许的任务。

核心技术决策：

1. **连接方向**：Windows Node 通过出站 WSS/HTTPS 主动连接云端，Windows 不开放业务入站端口。
2. **Windows 主体**：使用 .NET 10 LTS、Worker Service、ASP.NET Core 本机诊断 API。
3. **双进程边界**：Windows Service 管控制面；`DesktopRunner.exe` 在持续登录的交互式会话中管 GUI、COM 和截图。
4. **软件适配器**：Origin/Fluent 使用固定 Python Worker；Aspen/CAD 优先使用 C# COM/.NET；GUI 仅作补充。
5. **状态分工**：云端 PG 保存任务所有权与期望状态；节点 SQLite/终态文件保存本机执行证据。二者通过租约和重连对账，不构成两个业务事实源。
6. **产物分工**：Windows 本地文件是计算现场事实；上传到云端后，zcbot 用户工作目录中的文件是用户交付事实。
7. **首批 Origin**：主流程使用 Origin 官方推荐的外部 Python `originpro`，Computer Use 只做视觉验收和异常处理。

## 2. 目标与非目标

### 2.1 目标

- 云端 zcbot 可以发现节点能力、容量、软件版本和在线状态。
- 用户可以提交、查询、取消长时间运行的专业软件任务。
- 网络中断、云端重启或节点重启后，任务可以确定性对账。
- 节点可以上报阶段、进度、结构化指标、日志摘要和事件截图。
- 中间产物和最终产物支持校验、断点上传与按需导入工作目录。
- 单台节点可以逐步增加 Origin、Fluent、Aspen、CAD 等适配器。
- Computer Use 在独立低权限桌面会话运行，并经过能力白名单和动作策略约束。
- 节点不暴露用户工作区、云端凭据或其他用户任务。

### 2.2 首期非目标

- 不把 Windows Node 做成第二个聊天机器人或子 agent。
- 不开放任意 PowerShell、Python、LabTalk、COM、URL 或 Windows 路径。
- 不实现节点之间迁移已经开始执行的软件任务。
- 不实现通用 HPC 调度器、工作流 DAG 或自动重跑整个计算。
- 不持续把完整桌面视频发送给模型。
- 不依赖 SMB 共享目录作为任务协议。
- 不在首期实现自动更新、WebRTC 和多节点智能负载均衡。

## 3. 总体架构

```mermaid
flowchart LR
    User["用户"] --> Z["zcbot Web / 渠道"]
    Z --> Agent["Agent Loop"]
    Agent --> Tools["Compute Tools"]
    Tools --> CP["云端 Node Control Plane<br/>PG + Connection Manager"]
    Node["Windows Node Service<br/>.NET Worker"] -->|"出站 WSS + mTLS"| CP
    CP -->|"任务 offer / cancel / config"| Node
    Node -->|"heartbeat / event / terminal"| CP
    Node --> Pipe["ACL Named Pipe"]
    Pipe --> Desktop["DesktopRunner.exe<br/>交互式用户会话"]
    Desktop --> Origin["Origin / OriginPro"]
    Desktop --> Other["Fluent / Aspen / CAD"]
    Node --> Local["本机 SQLite + Job Directories"]
    Desktop --> Local
    Node -->|"HTTPS 分块上传"| Cache["云端隐藏计算缓存"]
    Cache --> Workspace["用户 working_dir"]
```

### 3.1 云端组件

| 组件 | 职责 |
|---|---|
| `NodeRegistry` | 节点注册、证书指纹、启停、能力和管理员标签 |
| `NodeConnectionManager` | WSS 连接、心跳、消息 ACK、同节点单活连接 |
| `SoftwareJobService` | 用户授权、幂等提交、节点选择、租约、取消和终态 |
| `ComputeTransferService` | 输入下载凭证、分块上传、SHA-256、容量与保留期 |
| `ComputeBroker` | 把任务事件推送到 Web UI；不承担持久化事实源 |
| `ComputeTools` | agent 可调用的能力发现、提交、查询、取消、产物导入工具 |

节点机制不复用现有 `generic_openapi` 外部系统定义。外部系统表达“用户凭据下的受控请求”；Windows Node 表达“平台托管设备、持久连接、执行租约与本机容量”。两者可以复用认证、审计、大结果和 ActionPolicy 原则，但不共用运行状态模型。

### 3.2 Windows 组件

| 进程 | 运行身份 | 职责 | 禁止事项 |
|---|---|---|---|
| `Zcbot.WindowsNode.Service` | 低权限服务账号 | 云连接、任务台账、租约、调度、传输、日志、进程控制 | 点击桌面、持有用户密码、执行任意脚本 |
| `Zcbot.DesktopRunner.exe` | 专用持续登录账号 | 会话内启动软件、UI Automation、截图、视频、弹窗检测 | 对外监听、决定用户任务、访问其他任务 |
| `OriginAdapter.Worker` | 由 DesktopRunner 启动 | 读取固定 schema、调用 `originpro`、导出和验证 | 网络访问、解释自然语言、加载用户代码 |
| 后续软件 Worker | 按适配器定义 | PyFluent、Aspen COM、CAD .NET/COM | 绕过 Node 能力与路径边界 |

Windows Service 位于 Session 0，不能可靠操作用户可见桌面。所有需要用户 profile、COM 桌面对象、可见窗口或截图的动作都由 `DesktopRunner.exe` 执行。Service 与 DesktopRunner 只使用本机命名管道通信，命名管道 ACL 仅允许两个指定账号。

## 4. Windows 技术栈

### 4.1 Node Service

- .NET 10 LTS
- `Microsoft.NET.Sdk.Worker`
- `BackgroundService`
- `ClientWebSocket` / `HttpClient`
- ASP.NET Core Minimal API，仅绑定 `127.0.0.1` 提供诊断接口
- `System.Threading.Channels` 管理本机有界任务队列
- SQLite WAL 保存执行台账
- Serilog 写结构化滚动日志和 Windows Event Log
- Windows Certificate Store 保存节点私钥和客户端证书
- Windows Job Objects 或受控 PID 树负责取消和超时回收
- Named Pipes 连接 DesktopRunner

ASP.NET Core 在这里仍是正确选型，但职责已经变化：它不是等云端调用的公开业务网关，而是 Windows Node 的宿主、诊断端点和基础设施框架。跨机业务通信由 Node 主动发起。

### 4.2 本机诊断 API

仅监听 loopback：

```text
GET  /health/live
GET  /health/ready
GET  /diagnostics/node
GET  /diagnostics/jobs
GET  /diagnostics/jobs/{job_id}
POST /diagnostics/reconnect
```

诊断 API 不提供提交任务、任意命令或软件操作。远程运维通过 VPN/堡垒机登录 Windows 后在本机访问，避免形成第二个业务入口。

### 4.3 Python 适配器运行时

Origin 和 Fluent 使用独立、固定版本、离线部署的 Python 运行时。Node 不在任务执行期间安装依赖，不接受请求指定解释器或包版本。

```text
D:\ZcbotNode\runtimes\
├── origin\
│   ├── python.exe
│   └── adapter\
└── fluent\
    ├── python.exe
    └── adapter\
```

Node 生成规范化 `request.json`，固定 Worker 读取请求；事件写 `events.jsonl`，产物写 `artifacts.json`，终态原子写 `terminal.json`。标准输出只用于诊断，不作为任务状态事实源。

## 5. 节点身份与连接

### 5.1 注册流程

```mermaid
sequenceDiagram
    participant Admin as 管理员
    participant Cloud as zcbot 云端
    participant Node as Windows Node
    Admin->>Cloud: 创建一次性 enrollment token
    Node->>Node: 生成设备密钥对
    Node->>Cloud: POST /v1/software-nodes/enroll
    Cloud->>Cloud: 消耗 token，创建 node_id
    Cloud-->>Node: 客户端证书、CA、云端地址
    Node->>Node: 私钥写入 Windows Certificate Store
    Node->>Cloud: mTLS 建立 WSS
    Cloud-->>Node: 注册成功与当前配置 revision
```

约束：

- enrollment token 一次性、短期有效，并绑定预期节点名称；
- 私钥在 Windows 本机生成且不可导出；
- 云端只保存证书指纹和公钥身份；
- 节点证书支持轮换、吊销和管理员禁用；
- 重装节点必须重新注册，不复用复制出来的私钥。

### 5.2 长连接

节点连接：

```text
WSS /v1/software-nodes/connect
```

统一消息 envelope：

```json
{
  "protocol_version": 1,
  "message_id": "019...",
  "type": "heartbeat",
  "sent_at": "2026-08-12T08:00:00Z",
  "payload": {}
}
```

| 方向 | 类型 | 语义 |
|---|---|---|
| Node → Cloud | `hello` | Node 版本、OS、boot ID、本机配置 revision |
| Node → Cloud | `heartbeat` | 容量、软件健康、运行任务摘要、磁盘 |
| Node → Cloud | `job_accept` / `job_reject` | 是否已原子接收 offer |
| Node → Cloud | `job_state` | 阶段、进度和结构化指标 |
| Node → Cloud | `job_event` | 重要事件、警告和截图引用 |
| Node → Cloud | `job_terminal` | 成功、失败、取消的唯一远端终态消息 |
| Node → Cloud | `lease_renew` | 续租仍在本机执行的任务 |
| Cloud → Node | `job_offer` | 带租约的任务候选，不等于已分派 |
| Cloud → Node | `job_cancel` | 请求协作式取消 |
| Cloud → Node | `config_changed` | 提示节点拉取新配置 |
| 双向 | `ack` / `ping` / `pong` | 去重、保活和连接质量 |

消息按 `message_id` 幂等。重要消息在发送方保存到收到 ACK；心跳和高频进度允许覆盖，不进入无限重放队列。

### 5.3 单活连接

同一 `node_id` 只允许一个活动连接。新连接带 `boot_id` 和递增 `connection_epoch`；云端原子替换旧连接。旧连接收到 fencing 后不得继续接受新任务，防止快照克隆或网络分区导致双执行。

## 6. 能力与容量模型

Node 在 `hello` 和心跳中声明由本机可信配置生成的能力：

```json
{
  "node_id": "019...",
  "node_version": "0.1.0",
  "os": "windows-11-enterprise-24h2",
  "capabilities": [
    {
      "name": "origin.plot",
      "adapter_version": "0.1.0",
      "software": "OriginPro",
      "software_version": "2026",
      "schema_version": 1,
      "max_concurrency": 1,
      "available_slots": 1,
      "health": "ready"
    },
    {
      "name": "computer.windows.capture",
      "schema_version": 1,
      "max_concurrency": 1,
      "available_slots": 1,
      "health": "ready"
    }
  ],
  "disk_free_bytes": 536870912000
}
```

能力清单来自管理员部署的适配器 manifest，不能由模型或用户请求自行添加。云端 definition 约束允许哪些用户、角色或任务使用某项能力；节点再次校验 capability、schema version、文件配额和本机 slot，形成双层防护。

## 7. 云端数据模型

建议新增三张表，不复用外部系统连接表：

```text
software_nodes(
  node_id pk, name, cert_fingerprint, status,
  labels jsonb, capabilities jsonb, config_revision,
  last_seen_at, disabled_at, created_at, updated_at
)

software_jobs(
  job_id pk, user_id fk, task_id fk, tool_call_id,
  capability, schema_version, request jsonb,
  idempotency_key, request_digest,
  node_id fk null, lease_id, lease_expires_at,
  status, stage, progress, metrics jsonb,
  error jsonb, artifact_manifest jsonb,
  created_at, started_at, terminal_at, updated_at
)

software_job_events(
  event_id pk, job_id fk, sequence,
  kind, level, payload jsonb, created_at
)
```

约束：

- `(user_id, idempotency_key)` 唯一；
- request 只保存规范化业务参数和文件引用，不保存二进制内容或密钥；
- events 只保存阶段变化、警告、错误、用户可见事件和产物事件，不保存视频帧和全部原始日志；
- 原始日志、截图和上传中产物进入隐藏文件缓存；
- 事件按配置保留，终态任务和用户交付文件遵守 zcbot 通用保留策略。

## 8. 任务状态、租约与恢复

### 8.1 云端状态机

```mermaid
stateDiagram-v2
    [*] --> queued
    queued --> offered
    offered --> dispatched: node accept
    offered --> queued: reject / offer timeout
    dispatched --> running
    running --> succeeded
    running --> failed
    running --> cancelling
    cancelling --> cancelled
    queued --> cancelled
    offered --> cancelled
    dispatched --> unknown: lease expired
    running --> unknown: lease expired
    cancelling --> unknown: lease expired
    unknown --> running: node reconnect + proof
    unknown --> succeeded: terminal reconciliation
    unknown --> failed: operator reconciliation
```

`unknown` 表示云端不知道现场状态，不等于失败，也不得立即把任务分派给另一台节点。

### 8.2 分派协议

1. 云端按 capability、schema、管理员授权、健康、空闲 slot 和标签选择候选节点。
2. 云端创建短期 offer lease，发送 `job_offer`。
3. Node 完成 schema、容量、磁盘、许可证和输入可用性预检。
4. Node 先把 job 和 lease 原子写入本地 SQLite，再发送 `job_accept`。
5. 云端以相同 lease ID 把状态改为 `dispatched`。
6. Node 下载输入并启动 Worker，持续续租。

节点收到重复 offer 时，根据本地 `job_id + request_digest` 返回原 accept/reject，不重复执行。

### 8.3 断线与租约

- 运行任务每 15 秒续租，默认租约 60 秒；参数可配置。
- 连接断开后，节点继续运行已开始任务，并把重要事件保存在本地 outbox。
- 租约过期后云端标记 `unknown`，进入恢复宽限期，不自动重派。
- 节点重连时上报所有非终态任务的 job、request digest、lease、本机阶段、PID、心跳和终态文件摘要。
- 云端对账后续租、接收终态，或要求节点停止孤儿任务。
- 只有明确证明 Worker 尚未开始，任务才能安全回到 `queued`。
- 已进入外部软件执行阶段的任务不自动跨节点重试。

### 8.4 节点重启

本地 SQLite 记录任务台账；任务目录的 `terminal.json` 是本机唯一终态文件。Node 启动时：

1. 扫描本地非终态台账；
2. 检查 Worker PID、boot ID、进程创建时间和任务目录；
3. 读取 `terminal.json`；
4. 能证明仍在运行则恢复监控；
5. 有终态文件则加入 outbox 等待回传；
6. 无进程无终态则标记 `NODE_RESTARTED_DURING_JOB`，不伪造成功。

## 9. 文件与产物传输

### 9.1 输入

Node 不访问整个用户 workspace。云端只为显式引用的文件创建短期、单任务、只读下载凭证。Node 下载后校验 SHA-256、声明大小、扩展名和内容类型。凭证不能列目录、不能换路径、不能用于其他 job。

### 9.2 上传

大产物不通过 WSS 消息传输。Node 使用 HTTPS 分块上传：

```text
POST /v1/software-jobs/{job_id}/artifacts/upload-session
PUT  /v1/compute/transfers/{transfer_id}/parts/{part_number}
POST /v1/compute/transfers/{transfer_id}/complete
```

上传校验 artifact ID、job 与租约、文件大小、分块摘要、最终 SHA-256、配额、允许类型及压缩包安全。

### 9.3 云端生命周期

Node 上传完成后先进入：

```text
<user_root>/.zcbot_cache/<task_id>/software_jobs/<job_id>/
```

该目录默认隐藏且有 TTL。用户或 agent 明确导入后复制到：

```text
<working_dir>/materials/simulation/<job_id>/
```

最终图、PDF、视频和可编辑工程可通过 `publish_artifacts` 提升为对话产物。真实文件仍是事实源。

## 10. zcbot 工具面

```text
compute_capability_list
software_job_submit
software_job_status
software_job_cancel
software_job_artifact_import
```

- capability list 只返回用户有权使用且有健康节点承载的能力；
- submit 只接受 capability schema，不接受 node ID、命令和路径；
- 节点选择由平台完成；
- status 返回阶段、进度、指标、重要事件和产物 manifest；
- cancel 按 ActionPolicy 分类并审计；
- artifact import 只接受 manifest 中的 artifact ID。

长任务不得让 agent 持续空等。完成时更新 Web 任务卡并通知用户，但不自动启动新 LLM run；用户点击“分析结果”或回复继续后再查询并导入产物。

## 11. Computer Use 与屏幕采集

优先级：软件官方 API/SDK → Windows UI Automation → 截图视觉坐标 → 暂停人工处理。Computer Use 不是工业计算主协议，结构化进度和结果始终优先。

首期 DesktopRunner 内部能力：

```text
session.health
window.list
window.capture
window.wait
popup.detect
process.launch_adapter
process.cancel_adapter
```

后续经安全评审后才开放点击、输入、快捷键和视频控制。优先使用 `automation_id + control name + window identity`，坐标点击只作最后手段。

截图与视频规则：

- 默认只采集关键事件截图；
- 优先捕获目标窗口；
- 敏感信息上传前遮罩；
- 视频默认关闭，显式启用时建议 1280×720、5–10 FPS、H.264 分段；
- 采集失败不得使专业软件任务失败；
- 模型只按需读取关键帧，不持续消费完整视频。

## 12. Origin 首批适配器

### 12.1 接口与执行位置

首期使用 Origin 官方推荐的外部 Python `originpro`。它能读写数据、创建和修改图形、导出图形，并启动可见或隐藏的 Origin；需要 Windows 本机安装并授权 Origin 2021 或更高版本。

- [Origin External Python](https://docs.originlab.com/externalpython/)
- [Origin Automation Server](https://docs.originlab.com/com/)
- [Origin 图形导出](https://docs.originlab.com/user-guide/publishing-and-export/)

C# COM 只作未覆盖能力或旧版本备用，并与实际 Origin 版本匹配。Origin Worker 由 DesktopRunner 在专用登录账号会话内启动，以统一用户 profile、许可证上下文、COM 会话和截图来源。默认隐藏执行；视觉验收时使用可见模式。

### 12.2 首期 capability

只开放 `origin.plot@v2`，接受 1–16 个 CSV、XLSX 或规范化 JSON 输入，不接受任意 Python、LabTalk、模板文件或宏。

```json
{
  "schema_version": 2,
  "inputs": [
    {"key": "seven_day", "artifact_id": "5af18255-c859-43f3-a424-220bc68b7db2", "selector": {"sheet": "Sheet1"}},
    {"key": "twenty_eight_day", "artifact_id": "6bf29366-d960-54f4-b535-331cd79c8ec3"}
  ],
  "operation": {
    "plot": {
      "type": "line_scatter",
      "series": [
        {"input": "seven_day", "x": "Temperature", "y": "Strength", "label": "7 d"},
        {"input": "twenty_eight_day", "x": "Temperature", "y": "Strength", "label": "28 d"}
      ],
      "template": "publication_double_column",
      "title": "温度对抗压强度的影响",
      "x_axis": {"title": "温度", "unit": "°C", "scale": "linear"},
      "y_axis": {"title": "抗压强度", "unit": "MPa", "scale": "linear"},
      "legend": {"enabled": true, "position": "top_right"},
      "error_bars": null
    }
  },
  "outputs": [
    {"key": "project", "type": "project", "format": "opju"},
    {"key": "figure_png", "type": "figure", "format": "png", "options": {"dpi": 600}},
    {"key": "figure_svg", "type": "figure", "format": "svg"},
    {"key": "figure_pdf", "type": "figure", "format": "pdf"}
  ]
}
```

当前仍只开放一个 `origin.plot@v2` 契约。`series[]` 统一使用数据角色字段：常规二维图为 `x/y`，误差棒为 `x/y/y_error`，XYZ 图为 `x/y/z`；服务端和 Node 均按 `type` 做判别校验。图形类型包括 line、scatter、line_scatter、column、bar、grouped_column、y_error、contour、surface_3d、ternary 和 heatmap，其中 heatmap 要求完整、等间距且无重复坐标的规则 XYZ 网格。后续可在同一角色模型内增加 box、histogram、XRD 堆叠图、热分析联图和多面板布局，不拆 capability；只有新增不同执行语义（如拟合、统计分析）时才增加 operation。

上述 JSON 同时是提交工具与云端账本、Windows Node 之间的 artifact 输入契约。
Agent 优先复用已有 artifact UUID；普通 task 文件先逐个调用
`register_artifact(path)` 获得 UUID，再以 `inputs`、`operation`、`outputs` 调用
`software_job_submit`。登记输入不会把文件发布为聊天交付物。v2 是当前唯一协议，
不读取 v1 请求或旧本地任务格式。

### 12.3 模板与产物

字体、线宽、配色、图幅和导出参数由管理员审核的模板定义。请求只引用模板 ID，provenance 记录模板、Origin、适配器版本和输入 SHA-256。

```text
D:\ZcbotNode\jobs\<job_id>\
├── request\request.json
├── input\<key>\<filename>
├── work\
├── logs\events.jsonl
├── screenshots\
├── recordings\
├── output\
│   ├── project.opju
│   ├── figure.png
│   ├── figure.svg
│   ├── figure.pdf
│   ├── plot-spec.json
│   └── provenance.json
├── artifacts.json
└── terminal.json
```

`terminal.json` 使用临时文件、flush 和原子 replace。成功前必须完成产物校验和 manifest 写入。

自动验收包括：输出存在且非空、PNG 尺寸/DPI、SVG/PDF 可解析、系列数量、轴标题/单位/图例、OPJU 保存、provenance 完整、Origin 正常退出且无许可证泄漏。

## 13. 并发、资源与许可证

- 每项 capability 独立声明 `max_concurrency`；
- Origin 默认并发 1；
- Origin 实例不跨 job 共享；
- 启动前检查内存、磁盘、桌面会话和许可证；
- Node 使用有界队列，云端只向有空闲 slot 的节点发 offer；
- 超时区分启动、无进展、总运行和取消宽限期；
- 取消先协作式退出，超时后回收精确进程树；
- PID、创建时间、可执行文件摘要与 job 绑定，避免误杀。

## 14. 安全与审计

- Node 只需出站 HTTPS/WSS，Windows 不开放业务端口；
- RDP 通过 VPN/堡垒机，不暴露公网；
- mTLS 验证节点，禁止跳过服务端 TLS；
- Service、DesktopRunner、运维账号分离且不授予管理员权限；
- 节点私钥存 Windows Certificate Store 并限制 ACL；
- capability schema 是唯一业务输入入口；
- 不接受命令、脚本、URL、绝对路径、UNC 和环境变量覆盖；
- 适配器与模板只由管理员部署；
- Worker 默认无外网，许可证服务器单独放行；
- 未知 capability 和未知 UI 动作 fail closed。

审计记录提交人、task、capability、node、软件/模板/适配器版本、分派、续租、取消、重连、终态、Computer Use 动作、输入输出摘要和导入位置。不得记录密码、Token、许可证密钥或未脱敏截图。

## 15. 可观测性与错误码

Node 心跳上报版本、OS、boot ID、connection epoch、CPU、内存、磁盘、上传队列、DesktopRunner 状态、软件版本、许可证健康、slot、运行 job 和 outbox 积压。

稳定错误码：

```text
NODE_OFFLINE
NODE_CAPABILITY_UNAVAILABLE
NODE_DISK_INSUFFICIENT
DESKTOP_SESSION_UNAVAILABLE
ADAPTER_VERSION_MISMATCH
INPUT_HASH_MISMATCH
ORIGIN_NOT_INSTALLED
ORIGIN_LICENSE_UNAVAILABLE
ORIGIN_START_TIMEOUT
ORIGIN_AUTOMATION_FAILED
OUTPUT_VALIDATION_FAILED
ARTIFACT_UPLOAD_FAILED
JOB_CANCELLED
NODE_RESTARTED_DURING_JOB
```

用户侧只返回可操作说明、是否可重试和 retry-after；完整诊断留在节点和管理员日志。

## 16. 部署建议

```text
D:\ZcbotNode\
├── app\
├── config\node.json
├── state\node.db
├── logs\
├── jobs\
├── runtimes\
├── adapters\
├── templates\
└── updates\
```

首期云主机建议：Windows 11 Enterprise 或经验证且有安全更新的 Windows 10 Enterprise、8 vCPU、32 GB RAM、200 GB 系统盘、500 GB 独立数据盘、CPU 实例。Origin 二维科研绘图不要求独立 GPU。

Windows 基线：固定版本并受控更新；禁止休眠和自动锁屏；固定分辨率与缩放；数据盘固定盘符；完成 Origin 人工基线任务；创建三个独立账号；DesktopRunner 登录后自动启动；仅允许必要出站和受控运维；稳定后制作镜像和恢复手册。

## 17. 实施阶段

### Phase 0：环境探针

- 确认 Windows、Origin/OriginPro 精确版本和许可证；
- 手工导入并导出 OPJU、PNG、SVG、PDF；
- 验证外部 `originpro` 可见/隐藏实例；
- 验证账号、RDP 断开、锁屏策略和截图；
- 连续运行 24 小时，确认许可证和残留进程；
- 测量典型任务时间、文件和磁盘占用。

### Phase 1：最小闭环

- enrollment、节点表、WSS Connection Manager；
- Node 注册、证书、心跳、能力上报；
- job 表、幂等提交、offer/accept 和基本租约；
- Origin 二维 XY、柱/条形、Y 误差棒、XYZ 等高线/三维曲面/三元图和规则网格热图；
- 输入下载、分块上传、SHA-256；
- zcbot 查询、取消、导入和发布；
- 最终截图与稳定错误码。

### Phase 2：可靠性与绘图可用性

- outbox、重连对账、unknown 状态和节点重启恢复；
- bar、box、histogram、heatmap、误差棒、多系列；
- 模板版本、自动机检、视觉验收；
- Web 任务卡、完成通知和渠道通知；
- 事件截图和可选录像；
- Origin 内置 skill 和回归样例集。

### Phase 3：平台化

- 经审核的 Computer Use 动作；
- 节点禁用、证书轮换、配置 revision、自动升级；
- 多节点选择、标签和许可证容量；
- Fluent、Aspen、CAD 适配器；
- 根据真实负载决定 GPU 节点或统一调度器。

## 18. 首期验收标准

1. Windows 不开放业务入站端口，Node 能通过 mTLS WSS 注册、重连和心跳。
2. 云端能发现 `origin.plot@v2`、软件版本、健康和 slot。
3. 同一幂等键不会创建两个任务。
4. 双连接时只有最新 epoch 能接受任务。
5. zcbot 能用 CSV 生成指定模板图并获得 `job_id`。
6. OPJU、PNG、SVG、PDF 均可打开并通过自动检查。
7. zcbot 能校验、导入和发布结果。
8. 连续执行 50 个任务，无残留进程、跨任务污染或许可证泄漏。
9. WSS 断开时任务继续，重连后能对账。
10. 云端或 Node 重启不会重复执行或误报终态。
11. 取消能结束精确进程树，不误杀其他实例。
12. 截图/录像失败不影响主任务。
13. 非法路径、脚本、越权 job、超限文件和伪造 artifact ID 被拒绝。
14. 提交、分派、取消、Computer Use 和产物导入均有审计。

## 19. 已否决方案

- **云端直调 Windows OpenAPI**：首版简单，但入站网络、设备身份、租约和多节点仍需重做；只保留 loopback 诊断 API。
- **Windows 安装完整 zcbot**：形成两套会话、模型、权限和状态；Node 只做执行。
- **全程 Computer Use**：对窗口和会话敏感且不适合数值结果；官方 API/SDK 为主。
- **Go 编写 Node**：Windows Service、COM/.NET、UI Automation、Named Pipes 更适合 .NET；Python 仅作固定适配器。
- **SMB + WinRM**：任意命令、共享权限、恢复和审计边界较差。

## 20. 实施前待确认

- 云厂商、Windows 镜像、网络出口和授权；
- Origin/OriginPro 精确版本；
- 节点锁或浮动许可证及并发数；
- 典型 Origin 输入和期望结果；
- 首批图形类型与现有绘图模板；
- 输入、产物、任务容量和保留期；
- 云端域名、内部 CA/mTLS 和 enrollment 管理；
- 首期完成通知范围；
- Windows 维护责任人与操作窗口。
