Click Path Audit

affaan-m/ECC/docs/zh-CN/skills/click-path-audit

作者 affaan-mef648e01899ba3e8dc6371642deaaf64b4477775无许可证275K 个星标收录于 2026年10月9日更新于 2026年10月9日仓库4天前更新

追踪每个面向用户的按钮/触点的完整状态变化序列,以发现功能单独工作但相互抵消、产生错误最终状态或使UI处于不一致状态的错误。适用于:系统调试未发现错误但用户报告按钮失效,或在任何涉及共享状态存储的重大重构之后。

AI 生成的概览

审计界面点击处理函数,找出一个调用静默抵消另一个调用、导致按钮失效的状态交互问题。

功能
该技能提供一套结构化流程,用于审计按钮、开关和表单提交等面向用户的交互触点。它先梳理每个状态存储操作及其副作用,再追踪处理函数中的每次函数调用,确认读取、写入或重置了哪些状态。它按缺陷模式报告问题,包括顺序撤销、异步竞态、过期闭包、缺失状态转换、死路径和 useEffect 干扰,并给出预期结果、实际结果和具体修复方案。它产出的是书面审计报告,而不是代码改动。
适用场景
当系统化调试未发现缺陷、但用户报告按钮或控件无反应时使用。它也适用于修改共享状态存储之后、涉及共享状态的重构之后,以及发布前针对关键用户流程的检查。
运行要求
不需要脚本或工具,仅为纯指令流程。它假定代码库使用 Zustand、Redux 或 React context 等共享状态存储,并建议在全应用审计时并行运行多个代理。

/click-path-audit — 行为流审计

发现静态代码审查遗漏的缺陷:状态交互副作用、顺序调用间的竞态条件,以及相互静默撤销的处理程序。

解决的问题

传统调试检查:

  • 函数是否存在?(缺少连接)
  • 是否崩溃?(运行时错误)
  • 是否返回正确类型?(数据流)

但未检查:

  • 最终 UI 状态是否与按钮标签承诺一致?
  • 函数 B 是否静默撤销了函数 A 刚刚执行的操作?
  • 共享状态(Zustand/Redux/context)是否存在抵消预期操作的副作用?

真实案例:一个"新邮件"按钮依次调用了 setComposeMode(true) 和 selectThread(null)。两者单独工作正常。但 selectThread 有一个副作用重置了 composeMode: false。按钮毫无反应。系统化调试发现了 54 个缺陷——这个被遗漏了。


工作原理

针对目标区域内的每个交互触点:

1. 识别处理函数(onClick、onSubmit、onChange 等)2. 按顺序追踪处理函数中的每个函数调用3. 对于每个函数调用:   a. 它读取了哪些状态?   b. 它写入了哪些状态?   c. 它是否对共享状态产生了副作用?   d. 它是否作为副作用重置/清除了任何状态?4. 检查:后续调用是否会撤销前面调用的状态变更?5. 检查:最终状态是否符合用户对按钮标签的预期?6. 检查:是否存在竞态条件(异步调用以错误顺序解析)?

执行步骤

步骤 1:映射状态存储

在审计任何触点之前,构建每个状态存储操作的副作用映射:

对于作用域内的每个 Zustand 存储 / React 上下文:  对于每个操作/设置器:    - 它设置了哪些字段?    - 它是否作为副作用重置了其他字段?    - 文档:actionName → {sets: [...], resets: [...]}

这是关键参考。"新邮件"缺陷在不知道 selectThread 重置了 composeMode 的情况下是不可见的。

输出格式:

STORE: emailStore  setComposeMode(bool) → 设置: {composeMode}  selectThread(thread|null) → 设置: {selectedThread, selectedThreadId, messages, drafts, selectedDraft, summary} 重置: {composeMode: false, composeData: null, redraftOpen: false}  setDraftGenerating(bool) → 设置: {draftGenerating}  ...
危险的重置(清除不属于自身状态的操作):  selectThread → 重置 composeMode(由 setComposeMode 拥有)  reset → 重置所有内容

步骤 2:审计每个触点

针对目标区域内的每个按钮/开关/表单提交:

TOUCHPOINT: [按钮标签] 在 [组件:行]  HANDLER: onClick → {    调用 1: functionA() → 设置 {X: true}    调用 2: functionB() → 设置 {Y: null} 重置 {X: false}  ← 冲突  }  EXPECTED: 用户看到 [按钮标签所承诺的描述]  ACTUAL: X 为 false,因为 functionB 重置了它  VERDICT: BUG — [描述]

检查以下每种缺陷模式:

