@windsland52/maafw-live 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +278 -2
  3. package/bin/maafw-live.mjs +25 -0
  4. package/docs/daemon-protocol.md +116 -0
  5. package/docs/keyframe-evidence-contract-v0.md +61 -0
  6. package/docs/keyframe-retention-contract-v0.md +236 -0
  7. package/lib/client/daemon.js +234 -0
  8. package/lib/client/daemon.js.map +1 -0
  9. package/lib/commands/annotate.js +172 -0
  10. package/lib/commands/annotate.js.map +1 -0
  11. package/lib/commands/calibrate.js +61 -0
  12. package/lib/commands/calibrate.js.map +1 -0
  13. package/lib/commands/color.js +73 -0
  14. package/lib/commands/color.js.map +1 -0
  15. package/lib/commands/crop.js +228 -0
  16. package/lib/commands/crop.js.map +1 -0
  17. package/lib/commands/env.js +215 -0
  18. package/lib/commands/env.js.map +1 -0
  19. package/lib/commands/index.js +64 -0
  20. package/lib/commands/index.js.map +1 -0
  21. package/lib/commands/input.js +219 -0
  22. package/lib/commands/input.js.map +1 -0
  23. package/lib/commands/kf.js +131 -0
  24. package/lib/commands/kf.js.map +1 -0
  25. package/lib/commands/reco.js +211 -0
  26. package/lib/commands/reco.js.map +1 -0
  27. package/lib/commands/repl.js +698 -0
  28. package/lib/commands/repl.js.map +1 -0
  29. package/lib/commands/runtime.js +514 -0
  30. package/lib/commands/runtime.js.map +1 -0
  31. package/lib/commands/skill.js +169 -0
  32. package/lib/commands/skill.js.map +1 -0
  33. package/lib/commands/timing.js +229 -0
  34. package/lib/commands/timing.js.map +1 -0
  35. package/lib/commands/version.js +66 -0
  36. package/lib/commands/version.js.map +1 -0
  37. package/lib/daemon/framed.mjs +2850 -0
  38. package/lib/daemon/reco_child.mjs +146 -0
  39. package/lib/exec.js +96 -0
  40. package/lib/exec.js.map +1 -0
  41. package/lib/flags.js +42 -0
  42. package/lib/flags.js.map +1 -0
  43. package/lib/image.js +90 -0
  44. package/lib/image.js.map +1 -0
  45. package/lib/index.js +139 -0
  46. package/lib/index.js.map +1 -0
  47. package/lib/interface/index.js +12 -0
  48. package/lib/interface/index.js.map +1 -0
  49. package/lib/interface/jsonc.js +95 -0
  50. package/lib/interface/jsonc.js.map +1 -0
  51. package/lib/interface/load.js +307 -0
  52. package/lib/interface/load.js.map +1 -0
  53. package/lib/interface/override.js +103 -0
  54. package/lib/interface/override.js.map +1 -0
  55. package/lib/interface/plan.js +188 -0
  56. package/lib/interface/plan.js.map +1 -0
  57. package/lib/pkg.js +18 -0
  58. package/lib/pkg.js.map +1 -0
  59. package/lib/protocol.js +90 -0
  60. package/lib/protocol.js.map +1 -0
  61. package/lib/runtime/actions.js +110 -0
  62. package/lib/runtime/actions.js.map +1 -0
  63. package/lib/runtime/keyframes.js +73 -0
  64. package/lib/runtime/keyframes.js.map +1 -0
  65. package/lib/runtime/session.js +86 -0
  66. package/lib/runtime/session.js.map +1 -0
  67. package/lib/types/client/daemon.d.ts +86 -0
  68. package/lib/types/commands/annotate.d.ts +3 -0
  69. package/lib/types/commands/calibrate.d.ts +7 -0
  70. package/lib/types/commands/color.d.ts +9 -0
  71. package/lib/types/commands/crop.d.ts +3 -0
  72. package/lib/types/commands/env.d.ts +2 -0
  73. package/lib/types/commands/index.d.ts +13 -0
  74. package/lib/types/commands/input.d.ts +17 -0
  75. package/lib/types/commands/kf.d.ts +10 -0
  76. package/lib/types/commands/reco.d.ts +23 -0
  77. package/lib/types/commands/repl.d.ts +2 -0
  78. package/lib/types/commands/runtime.d.ts +48 -0
  79. package/lib/types/commands/skill.d.ts +17 -0
  80. package/lib/types/commands/timing.d.ts +64 -0
  81. package/lib/types/commands/version.d.ts +3 -0
  82. package/lib/types/exec.d.ts +31 -0
  83. package/lib/types/flags.d.ts +58 -0
  84. package/lib/types/image.d.ts +27 -0
  85. package/lib/types/index.d.ts +1 -0
  86. package/lib/types/interface/index.d.ts +11 -0
  87. package/lib/types/interface/jsonc.d.ts +9 -0
  88. package/lib/types/interface/load.d.ts +113 -0
  89. package/lib/types/interface/override.d.ts +33 -0
  90. package/lib/types/interface/plan.d.ts +47 -0
  91. package/lib/types/pkg.d.ts +6 -0
  92. package/lib/types/protocol.d.ts +108 -0
  93. package/lib/types/runtime/actions.d.ts +166 -0
  94. package/lib/types/runtime/keyframes.d.ts +43 -0
  95. package/lib/types/runtime/session.d.ts +53 -0
  96. package/lib/types/update-check.d.ts +20 -0
  97. package/lib/types/usage.d.ts +3 -0
  98. package/lib/update-check.js +97 -0
  99. package/lib/update-check.js.map +1 -0
  100. package/lib/usage.js +50 -0
  101. package/lib/usage.js.map +1 -0
  102. package/package.json +81 -4
  103. package/skills/README.md +51 -0
  104. package/skills/maafw-live/SKILL.md +263 -0
  105. package/skills/maafw-live/references/examples.md +238 -0
  106. package/skills/maafw-live/references/pitfalls.md +118 -0
  107. package/skills/maafw-live/references/workflows.md +159 -0
