
Cs Refactor
- 1.3k installs
- 1.1k repo stars
- Updated August 3, 2026
- liuzhengdongfortest/codestable
cs-refactor is an agent skill for 代码优化的子流程入口,处理"行为不变、结构变"的工作(结构 / 性能 / 可读性),按 scan → design → apply 分步执行每步人工放行。触发:用户说"优化一下 / 重构 / 重写 / 拆一下 / 性能不行 / 代码太长"且不夹带行为改动。不处理新需求 / bug / 跨模块架构重划。.
About
The cs-refactor skill is designed for 代码优化的子流程入口,处理"行为不变、结构变"的工作(结构 / 性能 / 可读性),按 scan → design → apply 分步执行每步人工放行。触发:用户说"优化一下 / 重构 / 重写 / 拆一下 / 性能不行 / 代码太长"且不夹带行为改动。不处理新需求 / bug / 跨模块架构重划。. 顶部总览(一段):扫描范围 / 发现条数 / 按分类分布 / 按风险分布 / 建议先做哪几条 / 慎做哪几条 2. 清单条目(一条一块):字段顺序和硬约束见 reference/scan-checklist-format.md 整份交给用户,用户勾选 ✓ / ✗(✗ 写理由)后进阶段 2。不要替用户勾选。 --- 阶段 2:design 输入 用户勾选过的 {slug}-scan.md 方法库(每条勾选项必须映射到方法号 M-Ln-NN) 做的事 1. Invoke when the user asks about cs refactor or related SKILL.md workflows.
- 用户点名了具体文件 / 组件 → 就扫那些.
- "这个页面" → 入口组件 + 直接 import 的内部模块,不追公共依赖.
- "这个模块" → 模块目录下的文件,不追出模块边界.
- 范围 > 15 文件或 > 3000 行 → 触发第 6 条前置检查请用户先缩范围.
- L1 行为等价迁移:函数被很多处调用但接口/实现要改 → Parallel Change;整块老逻辑要被新实现替换 → Strangler Fig.
Cs Refactor by the numbers
- 1,277 all-time installs (skills.sh)
- +14 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #317 of 1,880 Design & UI/UX skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
cs-refactor capabilities & compatibility
- Capabilities
- 用户点名了具体文件 / 组件 → 就扫那些 · "这个页面" → 入口组件 + 直接 import 的内部模块,不追公共依赖 · "这个模块" → 模块目录下的文件,不追出模块边界 · 范围 > 15 文件或 > 3000 行 → 触发第 6 条前置检查请用户先缩范围
- Use cases
- frontend
What cs-refactor says it does
代码优化的子流程入口,处理"行为不变、结构变"的工作(结构 / 性能 / 可读性),按 scan → design → apply 分步执行每步人工放行。触发:用户说"优化一下 / 重构 / 重写 / 拆一下 / 性能不行 / 代码太长"且不夹带行为改动。不处理新需求 / bug / 跨模块架构重划。
代码优化的子流程入口,处理"行为不变、结构变"的工作(结构 / 性能 / 可读性),按 scan → design → apply 分步执行每步人工放行。触发:用户说"优化一下 / 重构 / 重写 / 拆一下 / 性能不行 / 代码太长"且不夹带行为改动。不处理新需求 / bug / 跨模块架构重划。
npx skills add https://github.com/liuzhengdongfortest/codestable --skill cs-refactorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.3k |
|---|---|
| repo stars | ★ 1.1k |
| Security audit | 3 / 3 scanners passed |
| Last updated | August 3, 2026 |
| Repository | liuzhengdongfortest/codestable ↗ |
How do I 代码优化的子流程入口,处理"行为不变、结构变"的工作(结构 / 性能 / 可读性),按 scan → design → apply 分步执行每步人工放行。触发:用户说"优化一下 / 重构 / 重写 / 拆一下 / 性能不行 / 代码太长"且不夹带行为改动。不处理新需求 / bug / 跨模块架构重划。?
代码优化的子流程入口,处理"行为不变、结构变"的工作(结构 / 性能 / 可读性),按 scan → design → apply 分步执行每步人工放行。触发:用户说"优化一下 / 重构 / 重写 / 拆一下 / 性能不行 / 代码太长"且不夹带行为改动。不处理新需求 / bug / 跨模块架构重划。.
Who is it for?
Developers using cs refactor workflows documented in SKILL.md.
Skip if: Skip when the task falls outside cs-refactor scope or needs a different stack.
When should I use this skill?
User asks about cs refactor or related SKILL.md workflows.
What you get
Completed cs-refactor workflow with documented commands, files, and expected deliverables.
- method-cited refactor plan
- per-step verification checklist
By the numbers
- Organizes refactor methods across 4 layers from L1 through L4
- Uses numbered method IDs such as M-L1-01 Parallel Change
Files
cs-refactor
启动必读
开始任何判断或动作前,先读取 .codestable/attention.md;缺失则视为骨架不完整,提示先补齐或运行 cs-onboard,不要回退到外部 AI 入口文件。
AI 自己重构有两个稳定失败模式:一是不知道模块真实需求和约束,改出来的东西功能不等价;二是一次吞掉的范围超过上下文承载,改到后面忘了前面的约束。这流程在"想优化"和"动手改"之间塞了扫描清单 + 方法库,让 AI 只接自己能稳定做对的活。
scan(扫优化点清单)→ design(和用户定做哪几条 + 顺序)→ apply(逐条执行,每步人工放行)核心纪律:行为等价是底线。一旦会改外部可观察行为 → 不走 refactor,走 feature(需求变)或 issue(bug 修)。
---
Fastforward 模式(小重构)
单函数 / 单组件 / 1-3 处优化 / 有测试可自证 / 不需要目视——走完整三阶段太重。触发 cs-refactor-ff:直接识别、一次对齐、原地改、跑测试自证,不产 scan / design / checklist。
触发:"小重构"、"快速重构"、"简单优化下 XX 函数"、"直接改"、"别那么多步骤"。
别走 ff:改动跨 > 1 文件 / 预计动点 > 3 处 / 需要目视验证 / 改公开接口(要 Parallel Change)/ 没有测试覆盖 / 跨模块。遇到劝用户走标准流程。ff 开干后发现变复杂切回完整流程从 scan 开始。
---
文件放哪儿
.codestable/refactors/{YYYY-MM-DD}-{slug}/
├── {slug}-scan.md ← 阶段 1 优化点清单
├── {slug}-refactor-design.md ← 阶段 2 执行方案
├── {slug}-checklist.yaml ← 阶段 2 生成,阶段 3 推进
└── {slug}-apply-notes.md ← 阶段 3 执行记录目录命名同 feature / issue。slug 短到一眼看出改的是什么(user-form-split、export-perf)。
为什么单独开目录不混进 features:refactor 产物是"代码当前状态扫描 + 执行记录"时效性强;feature 产物是"为什么这样设计"时效性弱。归档逻辑不一样。
---
三个阶段
| 阶段 | 产出 | 谁主导 |
|---|---|---|
| 1 scan | scan.md | AI 扫 + 前置检查,用户勾选 |
| 2 design | refactor-design.md + checklist.yaml | AI 起草,用户整体 review |
| 3 apply | 代码改动 + apply-notes.md | AI 执行,每步人工放行 |
阶段间有 checkpoint:scan 不勾选不进 design;design 不放行不动代码;apply 里 HUMAN 验证项不点头不推进下一步。
---
阶段 1:scan
先跑前置检查(7 条),命中就停
动笔扫之前先跑一遍。命中任何一条 → 中止 scan,给路由建议,不要硬凑。7 条检查和输出格式见 reference/refusal-routing.md。
零条合法输出——扫完真的没发现值得做的就老实说不要凑。
扫描范围锁定
进 scan 前确认:这次扫哪些文件。默认:
- 用户点名了具体文件 / 组件 → 就扫那些
- "这个页面" → 入口组件 + 直接 import 的内部模块,不追公共依赖
- "这个模块" → 模块目录下的文件,不追出模块边界
- 范围 > 15 文件或 > 3000 行 → 触发第 6 条前置检查请用户先缩范围
范围里要包含测试文件(用来判断第 2 条前置检查的测试覆盖)。
扫的时候看什么
按方法库四层当模板找:
- L1 行为等价迁移:函数被很多处调用但接口/实现要改 → Parallel Change;整块老逻辑要被新实现替换 → Strangler Fig
- L2 代码级重构:超长函数(> 50 行 / 圈复杂度 > 10)、重复条件片段、神秘临时变量、多层嵌套 if-else
- L3 结构拆分:组件 > 300 行 / 文件承担多件事 / 容器与展示混在一起 / 相同逻辑多组件各写一份(前端);Controller 直接调 DB / Service 缺失 / Repository 被绕开(后端)
- L4 性能:重复计算(可 memo)/ N+1 查询 / 列表无虚拟化或分页 / 事件监听无清理 / 大对象深响应(Vue)
完整方法库在 reference/methods.md,扫描时全量加载作匹配表。
产出格式
{slug}-scan.md 两部分:
1. 顶部总览(一段):扫描范围 / 发现条数 / 按分类分布 / 按风险分布 / 建议先做哪几条 / 慎做哪几条 2. 清单条目(一条一块):字段顺序和硬约束见 reference/scan-checklist-format.md
整份交给用户,用户勾选 ✓ / ✗(✗ 写理由)后进阶段 2。不要替用户勾选。
---
阶段 2:design
输入
- 用户勾选过的
{slug}-scan.md - 方法库(每条勾选项必须映射到方法号 M-Ln-NN)
做的事
1. 排顺序——勾选条目有依赖的排前(L1 的 Parallel Change 通常先跑,L2 的提取跟在后面)。独立的按"低风险 + AI 可自证"优先,HUMAN 验证项排后批量处理 2. 每条补执行细节:方法号 / 步骤 / 前置条件 / 退出信号 / 验证责任方(AI / HUMAN)/ 回滚策略 3. 识别前置依赖——测试覆盖不够的条目前置"补刻画测试";改公开接口的前置"搜调用方" 4. 整体 review:整稿交用户,放行后 status: approved 5. 抽 checklist:steps 对应执行顺序,checks 对应每步退出信号
design 文件结构
---
doc_type: refactor-design
refactor: {YYYY-MM-DD}-{slug}
status: draft | approved
scope: {扫描范围一句话}
summary: {本次要做的几条是什么,一句话}
---
# {slug} refactor design
## 1. 本次范围
- 从 scan 勾选了哪几条(编号)
- 明确不做的(被 ✗ 的)和理由
- 预估总工作量 / 总风险档位
## 2. 前置依赖
- 测试覆盖补齐(如需)
- 调用方搜索(如需)
- 其他一次性准备
## 3. 执行顺序
按步骤列,每步一块:
- 步骤 N:{一句话动作}
- 引用方法:M-Ln-NN {方法名}
- 具体操作:{照方法库步骤落到本项目具体文件 / 函数}
- 退出信号:{AI 跑什么测试 / HUMAN 看什么页面}
- 验证责任:AI 自证 | HUMAN
- 回滚:{出问题怎么还原,通常 git revert 某步}
## 4. 风险与看点
- 高风险步骤汇总
- 容易出错的点(跨步骤数据流变化等)---
阶段 3:apply
推进规则
1. 一步一做不批量——严格按 checklist 顺序,当前步不完成不开下一步 2. 每步完成走验证:
- AI 自证:跑指定测试 / 类型检查 / lint / grep 无残留旧引用。通过了记 apply-notes 继续
- HUMAN 验证:停下来汇报"第 N 步已完成,请在 {具体页面 / 操作} 目视确认,确认后我继续"。用户不明确说"继续"就不推进
3. 偏离当场记——执行中发现方案没考虑的情况(如有个调用方在动态 import 里),停下来汇报不发挥。和用户对齐后追加到 apply-notes,必要时回阶段 2 改 design 4. 行为等价自检——每步结束额外问"这一步有没有可能改了外部可观察行为?" 有怀疑就退回当步
apply-notes 格式
---
doc_type: refactor-apply-notes
refactor: {YYYY-MM-DD}-{slug}
---
# {slug} apply notes
## 步骤 1: {动作}
- 完成时间: {date}
- 改动文件: {file list}
- 验证结果: {测试输出 / HUMAN 确认语录}
- 偏离: {无 / 具体描述}
## 步骤 2: ...全部完成后
- 跑全量测试 + 类型检查 + lint
- 最后一次请用户整体目视确认(前端:打开主要页面点一圈)
- 确认通过后收尾 commit,message 引用 refactor 目录
---
退出条件
- [ ] scan 前置检查跑过,命中的已路由,没命中的才进 scan
- [ ]
{slug}-scan.md用户已勾选(✓/✗) - [ ] design 每条勾选项映射到方法号
- [ ] design 用户整体 review 通过
status: approved - [ ] checklist.yaml 已生成且通过
validate-yaml.py - [ ] apply 每步都有验证记录(AI 自证贴日志,HUMAN 贴用户确认语录)
- [ ] 全量测试 / 类型检查 / lint 通过
- [ ] 用户最后一次目视确认通过
---
容易踩的坑
- AI 硬凑清单——前置检查明显命中却找理由绕过,扫出一堆"代码可以更优雅"无量化问题的条目
- 夹带行为改动——在重构中间"顺便修了 bug / 优化提示文案"——拆成独立 issue 或 feature
- 跨步骤合并动作——一次提交做 2-3 步,失去"单步回滚"能力
- 把口味项列进清单——命名偏好 / 引号 / 箭头函数 vs function——走 decisions
- 扫大模块直接动手——> 15 文件 / > 3000 行不拆就进 scan,产出没法决策的长清单
- HUMAN 验证项自己跳过——前端效果 AI 看不到,不能用"类型检查过了"替代人工目视
- 覆盖率不够硬上——没测试的模块直接改,"行为等价"只是口头承诺
---
与相邻工作流的边界
- feature:加新能力 / 改需求。refactor 里冒出"顺便实现 X"停下拆出去
- issue:修 bug / 行为错了。refactor 里发现的 bug 记成新 issue 不偷偷修
- decisions:全项目长期约束("以后都用 composable"、"禁用 mixin")。refactor 可引用已有 decision 但不产出 decision
- architecture:跨模块边界重划 / 分层调整。单次 refactor 不跨模块;跨模块要拆成"更新架构 + 记决策 + N 个模块级 refactor"
- tricks / learning:refactor 中发现的手法 → tricks;踩的坑 → learning
---
相关文档
cs-refactor-ff/SKILL.md— 小重构超轻量通道reference/scan-checklist-format.md— scan 清单条目字段 / 顺序 / 硬约束reference/refusal-routing.md— scan 前置检查 7 条 + 路由表reference/methods.md— 方法库(L1-L4 四层分类).codestable/reference/shared-conventions.md— 跨工作流共享口径
重构方法库
scan 阶段匹配候选优化点的方法表,design 阶段每个执行步骤要引用一个方法号。
方法号 `M-L{层}-{序号}`。四层:
- L1 行为等价迁移——大改动有风险时把"改"拆成多步安全动作
- L2 代码级重构——Fowler 经典单次动作,单函数 / 局部改写
- L3 结构拆分——组件 / 模块 / 层级级别
- L4 性能与异步——行为等价但运行特征变(算复杂度 / 渲染次数 / IO 次数)
统一字段:适用 / 不适用 / 步骤 / 风险点 / 验证 / 前后端 / 配哪种 scan 项。前后端适用性大部分通用,特化的会在字段里标注。
---
L1 行为等价迁移
M-L1-01 Parallel Change 并行变更
- 适用:要替换一个被多处调用的函数/接口/数据结构,直接改会波及太多地方
- 不适用:只在一处用的内部函数(直接改就行)
- 步骤:
1. 新建 newThing,行为和 oldThing 完全一致(必要时做适配层) 2. 调用方一个一个切到 newThing,每切一个跑一次测试 3. 确认 oldThing 全局无引用(grep 可证)后删除
- 风险点:步骤 2 期间如果有新代码被加进来继续调
oldThing,切换会漏。对oldThing加 deprecated 标注或 lint 规则防回流 - 验证:每步跑测试 + 切换完 grep
oldThing全局 0 引用 - 前后端:通用
- 配哪种 scan 项:某函数 / 接口被 N 处调用,要改签名或实现
M-L1-02 Strangler Fig 绞杀者模式
- 适用:替换一整块老模块(甚至一整个子系统),老的不能立刻删、要长期共存
- 不适用:单函数或小范围改动(用 Parallel Change 就够)
- 步骤:
1. 在老模块外围加一层路由/代理,默认仍走老实现 2. 新实现逐个功能点接入,通过路由分流(新功能点走新实现,老功能点仍走老实现) 3. 老功能点一个一个迁过来,每迁一个跑全量回归 4. 全部迁完,删老模块和路由层
- 风险点:路由层成为永久依赖;新老实现中间状态不一致(如共享数据库时 schema 冲突)
- 验证:每次迁移后跑全量回归;监控老模块调用次数,应逐步归零
- 前后端:通用,后端尤其常见
- 配哪种 scan 项:"这块老逻辑要整体替换",不能一次性切
M-L1-03 Branch by Abstraction 分支抽象
- 适用:要替换一个被广泛使用的底层库 / 框架 / 核心数据结构
- 不适用:改动只影响局部
- 步骤:
1. 在调用点和老实现之间插入一层抽象接口,调用点改为依赖接口 2. 接口的默认实现仍指向老实现,跑测试验证行为不变 3. 在接口下实现新版本,通过 feature flag 或配置切换 4. 观察一段时间无问题,删除老实现和抽象层
- 风险点:抽象层设计不好会泄漏老实现细节到接口;feature flag 忘记清理
- 验证:每步跑测试;切换期间对比新老实现的输出
- 前后端:通用
- 配哪种 scan 项:要换底层依赖(如换 HTTP 客户端、换 ORM、换状态管理库)
M-L1-04 Characterization Test 刻画测试
- 适用:老代码没测试、行为不完全清楚,但马上要改——refactor 前置必做
- 不适用:代码逻辑极简(< 10 行、无分支)、或已有充分测试
- 步骤:
1. 对目标函数喂一批真实输入(可从生产日志采样) 2. 记录当前输出作为测试断言——不评价这个行为是否"正确",只固化现状 3. 跑测试确认通过,提交 4. 之后的重构每步都跑这组测试,任何一条失败都是行为偏离
- 风险点:固化的"现状"可能包含已知 bug——如果是故意要修 bug,走 issue 不走 refactor
- 验证:重构后测试全通过 = 行为等价
- 前后端:通用
- 配哪种 scan 项:前置检查第 2 条命中时,用本方法补测试
---
L2 代码级重构(Fowler 经典)
M-L2-01 Extract Function 提取函数
- 适用:函数内部有一段内聚逻辑可以命名(> 5 行、职责独立)
- 不适用:短、命名困难、和外层逻辑强耦合的片段
- 步骤:
1. 识别要提取的片段,起一个说清"做什么"的名字 2. 把用到的外部变量作为参数,把返回给外层的值作为返回值 3. 替换原片段为函数调用 4. 跑测试
- 风险点:参数过多(> 4 个)说明耦合太深,可能要先做 M-L2-07 引入参数对象;副作用跨边界(读写 this / 全局)会让"函数"变成伪装的过程
- 验证:跑单元测试
- 前后端:通用
- 配哪种 scan 项:函数过长 / 圈复杂度高 / 内部有可命名的段落
M-L2-02 Inline Function 内联函数
- 适用:函数体比名字更清楚 / 函数已经只剩包装作用 / 函数被调用次数极少
- 不适用:函数被广泛使用
- 步骤:
1. 找出所有调用点 2. 每个调用点用函数体替换 3. 删函数定义 4. 跑测试
- 风险点:调用点很多时内联出一堆重复代码;递归函数不能内联
- 验证:跑单元测试;grep 原函数名 0 引用
- 前后端:通用
- 配哪种 scan 项:空壳包装函数 / 抽象做过头的层
M-L2-03 Extract Variable / Replace Temp with Query 提取变量 / 以查询取代临时变量
- 适用:复杂表达式难以理解(长三元、多重计算);同一计算在多处用到
- 不适用:表达式已经清楚
- 步骤:
1. 把复杂表达式提取到命名变量 2. 如果该计算在多处复用,进一步提取为纯函数(query) 3. 跑测试
- 风险点:过度提取反而让变量满天飞;提取为 query 时要保证无副作用
- 验证:跑单元测试
- 前后端:通用
- 配哪种 scan 项:难懂的长表达式 / 重复计算
M-L2-04 Move Function 搬移函数
- 适用:函数更多使用另一个类/模块的数据;或函数和当前模块的主题不符
- 不适用:当前位置仍是最自然的位置
- 步骤:
1. 确认函数在新位置的所有依赖都可达 2. 在新位置创建函数,原位置改为转发调用(过渡期)或直接替换所有调用点 3. 迁移所有调用点后删原函数 4. 跑测试
- 风险点:函数依赖原位置的私有状态时不能直接搬
- 验证:跑测试;grep 原位置 0 引用
- 前后端:通用
- 配哪种 scan 项:函数位置错配 / 模块职责模糊
M-L2-05 Decompose Conditional 分解条件
- 适用:if / else 分支内部逻辑长,判断条件本身也复杂
- 不适用:分支短且清楚
- 步骤:
1. 把判断条件提取为命名函数(如 isEligibleForDiscount(user)) 2. 把各分支体提取为命名函数 3. 主体只剩 if (isX()) doA() else doB() 的骨架 4. 跑测试
- 风险点:过度分解让调用链变深
- 验证:跑单元测试
- 前后端:通用
- 配哪种 scan 项:嵌套 if-else / 复杂条件判断
M-L2-06 Replace Conditional with Polymorphism 以多态取代条件
- 适用:同一个 type / status 字段在多处触发相似的 switch/if-else 分发
- 不适用:只在一处分发 / 类型数量不稳定
- 步骤:
1. 为每个类型建立子类或策略对象,把原分支逻辑放入对应实现 2. 调用点改为调用多态方法 3. 删除原 switch/if-else 4. 跑测试
- 风险点:类型爆炸;前端里过度 OO 反而不如 map 查表清晰
- 验证:跑单元测试
- 前后端:通用
- 配哪种 scan 项:同一 type 字段在 3+ 处触发 switch
M-L2-07 Introduce Parameter Object 引入参数对象
- 适用:函数参数 > 4 个,或多处函数共享同一组参数
- 不适用:参数少且无关
- 步骤:
1. 把相关参数聚成一个对象 / 结构体 2. 函数签名改为接收该对象 3. 所有调用点构造对象传入 4. 跑测试
- 风险点:对象字段和函数实际用到的字段不一致(可能传了不用的字段)
- 验证:跑测试
- 前后端:通用
- 配哪种 scan 项:参数爆炸 / 重复的参数组
M-L2-08 Replace Nested Conditional with Guard Clauses 守卫语句
- 适用:函数开头有多层嵌套 if 检查边界/错误条件
- 不适用:条件之间有真实的互斥关系,不是纯守卫
- 步骤:
1. 把每个边界条件改写为"不满足就提前 return" 2. 主体逻辑从嵌套中拉出到顶层 3. 跑测试
- 风险点:改变了 return 的执行顺序;有 finally / cleanup 逻辑的要小心
- 验证:跑测试,覆盖所有边界条件
- 前后端:通用
- 配哪种 scan 项:深度嵌套 if 检查
---
L3 结构拆分
M-L3-01 Component Split 组件拆分(容器 / 展示)
- 适用:单组件 > 300 行;同时处理数据获取、状态管理、渲染;props 爆炸
- 不适用:小组件 / 拆分后子组件无独立意义
- 步骤:
1. 识别组件里哪部分是"数据编排"(容器),哪部分是"纯渲染"(展示) 2. 把展示部分抽到独立子组件,通过 props 接收数据和事件回调 3. 容器组件只负责数据获取 / 状态 / 传递 4. 逐个验证子组件可独立渲染
- 风险点:props 传递过深(props drilling);子组件和容器边界不清导致 props 仍然爆炸
- 验证:子组件可在 storybook / 测试环境独立渲染;整体交互行为不变
- 前后端:前端特化
- 配哪种 scan 项:超大组件 / 职责混杂的组件
M-L3-02 Extract Composable / Custom Hook 抽取组合式函数
- 适用:组件里有一段状态 + 副作用的逻辑(表单校验、数据获取、本地缓存、快捷键绑定等),可在多个组件间复用或单独测
- 不适用:逻辑和组件强耦合 / 只在一个组件里用且没增长
- 步骤:
1. 识别一段内聚的 reactive 状态 + 副作用 2. 抽到独立文件,Vue 为 use{Name}.ts,React 为 use{Name}.ts 3. 入参是配置项,返回是状态 + 操作方法 4. 组件改为调用该 composable/hook 5. 为 composable/hook 写单元测试(纯 JS 侧,不挂载组件)
- 风险点:抽取的边界不干净,组件和 composable 之间还在共享状态;生命周期钩子(onMounted / useEffect)里的清理没迁移
- 验证:组件行为不变;composable 单测通过
- 前后端:前端特化(Vue composable / React hook)
- 配哪种 scan 项:组件里封闭的逻辑块 / 多个组件有相似逻辑
M-L3-03 State Lifting / Lowering 状态提升 / 下沉
- 适用:状态放在错的层级——提升:多个兄弟组件需要共享的状态放在各自本地;下沉:只有一个子组件用的状态放在了父或全局
- 不适用:当前状态位置已是最低公共祖先
- 步骤:
1. 画出状态的读写点分布 2. 找到所有读写点的最低公共祖先(LCA) 3. 状态挪到 LCA,通过 props / context / 事件向下传、向上提 4. 跑交互验证
- 风险点:挪错层导致渲染范围扩大;context 滥用让性能变差
- 验证:交互行为不变;React DevTools / Vue DevTools 看渲染范围符合预期
- 前后端:前端特化
- 配哪种 scan 项:同一状态在多个组件重复 / 全局 store 里装了只有一处用的字段
M-L3-04 Service Layer Extraction 服务层抽取
- 适用:Controller / 路由处理函数里直接做业务逻辑(校验、多表查询、外部调用),代码越长越难测
- 不适用:非常简单的 CRUD 透传
- 步骤:
1. 建立 services/ 目录,为该业务域建一个 service 类/模块 2. 把业务逻辑从 controller 挪到 service 方法 3. Controller 只剩:解析请求 → 调 service → 组装响应 4. 为 service 方法写单元测试(不需要启 HTTP)
- 风险点:service 变成又一个"什么都装"的大类;事务边界处理不清
- 验证:集成测试(HTTP 层)不变;service 单元测试独立通过
- 前后端:后端特化
- 配哪种 scan 项:胖 controller / 业务逻辑贴在路由
M-L3-05 Repository Extraction 仓储层抽取
- 适用:Service 里直接写 SQL / 直接调 ORM;同一查询在多处重复
- 不适用:纯脚本 / 原型
- 步骤:
1. 为该实体建 Repository,封装所有 DB 访问(CRUD + 常用查询) 2. Service 改为依赖 Repository 3. 测试时可替换为内存实现或 mock Repository
- 风险点:Repository 成为泛型 DAO 集合,失去业务语义;事务跨 Repository 边界处理复杂
- 验证:集成测试通过;Service 层测试可用 mock Repository
- 前后端:后端特化
- 配哪种 scan 项:Service 里散落的 DB 访问
M-L3-06 Layer Rectification 分层纠偏
- 适用:违反既定分层(Controller 调了 DB、View 调了 Service、Model 调了 View)
- 不适用:项目没有明确分层约定 → 先走 decisions 定分层
- 步骤:
1. 确认项目分层约定(依赖 decisions 里的记录) 2. 找出所有违反点 3. 每个违反点走 Parallel Change(M-L1-01)迁到正确层 4. 加 lint 规则 / 代码审查检查点防回流
- 风险点:改动面大,建议拆多次 refactor;新旧共存期容易写出两套路径
- 验证:静态分析 / 依赖关系图无违反
- 前后端:后端常见,前端也适用
- 配哪种 scan 项:跨层依赖(命中前置检查第 3 条时优先走 architecture)
M-L3-07 Single Responsibility Split 职责分离
- 适用:一个类 / 模块承担了 > 2 个不相关的职责
- 不适用:职责虽多但紧密相关
- 步骤:
1. 列出当前类的所有方法,按"改动它们的理由"分组 2. 按分组拆分为多个类,每个类一个职责 3. 原类如果还需存在,改为协调者(组合各新类) 4. 迁移调用点
- 风险点:过度拆分 → 对象爆炸;分组判断主观,拆法因人而异
- 验证:每个新类单测独立通过;原外部行为不变
- 前后端:通用
- 配哪种 scan 项:什么都装的 Manager / Helper / Utils
---
L4 性能与异步
M-L4-01 Memoization 记忆化
- 适用:纯计算在同一输入下重复执行;渲染时依赖的 derived 值每次都重算
- 不适用:计算本身非常便宜 / 输入空间巨大(缓存不命中 + 内存占用)
- 步骤:
1. 识别纯计算点(无副作用、输出只依赖输入) 2. Vue 用 computed,React 用 useMemo / React.memo,纯 JS 用手写 memo 3. 跑 benchmark 对比前后
- 风险点:把非纯函数错误标为纯;缓存 key 不稳定导致永远不命中;大对象缓存泄漏
- 验证:行为不变;性能指标(CPU / 渲染次数)下降
- 前后端:通用(性能场景以前端居多)
- 配哪种 scan 项:重复计算 / 父组件每次渲染导致子组件重渲
M-L4-02 Batching 批处理
- 适用:高频小操作导致总开销过大(一次一次 DB 写、一次一次事件触发、一次一次渲染)
- 不适用:单次操作本身就够便宜 / 延迟敏感(批处理会引入延迟)
- 步骤:
1. 在操作和执行之间加一层缓冲 2. 按时间窗口 / 容量触发批执行 3. 调用点从"一次做一件"改为"扔进队列"
- 风险点:延迟增加;失败处理变复杂(批里有几条失败怎么办);内存压力
- 验证:吞吐提升;延迟仍在可接受范围;失败处理覆盖
- 前后端:通用
- 配哪种 scan 项:循环内 IO / 高频事件触发
M-L4-03 Lazy Loading / Code Splitting 懒加载 / 代码分割
- 适用:首屏包过大;某些页面 / 组件只在特定路径才用到
- 不适用:对所有用户都立即需要的核心内容
- 步骤:
1. 识别可延后加载的模块(按路由、按组件、按功能) 2. 改为动态 import(() => import(...))或路由级分包 3. 添加 loading / fallback UI 4. 构建产物看包分析器确认效果
- 风险点:切换时闪烁;网络差时加载卡顿;分包过细反而增加请求数
- 验证:首屏包大小下降;功能可正常延迟加载
- 前后端:前端特化
- 配哪种 scan 项:大 bundle / 不常用模块被强加载
M-L4-04 N+1 Query Elimination N+1 查询消除
- 适用:循环里对每条记录发起单独查询(N+1 问题)
- 不适用:记录数极少且查询便宜
- 步骤:
1. 定位循环中的查询 2. 改为一次批量查询(IN 查询、JOIN、或 ORM 的 eager load / dataloader) 3. 在代码里构建 id → 结果 的 map 替代循环查询 4. 跑性能测试确认查询次数下降
- 风险点:
IN列表过长;JOIN 笛卡尔积;eager load 过度导致内存飙升 - 验证:查询日志显示查询次数从 N+1 降到 1-2;结果正确
- 前后端:后端特化
- 配哪种 scan 项:循环里的 DB / 外部 API 调用
M-L4-05 Index & Cache 索引与缓存
- 适用:慢查询有明确的过滤字段但无索引;读多写少的数据可缓存
- 不适用:写密集场景加索引反降性能;一致性要求高的数据不该粗暴缓存
- 步骤:
1. 用慢查询日志 / EXPLAIN 定位瓶颈 2. 加索引:覆盖过滤和排序字段,注意复合索引顺序 3. 加缓存:选层次(应用内 / Redis / CDN),定义 TTL 和失效策略 4. 上线后观察命中率和延迟
- 风险点:索引过多影响写性能;缓存一致性(读到旧数据);缓存雪崩 / 穿透
- 验证:查询延迟下降;缓存命中率符合预期;数据一致性测试通过
- 前后端:后端特化
- 配哪种 scan 项:慢查询 / 重复读取的热数据
M-L4-06 Async & Cancellation 异步与取消
- 适用:长任务阻塞;组件卸载后仍在跑的副作用 / 网络请求;回调地狱
- 不适用:任务极短且不可取消
- 步骤:
1. 把同步长任务改成 async(Promise / async-await) 2. 加取消机制:AbortController(fetch)、Vue onUnmounted / React cleanup 里取消 3. 清理资源:定时器、事件监听、订阅 4. 测试组件快速切换 / 请求快速重发是否有残留
- 风险点:忘加 cleanup 导致内存泄漏 / 状态更新到已卸载组件(React 警告);取消后的中间态处理
- 验证:卸载 / 切换后无泄漏警告;测试快速切换场景
- 前后端:通用(前端场景居多)
- 配哪种 scan 项:回调地狱 / 未清理的副作用 / useEffect 无返回清理
M-L4-07 List Virtualization 列表虚拟化
- 适用:长列表(> 数百条)渲染卡顿;表格大数据量
- 不适用:列表短 / 行高不稳定(实现复杂度高)
- 步骤:
1. 选库(vue-virtual-scroller / react-window / tanstack-virtual 等) 2. 替换列表渲染为虚拟化组件 3. 处理行高(固定 / 可变)和滚动恢复
- 风险点:搜索 / Ctrl+F 只能找到已渲染行;可访问性(屏幕阅读器);打印
- 验证:滚动流畅;渲染 DOM 数限制在视口左右;交互行为不变
- 前后端:前端特化
- 配哪种 scan 项:超长列表无分页 / 无虚拟化
---
用法速查
- scan 阶段:扫到候选优化点匹配最合适的方法号填入"建议映射的方法"。匹配不上说明候选写太模糊,重写
- design 阶段:执行步骤引用方法号后,把"步骤"字段落到本项目的具体文件 / 函数。方法库的步骤是骨架不是直接复制的答案
- 扩展方法库:新方法号接着层内编号递增。新增完整填齐所有字段——缺字段不准入库
scan 前置检查与拒绝路由
scan 开始前跑一遍 7 条前置检查。任一命中中止 scan 给路由建议不硬凑清单。AI 默认倾向是"用户让我扫就得交点什么"——这是低质量重构清单的源头。拒绝输出是合法路径。
---
7 条前置检查(按顺序跑)
1. 用户描述里夹带行为改动吗?
触发:用户说"顺便加 X / 还要支持 Y / 改成返回 A 而不是 B / 顺手修下 Z"。
为什么停:refactor 底线是行为等价。混着做就没法验证"只动结构"——改完出问题分不清是重构引入的还是新能力引入的。
路由:
这次描述里有"{触发词}"属于行为改动不在 refactor 范围。建议拆两件事:行为改动走cs-feat(新能力)或cs-issue(bug 修),结构改动走 refactor。拆完再回来。
---
2. 目标模块有测试覆盖吗?
怎么查:扫一下是否有对应 .test.* / .spec.*,或跑覆盖率工具看关键路径。
触发:关键路径无测试覆盖 / 行覆盖率明显偏低(< 60%,项目有要求按项目要求)/ 有测试但测的是无关紧要的边角,核心业务路径不在测试里。
例外豁免:纯声明式内容(样式 / 静态配置 / 类型别名)/ 一目了然的短函数(< 10 行无分支)/ 纯展示组件(只有 Props → 渲染无内部逻辑)。
为什么停:没测试"行为等价"就只是口头承诺。
路由:
目标模块 {文件} 核心路径没测试覆盖。refactor 不能基于"口头承诺"的行为等价。先做前置:用 characterization test 固化当前行为——对目标函数喂一批真实输入记录当前输出作为测试断言。补完测试再回来。
---
3. 问题是跨模块的吗?
触发:扫描时多数候选优化点涉及——A 依赖 B 内部实现(不是公开接口)/ 同一职责分散在 3+ 个模块各写一份 / 模块边界本身混乱。量化阈值:> 50% 候选点落在跨模块关系上。
为什么停:单模块 refactor 不能解决跨模块问题。强行在单模块内部改要么改不动(依赖卡着)要么改完其他模块跟着出问题。
路由:
主要问题是跨模块的:{具体描述}。这不是单模块 refactor 能解决的,需要先走:
1. cs-arch 更新模块边界图2. cs-decide 记新依赖原则3. 回来拆成若干单模块 refactor 任务
---
4. 候选优化点全是风格口味吗?
触发:扫出来 > 50% 落在——命名风格 / 引号 / 分号 / 箭头函数 vs function / import 顺序 / 方法声明顺序 / 空行 / 缩进。
为什么停:风格口味不该靠人工 refactor 解决。一劳永逸是 lint 规则 + 自动修。
路由:
主要是风格口味(命名 / 引号 / 格式)。正确处理方式不是 refactor:
1. cs-decide 拍板风格规约2. ESLint / Prettier 加规则
3. 跑一次 --fix 自动修全项目---
5. 目标文件是生成产物或第三方代码吗?
怎么查:文件头有 // GENERATED / @generated / // DO NOT EDIT 标记 / 路径在 node_modules/ vendor/ dist/ build/ / 路径匹配 *.d.ts 但不是手写 / 有开源 license header。
为什么停:生成产物改了会被下次生成覆盖;第三方代码改了违反 license 也无法随上游更新。
路由:
{文件} 是 {生成产物 / 第三方代码}。改这里要么会被覆盖要么违反上游许可。正确做法:
- 生成产物 → 改生成源({具体脚本 / 模板})
- 第三方代码 → fork 或提 PR;或加一层 wrapper 改 wrapper
---
6. scan 范围太大吗?
触发(任一):涉及文件 > 15 个 / 涉及代码行数 > 3000 / 扫完预计 > 20 条候选。
为什么停:范围太大 AI 上下文承载不住会丢细节、自相矛盾;用户也没法一次性 review 这么多。
路由:
范围涉及 {N 个文件 / M 行} 超过单次 scan 上限。先做一件事再回来:
- 模块内部本来就该拆分 → 先走 cs-arch- 范围可缩 → 和用户挑一个子集("就看 {具体组件}")
---
7. 扫完真的有东西可改吗?
触发:前 6 条都过了,扫完扣掉口味项和重复项之后候选 < 3 条。
为什么停:零条是合法输出。AI 默认会为交差凑几条勉强算得上的,用户信了就改最后发现改了个寂寞甚至引入新问题。
路由:
扫完 {范围} 按硬约束过滤后值得做的 {0 / 1 / 2} 条不够开 design。两个选项:
- 现在不做:模块当前状态健康,等有具体触发点(性能 / 新增功能遇阻)再回来
- 降级处理:直接把这 {1-2} 条作为小修小补做掉不走完整 refactor
---
拒绝输出的固定格式
任一命中按这个格式输出——让用户一眼看到发生了什么 / 为什么 / 下一步去哪:
⛔ refactor 流程中止
命中前置检查:第 {N} 条 —— {检查名}
证据:
- {具体文件 / 行号 1}:{为什么触发}
- {具体文件 / 行号 2}:{为什么触发}
建议路由:
{引导文案}
回到 refactor 的条件:
{满足什么情况下可以重启本次 refactor}---
多条同时命中怎么办
按编号最小那条给路由——7 条按"越前面越该先处理"排:
1. 行为改动混进来,拆了再说 2. 没测试,补测试先 3. 跨模块,走架构层 4. 全是口味,走 decisions 5. 文件是生成的,换目标 6. 范围太大,缩范围 7. 扫完没啥可改,老实说
处理完第一条重新跑前置检查——修掉第一个问题后其他条件可能也变了。
---
为什么"拒绝"要做成显式路径
只让 AI"尽量产出",它会把模糊信号当有效信号、把口味项包装成"可读性优化"、把测试覆盖不足的模块照样改。
把"拒绝"定义清楚(什么情况下拒绝 / 怎么输出 / 之后去哪),AI 才会老实说"这事我不该接"。这和 feature-design 里"需求不清就退回 brainstorm"是同一种思路——用流程结构对抗 AI 的"交差倾向"。
scan 清单条目格式
scan 产出要被用户 30 秒扫一条决定 yes/no——字段固定、顺序固定、可写什么不可写什么有硬约束。
---
{slug}-scan.md 文件骨架
---
doc_type: refactor-scan
refactor: {YYYY-MM-DD}-{slug}
status: pending-user-selection | user-reviewed
scope: {扫描范围一句话,含文件/目录列表}
summary: {发现多少条,按分类分布}
---
# {slug} scan
## 总览
- 扫描范围:{文件/目录}
- 发现 N 条优化点:结构 a / 性能 b / 可读性 c
- 按风险:低 x / 中 y / 高 z
- 建议先做:#A #B #C(低风险、独立、AI 可自证)
- 建议慎做 / 后做:#D(高风险、触发渲染路径变化、需人工目视)
- 前置检查 7 条全过:✓
## 条目
[一条一块,格式见下节]用户勾选方式:在每条标题行末尾加 ✓ 或 ✗(✗ 后面跟一行理由)。AI 不替用户勾选。
---
单条字段顺序和格式
### [编号] {一句话标题} ← 用户在这行末尾标 ✓ 或 ✗
- **位置**:`src/xxx.vue:120-180`(可点开)
- **分类**:结构 / 性能 / 可读性(三选一,不叠加)
- **现状**:一句话白描现在怎么写的,必要时贴 ≤5 行原代码
- **问题**:为什么值得改——可度量的东西(圈复杂度、重复次数、渲染次数、行数、依赖方向)
- **建议**:动词开头,说清改成什么样
- **建议映射的方法**:M-Ln-NN(引用 methods.md 里的方法号)
- **风险**:低 / 中 / 高 + 一句话为什么
- **验证**:AI 自证(跑哪个测试/类型检查)| HUMAN(人要看什么页面/操作什么)
- **范围**:约 N 行 / M 文件字段顺序的理由
位置 → 分类 → 现状 → 问题 → 建议 → 方法 → 风险 → 验证 → 范围。对应人类决策流:在哪 → 是啥类型 → 现在怎样 → 为什么要动 → 怎么动 → 套哪个方法 → 多大代价 → 怎么验 → 工作量。换顺序会让读者多次折返。
标题写作约束
- ≤ 25 字,名词短语或动词短语,说动什么不说好在哪
- ✓ "把 handleData 的 3 层嵌套 filter 换成单次 reduce"
- ✗ "优化数据处理逻辑"(没说动什么)/ "提升 handleData 的可读性和性能"(说的是好处不是动作)
---
硬约束
AI 生成条目必须守,违反要自我纠正重写。
约束 1:问题字段不允许纯形容词
"太长 / 太乱 / 不优雅 / 耦合严重 / 难以维护"都要被拒绝。必须落到可度量的东西:行数 / 圈复杂度(> 10)/ 嵌套深度(> 3)/ 重复次数(同一数组遍历 N 次)/ 依赖方向(A 依赖 B 内部实现)/ 具体性能指标(N+1 查询 / 每次渲染重建 / 没有清理)。
约束 2:建议字段不允许开放式
不能写"考虑重构这块 / 建议整理一下 / 优化一下结构"。要写出具体动作:
- ✓ "抽成 useFormValidation composable,参数是 schema + initialValues,返回 errors + validate"
- ✗ "提取公共逻辑"(提到哪?什么公共?)/ "使用更好的模式"(哪个?)
约束 3:一条只做一件事
不能"拆成 composable 顺便把命名改一下"——命名是另一条。一个条目对应一个原子动作。
约束 4:同一位置最多出现在 3 条里
同一文件 / 函数出现在 4 条以上 → 这块应该整体设计而不是列清单改。退回前置检查触发"范围太大"或"架构问题"路由。
约束 5:不列口味项
箭头函数 vs function / 单引号 vs 双引号 / 命名风格 / 代码顺序 / import 顺序——一律不进清单。
例外:项目已有 decision 明确要求且代码违反——这种"问题"字段要引用 decision 编号。
约束 6:每条必须映射到方法库
"建议映射的方法"写不出 M-Ln-NN → 建议过于模糊重写到能对应某个方法。映射不上的不准进清单。
---
总览段的硬约束
顶部总览必须包含:扫描范围(具体文件 / 目录)+ 总条数和分类分布 + 风险分布 + 建议先做 3-5 条 + 建议慎做 / 后做 + 前置检查 7 条是否全过。
让用户不读全清单也能判断方向。写不出"建议先做哪几条"说明风险排序没想清楚,回炉。
---
反模式样本
写进 SKILL.md 的 AI 一眼就能对照检查。
❌ 反模式 1:形容词堆砌
### #3 优化数据处理逻辑
- 位置:src/utils/data.ts
- 分类:可读性
- 现状:handleData 函数处理用户数据
- 问题:代码可以更清晰
- 建议:重构 handleData 函数
- 建议映射的方法:(无)
- 风险:低
- 验证:AI 自证
- 范围:约 50 行问题:标题没说动什么;问题字段纯形容词;建议字段开放式;没方法号。
✅ 重写后
### #3 把 handleData 里的 3 层嵌套 filter 换成单次 reduce
- 位置:src/utils/data.ts:45-80
- 分类:性能
- 现状:handleData 对同一数组依次调用 filter → map → filter,长度 5000 的输入要遍历 3 次
- 问题:同数组被遍历 3 次(O(3n) 可降到 O(n));嵌套深度 3,圈复杂度 8
- 建议:合并为一次 reduce,累加器里同时做筛选和转换,保持现有输出结构
- 建议映射的方法:M-L2-03(提取/合并遍历)
- 风险:低(纯局部改动,有 5 个单元测试覆盖输入输出)
- 验证:AI 自证(跑 data.test.ts;benchmark 对比前后耗时)
- 范围:约 35 行 / 1 文件❌ 反模式 2:多件事塞一条
### #7 拆分 UserForm 组件并改进命名应拆成至少两条:一条"拆分 UserForm 组件",一条"重命名 XXX"(而命名改动大概率是口味项,应整个去掉)。
❌ 反模式 3:同一位置反复出现
如果 #3 #5 #8 #11 都指向 src/UserForm.vue,说明这块应该整体重设计,而不是散成 4 条小改动。应退回前置检查的第 3 条(跨模块 / 整体架构问题)或第 6 条(范围过大)。
---
用户勾选后的状态迁移
- 用户勾选完 → status 改为
user-reviewed - 被 ✗ 的条目保留在文件里(不要删),留痕"当时考虑过但不做"
- 被 ✓ 的条目就是阶段 2 design 的输入
- 全被 ✗ → 本次 refactor 终止,不进 design
Related skills
How it compares
Choose cs-refactor when you need a cited, step-verified method catalog for large legacy changes instead of ad hoc single-pass edits.
FAQ
What does cs-refactor do?
代码优化的子流程入口,处理"行为不变、结构变"的工作(结构 / 性能 / 可读性),按 scan → design → apply 分步执行每步人工放行。触发:用户说"优化一下 / 重构 / 重写 / 拆一下 / 性能不行 / 代码太长"且不夹带行为改动。不处理新需求 / bug / 跨模块架构重划。.
When should I use cs-refactor?
User asks about cs refactor or related SKILL.md workflows.
Is cs-refactor safe to install?
Review the Security Audits panel on this page before installing in production.