Files
nodeagent/docs/VM-VERIFICATION.md
T
jkooe 54f7f4c7ab test(vm): Parallels Win11 ARM 真机验证 —— A 组 15/0 + v1.5 四项全过 + 锚点端到端通过
## 环境
Parallels 27 + Win11 ARM,VM 10.211.55.9(共享网络);被控端 `-NodeId win-arm -AllowInput`。

## ⭐ B5 结论(与预期不同,但更有价值)
| 组合 | 结果 |
|---|---|
| `win-x64` 包(内含 x64 Node) | ⚠️ **能启动、能 listen 8765,但 TLS 握手 60s 不完成** → 协议层不可用(Prism 下) |
| **换 ARM64 Node(同版本 v22.20.0)** | ✅ **完全正常**:握手成功、连接、51 项能力 |

× 结论:`nodeagent-win-x64.zip` 不能在 ARM Windows 上实用;ARM 上需 ARM64 Node。

## 验证结果
- **A 组(verify.mjs 17 项)**:✅ 15 通过 / 0 失败 / 1 跳过(29.5s)
- **B1 v1.5 四项**:✅ 全过 —— 字符串热键 / 预设别名(`copy→ctrl+c` 映射正确)/ 长按 /
  后台定向投递(**explorer 命中 138 窗口**、WindowsTerminal 10 窗口)
  → **v1.5.0「未经真机就发版」的债,至此还清**
- **B4 锚点端到端**:✅ collect(62 条) → 上传云盘 → verify 判定「链已增长」+ 精确明细
- B2/B3:⏸ 阻塞(需 restart,而计划任务启动失败 —— 手工跑却完全正常)

## 本轮真机抓到的 2 个真 bug(都已修)
1. `control.ps1:100` 的 `$scheme:` 被 PowerShell 当 drive 引用 → **解析期错误 → 整个脚本不可用**
   (stop/start/status 全废);已修 + 加守卫(扫全部 .ps1 的 `$ident:`)
2. `anchor-audit.mjs` 调用**不存在的** `audit head` 子命令 → 改为 `invoke system.audit.head`
   (这种「能力存在但 CLI 无子命令」的错配,不真跑一次发现不了)

## 文档
`docs/VM-VERIFICATION.md` 补「实际验证结果」节 + 5 条新增排查项(安装/密钥/CLI 语法/计划任务)
2026-10-11 00:18:43 +08:00

