maafw-pipeline
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMaaFW Pipeline 开发
MaaFW Pipeline Development
编写全流程分两条动线,动手前先分轨:
- 新建轨:从零新建流程(任务或子流程)——需求 → 拆分与状态清单(含探索取证)→ 文件结构与命名 → 素材准备 → 节点编写 → 流程组合 → 自查与交接。任务可大可小:大任务逐级拆成子流程,嵌套组合,每一层走同样的步骤。
- 修改轨:在既有项目上改动、重构、审查——摸底 → 搜引用 → 修改 → 自查(见下),不按新建顺序硬套。
字段精确语义(字段名、参数、默认值、版本支持)不在本文复制,一律路由 MaaLLMWiki 的 3.1-任务流水线协议:版本锁定、引用回源、不可达时标记"未验证"(已安装 skill 时由其承载完整路由流程)。执行模型是下文一切推理的基础,在此给出最小版:
maallmwikiThe full development workflow is divided into two tracks; choose your track before starting:
- New Creation Track: Build a pipeline (task or sub-flow) from scratch — Requirements → Breakdown & State Inventory (including exploration and evidence collection) → File Structure & Naming → Asset Preparation → Node Authoring → Flow Composition → Self-Check & Handover. Tasks can be large or small: large tasks are broken down hierarchically into sub-flows, which are nested and composed, with each layer following the same steps.
- Modification Track: Modify, refactor, or review existing pipelines in a project — Assessment → Reference Search → Modification → Self-Check (see below). Do not rigidly follow the new creation order.
The precise semantics of fields (field names, parameters, default values, version support) are not duplicated in this document; all are routed to Section 3.1 Task Pipeline Protocol of MaaLLMWiki: version locking, reference traceability, and marking as "unverified" when unreachable (the full routing process is handled by the skill if it is installed). The execution model is the foundation of all reasoning below; a minimal version is provided here:
maallmwiki执行模型(最小心智模型)
Execution Model (Minimal Mental Model)
节点是三段式:识别 → 动作 → next。引擎在节点间如此运转:
- 任务由入口节点名启动():引擎初始化为"当前节点 = 入口节点、轮询列表 = [入口节点]"——入口作为唯一候选被识别(通常 DirectHit 恒命中);若识别超时,用它自己的
post_task,未命中也走它自己的 on_error。timeout - 当前节点动作完成后,对它的 next 列表按顺序轮询识别:每轮依次尝试各候选;本轮全未命中,等 后再截图重试(本轮候选全为 DirectHit 时跳过截图,零画面开销)。
rate_limit - 第一个命中的候选立即胜出(后续候选不再检测),进入该节点、执行其动作——动作成功则轮询它的 next 列表(回到第 2 步);动作失败走它的 on_error。
- 轮询超过当前节点的 (缺省 20s)仍无命中 → 走当前节点的 on_error——想调整某节点被识别的等待时长或超时去向,改的是它上一节点的
timeout/timeout,不是它自己的。on_error - 异常状态:
- 进入(三种):动作失败;轮询超时;被轮询列表中没有任何存在且启用的节点(不等 、立即未命中——不存在的引用过不了加载校验,走到这一步的多为
timeout节点或未设置的锚点)。enabled:false - 进入后:on_error 列表接替 next 列表被同样轮询——on_error 为空时 next 立即为空、循环直接终止,任务以失败收场。
- 解除:只由识别命中解除;命中后若动作失败,立即重新进入——因此结果上走出异常 = 命中且动作成功。
- 异常期间收紧:再次未命中(on_error 轮询超时,或 on_error 列表没有任何存在且启用的节点——如恢复节点名拼错,不等超时、立即失败)不进 on_error、任务直接失败;执行链走空时若仍处于异常状态,已登记的 回跳不生效,任务以失败终止。
[JumpBack]
- 进入(三种):动作失败;轮询超时;被轮询列表中没有任何存在且启用的节点(不等
- 终止与成败:
- 循环在 next 为空或外部 stop / StopTask 时终止;任务成败 = 终止时是否处于异常状态(正常态走空即成功)。
- 唯一例外 (仅正常态):子链走空不终止,重新轮询父节点的 next 列表(从头按序识别;父节点不经识别恢复为当前节点,超时与 on_error 归属随之回到它,动作不重跑)。例:
[JumpBack]、A.next=["B","[JumpBack]C"]、C.next=["D"]——C 命中执行后走 D,D 走空,接着轮询的就是D.next=[]。A.next
on_error 归属:看当前处于哪个节点——候选被识别不算进入节点,命中后才算进入;进入后的执行动作与轮询 next 列表都发生在本节点内,失败就走本节点的 on_error:动作失败走动作所在节点的 on_error,轮询 next 列表超时走 next 列表所属节点的 on_error。
Nodes follow a three-stage structure: Recognition → Action → next. The engine operates between nodes as follows:
- A task is started by an entry node name (): the engine initializes with "current node = entry node, polling list = [entry node]" — the entry node is recognized as the only candidate (usually a DirectHit that always matches); if recognition times out, it uses its own
post_task, and if it misses, it follows its own on_error.timeout - After the current node's action completes, its next list is polled sequentially for recognition: each candidate is tried in order per round; if all candidates miss in a round, the engine waits for before taking a new screenshot and retrying (screenshot is skipped if all candidates in the round are DirectHit, with zero screen overhead).
rate_limit - The first matching candidate wins immediately (subsequent candidates are no longer checked), the engine enters this node and executes its action — if the action succeeds, it polls the node's next list (returning to step 2); if the action fails, it follows the node's on_error.
- If polling exceeds the current node's (default 20s) with no matches → follow the current node's on_error — to adjust the waiting time or timeout destination for a node being recognized, modify its previous node's
timeout/timeout, not its own.on_error - Exception State:
- Entry (three types): Action failure; polling timeout; no existing and enabled nodes in the polled list (immediate miss without waiting for — non-existent references fail loading validation, and most cases that reach this step are nodes with
timeoutor unset anchors).enabled:false - After entry: The on_error list replaces the next list and is polled in the same way — if on_error is empty, next is immediately empty, the loop terminates directly, and the task ends in failure.
- Resolution: Only resolved by a recognition match; if the action fails after matching, the exception state is re-entered immediately — so effectively, exiting an exception = matching and successful action execution.
- Tightening during exception: A second miss (on_error polling timeout, or no existing and enabled nodes in the on_error list — e.g., a misspelled recovery node name, which fails immediately without waiting for timeout) does not enter on_error, and the task fails directly; if the execution chain runs empty while still in an exception state, registered jumps do not take effect, and the task terminates in failure.
[JumpBack]
- Entry (three types): Action failure; polling timeout; no existing and enabled nodes in the polled list (immediate miss without waiting for
- Termination and Success/Failure:
- The loop terminates when next is empty or an external stop / StopTask is issued; task success/failure = whether it is in an exception state at termination (running empty in normal state means success).
- Only exception: (normal state only): A sub-chain running empty does not terminate; instead, it re-polls the parent node's next list (recognizes sequentially from the beginning; the parent node is restored as the current node without re-recognition, its timeout and on_error ownership return to it, and its action is not re-executed). Example:
[JumpBack],A.next=["B","[JumpBack]C"],C.next=["D"]— after C matches and executes, it proceeds to D; when D runs empty, the next poll is forD.next=[].A.next
on_error Ownership: Determined by which node is currently active — a candidate being recognized does not count as entering the node; entry only occurs after a match. After entry, action execution and next list polling both happen within the current node, and failures follow the current node's on_error: action failures follow the on_error of the node where the action is located, and next list polling timeouts follow the on_error of the node that owns the next list.
硬护栏(全程生效)
Hard Guardrails (Effective Throughout)
- 探索优先:要写的每个状态必须有真实观测证据(截图、OCR 文本、色值、box 等);凭文档、节点名或记忆推断的状态一律视为 guessed,guessed 状态不得落笔。细则:
- 按转移推进:探索推进到哪个界面(以当前设备画面为准),就观测该界面的识别标志与点击目标;点击后实际观测到下一界面的标志出现(即 next 里的"出口"候选),这条转移即可落笔。弹窗处理节点同样只在见过该弹窗后写。写到哪、观测到哪,不必整个流程探索完再动笔;整段贯通与可重入不在写作门槛内,轮到自查与端到端验收去跑。
- 点击最小化副作用:非必要的提交/领取类按钮不点;能靠关键帧确认的状态不主动触发。
- 不可复现的状态(一次性奖励、首通引导、不可逆操作后的界面)无法主动到达,用留存的关键帧代替——工具暂存的重要变化帧同样算观测证据,写前逐帧核对;连关键帧都没有的仍按缺口处理。
- 复用已有节点时,其入口前提同样是必须观测的状态。
- 无法探索(无设备、无授权、会触发禁止的副作用)就停下报告缺口,不要硬写计划。
- 实时性场景不适用:抢购、QTE 等毫秒级反应无法靠"观察→决策"的探索模式,也超出轮询模型的反应速度——直接说明做不到,不硬写。
- 坐标卫生:点击目标由识别结果推导。缺省
target(继承本节点识别 box),绝大多数节点不需要写它;要偏移用true并注明依据;确需另指目标优先 string 引用(前置节点名 /target_offset,引用结果为空即动作失败);固定坐标数组视同硬编码,仅特殊场景(如负坐标从边缘计算)使用并注明理由——严禁[Anchor]锚点名+ 硬编码 target 坐标。DirectHit - 不编造字段:字段名、参数、版本支持拿不准就路由,宁可少写用默认值;开头 root 字段不解析、
$开头文件不读取。pipeline 文件按 jsonc 解析——行内与整行.注释直接可用;需要结构化注释时用///desc,占位提示用_desc/code(如_code表示该参数在 interface.json/Custom 代码里统一配置),template_code/doc亦同(尽量不用)——均为非协议字段(3.1 协议零记载),引擎对未知键静默忽略,作结构化注释属约定用法,纯说明优先 jsonc_doc注释。// - 基准分辨率中立:运行基准从项目 controller 配置动态获取(缺省 720 短边,兼容横竖屏);量 ROI 的截图必须走框架截图链路,不用外部图片。
- 循环必须有终止论证:凡执行会回到已执行节点候选列表的写法(回跳、next 回指成环),终止论证三选一并在注释说明。细则:
[JumpBack]- 限次:/
max_hit+timeout上报;on_error - 识别门控:候选带真实识别、动作以消除该识别为目标,动作可能失效时仍配兜底限次;
- 挂机意图:显式声明的无限产出循环,退出靠外部停止或条件节点,环内每轮有真实进展,重置计数必须显式;
- 只管"目标界面一直没出现":管不了"一直命中、停不下来"——只要每轮都有候选命中,超时永远不会触发;
timeout - DirectHit 禁入循环:恒命中且无识别门控,禁止作为 自回环或循环体候选——全 DirectHit 候选列表还会跳过截图,连画面变化都观测不到。
[JumpBack]
- 限次:
- Exploration First: Every state to be written must have real observational evidence (screenshots, OCR text, color values, bounding boxes, etc.); states inferred from documentation, node names, or memory are all considered guessed, and guessed states must not be written down. Detailed rules:
- Progress by transition: Observe the recognition markers and click targets of whichever interface the exploration has reached (based on the current device screen); after clicking, when the marker of the next interface is actually observed (i.e., the "exit" candidate in next), this transition can be written. Popup handling nodes are also only written after the popup has been seen. Write as you observe, no need to explore the entire flow before writing; full end-to-end connectivity and reentrancy are not thresholds for writing, they are checked during self-check and end-to-end acceptance.
- Minimize click side effects: Do not click unnecessary submit/claim buttons; do not actively trigger states that can be confirmed via keyframes.
- Unreproducible states (one-time rewards, first-run guides, interfaces after irreversible operations) cannot be reached actively; use saved keyframes instead — important change frames temporarily stored by tools also count as observational evidence, and should be checked frame by frame before writing; states without even keyframes are still treated as gaps.
- When reusing existing nodes, their entry prerequisites are also states that must be observed.
- If exploration is impossible (no device, no authorization, would trigger prohibited side effects), stop and report the gap; do not force-write plans.
- Not applicable to real-time scenarios: Millisecond-level reactions such as flash sales or QTEs cannot rely on the "observe → decide" exploration mode, and exceed the reaction speed of the polling model — directly state that it cannot be done, do not force-write.
- Coordinate Hygiene: Click targets are derived from recognition results. defaults to
target(inherits the current node's recognition box), and most nodes do not need to specify it; usetruefor offsets and note the basis; if a different target is truly needed, prioritize string references (previous node name /target_offset, empty reference result means action failure); fixed coordinate arrays are treated as hard coding, only used in special scenarios (e.g., negative coordinates calculated from edges) with reasons noted —[Anchor]anchor name+ hardcoded target coordinates are strictly prohibited.DirectHit - Do not fabricate fields: If unsure about field names, parameters, or version support, route to the documentation; prefer writing less and using default values. Root fields starting with are not parsed, and files starting with
$are not read. Pipeline files are parsed as jsonc — inline and full-line.comments are directly usable; use///descfor structured comments,_desc/codefor placeholder hints (e.g.,_codeindicates this parameter is uniformly configured in interface.json/Custom code), and similarlytemplate_code/doc(avoid using if possible) — all are non-protocol fields (not documented at all in the 3.1 protocol). The engine silently ignores unknown keys, and using them as structured comments is a conventional usage; for pure explanations, prefer jsonc_doccomments.// - Base Resolution Neutral: The running base resolution is dynamically obtained from the project's controller configuration (default 720px short edge, compatible with portrait and landscape); screenshots for measuring ROIs must go through the framework's screenshot pipeline, not external images.
- Loops must have termination justification: For any pattern where execution returns to the candidate list of a previously executed node (jumps, next references forming a loop), choose one of three termination justifications and explain it in comments. Detailed rules:
[JumpBack]- Limit count: /
max_hit+timeoutreporting;on_error - Recognition gating: Candidates have real recognition, and the action aims to eliminate that recognition; if the action may fail, still configure a fallback limit count.
- AFK intent: Explicitly declared infinite production loops, exited via external stop or condition nodes, with real progress per round in the loop, and count resets must be explicit;
- only handles "target interface never appears": It cannot handle "keeps matching, can't stop" — as long as a candidate matches every round, timeout will never trigger;
timeout - DirectHit prohibited in loops: As always-matching with no recognition gating, DirectHit is prohibited as a candidate for self-loops or loop bodies — a candidate list of all DirectHit also skips screenshots, so even screen changes cannot be observed.
[JumpBack]
- Limit count:
新建轨
New Creation Track
步骤 1–5 按段滚动推进:拆出的每个子流程各自走 1→5,探索一段、写一段,不必整个任务探索完再动笔;全部段落完成并自查后进第 6 步。
滚动推进必须伴随进度档案(跨会话的 working memory,外置成文件,放资源包外不被框架加载的位置):记录需求与拆分结论(子流程清单)、每段实现状态(计划中 / 已编写 / 已测试)、每个已观测状态的证据帧编号、当前断点(设备停在哪个界面)。关键帧与状态绑定归档——它同时是 observed 证据、复测识别的素材(节点测试模式:截图 + hits/box 期望)、模板裁剪的来源。
Steps 1–5 are rolled out segment by segment: each broken-out sub-flow follows steps 1→5 independently; explore one segment, write one segment, no need to explore the entire task before writing. After all segments are completed and self-checked, proceed to Step 6.
Rolling progress must be accompanied by a progress file (cross-session working memory, stored as an external file in a location outside the resource pack so it is not loaded by the framework): record requirements and breakdown conclusions (sub-flow list), implementation status of each segment (Planned / Written / Tested), evidence frame number for each observed state, and current breakpoint (which interface the device is on). Keyframes are archived bound to states — they serve as observed evidence, material for re-testing recognition (node test mode: screenshot + hits/box expectations), and source for template cropping.
1. 需求 → 拆分与状态清单(含探索取证)
1. Requirements → Breakdown & State Inventory (Including Exploration & Evidence Collection)
- 先拆再翻(滚动拆分):需求可大可小,大任务先拆成子任务/子流程——每个子流程有明确的入口/出口边界(约定 /
Start后缀),可跨任务复用的收进资源包内End顶层共享文件(pipeline/),复用边界由文件归属与跨模块引用表达,不靠节点名前缀(见 references/project-structure.md);子流程内部再同法拆分,嵌套任意层。拆分边界:一段可独立观测与独立验证的界面段/业务段。拆分不必一次完成——先定子流程边界的大框架,屏内的状态与弹窗随推进滚动补进清单。general.json - 屏内动线(先同屏、后出口):进入一个界面后,先写并即测该界面的异常处理节点——同屏内容不离开画面,写完就能测(屏内广度);出口最后写——写完测完人已在下一界面,顺接继续(屏间深度)。反序会先离开本屏,未适配的弹窗要整条流程重跑才能回来补测。
- 把每个(子)流程翻译成状态而非动作清单:起始态、每个中间态(含可能的弹窗)、成功态、失败态。每个状态回答两个问题:
- 用什么识别:固定图 → TemplateMatch;文本 → OCR(用完整稳定文本);色块 → ColorMatch;无视觉变化的流程节点 → DirectHit;目标尺寸 / 缩放会变(模板匹配失配)→ FeatureMatch;模板 / 文本 / 颜色都不可行的复杂目标 → NeuralNetworkClassify / NeuralNetworkDetect(自训 ONNX 模型);多条件同屏 → And / Or;都表达不了 → Custom(交接
expected)。完整名单与精确参数路由 3.1-任务流水线协议核对。maafw-custom - 证据是 observed 还是 guessed:哪段要写,哪段的状态必须全部 observed(硬护栏 1);尚未探索的段留到写到时再探索。
- 用什么识别:固定图 → TemplateMatch;文本 → OCR(
- Break down first, then translate (rolling breakdown): Requirements can be large or small; large tasks are first broken into sub-tasks/sub-flows — each sub-flow has clear entry/exit boundaries (conventionally suffixed with /
Start). Sub-flows reusable across tasks are placed in top-level shared files underEndin the resource pack (pipeline/). Reuse boundaries are expressed by file ownership and cross-module references, not by node name prefixes (see references/project-structure.md). Sub-flows are further broken down the same way, nested to any depth. Breakdown boundary: a segment of interface/business that can be independently observed and verified. Breakdown does not need to be completed all at once — first set the overall framework of sub-flow boundaries, then add on-screen states and popups to the inventory as you progress.general.json - On-screen workflow (same-screen first, then exit): After entering an interface, first write and immediately test the exception handling nodes for that interface — same-screen content stays on screen, so it can be tested right after writing (on-screen breadth). Write exits last — after writing and testing, you are already on the next interface, and can continue seamlessly (inter-screen depth). Reversing the order will leave the current screen first, and unadapted popups will require running the entire flow again to come back and test.
- Translate each (sub-)flow into states rather than action lists: initial state, each intermediate state (including possible popups), success state, failure state. Each state answers two questions:
- What to use for recognition: Fixed image → TemplateMatch; Text → OCR (use complete stable text for ); Color block → ColorMatch; Flow nodes with no visual change → DirectHit; Target size/zoom changes (template match mismatch) → FeatureMatch; Complex targets where template/text/color are not feasible → NeuralNetworkClassify / NeuralNetworkDetect (self-trained ONNX model); Multiple conditions on the same screen → And / Or; None of the above can express → Custom (hand over to
expected). Check the full list and precise parameters against the 3.1 Task Pipeline Protocol via routing.maafw-custom - Is the evidence observed or guessed: For whichever segment is being written, all states in that segment must be observed (Hard Guardrail 1); segments not yet explored are left to be explored when writing them.
- What to use for recognition: Fixed image → TemplateMatch; Text → OCR (use complete stable text for
2. 文件结构与命名
2. File Structure & Naming
先定落位再写内容:
- 新功能按模块拆文件/目录;文件组织两派选一固定:模块前缀式(——文件名带模块前缀、模块多时配目录,排序聚簇)或功能平铺式(
AutoCollect/AutoCollectRoute1.json平铺根目录,功能数适中时更轻),均有大项目实证;新建默认模块前缀式 + PascalCase 文件名(与节点 / 模板图大小写一套,目录从第一天起、无增长天花板),存量平铺项目照旧、增量新模块可开目录;细则见 references/naming.md。awards.json - pipeline JSON 有 v1 扁平与 v2 嵌套(/
recognition收敛为action,v4.4.0+)两种等价写法,字段语义通用;新建默认 v2(识别/动作/流程参数命名空间分开,错位字段在结构上不可发生),存量跟随既有主流风格、不必整仓转换,项目内统一(依据见 references/flow-patterns.md 示例注)。{type, param} - 节点名跨文件全局解析、大小写敏感;同资源包内重名即错误(跨包重名是渠道覆盖机制,见 references/naming.md);不以 开头,方括号(
$[)是 next / on_error 引用位的属性语法(]开头条目按属性前缀解析),节点名约定不使用;入口/收尾节点用[/Start后缀(约定);节点名语义按词位公式组织(End,下划线分隔槽位,见 references/naming.md);复用边界不用节点名前缀表达。任务_界面_对象_角色_变体 - image 按模块分目录,素材路径即引用键,改名必须同步改 pipeline 引用与 custom 代码内的读图调用(自定义识别 / 动作可自行加载图片)。
- 仓库布局、多资源包见 references/project-structure.md;资源目录下文件夹名禁 开头(Android 打包事故)。
_
Determine placement first, then write content:
- New features are split into files/directories by module; choose one of two file organization styles and stick with it: Module Prefix Style (— file names have module prefixes, paired with directories when there are many modules, clustered by sorting) or Flat Feature Style (
AutoCollect/AutoCollectRoute1.jsonlaid flat in the root directory, lighter for moderate numbers of features). Both are proven in large projects. New defaults: Module Prefix Style + PascalCase file names (consistent case with nodes/template images, directories from day one, no growth ceiling). Existing flat projects continue as before, and incremental new modules can use directories; see references/naming.md for details.awards.json - Pipeline JSON has two equivalent writing styles: v1 Flat and v2 Nested (/
recognitionare consolidated intoaction, v4.4.0+), with universal field semantics. New defaults: v2 (separate namespaces for recognition/action/flow parameters, misaligned fields cannot occur structurally). Existing projects follow the prevailing style, no need for full-repo conversion, just consistency within the project (see example notes in references/flow-patterns.md for basis).{type, param} - Node names are resolved globally across files and are case-sensitive; duplicate names within the same resource pack are errors (duplicate names across packs are a channel override mechanism, see references/naming.md). Do not start with ; square brackets (
$[) are attribute syntax for next / on_error reference positions (entries starting with]are parsed as attribute prefixes), and node names conventionally do not use them. Entry/exit nodes use[/Startsuffixes (convention). Node name semantics are organized by a word-position formula (End, slots separated by underscores, see references/naming.md). Reuse boundaries are not expressed via node name prefixes.Task_Interface_Object_Role_Variant - Images are divided into directories by module; asset paths are the reference keys. Renaming must synchronously update pipeline references and image-loading calls in custom code (custom recognition/actions can load images on their own).
- Repository layout and multi-resource packs see references/project-structure.md; folder names under the resource directory must not start with (Android packaging accident).
_
3. 素材准备
3. Asset Preparation
从状态清单推导素材缺口,补齐再写节点:
- 模板从基准分辨率的框架截图(无损原图缩放后)裁剪,裁剪源与识别输入保持同一图像空间。外部图片 / 游戏内截屏不一律禁用,判定标准是像素空间一致:模拟器自带截图在分辨率与控制器基准一致(或长宽比一致、可无损缩放到基准)、且无遮挡污染(通知栏 / 工具水印 / 有损压缩)时与框架截图同源同空间,可用;相机翻拍、比例不符、带污染的不可用。无论来源,一律过裁后自匹配复核兜底。
- 素材获取按工作流选工具,硬要求不随工具变(像素空间一致 + 裁后自匹配复核,见上条):agent 自主工作流优先实时观测底座(如 maafw-live)——帧流常驻、裁剪与取色全程程序化,人不必盯屏:模板从留存的原始分辨率帧裁(,识别空间一致)、探色(
crop)、无模板时候选区域编号选点(color)、不可复现状态从关键帧库留存帧裁剪(含事后离线annotate,不需要设备;产物带 L2 出处)。该工具的动线与判据读它自带的 skill(随包发布,本集合不重复):crop --from-kf。无观测底座时也可自写脚本走框架截图链路截图后程序化裁剪;人工在场调试可用官方工具链(VSCode maa-support 插件、MFA 工具箱、MPE 等)交互式截取。npx skills add https://github.com/Windsland52/maafw-live --skill maafw-live --global - 裁后自匹配复核:新模板在其来源帧的来源位置应命中(位置正确优先于得分,纯色模板得分是噪声)——裁完即验,不等流程联调才发现素材问题。
- 裁剪区域选稳定特征,避开动态数字/动效——动态内容使同一状态的每次捕获像素不同,模板命中不稳。
Derive asset gaps from the state inventory, fill them before writing nodes:
- Templates are cropped from framework screenshots at base resolution (after lossless scaling of the original image), with the cropping source and recognition input maintaining the same image space. External images / in-game screenshots are not universally prohibited; the criterion is pixel space consistency: Emulator built-in screenshots are usable if their resolution matches the controller's base (or aspect ratio matches and can be losslessly scaled to the base) and there is no occlusion or pollution (notification bar / tool watermark / lossy compression), as they share the same source and space as framework screenshots. Camera photos, mismatched proportions, or polluted images are not usable. Regardless of source, all templates must undergo post-cropping self-match verification as a fallback.
- Choose tools for asset acquisition based on workflow; hard requirements do not change with tools (pixel space consistency + post-cropping self-match verification, see previous item). Agent autonomous workflows prioritize real-time observation bases (e.g., maafw-live) — frame stream is resident, cropping and color picking are fully programmatic, no need for human screen monitoring: templates are cropped from saved original-resolution frames (, same recognition space), color sampling (
crop), point selection via candidate region numbering when no template exists (color), and unreproducible states are cropped from saved frames in the keyframe library (including post-hoc offlineannotate, no device needed; outputs carry L2 provenance). The workflow and criteria for this tool are in its built-in skill (released with the package, not repeated in this collection):crop --from-kf. Without an observation base, you can also write your own script to take screenshots via the framework's screenshot pipeline and then crop programmatically; for on-site manual debugging, use official toolchains (VSCode maa-support plugin, MFA Toolbox, MPE, etc.) for interactive capture.npx skills add https://github.com/Windsland52/maafw-live --skill maafw-live --global - Post-cropping self-match verification: A new template should match at its source position on its source frame (correct position takes priority over score; solid-color template scores are noise) — verify immediately after cropping, don't wait for flow integration testing to discover asset issues.
- Choose stable features for cropping areas, avoid dynamic numbers/animations — dynamic content causes different pixels per capture of the same state, making template matching unstable.
4. 节点编写
4. Node Authoring
每态一个节点,先识别后动作:
- 识别按状态清单的选型落字段;收紧到目标实际出现区域(提速且防误命中),起点可取识别 box 外扩约 20px——过紧易失配、过松易误中,不稳时扫描几档。
roi - 动作按意图选型,完整名单与精确参数路由 3.1-任务流水线协议核对:点击 /
Click,滑动LongPress/Swipe/MultiSwipe,按键Scroll/ClickKey/LongPressKey/KeyDown,输入KeyUp,应用启停InputText/StartApp,流程StopApp/StopTask,系统能力DoNothing/Command/Shell,扩展Screencap。点击落点遵守坐标卫生(硬护栏 2)。Custom - 要向用户展示节点消息(运行日志 / 轻提示 / 系统通知 / 弹窗)配节点 :按消息类型给模板(
focus等占位替换、支持{name}i18n),$选展示渠道;display上报遥测需项目 interface.json 配置了trace才生效——字段定义路由 3.1,模板与渠道机制路由 3.3 协议「节点通知处理」节。telemetry - 参数起点:以实测为准(得分裕量规则仅 TemplateMatch 套用;OCR / ColorMatch 语义不同;FeatureMatch 无 threshold,严格度由
threshold最少特征点数与countKNN 距离比控制)——起点取目标位实测得分减约 0.1(换场景会掉),核对仍高于该屏误配最高分;两侧贴得太近是模板 / roi 问题,调阈值救不了;能用ratio等待稳定的就不加 delay;拿不准的参数少写、用默认值(硬护栏 3)。*_wait_freezes - 写入纪律:增量插入而非整文件改写——JSONC 注释承载"为什么这么写",整写会毁掉它;缩进与字段顺序跟项目既有约定(常有格式化插件);坐标一律用框架缩放后坐标系的实测值。
One node per state, recognition first, then action:
- Recognition fields are set based on the type selected in the state inventory; is tightened to the area where the target actually appears (speeds up and prevents false matches). The starting point can be the recognition box expanded by about 20px — too tight easily causes mismatch, too loose easily causes false matches; scan several levels if unstable.
roi - Action types are selected based on intent; check the full list and precise parameters against the 3.1 Task Pipeline Protocol via routing: Click /
Click, SwipeLongPress/Swipe/MultiSwipe, KeyScroll/ClickKey/LongPressKey/KeyDown, InputKeyUp, App start/stopInputText/StartApp, FlowStopApp/StopTask, System capabilitiesDoNothing/Command/Shell, ExtensionScreencap. Click positions follow coordinate hygiene (Hard Guardrail 2).Custom - To display node messages to users (runtime logs / toast notifications / system notifications / popups), configure the node's : provide templates by message type (
focusand other placeholders are replaced, supports{name}i18n), select display channel with$;displaytelemetry reporting only takes effect iftraceis configured in the project's interface.json — field definitions are routed to 3.1, template and channel mechanisms are routed to Section "Node Notification Processing" of the 3.3 protocol.telemetry - Parameter starting points: is based on actual measurement (score margin rules only apply to TemplateMatch; OCR / ColorMatch have different semantics; FeatureMatch has no threshold, and strictness is controlled by
thresholdminimum feature points andcountKNN distance ratio) — the starting point is the measured score at the target position minus about 0.1 (it will drop when changing scenes), and verify it is still higher than the highest false match score on that screen. If the two sides are too close, it's a template/roi problem that adjusting the threshold can't fix; useratioto wait for stability instead of adding delay if possible; write fewer uncertain parameters and use default values (Hard Guardrail 3).*_wait_freezes - Writing discipline: Insert incrementally instead of rewriting the entire file — JSONC comments carry the "why it's written this way", and full rewrites will destroy them; indentation and field order follow the project's existing conventions (often with formatting plugins); all coordinates use measured values in the framework's scaled coordinate system.
5. 流程组合
5. Flow Composition
- 主干:最短可成功路径排成线性 next 链。细则:
- 等待目标出现:界面切换用"等待目标出现"节点表达,不用长 delay 凑;
- 参数保持缺省:/
pre_delay/ 节点级post_delay(next 轮询超时)尽量保持缺省;timeout - wait_freezes 的 例外:只在必须等画面稳定时用
timeout/pre_wait_freezes,其自身post_wait_freezes不属于"保持缺省"之列——默认 20s,等待区域有持续动画时等满才继续,常配 1~2s 小值兜底。timeout
- 分支:next 列表顺序即优先级,第一个命中执行。排序两原则:
- 遮蔽约束优先:某候选出现时另一候选也必然命中,前者必须排在前;排反了后者永远轮不到(功能错乱),若被遮蔽的恰是出口、遮蔽者的动作又消不掉自己的触发条件,就构成"一直命中"的死循环,救不了(硬护栏 5 的预防端在此);
timeout - 命中频次降序:其余候选按频次降序排,每轮按序识别,高频在前平均每轮少做识别,全局资源消耗最优;
- 表达手段:互斥分支用顺序表达;按位置/得分排序用 ,组合条件用
order_by/And。Or
- 遮蔽约束优先:某候选出现时另一候选也必然命中,前者必须排在前;排反了后者永远轮不到(功能错乱),若被遮蔽的恰是出口、遮蔽者的动作又消不掉自己的触发条件,就构成"一直命中"的死循环,
- 循环与中断。细则:
- 循环:循环体 + 出口节点放同一列表,限次防死磕(终止论证三选一见硬护栏 5);
max_hit - 弹窗 / 加载处理器:随时可能弹的界面(公告、奖励、断线)做独立处理节点,以 挂在关键等待点(回跳只在正常态兑现,异常态下链走空即任务失败);
[JumpBack] - 跨分支汇合用 ——引用未设置的锚点会被静默跳过。
anchor
- 循环:循环体 + 出口节点放同一列表,
- 等待与重试分层。细则:
- 等待用参数表达,不写结构:本身已在等待,节奏由
next: ["目标"]/timeout/*_wait_freezes调,自指 next 对"等下一屏出现"零增益;rate_limit - 重试需证据:动作重试只在遥测显示真实失效率后添加;
- 自指重试优先:线性流程用单节点自指 + 自身 即可(预算含首次进入、跨引用点全程累计),不建克隆节点;
max_hit - 克隆的门槛与纪律:确需独立重试预算或策略升级(重试前等待、长按替单击)才克隆;/
Retry后缀与源同前缀保持可搜;desc 注明克隆自哪个节点、与源刻意差异的字段(差异面)——差异面之外的字段与源不一致即漂移 bug,改源节点时差异面之外的字段有同步义务;Fallback - 共享处理器例外:被多处引用的节点在 累计语义下不能用小值,防线是严格识别门控;
max_hit用尽的候选静默退场(识别时跳过、不报错),列表照常轮询——再无可命中候选时空转至超时、走宿主节点的 on_error,耗尽本身不是失败信号;max_hit - 审查基线:无证据的自指 / 自回环在审查时视为待删项。
- 等待用参数表达,不写结构:
- 失败路径:每个 next 列表问一遍"全没命中怎么办"。细则:
- 兜底结构:(
timeout无限慎用,v5.5+)+-1兜底(回退/重试/上报),重试配on_error限次;max_hit - on_error 链自身必须能稳定命中——异常状态里再失败没有二次兜底,任务直接终止;
- on_error 只做异常恢复:不当正常流程的控制流(比如拿来实现 if-else 效果);
- 重试与 是安全带不是修复:反复失败先修根因(识别不稳/逻辑缺陷);
max_hit - 禁无识别门控的盲目重试:"没反应就原地点第二次"(第二次点击可能已落到下一界面的其他元素上);重新识别到按钮仍在才再点的有限重试是合法恢复手段;
- 动作失败走收敛:动作失败(框架报错)不以自指或自回环重试——持续的动作失败是缺陷不是抖动,让 on_error 收敛(上报 / 回退 / 重入子流程入口重跑识别),瞬态恢复须显式有界。
- 兜底结构:
模式示例 JSON 与稳定性法则(识别→操作→再识别、少用硬延迟)见 references/flow-patterns.md。
- Main Trunk: Arrange the shortest successful path as a linear next chain. Detailed rules:
- Wait for target to appear: Use "wait for target to appear" nodes for interface transitions, don't make do with long delays;
- Keep parameters default: /
pre_delay/ node-levelpost_delay(next polling timeout) should be kept default as much as possible;timeout - Exception for of wait_freezes: Only use
timeout/pre_wait_freezeswhen you must wait for the screen to stabilize; their ownpost_wait_freezesis not in the "keep default" category — default is 20s, and if the waiting area has continuous animation, it will wait the full time before continuing, often paired with a small 1~2s fallback value.timeout
- Branches: The order of the next list is the priority, and the first match executes. Two sorting principles:
- Occlusion constraint first: When one candidate appears, another candidate will definitely match, the former must be ranked first; if reversed, the latter will never be reached (functional disorder). If the occluded one is exactly the exit, and the occluder's action cannot eliminate its own trigger condition, it forms an "always matching" infinite loop that can't fix (this is the prevention side of Hard Guardrail 5);
timeout - Match frequency descending: The remaining candidates are sorted in descending order of frequency; each round recognizes sequentially, with high-frequency ones first, reducing average recognition per round and optimizing global resource consumption;
- Expression methods: Mutually exclusive branches are expressed by order; use for sorting by position/score, and
order_by/Andfor combined conditions.Or
- Occlusion constraint first: When one candidate appears, another candidate will definitely match, the former must be ranked first; if reversed, the latter will never be reached (functional disorder). If the occluded one is exactly the exit, and the occluder's action cannot eliminate its own trigger condition, it forms an "always matching" infinite loop that
- Loops and Interrupts. Detailed rules:
- Loops: Loop body + exit node are placed in the same list, limits the count to prevent dead loops (see Hard Guardrail 5 for three termination justification options);
max_hit - Popup / Loading Handlers: Interfaces that may pop up at any time (announcements, rewards, disconnections) are made into independent handling nodes, attached to key waiting points with (jumps only take effect in normal state; if the chain runs empty in exception state, the task fails);
[JumpBack] - Use for cross-branch convergence — references to unset anchors will be silently skipped.
anchor
- Loops: Loop body + exit node are placed in the same list,
- Waiting and Retry Layering. Detailed rules:
- Waiting is expressed with parameters, not structure: is already waiting by itself, the rhythm is adjusted by
next: ["target"]/timeout/*_wait_freezes, self-referencing next has zero benefit for "waiting for the next screen to appear";rate_limit - Retries require evidence: Action retries are only added after telemetry shows a real failure rate;
- Self-reference retry is preferred: For linear flows, a single node self-reference + its own is sufficient (budget includes first entry, accumulated across all reference points), no need to create clone nodes;
max_hit - Cloning thresholds and discipline: Only clone when independent retry budget or strategy upgrade is truly needed (wait before retry, long press instead of single click); use /
Retrysuffixes with the same prefix as the source to remain searchable; desc notes which node it is cloned from and which fields are intentionally different from the source (diff surface) — fields outside the diff surface that are inconsistent with the source are drift bugs, and when modifying the source node, fields outside the diff surface must be synchronized;Fallback - Shared handler exception: Nodes referenced by multiple places cannot use small values under the cumulative semantics; the defense is strict recognition gating. Candidates whose
max_hitis exhausted exit silently (skipped during recognition, no error), and the list is polled as usual — when there are no more matching candidates, it idles until timeout and follows the host node's on_error; exhaustion itself is not a failure signal;max_hit - Review baseline: Unjustified self-references / self-loops are treated as items to be deleted during review.
- Waiting is expressed with parameters, not structure:
- Failure Paths: Ask "what if all miss?" for every next list. Detailed rules:
- Fallback structure: (use
timeoutinfinite with caution, v5.5+) +-1fallback (rollback/retry/report), retries paired withon_errorlimit;max_hit - The on_error chain itself must be able to match stably — there is no second fallback if it fails again in exception state, and the task terminates directly;
- on_error is only for exception recovery: Do not use it as control flow for normal processes (e.g., to implement if-else effects);
- Retries and are seatbelts, not fixes: For repeated failures, fix the root cause first (unstable recognition / logical defects);
max_hit - Blind retries without recognition gating are prohibited: "Click again in the same spot if there's no response" (the second click may land on other elements of the next interface); limited retries where the button is re-recognized as still present before clicking again are legitimate recovery methods;
- Action failures go to convergence: Action failures (framework errors) are not retried via self-reference or self-loops — persistent action failures are defects, not jitters; let on_error converge (report / rollback / re-enter sub-flow entry and re-run recognition), and transient recovery must be explicitly bounded.
- Fallback structure:
Pattern example JSON and stability rules (recognize → operate → re-recognize, use less hard delays) see references/flow-patterns.md.
6. 自查与交接
6. Self-Check & Handover
- 可达性:无孤立节点、无 anchor 断链、无未解析引用;完备性四问——主线能跑?弹窗能处理?加载能等过去?不在目标场景时的行为已显式定义(自动跳过还是失败上报,是项目的产品决策,不能默认漏掉)?
- 有节点测试基建的项目(如带 目录与截图期望的)为新增识别节点补用例。
tests/ - 交接:单节点验证与端到端验收 → ;task 入口与选项接线 →
maafw-debug;JSON 表达不了的逻辑 →maafw-interface。maafw-custom
- Reachability: No isolated nodes, no broken anchor chains, no unresolved references; Four completeness questions — Can the main trunk run? Can popups be handled? Can loading be waited through? Is the behavior when not in the target scenario explicitly defined (auto-skip or failure report, this is a product decision for the project, cannot be omitted by default)?
- For projects with node testing infrastructure (e.g., with directory and screenshot expectations), add test cases for new recognition nodes.
tests/ - Handover: Single-node verification and end-to-end acceptance → ; task entry and option wiring →
maafw-debug; logic that cannot be expressed in JSON →maafw-interface.maafw-custom
修改轨(存量项目入口)
Modification Track (Legacy Project Entry)
改动、重构、审查既有 pipeline 时走此轨:
- 摸底(规模随改动伸缩,走索引不通读)。细则:
- 小修(bug、调字段、ROI 微调):定位目标节点及其定义与直接上下游即可;
- 结构性改动(新增功能、重构、动复用面)才摸复用面——先看地图(目录树 + interface.json 任务清单)→ 节点名索引用脚本提取(逐文件列 root key,勿逐文件通读)→ 按能力关键词检索、命中文件才读全文(词位命名的语义名即检索索引,共享件先查 );
general.json - 素材:按 目录结构按需检索;
image/ - 无论规模:先明确改动边界(哪些节点动、哪些只引用)。
- 搜引用:改节点名或素材路径前全库搜索引用点——漏改的后果按引用位置分档,并非都是静默:next / on_error 漏改加载期即失败(非锚点引用的存在性校验,能抓住;interface 的 pipeline_override 注入的悬空引用同样被拦);roi / target 引用、custom 的 run_task、template 素材路径漏改运行期失败(目标解析空即动作失败 / 任务不存在 / 模板懒加载缺图);条目(校验跳过锚点名)与 option 的 pipeline_override(override 落空)才是静默失联。引用点清单:
[Anchor]- 节点引用:next / on_error 的三种写法(裸字符串、前缀、
[JumpBack]X对象)、roi / target 的 string 引用、{name:"X"}、option 的 pipeline_override、custom 的 run_task / override_next;[Anchor] - 素材路径:pipeline 的 template 与 custom 代码内的读图调用(自定义识别 / 动作可自行加载 下的图);
image/ - 同前缀克隆:改识别 / 动作参数前另搜 /
Retry后缀——克隆与源静默漂移,同样不报错;Fallback - 跨语言引用:custom / agent 代码内写节点名(语言不限——C++ / Python / Node.js / Go 等)按入口分两类——/
run_task/run_recognition的 entry 按原始字符串查节点,传run_action只会去找字面叫这个名字的节点并失败,锚点跳转先"[Anchor]X"取实名再传入;get_anchor的 next 列表与 pipeline 引用位同解析,override_next/[JumpBack]属性语法可用。锚点本身可经 context API 读写([Anchor]/set_anchor,C API / agent RPC / 各绑定均暴露);写实名 + 改名前全库搜引用仍是基线防线。get_anchor
- 节点引用:next / on_error 的三种写法(裸字符串、
- 修改:按需对齐新建轨 2–5 的同等标准写新内容。
- 自查:可达性检查 + 反模式清单逐项核对(references/anti-patterns.md——坐标卫生、timeout/-1 滥用、循环限次、版本兼容)。
Use this track when modifying, refactoring, or reviewing existing pipelines:
- Assessment (scale scales with changes, use indexes instead of reading everything). Detailed rules:
- Minor fixes (bugs, field adjustments, ROI fine-tuning): Just locate the target node, its definition, and its direct upstream and downstream;
- Structural changes (new features, refactoring, changes to reuse surfaces) require assessing the reuse surface — first look at the map (directory tree + interface.json task list) → extract node name indexes with scripts (list root keys per file, don't read through each file) → search by capability keywords, read full text only for matched files (semantic names from word-position naming are search indexes, check first for shared items);
general.json - Assets: Search as needed according to the directory structure;
image/ - Regardless of scale: First clarify the change boundaries (which nodes are modified, which are only referenced).
- Search References: Search the entire repository for reference points before renaming nodes or asset paths — the consequences of missed changes are graded by reference location, not all are silent: Missed changes in next / on_error fail at load time (existence checks for non-anchor references can catch them; dangling references injected by interface's pipeline_override are also blocked); Missed changes in roi / target references, custom's run_task, template asset paths fail at runtime (empty target resolution means action failure / task does not exist / template lazy loading missing image); Only entries (anchor names skip validation) and option's pipeline_override (override misses) are silent disconnections. Reference point list:
[Anchor]- Node references: Three writing styles of next / on_error (bare string, prefix,
[JumpBack]Xobject), string references in roi / target,{name:"X"}, option's pipeline_override, custom's run_task / override_next;[Anchor] - Asset paths: template in pipeline and image-loading calls in custom code (custom recognition/actions can load images under on their own);
image/ - Same-prefix clones: Before modifying recognition / action parameters, also search for /
Retrysuffixes — clones and sources drift silently, also without errors;Fallback - Cross-language references: Node names written in custom / agent code (any language — C++ / Python / Node.js / Go, etc.) are divided into two categories by entry: entries for /
run_task/run_recognitionlook up nodes by raw string; passingrun_actionwill only look for a node literally named that and fail; for anchor jumps, first use"[Anchor]X"to get the real name then pass it in. The next list ofget_anchoris parsed the same as pipeline reference positions, andoverride_next/[JumpBack]attribute syntax can be used. Anchors themselves can be read and written via the context API ([Anchor]/set_anchor, exposed in C API / agent RPC / various bindings); writing real names + searching the entire repo for references before renaming is still the baseline defense.get_anchor
- Node references: Three writing styles of next / on_error (bare string,
- Modification: Write new content according to the same standards as steps 2–5 of the New Creation Track as needed.
- Self-Check: Reachability check + item-by-item verification against the anti-pattern list (references/anti-patterns.md — coordinate hygiene, timeout/-1 abuse, loop limit counts, version compatibility).
深入阅读(按需)
Further Reading (As Needed)
- references/naming.md — 文件/目录/节点/图片命名规范全文(协议层 + 两派实证)
- references/project-structure.md — 仓库布局、多资源包、任务入口存放、agent 组织
- references/flow-patterns.md — 流程设计展开、模式示例 JSON、稳定性法则
- references/anti-patterns.md — 坐标卫生细则、反模式清单、审查清单
- references/naming.md — Full naming specifications for files/directories/nodes/images (protocol layer + two schools of practice)
- references/project-structure.md — Repository layout, multi-resource packs, task entry storage, agent organization
- references/flow-patterns.md — Flow design expansion, pattern example JSON, stability rules
- references/anti-patterns.md — Coordinate hygiene details, anti-pattern list, review checklist