@namewta/speculo 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cli.js +2 -2
- package/dist/src/cli.js.map +1 -1
- package/dist/src/index.js +15 -7
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
- package/speculo/skills/worktree-isolation/SKILL.md +59 -0
- package/speculo/skills/worktree-isolation/references/audit-branch-tree.md +32 -0
- package/speculo/skills/worktree-isolation/references/create-worktree.md +39 -0
- package/speculo/skills/worktree-isolation/references/merge-and-cleanup.md +43 -0
- package/speculo/workflows/dev/00-INDEX.md +6 -2
- package/speculo/workflows/dev/01-grill-with-docs/01-grill-with-docs.md +26 -0
- package/speculo/workflows/dev/04-finalize/04-finalize.md +133 -0
- package/speculo/workflows/dev/04-finalize/completion-gate.md +40 -0
- package/speculo/workflows/dev/04-finalize/finalize-archive.md +55 -0
- package/speculo/workflows/dev/R-review/R-review.md +60 -26
- package/speculo/workflows/dev/R-review/code-quality-checklist.md +118 -0
- package/speculo/workflows/dev/R-review/removal-checklist.md +53 -0
- package/speculo/workflows/dev/R-review/review-axes.md +57 -0
- package/speculo/workflows/dev/R-review/review-setup.md +16 -8
- package/speculo/workflows/dev/R-review/review-verdict.md +40 -0
- package/speculo/workflows/dev/R-review/security-checklist.md +126 -0
- package/speculo/workflows/dev/R-review/solid-checklist.md +73 -0
- package/speculo/workflows/dev/_templates/completion-summary-template.md +24 -0
- package/speculo/workflows/dev/_templates/completion-verification-template.md +28 -0
- package/speculo/workflows/dev/_templates/review-report-template.md +19 -6
- package/speculo/workflows/dev/_templates/review-sources-template.md +11 -3
- package/speculo/workflows/dev/_templates/review-verdict-template.md +32 -0
- package/speculo/workflows/dev/R-review/review-two-axis.md +0 -33
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
id: dev/R-review
|
|
3
3
|
category: dev
|
|
4
4
|
name: Review
|
|
5
|
-
description: 从固定比较点开始,按 Standards
|
|
6
|
-
keywords: [review, diff, standards,
|
|
5
|
+
description: 从固定比较点开始,按 Spec、Engineering、Standards 三个独立维度审查当前 diff,并给出带严重度的裁决
|
|
6
|
+
keywords: [review, diff, spec, engineering, standards, security, solid, pr, 审查]
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Review 工作流执行指引
|
|
10
10
|
|
|
11
|
-
本工作流是 `dev/R` 入口,用于审查 `HEAD` 与用户提供的固定点之间的 diff
|
|
11
|
+
本工作流是 `dev/R` 入口,用于审查 `HEAD` 与用户提供的固定点之间的 diff。审查以**资深工程师视角**进行,结果必须分成三个**互相独立、互不掩盖**的维度,每条 finding 带严重度,最后给出整体裁决。
|
|
12
12
|
|
|
13
13
|
## 内置指引
|
|
14
14
|
|
|
@@ -16,49 +16,79 @@ keywords: [review, diff, standards, spec, pr, 审查]
|
|
|
16
16
|
|
|
17
17
|
当用户想审查分支、PR、进行中的变更,或要求 `review since <fixed-point>` 时使用。
|
|
18
18
|
|
|
19
|
-
###
|
|
19
|
+
### 三个审查维度
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
- 当前 change 目录:`.speculo/dev/<change>/`
|
|
23
|
-
- 可发现的标准来源:`.speculo/.config/RULES.md`、`.speculo/.config/context/`、`.speculo/.config/adr/`、`AGENTS.md`、`CONTRIBUTING.md`、配置文件等
|
|
24
|
-
- spec 来源:当前 change 的 PRD、slices、用户提供路径、commit message 中引用的 issue 或其他规格文档
|
|
21
|
+
三个维度是三种独立的"镜头",**不合并、不重排、不让一个维度的结论掩盖另一个**:
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
| 维度 | 问题 | 关注 |
|
|
24
|
+
|------|------|------|
|
|
25
|
+
| **Spec** | 做对了吗? | 是否忠实实现来源 issue / PRD / spec:缺失需求、范围蔓延、看似实现但有问题的需求 |
|
|
26
|
+
| **Engineering** | 做好了吗? | 不依赖成文规则的工程质量:SOLID 与架构、安全与可靠性、错误处理、性能、边界、死代码 |
|
|
27
|
+
| **Standards** | 合规吗? | 是否违反仓库**已记录**的标准:RULES、ADR、CONTRIBUTING、lint / 格式 / 类型配置 |
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
若缺少 spec,Spec 维度跳过并报告 `no spec available`;若仓库无成文标准,Standards 维度报告检查范围并说明覆盖空白。Engineering 维度始终执行。
|
|
30
|
+
|
|
31
|
+
### 严重度模型
|
|
32
|
+
|
|
33
|
+
每条 finding 必须标注严重度:
|
|
34
|
+
|
|
35
|
+
| 级别 | 名称 | 含义 | 动作 |
|
|
36
|
+
|------|------|------|------|
|
|
37
|
+
| **P0** | Critical | 安全漏洞、数据丢失风险、正确性 bug | 必须阻断合并 |
|
|
38
|
+
| **P1** | High | 逻辑错误、显著 SOLID 违背、性能回退、关键需求缺失 | 合并前应修复 |
|
|
39
|
+
| **P2** | Medium | 代码异味、可维护性隐患、轻微 SOLID 违背、范围蔓延 | 本 PR 修或建后续项 |
|
|
40
|
+
| **P3** | Low | 风格、命名、小建议 | 可选改进 |
|
|
31
41
|
|
|
32
42
|
### 执行原则
|
|
33
43
|
|
|
34
|
-
|
|
44
|
+
- 用户说的任何东西都是固定点。若用户没有指定固定点,先询问;拿到前不要继续。
|
|
45
|
+
- 比较命令使用三点语法:`git diff <fixed-point>...HEAD`,同时记录 `git log <fixed-point>..HEAD --oneline`。
|
|
46
|
+
- **Worktree 模式**:若当前 change 为 worktree 隔离模式(`.status.json` 的 `worktree_enabled` 为真),fixed point 默认取 `base_branch`,且审查必须完整覆盖 change 分支树 `base_branch..change_branch` 的**每一个 commit**,不能只看最新工作区状态。此时读取 `../../../skills/worktree-isolation/SKILL.md` 的 `references/audit-branch-tree.md`;非 worktree 模式不读取该 skill。
|
|
47
|
+
- **Review-first**:本工作流默认只产出审查结论,**不修改代码**;除非用户在看到 findings 后明确授权修复。
|
|
48
|
+
- **诚实优先**:无法覆盖的区域要显式声明(见 `review-verdict.md` 的 clean-review 要求),不得用"看起来没问题"代替实际检查。
|
|
49
|
+
- 机器已强制的标准(lint / 类型 / 格式)只记录来源,不重复人工检查工具已覆盖的内容。
|
|
50
|
+
- 如果环境支持并行子代理,三个维度应并行执行;如果不支持,按三个独立上下文顺序执行,并在报告中保持分离。
|
|
35
51
|
|
|
36
|
-
|
|
52
|
+
### 渐进披露(Engineering 维度深度清单)
|
|
37
53
|
|
|
38
|
-
|
|
54
|
+
进入 Engineering 维度审查时,按需读取同目录清单:
|
|
39
55
|
|
|
40
|
-
|
|
56
|
+
- `solid-checklist.md`:检查 SOLID 违背与架构异味、给重构启发式时读取。
|
|
57
|
+
- `security-checklist.md`:检查安全漏洞、竞态、密钥、密码学与运行时风险时读取。
|
|
58
|
+
- `code-quality-checklist.md`:检查错误处理、性能 / 缓存、边界条件时读取。
|
|
59
|
+
- `removal-checklist.md`:识别死代码与删除候选、产出删除 / 推迟计划时读取。
|
|
41
60
|
|
|
42
61
|
## 阶段
|
|
43
62
|
|
|
44
|
-
### 1. Review Setup —
|
|
63
|
+
### 1. Review Setup — 固定点、范围与来源收集
|
|
45
64
|
- 规范:`review-setup.md`
|
|
46
65
|
- 模板:`../_templates/review-sources-template.md`
|
|
47
66
|
- 产物:`review-sources.md`
|
|
48
67
|
- 完成准则:
|
|
49
|
-
- 已记录 fixed point、diff 命令、commit
|
|
50
|
-
- 已列出 standards
|
|
68
|
+
- 已记录 fixed point、diff 命令、commit 列表、diff 规模与分批策略
|
|
69
|
+
- 已列出 standards 来源与 spec 来源,或记录各自缺失
|
|
70
|
+
- 已标识关键路径(auth / 支付 / 数据写入 / 网络)
|
|
51
71
|
- `review-sources.md` 无残留 `[TODO:]`
|
|
52
72
|
|
|
53
|
-
### 2.
|
|
54
|
-
- 规范:`review-
|
|
73
|
+
### 2. Multi-Axis Review — 三维度审查
|
|
74
|
+
- 规范:`review-axes.md`
|
|
55
75
|
- 模板:`../_templates/review-report-template.md`
|
|
56
76
|
- 产物:`review-report.md`
|
|
57
77
|
- 完成准则:
|
|
58
|
-
-
|
|
59
|
-
- 每条 finding
|
|
78
|
+
- Spec / Engineering / Standards 分区独立呈现,不合并、不重排
|
|
79
|
+
- 每条 finding 带严重度(P0–P3)、文件/行或 hunk 依据,以及对应 spec / 清单 / 标准引用
|
|
60
80
|
- `review-report.md` 无残留 `[TODO:]`
|
|
61
81
|
|
|
82
|
+
### 3. Verdict & Next Steps — 裁决与后续确认
|
|
83
|
+
- 规范:`review-verdict.md`
|
|
84
|
+
- 模板:`../_templates/review-verdict-template.md`
|
|
85
|
+
- 产物:`review-verdict.md`
|
|
86
|
+
- 完成准则:
|
|
87
|
+
- 给出整体裁决(APPROVE / REQUEST_CHANGES / COMMENT)与严重度汇总
|
|
88
|
+
- 完成 clean-review 声明:检查了什么、未覆盖什么、残留风险
|
|
89
|
+
- 已向用户给出后续选项,未经确认不实施修复
|
|
90
|
+
- `review-verdict.md` 无残留 `[TODO:]`
|
|
91
|
+
|
|
62
92
|
## 依赖
|
|
63
93
|
|
|
64
94
|
- 软依赖:`../02-prd/02-prd.md` 或 `../I-to-issues/I-to-issues.md`,scope: same-change
|
|
@@ -71,12 +101,16 @@ Standards 维度检查 diff 是否违反仓库已记录标准;Spec 维度检
|
|
|
71
101
|
- `dev_entry` (string) — 固定为 `dev/R`
|
|
72
102
|
- `review_fixed_point` (string) — 用户提供的比较点
|
|
73
103
|
- `review_diff_command` (string) — 实际使用的 diff 命令
|
|
104
|
+
- `review_axes` (array) — 实际执行的维度,取值自 `spec` | `engineering` | `standards`
|
|
74
105
|
- `standards_sources` (array) — Standards 审查读取的规则来源
|
|
75
106
|
- `spec_sources` (array) — Spec 审查读取的规格来源
|
|
76
|
-
- `
|
|
107
|
+
- `severity_summary` (object) — 各严重度 finding 计数:`{ "p0": n, "p1": n, "p2": n, "p3": n }`
|
|
108
|
+
- `review_verdict` (approve | request_changes | comment | null) — 整体裁决
|
|
109
|
+
- `review_status` (collecting | reviewing | judged | completed | blocked) — 审查状态
|
|
77
110
|
|
|
78
111
|
## 完成与状态更新
|
|
79
112
|
|
|
80
113
|
- 进入每个 phase 时更新 `current_phase` 和 `phase_history`。
|
|
81
|
-
- 完成 setup 后写入 fixed point、diff
|
|
82
|
-
- 完成报告后更新 `review_status
|
|
114
|
+
- 完成 setup 后写入 fixed point、diff 命令、`review_axes` 和来源清单。
|
|
115
|
+
- 完成报告后更新 `severity_summary`,置 `review_status: judged`。
|
|
116
|
+
- 完成裁决后写入 `review_verdict`,置 `review_status: completed`;但不自动完成 change —— 是否进入修复(`../03-tdd/03-tdd.md`)、收尾归档(`../04-finalize/04-finalize.md`)或其他动作由用户决定。
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# 代码质量清单
|
|
2
|
+
|
|
3
|
+
服务 `R-review.md` 的 **Engineering 维度**。审查 diff 的错误处理、性能与边界条件时读取本文。重点标记会导致**静默失败**或**生产事故**的问题,并按下方"严重度提示"定级。
|
|
4
|
+
|
|
5
|
+
## 错误处理
|
|
6
|
+
|
|
7
|
+
### 需要标记的反模式
|
|
8
|
+
|
|
9
|
+
- **吞掉异常**:空 catch,或只打日志的 catch
|
|
10
|
+
```javascript
|
|
11
|
+
try { ... } catch (e) { } // 静默失败
|
|
12
|
+
try { ... } catch (e) { console.log(e) } // 打了日志就不管
|
|
13
|
+
```
|
|
14
|
+
- **过宽的 catch**:捕获 `Exception` / `Error` 基类而非具体类型
|
|
15
|
+
- **错误信息泄露**:把堆栈或内部细节暴露给用户
|
|
16
|
+
- **缺少错误处理**:可失败操作(I/O、网络、解析)周围没有 try-catch
|
|
17
|
+
- **异步错误处理**:未处理的 promise rejection、缺 `.catch()`、无 error boundary
|
|
18
|
+
|
|
19
|
+
### 应核对的最佳实践
|
|
20
|
+
|
|
21
|
+
- [ ] 错误在恰当的边界被捕获
|
|
22
|
+
- [ ] 错误信息对用户友好(不暴露内部细节)
|
|
23
|
+
- [ ] 错误带足够上下文记录,便于调试
|
|
24
|
+
- [ ] 异步错误被正确传播或处理
|
|
25
|
+
- [ ] 可恢复错误有定义好的兜底行为
|
|
26
|
+
- [ ] 关键错误触发告警 / 监控
|
|
27
|
+
|
|
28
|
+
### 追问
|
|
29
|
+
- "这个操作失败时会发生什么?"
|
|
30
|
+
- "调用方会知道出错了吗?"
|
|
31
|
+
- "有足够上下文调试这个错误吗?"
|
|
32
|
+
|
|
33
|
+
## 性能与缓存
|
|
34
|
+
|
|
35
|
+
### CPU 密集操作
|
|
36
|
+
- **热路径上的昂贵操作**:循环中编译正则、解析 JSON、做加密
|
|
37
|
+
- **阻塞主线程**:同步 I/O、无 worker / async 的重计算
|
|
38
|
+
- **重复计算**:同一计算被多次执行
|
|
39
|
+
- **缺少记忆化**:相同输入反复调用的纯函数
|
|
40
|
+
|
|
41
|
+
### 数据库与 I/O
|
|
42
|
+
- **N+1 查询**:循环里每个元素查一次,而非批量
|
|
43
|
+
```javascript
|
|
44
|
+
// 差:N+1
|
|
45
|
+
for (const id of ids) {
|
|
46
|
+
const user = await db.query(`SELECT * FROM users WHERE id = ?`, id)
|
|
47
|
+
}
|
|
48
|
+
// 好:批量
|
|
49
|
+
const users = await db.query(`SELECT * FROM users WHERE id IN (?)`, ids)
|
|
50
|
+
```
|
|
51
|
+
- **缺索引**:在未建索引的列上查询
|
|
52
|
+
- **过度取数**:只需几列却 SELECT *
|
|
53
|
+
- **无分页**:把整个数据集加载进内存
|
|
54
|
+
|
|
55
|
+
### 缓存问题
|
|
56
|
+
- **昂贵操作缺缓存**:重复的 API 调用、DB 查询、计算
|
|
57
|
+
- **缓存无 TTL**:脏数据被无限期返回
|
|
58
|
+
- **缓存无失效策略**:数据更新了但缓存没清
|
|
59
|
+
- **缓存键碰撞**:键唯一性不足
|
|
60
|
+
- **把用户私有数据全局缓存**:安全 / 隐私问题
|
|
61
|
+
|
|
62
|
+
### 内存
|
|
63
|
+
- **无界集合**:不断增长的数组 / map
|
|
64
|
+
- **大对象滞留**:持有引用阻止 GC
|
|
65
|
+
- **循环中字符串拼接**:应改用 StringBuilder / join
|
|
66
|
+
- **整文件加载**:应改用流式
|
|
67
|
+
|
|
68
|
+
### 追问
|
|
69
|
+
- "这个操作的时间复杂度是多少?"
|
|
70
|
+
- "数据量 10 倍 / 100 倍时行为如何?"
|
|
71
|
+
- "结果可缓存吗?该缓存吗?"
|
|
72
|
+
- "能批量代替逐条吗?"
|
|
73
|
+
|
|
74
|
+
## 边界条件
|
|
75
|
+
|
|
76
|
+
### Null / Undefined 处理
|
|
77
|
+
- **缺空值检查**:在可能为 null 的对象上访问属性
|
|
78
|
+
- **truthy / falsy 混淆**:`if (value)` 而 `0` 或 `""` 是合法值
|
|
79
|
+
- **过度可选链**:`a?.b?.c?.d` 掩盖了结构性问题
|
|
80
|
+
- **null 与 undefined 不一致**:混用且无明确约定
|
|
81
|
+
|
|
82
|
+
### 空集合
|
|
83
|
+
- **未处理空数组**:代码假设数组非空
|
|
84
|
+
- **空对象边界**:在空对象上 `for...in` 或 `Object.keys`
|
|
85
|
+
- **首 / 末元素访问**:`arr[0]` 或 `arr[arr.length-1]` 未先判空
|
|
86
|
+
|
|
87
|
+
### 数值边界
|
|
88
|
+
- **除零**:除法前缺检查
|
|
89
|
+
- **整数溢出**:超出安全整数范围的大数
|
|
90
|
+
- **浮点比较**:用 `===` 而非 epsilon 比较
|
|
91
|
+
- **负值**:本不该为负的索引或计数
|
|
92
|
+
- **off-by-one**:循环边界、数组切片、分页
|
|
93
|
+
|
|
94
|
+
### 字符串边界
|
|
95
|
+
- **空字符串**:未作为边界处理
|
|
96
|
+
- **纯空白字符串**:通过 truthy 检查但实际为空
|
|
97
|
+
- **超长字符串**:无长度上限导致内存 / 展示问题
|
|
98
|
+
- **Unicode 边界**:emoji、RTL 文本、组合字符
|
|
99
|
+
|
|
100
|
+
### 需要标记的危险模式
|
|
101
|
+
```javascript
|
|
102
|
+
const name = user.profile.name // 危险:无空值检查
|
|
103
|
+
const first = items[0] // 危险:数组访问未判空
|
|
104
|
+
const avg = total / count // 危险:除法未判零
|
|
105
|
+
if (value) { ... } // 危险:truthy 检查排除了 0、""、false
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 追问
|
|
109
|
+
- "如果它是 null / undefined 会怎样?"
|
|
110
|
+
- "如果集合为空会怎样?"
|
|
111
|
+
- "这个数的合法范围是什么?"
|
|
112
|
+
- "边界值(0、-1、MAX_INT)处会怎样?"
|
|
113
|
+
|
|
114
|
+
## 严重度提示
|
|
115
|
+
|
|
116
|
+
- 会导致正确性 bug、数据损坏或生产事故的静默失败 → **P0 / P1**
|
|
117
|
+
- 性能回退、可维护性隐患、未覆盖的边界 → **P1 / P2**
|
|
118
|
+
- 局部健壮性改进 → **P3**
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# 删除候选与迭代计划清单
|
|
2
|
+
|
|
3
|
+
服务 `R-review.md` 的 **Engineering 维度**。审查 diff 引入或暴露的死代码、冗余、关停特性时读取本文。区分**现在可安全删除**与**需计划后再删**,审查阶段只给出候选与计划,**不在审查中直接删除代码**。
|
|
4
|
+
|
|
5
|
+
## 优先级
|
|
6
|
+
|
|
7
|
+
- [ ] **P0**:需立即删除(安全风险、显著成本、阻塞其他工作)
|
|
8
|
+
- [ ] **P1**:本迭代删除
|
|
9
|
+
- [ ] **P2**:进 backlog / 下个迭代
|
|
10
|
+
|
|
11
|
+
## 现在可安全删除
|
|
12
|
+
|
|
13
|
+
### 候选项:[名称 / 描述]
|
|
14
|
+
|
|
15
|
+
| 字段 | 内容 |
|
|
16
|
+
|------|------|
|
|
17
|
+
| **位置** | `path/to/file.ts:line` |
|
|
18
|
+
| **理由** | 为什么应该删除 |
|
|
19
|
+
| **证据** | 无引用、死特性开关、已废弃 API |
|
|
20
|
+
| **影响** | 无 / 低 —— 无活跃消费者 |
|
|
21
|
+
| **删除步骤** | 1. 删代码 2. 删测试 3. 删配置 |
|
|
22
|
+
| **验证** | 跑测试、确认无运行时错误、观察日志 |
|
|
23
|
+
|
|
24
|
+
## 推迟删除(需计划)
|
|
25
|
+
|
|
26
|
+
### 候选项:[名称 / 描述]
|
|
27
|
+
|
|
28
|
+
| 字段 | 内容 |
|
|
29
|
+
|------|------|
|
|
30
|
+
| **位置** | `path/to/file.ts:line` |
|
|
31
|
+
| **为何推迟** | 有活跃消费者、需迁移、需干系人签字 |
|
|
32
|
+
| **前置条件** | 特性开关关闭 2 周、遥测显示 0 使用 |
|
|
33
|
+
| **破坏性变更** | 列出 API / 契约变更 |
|
|
34
|
+
| **迁移计划** | 消费者迁移步骤 |
|
|
35
|
+
| **时间线** | 目标日期或迭代 |
|
|
36
|
+
| **负责人** | 责任人 / 团队 |
|
|
37
|
+
| **验证** | 确认可安全删除的指标(错误率、使用计数) |
|
|
38
|
+
| **回滚计划** | 出问题时如何恢复 |
|
|
39
|
+
|
|
40
|
+
## 删除前核对
|
|
41
|
+
|
|
42
|
+
- [ ] 全代码库搜索过所有引用(`rg`、`grep`)
|
|
43
|
+
- [ ] 检查过动态 / 反射式调用
|
|
44
|
+
- [ ] 确认无外部消费者(API、SDK、文档)
|
|
45
|
+
- [ ] 复核过特性开关遥测(如适用)
|
|
46
|
+
- [ ] 测试已更新 / 删除
|
|
47
|
+
- [ ] 文档已更新
|
|
48
|
+
- [ ] 已通知团队(如为共享代码)
|
|
49
|
+
|
|
50
|
+
## 严重度提示
|
|
51
|
+
|
|
52
|
+
- 引入的死代码 / 冗余本身一般是 **P3**;但当它**掩盖了正确性或安全风险**,或带来显著维护 / 成本负担时升级到 **P2 / P1**。
|
|
53
|
+
- 审查只产出删除候选与计划;实际删除交由后续 `../03-tdd/03-tdd.md` 或专门的清理任务执行。
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Multi-Axis Review Phase
|
|
2
|
+
|
|
3
|
+
## 输入
|
|
4
|
+
|
|
5
|
+
- `.speculo/dev/<change>/review-sources.md`
|
|
6
|
+
- `git diff <fixed-point>...HEAD`
|
|
7
|
+
- spec 来源文件或 `no spec available`
|
|
8
|
+
- standards 来源文件或覆盖空白说明
|
|
9
|
+
- Engineering 深度清单:同目录 `solid-checklist.md`、`security-checklist.md`、`code-quality-checklist.md`、`removal-checklist.md`
|
|
10
|
+
|
|
11
|
+
## 产物
|
|
12
|
+
|
|
13
|
+
- `.speculo/dev/<change>/review-report.md`,由 `../_templates/review-report-template.md` 填写
|
|
14
|
+
|
|
15
|
+
## 填写引导
|
|
16
|
+
|
|
17
|
+
三个维度各自独立成区,每条 finding 都要带**严重度(P0–P3)**、**文件/行或 hunk 依据**、**引用来源**,并尽量给出**可执行的修复建议**。
|
|
18
|
+
|
|
19
|
+
### Spec 维度(做对了吗)
|
|
20
|
+
|
|
21
|
+
1. 先读 spec,再读 diff。
|
|
22
|
+
2. 报告:缺失需求、范围蔓延(spec 外的实现)、看似实现但有问题的需求。
|
|
23
|
+
3. 每条引用 spec 原文。缺少 spec 时整区写 `no spec available`。
|
|
24
|
+
|
|
25
|
+
### Engineering 维度(做好了吗)
|
|
26
|
+
|
|
27
|
+
按需读取四份清单,逐项扫描 diff:
|
|
28
|
+
|
|
29
|
+
1. **SOLID 与架构**(`solid-checklist.md`):SRP/OCP/LSP/ISP/DIP 违背、代码异味;提重构时说明为何改善内聚 / 降低耦合,非平凡重构给增量计划。
|
|
30
|
+
2. **安全与可靠性**(`security-checklist.md`):注入 / XSS / SSRF / 路径穿越、认证授权、密钥泄露、竞态(TOCTOU、共享状态、DB 并发)、密码学、运行时风险;每条说明可利用性与影响。
|
|
31
|
+
3. **代码质量**(`code-quality-checklist.md`):错误处理(吞异常、异步错误)、性能(N+1、热路径昂贵操作、缓存)、边界条件(null、空集合、数值 / 字符串边界、off-by-one)。
|
|
32
|
+
4. **删除候选**(`removal-checklist.md`):死代码、冗余、关停特性;区分可安全删除与需计划,只产出候选与计划,不在审查中删代码。
|
|
33
|
+
|
|
34
|
+
### Standards 维度(合规吗)
|
|
35
|
+
|
|
36
|
+
1. 先读已记录标准(RULES、ADR、CONTRIBUTING、配置),再读 diff。
|
|
37
|
+
2. 报告违反**已成文**标准的位置,引用标准来源。
|
|
38
|
+
3. 工具已机器强制的项不重复人工检查;无成文标准时说明覆盖空白。
|
|
39
|
+
|
|
40
|
+
### 并行与隔离
|
|
41
|
+
|
|
42
|
+
- 如果可用,使用三个并行子代理分别审查 Spec、Engineering、Standards。
|
|
43
|
+
- 如果没有子代理,分三个独立小节顺序执行,不让任一维度的结论影响另一维度。
|
|
44
|
+
- 最终报告在 `## Spec`、`## Engineering`、`## Standards` 下并排呈现,可轻微清理措辞,但不要合并或重排 findings。
|
|
45
|
+
|
|
46
|
+
## 边界
|
|
47
|
+
|
|
48
|
+
- 不修复代码(review-first)。
|
|
49
|
+
- 不把三个维度混成一个优先级列表。
|
|
50
|
+
- 缺少 spec 时跳过 Spec 维度并明确写 `no spec available`;Engineering 维度始终执行。
|
|
51
|
+
- 严重度按各清单的"严重度提示"判定,不凭印象拔高或压低。
|
|
52
|
+
|
|
53
|
+
## 完成准则
|
|
54
|
+
|
|
55
|
+
- `review-report.md` 已按 Spec / Engineering / Standards 三区呈现
|
|
56
|
+
- 每条 finding 有严重度、明确依据和来源引用
|
|
57
|
+
- `.status.json` 写入 `severity_summary`,`review_status: judged`
|
|
@@ -12,28 +12,36 @@
|
|
|
12
12
|
|
|
13
13
|
## 填写引导
|
|
14
14
|
|
|
15
|
-
1. 沿用用户提供的 fixed point
|
|
15
|
+
1. 沿用用户提供的 fixed point,不自行替换为其他分支。**Worktree 模式**(`.status.json` 的 `worktree_enabled` 为真)下,若用户未另行指定,fixed point 默认取 `base_branch`,并按 `../../../skills/worktree-isolation/SKILL.md` 的 `references/audit-branch-tree.md` 用 `git log <base_branch>..<change_branch> --oneline` 记录 change 分支树**全部 commit**、`git diff <base_branch>...<change_branch>` 取全量 diff,确保审查覆盖每个 commit。
|
|
16
16
|
2. 记录 `git diff <fixed-point>...HEAD` 和 `git log <fixed-point>..HEAD --oneline`。
|
|
17
|
-
3.
|
|
17
|
+
3. 用 `git diff <fixed-point>...HEAD --stat` 评估 diff 规模并定分批策略:
|
|
18
|
+
- **无变更**:`git diff` 为空时,告知用户并询问是否改审 staged 变更或某个 commit 区间,拿到前不继续。
|
|
19
|
+
- **大 diff(> 500 行)**:先按文件 / 模块汇总,再按模块或功能分批审查。
|
|
20
|
+
- **混合关注点**:按逻辑功能分组,不只按文件顺序。
|
|
21
|
+
4. 标识关键路径:auth / 授权、支付 / 金额、数据写入、网络 / 外部调用、并发 —— 这些区域在 Engineering 维度需重点审查。
|
|
22
|
+
5. 寻找 spec 来源,顺序为:
|
|
18
23
|
- commit message 中的 issue / PR 引用
|
|
19
24
|
- 用户作为参数传入的路径
|
|
20
25
|
- `.speculo/dev/<change>/prd.md`、`slices.md`、`decision-log.md`
|
|
21
26
|
- 仓库中与分支名或功能匹配的规格文档
|
|
22
|
-
|
|
27
|
+
6. 寻找 standards 来源,常见路径包括:
|
|
23
28
|
- `.speculo/.config/RULES.md`
|
|
24
29
|
- `.speculo/.config/context/`
|
|
25
30
|
- `.speculo/.config/adr/`
|
|
26
31
|
- `AGENTS.md`、`CONTRIBUTING.md`
|
|
27
32
|
- `.editorconfig`、`eslint.config.*`、`biome.json`、`prettier.config.*`、`tsconfig.json`
|
|
28
|
-
|
|
33
|
+
7. 机器强制的标准只记录来源,不重复检查工具已覆盖的内容。
|
|
34
|
+
8. Engineering 维度不需要外部来源,但记录将依据同目录的 `solid-checklist.md`、`security-checklist.md`、`code-quality-checklist.md`、`removal-checklist.md`。
|
|
29
35
|
|
|
30
36
|
## 边界
|
|
31
37
|
|
|
32
|
-
-
|
|
38
|
+
- 不开始主观审查,先完成来源与范围收集。
|
|
33
39
|
- 找不到 spec 时不要编造;记录 `no spec available`。
|
|
40
|
+
- 找不到成文标准时记录覆盖空白,不把缺失当作"无问题"。
|
|
34
41
|
|
|
35
42
|
## 完成准则
|
|
36
43
|
|
|
37
|
-
- fixed point、diff 命令、commit
|
|
38
|
-
-
|
|
39
|
-
-
|
|
44
|
+
- fixed point、diff 命令、commit 列表、diff 规模与分批策略已记录
|
|
45
|
+
- worktree 模式下已记录 change 分支树 `base_branch..change_branch` 的全部 commit
|
|
46
|
+
- standards 来源、spec 来源、关键路径已记录
|
|
47
|
+
- `.status.json` 写入 `review_fixed_point`、`review_diff_command`、`review_axes`、`standards_sources`、`spec_sources`,`review_status: collecting`
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Verdict & Next Steps Phase
|
|
2
|
+
|
|
3
|
+
## 输入
|
|
4
|
+
|
|
5
|
+
- `.speculo/dev/<change>/review-report.md`(三维度 findings)
|
|
6
|
+
- `.status.json` 的 `severity_summary`
|
|
7
|
+
|
|
8
|
+
## 产物
|
|
9
|
+
|
|
10
|
+
- `.speculo/dev/<change>/review-verdict.md`,由 `../_templates/review-verdict-template.md` 填写
|
|
11
|
+
|
|
12
|
+
## 填写引导
|
|
13
|
+
|
|
14
|
+
1. **严重度汇总**:统计三维度合计的 P0 / P1 / P2 / P3 计数。
|
|
15
|
+
2. **整体裁决**,依据汇总给出其一:
|
|
16
|
+
- `REQUEST_CHANGES`:存在任何 P0,或存在合并前应修复的 P1
|
|
17
|
+
- `COMMENT`:无 P0/P1,但有值得跟进的 P2/P3
|
|
18
|
+
- `APPROVE`:无阻断项,至多少量 P3
|
|
19
|
+
3. **Clean-review 诚实声明**(无论是否发现问题都必须写):
|
|
20
|
+
- **检查了什么**:覆盖到的文件 / 模块 / 维度(worktree 模式下须确认已覆盖 `base_branch..change_branch` 的每个 commit)
|
|
21
|
+
- **未覆盖什么**:未审的区域及原因(如 "未验证数据库迁移"、"大 diff 仅抽样审查了 X 模块")
|
|
22
|
+
- **残留风险**:建议补充的测试或后续验证
|
|
23
|
+
4. **后续选项**:向用户给出明确选项并等待选择,未经确认不实施修复:
|
|
24
|
+
1. 修复全部
|
|
25
|
+
2. 仅修复 P0 / P1
|
|
26
|
+
3. 修复指定项(由用户点名)
|
|
27
|
+
4. 不改动,审查到此为止
|
|
28
|
+
5. 用户选择修复时,移交 `../03-tdd/03-tdd.md` 的红绿重构循环执行,并在该 change 内继续维护状态。
|
|
29
|
+
|
|
30
|
+
## 边界
|
|
31
|
+
|
|
32
|
+
- 不修复代码;本阶段只裁决与确认。
|
|
33
|
+
- 不夸大或弱化裁决;裁决必须与 `severity_summary` 一致。
|
|
34
|
+
- 不把"未覆盖"伪装成"无问题"。
|
|
35
|
+
|
|
36
|
+
## 完成准则
|
|
37
|
+
|
|
38
|
+
- `review-verdict.md` 含整体裁决、严重度汇总、clean-review 三项声明、后续选项
|
|
39
|
+
- `review-verdict.md` 无残留 `[TODO:]`
|
|
40
|
+
- `.status.json` 写入 `review_verdict`,`review_status: completed`
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# 安全与可靠性清单
|
|
2
|
+
|
|
3
|
+
服务 `R-review.md` 的 **Engineering 维度**。审查 diff 是否引入安全漏洞或运行时风险时读取本文。每条命中都要同时说明**可利用性(exploitability)**与**影响(impact)**,并按下方"严重度提示"定级。
|
|
4
|
+
|
|
5
|
+
## 输入 / 输出安全
|
|
6
|
+
|
|
7
|
+
- **XSS**:不安全的 HTML 注入、`dangerouslySetInnerHTML`、未转义模板、`innerHTML` 赋值
|
|
8
|
+
- **注入**:通过字符串拼接或模板串构造的 SQL / NoSQL / 命令 / GraphQL 注入
|
|
9
|
+
- **SSRF**:用户可控 URL 在无 allowlist 校验下访问内部服务
|
|
10
|
+
- **路径穿越**:用户输入未经清洗进入文件路径(`../` 攻击)
|
|
11
|
+
- **原型污染**:JavaScript 中用用户输入做不安全的对象合并(`Object.assign`、带用户输入的展开)
|
|
12
|
+
|
|
13
|
+
## 认证 / 授权(AuthN/AuthZ)
|
|
14
|
+
|
|
15
|
+
- 读写操作缺少租户或归属(ownership)校验
|
|
16
|
+
- 新端点没有 auth guard 或 RBAC 约束
|
|
17
|
+
- 信任客户端传入的 role / flag / ID
|
|
18
|
+
- 越权访问(IDOR —— 不安全的直接对象引用)
|
|
19
|
+
- 会话固定或弱会话管理
|
|
20
|
+
|
|
21
|
+
## JWT 与令牌安全
|
|
22
|
+
|
|
23
|
+
- 算法混淆攻击(期望 `RS256` 却接受 `none` 或 `HS256`)
|
|
24
|
+
- 弱密钥或硬编码密钥
|
|
25
|
+
- 缺少 `exp` 过期或未校验
|
|
26
|
+
- 敏感数据放进 JWT payload(token 是 base64,不是加密)
|
|
27
|
+
- 不校验 `iss`(签发者)或 `aud`(受众)
|
|
28
|
+
|
|
29
|
+
## 密钥与 PII
|
|
30
|
+
|
|
31
|
+
- API key、token、凭据出现在代码 / 配置 / 日志
|
|
32
|
+
- 密钥进入 git 历史,或环境变量暴露给客户端
|
|
33
|
+
- 过度记录 PII 或敏感载荷
|
|
34
|
+
- 错误信息缺少数据脱敏
|
|
35
|
+
|
|
36
|
+
## 供应链与依赖
|
|
37
|
+
|
|
38
|
+
- 未锁版本的依赖,允许恶意更新
|
|
39
|
+
- 依赖混淆(私有包名冲突)
|
|
40
|
+
- 从不可信源或 CDN 引入且无完整性校验
|
|
41
|
+
- 含已知 CVE 的过期依赖
|
|
42
|
+
|
|
43
|
+
## CORS 与响应头
|
|
44
|
+
|
|
45
|
+
- 过宽的 CORS(带 credentials 时 `Access-Control-Allow-Origin: *`)
|
|
46
|
+
- 缺少安全响应头(CSP、X-Frame-Options、X-Content-Type-Options)
|
|
47
|
+
- 暴露内部头或堆栈信息
|
|
48
|
+
|
|
49
|
+
## 运行时风险
|
|
50
|
+
|
|
51
|
+
- 无界循环、递归调用或大块内存缓冲
|
|
52
|
+
- 外部调用缺少超时、重试或限流
|
|
53
|
+
- 请求路径上的阻塞操作(async 上下文中的同步 I/O)
|
|
54
|
+
- 资源耗尽(文件句柄、连接、内存)
|
|
55
|
+
- ReDoS(正则表达式拒绝服务)
|
|
56
|
+
|
|
57
|
+
## 密码学
|
|
58
|
+
|
|
59
|
+
- 弱算法(用于安全目的的 MD5、SHA1)
|
|
60
|
+
- 硬编码 IV 或 salt
|
|
61
|
+
- 只加密不认证(ECB 模式、无 HMAC)
|
|
62
|
+
- 密钥长度不足
|
|
63
|
+
|
|
64
|
+
## 竞态条件(Race Conditions)
|
|
65
|
+
|
|
66
|
+
竞态是引发间歇性故障和安全漏洞的隐蔽缺陷,重点关注:
|
|
67
|
+
|
|
68
|
+
### 共享状态访问
|
|
69
|
+
- 多线程 / 协程 / 异步任务无同步地访问共享变量
|
|
70
|
+
- 并发修改全局状态或单例
|
|
71
|
+
- 无正确加锁的惰性初始化(double-checked locking 问题)
|
|
72
|
+
- 在并发上下文使用非线程安全集合
|
|
73
|
+
|
|
74
|
+
### 先检查后行动(TOCTOU)
|
|
75
|
+
- `if (exists) then use` 无原子操作
|
|
76
|
+
- `if (authorized) then perform`,而授权可能变化
|
|
77
|
+
- 文件存在性检查后再做文件操作
|
|
78
|
+
- 余额检查后扣减(金融操作)
|
|
79
|
+
- 库存检查后下单
|
|
80
|
+
|
|
81
|
+
### 数据库并发
|
|
82
|
+
- 缺少乐观锁(`version` 列、`updated_at` 校验)
|
|
83
|
+
- 缺少悲观锁(`SELECT FOR UPDATE`)
|
|
84
|
+
- 无事务隔离的 read-modify-write
|
|
85
|
+
- 非原子的计数器自增(应用 `UPDATE SET count = count + 1`)
|
|
86
|
+
- 并发插入触发唯一约束冲突
|
|
87
|
+
|
|
88
|
+
### 分布式系统
|
|
89
|
+
- 共享资源缺少分布式锁
|
|
90
|
+
- 领导选举竞态
|
|
91
|
+
- 缓存失效竞态(写后读到脏数据)
|
|
92
|
+
- 缺少正确排序的事件顺序依赖
|
|
93
|
+
- 集群操作的脑裂
|
|
94
|
+
|
|
95
|
+
### 需要标记的危险模式
|
|
96
|
+
```
|
|
97
|
+
# 危险模式:
|
|
98
|
+
if not exists(key): # TOCTOU
|
|
99
|
+
create(key)
|
|
100
|
+
|
|
101
|
+
value = get(key) # read-modify-write
|
|
102
|
+
value += 1
|
|
103
|
+
set(key, value)
|
|
104
|
+
|
|
105
|
+
if user.balance >= amount: # 先检查后行动
|
|
106
|
+
user.balance -= amount
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 追问
|
|
110
|
+
- "两个请求同时进入这段代码会怎样?"
|
|
111
|
+
- "这个操作是原子的,还是可被打断?"
|
|
112
|
+
- "这段代码访问了哪些共享状态?"
|
|
113
|
+
- "高并发下它的行为如何?"
|
|
114
|
+
|
|
115
|
+
## 数据完整性
|
|
116
|
+
|
|
117
|
+
- 缺少事务、部分写入或状态更新不一致
|
|
118
|
+
- 持久化前校验薄弱(类型强转问题)
|
|
119
|
+
- 可重试操作缺少幂等性
|
|
120
|
+
- 并发修改导致的丢失更新(lost update)
|
|
121
|
+
|
|
122
|
+
## 严重度提示
|
|
123
|
+
|
|
124
|
+
- 可被利用的安全漏洞、数据丢失风险、敏感信息泄露 → **P0**(阻断合并)
|
|
125
|
+
- 需特定条件触发但影响显著的安全 / 可靠性缺陷 → **P1**
|
|
126
|
+
- 纵深防御缺口、低影响硬化项 → **P2**
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# SOLID 与架构异味清单
|
|
2
|
+
|
|
3
|
+
服务 `R-review.md` 的 **Engineering 维度**。在审查 diff 的设计质量时读取本文,按 SOLID 与常见代码异味定位结构性问题,并对照下方"严重度提示"给出 P0–P3。
|
|
4
|
+
|
|
5
|
+
## SOLID 异味提示
|
|
6
|
+
|
|
7
|
+
### SRP(单一职责)
|
|
8
|
+
|
|
9
|
+
- 一个文件承担互不相关的关注点(如 HTTP + DB + 领域规则混在一起)
|
|
10
|
+
- 大类 / 大模块内聚低,存在多个变更原因
|
|
11
|
+
- 函数编排了大量互不相关的步骤
|
|
12
|
+
- 知道太多系统细节的 God Object
|
|
13
|
+
- **追问**:"这个模块只因为哪一个原因而改变?"
|
|
14
|
+
|
|
15
|
+
### OCP(开闭)
|
|
16
|
+
|
|
17
|
+
- 新增一种行为要修改多个 switch / if 分支
|
|
18
|
+
- 功能增长需要改核心逻辑,而不是扩展点
|
|
19
|
+
- 没有 plugin / strategy / hook 等变化点
|
|
20
|
+
- **追问**:"不动现有代码能加一个新变体吗?"
|
|
21
|
+
|
|
22
|
+
### LSP(里氏替换)
|
|
23
|
+
|
|
24
|
+
- 子类检查具体类型,或对基类方法抛异常
|
|
25
|
+
- 重写方法弱化了前置条件、强化了后置条件
|
|
26
|
+
- 子类忽略或空实现父类行为
|
|
27
|
+
- **追问**:"调用方无感知地替换任意子类能成立吗?"
|
|
28
|
+
|
|
29
|
+
### ISP(接口隔离)
|
|
30
|
+
|
|
31
|
+
- 接口方法很多,实现者大多用不到
|
|
32
|
+
- 调用方为很窄的需求依赖很宽的接口
|
|
33
|
+
- 接口方法出现空 / 桩实现
|
|
34
|
+
- **追问**:"每个实现者都用到了全部方法吗?"
|
|
35
|
+
|
|
36
|
+
### DIP(依赖倒置)
|
|
37
|
+
|
|
38
|
+
- 高层逻辑直接依赖具体 IO、存储或网络类型
|
|
39
|
+
- 硬编码实现,而不是抽象或注入
|
|
40
|
+
- import 链把业务逻辑耦合到基础设施
|
|
41
|
+
- **追问**:"不改业务逻辑能换掉实现吗?"
|
|
42
|
+
|
|
43
|
+
## 常见代码异味(SOLID 之外)
|
|
44
|
+
|
|
45
|
+
| 异味 | 信号 |
|
|
46
|
+
|------|------|
|
|
47
|
+
| **Long method** | 函数 > 30 行,多层嵌套 |
|
|
48
|
+
| **Feature envy** | 方法用别的类的数据多过用自己的 |
|
|
49
|
+
| **Data clumps** | 同一组参数反复一起传递 |
|
|
50
|
+
| **Primitive obsession** | 用 string / number 代替领域类型 |
|
|
51
|
+
| **Shotgun surgery** | 一处改动要散落地改多个文件 |
|
|
52
|
+
| **Divergent change** | 一个文件因多个无关原因反复改 |
|
|
53
|
+
| **Dead code** | 不可达或从不被调用的代码(详见 `removal-checklist.md`) |
|
|
54
|
+
| **Speculative generality** | 为假想的未来需求做的抽象 |
|
|
55
|
+
| **Magic numbers/strings** | 没有命名常量的硬编码值 |
|
|
56
|
+
|
|
57
|
+
## 重构启发式
|
|
58
|
+
|
|
59
|
+
1. **按职责拆,而不是按体积拆** —— 小文件也可能违反 SRP
|
|
60
|
+
2. **需要时才引入抽象** —— 等到第二个用例再抽
|
|
61
|
+
3. **重构保持增量** —— 先隔离行为再搬移
|
|
62
|
+
4. **先保行为** —— 重构前先有测试兜底
|
|
63
|
+
5. **按意图命名** —— 命名困难往往说明抽象有问题
|
|
64
|
+
6. **组合优于继承** —— 继承带来强耦合
|
|
65
|
+
7. **让非法状态不可表达** —— 用类型固化不变量
|
|
66
|
+
|
|
67
|
+
## 严重度提示
|
|
68
|
+
|
|
69
|
+
- 导致正确性问题或架构性返工的结构缺陷 → **P1**
|
|
70
|
+
- 明显但局部的 SOLID 违背、可维护性隐患 → **P2**
|
|
71
|
+
- 命名、轻微异味、可选改进 → **P3**
|
|
72
|
+
|
|
73
|
+
> 提出重构时,必须说明它**为什么**改善内聚 / 降低耦合,并给出最小、安全的拆分;非平凡重构给增量计划,不给大重写。
|