模式 1:顺序撤销
handler() {  setState_A(true)     // 设置 X = true  setState_B(null)     // 副作用:重置 X = false}// 结果:X 为 false。第一次调用毫无意义。
模式 2:异步竞态
handler() {  fetchA().then(() => setState({ loading: false }))  fetchB().then(() => setState({ loading: true }))}// 结果:最终的 loading 状态取决于哪个先完成
模式 3:过期闭包
const [count, setCount] = useState(0)const handler = useCallback(() => {  setCount(count + 1)  // 捕获了过时的 count  setCount(count + 1)  // 同样的过时 count — 只增加 1,而不是 2}, [count])
模式 4:缺失状态转换
// 按钮显示"保存",但处理程序仅验证,从未实际保存// 按钮显示"删除",但处理程序设置了一个标志而未调用API// 按钮显示"发送",但API端点已被移除/损坏
模式 5:条件死路径
handler() {  if (someState) {        // 此时 someState 始终为 false    doTheActualThing()    // 永远不会执行到  }}
模式 6:useEffect 干扰
// Button 设置 stateX = true// useEffect 监听 stateX 并将其重置为 false// 用户看不到任何变化

步骤 3:报告

针对发现的每个缺陷:

CLICK-PATH-NNN: [严重性: 严重/高/中/低]  触点: [按钮标签] 位于 [文件:行号]  模式: [顺序撤销 / 异步竞态 / 过期闭包 / 缺失过渡 / 死路径 / useEffect 干扰]  处理函数: [函数名或内联]  追踪:    1. [调用] → 设置 {字段: 值}    2. [调用] → 重置 {字段: 值}  ← 冲突  预期: [用户期望的结果]  实际: [实际发生的结果]  修复: [具体修复方案]

范围控制

此审计成本较高。请适当限定范围:

  • 全应用审计: 在发布或重大重构后使用。按页面启动并行代理。
  • 单页面审计: 在构建新页面或用户报告按钮失效后使用。
  • 存储聚焦审计: 在修改 Zustand 存储后使用——审计所有使用已更改操作的消费者。

全应用推荐的代理拆分:

Agent 1:映射所有状态存储(步骤 1)——这是所有其他代理的共享上下文Agent 2:仪表盘(任务、笔记、日志、想法)Agent 3:聊天(DanteChatColumn、JustChatPage)Agent 4:邮件(ThreadList、DraftArea、EmailsPage)Agent 5:项目(ProjectsPage、ProjectOverviewTab、NewProjectWizard)Agent 6:CRM(所有子标签页)Agent 7:个人资料、设置、保险库、通知Agent 8:管理套件(所有页面)

代理 1 必须首先完成。其输出是所有其他代理的输入。


何时使用

  • 系统化调试发现"无缺陷"但用户报告 UI 失效后
  • 修改任何 Zustand 存储操作后(检查所有调用者)
  • 任何涉及共享状态的重构后
  • 发布前,针对关键用户流程
  • 当按钮"无反应"时——这是解决该问题的工具

何时不使用

  • 针对 API 级别缺陷(错误的响应结构、缺失端点)——使用系统化调试
  • 针对样式/布局问题——视觉检查
  • 针对性能问题——性能分析工具

与其他技能的集成

  • 在 /superpowers:systematic-debugging(发现其他 54 种缺陷类型)之后运行
  • 在 /superpowers:verification-before-completion(验证修复是否有效)之前运行
  • 反馈至 /superpowers:test-driven-development——此处发现的每个缺陷都应添加测试

示例:启发此技能的缺陷

ThreadList.tsx "新邮件"按钮:

onClick={() => {  useEmailStore.getState().setComposeMode(true)   // ✓ 设置 composeMode = true  useEmailStore.getState().selectThread(null)      // ✗ 重置 composeMode = false}}

存储定义:

selectThread: (thread) => set({  selectedThread: thread,  selectedThreadId: thread?.id ?? null,  messages: [],  drafts: [],  selectedDraft: null,  summary: null,  composeMode: false,     // ← 这个静默重置导致按钮失效  composeData: null,  redraftOpen: false,})

系统化调试遗漏了它,因为:

  • 按钮有 onClick 处理程序(未失效)
  • 两个函数都存在(无缺失连接)
  • 两个函数均未崩溃(无运行时错误)
  • 数据类型正确(无类型不匹配)

点击路径审计捕获了它,因为:

  • 步骤 1 映射出 selectThread 重置了 composeMode
  • 步骤 2 追踪处理程序:调用 1 设置为 true,调用 2 重置为 false
  • 判定:顺序撤销——最终状态与按钮意图矛盾

来源与署名

来源:affaan-m/ECC位于docs/zh-CN/skills/click-path-audit提交ef648e0

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架