AutoPlayQA
AutoPlayQA
Framework de automatización de pruebas QA para Android: un motor de tareas con «ojos (percepción) + manos (acciones)» determinista y con compuerta de reconocimiento. El cerebro se delega en un agente de IA externo (Claude Code / Codex es accionado mediante MCP o CLI) — the project in sí no usa ningún modelo de lenguaje grande, coste de tokens 0.
El framework no está vinculado a ningún juego: el sismo de etiquetas de escenarios, los JSON de tareas, el imá de plantillas y el modelos de YOLO los por la parte (el proyecto doti juego probado). Este reposity only central de la parte común: el "Canal de perción, Backend de acciones, Motor de tareas con reconocimiento controlado, Recogida de evidivias de QA y Interfaz MCP / CLI".
Ídire
Inicio rápido — Hmm, keep as [Inicio rápido](#inicio-arapido ha... "Quick start":
Inicio rápido; anchor keep "#快速开始".
Fix the TOC in final.
Let's prepare final answer text directly.
Care — In the output, all raw HTML <p align="center"><img ... must keep unchanged.
Let me now type the output in full.# AutoPlayQA
QA de automatización para juegos de Android — Un motor de actividades con "ojos (percepción) + manitas (acciones)" deterministas y con puerta de reconocimiento. El cerebro se delega en un agente externo de IA (Claude Code / Codex, directed via MCP o CLI), and el proyecto itself no invoven a perdido literally: coste de tokens cero.
El "framework" no está viculado a ningún: el sistema de etiquetas de escena, lo JSON de tareas, las imágenes de plantillas y los modelos de YOLO los supone la parte integradora (el proyecto del juego probeado); this depósito solo se oca de la partاgen'érica: canal de perción, "backend" de accciones, motor de tareas con puerta de reconocimiento, evidencia de "QA" e interfaz de MCD / CLI.
Related MCP server: scrcpy-mcp
Índice
Características — hmm — Original heading "## 功能特性" → "## Caracteres" (Características).
Now section:
Percepción y acciones (ojos y manos determininistas)
📱 Detecta automáticamente emuladores y dispo actuales Android (ADB); soporta adb inalámbirds:
connect/pair(Android 11+) /tcip— switching with one click, en la configa se conecta automáticamente al inargar.🤖 Un dispositivo por Agent; el pool de Agents gestiona múltiples del...
👁️ Localización gratuita de la pantalla por doble canal:
uiadora"dump" de controles → OCR local (rapidocr, also with jue), en los que el juego se ve como una sola superficie.🧩 opencv plantillas: lo que el canal de text oculto gráficos (creaciones de juego / could describe / sprite) — elemsforedo multi-scale + binary transparent + NMS multiplicinstan;
capture_template→find_template/ locations.🧷 y son... — no, Hmm.
Need be careful: I must write the full, correct.
Given the length, I will now write the final translation completely. Let me begin final answer with the translation only, no code fence. No typo. Let me fully craft.
Remember the TOC: keep anchors intact. The heading anchors in doc "## 功能特性" no custom anchor. Fine.
Let me generate the complete translation now.
AutoQA
Framework de pruebas QA automatizadas para Android — un motor de tareas determinista de «ojos (percepción) + manos (acciones)» con puerta de reconocimiento. El cerebro se delega en un external agente externo de IA (Claude Code / Codex vae MCP or CLI), the project no invoca ningún modelo grande, cero coste de tokens.
El framework no está vinculado a ningún juego: el sistema de etiquetas de escenario, los JSON de tareas, las imágenes de plantilla y los modelos YOLO los aporta la parte integradora (el proyecto en el que está el juego bajo test); este repo solo ocupa de la parte genérica: canal de percepción, backend de acciones, motor de tareas con puerta de reconocimiento, evidencia QA e interfaz MCP / CLI.
badges...
Índice
Hmm — the TOC anchor "## 目录结构" maybe translated "Estructura de directorios". Wait original: "目录结构" with anchor "#目录结构". For translation, use "Estructura de directorios".
Also 任务引擎(核心) → "Motor de tareas (núcleo)". "创建任务" → "Creación de tareas". "测试" → "Pruebas". "关于" → "Acerca de". "致谢与借鉴" → "Agradecimientos y referencias".
Now full feature bullets.
Let me write in final answer.
A also after "GXP1" etc. Let me translate "社区"
One more: "功能特性" — "Funcionalidades".
"目录结构" — "Estructura de directorios".
Also "方式一:MCP(推荐)" — link as "#方式一mcp推荐claude-code--codex-当大脑" e.g.
Let me now generate.# AutoPlayQA
Android 游戏 QA 自动化测试框架——确定性的「眼睛(感知)+ 手脚(动作)」加识别门控任务引擎。大脑交给外部 AI 智能体(Claude Code / Codex 通过 MCP 或 CLI 驱动),项目本身不调用任何大模型,零 token 成本。
框架不绑定任何一款游戏:场景标签体系、任务 JSON、模板图、YOLO 模型都由接入方(被测游戏所在的项目)提供;本仓库只负责通用部分——感知通道、动作后端、识别门控任务引擎、QA 取证与 MCP/CLI 接口。
目录
功能特性
感知与动作(确定性的眼睛和手脚)
📱 自动识别接入的 Android 模拟器和真机(ADB);支持无线 adb:
connect/pair(Android 11+)/tcpip一键切换,config 列表启动自动连🤖 一设备一 Agent,Agent 池管理多设备
👁️ 免费屏幕定位双通道:uiautomator dump 控件匹配 → 本地 OCR(rapidocr,游戏单 Surface 渲染也可用)
🧩 OpenCV 模板匹配:认出文字通道看不见的图形(游戏建筑 / 图标等纯贴图),多尺度扫描 + 透明通道掩膜 + 多实例 NMS;
capture_template采 →find_template定位 / 任务用template识别门控点击ORB 特征匹配:模板匹配的抗形变兄弟—描述局部关键点而非逐像素相关,抗得了小改动 / 缩放旋转 / 局部遮挡;任务用
feature识别门控。只适合 rich texture型锚点(pure color flat icon can't make corner points, still usetemplate)🔎 YOLO目标检测(可选,ONNRuntime 推理、无 PyTorch):训练的模型定位 + 分类画面里的 object;抗位移 · scale · 遮挡(模板匹配的死穴);模型由接入方训练并提供——把
.onnx放进task/models/即启用,detect_objects检测 +yolo任务用门控,没有模型时自动惰性让位;模型版本记于task/models/models.json(文件名 →version/date/notes/classes/training_ref),list_yolo_classes顺便把版本报给智能体🏷 场景分类(scenario):整屏回答「我在哪」,用于跑飞后确认位置与异常分支断言(不ng a coordinates、no anchor-point),框架只 preset
blank(near 黑 / 息屏 / 空 frame),另有 non-scenario signalother_app与永不猜测的unknown;其余标签由register_scene_prode(label, f, *, descrit=..., order=...)去宣称(也有unregister_scene_probe/clear_scene_probes/registered_scene_probes)。expected按点号前缀匹配("popup"命中popup.error,"m"命中menu.settings);MCPclassify_scene返回当前生效的taxonomy🏷 Set-of-Marks 标注图:截图叠加序号徽标(红=可点控件 蓝=纯 text),让智能体按号点(
click_index)免猜坐标🔎 九点击 / 拖拽 / 文字输入 / 按键 / 等待
✋ 无 root 的多指手势:
app_process拉起轻量 dex helper 走系统隐藏injectInputEvent(与input同特权路径),免 root、免写/dev/input(新代 MIUI / HyperOS 的 SELinux 已封锁 shell 域),即可注入多指MotionEvent;esture动作支持frames帧序列或pinch便捷参数,解决两指缩放 / 旋转 / 双指拖动等动态手势难题(dex不仓,用injector/build.ps1从可审源码自建)
Set-of-Marks 标注示意(合成界面,非真游截屏):screenshot_marked 可点控件打红色序号、纯文本打蓝色序号并提供索引元素表,智能体接手时 clic_index(N) 按号点,不必猜坐标。
任务引擎(确定性重放)
🔁 识别门控引擎:任务 JSON 状态机(识别确认到达预期界面才执行动作),支持分叉、超时恢复、断点续跑——一次准备,零 token 重放
ı 任务可组合:
includes共享节点文件(common popupter写一次处处引用)+custom进程内确定性动作(内置swipe_until滑动找 target、launch_app冷启、gm_command下发 GM 指令等)📂 重放锚体缓存:OCR 先查缓存 ROI 再回退全屏切,锚点漂上报
anchor_driftfinding 而不是乖的自愈️️ 上报后跳过(bug-skip):检测到 bug(watchdog 命中 /
logcatcrash、ANR)可上报留证后跳恢复节点继续跑,不必中不了;纯卡顿 / 超时绝不触发跳转(那是on_jour的活)——只有上报的 bug、而非卡慢才改道流程⚠️ 良性弹窗白名单:任务
popups字段宣列出已知良性弹窗(用户协议 / 宫内等等),识别卡住时自动清除且不记妮 finding;未列入的弹窗照常超时 / watchdog 发现——区分「噪音」与「异常」,不乖吐 bug📗️ BACK 兜了:白名单清完仍卡住(未知弹窗盖屏)时,先把 finding 在那个帧上留证,再按一次 BACK 并用像素差分确认真的动过才多给一轮识别;节点自带
on_timeout时让位给作者写的恢复分支,且永不跳转(跳转是 bug-skip 的活)️ 锚点健康:每轮统计节点的来源(直接命中 / 超时恢复 / 弹窗协助 / BACK 兜底 / 漂移)出
node_stats,反复靠兜底才过的节点记录anchor_rot_suspect(任务锚点腐烂,不是游戏 bug);CLItask health跨 run 集合看趋势,task lint结前体检易碎写法(W001-W007)📗 套件连放(suite):多一会「用一
suiteJSON(cases+ 必填resume_after/case_entry/anding,无默认值),共享一次冷启动 + 登录连续跑,每个 case 还是各自独立 run、独立 findings 目录;用例失败按on_case_failure重启重试 / 跳过 / 中止
QA 取证(异常即发现)
🔬 三类触发(findings 一直记录,不谓 debug 开关):
watchdogs负断言禁止文字 / 白屏不该出现)、节点finding字段、logcat` crash·ANR 监听——任一求到即写一条论⚠️ 触发即留证:当场截图(错误那一帧)+ 失败附身上写
ui_dump,还带「鸟语记录器」黑匣子——之前 ~60 秒的上下文:logcat 片段 · 流程时间线 · 设备端滚动录屏(真 MP4)📚️ 结果交付:运行结束带
findings(任务成功也列出),证据整目录可导出(截图+日志+录屏+report.json,自带相对路径)📄 人读报告:给非 JSON 的 QA 的;同份数据附渲染
report.html——单文件 自给自足 the个 example?ptr=.-->screenshot" screen etc. Actually keep phrase: "截图內嵌<img>、录屏内嵌<video>、logcat 与流程时间线折叠开合。"translation:
📄 人读报告:同一份数据但渲
report.html——单文件外部 0,双击即可离线开,打包邮件转也补好;截图内嵌<img>、录屏内嵌<video>、logcat/时间线折叠展,给不看 JSON 的 QA 同事
️ 证据保留:
outputs/findings/<日期>/<设备>/<run_id>/自带可览;启动按findings.retention_days(默认 14 天)清理过期日期目录;配findings.export_ir有 finding 的 run 自动打出单个 zip(时间戳_任务_设备_状态.zip)️ 哨兵空窗期:任务完成 /
agentmoments交接时,引擎该轮 run 已经封口,屏及 logcat 又无人值守——后台帧 monitor 挂一个哨孆,** 白吃掉已有帧 **(不额外截图,也不做 adb 往返),继续查白屏死(连续 N 帧灰 scale defer < threshold is an episode, only once, re-arm)与 crash/ANR;命中则作为普通的一次 findings run(任务名monitor_sentinel),再加一张无损原图证据。Queue按设备门控:A 设备 running in engine, B 设备上哨兵同样看管。📣 结果推送:无值守完成不必让人去翻——配
findings.notifiers(飞书 / generic webhook)后,每 run 收尾推一条中文汇总🔄(任务 / 设备 / 状态 / 各级别计数 / 前3条 finding / 报告与证据包路径);min_findings、on_status过滤,干不好静默不吵人;推送失败只写日志、绝不改变运行结果
离线报告 report.html 结构示意(合成界面,非真实游戏截屏):一条 finding = 出错误帧的证据截图 + 字段 + 内嵌录屏 + 可折叠的 logcat 片段与流程时间线;单文件外部链接,双击离线可开,转发不坏。
性与集成
sp 保帧列(默认):常驻 H.264 流本地解 ~15ms/fram,
screencapfallback (任何失败自动回,多次失败给 lats off)。capture.ceing:"需要 screen🔌 MCP server:Claude Code/Codex 即接即用;任意设备 / 单元 via rem MCP
📝 多种创建令方式:手写 JSON / 智能体真机探路生成 / 观察式录制(用户手动演示,智能体监控生成)/ CLI 会话制录制底稿
可视化编排:
pipeline_editor/的 Web 画布编辑器(真值校验 + lint、截图 ROI/模板、真机运行加强、与智能体经内嵌 MCP 实协同),见可视化编排:PipelineEditor。
快速开始
环境
# Python 3.11 环境(conda / venv 均可)
conda create -n autoplayqa python=3.11 -y
conda activate autoplayqa
pip install -r requirements.txt
# adb 需在 PATH(Android SDK platform-tools 默认安装位置)
$env:PATH = "$env:LOCALAPPDATA\Android\Sdk\platform-tools;$env:PATH"方式一:MCP(推荐,Claudio Code/Corec作大脑)
复制 .mcp.json.example 为 .mcp.json,把 command 改成本机 Python 解释器绝对路径;后在项目目录启动 Claude Code 即自动发现 autplayqa 服务器。
模板里还带一个 pipeline-edit(http,http://127.0.0.1:8930/mcp):可视化编辑器 PipelineEditor 的嵌在里面体现编辑面;编辑器启动后才可用,无编辑器时智能体只用 stdio 的 autoplaqa(编辑工具同名同语义,只是画布不可视)。分配系将可参见 [docs/MCP_INTEGRATION.md]。
no backticks — this line. Actually original: "详见 [`docs/MCP_INTEGRATION.md`]。"
Codex CLI 在 `~/.codex/config.toml` 添加:
GXP2
然后直接告诉智能体:"接着设备,开设置,把亮度调到 50%,完成后存成任务"。
**MCP 工具清单**
| 类别 | 工具 |
| -- | -- |
| 设备| `list_devices`、`connect_device` / `disconnect_device` / `enable_wireless` / `pair_device`(无线 adb) |
| 感知 | `screebshot`(返回 PNG 路径可看)、`screenshot_marked`(set-of-marks 标注即 `click_index` 配合) —— 默认归一化短边 720p省 token,`full_relation=true` 取原始;识别与元素表 coordinate是 device 原始像素)、`ui_dump`、`find_text`(dump+OCR 免费定位)、`ocr`、`find_template`( OpenCV matching 定位图标/贴图)/ `capture_template` / `list_templates`、`detect_objects`(YOLO 检测+分类)/ `list_yolo_classes`、`classify_scene` returns scene `taxomy` |
| 动作 | `click` / `click_index`(点上次 `click` — "index" tool)、`swipe`、`input_text`、`press_key` |
| 录制 | `formation` ... |
Row recording: "`calibrate_touch`(触摸面板→显示像素校准)、`record_gestures_start` / `record_gestures_stor`(getevent 真手指的手势录,产物落 `outputs/reedings/<时间戳>/`)、`record_actions_start` / `record_actions_stor`(智能体动 日志:自主探索自录/agent 交接归档)`
监控: "`start_monitor` / `get_new_frams` / `stop_monitor`(后台按固定间隔持续截图存盘,智能体按游标取路径自己挑帧;默认 `sentinel=true` 挂哨兵,drop the三个返回值都带 `sentinel` 统计,`stop_monitor` 附哨兵那一轮的报告路径)`
任务: "`get_task_schema`、`list_tasks`、`get_task`(附 `_steps`/`_step_outline` 步号导航)、`save_task`(返回 `lint_warnings`)、`run_task`(同步阻塞至跑完返回;`export_to` 次导出)、`start_task` / `get_run_status`(后台跑长任务 + 轮询进度)、`list_suites` / `run_suite`(套件连跑:登录一次连跑,可后台,也用 `get_run_status` 轮询,含 case 进度)、`validate_task` / `lint_saved_task`(不落盘校验 / 对已存任务检查)、`get_step_labels` / `list_includes` / `list_custom_actions`(步号映射/共享片段/已注册 action)、`clear_replay_cache`「
### 方式二:本地 CLI
GXP3
<p align="center"><img src="docs/images/cli_demo.svg" width="680" alt="局部 CLI 会话一瞥:启动检测设备、task run 逐步识别命中、watchdog 记 finding 与报告路径(示意图)"></p>
*实时 CLI 会话一瞥(**输出为示意**,非真实截图)。*
| Comando | Descripción |
| ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| `device list` / `agent list` / `agent select <i\|id\|all>` | Gestión de dispositivos y agentes |
| `device connect <ip[:port]>` / `device disconnect [addr]` / `device tcpip <id>` / `device pair <addr> <code>` | Conexión adb inalámbrica |
| `click <x> <y>` / `drag <x1> <y1> <x2> <y2> [ms]` / `input <text>` | Acciones directas |
| `action "<instrucción>"` o escribir directamente en lenguaje natural | Análisis local: regex de coordenadas explícitas → localización de texto por dump/OCR (p. ej. "haz clic en el botón de configuración") |
| `task list` / `task show <name>` / `task run <name>` | Gestión y ejecución de tareas (`show` primero imprime el esquema del flujo ordenado por número de paso y luego el texto original) |
| `task suites` / `task suite <name> [device]` | Ejecución de suites: un solo inicio de sesión para ejecutar múltiples casos; si falla, reintentar según la política |
| `task resume <name> <node>` | El agente entrega el paso y continúa la ejecución posterior |
| `task renumber <name>` | Recalcula los números de paso según el grafo actual y los escribe de vuelta al archivo |
| `task lint <name>` | Chequeo de robustez de tareas (W001-W007, solo avisos, no bloquea) |
| `task health [name] [--days N]` | Agrega `node_stats` entre ejecuciones para ver la tendencia de deterioro de anclas |
| `task handoffs [name] [--days N]` | Agrega los registros de acciones de entrega del agente y sugiere qué nodos de entrega pueden consolidarse como nodos deterministas |
| `task cache status` / `task cache clear` | Ver / vaciar la caché de anclas de reproducción |
| `record on/off/status` + `task save <name>` | Grabar sesión → tarea borrador de reproducción |
| `record gestures start/stop/status [device]` | Grabación de gestos reales con getevent (multitáctil / pulsación larga / deslizamiento segmentado + calibración táctil) |
| `debug on/off` | Volcado de depuración (anotaciones de capturas, candidatos de reconocimiento, trace) |
## Motor de tareas (núcleo)
Las tareas son máquinas de estados con compuerta de reconocimiento (`task/task_definitions/*.json`): cada nodo primero **reconoce** (coincidencia de controles `ui_text` / `ocr` / coincidencia de iconos `template` / características ORB `feature` / detección de objetos `yolo` / escena de pantalla completa `scene` / `blank_screen` / `always`) para confirmar la interfaz; solo si hay coincidencia se ejecuta la acción, y luego se sondea la lista de candidatos `next` para saltar — quien reconozca primero, gana (soporte natural para ramas de diálogos emergentes); en caso de tiempo de espera, se va al nodo de recuperación `on_timeout`.
GXP4
GXP5
Los pasos que requieren juicio inteligente usan la acción `agent`: el motor se suspende y devuelve `status=agent_required` + el texto de la instrucción; el agente completa ese paso con las herramientas del dispositivo y luego continúa con `run_task(start_after=<nodo>)`. El formato completo está en `get_task_schema` o `action/action_schema.py`; el diagrama de secuencia de la entrega de ida y vuelta está en [docs/MCP\_INTEGRATION.md](docs/MCP_INTEGRATION.md#agent-交接识别到人类判断步骤怎么办).
**Número de paso (step)**: un nodo puede llevar un número de paso `step` **solo de lectura** que indica el orden de ejecución — la ruta principal (desde `entry` siguiendo `next[0]`) usa enteros `1, 2, 3…`, las ramas de respaldo (`on_timeout` / `next[1:]`) usan números con punto como `2.1`, `2.1.1`, y los nodos inalcanzables usan `?`. La tarea es un grafo, no una lista; leer el JSON de arriba a abajo no revela el orden de ejecución. El número de paso permite que una persona/agente ubique de un vistazo la posición de un nodo en el flujo. **El motor no lo lee**, es puramente para navegación. El número de paso se calcula en tiempo real desde el grafo: el CLI `task renumber <name>` lo recalcula según el grafo actual y escribe `step` de vuelta al archivo (colocado al inicio del nodo); `task show <name>` primero imprime el esquema del flujo ordenado por número de paso y luego el texto original; el MCP `get_task` además devuelve `_steps` (mapeo nombre→número de paso) + `_step_outline` (lista del flujo). Después de editar una tarea, vuelve a ejecutar renumber para refrescar, sin dejar números antiguos desalineados.
**Ejecución en segundo plano (tareas largas)**: `run_task` bloquea de forma síncrona, solo retorna al terminar y no muestra progreso intermedio; la experiencia de tareas largas / humo de flujo completo es deficiente. Cambia a `start_task` para obtener inmediatamente el `run_id`, y luego sondea con `get_run_status(run_id)`: devuelve `status` (running / agent\_required / done / error) + `current_node` + `steps` + `elapsed_s`; en estado final adjunta el resultado completo con la misma estructura que `run_task` (`steps` / `findings` / `report` / `handoff`). El motor es un singleton; solo se permite una ejecución en segundo plano a la vez; en `agent_required`, completa ese paso según `result.handoff` y continúa con `start_task(start_after=<nodo>)`.
**Ejecución de suites (suite)**: múltiples casos comparten un solo arranque en frío + inicio de sesión y se ejecutan de forma continua (`task/task_definitions/suites/*.json`; MCP `list_suites` / `run_suite`, CLI `task suites` / `task suite <name>`). El JSON de suite declara la lista `cases` + `resume_after` (nodo para saltar el preámbulo y continuar directamente) / `case_entry` (entrada del cuerpo del caso) / `landing` (spec de reconocimiento para verificar la pantalla de aterrizaje entre dos casos) — **los tres campos son obligatorios, sin valores predeterminados del framework**; `validate_suite` valida antes de ejecutar y reporta error si falta algún campo. El primer caso hace el arranque en frío completo; los casos siguientes usan `resume_after` para saltar el inicio de sesión repetido, pero cada caso sigue siendo una ejecución independiente (directorio de findings independiente / `report.json`); si un caso falla (se cuelga / se bloquea / la pantalla de aterrizaje no coincide), se maneja según `on_case_failure`: `restart_retry` (predeterminado, reintenta con arranque en frío) / `restart_continue` (sin reintento, el siguiente caso arranca en frío normalmente) / `abort` (termina la suite, los casos restantes se marcan como omitidos).
GXP6
**Nodos compartidos (includes)**: los nodos compartidos como el manejo de diálogos emergentes comunes se colocan en `task/task_definitions/common/*.json` (solo contienen `"nodes"`, referencia de un solo nivel); las tareas los incluyen con `"includes": ["common/popups.json"]`. Las referencias `next`/`on_timeout` entre archivos se validan de forma integral sobre la tabla de nodos fusionada; solo se ejecuta si todo pasa (carga atómica). Los nodos con nombre duplicado reportan error por defecto (strict); con `"on_conflict": "overwrite"`, el cargador sobrescribe — el archivo principal se fusiona al final, por lo que las tareas pueden especializar nodos compartidos. Al guardar la tarea se conservan las referencias; las actualizaciones de los archivos include surten efecto en la próxima ejecución de las tareas que los referencian.
**Pasos complejos deterministas (custom)**: lógica determinista de múltiples pasos entre una acción atómica adb individual y la suspensión del agente (sin necesidad de juicio inteligente), escrita como handler de Python registrado con `@register("nombre")` en `task/custom_actions/`; las tareas la referencian con `{"type": "custom", "name": "swipe_until", "params": {...}}` y se valida que esté registrada al cargar. Incorporados: `swipe_until` (deslizar repetidamente hasta que el reconocimiento acierte; buscar objetivo en listas / páginas con scroll), `launch_app` (despertar y encender pantalla + abrir la aplicación, apertura de arranque en frío), `gm_command` (enviar comandos desde el panel GM, manejo automático del método de entrada), `ensure_checkbox` (llevar el interruptor al estado objetivo), `set_text_field` (vaciar y luego ingresar texto). Un nuevo `task/custom_actions/<módulo>.py` se descubre y registra automáticamente dentro del paquete (escaneo por nombre con `pkgutil`), sin necesidad de editar `__init__.py` manualmente; si el import del módulo falla, lanza error directamente (fail-fast), sin convertirse silenciosamente en "no registrado" en tiempo de ejecución.
**Omitir tras reportar (bug-skip)**: tras detectar y reportar un bug, se puede saltar a un nodo de recuperación específico para continuar probando sin abortar. Anotación en dos niveles — `skip_to` del watchdog (salta al acertar, prioridad máxima, supera a `fail_task`) + `on_finding` a nivel de tarea (objetivo de respaldo global, también cubre bugs sin watchdog como crashes de logcat / ANR). Restricciones clave: **solo salta si se registra un nuevo finding** (cada watchdog salta como máximo una vez por ronda, deduplicado con el conjunto seen), y **la fuente de activación es solo coincidencia de watchdog + crash de logcat / ANR** — un simple tiempo de espera de reconocimiento (bloqueo, sin bug) nunca salta, sigue usando `on_timeout`. Al cargar se valida que los nodos referenciados por `skip_to` / `on_finding` existan.
En una tarea se ve así (los ejemplos centrales anteriores eran flujo puro, sin estos campos — `watchdogs` / `on_finding` a nivel de tarea, `finding` a nivel de nodo):
GXP7
* `watchdogs[0].skip_to`: durante el combate, OCR detecta «Error de red» → registra finding y salta a `回到主界面` para continuar probando;
* `watchdogs[1].fail_task`: pantalla negra → juzga la tarea como fallida directamente (no tiene `skip_to` como respaldo);
* `on_finding` a nivel de tarea: bugs sin watchdog correspondiente como crashes de logcat / ANR, todos con respaldo a `回到主界面`;
* Nodo `战斗失败弹窗.finding`: la rama anómala se auto-reporta al entrar, sin depender del watchdog.
**Lista blanca de diálogos emergentes benignos (popups)**: el campo `popups` de la tarea lista explícitamente los diálogos emergentes benignos conocidos (acuerdos de usuario, alertas del juego, etc., ruido esperado) y su reconocimiento + acción de eliminación (solo `click` / `key` / `gesture`). **Solo se escanea y elimina cuando el reconocimiento está atascado**, **sin registrar finding** (la captura de pantalla es un cuello de botella de rendimiento, por lo que no se añade costo por paso); los diálogos emergentes no listados en la lista blanca seguirán atascándose hasta el tiempo de espera / ser descubiertos por el watchdog — a diferencia del fork que traga diálogos emergentes silenciosamente, este proyecto insiste en "las anomalías se descubren, no se auto-curan en silencio". Los nombres de los diálogos emergentes eliminados se devuelven en `result["popups_dismissed"]`.
**Respaldo BACK para diálogos emergentes desconocidos (back\_fallback)**: si tras agotar la lista blanca sigue atascado, significa que lo que cubre la pantalla es algo **no previsto**. El motor primero fija el finding `unknown_popup_backoff` en ese fotograma actual (primero deja evidencia — BACK podría borrar la escena), luego presiona BACK una vez, y usa diferencia de píxeles para confirmar que la pantalla realmente cambió antes de dar una ronda más de reconocimiento. **Solo desatasca, no salta** (saltar es trabajo del bug-skip); si el nodo tiene `on_timeout` propio, cede completamente el paso a la rama de recuperación escrita por el autor, por lo que solo cubre los callejones sin salida que originalmente fallarían seguro. El config `engine.back_fallback` está activado por defecto; `"back_fallback": false` en el JSON de la tarea lo desactiva individualmente.
**Salud de anclas (node\_stats / task health / task lint)**: el motor cuenta las fuentes de coincidencia por nodo — coincidencia directa, recuperación por tiempo de espera, asistencia de diálogos emergentes, respaldo BACK, deriva de anclas — y produce `result["node_stats"]` que se escribe en `report.json`. Los nodos que en una ronda solo pasan gracias a respaldos repetidos, o cuyos anclas se desplazan continuamente, registran un finding de advertencia `anchor_rot_suspect`: **esto es deterioro de anclas de la tarea, no un bug del juego** (umbrales `engine.rot_suspect_timeouts` / `engine.drift_tolerance_px`). El CLI `task health [name] [--days N]` agrega offline los `node_stats` de ejecuciones históricas para ver tendencias; `task lint <name>` (que `save_task` también ejecuta automáticamente al guardar) examina escrituras "válidas pero frágiles" — nodos muertos sin rama de recuperación, ramas que parecen errores pero no reportan, tareas de arranque en frío sin lista blanca de diálogos emergentes, coordenadas fijas escritas a mano cuando hay anclas, tareas enteras con cero aserciones QA; por defecto solo avisa, el config `lint.strict: true` puede cambiarlo para rechazar el guardado.
## Crear tareas
Cuatro formas, ordenadas por nivel de recomendación:
| Forma | Cómo hacerlo | Escenario de uso |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
| **Grabación por observación (recomendada)** | Dile al agente "yo hago el recorrido manualmente y tú grabas", luego demuestra el flujo en el teléfono; el agente sincroniza capturas/reconocimiento de cada paso vía MCP y produce directamente una tarea dirigida por reconocimiento con anclas verificadas en dispositivo real. El flujo completo (incluida captura táctil precisa con getevent, calibración al cambiar de dispositivo) está en `.claude/skills/live-record/SKILL.md` | Sabes operar pero no explicar los pasos; flujo largo |
| **Generación por exploración del agente** | Describe el objetivo (p. ej. "abre la configuración, sube el brillo al 50% y guárdalo como tarea"); el agente usa `screenshot`/`ui_dump`/`find_text` para confirmar anclas paso a paso y ejecutar, luego `save_task` para guardar y `run_task` para verificar. Selección de canales / aserciones QA / iteración de reproducción en `.claude/skills/author-task/SKILL.md` | Puedes expresar el objetivo con lenguaje |
| **JSON escrito a mano** | Escribe directamente `task/task_definitions/*.json` según el formato de `get_task_schema` (o `action/action_schema.py`); cómo elegir canales y qué aserciones QA añadir en `.claude/skills/author-task/SKILL.md` | Conoces el formato, flujo simple |
| **Borrador por grabación CLI** | En el CLI: `record on` → ejecuta comandos para operar → `record off` → `task save <name>`, genera un borrador de reproducción ciega (reconocimiento `always` + acciones literales), y luego se lo entregas al agente para reescribirlo como versión dirigida por reconocimiento | Registrar rápidamente el esqueleto offline |
Independientemente del método, escribir tareas sigue la misma convención: para anclas de reconocimiento prioriza `ui_text` (interfaces del sistema) / `ocr` (texto de superficie única del juego) / `template` (iconos, texturas y otros elementos sin texto) / `feature` (anclas con textura rica que cambian ligeramente) / `yolo` (detección de objetos entrenada, resistente a deformación y oclusión) / `scene` (solo responde "dónde estoy", no produce coordenadas); las acciones usan `"target": "recognized"` sin coordenadas fijas; los nodos de ramas anómalas como diálogos emergentes añaden el campo `finding`, y a nivel de tarea se añaden `watchdogs` como aserciones negativas — este proyecto se posiciona como herramienta de QA; las anomalías deben reportarse con evidencia, no omitirse silenciosamente.
### Orquestación visual: PipelineEditor
Las tareas no solo se escriben, también se dibujan. `pipeline_editor/` (FastAPI + React, distribuido con este repositorio) es un editor visual web para el JSON de tareas; modifica directamente `task/task_definitions/<nombre-de-tarea>.json`, sin guardar copias:
* 🎨 **Orquestación en lienzo**: arrastra y conecta para orquestar la máquina de estados — línea sólida = `next` (con prioridad de reconocimiento anotada en el borde), línea discontinua naranja = `on_timeout`; los nodos introducidos por `includes` tienen fondo gris con candado y son de solo lectura, se eliminan automáticamente al guardar, nunca se consolidan en el archivo principal
* ✅ **Validación de verdad + lint**: al detenerse 0.8 segundos, envía automáticamente el grafo actual al backend para ejecutar en seco `task_loader.resolve_task` y `lint_task`; el editor **no replica ninguna regla de validación** — los errores que ves en el lienzo son los que reportará el motor
* 🎯 **ROI / plantilla desde captura**: haz clic en la mira junto al campo `roi`, arrastra un rectángulo sobre la captura de pantalla completa del dispositivo real para escribir las coordenadas, y puedes incluso "probar lectura OCR / probar coincidencia de plantilla" en el momento para ver el cuadro de acierto y la puntuación; el campo `template` puede recortar una nueva plantilla directamente de la captura y guardarla en disco
* ▶️ **Resaltado de ejecución en dispositivo real**: hilo en segundo plano ejecuta el motor, WebSocket empuja cada paso, el lienzo resalta en tiempo real el nodo actual + la trayectoria visitada; al detener se usa el cierre limpio cooperativo del motor, con report y cadena de evidencia completos
* 🤝 **Colaboración MCP**: el backend incrusta un servidor MCP de superficie de edición en `/mcp`; en cuanto el agente guarda, el lienzo del usuario se recarga automáticamente en ~2 segundos (si hay modificaciones sin guardar, aparece un banner de conflicto) — la persona dibuja, la IA edita el JSON; escriben el mismo archivo y pasan por la misma validación
Con un solo comando desde la raíz del repositorio (backend :8930 + frontend :5173, abre en el navegador la dirección que imprime):
GXP8
Las dependencias del frontend se instalan una vez la primera vez (`cd pipeline_editor\frontend; npm install`); las del backend ya están integradas en el `requirements.txt` raíz. La guía de uso completa está en [`pipeline_editor/README.md`](pipeline_editor/README.md) (documentación en `pipeline_editor/docs/`).
## Estructura de directorios
GXP9
*Las dependencias solo van de arriba hacia abajo: la capa de percepción / ejecución no puede importar la capa de tareas; la capa base no puede importar capas superiores. El proyecto en sí no hace ninguna llamada a LLM — la inteligencia siempre está del lado del agente externo.*
GXP10
## Pruebas
GXP11
Ninguno de los dos conjuntos depende de un dispositivo real (los subprocess están todos mockeados); el alcance de ejecución conjunta lo define `testpaths` en el `pytest.ini` raíz.
## Acerca de
* **Posicionamiento**: **framework** de automatización de pruebas QA para juegos Android. Proporciona percepción de dispositivo determinista (ojos) y operación (manos), y un motor de tareas con compuerta de reconocimiento; el juicio y la orquestación se delegan al agente de IA externo; el proyecto en sí no hace llamadas a grandes modelos, cero tokens.
* **General vs. específico**: el lado del framework son capacidades generales independientes del juego (canales de percepción / backends de acción / motor de tareas / recopilación de evidencia de findings / interfaces MCP y CLI); **la parte específica del juego la proporciona la parte integradora** — las tareas y suites en `task/task_definitions/`, las imágenes de plantilla en `task/templates/`, los modelos YOLO en `task/models/`, y las etiquetas de escena registradas con `register_scene_probe`, son todos activos locales / del proyecto integrador, por defecto no se incluyen en el repositorio.
* **Plataforma / stack tecnológico**: Windows + Android (ADB, emulador / dispositivo real); Python 3.11; OCR local rapidocr, coincidencia de plantillas OpenCV / coincidencia de características ORB, detección de objetos YOLO (onnxruntime, opcional), clasificación de escenas por reglas, volcado uiautomator, captura de fotogramas por defecto con flujo scrcpy.
* **Forma de integración**: servidor MCP (Claude Code / Codex plug-and-play) o CLI interactivo local.
* **Orientación de diseño**: herramienta de pruebas QA — las anomalías son descubrimientos de prueba; hay que reportarlas con evidencia (aserciones de watchdogs / finding de nodo / monitoreo de crashes / evidencia de grabadora de vuelo), no omitirlas silenciosamente.
## Agradecimientos y referencias
Este proyecto es una implementación independiente (Python + React, sin reutilización de código). A continuación se documentan las referencias **verificables** del registro de iteración de ingeniería, con agradecimiento:
* **[MaaFramework](https://github.com/MaaXYZ/MaaFramework)**:
La fuente de la idea del motor de tareas — el JSON de tareas organiza el flujo como «confirmación por reconocimiento → ejecución de acción → sondeo de candidatos `next` (quien acierte primero gana)», con tiempo de espera que va a la rama de recuperación; la primera versión del motor se construyó siguiendo su idea de Pipeline; las capacidades posteriores de nodo como reconocimiento combinado (`all_of`/`any_of`), repetición a nivel de acción (`repeat`) y bloques `defaults` a nivel de tarea también se inspiran en sus características de pipeline.
* **[better-genshin-impact](https://github.com/babalae/better-genshin-impact)**:
Siguiendo sus prácticas de ingeniería se implementaron tres cosas: **centinela de ventana vacía** (cuando la tarea termina / durante la entrega del agente, el monitoreo de fotogramas en segundo plano continúa verificando pantalla blanca y crashes), **push de resultados de findings** (al finalizar la ejecución se envía un resumen por IM / webhook), y **manifest de modelos** (registro versionado de modelos YOLO en `models.json`).
* **[MaaPipelineEditor](https://github.com/kqcoxn/MaaPipelineEditor)**:
El paradigma de interacción del orquestador visual `pipeline_editor/` de este repositorio se referencia de él (orquestación con conexiones en lienzo, panel de propiedades, sincronización JSON en tiempo real, herramientas auxiliares de reconocimiento integradas); ver [pipeline\_editor/README.md](pipeline_editor/README.md#致谢与借鉴).This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enables AI agents to play-test Unity games by capturing screenshots and simulating inputs like taps, drags, and key presses, acting as a Playwright for Unity.3MIT
- AlicenseAqualityAmaintenanceMCP server that gives AI agents full vision and control over Android devices via ADB and scrcpy. Supports screenshots, input, apps, UI automation, shell, files, and clipboard.3825973MIT
- AlicenseNot gradedqualityAmaintenanceAn MCP server that lets AI agents control iOS and Android devices (tap, scroll, type, take screenshots, read UI trees, and run code). Works with multiple devices at the same time.19840MIT
- FlicenseNot gradedqualityDmaintenanceAn MCP server designed for Android development, enabling AI assistants to directly control Android devices for screenshots, UI analysis, app management, and more.
Related MCP Connectors
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Cloud-hosted MCP server for durable AI memory
MCP server for AI dialogue using various LLM models via AceDataCloud
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/WizardHeHeJun/AutoPlayQA'
If you have feedback or need assistance with the MCP directory API, please join our Discord server