tidy
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesetidy
tidy
- IS: a hunt for complexity, then the fix. Five angles read the current diff looking for what is duplicated, overbuilt, wasteful, bolted on at the wrong depth, or untested; the orchestrator merges the findings, edits the working tree, and proves the build is still green. shows more changes after than before.
git status - IS NOT: a findings report (use : read-only, severity-tiered, never edits a file), an architecture refactor, or a license to touch files outside the diff.
pr-reviewer
It hunts complexity, not correctness. A concurrency race or a missing idempotency key is 's ground; duplicated logic, a layer with one caller, and a special case bolted onto shared code are this skill's, and it finds them itself rather than waiting to be handed a list.
pr-reviewerSelf-contained by design: every phase runs on any harness that loads a skill, with or without a subagent tool, and never depends on a host's built-in review command.
When to run: after the feature works and the tests pass, before opening the PR. Not mid-implementation, where it polishes code the next commit deletes. It reads the whole diff, so cost scales with diff size; on a large one, narrow it to a path.
After a review. then is the common pair. A report that already exists is extra input, never a smaller sweep: run all five angles regardless, and apply the report's confirmed findings alongside your own. Two passes looking for different things is the point of running both, and the correctness fixes a review confirmed would otherwise be left for the user to hand-apply.
pr-reviewertidy- 功能: 排查代码复杂度并进行修复。从五个维度扫描当前diff,查找重复代码、过度设计、冗余操作、层级错位或未测试的内容;协调器整合排查结果,编辑工作区代码,并确保构建仍能正常通过。执行后会显示新增的修改。
git status - 非功能: 不是排查报告工具(如需只读、分严重级别的报告且不修改文件,请使用),不是架构重构工具,也无权修改diff范围外的文件。
pr-reviewer
它仅排查复杂度问题,不处理正确性问题。并发竞争或缺少幂等键属于的处理范畴;而重复逻辑、仅有一个调用者的层级、添加到共享代码上的特殊处理则是本技能的目标,它会主动发现这些问题,而非等待用户提供问题列表。
pr-reviewer设计上具备独立性:每个阶段均可在任何加载该技能的环境中运行,无论是否有子代理工具,且从不依赖宿主内置的评审命令。
运行时机: 在功能实现完成且测试通过后,提交PR之前。不要在实现过程中运行,否则会优化后续提交中会被删除的代码。它会读取整个diff,因此耗时随diff大小增加;如果diff较大,可将范围缩小到特定路径。
评审后运行: 先运行再运行是常见组合。已有的评审报告是额外输入,但不会缩小排查范围:仍会运行全部五个维度,并将报告中已确认的结论与自身排查结果一同应用。两者的排查重点不同,分开运行才能覆盖更多问题,否则评审确认的正确性修复需要用户手动应用。
pr-reviewertidyContents
目录
- Workflow checklist
- Phase 1: Scope, baseline, and any incoming review
- Phase 2: Run five review angles
- Phase 3: Merge findings and apply fixes
- Phase 4: Verify and report
- Gotchas
- Related skills
- 工作流检查清单
- 阶段1:范围、基准线及现有评审结果
- 阶段2:运行五个评审维度
- 阶段3:整合排查结果并应用修复
- 阶段4:验证并报告
- 注意事项
- 相关技能
Workflow checklist
工作流检查清单
Copy this to track progress:
text
Tidy progress:
- [ ] Phase 1: Scope the diff, read any incoming review, load instruction files, capture lint/type-check/test baseline
- [ ] Phase 2: Run all five angles (read-only, fixed return format), concurrently where possible
- [ ] Phase 3: Merge findings, resolve conflicts, apply fixes in precedence order
- [ ] Phase 4: Re-run checks, revert out-of-diff churn, report with command evidence复制以下内容跟踪进度:
text
Tidy进度:
- [ ] 阶段1:确定diff范围,读取现有评审结果,加载说明文件,记录lint/类型检查/测试基准线
- [ ] 阶段2:运行全部五个维度(只读,固定返回格式),尽可能并发执行
- [ ] 阶段3:整合排查结果,解决冲突,按优先级应用修复
- [ ] 阶段4:重新运行检查,撤销diff外的不必要修改,附带命令证据提交报告Phase 1: Scope, baseline, and any incoming review
阶段1:范围、基准线及现有评审结果
- Run (plus
git diffwhen changes are staged) to capture the diff. No git changes: review the files you edited earlier in this session or the files the user named.git diff --staged - Look for a review that already ran over this diff: a report earlier in the session, a host review command's findings, or PR comments the user pasted. Its confirmed findings are decided work with the fix already written, so they go straight into Phase 3 without re-derivation. Findings it marked plausible are candidates: verify each against the code before applying, and drop it with a reason if the trigger is not real. This is a head start, not a substitute; the angles still run in full. If no review ran, go to step 3.
pr-reviewer - Read /
CLAUDE.mdin the project root and in any nested package or MFE directory whose code is in the diff. Conventions there (design system, styling tokens, data-fetching patterns, naming) override this skill's defaults when they conflict; extract the rules that cover the changed paths.AGENTS.md - Run the project's lint, type-check, and test commands (read scripts;
package.json,yarn lint,yarn type-checkare typical) and record pre-existing failures. Without this baseline you cannot tell a regression you introduced from a failure that was already there.yarn test
- 运行(若有暂存修改,需同时运行
git diff)获取diff。若无Git修改:查看本次会话中之前编辑的文件或用户指定的文件。git diff --staged - 查找针对该diff的现有评审结果:本次会话中更早的报告、宿主评审命令的结果,或用户粘贴的PR评论。其中已确认的结论是已明确的待处理项,且修复方案已确定,可直接进入阶段3,无需重新推导。标记为“合理”的结论需先验证代码再应用,若触发条件不成立则说明原因后丢弃。这是一个加速项,而非替代方案:所有维度仍需完整运行。若无评审结果,进入步骤3。
pr-reviewer - 读取项目根目录及diff中涉及的嵌套包或MFE目录下的/
CLAUDE.md。当其中的约定(设计系统、样式令牌、数据获取模式、命名规则)与本技能的默认规则冲突时,以这些约定为准;提取覆盖修改路径的规则。AGENTS.md - 运行项目的lint、类型检查和测试命令(查看脚本;典型命令如
package.json、yarn lint、yarn type-check)并记录已存在的失败项。没有这个基准线,无法区分是修复引入的回归还是原本就存在的故障。yarn test
Phase 2: Run five review angles
阶段2:运行五个评审维度
Two ways to run them, same five angles and same output either way:
- With a subagent tool (Claude Code's Agent tool or equivalent): launch all five concurrently in a single message. Each prompt carries the full diff, the in-scope instruction-file rules, and a read-only constraint. Fastest path, and the default where it exists.
- Without one (most harnesses): work the five yourself in sequence in this context, one focused pass per angle, collecting findings as you go. Do not blend them into a single read; the angles catch different things precisely because each pass has one question.
Either way, nothing is edited until Phase 3, and the orchestrator makes every edit. That is what keeps two angles from rewriting the same hunk.
All five run every time, including after a review. A review reports what it can defend as a defect and drops the rest; these angles hunt what it is built to leave alone, so an angle that overlaps a report still turns up findings the report did not carry. Where an angle lands on something already in the report, Phase 3's dedupe collapses it. Skipping an angle because someone else looked nearby trades a certain loss for a speculative saving.
The return format for each angle: one finding per bullet as , issue, proposed fix; or an explicit "no findings" statement when the diff is clean on that angle.
file:line有两种运行方式,最终的五个维度和输出结果一致:
- 使用子代理工具(如Claude Code的Agent工具或同类工具):在一条消息中并发启动全部五个维度。每个提示都包含完整diff、范围内的说明文件规则以及只读约束。这是最快的方式,也是支持该工具时的默认选项。
- 不使用子代理工具(大多数环境):在此上下文环境中依次处理五个维度,每个维度进行一次专注扫描,收集排查结果。不要将它们合并为一次扫描:每个维度针对不同问题,正是因为每次扫描只关注一个问题,才能发现不同的内容。
无论哪种方式,在阶段3之前都不会修改任何文件,且所有编辑操作均由协调器执行。这样可以避免两个维度修改同一代码块的冲突。
每次运行都要执行全部五个维度,包括评审之后。评审报告只会记录能被认定为缺陷的问题,而本技能的维度会排查评审工具忽略的内容,因此即使某个维度与报告有重叠,仍会发现报告未涵盖的问题。如果某个维度发现的内容已在报告中存在,阶段3的去重步骤会合并它们。因为别人检查过就跳过某个维度,会必然导致遗漏问题,而所谓的效率提升只是假象。
每个维度的返回格式:每个问题以、问题描述、修复建议的形式作为一个项目符号;如果该维度下diff无问题,则明确说明“无排查结果”。
file:lineAngle 1: Reuse
维度1:复用性
Take each block of new code down this ladder and stop at the first rung that holds. The rung it stops on is the finding: everything below it is code that did not need to be written.
- Does it need to exist at all? Nothing calls it, nothing needs it yet, or the requirement it serves is speculative. Delete it.
- Is it already in this codebase? Search utility directories, shared modules, and the files adjacent to the changed ones. Name the existing function to use instead. Near-duplicate blocks inside the diff count too: two copies of the same logic with one value changed want one function with a parameter.
- Does the stdlib do it? Hand-rolled string manipulation, date maths, path handling, ad-hoc type guards. Name the stdlib function.
- Does a native platform feature cover it? over a picker lib, CSS over JS,
<input type="date">over a formatting lib, a DB constraint over an app-level check.Intl - Does an already-installed dependency solve it? Check before accepting anything new. Flag any dependency this diff adds for something the rungs above already cover.
package.json - Can it be one line? If so, one line.
Two guards, because a shorter diff is not automatically the better one:
- The ladder runs after you understand the code, not instead of it. Trace what the block actually does before proposing the rung above it. A smaller change in the wrong place is not a simplification, it is a second bug.
- Where two options are the same size, take the more correct one. Simpler means less code, not the flimsier algorithm. A one-liner that mishandles an empty input is not a win over three lines that do not.
对每段新代码依次检查以下层级,找到第一个适用的层级即可。最终停留的层级即为排查结果:该层级以下的代码都无需编写。
- 是否完全不需要存在? 没有任何调用、目前无需求,或其服务的需求是推测性的。直接删除。
- 代码库中是否已存在? 搜索工具目录、共享模块以及修改文件的相邻文件。指明应使用的现有函数。diff内的近似重复代码也属于此类:两段仅一个值不同的相同逻辑应合并为一个带参数的函数。
- 标准库是否已实现该功能? 手动实现的字符串处理、日期计算、路径处理、临时类型守卫等。指明对应的标准库函数。
- 原生平台特性是否已覆盖? 比如使用替代日期选择器库、用CSS替代JS逻辑、用
<input type="date">替代格式化库、用数据库约束替代应用层检查。Intl - 已安装的依赖是否能解决? 在接受新依赖前先检查。标记diff中添加的、可被上述层级覆盖的依赖。
package.json - 能否简化为一行代码? 如果可以,就简化为一行。
有两个注意事项,因为更短的diff并不一定更好:
- 只有理解代码后才能应用上述层级检查,而非替代理解过程。 在建议使用上层方案前,先追踪代码的实际功能。错误位置的简化不是优化,而是引入第二个Bug。
- 如果两个方案代码量相同,选择更正确的那个。 简化意味着更少的代码,而非更脆弱的算法。一行代码若无法处理空输入,并不比三行正确处理的代码更优。
Angle 2: Quality
维度2:代码质量
Lint already catches unused imports, unreachable code, and hooks called conditionally, and Phase 1 ran it. This angle is for what lint cannot see.
- Redundant state: state that duplicates existing state, cached values that could be derived, observers/effects that could be direct calls
- Parameter sprawl: adding new parameters to a function instead of generalizing or restructuring existing ones
- Leaky abstractions: exposing internal details that should be encapsulated, or breaking existing abstraction boundaries
- Stringly-typed code: raw strings where constants, string unions, or branded types already exist in the codebase
- Unnecessary JSX nesting: wrapper Boxes/elements that add no layout value; check whether inner component props (flexShrink, alignItems, etc.) already provide the needed behavior
- Unnecessary comments: comments explaining WHAT the code does (well-named identifiers already do that), narrating the change, or referencing the task/caller get deleted; keep only non-obvious WHY (hidden constraints, subtle invariants, workarounds)
- Debug residue: commented-out JSX or logic, stray ,
console.log, anddebugger. Move TODO comments to the summary with a note on what they're blocking rather than deleting them silentlyalert - types: replace with the actual type, or
anywhere the type is genuinely unknown. Never widen just to silence an errorunknown - React hook dependency arrays: ,
useEffect,useCallbackdeps must be exhaustive. Flag any newly addeduseMemo// eslint-disable-next-line react-hooks/exhaustive-deps - Over-memoisation: remove /
useCallbackthat adds no value: wrapping auseMemoupdater (the updater form is already stable), memoising with Apollo query objects as deps (busts on every refetch), or computing a value used only in the same component. KeepsetStateonly when the reference is passed to a child that would otherwise re-render, anduseCallbackonly when the computation is demonstrably expensiveuseMemo - List keys: stable, unique keys on rendered lists. Never unless the list is static and non-reorderable
index - for derived state: compute values directly from existing state/props instead
useEffect - Pattern compliance with /
CLAUDE.md: imports from deprecated component packages, old styling tokens, long relative paths where path aliases exist, queries/mutations not following the established custom-hook pattern, naming inconsistent with surrounding filesAGENTS.md - Magic numbers/strings: extract to a named constant if used more than once or the value has no obvious meaning
- Unrequested compatibility: old/new dual paths, legacy aliases, or deprecated re-exports added in this diff when nothing depends on the old path. Delete it unless a real consumer is named
- Speculative flexibility: interfaces with one implementation, factories for one product, config for a value that never changes, layers with one caller, or parameters nothing passes, added in this diff. Inline or delete until a second consumer exists. Where the speculative layer exists to absorb a special case, that is an Angle 4 finding, and the deeper fix wins
Lint工具已经能捕获未使用的导入、不可达代码和条件调用的Hook,且阶段1已运行过Lint。本维度处理Lint无法发现的问题。
- 冗余状态:重复现有状态的状态、可推导的缓存值、可直接调用的观察者/副作用
- 参数膨胀:给函数添加新参数而非泛化或重构现有参数
- 抽象泄漏:暴露应封装的内部细节,或打破现有的抽象边界
- 字符串类型代码:在代码库已有常量、字符串联合类型或品牌类型的情况下仍使用原始字符串
- 不必要的JSX嵌套:无布局价值的包装Box/元素;检查内部组件的props(如flexShrink、alignItems等)是否已提供所需行为
- 不必要的注释:解释代码“做什么”的注释(命名良好的标识符已能说明)、描述修改过程的注释、引用任务/调用者的注释应删除;仅保留非显而易见的“为什么”注释(隐藏约束、微妙的不变量、临时解决方案)
- 调试残留:注释掉的JSX或逻辑、零散的、
console.log和debugger。将TODO注释移至摘要并说明其阻塞的内容,而非静默删除alert - 类型:替换为实际类型,若类型确实未知则使用
any。绝不能为了消除错误而放宽类型unknown - React Hook依赖数组:、
useEffect、useCallback的依赖必须完整。标记新增的useMemo注释// eslint-disable-next-line react-hooks/exhaustive-deps - 过度记忆化:移除无价值的/
useCallback:包裹useMemo更新器(更新器形式本身已稳定)、以Apollo查询对象为依赖的记忆化(每次重新获取都会失效)、或计算仅在同一组件中使用的值。仅当引用传递给会因此重渲染的子组件时保留setState,仅当计算成本明显高昂时保留useCallbackuseMemo - 列表键:渲染列表使用稳定、唯一的键。绝不要使用,除非列表是静态且不可重新排序的
index - 用处理派生状态:直接从现有状态/Props计算值
useEffect - 遵守/
CLAUDE.md的模式:从已废弃的组件包导入、使用旧样式令牌、在存在路径别名的情况下使用长相对路径、未遵循既定自定义Hook模式的查询/变更、命名与周围文件不一致AGENTS.md - 魔术数字/字符串:如果使用多次或含义不明确,提取为命名常量
- 不必要的兼容性:diff中添加的新旧双路径、旧别名、已废弃的重导出,但没有任何内容依赖旧路径。除非有明确的消费者,否则删除这些内容
- 推测性灵活性:diff中添加的仅有一个实现的接口、仅生产一种产品的工厂、值从不变化的配置、仅有一个调用者的层级、无参数传入的参数。在出现第二个消费者之前,内联或删除这些内容。如果推测性层级是为了处理特殊情况,属于维度4的排查结果,此时更深层次的修复更优
Angle 3: Efficiency
维度3:执行效率
- Unnecessary work: redundant computations, repeated file reads, duplicate network/API calls, N+1 patterns
- Missed concurrency: independent operations run sequentially when they could run in parallel
- Hot-path bloat: new blocking work added to startup or per-request/per-render hot paths
- Recurring no-op updates: state/store updates inside polling loops, intervals, or event handlers that fire unconditionally need a change-detection guard so downstream consumers aren't notified when nothing changed. Also: if a wrapper function takes an updater/reducer callback, verify it honors same-reference returns (or whatever the "no change" signal is); otherwise callers' early-return no-ops are silently defeated
- Unnecessary existence checks: pre-checking file/resource existence before operating (TOCTOU anti-pattern); operate directly and handle the error
- Memory: unbounded data structures, missing cleanup, event listener leaks. Also long-lived objects built from a closure: the captured scope stays alive for the object's lifetime, so a handler that closes over a large response holds it forever. Pass the fields it needs instead
- Overly broad operations: reading entire files when only a portion is needed, loading all items when filtering for one
- 不必要的操作:冗余计算、重复文件读取、重复网络/API调用、N+1查询模式
- 未利用的并发:可并行执行的独立操作却按顺序执行
- 热路径冗余:在启动或每个请求/渲染的热路径中添加新的阻塞操作
- 重复无意义更新:轮询循环、定时器或事件处理器中无条件触发的状态/存储更新需要添加变更检测守卫,避免下游消费者在无变更时收到通知。另外:如果包装函数接收更新器/ reducer回调,需验证是否支持相同引用返回(或其他“无变更”信号);否则调用者的提前返回无意义更新会被静默忽略
- 不必要的存在检查:操作前预先检查文件/资源是否存在(TOCTOU反模式);直接执行操作并处理错误
- 内存问题:无界数据结构、缺失清理逻辑、事件监听器泄漏。另外:闭包构建的长生命周期对象:捕获的作用域会随对象生命周期保持活跃,因此引用大型响应的处理程序会永久占用该响应。应仅传递所需字段
- 过度宽泛的操作:仅需部分内容却读取整个文件、仅需筛选一个项目却加载所有项
Angle 4: Altitude
维度4:层级合理性
One question: is each change made at the right depth, or bolted on above it? The signal is a special case layered onto shared infrastructure. When a fix reads as "except for this case", the mechanism underneath is usually the thing that should have changed.
- Special case on a shared path: a branch keyed to one caller, route, tenant, feature flag, or file type added inside code that serves all of them. Name the general rule the branch is an instance of, and whether the shared mechanism can express it
- Fix at the call site instead of the source: the same guard, coercion, or normalisation added at one caller when the function it calls could return the right shape for every caller. Grep every caller of the function the diff touches. One guard inside the shared function is a smaller diff than one per caller, and fixing only the path the ticket named leaves the sibling callers broken
- Symptom fix: a value corrected after the fact (clamping, re-sorting, patching a field back in) rather than produced correctly. Trace back to where it was built wrong
- Fix that only holds for the reported input: a condition tuned to the example in the ticket. Ask what the neighbouring input does
Altitude findings are the ones most worth raising and least worth forcing. Where lifting the fix means redesigning the shared mechanism, that is a summary note for the user, not an edit this pass makes. Apply it only when the deeper fix is smaller than the special case it replaces.
只有一个问题:每处修改是否在正确的层级,还是被附加到了上层?信号是在共享基础设施上添加的特殊处理。如果修复看起来是“除了这种情况”,通常底层机制才是需要修改的对象。
- 共享路径上的特殊处理:在服务所有调用者的代码中添加针对特定调用者、路由、租户、功能标志或文件类型的分支。指明该分支对应的通用规则,以及共享机制是否能表达该规则
- 在调用方修复而非源头:在某个调用方添加相同的守卫、强制转换或标准化,而被调用的函数本可为所有调用方返回正确格式。搜索diff中涉及函数的所有调用方。在共享函数内添加一个守卫比每个调用方各加一个的diff更小,仅修复工单指定路径会导致其他调用方仍存在问题
- 症状修复:事后修正值(如截断、重新排序、补回字段)而非从源头正确生成。追踪值被错误生成的位置
- 仅对报告输入有效的修复:针对工单中的示例调整条件。需考虑相邻输入的情况
层级合理性的排查结果最值得提出,但最不应强制修复。如果提升修复层级需要重新设计共享机制,应在摘要中告知用户,而非在本次扫描中修改。仅当深层修复比特殊处理的代码量更小时才应用。
Angle 5: Test discipline
维度5:测试规范
The bar for every finding: a test earns its place only if it can fail for a reason someone would act on. Each proposed test must name, in one sentence, the failure it prevents; a proposal without that sentence is not a finding. Tests earn their place by proving behaviour that regresses independently of the edit: filtering, derivation, validation, permissions, region/runtime gating, data transformation, generation contracts, a class-wide invariant. A changed config row, flag default, route entry, label, or copy string earns no test; the owning diff and the behaviour that surfaced the issue verify it. Never flag a new component or hook merely for lacking a co-located test file.
- Bug fix without a repro test: the diff fixes a bug but no test fails on the pre-fix code. The one missing-test finding that is always flagged. The repro belongs at the seam that failed (route, API, browser flow, integration point); a unit test on a helper invented during the fix is not regression coverage unless that helper owns the failing behaviour.
- Stale assertions: existing tests covering changed code that no longer reflect the updated behaviour
- Missing tests that clear the bar: new branching logic, a contract others depend on, or a refactor-surviving invariant in the diff with no test. State the failure each proposed test prevents
- Useless tests added in this diff, flagged for deletion: render-only tests (presence checks with no interaction or branch), mock-echo assertions (asserting a mock was called or returned its mocked value), change-detector snapshots, framework re-tests, happy-path triplication of the same branch, diff-mirror tests (the assertion repeats a literal copied from the diff: a config row, flag default, route entry, label, or copy string; a second ledger, not behaviour coverage), export-for-testability tests (a helper extracted or exported solely so a test can name it), fake-integration tests (an in-memory emulator of behaviour that lives in the real system: schema, validators, indexes, permissions; it cannot catch the bug class it claims to cover). Name the pattern each matches. A config-adjacent test stays only if it proves a rule across a class of cases; one whose name contains a single item id and whose assertion repeats the value just changed goes.
每个排查结果的标准:测试仅在能针对有人会处理的原因失败时才有存在价值。每个建议的测试必须用一句话说明其预防的故障;无这句话的建议不算排查结果。测试需能证明独立于修改的回归行为:过滤、推导、验证、权限控制、区域/运行时限制、数据转换、生成契约、类级不变量。修改的配置行、标志默认值、路由条目、标签或文案无需测试;对应的diff和发现问题的行为已能验证。绝不要仅因新组件或Hook缺少配套测试文件而标记问题。
- 无复现测试的Bug修复:diff修复了Bug,但修复前的代码没有测试失败。这是唯一必须标记的缺失测试情况。复现测试应放在故障发生的边界(路由、API、浏览器流程、集成点);修复过程中创建的辅助函数的单元测试不算回归覆盖,除非该辅助函数是故障的根源。
- 过时断言:覆盖修改代码的现有测试不再反映更新后的行为
- 符合标准的缺失测试:diff中的新分支逻辑、他人依赖的契约、重构后仍需保留的不变量没有测试。说明每个建议测试预防的故障
- diff中添加的无用测试,标记为删除:仅渲染测试(无交互或分支的存在检查)、模拟回声断言(断言模拟被调用或返回模拟值)、变更检测器快照、框架重测、同一分支的快乐路径重复测试、diff镜像测试(断言重复diff中的字面量:配置行、标志默认值、路由条目、标签或文案;属于重复记录,而非行为覆盖)、为测试而导出的测试(仅为了测试而提取或导出的辅助函数)、伪集成测试(模拟真实系统中的行为: schema、验证器、索引、权限;无法捕获其声称覆盖的Bug类型)。指明每个测试对应的模式。配置相关的测试仅当能证明一类案例的规则时保留;名称包含单个项目ID且断言重复刚修改的值的测试应删除。
Phase 3: Merge findings and apply fixes
阶段3:整合排查结果并应用修复
Collect the incoming review's findings and all five angles' findings, then merge before editing anything:
- Dedupe: collapse findings that point at the same lines or share one root cause into a single fix. Where an angle rediscovers something the incoming review already confirmed, keep the review's version: it carries the severity and the reasoning the user has already read.
- Drop false positives: if a finding is wrong or not worth the churn, skip it and record the reason for the summary. Do not argue with the finding or apply it halfway. A confirmed finding from the incoming review is not dropped on your own judgement; if you believe it is wrong, apply nothing there and say so, because the user read that report and expects those lines to change.
- Order by precedence: confirmed review findings first, since a correctness fix changes what the right shape even is; then altitude, since lifting a fix can delete the code the other angles were about to clean; then reuse swaps and deletions (Angle 1 plus dead-code findings), then quality rewrites (Angle 2), then efficiency (Angle 3), then test-assertion updates last so they target the final shape of the code. Simplifying a block another finding deletes is wasted work.
- Resolve conflicts: when two findings propose incompatible rewrites of the same lines, prefer the one that deletes more code, and where they delete about the same amount, the more boring one. If neither clearly wins, apply neither and present both options in the summary instead of guessing. Deleting more is the tie-break, not the goal: a rewrite that sheds lines by dropping a case the old code handled is a regression wearing a smaller diff.
Apply each fix directly, re-reading the target region first; earlier fixes shift line numbers.
Scope rules:
- Only edit files inside the diff. Reading an adjacent file to understand a pattern is fine; rewriting it is not.
- No new abstractions, no architecture refactors, no fixes to pre-existing issues outside the diff. An altitude finding that needs the shared mechanism redesigned goes in the summary, not the working tree.
- Tests are never silently written: proposed missing tests are surfaced in the summary with the one-sentence failure each prevents, for the user to decide on. Useless tests added in this diff (Angle 5, category 4) get deleted like any other quality fix. Stale assertions in existing tests covering changed code do get fixed.
收集现有评审结果和五个维度的排查结果,在编辑前先整合:
- 去重:将指向同一行或同一根源的排查结果合并为一个修复。如果某个维度重新发现了现有评审已确认的内容,保留评审版本:它包含用户已阅读的严重级别和推理过程。
- 删除误报:如果排查结果错误或不值得修改,跳过并在摘要中记录原因。不要质疑排查结果或部分应用。现有评审中已确认的结果不能自行判断删除;如果认为错误,不要应用并说明原因,因为用户已阅读报告并期待这些代码被修改。
- 按优先级排序:先应用已确认的评审结果,因为正确性修复会改变代码的正确形态;然后是层级合理性修复,因为提升修复层级可能会删除其他维度要清理的代码;接着是复用性替换和删除(维度1加死代码排查结果);然后是代码质量重写(维度2);再是效率优化(维度3);最后是测试断言更新,使其针对代码的最终形态。简化会被其他结果删除的代码是无用功。
- 解决冲突:当两个排查结果对同一行提出不相容的重写时,优先选择删除更多代码的方案;如果删除量相近,选择更保守的方案。如果两者都没有明显优势,都不应用,而是在摘要中呈现两个选项,不要猜测。删除更多代码是平局决胜规则,而非目标:通过丢弃旧代码处理的案例来减少代码量的重写是披着更短diff外衣的回归。
直接应用每个修复,应用前重新阅读目标区域;早期修复会改变行号。
范围规则:
- 仅修改diff范围内的文件。可以读取相邻文件理解模式,但不能修改它们。
- 不添加新抽象,不进行架构重构,不修复diff范围外的原有问题。需要重新设计共享机制的层级合理性排查结果应放在摘要中,而非修改工作区。
- 绝不静默编写测试:建议添加的缺失测试应在摘要中列出,并说明每个测试预防的故障,由用户决定是否添加。diff中添加的无用测试(维度5第4类)像其他代码质量修复一样被删除。覆盖修改代码的现有测试中的过时断言需要修复。
Phase 4: Verify and report
阶段4:验证并报告
- Re-run the exact lint, type-check, and test commands from Phase 1. Any failure not in the baseline was introduced by your fixes; resolve it before finishing. Leave pre-existing failures alone and list them in the summary.
- If a lint/format autofix reformatted files outside the diff, each one. Run
git restore <path>and confirm only in-diff files changed before finishing.git status - Report in this shape. If the code was already clean, say so explicitly under Applied. "Looks good" without command output is not a valid exit.
markdown
undefined- 重新运行阶段1中完全相同的lint、类型检查和测试命令。任何不在基准线中的失败都是修复引入的回归;完成前需解决这些问题。保留原有失败项并在摘要中列出。
- 如果lint/格式化自动修复修改了diff范围外的文件,使用恢复每个文件。运行
git restore <path>并确认仅diff范围内的文件被修改后再完成。git status - 按以下格式报告。如果代码已经很整洁,需在“已应用”部分明确说明。仅说“看起来不错”而无命令输出是无效的结束方式。
markdown
undefinedTidy
Tidy
Applied
- <what changed> (<source: review, or angle name>)
path/to/file.ts:line
Skipped
- <finding> (<why: false positive, not worth the churn, two incompatible fixes>)
path/to/file.ts:line
For you to decide
- Test gaps, each with the one-sentence failure it prevents
- Altitude findings whose real fix is a separate change
- Simplifications applied that cut a real corner, each naming the ceiling it now has and what to do when the code outgrows it
- TODOs found in the diff, with what each is blocking
Checks
- : <result> (baseline: <result>)
<command>
undefined已应用
- <修改内容> (<来源:评审或维度名称>)
path/to/file.ts:line
已跳过
- <排查结果> (<原因:误报、不值得修改、两个不相容修复>)
path/to/file.ts:line
需您决定
- 测试缺口,每个缺口说明其预防的故障(一句话)
- 需单独修改的层级合理性排查结果
- 简化时牺牲了部分功能的修改,说明当前限制及代码超出限制时的处理方式
- diff中发现的TODO,说明每个TODO阻塞的内容
检查结果
- : <结果> (基准线:<结果>)
<命令>
undefinedGotchas
注意事项
- Launching subagents one at a time when the harness supports concurrency: five serial runs roughly quintuple wall-clock time for no extra signal. One message, all five.
- Collapsing the five angles into a single read on a harness with no subagent tool: one pass looking for everything finds the first thing. Five narrow passes is the point, and it is still cheaper than the diff was to write.
- A formatter autofix (or equivalent) reformatting unrelated files: the diff fills with churn the reviewer must wade through.
yarn lint --fixevery out-of-diff path before finishing.git restore - Widening a type to to silence an error a fix introduced: that hides the breakage instead of resolving it. Find the real type.
any - Fixing pre-existing failures because they are "right there": scope creep turns a cleanup pass into an unreviewable mixed change. Surface them in the summary instead.
- Angle 5 padding the summary with test proposals: coverage looks like rigor, so review passes over-propose tests. Every proposal without a named failure it prevents gets dropped in the Phase 3 false-positive pass.
- Rewriting a shared mechanism because Angle 4 found a special case: the altitude finding was right and the fix is a separate PR. This pass reports it and moves on.
- Narrowing the sweep because a review already ran. The two look for different things, so a skipped angle is a real loss and the saving is imaginary. Run all five; dedupe at Phase 3.
- Repeating a report's finding back in different words as if it were new. That is a dedupe failure, not a coverage win. Where an angle rediscovers something the report confirmed, it is one finding.
- Quietly not applying a confirmed review finding because you disagree with it. The user read that report and is expecting those lines to change. Apply it, or say plainly that you did not and why.
- 在支持并发的环境中逐个启动子代理:五次串行运行会使耗时大致增加五倍,且无额外收益。应在一条消息中启动全部五个维度。
- 在无子代理工具的环境中将五个维度合并为一次扫描:一次扫描查找所有问题只会发现第一个问题。五次针对性扫描才是关键,且总耗时仍比编写diff的时间少。
- 格式化自动修复(如或同类命令)修改了无关文件:diff中会充满评审者需处理的冗余内容。完成前需使用
yarn lint --fix恢复所有diff外的路径。git restore - 为消除修复引入的错误而将类型放宽为:这会隐藏问题而非解决问题。应找到正确的类型。
any - 因为“就在眼前”而修复原有失败项:范围蔓延会使清理扫描变成无法评审的混合修改。应在摘要中提出这些问题。
- 维度5在摘要中添加过多测试建议:覆盖率看起来严谨,因此评审会过度建议测试。每个无明确预防故障的建议都会在阶段3的误报处理中被删除。
- 因为维度4发现特殊处理而重写共享机制:层级合理性排查结果是正确的,但修复应放在单独的PR中。本次扫描仅报告该问题并继续。
- 因为已有评审而缩小扫描范围:两者的排查重点不同,跳过维度必然导致遗漏问题,所谓的效率提升只是假象。运行全部五个维度,在阶段3去重。
- 将报告中的排查结果用不同语言重复呈现为新发现:这是去重失败,而非覆盖提升。如果某个维度重新发现了报告已确认的内容,应合并为一个排查结果。
- 因不同意而静默不应用已确认的评审结果:用户已阅读报告并期待这些代码被修改。要么应用,要么明确说明不应用的原因。
Related skills
相关技能
- : the other hunt. It looks for correctness, security, and structural defects it can defend, and reports without editing; this skill looks for complexity and fixes it. Running it first is the common path, and its confirmed findings get applied here alongside this skill's own. Route there when the user wants to see findings before anything changes.
pr-reviewer - : creates the PR after tidy finishes and the build is green.
pr-creator - (Harden mode): repo-wide guardrails (dead code, duplication, file size) wired into hooks and CI. What keeps each tidy pass small instead of a sweep.
codebase-architecture
- :另一种排查工具。它查找可被认定的正确性、安全性和结构缺陷,并仅报告不修改;本技能查找复杂度问题并修复。先运行它是常见流程,其已确认的结果会与本技能的结果一同应用。当用户希望先查看排查结果再修改时使用该工具。
pr-reviewer - :在tidy完成且构建正常后创建PR。
pr-creator - (强化模式):仓库级别的防护规则(死代码、重复代码、文件大小)集成到Hook和CI中。用于确保每次tidy扫描的范围较小,而非全面扫描。
codebase-architecture