debug-broken-ui
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseThe app is broken and the code looks fine
应用故障但代码看起来无问题
Reading the source again will not tell you why. The evidence is in the running app, and most of it never reaches the screen: the request that failed, the store that never moved, the handler that was never bound, the element covered by something invisible.
Reticle reads all of it from inside the page. Not installed? , then the skill.
RETICLE_INSTALL_SOURCE=npx_skill npx @reticlehq/server@latest initinstall-and-verify反复查看源代码无法找到原因。故障证据存在于运行中的应用里,且大部分不会显示在界面上:失败的请求、从未更新的状态存储、未绑定的事件处理器、被不可见元素遮挡的组件。
Reticle 会从页面内部读取所有这些信息。还未安装?执行 ,然后使用 技能。
RETICLE_INSTALL_SOURCE=npx_skill npx @reticlehq/server@latest initinstall-and-verifyDo not start by guessing. Start by reproducing.
不要靠猜测开始,先复现问题
reticle_snapshot({ sessionId, mode: "interactive" }) // controls only, with refs
reticle_act_and_wait({ sessionId, ref, action: "click", until: { kind: "element", query: { testid: "..." } } })The verdict already narrows it: / means a channel saw something incompatible with the UI: you have the bug. means Reticle drove it and could not tell, which is a different investigation from "it failed".
nocontradictedunknownRead the act result before you call anything else. Its block already carries the whole causal window of that one click: , , , , , , , : real before→after diffs, not counts. The console, network, storage and state calls below are for going DEEPER into something the summary already pointed at. Calling all three straight after an act pays three model round trips (and, in an approval-gated client, three human clicks) for evidence you were already holding.
summarynet {total, errors, headline}consoleErrorsstateDiffs [{path, from, to}]storageDiffs [{key, from, to}]routesignalslayoutShiftlongTaskssummary.stateUnwatched: truestateDiffsWhen the summary does point somewhere, read that channel scoped to what you just did: pass from the act result, or you are reading a buffer that predates the click:
sincereticle_console({ sessionId, since })
reticle_network({ sessionId, since })
reticle_state({ sessionId, store })reticle_snapshot({ sessionId, mode: "interactive" }) // controls only, with refs
reticle_act_and_wait({ sessionId, ref, action: "click", until: { kind: "element", query: { testid: "..." } } })判定结果会缩小排查范围: / 表示某个渠道发现了与UI不一致的情况:你找到了bug。 表示Reticle执行了操作但无法判断,这与“操作失败”是不同的排查方向。
nocontradictedunknown先查看操作结果再调用其他命令。 结果中的块已经包含了此次点击的完整因果链信息:、、、、、、、:这些是真实的前后差异数据,而非统计计数。下方的控制台、网络、状态调用命令用于深入分析已指向的问题。操作后直接调用这三个命令会产生三次模型往返请求(在需要人工审批的客户端中,还需要三次人工点击),但其实你已经持有相关证据了。
summarynet {total, errors, headline}consoleErrorsstateDiffs [{path, from, to}]storageDiffs [{key, from, to}]routesignalslayoutShiftlongTaskssummarysummary.stateUnwatched: truestateDiffs当指向某个方向时,针对你刚执行的操作查看对应渠道的数据:传入操作结果中的参数,否则你读取的是点击之前的缓存数据:
summarysincereticle_console({ sessionId, since })
reticle_network({ sessionId, since })
reticle_state({ sessionId, store })The diagnosis table
诊断对照表
| What you see | What it is | Next |
|---|---|---|
| No request fired at all | the handler is not bound, or a client cache served a stale value | |
Request fired, | a real backend failure the UI swallowed | the response body is in the network entry |
| the app never read the response: verdict says | usually a real bug in the success path |
| Request fine, DOM fine, store stale | UI-vs-state desync, invisible to any screenshot | |
| Click did nothing, no error | the control is dead, occluded, or disabled | |
| Element "not found" that you can see | virtualised list has not mounted it | |
| Looks logged in, behaves logged out | the token never persisted | |
| Console error that predates your click | a pre-existing fault, not your bug | call it out before continuing |
| 现象 | 原因 | 下一步操作 |
|---|---|---|
| 完全没有发送请求 | 事件处理器未绑定,或客户端缓存返回了过时值 | 使用 |
请求已发送,返回 | UI吞掉了真实的后端错误 | 响应体在网络记录中 |
返回 | 应用从未读取响应:判定结果显示 | 通常是成功路径中的真实bug |
| 请求正常,DOM正常,状态存储过时 | UI与状态不同步,截图无法发现 | |
| 点击无响应,无错误 | 控件失效、被遮挡或已禁用 | |
| 可见元素提示“未找到” | 虚拟列表尚未挂载该元素 | 使用 |
| 显示已登录,但表现为未登录 | token从未持久化存储 | 使用 |
| 控制台错误早于你的点击操作 | 预先存在的故障,与当前bug无关 | 在继续排查前先指出该问题 |
Get the file, not a theory
获取具体文件位置,而非理论推测
reticle_inspect({ sessionId, ref })Returns the component and for the element you are looking at, plus whether it is occluded, sized, disabled or off-theme. That is the pointer to open. End the investigation with a location, not a hypothesis.
source: { file, line }reticle_inspect({ sessionId, ref })返回你查看的元素对应的组件及,还会告知元素是否被遮挡、尺寸、是否禁用或偏离主题。这就是你需要打开的文件位置。以定位结果结束排查,而非停留在假设阶段。
source: { file, line }When the flow is long
当流程较长时
Do not ping-pong act → snapshot → act → snapshot to find the failing step. Drive the journey with and assert once; the first step whose consequence fails is the one to look at, and you paid a fraction of the calls to find it.
reticle_act_sequence不要通过反复执行 act → snapshot → act → snapshot 来寻找失败步骤。使用执行完整流程并一次性断言;第一个未达预期的步骤就是需要排查的对象,这样能大幅减少调用次数。
reticle_act_sequenceBefore you say it is fixed
在确认修复前
Re-run the reproduction as a verdict ( with the consequence named up front) rather than eyeballing the page. A fix confirmed by looking at it is the failure mode that created this ticket.
reticle_act_and_waitAnd never weaken the check to make it pass.
Troubleshooting Reticle itself (as opposed to the app): . Everything else: . If Reticle could not see something you needed, with .
curl https://docs.reticle.sh/troubleshooting.mdcurl https://docs.reticle.sh/llms.txtreticle_feedbackkind: "gap"不要通过肉眼观察页面来确认修复,而是将复现流程作为判定依据(使用并提前指定预期结果)。靠肉眼确认修复正是导致此类工单出现的常见问题。
reticle_act_and_wait永远不要为了让检查通过而降低校验标准。
排查Reticle自身问题(而非应用问题):执行 。其他问题:执行 。如果Reticle未能捕捉到你需要的信息,使用并设置。
curl https://docs.reticle.sh/troubleshooting.mdcurl https://docs.reticle.sh/llms.txtreticle_feedbackkind: "gap"