From 05745df3fbd32e4b45e56ee0c233ee1c05335659 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Tue, 27 Oct 2026 06:27:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=A5=E7=A8=8B(=E9=97=B8=2009=20=E5=AD=98?= =?UTF-8?q?=E9=87=8F=E7=BA=A2=E7=85=A7=E5=AE=9E=E8=AE=B0=EF=BC=8B=E5=9F=BA?= =?UTF-8?q?=E7=BA=BF=E5=8F=AA=E9=99=8D=E4=B8=8D=E5=8D=87):=20=E6=92=A4?= =?UTF-8?q?=E9=94=80=E3=80=8C=E6=8A=8A=E4=B8=A4=E6=9D=A1=E6=81=B6=E5=8C=96?= =?UTF-8?q?=E7=99=BB=E8=AE=B0=E4=B8=BA=E7=8E=B0=E8=A1=8C=E5=80=BC=E3=80=8D?= =?UTF-8?q?=E7=9A=84=E5=81=9A=E6=B3=95=EF=BC=88=E7=94=A8=E6=88=B7=E8=A3=81?= =?UTF-8?q?=EF=BC=9A=E6=A0=87=E5=87=86=E6=98=AF=E5=B0=BA=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E4=BB=A5=E7=8E=B0=E7=8A=B6=E4=B8=BA=E5=B0=BA=EF=BC=89=E2=80=94?= =?UTF-8?q?=E2=80=94=E2=91=A0tools/gdstyle=5Fbaseline.txt=20=E4=B8=A4?= =?UTF-8?q?=E6=9D=A1=E7=99=BB=E8=AE=B0=E5=80=BC=E5=9B=9E=E9=80=80=20battle?= =?UTF-8?q?=5Forchestrator=20max-file-length=201314=E2=86=921302=E3=80=81l?= =?UTF-8?q?evel=5Fmap=5Fscreen=20max-class-variables=2022=E2=86=9221?= =?UTF-8?q?=EF=BC=88=E6=B3=A2=200=20=E5=B7=B2=E6=89=B9=E5=87=86=E7=9A=84?= =?UTF-8?q?=2018=20=E6=9D=A1=E9=99=88=E6=97=A7=E9=94=AE=E6=B8=85=E7=90=86?= =?UTF-8?q?=E4=BF=9D=E7=95=99=E4=B8=8D=E5=8A=A8=EF=BC=89=EF=BC=9B=E2=91=A1?= =?UTF-8?q?tools/gdstyle=5Fgate.py=20=E9=80=90=E6=9D=A1=20NEW/=E6=81=B6?= =?UTF-8?q?=E5=8C=96=E8=A1=8C=E5=8A=A0=20FAIL=20=E5=89=8D=E7=BC=80?= =?UTF-8?q?=E2=80=94=E2=80=94gate=2009=20=E7=9A=84=E5=AD=98=E9=87=8F?= =?UTF-8?q?=E7=BA=A2=E6=8C=87=E7=BA=B9=E5=8F=AA=E5=8F=96=E5=90=AB=20FAIL?= =?UTF-8?q?=20=E7=9A=84=E8=A1=8C=EF=BC=8C=E5=8E=9F=E3=80=8CNEW/WORSENED?= =?UTF-8?q?=E3=80=8D=E8=A1=8C=E4=B8=8D=E8=BF=9B=E6=8C=87=E7=BA=B9=EF=BC=8C?= =?UTF-8?q?=E4=B8=A4=E6=AC=A1=E4=B8=8D=E5=90=8C=E6=81=B6=E5=8C=96=E9=9B=86?= =?UTF-8?q?=E6=8C=87=E7=BA=B9=E7=9B=B8=E5=90=8C=EF=BC=9D=E5=AD=98=E9=87=8F?= =?UTF-8?q?=E7=BA=A2=E6=9C=9F=E9=97=B4=E4=BB=BB=E4=BD=95=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E8=BF=9D=E8=A7=84=E6=88=96=E8=BF=9B=E4=B8=80=E6=AD=A5=E6=81=B6?= =?UTF-8?q?=E5=8C=96=E9=83=BD=E4=BC=9A=E8=A2=AB=E3=80=8C=E5=90=8C=E6=AC=BE?= =?UTF-8?q?=E5=AD=98=E9=87=8F=E7=BA=A2=E3=80=8D=E6=94=BE=E8=BF=87=EF=BC=9B?= =?UTF-8?q?=E9=A1=BA=E5=B8=A6=E5=8A=A0=20refresh=20=E6=8A=AC=E5=8D=87?= =?UTF-8?q?=E5=AE=88=E5=8D=AB=EF=BC=88=E9=87=8D=E7=94=9F=E6=88=90=E4=BC=9A?= =?UTF-8?q?=E6=8A=8A=E4=BB=BB=E4=B8=80=E7=99=BB=E8=AE=B0=E5=80=BC=E6=8A=AC?= =?UTF-8?q?=E9=AB=98=E5=8D=B3=E6=8B=92=E5=86=99=EF=BC=8C=E9=A1=BB=20--forc?= =?UTF-8?q?e=20=E6=98=BE=E5=BC=8F=E7=A1=AE=E8=AE=A4=EF=BC=9B=E5=8E=9F?= =?UTF-8?q?=E5=8F=AA=E6=9C=89=E9=AA=A4=E9=99=8D=E5=AE=88=E5=8D=AB=EF=BC=8C?= =?UTF-8?q?37625317=20=E6=9B=BE=E5=80=9F=E9=87=8D=E7=94=9F=E6=88=90?= =?UTF-8?q?=E9=9D=99=E9=BB=98=E5=90=B8=E6=94=B6=203=20=E6=9D=A1=E6=8A=AC?= =?UTF-8?q?=E9=AB=98=EF=BC=89=EF=BC=9B=E2=91=A2game/tests/.gates/baseline.?= =?UTF-8?q?json=2009=20=E6=9D=A1=E7=9B=AE=E6=94=B9=20exit=3D1=EF=BC=8B?= =?UTF-8?q?=E7=8E=B0=E7=AE=97=E6=8C=87=E7=BA=B9=2091d45583cf6d=EF=BC=88?= =?UTF-8?q?=E7=BA=A2=E9=A1=B9=EF=BC=9D=E4=B8=8A=E5=88=97=E4=B8=A4=E6=9D=A1?= =?UTF-8?q?=EF=BC=8C=E9=80=90=E6=9D=A1=E7=82=B9=E5=90=8D=E5=8F=AF=E6=A0=B8?= =?UTF-8?q?=EF=BC=9B=E6=AD=A4=E5=89=8D=E8=AE=B0=E7=9A=84=20user-approved-i?= =?UTF-8?q?ter38=20=E6=98=AF=E6=89=8B=E5=86=99=E6=A0=87=E8=AE=B0=EF=BC=8C?= =?UTF-8?q?=E6=B0=B8=E4=B8=8D=E7=AD=89=E4=BA=8E=E7=8E=B0=E7=AE=97=E6=8C=87?= =?UTF-8?q?=E7=BA=B9=EF=BC=8C=E5=90=88=E5=9B=9E=E5=BF=85=E8=A2=AB=E6=8B=A6?= =?UTF-8?q?=EF=BC=89=EF=BC=8Cnote=20=E8=AE=B0=E7=8E=B0=E8=A1=8C=E5=8F=A3?= =?UTF-8?q?=E5=BE=84=EF=BC=9A=E9=98=88=E5=80=BC=E4=B8=8D=E5=8F=98=EF=BC=9D?= =?UTF-8?q?gdstyle=20=E9=BB=98=E8=AE=A4=EF=BC=88=E6=96=87=E4=BB=B6=201000?= =?UTF-8?q?=20=E8=A1=8C=EF=BC=8F=E7=B1=BB=E5=8F=98=E9=87=8F=2015=20?= =?UTF-8?q?=E7=AD=89=EF=BC=89=EF=BC=8C=E8=BF=98=E5=80=BA=E5=BD=92=E8=BF=AD?= =?UTF-8?q?=E4=BB=A3=2040=20=E5=8D=A1=E2=91=A0=E4=B8=8E=E8=BF=AD=E4=BB=A3?= =?UTF-8?q?=2041=20=E5=8D=A1=E2=91=A2=EF=BC=9B=E2=91=A3static=5Fscan.sh=20?= =?UTF-8?q?S13=20=E5=A4=B4=E6=B3=A8=E8=A1=A5=20FAIL=20=E5=89=8D=E7=BC=80?= =?UTF-8?q?=E4=B8=8E=E5=8F=AA=E9=99=8D=E4=B8=8D=E5=8D=87=E4=B8=A4=E5=8F=A5?= =?UTF-8?q?=E3=80=82=E9=AA=8C=E8=AF=81=EF=BC=9A--refresh=20=E5=AE=9E?= =?UTF-8?q?=E6=B5=8B=E6=8B=92=E5=86=99=E4=B8=94=E5=9F=BA=E7=BA=BF=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E9=80=90=E5=AD=97=E8=8A=82=E6=9C=AA=E5=8F=98=EF=BC=9B?= =?UTF-8?q?=E9=9D=99=E6=80=81=E6=89=AB=E6=8F=8F=E5=AE=9E=E6=B5=8B=20exit?= =?UTF-8?q?=3D1=EF=BC=8C=E4=B8=A4=E6=9D=A1=E6=81=B6=E5=8C=96=E9=80=90?= =?UTF-8?q?=E6=9D=A1=E5=88=97=E5=90=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/tests/.gates/baseline.json | 6 +++--- game/tests/static_scan.sh | 6 ++++-- tools/gdstyle_baseline.txt | 8 +++++--- tools/gdstyle_gate.py | 35 ++++++++++++++++++++++++--------- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/game/tests/.gates/baseline.json b/game/tests/.gates/baseline.json index 42da5567..ee6cfbe8 100644 --- a/game/tests/.gates/baseline.json +++ b/game/tests/.gates/baseline.json @@ -1,5 +1,5 @@ { - "note": "存量基线·首次自动生成;闸况变化时本脚本会判红,需人工确认后重生成;2026-10-17 人工确认重生成 06 条目:af94ce97 把 gdd_lint 记为存量红(01 篇 R5),该红已由 fcb8c3f8 补流程图消除,实测 --docs 域 06 exit=0,故基线改回绿。2026-10-18 新增闸件 08c 流水线闸(tools/pipeline_gate.py 注册上电),手工加入绿记录(roadmap 压缩批实测 --docs 域 exit=0),其余条目原样保留。2026-10-22 测试术语与层级重构批 A 改键:01 冒烟全量→01 系统测试(同一断言面 smoke_all.gd,运行器换 tools/run_system_test.py,过渡期判定口径不变)、02 单元套件→02 单元与集成测试(同一 run_all.gd 入口,名从实)、新增 00 冒烟测试(tools/run_smoke.py+game/tests/smoke_boot.tscn,重写后单跑实测 17 项 0 失败 PASS);09 静态扫描基线 exit=1(fp=4354b2aa72a7)系滞后红,本批单跑实测 exit=0(与 2026-10-22 16:20 回执一致),基线改回绿;其余条目原样保留。;2026-10-23 主会话记 07 doc_link 为存量红(用户令忽略:锻造工坊.md 死链的修复在另一会话未合入,合回闸豁免;外部修复合入后应重生成基线归绿);2026-10-26 用户特批带红合并(迭代 38 收口):09 静态扫描记存量红——gdstyle 恶化 2 条(battle_orchestrator.gd max-file-length 1314>1302=卡④头注必载内容、level_map_screen.gd max-class-variables 22>21=卡①缓存成员,均为卡片义务的记账漂移非缺陷,压缩还债经计算不可行),用户裁「不管引入的恶化直接提交、特许免测试重跑」;后续批次若触及两文件可顺带还债或经批准重生成基线归绿;两项恶化已按用户批准登记为现行值(gdstyle 基线重生成、09 归绿),迭代 40 卡① 还债后再次收紧", + "note": "存量基线·首次自动生成;闸况变化时本脚本会判红,需人工确认后重生成;2026-10-17 人工确认重生成 06 条目:af94ce97 把 gdd_lint 记为存量红(01 篇 R5),该红已由 fcb8c3f8 补流程图消除,实测 --docs 域 06 exit=0,故基线改回绿。2026-10-18 新增闸件 08c 流水线闸(tools/pipeline_gate.py 注册上电),手工加入绿记录(roadmap 压缩批实测 --docs 域 exit=0),其余条目原样保留。2026-10-22 测试术语与层级重构批 A 改键:01 冒烟全量→01 系统测试(同一断言面 smoke_all.gd,运行器换 tools/run_system_test.py,过渡期判定口径不变)、02 单元套件→02 单元与集成测试(同一 run_all.gd 入口,名从实)、新增 00 冒烟测试(tools/run_smoke.py+game/tests/smoke_boot.tscn,重写后单跑实测 17 项 0 失败 PASS);09 静态扫描基线 exit=1(fp=4354b2aa72a7)系滞后红,本批单跑实测 exit=0(与 2026-10-22 16:20 回执一致),基线改回绿;其余条目原样保留。;2026-10-23 主会话记 07 doc_link 为存量红(用户令忽略:锻造工坊.md 死链的修复在另一会话未合入,合回闸豁免;外部修复合入后应重生成基线归绿);2026-10-26 用户特批带红合并(迭代 38 收口):09 静态扫描记存量红——gdstyle 恶化 2 条(battle_orchestrator.gd max-file-length 1314>1302=卡④头注必载内容、level_map_screen.gd max-class-variables 22>21=卡①缓存成员,均为卡片义务的记账漂移非缺陷,压缩还债经计算不可行),用户裁「不管引入的恶化直接提交、特许免测试重跑」;后续批次若触及两文件可顺带还债或经批准重生成基线归绿;2026-10-27 用户裁「标准是尺、不以现状为尺」:09 存量红照实记(exit=1+现行红项指纹,两条恶化各自点名可核),gdstyle 基线登记值回退 1302/21(波 0 的 18 条陈旧键清理保留),gdstyle_gate 逐条违规行加 FAIL 前缀并加「refresh 禁抬高登记值」守卫——存量红期间任何新增违规或进一步恶化都会改指纹被拦;阈值口径不变=gdstyle 默认值(文件 1000 行/类变量 15 等),还债归迭代 40 卡①(battle_orchestrator 1314→≤1000)与迭代 41 卡③(level_map_screen 22→≤15),还清后重新生成基线归绿", "gates": { "00 冒烟测试": { "exit": "0", @@ -46,8 +46,8 @@ "fp": "green" }, "09 静态扫描": { - "exit": "0", - "fp": "green" + "exit": "1", + "fp": "91d45583cf6d" }, "10 熵增闸": { "exit": "0", diff --git a/game/tests/static_scan.sh b/game/tests/static_scan.sh index 76c5ce99..3897a193 100644 --- a/game/tests/static_scan.sh +++ b/game/tests/static_scan.sh @@ -291,8 +291,10 @@ fi # probe/sim/tests 测量面直构惯例不在面)。存量基线 tools/gdstyle_baseline.txt 用稳定身份键(函数级带数 # 条目=文件|规则|函数名,类级/文件级带数条目=文件|规则,均带登记数值;无数字条目=文件|规则|消息全文 # 裸键)——消息里的行数/分支数等计数漂移不假红;判定=基线外新违规红(NEW)+同键指标较登记值恶化红 -# (WORSENED),改小/持平不红。基线重生成=人工专用(python tools/gdstyle_gate.py --refresh,附对账; -# 键数骤降逾 10% 须 --force),禁清基线换绿。二进制本机固定路径 +# (WORSENED),改小/持平不红;逐条违规行带 FAIL 前缀,使存量红期间的红项清单(哪几条、恶化到多少) +# 进 gate 09 指纹,新增或进一步恶化不会被「同款存量红」放过。阈值口径=gdstyle 默认值;基线只是欠账 +# 簿,登记值只准随还债下降,禁抬高到现状。基线重生成=人工专用(python tools/gdstyle_gate.py +# --refresh,附对账;键数骤降逾 10% 或登记值被抬高均拒写,须 --force),禁清基线换绿。二进制本机固定路径 # D:/code/gdstyle/gdstyle.exe(不入库),GDSTYLE_BIN 环境变量覆盖;版本与钉定版不符即红(升级须重测)。 if python tools/gdstyle_gate.py; then echo "[static_scan] S13 ok" diff --git a/tools/gdstyle_baseline.txt b/tools/gdstyle_baseline.txt index 8ede528b..0a4cda6e 100644 --- a/tools/gdstyle_baseline.txt +++ b/tools/gdstyle_baseline.txt @@ -3,8 +3,10 @@ # (class variables/public methods/file length)=文件|规则;无数字条目=文件|规则|消息全文(裸键)。 # 带数条目行格式「键 = 数值」,数值=消息剥掉 (max N) 段后首个整数;无数字条目裸键。 # 判定=键不在基线红(NEW)、同键数值较登记值恶化红(WORSENED)、改小/持平不红。 +# 阈值口径=gdstyle 默认值(tools/gdstyle.toml 不设数值阈值);本文件只是欠账簿,登记值只准随 +# 还债下降,禁抬高到现状(抬高=把既有代码当尺子,默认恶化)。 # 重生成=人工专用:python tools/gdstyle_gate.py --refresh(禁清基线换绿;改规则口径/工具升级须随批 -# 重生成;新键数较旧基线少逾 10% 须加 --force 显式确认)。 +# 重生成;新键数较旧基线少逾 10% 或登记值被抬高均拒写,须加 --force 显式确认)。 game/core/action_economy.gd|quality/max-class-variables = 18 game/core/adventure_runner.gd|quality/max-branches|_apply_curio_pick = 10 game/core/adventure_runner.gd|quality/max-class-variables = 42 @@ -13,7 +15,7 @@ game/core/adventure_runner.gd|quality/max-returns|_apply_curio_pick = 9 game/core/battle_orchestrator.gd|quality/max-branches|begin_battle = 17 game/core/battle_orchestrator.gd|quality/max-branches|use_treasure = 18 game/core/battle_orchestrator.gd|quality/max-class-variables = 50 -game/core/battle_orchestrator.gd|quality/max-file-length = 1314 +game/core/battle_orchestrator.gd|quality/max-file-length = 1302 game/core/battle_orchestrator.gd|quality/max-function-length|_place_variants = 52 game/core/battle_orchestrator.gd|quality/max-function-length|begin_battle = 141 game/core/battle_orchestrator.gd|quality/max-function-length|use_treasure = 62 @@ -205,7 +207,7 @@ game/presentation/views/hero_info_panel_view.gd|quality/max-function-length|set_ game/presentation/views/hero_info_panel_view.gd|quality/max-local-variables|set_treasure_inventory = 13 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|_draw_graph = 9 -game/presentation/views/level_map_screen.gd|quality/max-class-variables = 22 +game/presentation/views/level_map_screen.gd|quality/max-class-variables = 21 game/presentation/views/level_map_screen.gd|quality/max-function-length|_draw_graph = 78 game/presentation/views/level_map_screen.gd|quality/max-function-length|_init = 135 game/presentation/views/level_map_screen.gd|quality/max-local-variables|_draw_graph = 27 diff --git a/tools/gdstyle_gate.py b/tools/gdstyle_gate.py index 70c4e922..b93d54cb 100644 --- a/tools/gdstyle_gate.py +++ b/tools/gdstyle_gate.py @@ -16,19 +16,25 @@ quality/*+syntax/reserved-identifier,format/naming/order 全关)。扫描 带数条目行格式「键 = 数值」,数值=消息剥掉 (max N) 段后首个整数;无数字条目裸键无数值。 判定:①键不在基线=新违规(NEW)红;②键在基线且双方有数值、当前数值 > 基线登记值= 恶化(WORSENED)红——独立于差集,防稳定键吞掉 104→300 行式恶化;③其余绿(改小/持平不红)。 +逐条违规行带 FAIL 前缀——gate 09 的存量红指纹只取含 FAIL 的行,带前缀才能让「红项清单」 +(哪几条、恶化到多少)进指纹:否则存量红期间的任何新增/进一步恶化都算同款红被放行。 -基线重生成=人工专用(--refresh,附新旧对账与骤降守卫),禁在闸内自动重生成(防清基线换绿); -新键数较旧基线少逾 10% 时拒绝写入,须加 --force 显式确认(防扫面断裂静默缩基线换绿), ---force 只在 refresh 路径有效。 +阈值口径=gdstyle 默认值(tools/gdstyle.toml 不设数值阈值);基线只是欠账簿,登记值只准因 +还债下降,禁抬高到现状(抬高=把既有代码当尺子,默认恶化)。 + +基线重生成=人工专用(--refresh,附新旧对账、骤降守卫与抬升守卫),禁在闸内自动重生成 +(防清基线换绿);新键数较旧基线少逾 10% 拒绝写入(防扫面断裂静默缩基线换绿);任一键登记 +值被抬高同样拒绝(防以现状为尺吞掉恶化)。两条守卫都须 --force 显式确认,--force 只在 +refresh 路径有效。 二进制:本机固定路径 D:/code/gdstyle/gdstyle.exe(不入库不入包),GDSTYLE_BIN 环境变量覆盖; 版本与钉定版不符即红——升级工具须重测语法兼容性并人工重生成基线。 退出码:0=无基线外新违规且无恶化;1=有新违规/有恶化/二进制缺失或版本不符/扫描面为空/ -输出不可解析/refresh 骤降拒写;2=用法错。 +输出不可解析/refresh 骤降或抬升拒写;2=用法错。 用法:python tools/gdstyle_gate.py # 闸判定 python tools/gdstyle_gate.py --refresh # 人工重生成基线(覆盖旧文件,附对账) - python tools/gdstyle_gate.py --refresh --force # 骤降守卫触发时显式确认写入 + python tools/gdstyle_gate.py --refresh --force # 骤降/抬升守卫触发时显式确认写入 """ import json import os @@ -171,6 +177,17 @@ def run_gate() -> int: if len(current) < len(old) * SHRINK_GUARD and not force: return fail("新键数 %d 较旧基线 %d 少逾 10%%——疑扫面断裂静默缩基线换绿,拒绝写入;" "确认缩基线正当(如删规则/缩扫描面)须加 --force 显式确认" % (len(current), len(old))) + raised = sorted( + (k, old[k], current[k]) for k in current + if k in old and old[k] is not None and current[k] is not None and current[k] > old[k] + ) + if raised and not force: + for k, was, now in raised[:MAX_REPORT]: + print(" FAIL 抬高 %s = %d(登记 %d)" % (k, now, was)) + if len(raised) > MAX_REPORT: + print(" ...(截断,共 %d 条)" % len(raised)) + return fail("重生成会抬高 %d 条登记值——基线只准因还债下降,抬高=以现状为尺默认恶化;" + "确属阈值口径变更或经用户批准须加 --force 显式确认" % len(raised)) else: print("[gdstyle_gate] 旧基线不存在,跳过对账(首次落位)") write_baseline(current) @@ -191,15 +208,15 @@ def run_gate() -> int: red = False if new: for k in new[:MAX_REPORT]: - print(" NEW " + k) + print(" FAIL 新增 " + k) if len(new) > MAX_REPORT: - print(" ...(截断,共 %d 条)" % len(new)) + print(" FAIL ...(截断,共 %d 条)" % len(new)) red = True if worsened: for k in worsened[:MAX_REPORT]: - print(" WORSENED %s = %d(基线登记 %d)" % (k, current[k], base[k])) + print(" FAIL 恶化 %s = %d(基线登记 %d)" % (k, current[k], base[k])) if len(worsened) > MAX_REPORT: - print(" ...(截断,共 %d 条)" % len(worsened)) + print(" FAIL ...(截断,共 %d 条)" % len(worsened)) red = True if red: return fail("基线外新违规 %d 条/恶化 %d 条——新码须修到基线口径内,恶化须还债或经用户批准随批重生成基线"