Files
gplan-2/game/tests/static_scan.sh
T
DKChan a2d6e03df2 feat(规约): 文件头≤8行白名单制第二轮立规+头注机器闸S10(2026-10-15 用户令)
code-conventions §1.4.1 换代:## 文档注释载体+8行上限+五类白名单+黑名单+写法权威参照(Google Python Style Guide §3.8 + PEP 257,GDScript 官方指南无文件头条款不自造标准);§2.1 信号契约改入发送方 ## 文档注释每信号一行、计入上限;CLAUDE.md 硬性红线同步换代;新建 tools/audit_file_headers.py(R1行数/R2日期/R3变更叙事,正例反例边界例盲测通过:恰好8行过/机制词结算批不误伤/无头注过),static_scan.sh 挂 S10。纯规则与工具零行为变更;实测存量 125 处约 90 文件,清偿批在册待发令
2026-10-15 04:45:00 +08:00

57 lines
4.0 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# tests/static_scan.sh — ADR-0004 静态扫描域 S1–S8 可执行子集
# 规则全集与动机:design/dev/architecture/adr-0004-test-carrier-and-ci.md §Decision 3
# 正式工程(core/ 存在)时执行;否则优雅跳过(工程在 game/core——2026-09-24 转正结构批后仓库根布局)。
# 纪律:新违规案例必须先补本脚本规则再修码(design/dev/code-conventions.md 缺陷-规范对照表)。
set -u
cd "$(dirname "$0")/../.." # 迭代 27 T5 修正——2026-09-24 布局迁移后 /.. 落 game/ 致 game/core 守卫恒跳过(静默空转遗产),S 闸规则路径均为仓根相对
if [ ! -d game/core ]; then
echo "[static_scan] game/core 不存在(工程未创建)——跳过,退出 0"
exit 0
fi
fail=0
# S9 — 类型闸(迭代 27 T5——code-conventions §4 机器闸:产品码无类型容器/有值返回缺类型/参数缺类型)
if python tools/audit_type_hints.py; then
echo "[static_scan] S9 ok"
else
echo "[static_scan] S9 FAIL: 类型闸存量未归零(R1/R2/R3 见上清单)"
fail=1
fi
# S10 — 文件头闸(code-conventions §1.4.1 第二轮 2026-10-15:头注 ≤8 行+日期/变更叙事黑名单)
if python tools/audit_file_headers.py; then
echo "[static_scan] S10 ok"
else
echo "[static_scan] S10 FAIL: 文件头存量见上清单(白名单清偿批在册)"
fail=1
fi
# S1/S2 — 玩法代码禁 randomize()/自建 RandomNumberGenerator/全局随机函数(绕开 RngService 的口子)
# 2026-09-24 首次实跑收敛(转正结构批):违规签名=裸 randomize/rand* 调用(实例方法 .randi() 排除)
# + RngService 之外的 RandomNumberGenerator.new();接收服务注入流的类型标注不属违规(core 五文件 15 处实证)
hits=$(grep -rnE '\brandomize[[:space:]]*\(|(^|[^.[:alnum:]_])randi[[:space:]]*\(|(^|[^.[:alnum:]_])randf[[:space:]]*\(|(^|[^.[:alnum:]_])randf_range[[:space:]]*\(' \
game/core game/presentation --include='*.gd' 2>/dev/null | grep -vE '^[^:]+:[0-9]+:[[:space:]]*#' | grep -v 'ADR-0007-exempt' | wc -l)
hits2=$(grep -rn 'RandomNumberGenerator\.new()' game/core game/presentation --include='*.gd' 2>/dev/null | grep -vc rng_service)
if [ "$hits" -gt 0 ] || [ "$hits2" -gt 0 ]; then echo "[static_scan] S1/S2 FAIL: 全局随机/RNG 自建命中 $hits+$hits2 处"; grep -rnE '\brandomize[[:space:]]*\(|(^|[^.[:alnum:]_])randi[[:space:]]*\(|(^|[^.[:alnum:]_])randf[[:space:]]*\(|(^|[^.[:alnum:]_])randf_range[[:space:]]*\(' game/core game/presentation --include='*.gd' 2>/dev/null; grep -rn 'RandomNumberGenerator\.new()' game/core game/presentation --include='*.gd' 2>/dev/null | grep -v rng_service; fail=1; else echo "[static_scan] S1/S2 ok"; fi
# S4 — core/ 禁 extends Control/Node2D、禁 .tscn preload(headless 债)
hits=$(grep -rnE 'extends[[:space:]]+(Control|Node2D)\b|\.tscn' game/core --include='*.gd' 2>/dev/null | wc -l)
if [ "$hits" -gt 0 ]; then echo "[static_scan] S4 FAIL: core 引擎/UI 依赖命中 $hits 处"; grep -rnE 'extends[[:space:]]+(Control|Node2D)\b|\.tscn' game/core --include='*.gd' 2>/dev/null; fail=1; else echo "[static_scan] S4 ok"; fi
# S3 — core/ 禁 ConfigDB 外 data 表加载(schema class_name 直引豁免)
hits=$(grep -rnE '\b(load|preload)[[:space:]]*\(|ResourceLoader\.load' core --include='*.gd' 2>/dev/null \
| grep -v 'res://tests/' | wc -l)
if [ "$hits" -gt 0 ]; then echo "[static_scan] S3 WARNING(人工复核——class_name 直引误报需逐条排除): $hits 处"; grep -rnE '\b(load|preload)[[:space:]]*\(|ResourceLoader\.load' core --include='*.gd' 2>/dev/null; fi
# TODO(正式工程落地后精化为扫描配置并升格为硬失败):
# S5 core/ 禁裸引用 ConfigDB/RngService 全局标识符(--script 模式 parse error;grep 近似误报多,需 AST 级或精确白名单)
# S6 core↔core 信号连接只许方法 Callable(禁 lambda 捕获 self);发射者禁反向引用
# S7 B2/B3/B4 API 符号命中文件 ⊆ B1 文件集(编排唯一性)
# S8 结算路径 await 零命中(B1 结算/编排文件集)
exit $fail