代码审查标准与流程

2026-10-09建立。每一条规则都来自实测量化,不是凭空定的。
复现:python3 scripts/code_quality_scan.py

零、为什么要有这份文档

昨晚(10-08)一整晚的实测暴露了一件事:这个项目最贵的不是写代码,是漏。

实际发生的事漏掉的代价
subpackages 少个字母,11 个页面 3.8 天打不开无人察觉;小齐独立数页面数才发现
详情页编造文案「神山脚下在地工坊手作」上线客人看到商品介绍是编的
情报包显示「1晚」+ 要求选入住日期交付给客人的是错的信息
git fetch 当成 pull 用,服务器停在两天前别人据此质疑了一个已修好的问题
「主包 0.925MB」是推算不是实测没落地的东西报表上是绿的

⇒ 审查的第一目标不是"写得漂亮",是"拦住上面这类东西"。


一、代码规模实况(定标准的依据)

项数量
后端 Python139 文件 / 44,206 行
C 端 TypeScript96 文件 / 10,710 行
超 1000 行的文件10 个(最大 miniapp_orders.py 2035 行)
后端测试文件6 个
C 端测试文件0 个 🔴
CI 配置无 🔴
已有门禁脚本20+ 个(scripts/*.py),但没接进任何自动流程
git hook.githooks/pre-commit 存在,但 core.hooksPath 未设置 ⇒ 不生效

二、审查分级:按「能不能拦住事故」定,不按「好不好看」定

🔴 BLOCKER —— 一律不许合并

#规则为什么要这条(对应昨晚/实测的真实教训)
B1SQL 禁止拼接用户可控值,必须用 $1 占位符实测 91 处 f-string 拼 SQL(demand.py、guides.py、admin_goods.py…)。多数 where_sql 是代码自己拼的片段(值走参数化),但必须逐个判"拼接内容是否可控",不能一概放过
B2任何占位/兜底文案不得编造业务事实「神山脚下在地工坊手作」是上线前占位、上线忘清⇒ 客人看到假信息。宁可少一块,不给假信息
B3未接通的功能不许摆可点入口巡检抓到 3 处(语音导览「测试」按钮、护照「继续领取」、评价提交)⇒ 摆一个点不动的入口比不做更糟
B4配置键名/字段名必须机器校验subpackages vs subPackages:JSON 合法、编译不报错、文件全在,只有脚本能发现
B5交付前必须真机/真服务验证,不能只看代码「真机验证通过」与「线上生效」是两件事——C端缺陷只有上传小程序才生效
B6金额必须用整数分计算,禁止浮点微信支付踩过:0.1 + 0.2 类问题
B7禁止裸 except: / except: pass静默吞错让故障无法定位

🟠 HIGH —— 合并前必须处理或明确豁免

#规则依据
H1改动必须真机/真接口验证并附证据(截图/响应/日志)昨晚 5 处漏改,全是"改完就以为好了"
H2改一处要扫全部(同类型页面/接口)修 4 个详情页时顺手造了 2 处新问题
H3指标必须标注实测 vs 推算「主包 0.925MB」是推算
H4查历史必须用 git log --first-parent混入分支提交会得到错误时间线
H5查远端状态必须用 ls-remote/fetch,不能用本地缓存的 origin/xxx我差点报"远端没C 端"(实际有456 个文件)
H6单文件 >800 行要拆分10 个文件超 1000 行,最大 2035 行
H7删除分支前必须验「已推送 + 已并入主线」7 个未推送分支里3 个内容仅存本地

🟡 MEDIUM —— 建议处理

💭 NIT —— 有余力再说

命名、注释、文件组织等风格问题——只要不误导人,不必在审查里争论。


三、流程:三道关,每道都机器判定,人只做机器判不了的事

① 提交前(本地,pre-commit)── 机器秒级拦截
       ↓
② 合并前(PR/复核)──── 人 + 机器报告
       ↓
③ 部署后(线上抽验)──── 真机/真服务

第 ① 关:pre-commit(本地,<5 秒)

先决条件:git config core.hooksPath .githooks(现在没设置,等于没生效)

# ① 类型/语法(注意:node --check 对 .ts 无效,必须用 esbuild)
npx esbuild@0.24.0 <改动的.ts> --outfile=/dev/null
python3 -m py_compile <改动的.py>

# ② 质量扫描(只扫改动的文件,秒级)
python3 scripts/code_quality_scan.py --changed

# ③ app.json 页面注册(这个坑太隐蔽,每次必查)
python3 scripts/check_app_json_pages.py

规则:BLOCKER 一项不过 ⇒ 不许提交(不是"提醒",是拦住)。

第 ② 关:合并前复核

复核者要做的三件事(顺序不能乱):

  1. 先跑机器报告:code_quality_scan.py + check_app_json_pages.py
  2. 自己核「改动的实情」:不采信提交信息里的自报。独立复核命令本身要先确认看的是哪份文件
  3. 对照 B1–B7 逐条打勾,写清哪些过了、哪些豁免、为什么

复核者必须做「反证」:

第 ③ 关:部署后

目标手段
后端部署后读容器内文件指纹/特征码(不是看仓库 HEAD)
C 端只有上传小程序才生效;「真机验证通过 ≠ 线上生效」
页面数/配置真机逐页打开 + 拼图对比(sweep_all_pages.py + make_contact_sheet.py)

四、审查者的三条纪律

1. 不采信自报,独立复核

提交信息说"已修复"不算数。但也不能假设对方错 —— 先确认你看的是哪一份:

昨晚小齐看到「29 页、无分包」,我看到「18 + 11」。
真相:我 22:21 只 fetch 没 pull,服务器停在两天前。两个人都没错,是信息不同步。

2. 范围不能自己划

义父:「你只是习惯在既定的范围内查问题」——
我只查 4 个"详情页",于是 11 个分包页从未被打开过。
⇒ 用客观清单驱动(app.json 全文、目录遍历),不靠"我以为该看哪里"。

3. 🔴 指标必须标「实测」还是「推算」

「没落地的东西,报表上是绿的。」——"主包 0.925MB"是按预期结构算的,分包当时根本没生效。

五、可复用的自证机制(本项目的核心资产)

任何自动检查,先证明它自己是对的,再信它的结论。

# scripts/code_quality_scan.py 里已内置
'selfcheck':     ('f"SELECT * FROM t WHERE id={x}"', True),   # 必须抓到
'selfcheck_neg': ('sql = "SELECT * FROM t WHERE id=$1"', False), # 必须不抓

实测战绩:这条机制在建立当天就抓到我自己写的 except 规则有 bug(多行样本配单行正则,恒不命中)。若没这关,它会报「0 处裸 except」——一个假绿灯。

⇒ 规则:

  1. 每条规则配正/负样本,自证不通过则整个报告不可信(脚本会退出码 2 拒绝出结论)
  2. 检查脚本本身要有 -test 模式
  3. 🔴 扫不出来的只能说"未发现",不能说"不存在"

六、落地顺序(按性价比,不按理想)

阶段动作收益
第1 周① 接上 core.hooksPath ② code_quality_scan.py --changed 进 pre-commit ③ check_app_json_pages.py 进 pre-commit拦住 B4 类静默故障(昨晚那 3.8 天)
第 2 周④ 91 处 f-string SQL 逐个判「拼接内容是否可控」,可控的改参数化关闭 B1
第 3-4 周⑤ 补 C 端测试(当前 0 个)⑥ 超 1000 行的 10 个文件各抽 1 处拆分降低 H6
持续⑦ 每次线上事故回头补一条规则(昨晚已补 7 条)规则来自真实教训,不是想象

七、当前实况(2026-10-09 基线)

🔴 BLOCKER:  SQL f-string 拼接  94 处(其中 91 处需人工判可控性)
🟠 HIGH:     SQL + 拼接        5 处
🟡 MEDIUM:   as any          256 处
💭 NIT:      console.log 2 / TODO 5
✅ 裸 except 0 / except-pass 0 / @ts-ignore 0 / 非空断言 0

C 端测试 0 个 · CI 无 · pre-commit 未生效

⇒ 这三条是当前最大的结构性缺口。