@@ -0,0 +1,159 @@
1
+ # 动线细节:命令级选择与实测经验
2
+
3
+ 本文件是 [SKILL.md](../SKILL.md) 四条动线的展开。字段与参数以
4
+ [daemon-protocol.md](https://github.com/Windsland52/maafw-live/blob/main/docs/daemon-protocol.md) 为准;
5
+ 这里只写"为什么这么选、什么时候不该这么选、实测值是多少"。
6
+
7
+ ## A. 观测:什么时候用事件、什么时候用轮询
8
+
9
+ | 目标 | 手段 | 为什么 |
10
+ | :--- | :--- | :--- |
11
+ | 知道画面何时开始/停止变化 | `stream start` + 订阅 `event`(change / stable) | 事件带变化区域与帧序,不用自己比像素 |
12
+ | 确认某个状态现在在不在 | `reco`(对当前帧/缓冲帧) | 识别比"看图判断"确定 |
13
+ | 拿"变化前后"的画面 | 事件锚点帧 + `frame get --seq` | 锚点帧已在 L0/锚区,不需要重截 |
14
+ | 找"某个东西在哪" | `annotate` → 选号 → 得 ctrl 坐标 | 候选区域的坐标是算出来的,不是猜的 |
15
+ | 找"这里是什么颜色" | `color --roi` | 实测均值/HSV/主色,避免模型报色值 |
16
+
17
+ 候选表的分辨率预期(实测,同一画面两种交付尺寸):
18
+
19
+ | | 720p(6 帧) | 1080p(1 帧) |
20
+ | :--- | :--- | :--- |
21
+ | 去重后候选 | 中位 54 / 最大 135 | 96 |
22
+ | 进表数(上限 30) | 30(4/6 帧打满) | 30(打满) |
23
+ | **画面覆盖率** | 中位 **19%** | **6.2%** |
24
+
25
+ 上限 30 是固定的(面向模型上下文预算),所以**分辨率越高,"被标记的画面比例"越低**——1080p 下候选表
26
+ 更像"取样"而不是"覆盖"。高分辨率场景不要指望它覆盖画面:优先 OCR(语义最强),其次点选(`crop --point`)。
27
+
28
+ 同一条纪律也适用于采集:项目跑在高分辨率时,采集要在同一空间里做——
29
+ `maafw-live repl --kind adb --target <addr> --short-side 1080`,一次会话里 `screencap` + `kf promote latest`
30
+ (已在 1920×1080 上验过);项目模式跟 `interface.json` 的 `display_short_side` 走,别手动改。
31
+
32
+ 节奏与容量:
33
+
34
+ - `stream` 的 fps 与 scale 决定 CPU 与环内容量;活跃场景 5–10 fps 够用,静态等待降到 1–2 fps。
35
+ - 环形缓冲(L1 小图)与 L0 原图缓存是两条链:**环里的小图能看不能当证据**,原图才能裁模板(见动线 C/D)。
36
+ - L0 有双重上限(张数 + 字节预算),先淘汰滚动区;`kf status` 看实时占用与 seq 区间——升格前拿不准就先看它。
37
+
38
+ 校准(写进 pipeline 之前做一次,换场景再复测):
39
+
40
+ ```bash
41
+ $ maafw-live calibrate --project <dir> # 静止画面采样,给 blockThresh / changeGlobal 推荐值(REPL 无此命令)
42
+ maa> stream start --fps 6 --block-thresh <推荐> --change-global <推荐>
43
+ ```
44
+
45
+ ## B. 识别实测:怎么选图像来源
46
+
47
+ | 来源 | 命令 | 用途 |
48
+ | :--- | :--- | :--- |
49
+ | 离线 PNG | `reco --image f.png` | 复现历史帧上的识别;做参数扫描 |
50
+ | 缓冲帧 | `reco --seq <n>` | 对"刚刚那一帧"复测(需 `repl` 且已 `stream start`) |
51
+ | 当前画面 + 真机动作 | `reco --act --node <json>` | 验证 target 框语义与落点(**会真的动设备**) |
52
+
53
+ 要点:
54
+
55
+ - 整节点透传(`--node`)只在"节点自己没写模板、而调用方提供了模板图"时补模板引用;其余字段一律原样交给框架,
56
+ V1 扁平与 V2 嵌套不做转换。字段语义有问题就查 MaaLLMWiki 的协议原文,不要在本工具层猜。
57
+ - `--sweep` 用来找阈值起点,不是用来"调到达标":扫描结果的最高分若 < 0.5,说明模板与画面不匹配。
58
+ - `--act` 会先识别、再动作;识别未命中时动作半不执行(如实报在 `stage`)——不要把"没执行"读成"执行了但没效果"。
59
+ - 图像是判据的一部分:小图空间里算出的 box **不能**直接抄成 pipeline 的 roi。
60
+
61
+ ## C. 模板裁剪:输入怎么给、结果怎么判
62
+
63
+ 输入选择(**框该给多大有实测结论**,15 例真实 UI 目标):
64
+
65
+ - 知道大致范围 → `--roi x,y,w,h`(**宽松框**)。实测:**每边留 6–10px 最稳**;把上一次 snap 的输出直接
66
+ 当输入也可以(文字类目标第二遍只差 ±1px)。**余量给到元素尺寸的 60–80% 就开始出问题**——
67
+ 图鉴图标给 110×110 时 snap 收到 57×69(真值 69×62,宽度少了 12px),物品卡片给 180×180 时高度被拉到 152,
68
+ **而 `positionOk` 不会报警**(框仍与真值大幅重叠)。所以别用大余量,也别把 `positionOk` 当"框完美"的证明。
69
+ - 想知道框稳不稳 → **同一目标再裁一遍比 `box`**:文字类 ±1px;内部有渐变的图形可能再收一档
70
+ (实测物品卡片 120×120 → 104×113),那就把第二遍的结果当最终框。
71
+ - 只知道一个点 → `--point x,y [--pad n]`(默认外扩 24px),点→ROI 派生与裁剪共享同一条 snap 链。
72
+ - 边界贴太紧、目标撑满框、大面积纯色 → snap 可能撤不动;工具会把收紧框、加边距、外扩档、原框都进候选池,
73
+ 位置正确者优先。仍不达标就换框,或改走 `annotate` 选点。
74
+
75
+ 结果判读:
76
+
77
+ | 字段 | 怎么读 |
78
+ | :--- | :--- |
79
+ | `positionOk` | **第一判据**:模板在同帧上是否落回裁剪处。false = 模板不独特,别用 |
80
+ | `score` | 第二判据:位置对但得分 < 0.7 时提示注意跨帧稳定性 |
81
+ | `snapped` | snap 是否收紧成功;false 表示用了原宽松框 |
82
+ | `cross` | 跨帧验证(另抓一帧再匹配);`score` 大幅衰减或 `posOk=false` = 对动态区域敏感 |
83
+ | `spaceCheck` | 源帧空间 vs 当前控制器尺寸;`match:false` 时模板与当前识别空间不一致 |
84
+ | `provPath` | L2 出处侧车路径;`--no-prov` 时为 null |
85
+
86
+ 耗时预期:自匹配是"逐候选起一个识别子进程"。**实测(MuMu v5 + maa-node 5.14.2,1280×720)**:
87
+ 健康区域 **9 次评估 / 约 10.5s**(首个候选就位置正确、得分 ≥0.99 → 早停);退化区域 **17 次评估 / 约 20s**
88
+ (跑满候选池 + 两轮 ±2px 精修)。所以"数十秒"是上限口径,**耗时翻倍本身就是"这块内容不独特"的信号**。
89
+ 分辨率影响很小:同元素在 1920×1080 上同样 9 次评估、11.9s(+13%)——成本由起子进程主导,不由像素数主导
90
+ (`snapTol` 是通道差之和、`snapFrac` 是比例,两者都与分辨率无关,实测 4/4 通过)。
91
+ 不要误判为卡死;一次裁剪的成本要算进动线预算。
92
+
93
+ 关于 snap 的预期(同一批实测):**框给得越大,snap 越可能不起作用**——480×270 这种占屏 1/6 的宽松框,
94
+ 24 例里只有 1 例真的改变了最终框,其余都被候选池退回原框(`snapped:true` 只说明"算出了收紧框",
95
+ 不代表最终用了它)。要 snap 出力,宽松框应当**贴着目标放大一圈**(例如目标 70×60、`--roi` 给 78×76),
96
+ 而不是整屏网格。判据始终是 `positionOk` 与得分,不指望 snap 救场。
97
+
98
+ 裁剪产物(L2)与出处:
99
+
100
+ ```jsonc
101
+ // tpl.png.prov.json(schema 1)
102
+ {
103
+ "level": "L2",
104
+ "derivedFrom": { "kind": "kf", "id": "kf:<库UUID>:0142", "sha256": "...", "ctrlW": 1280, "ctrlH": 720 },
105
+ "transform": { "op": "crop", "resize": false, "scale": 1, "loose": [...], "crop": [...] },
106
+ "selfMatch": { "score": 1, "positionOk": true, "box": [...], "tries": 9 },
107
+ "cross": null
108
+ }
109
+ ```
110
+
111
+ 出处里**没有**设备地址/目标——L2 是要提交进仓库的交付物,设备来源留在本地 manifest。
112
+
113
+ ## D. 留存与离线裁剪:时间线
114
+
115
+ ```
116
+ 观测到状态 ──┬─ kf promote latest ← 必须在捕获它的那个 daemon 会话里做
117
+ │ (身份在接受请求时固定;已淘汰则失败,不取新帧冒充)
118
+ │
119
+ ├─ kf list / kf resolve ← 纯离线,不依赖 daemon 存活
120
+ │
121
+ └─ crop --from-kf <ID> ← 离线裁剪:不需要设备,也不需要那次会话还活着
122
+ ```
123
+
124
+ 判断表:
125
+
126
+ | 情形 | 结论 |
127
+ | :--- | :--- |
128
+ | `kf resolve` → `available` | 文件在、哈希对、元数据全,可作裁剪源 |
129
+ | `missing` | 本机不可复核(文件丢失/无此 ID/裸序号);**不代表历史从未观测** |
130
+ | `corrupt` | sha256 不匹配(文件被改/损坏),拒绝裁剪 |
131
+ | `unsupported` | manifest 版本不认识或结构不符;不默认重建 |
132
+ | L0 已淘汰、只剩 L1 | 只能作参考帧,**不作 state 证据本体** |
133
+
134
+ 裁剪源选择:
135
+
136
+ - 状态还在画面上 → 直接 `crop --roi`(热缓存路径,快,且能顺带跨帧验证)。
137
+ - 状态已消失/设备不在手上/换了会话 → `crop --from-kf`(离线;跨帧验证缺省关,`--cross` 才做)。
138
+ - 两边都要(状态可复现时):`--from-kf ... --cross`,同时得到"来源固定"与"新帧仍稳定"两个结论。
139
+
140
+ 升格容量纪律:L0 缓存有界,`kf promote` 时机会决定你还有没有证据。动线纪律是**看到即升格,不攒到最后**;
141
+ 库满额时工具会**拒绝新增并报告**(不会后台静默删除已升格帧),清理或扩容由人决定。
142
+
143
+ ## Z. 经验值速查(全部来自实测;改动与否都写清)
144
+
145
+ | 项 | 值 | 实测依据 | 状态 |
146
+ | :--- | :--- | :--- | :--- |
147
+ | 宽松框余量 | **每边 6–10px**(或上一次 `snap` 输出直接当输入) | 15 例真实 UI 目标:14/15 位置正确;大余量(60–80%)时 snap 会偏而 `positionOk` 不报警 | 使用纪律 |
148
+ | 模板判据 | 位置正确 → 跨帧稳定 → **空间一致** | 网格 91.7% / 真实 UI 14/15;空间不符时退出 `FINDINGS(3)` | 判据链 |
149
+ | 裁剪耗时 | 健康 **9 次评估 ≈10.5s**;退化 **17 次 ≈20s** | 24+36+15 例;1080p 仅 +13% | 预期口径 |
150
+ | 裁剪成本与分辨率 | 基本无关(`snapTol` 是通道差、`snapFrac` 是比例) | 1920×1080 同元素 9 次、1.1× 耗时 | 已验 |
151
+ | `snapTol` / `snapFrac` | 90 / 0.12 | A/B:调"敏感"(60 / 0.2)触发更多但**位置正确率 91.7% → 83.3%** | **未改**(数据不支持) |
152
+ | SoM 候选上限 | 30,截断**按横向分带轮转** | 6 帧 4 次打满、真实规模中位 54、默认上限只放出 41%;改前大厅 63 个底部候选全被截掉 | **已按数据改** |
153
+ | 候选合并 IoU | 0.6 | 0.4 / 0.6 / 0.8 → 合并总数 289 / 310 / 328(±6%,平坦区) | **未改** |
154
+ | edge z / 地板 | 1.2 / 2000 | 放松到 0.6 / 600 后 edge 独立候选反而更少(17 → 15,大簇被 conn 吸收) | **未改**(别调它) |
155
+ | 候选覆盖率预期 | 720p 约 19%;**1080p 仅 6.2%** | 上限固定、分辨率越高覆盖越低 | 使用预期 |
156
+ | 识别阈值起点 | 实测最高置信度 **− 0.1**;得分 < 0.5 视为不匹配 | 参数扫描 + 假命中修复后的实测 | 使用纪律 |
157
+
158
+ 要动上面任何一个常数:先跑 `npm run survey:crop` / `npm run survey:som`(本仓 `scripts/`,离线、不需要设备),
159
+ 拿 A/B 数据再改——本表里"未改"的项都是量过之后**决定不动**的,不是没人管。