关于 replay-user-flows
用于 Reticle 的技能,可将应用操作旅程保存为 flow,并作为回归检查重放。它使用语义锚点和明确声明的结果,让录制内容不止于重现点击。
主要功能
- 01自动将会话操作保存为 flow
- 02确定性重放 flow
- 03按变更文件筛选 flow
- 04依据建议重新绑定漂移锚点
- 05检查断言覆盖情况
适用场景
- 01回归检查产品关键旅程
- 02重放受代码变更影响的 flow
- 03找出未断言结果的已存 flow
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ reticlehq/ reticle --skill replay-user-flows安装后在 Claude Code 中输入/replay-user-flows确认已加载。
详细介绍
记录一次旅程,永久重新验证
探索应用以找到一段旅程是最费时的部分;每次变更后再用模型重新执行,都会再次付出这笔成本。Reticle 流程只需付出一次:旅程会连同语义锚点一起保存,之后即可确定性地重放。
需要在项目中接入 Reticle。还没设置?请遵循 reticle 技能:它会安装 Reticle,在 init 修改应用文件前征求用户同意,并验证一条流程。
记录
无需询问。会话结束时,执行过程会自动保存为流程,写入 .reticle/flows/。请提交它:这样仓库中的任何 Agent 都能重放。
是否值得提交,取决于你如何执行。只有在你声明了预期结果时,步骤才会保留断言,因此请像这样执行黄金路径:
reticle_act_and_wait({ sessionId, ref, action: "click", until: { kind: "signal", name: "task:created" } })
该步骤会作为测试重放。单独使用 reticle_act 只会保存一次点击,没有任何结果需要验证;即使发生回归,重放也会显示通过。
如果想主动命名流程,而不是使用自动名称,可通过 reticle_run { tool, args } 调用 reticle_record 和 reticle_flow_save。它们都不会在默认工具列表中展示,也没必要展示:reticle_run 属于默认工具集,可按名称分发到任何已注册工具。设置 RETICLE_ADVERTISE_ALL_TOOLS=1 会直接展示它们,但使用的是较早且尚未合并的工具名称。不要为 Agent 设置它:本技能中的调用使用默认名称。
请标注业务结果,而不只是点击,这样重放才能证明旅程_确实达成了_目标。扩展工具集中的示例,如上面两个工具:
reticle_run({ tool: "reticle_annotate", sessionId, args: { flow: "create-task", kind: "intent", text: "create a task and see it in the list" } })
reticle_run({ tool: "reticle_annotate", sessionId, args: { flow: "create-task", kind: "success-state", signal: "task:created" } })
无需事先添加 data-testid。 如果元素没有 testid,步骤会自动锚定到其组件和源代码位置;即使重构后保留 testid,重放也仍会通过。
重放
reticle_verify({ sessionId, action: "change", files: ["src/tasks/TaskList.tsx"] })
这会重放覆盖这些文件的流程。若要直接重放指定流程,可通过 reticle_run 调用 reticle_flow_replay。
状态分为三种,失败时的信息清晰可读,不会让人摸不着头脑:
| 状态 | 含义 | 下一步 |
|---|---|---|
ok | 所有锚点均已解析,所有预期结果均成立 | 完成 |
drift | 未能匹配某个锚点:testid 被重命名,或某个信号始终未触发 | 查看 decision.nextAction;其中会标出文件和行号,以及最接近的可用锚点 |
error | 流程文件缺失或无效,或某个步骤在运行时失败 | 根据错误信息中的失败步骤进行修复 |
发生偏移时,reticle_verify { action: "heal" } 会根据最接近的匹配项提出重新绑定建议,避免流程逐渐失效。若重命名是有意为之,就应用该建议;若不是,就将其视为问题。
任意变更后重新验证整个测试套件
reticle_verify({ sessionId, action: "flows" })
// → { status, total, passed, failed, failures: [{ flow, verdict, whatChanged, whereInSource, nextAction }] }
一次调用,重放所有已保存的流程,不必为每条流程都调用一次模型。只有失败时才会提供详细信息,因此检查全绿的套件成本很低。构建 → reticle_verify { action: "flows" } → 根据各项 nextAction 修复 → 重复,这就是回归循环,也是记录流程的根本目的。
只重放变更可能影响的流程
套件很大时,修改一个文件后重放所有流程纯属浪费。直接提供差异:
reticle_verify({ sessionId, action: "change", since: "HEAD~1" })
它会找出覆盖你所编辑文件的已保存流程,并只重放这些流程。你可以提供 git 引用或文件列表。在开发循环中使用此方法,发布前再运行 reticle_verify { action: "flows" }:前者范围小、速度快,后者则能确保完整覆盖。
哪些流程确实能证明结果
reticle_run({ tool: "reticle_domain", sessionId }) // not advertised, one hop away
// → { flowCount, coverage: { asserted, presenceOnly, assertionFree }, gaps: { declaredUntestedSignals, … } }
不包含任何断言的已记录流程,即使发生回归,重放也会显示通过:它只能证明点击仍可执行,无法证明应用仍正常工作。录制完成后请检查这一点:任何出现在 assertionFree 中的流程都需要通过 annotate 添加 success-state,否则它就只是装饰。
不应录制的情况
只运行一次的操作流程,用 reticle_act_and_wait 执行后便可忘掉。录制那些定义产品的流程(回归出问题会让人头疼的流程),探索性操作流程则不必保存。录制一套 40 条半吊子流程,耗费的精力远超其带来的价值。
诚实
回放会如实报告实际发生的情况。drift 不代表通过;如果应用确实出了问题,却通过修复操作流程让状态变绿,这是让整套流程失去价值的唯一做法。如果重命名并非有意为之,那么 drift 就是发现的问题:使用 whereInSource 指针报告。
完整操作流程参考,一页即可查阅:curl https://docs.reticle.sh/flows.md。所有内容的索引:curl https://docs.reticle.sh/llms.txt。