关于 justify
用于审查已完成代码变更的技能,重点识别偏向新增代码的做法,并要求逐项说明理由。它还检查测试逻辑、设计不变量及变更是否有证据支持。
主要功能
- 01计算增量偏差分数与风险区间
- 02检查测试逻辑是否被修改
- 03评估变更的必要性与最小性
- 04识别设计不变量冲突
- 05为每项变更生成理由报告
- 06记录需权衡的设计决策
适用场景
- 01提交代码前审查实现变更
- 02在拉取请求前检查测试修改
- 03评估新增抽象或兼容层是否必要
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ athola/ claude-night-market --skill justify安装后在 Claude Code 中输入/justify确认已加载。
详细介绍
修复问题所需的最小改动, 才是最安全、适合合并的改动。 添加代码很容易。让代码不再必要, 才是工程。
论证
添加偏差问题
AI 模型经过训练,旨在提供帮助,因此会系统性地偏向于添加代码,而不是 修复根本原因:
| AI 的默认行为 | 正确做法 |
|---|---|
| 添加变通方案 | 修复根本原因 |
| 修改测试预期 | 修复实现 |
| 新建辅助工具 | 使用已有工具 |
| 添加错误处理 | 防止错误发生 |
| 添加兼容性垫片 | 删除旧代码 |
| 用 try/catch 包装 | 修复异常来源 |
这项技能会审查改动是否存在这些模式, 并要求对每一项给出明确的理由。
何时使用
- 完成实现工作后
- 提交或创建 PR 前
- 检查自己的改动质量时
- scope-guard 标记为红色/黄色区域时
何时不要使用
- 编写代码之前,因为这项技能审查的是已完成的工作(请使用
imbue:karpathy-principles) - 判断某个功能是否属于范围时(请使用
imbue:scope-guard)
审查流程
第 1 步:收集差异
# Determine base branch
base=$(git merge-base master HEAD 2>/dev/null \
|| git merge-base main HEAD 2>/dev/null)
# Get change statistics
git diff "$base" --stat
git diff "$base" --shortstat
git diff "$base" --diff-filter=A --name-only # new files
git diff "$base" --diff-filter=M --name-only # modified files
git diff "$base" --diff-filter=D --name-only # deleted files
第 2 步:计算添加偏差分数
为每个维度打分 0-3(0 = 无偏差,3 = 偏差严重):
| 信号 | 权重 | 衡量方式 |
|---|---|---|
| 行数比例 | 2x | additions / max(deletions, 1) |
| 新文件 | 2x | --diff-filter=A 的计数 |
| 测试逻辑改动 | 3x | 测试断言/预期差异 |
| 新抽象 | 1x | 新类、函数、模块 |
| 变通方案模式 | 2x | 新增的 try/catch、if/else 守卫 |
行数比例评分:
| 比例 | 分数 | 说明 |
|---|---|---|
| < 2:1 | 0 | 改动均衡 |
| 2:1 到 5:1 | 1 | 轻微偏向添加 |
| 5:1 到 10:1 | 2 | 很可能存在添加偏差 |
| > 10:1 | 3 | 添加偏差严重 |
汇总分数:
bias_score = sum(signal_score * weight) / sum(weights)
| 汇总分数 | 区域 | 操作 |
|---|---|---|
| 0.0 - 0.5 | 绿色 | 继续 |
| 0.5 - 1.5 | 黄色 | 逐项说明每个信号 |
| 1.5 - 2.5 | 红色 | 重新考虑方案 |
| 2.5+ | 停止 | 方案很可能不正确 |
第 3 步:检查是否遵守铁律
铁律指出:由测试驱动实现,而不是反过来。检查是否存在违规:
# Find test files that were modified
git diff "$base" --name-only | rg "test_|_test\.|spec\." \
|| git diff "$base" --name-only | grep -E "test_|_test\.|spec\."
# For each modified test file, check what changed
git diff "$base" -- <test_file> | rg "^[-+].*assert|^[-+].*expect|^[-+].*should"
违规模式(测试逻辑遭到篡改):
- 断言值被修改(预期输出被改动)
- 测试用例被删除或注释掉
- 添加了
@skip或@pytest.mark.skip - 错误预期被放宽(使用宽泛的异常类型)
- Mock 返回值被修改以匹配新行为
- 测试被重命名,不再描述原有行为
每项违规都需要明确说明理由:
“我修改了这个测试断言,因为 需求发生了变化,而不是因为我的实现 无法满足原始需求。”
如果需求没有变化,测试就不应该改变。 应改为修复实现。
第 4 步:最小干预分析
对于每个改动过的文件,请回答:
-
这项改动有必要吗? 不修改这个文件能否实现目标?
-
这是最小改动吗? 能否用更少的代码行实现相同结果?
-
这项改动增加了还是减少了复杂度? 新函数、类或控制流都意味着增加了 需要说明理由的复杂度。
-
是否存在优先删减的替代方案? 能否通过删除代码来解决问题,而不是 添加代码?
步骤 4.5:不变量影响分析
改动可以很小,却仍可能造成灾难性后果, 如果它悄然改写了一个承载关键设计决策。 对于每个变更文件,检查它是否涉及设计 不变量:
不变量包括:
- 架构模式(模块边界、分层 隔离、数据流方向)
- 数据结构选择(为何用映射而非列表,为何 采用规范化而非反规范化)
- API 契约(公共接口、协议格式)
- 错误处理策略(快速失败还是恢复)
- 并发模型(单线程假设、 Actor 模型、无共享)
检测启发式:
# Check for structural changes (new modules, moved
# boundaries, changed interfaces)
git diff "$base" --name-only | rg "(interface|abstract|base|core|types|schema|model)" \
|| git diff "$base" --name-only | grep -E "(interface|abstract|base|core|types|schema|model)"
# Check for pattern-breaking changes
git diff "$base" -U5 | rg "(TODO.*refactor|HACK|WORKAROUND|XXX)" \
|| git diff "$base" -U5 | grep -E "(TODO.*refactor|HACK|WORKAROUND|XXX)"
检测到不变量冲突时:
不要悄然自行选择解决方案。向人类呈现以下三个 选项:
| 选项 | 说明 | 适用情形 |
|---|---|---|
| 保留 | 不添加此功能;该不变量能带来长期收益 | 不变量简化了许多事情;功能只是锦上添花 |
| 分层叠加 | 以不够优雅的方式在其上添加功能 | 功能确有必要;不变量仍有价值;可以接受不完美 |
| 修订 | 改变不变量本身 | 新的认知确实推翻了原始决策 |
添加到论证报告:
### Invariant Impact: NONE / DETECTED
[If DETECTED:]
- **Invariant**: [name the design decision]
- **Conflict**: [what change clashes with it]
- **Option chosen**: Preserve / Layer / Revise
- **Justification**: [why this option, not the others]
- **Human reviewed**: YES / NO — if NO, flag as
requiring review before merge
**风险累积警告:**糟糕的不变量决策 会不断累积。如果此分支有多项不变量 修订,应将整个分支标记为需要架构 审查。每次悄然更改不变量,都会成倍增加 代码库无法挽救的概率。
步骤 5:生成论证报告
输出一份结构化报告:
## Justification Report
**Branch**: feature/xyz
**Base**: master
**Delta**: +N/-M lines, X files changed
### Additive Bias Score: X.X (ZONE)
| Signal | Score | Detail |
|--------|-------|--------|
| Line ratio | N | +A/-D = R:1 |
| New files | N | [list] |
| Test changes | N | [list] |
| New abstractions | N | [list] |
| Workarounds | N | [list] |
### Iron Law Compliance: PASS/FAIL
[List any test logic modifications with justification]
### Change-by-Change Justification
#### file.py (+N/-M)
- **What**: [description]
- **Why**: [root cause this addresses]
- **Alternatives considered**: [what else could work]
- **Why this is minimal**: [why fewer changes won't work]
#### test_file.py (+N/-M)
- **What**: [description]
- **Justification**: [why test logic changed, if it did]
- **Iron Law status**: PASS/VIOLATION
### Risk Assessment
| Factor | Rating |
|--------|--------|
| Lines changed | LOW/MED/HIGH |
| Files touched | LOW/MED/HIGH |
| Test modifications | NONE/JUSTIFIED/VIOLATION |
| New abstractions | NONE/JUSTIFIED/UNNECESSARY |
| Overall merge risk | LOW/MED/HIGH |
### Recommendations
[List any changes that should be reconsidered,
simpler alternatives, or unnecessary additions]
决策权重
评估相互竞争的方案时,应考虑 以下因素及其权重:
| 因素 | 权重 | 理由 |
|---|---|---|
| 更少的代码行改动 | 高 | 风险更低,更易审查 |
| 不新增文件 | 高 | 不增加维护负担 |
| 不改动测试逻辑 | 高 | 符合铁律 |
| 修复根本原因 | 高 | 防止问题重现 |
| 删除代码 | 加分 | 缩小维护范围 |
| 增加抽象 | 扣分 | 仅在第 3 次使用时才有充分理由 |
| 增加错误处理 | 中性 | 仅在系统边界处添加 |
减法测试:接受任何改动前, 请问:“我能否通过删除代码而不是 添加代码来实现这一点?”如果可以,优先采用减法方案。
与工作证明的集成
Justify 通过变更级问责机制扩展工作证明:
- proof-of-work:“是否有效?”(证据)
- justify:“这是否是正确的做法?”(推理)
声称工作已完成前,两者都必须具备。 先运行 proof-of-work,再运行 justify。
需要标记的反模式
1. 修改测试
更改测试预期以迁就有缺陷的代码。 修复:还原测试改动,修复实现。
2. 大范围零散添加
为修复单一问题而在许多文件中添加代码。 修复:找到唯一的改动点。
3. 防御性过度设计
为实践中不可能发生的情形添加 try/catch、空值检查或验证。 修复:信任内部代码。仅在边界处进行验证。
4. 过早抽象
为单一使用场景创建辅助函数、工具类或基类。 修复:内联代码。到第 3 次使用时再抽象。
5. 兼容性垫片
添加向后兼容代码,而不是更新调用方。 修复:直接更新调用方。删除无用路径。
6. 悄然修订不变量
更改架构模式、数据结构 选择或 API 契约,却不承认 正在修订设计不变量。 修复:明确指出该不变量。向人类呈现 3 个选项 (保留、分层叠加、修订)。不要 自行作出判断:模型会倾向于训练数据的 “平均值”,而错误的不变量 决策会不断累积,最终导致代码库 无法挽救。
审查问题(来自 leyline:additive-bias-defense)
在为任何变更辩护之前,请先回答以下问题。 如果第 4 和第 5 个问题的答案不是具体证据, 则该变更没有正当理由。
- 优先级一致性:这是否偏离了 当前优先级?
- 关键性:在当前阶段实施是否至关重要?
- 简单性:是否存在更简单或更优雅的 解决方案?
- 证据:有什么证据能证明这是必需的 (而非假设)?
- 后果:如果不添加此项,会有什么问题?
举证责任倒置
默认立场是:这项新增内容不应存在。 必须由变更证明其必要性,而不是由审查者证明它没有必要。
生成论证报告(步骤 5)时,添加一个 Burden of Proof 部分:
| 变更 | 审查问题 4 的答案 | 审查问题 5 的答案 | 结论 |
|---|---|---|---|
| file.py | [证据] | [后果] | 有正当理由/需要证据/没有正当理由 |
结论为 unjustified 的变更必须在报告通过前删除或返工。
记录权衡(决策日志)
当此步骤对存在实际备选方案的决策作出定论时,应趁推理过程仍在进行,将其记录到
docs/tradeoffs.md(起草并确认):
- 如果已安装 leyline,调用
Skill(leyline:decision-journal)并附加 一条权衡记录(包含决策、权衡过的选项以及作出的牺牲;将phase设为review)。展示草稿;确认后再附加。 - 备选方案(未安装 leyline):使用文件内的
ENTRY TEMPLATE,向
docs/tradeoffs.md追加记录;分配下一个TR-NNNID。
明智的忠告
你正在做的事情是否偏离了你的优先事项? 在当前阶段实施是否至关重要? 少依赖 AI 和最初的思路。 挑战自己,做得更好,思考更优雅的实现方式或更简单的解决方案。
退出标准
- 已计算加性偏差分数,并报告其所在区间(GREEN/YELLOW/RED/STOP)。
- 铁律合规性标记为 PASS 或 FAIL;如修改了测试逻辑,须说明理由。
- 每项变更都有一个结论(justified、needs_evidence 或
unjustified);最终报告中不得保留任何
unjustified结论。 - 如检测到不变量冲突,须明确指出,并给出所选方案及人工审查标记。
- 报告通过前,须将有正当理由的非平凡新增内容记录到
docs/tradeoffs.md(或文件内模板)。
相关技能
imbue:karpathy-principles- “Surgical Changes”和 “Goal-Driven Execution”原则会从更高层次的综合视角调用此审计leyline:additive-bias-defense- 本审计详细落实的约定imbue:proof-of-work- 本审计的补充验证层(proof-of-work 会询问“是否奏效?”, justify 会询问“是否有必要存在?”)- 完整的关卡技能联邦图请参阅
docs/quality-gates.md#skill-level-quality-gate-composition