feat(静态扫描S13): gdstyle v0.4.0 质量规则闸引入——tools/gdstyle.toml 只开 quality/*(format/naming/order 与 S9/S10 重叠全关,lex-error 关 INT64_MIN 已知误报,no-debug-print 显式开)+tools/gdstyle_gate.py 闸件(版本钉 0.4.0 不符即红+文件|规则|消息 三元组基线差集,仅基线外新违规判红,--refresh 人工专用)+存量基线 239 条(扫描面=产品码 core/data/presentation 100 个 .gd)+static_scan.sh S13 段(防静默空转自检)+README 速查行补 S13+待办清单条目做完删除。变异验证:hud_presenter.gd 注入重复 load 红令→还原绿;基线三验(重复跑稳定/行漂移容忍/版本钉红)全过。全量域闸绿(回执 full 档,S13 实跑 ok)

This commit is contained in:
DKChan committed 2026-10-25 00:07:55 +08:00
1 parent bb63c93c4e
commit 01774323db
6 files changed
+427 -10

No files matched your search

+1 -1
View File
@@ -61,7 +61,7 @@ tests/
| `tests/run_all.gd`(单元与集成) | 公式/状态机/契约/跨系统闭环(40 套件 manifest) | 退出码+三硬闸(见下) | 新套件单跑调试;逻辑改动的最小单元复跑 |
| `tools/probe_gate.sh`(场景探针,`--click`/`--full` 两模式) | UI 可达性、可见性、状态——真实实例化场景+真实输入路径 | 探针自检+退出码 | 新增 UI 区域的配套探针直跑与断言复核 |
| `tools/render_gate.sh`(渲染 golden) | 画面基线——截图与基线图逐像素容差比对 | golden 比对脚本(依赖 PIL) | 主题/素材/排版类改动;窗口化运行,需开显示器 |
| `game/tests/static_scan.sh`(S 域) | 项目纪律:RNG 单点/core 纯度/类型标注/文件头/注释禁词/旧符号残留 | 退出码(逐规则 FAIL 行) | 改产品码前后的快速自检;新增纪律先补扫描规则再修码 |
| `game/tests/static_scan.sh`(S 域) | 项目纪律+第三方质量规则:RNG 单点/core 纯度/类型标注/文件头/注释禁词/旧符号残留;S13=gdstyle 质量规则(重复 load、循环内 await、循环内分配、不可达代码等真缺陷类,存量基线外新违规才红) | 退出码(逐规则 FAIL 行) | 改产品码前后的快速自检;新增纪律先补扫描规则再修码 |
| `tools/parity_anchor.py`(回放对拍) | 同种子下三变体逐位确定性 | 工具脚本逐位比对 | 本批触及数值/存档/RNG/结算面时;须用户批准发起 |
| 测量件(`game/sim/`,逐件见下「游离脚本台账」) | 期望/分布读数——只给读数,不判对错 | 人工读 stdout 或配套工具脚本 | 调参与归因;MC 类一律用户发起(档位表见 `sim-data/README.md`「MC 采集档位表」) |
+15
View File
@@ -236,4 +236,19 @@ else
fi
fi
# ── S13 — 第三方质量规则闸(gdstyle v0.4.0,版本钉死)──
# 规则说明自持本头注(随 S11/S12 惯例):gdstyle(github.com/atelico/gdstyle,Rust 单二进制)只开
# quality/* 抓真缺陷(重复 load/循环内 await/循环内分配/不可达代码/自比较/字典重复键/残留
# print 等),format/*/naming/*/order/* 与 S9/S10 职能重叠全关;扫描面=产品码三目录(与 S9 同口径,
# probe/sim/tests 测量面直构惯例不在面)。存量基线 tools/gdstyle_baseline.txt(文件|规则|消息 三元组
# ——消息含违规对象标识,行漂移稳定),只有基线外新违规才红;基线重生成=人工专用
# (python tools/gdstyle_gate.py --refresh),禁清基线换绿。二进制本机固定路径
# D:/code/gdstyle/gdstyle.exe(不入库),GDSTYLE_BIN 环境变量覆盖;版本与钉定版不符即红(升级须重测)。
if python tools/gdstyle_gate.py; then
echo "[static_scan] S13 ok"
else
echo "[static_scan] S13 FAIL: 基线外新违规或二进制/版本/扫描面问题(清单见上)"
fail=1
fi
exit $fail
+52
View File
@@ -0,0 +1,52 @@
# gdstyle.toml — S13 第三方质量规则闸的 gdstyle 配置(tools/gdstyle_gate.py 以 -c 显式指定本文件)
#
# 只开质量类规则:抓真缺陷(重复 load/循环内 await/循环内分配/不可达代码/自比较/字典重复键等),
# 存量进 tools/gdstyle_baseline.txt,基线外新违规才红。format/*/naming/*/order/* 与 S9/S10 职能重叠
# 全关(gdstyle 不支持通配符关停,须逐条枚举);syntax/lex-error 关——core/rng_service.gd 的
# INT64_MIN 负字面量是已知误报(Godot 自家解析器放行);type-hint 与 S9 类型闸重叠关;
# empty-function 关(合法桩形态自由)。quality/no-debug-print 本是 opt-in 默认不跑,此处显式开
# ——产品码残留 print() 属真缺陷。阈值(函数长度/参数数等)取 gdstyle 默认值:
# 改阈值=基线口径变,须随批人工重生成基线。工具版本钉 v0.4.0(闸件校验,升级须重测兼容性)。
[rules]
# ── 格式类全关(与 S9 类型闸/S10 文件头闸职能重叠)──
"format/blank-lines" = "off"
"format/boolean-operators" = "off"
"format/brace-spacing" = "off"
"format/call-paren-spacing" = "off"
"format/colon-spacing" = "off"
"format/comma-spacing" = "off"
"format/comment-spacing" = "off"
"format/double-quotes" = "off"
"format/enum-one-per-line" = "off"
"format/float-literal-zeros" = "off"
"format/large-number-underscores" = "off"
"format/max-line-length" = "off"
"format/no-tabs-as-spaces" = "off"
"format/no-unnecessary-parens" = "off"
"format/number-literals" = "off"
"format/one-statement-per-line" = "off"
"format/operator-spacing" = "off"
"format/trailing-comma" = "off"
"format/trailing-newline" = "off"
"format/trailing-whitespace" = "off"
# ── 命名类全关(命名纪律归 code-conventions 与评审面)──
"naming/class-name-pascal-case" = "off"
"naming/constant-name-screaming-case" = "off"
"naming/enum-member-screaming-case" = "off"
"naming/enum-name-pascal-case" = "off"
"naming/file-name-snake-case" = "off"
"naming/function-name-snake-case" = "off"
"naming/node-name-pascal-case" = "off"
"naming/private-underscore-prefix" = "off"
"naming/signal-name-snake-case" = "off"
"naming/signal-past-tense" = "off"
"naming/variable-name-snake-case" = "off"
# ── 排序类关(官方风格指南性质,存量过大)──
"order/class-member-order" = "off"
# ── 语法类:lex-error 关(已知误报),reserved-identifier 留守(保留字当名字=真缺陷)──
"syntax/lex-error" = "off"
# ── 质量类关两条(职能重叠),其余 quality/* 全部默认 warn 在跑 ──
"quality/type-hint" = "off"
"quality/empty-function" = "off"
"quality/no-debug-print" = "warn"
+241
View File
@@ -0,0 +1,241 @@
# gdstyle 存量基线(S13)——文件|规则|消息 三元组,每行一条;只记基线不记豁免理由。
# 重生成=人工专用:python tools/gdstyle_gate.py --refresh(禁清基线换绿;改规则口径/工具升级须随批重生成)。
game/core/action_economy.gd|quality/max-class-variables|class has 18 variables (max 15)
game/core/adventure_runner.gd|quality/max-branches|function '_apply_curio_pick' has 10 branches (max 8)
game/core/adventure_runner.gd|quality/max-branches|function '_draw_curio_candidates' has 11 branches (max 8)
game/core/adventure_runner.gd|quality/max-branches|function 'resume_adventure' has 10 branches (max 8)
game/core/adventure_runner.gd|quality/max-class-variables|class has 43 variables (max 15)
game/core/adventure_runner.gd|quality/max-file-length|file is 1050 lines long (max 1000)
game/core/adventure_runner.gd|quality/max-function-length|function '_draw_curio_candidates' is 85 lines long (max 50)
game/core/adventure_runner.gd|quality/max-function-length|function '_start_current_level' is 55 lines long (max 50)
game/core/adventure_runner.gd|quality/max-function-length|function 'resume_adventure' is 104 lines long (max 50)
game/core/adventure_runner.gd|quality/max-local-variables|function '_draw_curio_candidates' has 26 local variables (max 10)
game/core/adventure_runner.gd|quality/max-local-variables|function 'resume_adventure' has 13 local variables (max 10)
game/core/adventure_runner.gd|quality/max-public-methods|class has 23 public methods (max 20)
game/core/adventure_runner.gd|quality/max-returns|function '_apply_curio_pick' has 9 return statements (max 6)
game/core/battle_orchestrator.gd|quality/max-branches|function 'begin_battle' has 17 branches (max 8)
game/core/battle_orchestrator.gd|quality/max-branches|function 'use_treasure' has 18 branches (max 8)
game/core/battle_orchestrator.gd|quality/max-class-variables|class has 50 variables (max 15)
game/core/battle_orchestrator.gd|quality/max-file-length|file is 1302 lines long (max 1000)
game/core/battle_orchestrator.gd|quality/max-function-length|function '_place_variants' is 52 lines long (max 50)
game/core/battle_orchestrator.gd|quality/max-function-length|function 'begin_battle' is 141 lines long (max 50)
game/core/battle_orchestrator.gd|quality/max-function-length|function 'use_treasure' is 62 lines long (max 50)
game/core/battle_orchestrator.gd|quality/max-local-variables|function '_place_variants' has 14 local variables (max 10)
game/core/battle_orchestrator.gd|quality/max-local-variables|function 'begin_battle' has 16 local variables (max 10)
game/core/battle_orchestrator.gd|quality/max-local-variables|function 'use_treasure' has 11 local variables (max 10)
game/core/battle_orchestrator.gd|quality/max-nesting-depth|function '_place_variants' has nesting depth 6 (max 4)
game/core/battle_orchestrator.gd|quality/max-parameters|function '_apply_flat_row' has 7 parameters (max 5)
game/core/battle_orchestrator.gd|quality/max-parameters|function '_apply_gp_row' has 6 parameters (max 5)
game/core/battle_orchestrator.gd|quality/max-parameters|function '_apply_percent_row' has 6 parameters (max 5)
game/core/battle_orchestrator.gd|quality/max-parameters|function '_dispatch_row' has 6 parameters (max 5)
game/core/battle_orchestrator.gd|quality/max-parameters|function '_emit_row' has 8 parameters (max 5)
game/core/battle_orchestrator.gd|quality/max-parameters|function '_grant_routed' has 8 parameters (max 5)
game/core/battle_orchestrator.gd|quality/max-parameters|function '_submit_flat_hero' has 7 parameters (max 5)
game/core/battle_orchestrator.gd|quality/max-returns|function '_apply_flat_row' has 9 return statements (max 6)
game/core/battle_orchestrator.gd|quality/max-returns|function '_fx_fact' has 7 return statements (max 6)
game/core/battle_orchestrator.gd|quality/max-returns|function 'begin_battle' has 7 return statements (max 6)
game/core/battle_orchestrator.gd|quality/max-returns|function 'use_treasure' has 8 return statements (max 6)
game/core/board_generator.gd|quality/max-branches|function 'measure_inferability' has 12 branches (max 8)
game/core/board_generator.gd|quality/max-function-length|function '_attempt' is 51 lines long (max 50)
game/core/board_generator.gd|quality/max-function-length|function 'generate' is 62 lines long (max 50)
game/core/board_generator.gd|quality/max-function-length|function 'measure_inferability' is 64 lines long (max 50)
game/core/board_generator.gd|quality/max-local-variables|function 'generate' has 14 local variables (max 10)
game/core/board_generator.gd|quality/max-local-variables|function 'measure_inferability' has 13 local variables (max 10)
game/core/board_generator.gd|quality/max-nesting-depth|function 'measure_inferability' has nesting depth 5 (max 4)
game/core/board_generator.gd|quality/max-parameters|function '_finalize' has 6 parameters (max 5)
game/core/config_db.gd|quality/max-class-variables|class has 25 variables (max 15)
game/core/config_db.gd|quality/max-public-methods|class has 44 public methods (max 20)
game/core/config_db_cross_validator.gd|quality/max-branches|function 'cross_validate' has 31 branches (max 8)
game/core/config_db_cross_validator.gd|quality/max-function-length|function 'cross_validate' is 159 lines long (max 50)
game/core/config_db_cross_validator.gd|quality/max-local-variables|function 'cross_validate' has 39 local variables (max 10)
game/core/config_db_cross_validator.gd|quality/max-local-variables|function 'validate_skill_pool_links' has 11 local variables (max 10)
game/core/config_db_cross_validator.gd|quality/max-nesting-depth|function 'cross_validate' has nesting depth 6 (max 4)
game/core/config_db_resolver.gd|quality/max-branches|function '_resolve_progress' has 16 branches (max 8)
game/core/config_db_resolver.gd|quality/max-branches|function 'resolve_enemy_rowset' has 12 branches (max 8)
game/core/config_db_resolver.gd|quality/max-function-length|function '_resolve_progress' is 52 lines long (max 50)
game/core/config_db_resolver.gd|quality/max-local-variables|function '_resolve_progress' has 11 local variables (max 10)
game/core/damage_controller.gd|quality/max-branches|function '_hero_attack_ctx' has 9 branches (max 8)
game/core/damage_controller.gd|quality/max-branches|function '_hero_attack_redeem' has 10 branches (max 8)
game/core/damage_controller.gd|quality/max-class-variables|class has 19 variables (max 15)
game/core/damage_controller.gd|quality/max-function-length|function '_hero_attack_ctx' is 61 lines long (max 50)
game/core/damage_controller.gd|quality/max-function-length|function '_hero_attack_redeem' is 54 lines long (max 50)
game/core/damage_controller.gd|quality/max-local-variables|function '_hero_attack_ctx' has 16 local variables (max 10)
game/core/damage_controller.gd|quality/max-local-variables|function '_hero_attack_redeem' has 12 local variables (max 10)
game/core/damage_controller.gd|quality/max-local-variables|function '_resolve_enemy_skill' has 13 local variables (max 10)
game/core/damage_controller.gd|quality/max-parameters|function 'open_ticket' has 12 parameters (max 5)
game/core/effect_engine.gd|quality/max-branches|function 'validate_trigger_row' has 14 branches (max 8)
game/core/effect_engine.gd|quality/max-function-length|function '_cond_ok' is 52 lines long (max 50)
game/core/effect_engine.gd|quality/max-function-length|function 'rebuild' is 55 lines long (max 50)
game/core/effect_engine.gd|quality/max-local-variables|function 'validate_trigger_row' has 11 local variables (max 10)
game/core/effect_engine.gd|quality/max-nesting-depth|function '_cond_ok' has nesting depth 5 (max 4)
game/core/effect_engine.gd|quality/max-nesting-depth|function 'rebuild' has nesting depth 5 (max 4)
game/core/effect_engine.gd|quality/max-returns|function '_cond_ok' has 19 return statements (max 6)
game/core/effect_engine.gd|quality/no-else-return|unnecessary 'elif' after 'return'
game/core/level_runner.gd|quality/max-class-variables|class has 40 variables (max 15)
game/core/level_runner.gd|quality/max-file-length|file is 1013 lines long (max 1000)
game/core/level_runner.gd|quality/max-parameters|function 'start_level_external' has 8 parameters (max 5)
game/core/level_runner.gd|quality/max-public-methods|class has 54 public methods (max 20)
game/core/level_runner.gd|quality/max-returns|function '_enter_node' has 7 return statements (max 6)
game/core/meta_progression.gd|quality/max-public-methods|class has 31 public methods (max 20)
game/core/meta_progression.gd|quality/max-returns|function 'tree_can_buy' has 8 return statements (max 6)
game/core/minesweeper_rules.gd|quality/max-function-length|function '_do_dig' is 53 lines long (max 50)
game/core/node_map_generator.gd|quality/max-branches|function '_assign_types' has 11 branches (max 8)
game/core/node_map_generator.gd|quality/max-branches|function 'check_params' has 12 branches (max 8)
game/core/node_map_generator.gd|quality/max-branches|function 'validate_output' has 34 branches (max 8)
game/core/node_map_generator.gd|quality/max-function-length|function 'validate_output' is 132 lines long (max 50)
game/core/node_map_generator.gd|quality/max-local-variables|function '_add_forks' has 12 local variables (max 10)
game/core/node_map_generator.gd|quality/max-local-variables|function '_build' has 15 local variables (max 10)
game/core/node_map_generator.gd|quality/max-local-variables|function 'validate_output' has 22 local variables (max 10)
game/core/node_map_generator.gd|quality/max-nesting-depth|function '_check_fork_rules' has nesting depth 5 (max 4)
game/core/node_map_generator.gd|quality/max-returns|function 'validate_output' has 7 return statements (max 6)
game/core/reward_economy.gd|quality/max-function-length|function 'roll_board' is 54 lines long (max 50)
game/core/reward_economy.gd|quality/max-local-variables|function '_skewed_cell_rows' has 13 local variables (max 10)
game/core/reward_economy.gd|quality/max-local-variables|function 'roll_board' has 11 local variables (max 10)
game/core/save_manager.gd|quality/max-public-methods|class has 52 public methods (max 20)
game/core/save_manager.gd|quality/max-returns|function '_peek_summary_at' has 7 return statements (max 6)
game/core/save_manager.gd|quality/max-returns|function 'load_from_disk' has 8 return statements (max 6)
game/core/settlement/combat_segment.gd|quality/max-function-length|function 'run' is 83 lines long (max 50)
game/core/settlement/combat_segment.gd|quality/max-local-variables|function 'run' has 13 local variables (max 10)
game/core/settlement/grant_segment.gd|quality/max-branches|function '_judge_seal' has 14 branches (max 8)
game/core/settlement/grant_segment.gd|quality/max-branches|function 'run' has 33 branches (max 8)
game/core/settlement/grant_segment.gd|quality/max-function-length|function '_judge_seal' is 84 lines long (max 50)
game/core/settlement/grant_segment.gd|quality/max-function-length|function 'run' is 211 lines long (max 50)
game/core/settlement/grant_segment.gd|quality/max-local-variables|function '_judge_seal' has 11 local variables (max 10)
game/core/settlement/grant_segment.gd|quality/max-local-variables|function 'run' has 36 local variables (max 10)
game/core/settlement/grant_segment.gd|quality/max-nesting-depth|function '_judge_seal' has nesting depth 6 (max 4)
game/core/settlement/grant_segment.gd|quality/max-nesting-depth|function 'run' has nesting depth 6 (max 4)
game/core/status_container.gd|quality/max-nesting-depth|function 'apply_effect' has nesting depth 5 (max 4)
game/core/status_container.gd|quality/max-parameters|function '_new_instance' has 7 parameters (max 5)
game/core/status_container.gd|quality/max-returns|function 'apply_effect' has 9 return statements (max 6)
game/core/treasure_items.gd|quality/max-branches|function 'validate_use' has 11 branches (max 8)
game/core/treasure_items.gd|quality/max-nesting-depth|function 'validate_use' has nesting depth 5 (max 4)
game/core/unit_container.gd|quality/max-function-length|function 'spawn' is 81 lines long (max 50)
game/core/unit_container.gd|quality/max-local-variables|function 'spawn' has 17 local variables (max 10)
game/core/unit_container.gd|quality/max-parameters|function 'spawn' has 10 parameters (max 5)
game/data/schemas/adventure_table.gd|quality/max-class-variables|class has 44 variables (max 15)
game/data/schemas/board_gen_table.gd|quality/max-branches|function 'validate' has 20 branches (max 8)
game/data/schemas/board_gen_table.gd|quality/max-function-length|function 'validate' is 67 lines long (max 50)
game/data/schemas/board_gen_table.gd|quality/max-local-variables|function 'validate' has 16 local variables (max 10)
game/data/schemas/enemy_table.gd|quality/max-branches|function 'validate' has 32 branches (max 8)
game/data/schemas/enemy_table.gd|quality/max-function-length|function 'validate' is 116 lines long (max 50)
game/data/schemas/enemy_table.gd|quality/max-local-variables|function 'validate' has 29 local variables (max 10)
game/data/schemas/forge_table.gd|quality/max-branches|function 'validate' has 30 branches (max 8)
game/data/schemas/forge_table.gd|quality/max-function-length|function 'validate' is 95 lines long (max 50)
game/data/schemas/forge_table.gd|quality/max-local-variables|function 'validate' has 20 local variables (max 10)
game/data/schemas/level_gen_params.gd|quality/max-branches|function 'validate' has 15 branches (max 8)
game/data/schemas/level_gen_params.gd|quality/max-function-length|function 'validate' is 59 lines long (max 50)
game/data/schemas/level_gen_params.gd|quality/max-local-variables|function 'validate' has 18 local variables (max 10)
game/data/schemas/level_table.gd|quality/max-branches|function '_validate_graph' has 21 branches (max 8)
game/data/schemas/level_table.gd|quality/max-branches|function '_validate_level_nodes' has 12 branches (max 8)
game/data/schemas/level_table.gd|quality/max-function-length|function '_validate_graph' is 99 lines long (max 50)
game/data/schemas/level_table.gd|quality/max-local-variables|function '_validate_graph' has 19 local variables (max 10)
game/data/schemas/meta_table.gd|quality/max-branches|function 'validate' has 14 branches (max 8)
game/data/schemas/meta_table.gd|quality/max-function-length|function 'validate' is 60 lines long (max 50)
game/data/schemas/meta_table.gd|quality/max-local-variables|function 'validate' has 14 local variables (max 10)
game/data/schemas/meta_tree_table.gd|quality/max-branches|function 'validate' has 26 branches (max 8)
game/data/schemas/meta_tree_table.gd|quality/max-function-length|function 'validate' is 86 lines long (max 50)
game/data/schemas/meta_tree_table.gd|quality/max-local-variables|function 'validate' has 13 local variables (max 10)
game/data/schemas/meta_tree_table.gd|quality/max-nesting-depth|function 'validate' has nesting depth 5 (max 4)
game/data/schemas/reward_table.gd|quality/max-branches|function 'validate' has 30 branches (max 8)
game/data/schemas/reward_table.gd|quality/max-function-length|function 'validate' is 99 lines long (max 50)
game/data/schemas/reward_table.gd|quality/max-local-variables|function 'validate' has 20 local variables (max 10)
game/data/schemas/settlement_table.gd|quality/max-branches|function 'validate' has 16 branches (max 8)
game/data/schemas/settlement_table.gd|quality/max-class-variables|class has 18 variables (max 15)
game/data/schemas/shop_table.gd|quality/max-branches|function 'validate' has 22 branches (max 8)
game/data/schemas/shop_table.gd|quality/max-function-length|function 'validate' is 84 lines long (max 50)
game/data/schemas/shop_table.gd|quality/max-local-variables|function 'validate' has 20 local variables (max 10)
game/data/schemas/skill_table.gd|quality/max-branches|function 'validate' has 29 branches (max 8)
game/data/schemas/skill_table.gd|quality/max-function-length|function 'validate' is 80 lines long (max 50)
game/data/schemas/status_effect_table.gd|quality/max-branches|function 'validate' has 12 branches (max 8)
game/data/schemas/treasure_item_table.gd|quality/max-branches|function 'validate' has 44 branches (max 8)
game/data/schemas/treasure_item_table.gd|quality/max-function-length|function 'validate' is 147 lines long (max 50)
game/data/schemas/treasure_item_table.gd|quality/max-local-variables|function 'validate' has 26 local variables (max 10)
game/data/schemas/treasure_item_table.gd|quality/max-nesting-depth|function 'validate' has nesting depth 6 (max 4)
game/data/schemas/variation_table.gd|quality/max-branches|function 'validate' has 20 branches (max 8)
game/data/schemas/variation_table.gd|quality/max-function-length|function 'validate' is 58 lines long (max 50)
game/presentation/battle_narrator.gd|quality/max-returns|function 'bonus_card_text' has 9 return statements (max 6)
game/presentation/camp_flow_context.gd|quality/max-parameters|function '_init' has 12 parameters (max 5)
game/presentation/curio_flow_context.gd|quality/max-class-variables|class has 16 variables (max 15)
game/presentation/curio_flow_context.gd|quality/max-parameters|function '_init' has 16 parameters (max 5)
game/presentation/curio_interact_controller.gd|quality/max-class-variables|class has 18 variables (max 15)
game/presentation/hud_presenter.gd|quality/max-parameters|function '_refresh_out_of_battle' has 6 parameters (max 5)
game/presentation/hud_presenter.gd|quality/max-parameters|function 'refresh' has 8 parameters (max 5)
game/presentation/hud_presenter.gd|quality/max-parameters|function 'tune_sim_report' has 10 parameters (max 5)
game/presentation/main.gd|quality/max-class-variables|class has 49 variables (max 15)
game/presentation/main.gd|quality/max-file-length|file is 1509 lines long (max 1000)
game/presentation/main.gd|quality/max-function-length|function '_build_ui' is 189 lines long (max 50)
game/presentation/playtest_logger.gd|quality/no-debug-print|debug 'print()' call found
game/presentation/treasure_interact_controller.gd|quality/max-local-variables|function 'inventory_projection' has 11 local variables (max 10)
game/presentation/treasure_interact_controller.gd|quality/max-parameters|function '_init' has 7 parameters (max 5)
game/presentation/tune_sim_controller.gd|quality/await-in-loop|'await' used inside a loop
game/presentation/tune_sim_controller.gd|quality/max-local-variables|function 'run' has 11 local variables (max 10)
game/presentation/tune_sim_controller.gd|quality/no-debug-print|debug 'print()' call found
game/presentation/ui_assembler.gd|quality/allocation-in-loop|object allocation '.new()' inside a loop
game/presentation/ui_assembler.gd|quality/max-function-length|function 'build_start_overlay' is 83 lines long (max 50)
game/presentation/ui_assembler.gd|quality/max-local-variables|function 'build_start_overlay' has 16 local variables (max 10)
game/presentation/views/ap_bar_view.gd|quality/max-function-length|function '_init' is 69 lines long (max 50)
game/presentation/views/battle_end_overlay.gd|quality/allocation-in-loop|object allocation '.new()' inside a loop
game/presentation/views/battle_end_overlay.gd|quality/max-class-variables|class has 20 variables (max 15)
game/presentation/views/battle_end_overlay.gd|quality/max-function-length|function '_init' is 81 lines long (max 50)
game/presentation/views/battle_end_overlay.gd|quality/max-parameters|function 'open_victory' has 8 parameters (max 5)
game/presentation/views/battle_log_view.gd|quality/max-branches|function '_format_row' has 9 branches (max 8)
game/presentation/views/battle_log_view.gd|quality/max-function-length|function '_format_row' is 68 lines long (max 50)
game/presentation/views/battle_log_view.gd|quality/max-local-variables|function '_format_row' has 21 local variables (max 10)
game/presentation/views/battle_log_view.gd|quality/max-returns|function '_format_row' has 13 return statements (max 6)
game/presentation/views/battle_stage_view.gd|quality/allocation-in-loop|object allocation '.new()' inside a loop
game/presentation/views/battle_stage_view.gd|quality/max-function-length|function '_init' is 97 lines long (max 50)
game/presentation/views/battle_stage_view.gd|quality/max-returns|function '_enemy_portrait_tex' has 9 return statements (max 6)
game/presentation/views/board_cell_unit.gd|quality/max-branches|function '_draw' has 29 branches (max 8)
game/presentation/views/board_cell_unit.gd|quality/max-class-variables|class has 31 variables (max 15)
game/presentation/views/board_cell_unit.gd|quality/max-function-length|function '_draw' is 147 lines long (max 50)
game/presentation/views/board_cell_unit.gd|quality/max-local-variables|function '_draw' has 19 local variables (max 10)
game/presentation/views/board_fx_view.gd|quality/allocation-in-loop|object allocation '.new()' inside a loop
game/presentation/views/board_view.gd|quality/allocation-in-loop|object allocation '.new()' inside a loop
game/presentation/views/board_view.gd|quality/max-branches|function '_paint_cell' has 24 branches (max 8)
game/presentation/views/board_view.gd|quality/max-branches|function '_wall_tile_for' has 14 branches (max 8)
game/presentation/views/board_view.gd|quality/max-class-variables|class has 45 variables (max 15)
game/presentation/views/board_view.gd|quality/max-file-length|file is 1220 lines long (max 1000)
game/presentation/views/board_view.gd|quality/max-function-length|function '_paint_cell' is 139 lines long (max 50)
game/presentation/views/board_view.gd|quality/max-local-variables|function '_digit_ink_mode' has 12 local variables (max 10)
game/presentation/views/board_view.gd|quality/max-local-variables|function '_paint_cell' has 22 local variables (max 10)
game/presentation/views/board_view.gd|quality/max-public-methods|class has 27 public methods (max 20)
game/presentation/views/board_view.gd|quality/max-returns|function '_wall_center_tile' has 7 return statements (max 6)
game/presentation/views/board_view.gd|quality/max-returns|function '_wall_tile_for' has 15 return statements (max 6)
game/presentation/views/board_zone_view.gd|quality/max-function-length|function '_init' is 59 lines long (max 50)
game/presentation/views/camp_overlay_view.gd|quality/allocation-in-loop|object allocation '.new()' inside a loop
game/presentation/views/camp_overlay_view.gd|quality/max-class-variables|class has 19 variables (max 15)
game/presentation/views/camp_overlay_view.gd|quality/max-function-length|function '_init' is 149 lines long (max 50)
game/presentation/views/camp_overlay_view.gd|quality/max-function-length|function '_rebuild_forge' is 72 lines long (max 50)
game/presentation/views/camp_overlay_view.gd|quality/max-function-length|function '_rebuild_tree' is 61 lines long (max 50)
game/presentation/views/camp_overlay_view.gd|quality/max-function-length|function 'refresh_camp' is 61 lines long (max 50)
game/presentation/views/camp_overlay_view.gd|quality/max-local-variables|function '_init' has 28 local variables (max 10)
game/presentation/views/camp_overlay_view.gd|quality/max-local-variables|function '_rebuild_forge' has 20 local variables (max 10)
game/presentation/views/camp_overlay_view.gd|quality/max-local-variables|function '_rebuild_tree' has 21 local variables (max 10)
game/presentation/views/camp_overlay_view.gd|quality/max-local-variables|function 'refresh_camp' has 17 local variables (max 10)
game/presentation/views/curio_pick_overlay.gd|quality/max-function-length|function '_init' is 52 lines long (max 50)
game/presentation/views/curio_pick_overlay.gd|quality/max-returns|function '_icon_for_id' has 7 return statements (max 6)
game/presentation/views/debug_overlay.gd|quality/max-class-variables|class has 17 variables (max 15)
game/presentation/views/debug_overlay.gd|quality/max-function-length|function '_build' is 124 lines long (max 50)
game/presentation/views/debug_overlay.gd|quality/max-local-variables|function '_build' has 22 local variables (max 10)
game/presentation/views/hero_info_panel_view.gd|quality/allocation-in-loop|object allocation '.new()' inside a loop
game/presentation/views/hero_info_panel_view.gd|quality/max-function-length|function '_init' is 74 lines long (max 50)
game/presentation/views/hero_info_panel_view.gd|quality/max-function-length|function 'set_treasure_inventory' is 57 lines long (max 50)
game/presentation/views/hero_info_panel_view.gd|quality/max-local-variables|function 'set_treasure_inventory' has 13 local variables (max 10)
game/presentation/views/legend_overlay.gd|quality/allocation-in-loop|object allocation '.new()' inside a loop
game/presentation/views/level_map_screen.gd|quality/max-branches|function '_draw_graph' has 9 branches (max 8)
game/presentation/views/level_map_screen.gd|quality/max-class-variables|class has 21 variables (max 15)
game/presentation/views/level_map_screen.gd|quality/max-function-length|function '_draw_graph' is 78 lines long (max 50)
game/presentation/views/level_map_screen.gd|quality/max-function-length|function '_init' is 135 lines long (max 50)
game/presentation/views/level_map_screen.gd|quality/max-local-variables|function '_draw_graph' has 27 local variables (max 10)
game/presentation/views/level_map_screen.gd|quality/max-local-variables|function '_init' has 21 local variables (max 10)
game/presentation/views/settings_overlay.gd|quality/max-function-length|function '_build' is 77 lines long (max 50)
game/presentation/views/settings_overlay.gd|quality/max-local-variables|function '_build' has 13 local variables (max 10)
game/presentation/views/standee_body.gd|quality/allocation-in-loop|object allocation '.new()' inside a loop
game/presentation/views/standee_body.gd|quality/max-class-variables|class has 29 variables (max 15)
game/presentation/views/standee_body.gd|quality/max-function-length|function '_draw' is 84 lines long (max 50)
game/presentation/views/standee_body.gd|quality/max-local-variables|function '_draw' has 26 local variables (max 10)
game/presentation/views/ui_kit.gd|quality/max-local-variables|function 'beams_rect' has 13 local variables (max 10)
game/presentation/views/ui_kit.gd|quality/max-parameters|function '_init' has 6 parameters (max 5)
game/presentation/views/ui_kit.gd|quality/max-parameters|function 'bcard' has 6 parameters (max 5)
game/presentation/views/ui_kit.gd|quality/max-parameters|function 'modal_shell' has 6 parameters (max 5)
game/presentation/views/ui_kit.gd|quality/max-public-methods|class has 26 public methods (max 20)
+117
View File
@@ -0,0 +1,117 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""gdstyle_gate.py — S13 第三方质量规则闸件(game/tests/static_scan.sh 调用)
跑 gdstyle(github.com/atelico/gdstyle,Rust 单二进制,版本钉 v0.4.0)质量规则扫描,
与存量基线 tools/gdstyle_baseline.txt 做差集——只有基线外的新违规才红。
规则口径见 tools/gdstyle.toml 头注(只开 quality/*+syntax/reserved-identifier,
format/naming/order 全关)。扫描面=产品码三目录(game/core、game/data、game/presentation,
与 S9 类型闸同口径——probe/sim/tests 测量面直构惯例不在面)。
基线键=文件|规则|消息 三元组:消息含违规对象标识(如 duplicated load 的路径),行漂移稳定
(gdstyle 的 JSON 输出不含源码行文本,行号键会随编辑成片假红)。基线重生成=人工专用
(--refresh),禁在闸内自动重生成(防清基线换绿)。
二进制:本机固定路径 D:/code/gdstyle/gdstyle.exe(不入库不入包),GDSTYLE_BIN 环境变量覆盖;
版本与钉定版不符即红——升级工具须重测语法兼容性并人工重生成基线。
退出码:0=无基线外新违规;1=有新违规/二进制缺失或版本不符/扫描面为空/输出不可解析;2=用法错。
用法:python tools/gdstyle_gate.py # 闸判定
python tools/gdstyle_gate.py --refresh # 人工重生成基线(覆盖旧文件)
"""
import json
import os
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
CONFIG = ROOT / "tools" / "gdstyle.toml"
BASELINE = ROOT / "tools" / "gdstyle_baseline.txt"
SCAN_DIRS = ["game/core", "game/data", "game/presentation"]
PINNED_VERSION = "0.4.0"
DEFAULT_BIN = "D:/code/gdstyle/gdstyle.exe"
MAX_REPORT = 50
def fail(msg: str) -> int:
print("[gdstyle_gate] FAIL — %s" % msg)
return 1
def run_gate() -> int:
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
refresh = "--refresh" in sys.argv[1:]
if sys.argv[1:] and not refresh:
print("[gdstyle_gate] 用法: python tools/gdstyle_gate.py [--refresh]")
return 2
binary = os.environ.get("GDSTYLE_BIN", DEFAULT_BIN)
try:
ver = subprocess.run([binary, "--version"], capture_output=True, text=True, timeout=30)
except (FileNotFoundError, OSError):
return fail("gdstyle 二进制不可用:%s(本机固定路径,GDSTYLE_BIN 可覆盖;"
"v%s Windows 版见 github.com/atelico/gdstyle releases)" % (binary, PINNED_VERSION))
if PINNED_VERSION not in (ver.stdout or ""):
return fail("gdstyle 版本不符:钉定 v%s,实得 %r——升级工具须重测语法兼容性并人工重生成基线"
% (PINNED_VERSION, (ver.stdout or "").strip()))
face = [p for d in SCAN_DIRS for p in Path(ROOT, d).rglob("*.gd")]
if not face:
return fail("扫描面为空——%s 下零个 .gd(路径写错导致的静默空转)" % "、".join(SCAN_DIRS))
try:
proc = subprocess.run(
[binary, "check", "--format", "json", "--no-color", "-c", str(CONFIG)] + SCAN_DIRS,
capture_output=True, text=True, timeout=300, cwd=str(ROOT), encoding="utf-8",
)
except subprocess.TimeoutExpired:
return fail("gdstyle 扫描超时(300s)")
try:
findings = json.loads(proc.stdout or "[]")
except json.JSONDecodeError:
return fail("gdstyle 输出不可解析为 JSON(stderr 头部:%r)" % (proc.stderr or "")[:200])
keys = set()
for f in findings:
if not isinstance(f, dict) or "rule" not in f:
continue
file_path = str(f.get("file", "")).replace("\\", "/")
keys.add("%s|%s|%s" % (file_path, f["rule"], f.get("message", "")))
if refresh:
lines = [
"# gdstyle 存量基线(S13)——文件|规则|消息 三元组,每行一条;只记基线不记豁免理由。",
"# 重生成=人工专用:python tools/gdstyle_gate.py --refresh(禁清基线换绿;改规则口径/工具升级须随批重生成)。",
]
lines += sorted(keys)
BASELINE.write_text("\n".join(lines) + "\n", encoding="utf-8")
print("[gdstyle_gate] 基线已重生成:%s 条(%s)" % (len(keys), BASELINE.name))
return 0
base = set()
if BASELINE.exists():
for line in BASELINE.read_text(encoding="utf-8").splitlines():
s = line.strip()
if s and not s.startswith("#"):
base.add(s)
else:
return fail("基线文件不存在:%s(首次落位跑 python tools/gdstyle_gate.py --refresh,须经用户批准)" % BASELINE.name)
new = sorted(keys - base)
print("[gdstyle_gate] 扫描面 %d 个 .gd;命中 %d 条,基线内 %d 条,基线外新违规 %d 条"
% (len(face), len(keys), len(keys & base), len(new)))
if new:
for k in new[:MAX_REPORT]:
print(" NEW " + k)
if len(new) > MAX_REPORT:
print(" ...(截断,共 %d 条)" % len(new))
return fail("基线外新违规 %d 条——新码须修到基线口径内,或经用户批准随批重生成基线" % len(new))
print("[gdstyle_gate] ok")
return 0
if __name__ == "__main__":
sys.exit(run_gate())
+1 -9
View File
@@ -14,7 +14,7 @@
**现状**:工程债证据=reports/审计-game代码结构审查-2026-10-24.md §二 C1(已独立复现):tools/audit_type_hints.py:29 的 FUNC_DECL 正则两洞——①无返回类型声明按 GDScript 语法必然以 `:` 结尾,正则要求 `)` 后只跟 `->`/注释/行尾,R2 目标形态 100% 失配(R2 从上线起恒零命中恒绿);②`^(\s*)func` 不认 `static ` 前缀,static 函数对 R2/R3 整体漏网。实证存量(闸当前退出码 0):core/level_runner.gd:632、core/attunement.gd:10、presentation/main.gd:565、presentation/views/hud_presenter.gd:10-11、core/reward_economy.gd:104/119/131/146、core/unit_container.gd:275。属架构文档测试域自警的「规则扫描面为空=恒绿」静默失效模式(零命中自检因 R1/R3 仍有命中能力未拦住)。
**归属**:tools/ 静态扫描域(闸件批,非迭代批——gdstyle 条目同款执行形态:正则修后先跑出存量红、补注解或 `# type-hint: ignore` 归零、闸改动配变异验证)
**归属**:tools/ 静态扫描域(闸件批,非迭代批——gdstyle 引入批 2026-10-24 已按同款形态收口:先摸存量、闸改动配变异验证)
**状态**:待写卡
@@ -36,14 +36,6 @@
**状态**:待文档设计
#### gdstyle 引入——GDScript 第三方 linter 接入检查面(2026-10-24 登记,来源=会话提及,设计面=工程直入)
**现状**:工程债证据=2026-10-24 会话实测三件:①本机已装 gdtoolkit 4.5.0(gdlint/gdparse,PyPI 最新即此版)对 3 个在役文件解析假红(presentation/curio_interact_controller.gd、tests/system_test.gd、probe/ui_click_probe.gd——不认 Godot 4.7 新语法,Godot 自家解析器对三者全过);②候选 gdstyle v0.4.0(github.com/atelico/gdstyle,Rust 单二进制)对上述 3 文件全过、全工程 194 个 .gd 仅 1 处解析误报(core/rng_service.gd 头部 INT64_MIN 负字面量,Godot 特判放行,单条可豁免);③gdck v0.8.0 同测 3 文件挂 2,出局。价值面=质量类规则(duplicated-load/await-in-loop/allocation-in-loop)是自建 grep 闸查不到的补充信号;格式类规则与 S9/S10 重叠、应全关。用户 2026-10-24 立项引入。
**归属**:tools/ 检查面与测试基建。执行形态=非迭代批:gdstyle.toml 落仓库(只开质量类规则)+版本锁定,先非闸跑全量摸存量,再借闸机「存量基线·零新增」机制收编进 09 静态扫描域;闸件改动按 test-conventions 配变异验证。
**状态**:待写卡
#### 测试术语与层级重构批 A——测试命名+频率规则+新冒烟测试(2026-10-22 登记,来源=会话提及,设计面=工程直入)
**现状**:测试域名实分离(名叫冒烟的载体实为千项断言面)、每轮跑闸频率过高、测试金字塔倒挂的规则重构,合同=reports/提案-测试术语与层级重构方案-2026-10-22.md(v2,2026-10-22 用户裁决全部闭合、待裁点清零)。批 A=非迭代批(规则与闸件批),用户 2026-10-22 直接下开工令执行:待办清单登记 → 改规则(process-conventions/roadmap loop 规范/术语表退役词对照/AGENTS.md 规则行)→ 写新冒烟测试(game/tests/smoke_boot.tscn/.gd+tools/run_smoke.py 重写)与系统测试宿主(tools/run_system_test.py+game/tests/system_test.gd 薄壳)→ 改闸机键映射(新增 00 冒烟测试、01 改系统测试、02 改单元与集成测试)→ 改描述性文档与 iter 技能三副本 → 全量域闸验证。批 B(断言迁移,用户特批免卡直改 game/)停机等用户发令,不在本条执行面。