223 lines
10 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.
# VM 验证清单(Parallels Desktop 27 + Windows 11 ARM)
> 用途:Windows 真机不可用时,用 **Parallels 27 的 Windows 11 ARM 虚拟机**提前跑掉
> **架构无关**的验证项,把"等机器"的时间省下来。
>
> ⚠️ **本清单的结论必须按 §5 的规则标注**:VM 验过的项写「VM 已验」,并注明
> 是否仍需真机复验。**不要把 VM 结论当作真机结论** —— 二者架构不同。
---
## 1. 能补什么 / 不能补什么
| 类别 | 项 | VM 可否 |
|---|---|---|
| **协议层**(与架构无关) | v23 三防护(握手封禁/连接上限/空闲断开)、审计锚点端到端、v26 计划任务清理逻辑 | ✅ **可验,结论直接可用** |
| **输入注入层** | v1.5 四项(字符串热键/预设别名/长按/后台定向投递) | ✅ 可验(走 Win32 `SendInput`/`WM_APPCOMMAND`,ARM Windows 同样完整) |
| **安装与自持** | `install.cmd` 自提权、计划任务注册、受控重启 | ✅ 可验(VM 里也是真 Windows,机制一致) |
| **系统能力** | 进程/服务/文件/剪贴板/命令执行/`winget` | ✅ 可验 |
| **刻意不可验** | 第三方杀软拦截(火绒等) | ❌ VM 里只有 Defender |
| | 显示 / DPI / 多显示器 / 坐标校准 | ❌ VM 显示栈不同 |
| | 性能指标(P95 时延等) | ❌ VM 数字不可比 |
| **需注意** | `win-x64` 包在 ARM Windows 上走 **Prism 模拟** | ⚠️ 能跑但慢;**这本身是值得记录的兼容性结论**(见 B5) |
---
## 2. 前置准备
```
① Parallels 27 装 Windows 11 ARM(Pro/Enterprise)
└ Apple silicon 只能跑 ARM 版 Windows(x86_64 仅 Pro/Business 的早期预览,性能显著更低)
② 网络 → 桥接(Bridged),不要用默认「共享网络」
└ 共享/NAT 下 VM 拿不到同网段 IP → UDP 广播发现(v4)测不了,Mac 也未必能直连
③ VM 内装 Node:优先 **ARM64 版**(避开 Prism 模拟层)
└ 若想验分发包,另见 B5(用项目打的 win-x64 包)
④ VM 内起被控端(二选一)
a. 免安装:双击 run-portable.cmd (不注册计划任务,适合快速验能力)
b. 正式装:解压 nodeagent-win-x64.zip → 双击 install.cmd(自提权,会建计划任务)
⑤ Mac 端登记设备并连接
nodeagent --node vm connect <VM的IP> --key <密钥> --insecure
nodeagent --node vm info # 看到 51 项能力即通
```
> 建议设备名用 `vm`,与真机 `win` 分开 —— 后续所有命令都在 `--node vm` 上跑。
---
## 3. 验证清单
### A. 基础验收(17 项,一步到位)
```bash
# 对齐 PRD FR-01~FR-08 的全套验收,可同时输出 Markdown 报告
node scripts/verify.mjs --host <VM的IP> --port 8765 --key <密钥> --insecure \
--report /tmp/vm-verify.md
```
**判定**:脚本自报通过项;报告存档(日后对比真机报告,差异项即为"架构相关")。
---
### B. 待办专项(逐条)
#### B1. v1.5 四项(该版当初未经真机就发版)
```bash
# ① 字符串热键(分隔符 + - 空格、大小写不敏感)
nodeagent --node vm key press "ctrl+shift+esc"
# 期望:{ pressed: true, chords: [...] }(被控端返回里**没有 keys 字段**,别按它判)
# ② 预设别名(约 50 个语义名)
nodeagent --node vm key press copy
# 期望:同上,且 args 走 preset 分支(非 hotkey)
# ③ 长按
nodeagent --node vm key press f24 --hold 800
# 期望:按下并保持 800ms
# ④ 后台定向投递(PostMessage 到指定进程,窗口被遮挡也生效)
nodeagent --node vm ps # 先取一个目标 PID
nodeagent --node vm key press f24 --route post --pid <PID>
# 期望:{ pressed: true };目标进程窗口被遮挡/最小化时**仍然生效**
```
**判定**:四条都返回 `pressed: true` 且无异常。
**选键建议**:用 `f24` / `shift` / `copy` 这类**无副作用**的键(F24 几乎无程序绑定)。
#### B2. v23 三防护(配置在 `agent.json` 的 `security` 段)
```jsonc
// VM 被控端数据目录下的 agent.json
{ "security": { "auth_ban": { "max_attempts": 3, "ban_ms": 60000 }, "idle_timeout_ms": 60000 } }
```
```bash
# ① 握手失败封禁:连续用**错误密钥**连 -> 达阈值后**正确密钥也被拒**
for i in 1 2 3; do nodeagent --node tmp connect <IP> --key WRONG --insecure; done
nodeagent --node tmp connect <IP> --key <正确密钥> --insecure
# 期望:前几次报 E_AUTH_FAILED;达到 max_attempts 后,即使是正确密钥也报被封禁
# ② 连接上限:并发开连接直到第 N+1 个被拒
# 期望:超出上限的连接被拒(E_NODE_BUSY 或等价错误)
# ③ 空闲断开:连上后静置超过 idle_timeout_ms
# 期望:连接被服务端主动断开,控制端收到 closed
```
**判定**:三种防护各自可达且**恢复后正常**(封禁到期、连接释放、重连成功)。
#### B3. v26 自重启任务清理(治"Running 僵尸")
```bash
# ① 触发受控重启
nodeagent --node vm restart # 重启会让配置变更生效,连接会短暂断开
# ② 重连后查看计划任务
nodeagent --node vm exec "schtasks /query /fo csv /tn \"nodeagent-selfrestart*\""
```
**判定**:
- 清理条件为「**非 Running** 或 **LastRunTime 早于 1 小时**」
- 刚创建的那个任务(当前 agent 的宿主)**必须仍在** ← 若它被清掉,说明误杀了宿主(严重)
- 一小时后复查:旧任务应已被清理,**不再累积**
#### B4. 审计锚点端到端(此前只做了离线 fixture 验证)
```bash
# ① 生成锚点(拉 VM 的链头)
node scripts/anchor-audit.mjs collect --node vm --out /tmp/vm-anchor.jsonl --note "VM 验证"
# ② 上传到链外(云盘 …/Project/NodeAgent/anchors/,文件名带年月日)
# ③ 从云盘下载回来再比对
node scripts/anchor-audit.mjs verify --anchors /tmp/vm-anchor.jsonl --node vm
# 期望:ok:true,verdict 为「链已增长」或「与锚点完全一致」
# (刚锚定就比对通常显示"已增长" —— 锚定动作自身也写一条审计,属正常)
```
**判定**:`collect` 能拿到链头、云盘上传成功、`verify` 返回 `ok:true`。
#### B5. `win-x64` 包在 ARM Windows 上的兼容性(额外结论)
```bash
# 把项目打的包解压到 VM,用**包内自带的 x64 Node**起被控端(走 Prism 模拟)
# 期望:能起、能被连接、基础能调用
```
**判定**:能跑 → 说明分发包对 ARM Windows 也友好(**值得写进 README 的加分结论**);
不能跑或异常 → 记录现象,并在文档里注明"分发包需 ARM64 版本方能原生运行"。
---
## 4. 一键顺序(建议)
```
A 基础验收(verify.mjs)
→ B1 v1.5 四项
→ B2 v23 三防护(改 agent.json 后需 restart)
→ B3 v26 清理(restart 后查任务)
→ B4 锚点端到端
→ B5 x64 包兼容性
```
每步完成后把结论记到 `docs/ROADMAP.md` §九 台账,**并标注来源是 VM 还是真机**。
---
## 5. 结论标注规则(强制)
| 情形 | 台账/CHANGELOG 写法 |
|---|---|
| 架构无关项(B2/B3/B4)在 VM 验过 | `✅ 已验证(VM · Windows 11 ARM)` |
| 输入/系统能力(A/B1)在 VM 验过 | `✅ 已验证(VM)`,**若涉及坐标/DPI 则加注「坐标类待真机复验」** |
| 杀软交互 / 显示 / 性能 | `⏳ 待真机`(VM 不可替代,**不得**因 VM 通过就标已验) |
| x64 包在 ARM 上跑通(B5) | `✅ 兼容性结论:win-x64 包可在 ARM Windows 运行(经 Prism)` |
> **一条纪律**:VM 与真机**架构不同**(真机 i7-12650H = x86_64)。任何"VM 通过"
> 都不能自动推出"真机通过";涉及**原生二进制、驱动、杀软、显示栈**的部分尤其如此。
> 宁可多留一条"待真机复验",也不要让台账出现无法追溯来源的"已验证"。
---
## 6. 已知 VM 环境差异(排查时先看这里)
| 现象 | 原因 | 处理 |
|---|---|---|
| `discover`(UDP 广播发现)无结果 | 网络是共享/NAT | 改**桥接** |
| 分辨率/坐标与真机不符 | VM 显示栈不同 | 只做逻辑验证,坐标待真机 |
| 性能数字明显偏低 | VM + 可能的 Prism 模拟 | **不要**采信 VM 的性能指标 |
| 杀软相关错误复现不了 | VM 里只有 Defender | 需真机(或另行安装第三方杀软) |
| x64 Node 启动慢/异常 | 走 Prism 模拟 | 换 ARM64 Node 复核 |
---
## 7. 实际验证结果(2026-10-11,Parallels 27 + Win11 ARM)
> 本节是**实测记录**,不是计划。环境:Parallels 共享网络,VM `10.211.55.9`,
> Mac 侧 `bridge100=10.211.55.2`;被控端 `-NodeId win-arm -AllowInput`。
### B5 结论(重要,与预期不同)
| 组合 | 结果 |
|---|---|
| **`win-x64` 包(内含 x64 Node)** | ⚠️ **能启动、能 listen 8765,但 TLS 握手 60s 不完成** → **协议层不可用**(Prism 模拟下) |
| **换成 ARM64 Node(同版本 v22.20.0)** | ✅ **完全正常**:TLS 握手成功、连接、51 项能力 |
**结论**:`nodeagent-win-x64.zip` **不能在 ARM Windows 上实用**。
在 ARM Windows 上需用 **ARM64 Node** 启动 `agent.mjs`(或替换包内 `node.exe`)。
### 各项结果
| 项 | 结果 |
|---|---|
| A 组(`verify.mjs` 17 项) | ✅ 15 通过 / 0 失败 / 1 跳过 |
| B1 v1.5 四项 | ✅ 全过(含 `route=post` 实测命中 138 窗口) |
| B4 锚点端到端 | ✅ 全过(含上传云盘) |
| B2 v23 三防护 | ⏸ 阻塞:需改配置 + restart,而计划任务当前启动失败 |
| B3 v26 清理 | ⏸ 同上 |
### 实测新增的排查项(补进 §6)
| 现象 | 原因 | 处理 |
|---|---|---|
| 装了却连不上(TLS 握手不完成) | **x64 Node 在 Prism 下协议层异常** | 换 ARM64 Node |
| `control.ps1` 报"变量引用无效" | 脚本里 `$var:` 被当 drive 引用(**解析期**错误 → 整个脚本废) | 已修(写 `${var}`);已加守卫 |
| 直接跑 `install.ps1` 后找不到 `PSK.txt` | **只有 `install.cmd` 才产生 PSK.txt** | 密钥在 `<数据目录>\agent.json` 的 `key` 字段 |
| 装完输入类能力不可用 | `install.cmd` 不传 `-AllowInput`(默认 false) | 用 `install.ps1 -AllowInput` |
| `nodeagent --node x cmd` 报"未知命令" | `--node` **前置需等号** | 写 `--node=x`,或放命令后 |
| 计划任务启动后端口不通 | 待查(手工跑正常) | `(Get-ScheduledTask -TaskName nodeagent).Actions` |