From 9c36c7a237eab5b70cb95a74da01283800eb9ad6 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Mon, 2 Nov 2026 06:29:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=A5=E7=A8=8B(=E5=B7=A5=E7=A8=8B=E6=B8=85?= =?UTF-8?q?=E7=90=86=E6=89=B9=C2=B7=E7=94=A8=E6=88=B7=E4=BB=A4):=20?= =?UTF-8?q?=E5=85=AD=E4=BB=B6=E7=9B=B4=E6=94=B9=E5=90=88=E6=89=B9=E2=80=94?= =?UTF-8?q?=E2=80=94=E2=91=A0palette=5Fcheck=E5=9F=BA=E7=BA=BF=E5=BB=BA?= =?UTF-8?q?=E6=A1=A3+=E5=8F=8C=E9=97=A8=E2=91=A1=E6=9C=BA=E6=A3=80?= =?UTF-8?q?=E5=8C=96:=20golden/palette=5Fbaseline=E4=B8=A4PNG(token92?= =?UTF-8?q?=E8=89=B2=E2=88=AA=E7=B4=A0=E6=9D=90=E5=BF=AB=E7=85=A71274?= =?UTF-8?q?=E8=89=B2=3D=E5=B9=B6=E9=9B=861346=E8=89=B2)+gen=5Fpalette=5Fba?= =?UTF-8?q?seline.py=E5=BB=BA=E6=A1=A3=E5=88=B7=E6=96=B0=E4=BB=B6+?= =?UTF-8?q?=E9=97=B8=E8=84=9A=E6=9C=AC05b=E8=89=B2=E6=9D=BF=E9=97=B8(code?= =?UTF-8?q?=E5=9F=9F,quick/=E5=BD=B1=E5=93=8D=E9=9D=A2SKIP)+=E5=A4=B4?= =?UTF-8?q?=E6=B3=A8=E5=9F=BA=E7=BA=BF=E7=BA=AA=E5=BE=8B,=20=E9=97=A8?= =?UTF-8?q?=E2=91=A0=E8=AF=AD=E4=B9=89=E6=A3=80=E6=9F=A5=E4=B8=8E48?= =?UTF-8?q?=E8=AE=A1=E6=95=B0=E4=B8=8A=E9=99=90=E4=B8=8D=E6=89=BF=E8=BD=BD?= =?UTF-8?q?(=E5=8F=A3=E5=BE=84=E5=BD=92art-bible=20owner,=E5=91=88?= =?UTF-8?q?=E6=8A=A5);=20=E2=91=A1extract=5Fchecks=E8=A1=A5check=5Fquiet?= =?UTF-8?q?=E9=9D=99=E9=BB=98=E9=80=9A=E9=81=93:=20CALL=5FRE/DEF=5FRE?= =?UTF-8?q?=E6=89=A9=E5=8F=8C=E9=80=9A=E9=81=93+collect=5Fcall=E6=8C=89?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=E9=95=BF=E5=81=8F=E7=A7=BB+quiet=E5=88=97?= =?UTF-8?q?=E8=AE=B0channel:check=5Fquiet,=20=E8=87=AA=E8=AF=81=E4=B8=89?= =?UTF-8?q?=E9=87=8D(=E5=8F=8C=E8=AE=A1=E7=AD=89=E5=BC=8F2155=3D=3D2155/?= =?UTF-8?q?=E6=96=B0=E6=97=A7=E5=AF=B9=E6=8B=8D1719=E2=86=922133=3D+414?= =?UTF-8?q?=E5=85=A5=E8=B4=A6/=E5=BE=80=E8=BF=94--diff=20PASS=E9=9B=B6?= =?UTF-8?q?=E5=B7=AE=E5=BC=82),=20test-conventions=C2=A75.2=E5=B1=80?= =?UTF-8?q?=E9=99=90=E5=A4=87=E6=A1=88=E5=8F=A5=E9=9A=8F=E6=89=B9=E6=8D=A2?= =?UTF-8?q?=E4=BB=A3;=20=E2=91=A2=E6=A0=B7=E5=BC=A0S1b=E5=9B=9B=E8=89=B2?= =?UTF-8?q?=E5=A2=A8=C3=97PANEL=5FDATA=E5=9E=AB=E7=89=8C=E2=89=A54.5:1?= =?UTF-8?q?=E8=89=B2=E5=80=BC=E5=AF=B9=E8=A1=A8=E6=96=AD=E8=A8=80(?= =?UTF-8?q?=E8=AF=BB=E6=95=B04.97=E2=80=935.62=E4=B8=8E=E5=AE=A1=E8=AE=A1?= =?UTF-8?q?=E5=A4=8D=E7=AE=97=E9=80=90=E4=BD=8D=E4=B8=80=E8=87=B4,=20?= =?UTF-8?q?=E6=A0=B7=E5=BC=A031/31=E5=85=A8=E7=BB=BF;=20V10=E5=9F=BA?= =?UTF-8?q?=E7=BA=BF=E5=AF=B9=E6=8B=8D=E5=9B=BEartwork=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E4=BB=B6--save-baseline=E9=87=8D=E5=BB=BA);=20=E2=91=A3main.gd?= =?UTF-8?q?=E6=AD=BBpreload=E6=B8=85=E7=90=8610=E6=9D=A1(=E7=99=BB?= =?UTF-8?q?=E8=AE=B08=E6=9D=A1=E5=A4=8D=E6=A0=B8=E5=A4=9A=E5=87=BA2?= =?UTF-8?q?=E6=9D=A1,=207=E5=85=B7=E5=90=8D=E6=B6=88=E8=B4=B9=E9=9D=A2?= =?UTF-8?q?=E5=B7=B2=E8=BF=81main=5Fui=5Fbuild=E6=8B=86=E4=BB=B6=E8=87=AA?= =?UTF-8?q?=E6=8C=81,=20=E9=80=90=E6=9D=A1grep=E5=A4=8D=E6=A0=B8=E9=9B=B6?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BD=BF=E7=94=A8),=20presentation=2017?= =?UTF-8?q?=E5=A5=97=E4=BB=B6=E5=85=A8=E7=BB=BF+=E5=86=92=E7=83=9F15?= =?UTF-8?q?=E9=A1=B90=E5=A4=B1=E8=B4=A5=E5=85=9C=E5=BA=95;=20=E2=91=A4?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E6=8D=A2=E4=BB=A3:=20ui=5Fkit=20TEX=5FHERO?= =?UTF-8?q?=5FPORTRAIT=E3=80=8C48px=E6=A1=A3=E3=80=8D=E2=86=92=E5=8E=9F?= =?UTF-8?q?=E7=A8=BF=E5=88=86=E8=BE=A8=E7=8E=87+=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E6=A1=A3=E8=AF=BBPORTRAIT=5FDISPLAY=5FH,=20path=5Fcheck?= =?UTF-8?q?=E5=A4=B4=E6=B3=A8=E5=88=A0=E6=97=A5=E6=9C=9F=E6=89=B9=E6=B3=A8?= =?UTF-8?q?=E8=AE=B0;=20=E2=91=A5CAMP=5FHEADER=5FBAND=E9=80=80=E5=BD=B9?= =?UTF-8?q?=E8=AF=84=E4=BC=B0:=204=E5=A4=84=E6=B6=88=E8=B4=B9=E9=9D=A2?= =?UTF-8?q?=E6=A0=B8=E8=BF=87(=E5=85=B3=E5=8D=A1=E5=B1=8F2/=E5=95=86?= =?UTF-8?q?=E5=BA=971/KeystoneBadge=E5=B7=A5=E5=8E=821),=20=E9=80=80?= =?UTF-8?q?=E5=BD=B9=E5=88=A0=E9=99=A4=E4=B8=8D=E6=88=90=E7=AB=8B,=20?= =?UTF-8?q?=E5=A4=84=E7=BD=AE=3D=E6=94=B9=E5=90=8D=E4=B8=AD=E6=80=A7?= =?UTF-8?q?=E5=8C=96=E5=BD=92ui=5Fkit=E4=BB=A4=E7=89=8C=E6=89=B9=E9=A1=BA?= =?UTF-8?q?=E5=B8=A6(=E9=9B=B6=E5=80=BC=E5=8F=98=E5=8C=96);=20=E2=91=A6run?= =?UTF-8?q?=5Fall=5Fgates=2002=E4=BC=A0=E5=8F=82=E6=A0=B8=E6=9F=A5=3Dd32ff?= =?UTF-8?q?342=E5=B7=B2=E5=AE=8C=E6=88=90=E6=BC=8F=E5=88=A0=E9=9B=B6?= =?UTF-8?q?=E6=94=B9=E5=8A=A8;=20=E5=BE=85=E5=8A=9E=E6=B8=85=E5=8D=957?= =?UTF-8?q?=E6=9D=A1=E7=9B=AE=E6=95=B4=E6=9D=A1=E5=88=A0=E9=99=A4(?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E6=9C=BA=E5=87=BA=E5=8F=A3),=20pipeline=5Fga?= =?UTF-8?q?te=20PASS(33=E6=9D=A1=E7=9B=AE/49=E6=80=BB=E8=A1=A8=E8=A1=8C);?= =?UTF-8?q?=20=E4=BA=A7=E5=87=BA=E7=89=A9=3Dreports/=E5=B7=A5=E7=A8=8B?= =?UTF-8?q?=E6=94=B9=E5=8A=A8=E6=8A=A5=E5=91=8A-=E5=B7=A5=E7=A8=8B?= =?UTF-8?q?=E6=B8=85=E7=90=86=E6=89=B9-2026-11-02.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design/engineering/test-conventions.md | 2 +- game/presentation/main.gd | 10 -- game/presentation/views/ui_kit.gd | 2 +- .../golden/palette_baseline/art_snapshot.png | Bin 0 -> 2572 bytes .../golden/palette_baseline/ui_tokens.png | Bin 0 -> 337 bytes reports/工程改动报告-工程清理批-2026-11-02.md | 75 +++++++++++++ tools/extract_checks.py | 43 +++---- tools/gen_palette_baseline.py | 105 ++++++++++++++++++ tools/palette_check.py | 13 ++- tools/path_check.py | 2 +- tools/render_sample_sheet_v3.py | 12 ++ tools/run_all_gates.sh | 8 ++ 待办清单.md | 56 ---------- 13 files changed, 238 insertions(+), 90 deletions(-) create mode 100644 game/tests/golden/palette_baseline/art_snapshot.png create mode 100644 game/tests/golden/palette_baseline/ui_tokens.png create mode 100644 reports/工程改动报告-工程清理批-2026-11-02.md create mode 100644 tools/gen_palette_baseline.py diff --git a/design/engineering/test-conventions.md b/design/engineering/test-conventions.md index 09c7c39e..039058c1 100644 --- a/design/engineering/test-conventions.md +++ b/design/engineering/test-conventions.md @@ -35,7 +35,7 @@ 需求卡片 §8「改动—验收对照表」每一条都要落成可执行的验证;本文定统一写法,卡里定每批的具体内容(测什么/注入哪里)。写卡期查不出执行载体的条目=不可测,当场呈报,禁拖到实现期。 1. **执行载体五选一,逐条声明**:单元测试(`tests/run_all`)/系统测试断言(`tests/system_test.gd`)/场景探针(`probe/` 下 `*_probe`)/MC 同种子逐项比对/人工核对(仅限无法自动化的纪律类需求点,如命名锁定、数值占位)。行为类条目以自动化载体为主。 -2. **粒度与对应关系**:每条清单条目至少一个自动断言,且断言必须从该条目的真实入口进入;多条条目可合用一个测试函数,但每条都要有自己单独可判红的判据(取证口径见 §8.4 唯一口径——禁变异/禁撤销)。断言失败消息末尾带编号尾缀〔卡短名 Vn〕(如〔秘宝批 V3〕)——断言与卡片清单可互相 grep 查找。**工具面局限备案(2026-10-27 迭代 39 验收审计)**:`Kit.check_quiet` 静默收集形态(计数不入判定即打印、失败消息进 problems 汇总)的断言消息不进 `tools/extract_checks.py` 扫描面——验收尾缀 grep 对该通道失效;如需覆盖属提取器改版(工程批)。 +2. **粒度与对应关系**:每条清单条目至少一个自动断言,且断言必须从该条目的真实入口进入;多条条目可合用一个测试函数,但每条都要有自己单独可判红的判据(取证口径见 §8.4 唯一口径——禁变异/禁撤销)。断言失败消息末尾带编号尾缀〔卡短名 Vn〕(如〔秘宝批 V3〕)——断言与卡片清单可互相 grep 查找。`Kit.check_quiet` 静默收集形态(计数不入判定即打印、失败消息进 problems 汇总)的断言已入 `tools/extract_checks.py` 扫描面(2026-11-02 提取器改版:三通道同口径提取,静默通道条目 quiet 列记 `channel:check_quiet`),验收尾缀 grep 对该通道有效。 3. **断言词汇按验证对象五选一**: | 词汇 | 适用场景 | diff --git a/game/presentation/main.gd b/game/presentation/main.gd index 09caad6f..ec7c655a 100644 --- a/game/presentation/main.gd +++ b/game/presentation/main.gd @@ -14,21 +14,11 @@ const AUTOLOAD_PATH_RNG := "/root/RngService" const AUTOLOAD_PATH_SAVE := "/root/SaveManager" const AUTOLOAD_PATH_META := "/root/MetaProgression" -const UiAssembler := preload("res://presentation/ui_assembler.gd") const Narrator := preload("res://presentation/battle_narrator.gd") -const TuneSimController := preload("res://presentation/tune_sim_controller.gd") -const DebugSessionScript := preload("res://presentation/debug_session.gd") -const TreasureInteractController := preload("res://presentation/treasure_interact_controller.gd") # 秘宝两步交互 -const CurioInteractController := preload("res://presentation/curio_interact_controller.gd") # 三选一与替换子交互 -const CampShopPresenter := preload("res://presentation/camp_shop_presenter.gd") # 营地/商店投影 -const BoardResolversScript := preload("res://presentation/board_resolvers.gd") # 棋盘解析回调族 const MainUiBuild := preload("res://presentation/main_ui_build.gd") # 装配分步承接件 const MainAdventureFlow := preload("res://presentation/main_adventure_flow.gd") # 冒险流程承接件 const MainOverlayFlow := preload("res://presentation/main_overlay_flow.gd") # 覆盖层流程承接件 const MainDebugFlow := preload("res://presentation/main_debug_flow.gd") # 调试流程承接件 -const MenuScreenScene := preload("res://presentation/scenes/menu_screen.tscn") # 三屏壳场景 -const CampScreenScene := preload("res://presentation/scenes/camp_screen.tscn") -const AdventureScreenScene := preload("res://presentation/scenes/adventure_screen.tscn") var db var run_scope = null # 会话状态承载(run_scope.gd;_ready 即建闲时态,永非 null) diff --git a/game/presentation/views/ui_kit.gd b/game/presentation/views/ui_kit.gd index 7ce53dd1..3c8d24c6 100644 --- a/game/presentation/views/ui_kit.gd +++ b/game/presentation/views/ui_kit.gd @@ -230,7 +230,7 @@ static func motion(dur: float) -> float: # 的字形/无演出回退路径;禁 preload(素材缺位树上直接断言炸脚本,冒烟安全红线) const TEX_HERO_IDLE := "res://assets/art/character/character_hero_idle.png" const TEX_HERO_WALK := "res://assets/art/character/character_hero_walk.png" -const TEX_HERO_PORTRAIT := "res://assets/art/character/character_hero_portrait.png" # B 区站桩立绘·normal 态(48px 档) +const TEX_HERO_PORTRAIT := "res://assets/art/character/character_hero_portrait.png" # B 区站桩立绘·normal 态(素材=原稿分辨率,显示档缩放读 standee_motion PORTRAIT_DISPLAY_H) const TEX_HERO_ATTACK := "res://assets/art/character/character_hero_attack.png" # B 区站桩立绘·attack 态(三态切换) const TEX_HERO_HIT := "res://assets/art/character/character_hero_hit.png" # B 区站桩立绘·hit 态(三态切换) # 敌种立绘(B 区站桩)——文件键 = 数据表主键 enemy_id(圣经 §8.3 命名规范), diff --git a/game/tests/golden/palette_baseline/art_snapshot.png b/game/tests/golden/palette_baseline/art_snapshot.png new file mode 100644 index 0000000000000000000000000000000000000000..8e5fb8be7ed3faa186908f5f960b4f832e4bd863 GIT binary patch literal 2572 zcmV+n3iI`eP)&(JVdZS2uNari2~&%k_XA{teqR_kIvk=bI#ste|xQOe{1b^ z2!K%X$6rLxV7U%$Un^lj=xrm?? zRG6o_;X7iZ3{d}+7>__v8Bhj~cfhrwES@_H--il={jd^HLp;$XV2&w(mM#2PahN7Q zYZp&!SD3uGqjuX)!pQSzJHo#BU|6!3QgGt<`Yl}bB%%p82_%Zx_MWT@rJybd)yjkA z3Z=bm@LU*as4rkggfSRU=V1gq`7vz$YNy2k=6UuLc`z**)JF?i?CpV}kV@za(Pu(f<<1k`z9i#Tv%fcetT9BLo`=pH72^di^yKw=R z|3GleGWch~6nLy4C)0zK!OYo+WV!SKxQ^&^1k)=O_F!Q4U3~r_8F%gfnX*KLM?VmU zqbbb^fF!(_Y-Hzga}%Gcm)S((qI8{7cD@Hw>qj`TbvlfwJqbU;uI;iU90Q7k0Rtj( zr<|W`mGOcl;oF+15d2EOl36t*P=*QHLr@7C>}VC^z=IPRb&v4NMI_pJTz?z?v<%)p z4LgeL*>I|09Mi8w^6$kZ(jzTmqekis5E&0s+XOW{vQe}|BB||-G~5V3-ik4qf^krz zABNyq+`mDNUSJ~#)v}`*$r8y3YYf~B+uzWqYzUfRg6H9cWm7*Q2%!lgW1i;0-NH=B zm+X_I?ibzkbi%Ua$P$wzNqJiG8br8;?Q69ICJaOBgPVpL)chZTH3uBz?lp+|@Lj2O zw4nw@Wp3?hhW`6Xdq5cjMM)R%&3>D+|k;SHjYa6+G89e9cd-qqrCfbrmN zz=lDoIl_sSZg@P~R!b~FLiP;;P2eH;bH%Iojv#gz5f5$+jL$|--{L_FkwXO<-2@C> zks`H#&7 zk6_oq>5(bF6jre|9^jixF{vEkdTl?FbTJ-l7fjK!foL5&))sal5SzwVpT?|-u)|0+ z@ZYaVX|zZY=_#&%?`gwxH{8!@>8B^Ba~ogHyT zmhW2y)FE?Hmh6opyc3!0VE04y=vr|(SNstTWhl-S<d8yH_9)E07k;0TLQNSdLH} zDV=d<9N`Iq&$B$SUx(?lV;dNtyh^`%vZQkp$}X2@U5pSf(Fs1l=bu1b7P-liZuAjv z5aXuD#GffSBqIo=0Z(Q@q^5EAa%5`@?inF?N!VpjgWUNSl-&sS%2Z;UoKE5bx30vP z5^>@10g+QUf=EW!t|u@&oDhFmzr-No<;I%t&>4+TaK!6@|>Q@XBJ}KBQV>f;c?4& zd<&A-i1S;Ukd7izDzfy#JU)cP-(fA}hf7dii=YU$M&KZ~EQZsENCj%H0pe_3ilmR~ zyVbs>AHP|;k3$@>sXOKp$WND1Av7)2($C@O9h z_g=u zw*R#d{#Q+)F%y-geBoE9>_y3}i$smUx?yA+x#&eX=(rkwV;K>tYF~{7QILY)iGn zqWYfFgfKsPM}Vl9&h4+@8;^7MQdoMBMD-3X=)#Mu#m~*(!i-XB28`!qZs-AhIW~bO z5Q=mA-%!0t%v#PMeVt}I$}dmjYwyF-ns)}czVSb|W#Lr(Q(;(;RmB*iX@T3Wkeuzr@%nTz|FxwjxRvpmGkk%q8lf_K1x0`U`FH z3N>_&UAy4hDu0%dI>S?{{{;Lx`NC>{SnVm{%1vDM6yIITo96PJ*DUGN+Ac%6~o2VVf{cXZ$O|2BAEw7+vYav~x12(Tt4m!5T?S<{7)&xD z8HCATQBsu1pOQ(}xuUp1Sq`5M0ch##*Of=G7-6s=Q?}>JtORTgevrT5_@yc@l4vH# zUkwsN$mjPvc$S^dVs+zFztz#z3Sub3Yy*~|J*m#XoL_!!&VQ|HWb5kSSR8+i jB#Km@BQ*np*PQ+bS}{J=%uygs00000NkvXXu0mjfN~e>V literal 0 HcmV?d00001 diff --git a/reports/工程改动报告-工程清理批-2026-11-02.md b/reports/工程改动报告-工程清理批-2026-11-02.md new file mode 100644 index 00000000..91905693 --- /dev/null +++ b/reports/工程改动报告-工程清理批-2026-11-02.md @@ -0,0 +1,75 @@ +# 工程改动报告——工程清理批(2026-11-02) + +接收方:待办清单 7 条目(本批完成整条删除——palette_check 基线建档/CAMP_HEADER_BAND 评估/ui_kit 立绘注释/迭代 43 四色墨断言/断言提取器 check_quiet/run_all_gates 02 传参〔已完成漏删〕/main.gd 死 preload)。 + +## 一、批定位 + +工程改动批(用户发令直改,不写卡)。worktree `eng-cleanup`,基点 7e9e57fd,基点即 master 尖端。七件:六件本批落地+一件核查确认已完成(run_all_gates 02 传参)。 + +## 二、逐件落地 + +### 件 1 palette_check 基线建档+双门机检化 + +- 基线目录 `game/tests/golden/palette_baseline/`(图像白名单在册目录)两张条带 PNG:`ui_tokens.png` 92 色(ui_kit.gd 全量 Color8 常量唯一值快照)+ `art_snapshot.png` 1274 色(现役素材 128 张 PNG 唯一色并集快照);并集 1346 色=双门②「新增色 vs 既有色板」的既有色板机检承载物。 +- 新件 `tools/gen_palette_baseline.py`:基线建档与刷新器(token 提取剔除注释行;素材目录零 PNG 拒绝生成空快照)。 +- `tools/palette_check.py` 零代码改动——头注补基线构成与维护纪律、退出码描述校正(单张超 32 色是 WARN 非 FAIL)。 +- 闸机接线:`tools/run_all_gates.sh` 新增 **05b 色板闸**(code 域;--quick 与影响面选闸 SKIP;素材齐盘预检之后段执行)——扫 `game/assets/art` 全目录对基线判新增色近色红。 +- 口径边界(呈报):门①语义检查属设计面人工核对(§4.2 色相语义判域),不入本器执法面;48 token 计数上限不接闸——ui_kit 现役唯一色值 92 与「48 上限」的成员名单口径差归 art-bible §4.1 owner 裁定,本批不自裁。 +- 维护纪律:素材批收尾跑 `python tools/gen_palette_baseline.py` 重生成全套并随批提交——新色过门后须入基线,否则下批扫描把已过门的新色再报新增;两张 PNG 缺一即漏判。 + +### 件 2 extract_checks.py 补 check_quiet 静默通道 + +- `CALL_RE` → `check(?:_quiet)?\(`、`DEF_RE` 同扩(func check / func check_quiet 定义行双拦)、`collect_call` 按实际匹配长度偏移;check_quiet 通道契约 cond 在前,条目 quiet 列记 `channel:check_quiet`。单趟正则无重叠匹配,结构上不双计。 +- 自证三重(当轮实跑):①双计等式——旧两正则匹配数之和 2155 == 新 CALL_RE 2155(全 tests 面);②新旧版条目对拍 1719 → 2133,差 414 条 check_quiet 入账(grep 调用行实数 416,差 2=定义行与注释行不入账,方向自洽);③`--extract` 生成临时清单后 `--diff` 往返对账 PASS 零差异(标签/cond/计数三对齐)。 +- 验证集清单已随验证体系整改阶段 2 退役,`--diff` 无存档参照——对账自证以临时清单往返承载,语义等同。 +- 随批换代 `design/engineering/test-conventions.md` §5.2 工具面局限备案句(2026-10-27 立的「断言消息不进扫描面——验收尾缀 grep 对该通道失效」已消除,留存会漂移);文档设计面仅此一句现状描述更新,申报。 + +### 件 3 意图徽标四色墨机检断言 + +- `tools/render_sample_sheet_v3.py` `run_screen_checks` 增 **S1b**:意图徽标四色墨(攻击/增益/减益/蓄力)对 PANEL_DATA 垫牌(#E9D9B8,与绘制矩形 fill 同源)≥4.5:1 色值对表断言,四墨值即脚本意图色表四值,零新增色。 +- 当轮真实读数:攻击 5.62/增益 5.10/减益 4.97/蓄力 5.21——与独立审计复算区间 4.97–5.62 逐位一致。 +- 样张机检 31/31 全绿。V10 改前基线对拍图属 artwork(不入 git)环境件,worktree 用 `--save-baseline` 重建(本批零素材零绘制变更,基线等值)。 + +### 件 4 main.gd 拆件遗留死 preload 清理 + +- 逐条 grep 复核(登记纪律):死码 **10 条**——登记 8 条,复核多出 2 条(三场景 preload 中 AdventureScreenScene 登记时另有消费面、UiAssembler 登记时在役;现全零)。UiAssembler 唯一非定义出现=组合根接线段注释提及类名(非常量使用)。 +- 7 具名(TuneSimController/DebugSessionScript/TreasureInteractController/CurioInteractController/CampShopPresenter/BoardResolversScript 等)消费面已迁 `main_ui_build.gd:9-13`(拆件自持 preload)——main.gd 旧常量=拆件残留重复声明;三场景消费面=system_test.gd `load()` 与 main.tscn,删常量不触。 +- 删除 10 条 const preload,保留 Narrator/MainUiBuild/MainAdventureFlow/MainOverlayFlow/MainDebugFlow 五条在役。 + +### 件 5 过时注释换代 + +- `game/presentation/views/ui_kit.gd` TEX_HERO_PORTRAIT 行注释「48px 档」→「素材=原稿分辨率,显示档缩放读 standee_motion PORTRAIT_DISPLAY_H」(迭代 48 显示档批现行口径)。 +- `tools/path_check.py` 头注删「· 立绘定档批 2026-10-07」日期批注记(变更叙事黑名单类);47 行键集指名核实现行仍在役(standee_asset_check 现行 import STANDEE_DISPLAY_H),不改。 + +### 件 6 ui_kit CAMP_HEADER_BAND 令牌退役评估 + +现役消费面 4 处逐一核过:`level_map_screen.gd:107/144`(关卡屏头带与地图条)、`shop_overlay_view.gd:49`(商店头带)、`ui_kit.gd` KeystoneBadge 工厂(钥石徽描边——消费方=营地覆盖层+状态面板钥石余额行)。 + +**结论**:「退役删除」不成立——4 处在用且全是活面板绘制面;营地域柜台头带语义岗已随迭代 47 四柜台覆盖层退役,令牌现役值 #6E4526 只剩材质棕底色语义(木色头带/徽章描边)。**处置=改名中性化**(脱 CAMP_ 前缀,名随现役语义,如 WOOD_BAND 一族)归 ui_kit 令牌批顺带;改名零值变化零渲染变化,届时逐点核后动。维持原登记口径「退役归 ui_kit 令牌批顺带处置、非独立强删」。 + +### 件 7 run_all_gates 02 关联档传参(核查确认已完成) + +`d32ff342`(工程小件批·件 1)已落两案中的「解析器补逗号切分」案:`run_all.gd` 选跑解析补 `split(",")`,闸脚本逗号串传参与之配套,孤立验证四套件全绿。本批零改动,条目属完成漏删。 + +## 三、待办清单 + +删 7 条(整条删除,状态机出口):palette_check 基线建档/CAMP_HEADER_BAND 评估/ui_kit 立绘注释/迭代 43 移交小件(①能力清单补行已随 2026-10-31 写卡批落位、②四色墨断言本批落)/断言提取器改版/run_all_gates 02 传参(d32ff342 已完成)/main.gd 死 preload。流水线闸复验 PASS(33 条目/49 总表行)。 + +## 四、窄验读数(worktree 内当轮实跑) + +| 验证 | 读数 | +|---|---| +| palette_check 带基线扫 art 全目录 | 128 张 0 红 0 新增色 | +| presentation 单元套件(main.gd/ui_kit.gd 编译面) | 17 suites 全绿 | +| 冒烟 run_smoke | 15 项 0 失败,三闸全过 | +| 样张 render_sample_sheet_v3 | 31/31 全绿(含新 S1b) | +| path_check | 0 处问题 | +| extract_checks | 双计等式过/1719→2133/往返对账 PASS | +| pipeline_gate | PASS(33 条目/49 总表行/交叉核 3 链) | + +全量回归归合回后本地 CI(post-merge 钩子自动跑,含新 05b 色板闸)。 + +## 五、边界与移交 + +- 48 token 计数上限的机检承载与门①语义检查不属本批(口径归 art-bible owner),呈报待裁。 +- 05b 色板闸的基线维护义务(素材批收尾刷新)已写进 palette_check.py 头注与 gen_palette_baseline.py 头注,闸机注释同步点名。 diff --git a/tools/extract_checks.py b/tools/extract_checks.py index 5183eeb6..c1344161 100644 --- a/tools/extract_checks.py +++ b/tools/extract_checks.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- r"""extract_checks.py — 断言静态提取器(验证集清单生成与出口对账) -机器提取宿主脚本的全部静态 check( 调用点(每个调用点记录:所在文件、所在函数、 +机器提取宿主脚本的全部静态断言调用点(每个调用点记录:所在文件、所在函数、 行号、标签字符串字面量原文、cond 表达式原文),提供两种模式: 用法: @@ -19,10 +19,11 @@ r"""extract_checks.py — 断言静态提取器(验证集清单生成与出口 断言,对账时以「新增」出现(非迁移面),出口判定以显式模式为准。 提取口径: - - 静态 check( 调用点,两种通道都认:smoke/系统宿主的 check(cond, label)(cond 在前) - 与单元/集成宿主的 Kit.check("label", cond)(点前缀=标签在前);`_check(` 等同名 - 前缀调用非标准通道,不取。 - - 调用点可跨行:从 `check(` 起括号配平归集完整实参文本(() [] {} 三种括号都计深度); + - 静态断言调用点,三通道都认:smoke/系统宿主的 check(cond, label)(cond 在前)、 + 单元/集成宿主的 Kit.check("label", cond)(点前缀=标签在前)、静默收集通道 + Kit.check_quiet(cond, label)(cond 在前,条目 quiet 列记 channel:check_quiet); + `_check(` 等同名前缀调用非标准通道,不取。 + - 调用点可跨行:从调用名起括号配平归集完整实参文本(() [] {} 三种括号都计深度); 字符串字面量内的括号/逗号/井号、行尾注释、转义序列均不参与结构判定(码位掩码单趟预扫)。 - cond 摘要=cond 原文跨行折叠为单行(连续空白并一空格);标签原文=标签实参里的字符串 字面量逐字保真(含引号与转义序列原样,禁改写);标签实参若带格式化/拼接后缀 @@ -64,8 +65,8 @@ def default_sources(): files.extend(sorted(p.rglob("*.gd"))) return sorted(files) -CALL_RE = re.compile(r"check\(") -DEF_RE = re.compile(r"^\s*(static\s+)?func\s+check\s*\(") +CALL_RE = re.compile(r"check(?:_quiet)?\(") +DEF_RE = re.compile(r"^\s*(static\s+)?func\s+check(?:_quiet)?\s*\(") FUNC_RE = re.compile(r"^(static\s+)?func\s+([A-Za-z_][A-Za-z0-9_]*)") LITERAL_RE = re.compile(r'"((?:[^"\\]|\\.)*)"') OPENERS = "([{" @@ -188,9 +189,9 @@ def split_args(body): return args -def collect_call(joined, start): - """从 check( 的 start 起括号配平归集调用。返回 (body, end_pos);不配平返回 None。""" - i = start + len("check(") +def collect_call(joined, start, call_len): + """从调用名起点起括号配平归集调用。返回 (body, end_pos);不配平返回 None。""" + i = start + call_len depth = 1 in_str = False parts = [] @@ -228,7 +229,7 @@ def collect_call(joined, start): def extract(src_path: Path): - """提取单文件全部静态 check( 调用点。返回(条目列表, 函数表),条目保持源码顺序。""" + """提取单文件全部静态断言调用点(check/check_quiet)。返回(条目列表, 函数表),条目保持源码顺序。""" src = src_path.read_text(encoding="utf-8") lines = src.split("\n") funcs = func_table(lines) @@ -247,28 +248,32 @@ def extract(src_path: Path): entries = [] for m in CALL_RE.finditer(joined): if not mask[m.start()]: - continue # 字符串字面量内 / 注释里的 check( 字样 + continue # 字符串字面量内 / 注释里的调用名字样 ln = line_of(m.start()) if DEF_RE.match(lines[ln - 1]): - continue # func check 定义行 + continue # func check / func check_quiet 定义行 prev = joined[m.start() - 1] if m.start() > 0 else "" if prev and (prev.isalnum() or prev == "_"): continue # `_check(` 等同名前缀——非标准通道 - label_first = prev == "." # Kit.check("label", cond)——点前缀=标签在前 - body, end_pos = collect_call(joined, m.start()) + is_quiet = m.group(0).startswith("check_quiet") + if is_quiet: + label_first = False # Kit.check_quiet(cond, label)——cond 在前 + else: + label_first = prev == "." # Kit.check("label", cond)——点前缀=标签在前 + body, end_pos = collect_call(joined, m.start(), len(m.group(0))) if body is None: - raise SystemExit("[extract_checks] FAIL:%s 行 %d 起的 check( 括号不配平到文件尾——先查解析缺口" + raise SystemExit("[extract_checks] FAIL:%s 行 %d 起的断言调用括号不配平到文件尾——先查解析缺口" % (src_path.name, ln)) args = split_args(body) if len(args) not in (2, 3): raise SystemExit( - "[extract_checks] FAIL:%s 行 %d 的 check( 拆出 %d 个实参(预期 2/3)——解析缺口,先查再跑" + "[extract_checks] FAIL:%s 行 %d 的断言调用拆出 %d 个实参(预期 2/3)——解析缺口,先查再跑" % (src_path.name, ln, len(args))) if label_first: label_expr, cond = args[0], args[1] else: cond, label_expr = args[0], args[1] - quiet = args[2] if len(args) == 3 else "" + quiet = "channel:check_quiet" if is_quiet else (args[2] if len(args) == 3 else "") lm = LITERAL_RE.search(label_expr) if lm is None: continue # 标签实参无字面量(wrapper 直传变量——既有套件先例 reward_overlay_test _req) @@ -336,7 +341,7 @@ def render_list(entries, funcs_by_src, src_names, carry=None) -> str: out.append("# 验证集清单(断言快照·冻结)") out.append("") out.append("> 生成日期:%s · 基点 commit:`%s` · 源:%s" % (date.today().isoformat(), base_commit(), "、".join(src_names))) - out.append("> 提取口径:静态 `check(` 调用点,括号配平归集(可跨行);缺省源=三宿主遍历") + out.append("> 提取口径:静态 `check(`/`check_quiet(` 调用点,括号配平归集(可跨行);缺省源=三宿主遍历") out.append("> (unit/**+integration/**+system_test.gd)。本基点实测 %d 个静态调用点;行级" % len(entries)) out.append("> `grep -c \"check(\"` 是另一口径(含 `func check(` 定义行与注释行),两口径各自浮动,") out.append("> 禁互相换算(tests/README「断言计数双口径」)。运行时计数大于静态计数=循环展开条目。") diff --git a/tools/gen_palette_baseline.py b/tools/gen_palette_baseline.py new file mode 100644 index 00000000..78d58086 --- /dev/null +++ b/tools/gen_palette_baseline.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""色板基线生成器——palette_check 双门②基线的建档与刷新件。 + +产出两张 1×N 条带 PNG 落 game/tests/golden/palette_baseline/(图像白名单在册目录): + ui_tokens.png = ui_kit.gd 全量 Color8 常量唯一色值(token 板现役值快照) + art_snapshot.png = 现役素材(game/assets/art 递归)全量唯一色快照(像素板+各屏环境子板) + +palette_check --baseline 取目录下全部 PNG 的唯一色并集为「既有色板」;基线缺一张 +即漏判——基线刷新必须重生成全套。维护纪律:素材批收尾跑一次本器刷新并随批提交 +(新色过门②后须入基线,否则下批扫描把已过门的新色再报新增)。 + +用法: + python tools/gen_palette_baseline.py [--repo <仓库根>] +退出码: 0 成功 / 2 前置缺位(ui_kit.gd 或素材目录缺 / 素材零 PNG) +""" +import argparse +import os +import re +import sys + +from PIL import Image + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from palette_check import palette_of # 排除全透明的唯一色提取——与检查器同口径 + + +def strip_comments(text): + """剔 GDScript 行注释与字符串字面量,防注释里举的色值被误收进 token 快照。""" + out = [] + for line in text.split("\n"): + i = line.find("#") + if i != -1: + line = line[:i] + out.append(line) + return "\n".join(out) + + +def token_cols(ui_kit_path): + """ui_kit.gd 全量 Color8 唯一色值集合。""" + text = strip_comments(open(ui_kit_path, encoding="utf-8").read()) + vals = re.findall(r"Color8\((\d+),\s*(\d+),\s*(\d+)\)", text) + return sorted(set((int(r), int(g), int(b)) for r, g, b in vals)) + + +def scan_dirs(roots): + """递归扫 PNG,唯一色并集(含像素位置首见序不保——并集无序)。""" + cols = set() + count = 0 + for root in roots: + for dirpath, _, names in os.walk(root): + for fn in sorted(names): + if fn.lower().endswith(".png"): + c, _n = palette_of(os.path.join(dirpath, fn)) + cols |= c + count += 1 + return cols, count + + +def write_strip(cols, out_path): + """1×N 条带 PNG(一色一像素列)。""" + cols = sorted(cols) + im = Image.new("RGB", (len(cols), 1)) + for i, c in enumerate(cols): + im.putpixel((i, 0), c) + im.save(out_path) + return len(cols) + + +def main(): + if hasattr(sys.stdout, "reconfigure"): + sys.stdout.reconfigure(encoding="utf-8", errors="replace") + ap = argparse.ArgumentParser(description="色板基线生成器(token∪素材快照)") + ap.add_argument("--repo", default=".", help="仓库根(含 game/ 与 tools/)") + args = ap.parse_args() + + ui_kit = os.path.join(args.repo, "game", "presentation", "views", "ui_kit.gd") + artdir = os.path.join(args.repo, "game", "assets", "art") + outdir = os.path.join(args.repo, "game", "tests", "golden", "palette_baseline") + if not os.path.isfile(ui_kit): + print("[gen_palette_baseline] FAIL:ui_kit.gd 缺:%s" % ui_kit) + return 2 + if not os.path.isdir(artdir): + print("[gen_palette_baseline] FAIL:素材目录缺:%s" % artdir) + return 2 + os.makedirs(outdir, exist_ok=True) + + tcols = token_cols(ui_kit) + n_t = write_strip(tcols, os.path.join(outdir, "ui_tokens.png")) + + acols, npng = scan_dirs([artdir]) + if npng == 0: + print("[gen_palette_baseline] FAIL:素材目录零 PNG(素材未同步)——拒绝生成空快照") + return 2 + n_a = write_strip(acols, os.path.join(outdir, "art_snapshot.png")) + + union = set(tcols) | set(acols) + print("[gen_palette_baseline] 已生成:ui_tokens.png %d 色 / art_snapshot.png %d 色" + "(素材 %d 张 PNG);基线并集 %d 色 → %s" + % (n_t, n_a, npng, len(union), outdir)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/palette_check.py b/tools/palette_check.py index b1cc3d87..9a0575ee 100644 --- a/tools/palette_check.py +++ b/tools/palette_check.py @@ -17,12 +17,21 @@ 另:必须排除全透明像素 (0,0,0,0)(同standee_asset_check 的坑)。 +基线(双门②「新增色 vs 既有色板」的既有色板机检承载物): + 目录 = game/tests/golden/palette_baseline/,两张条带 PNG(1×N,一色一像素列): + ui_tokens.png = ui_kit.gd 全量 Color8 token 快照(token 板现役值) + art_snapshot.png = 现役素材全量唯一色快照(像素板+各屏环境子板) + 两张并集=「既有色板」。缺一张即漏判——基线刷新必须重生成全套。 + 门①语义检查属设计面人工核对(§4.2 色相语义判域),不在本器执法面。 + 用法: - # 主用法:扫目录,新增色相对 --baseline 判定 + # 主用法(闸机 05b 色板闸承载):扫目录,新增色相对 --baseline 判定 python tools/palette_check.py <目录> --baseline <基线目录> # 无基线:只出读数(单张色数/ 近色对计数),不判红 python tools/palette_check.py <目录> -退出码: 0 通过 / 1 有红灯(仅新增色违规或超单张上限时) + # 基线建档与刷新:重扫现役素材∪token 重生成基线条带(素材批收尾动作,随批提交) + python tools/gen_palette_baseline.py +退出码: 0 通过 / 1 有红灯(仅新增色近色不过门②时) """ import os import sys diff --git a/tools/path_check.py b/tools/path_check.py index 60f979b5..eba52dbf 100644 --- a/tools/path_check.py +++ b/tools/path_check.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -"""B3 路径核对器(圣经 §8.3② 挂点实现 · 立绘定档批 2026-10-07)。 +"""B3 路径核对器(圣经 §8.3② 挂点实现)。 职责:扫描 asset-path-map.md 声明的全部路径 + 代码侧素材常量, 报「悬空(声明存在但盘上无)/ 退役未清(仍引用已退役命名)」。 diff --git a/tools/render_sample_sheet_v3.py b/tools/render_sample_sheet_v3.py index f540deb8..744f007e 100644 --- a/tools/render_sample_sheet_v3.py +++ b/tools/render_sample_sheet_v3.py @@ -1209,6 +1209,18 @@ def run_screen_checks(scr, zones, board_origin, frames_strip, frames_meta, s6_im weakest = min(ratios, key=lambda r: r[1]) check("S1", "整屏①全部文字对直接背景 ≥4.5:1(WCAG AA)", all(r[1] >= 4.5 for r in ratios), "最弱 %s=%.2f;全部 %s" % (weakest[0], weakest[1], ratios)) + # S1b 意图徽标四色墨对 PANEL_DATA 垫牌 ≥4.5:1(色值对表——镜像实装同值;垫牌=ui_kit PANEL_DATA #E9D9B8, + # 与 draw_standee 徽标垫矩形 fill 同源;四墨=意图色表 damage/buff/debuff/charge 四值) + panel_data = (233, 217, 184) + intent_inks = [("攻击墨", (150, 44, 36)), ("增益墨", (30, 90, 150)), + ("减益墨", (122, 66, 148)), ("蓄力墨", (116, 80, 11))] + iratios = [(n, round((max(wcag_lum(a), wcag_lum(panel_data)) + 0.05) + / (min(wcag_lum(a), wcag_lum(panel_data)) + 0.05), 2)) + for n, a in intent_inks] + iweak = min(iratios, key=lambda r: r[1]) + check("S1b", "意图徽标四色墨对 PANEL_DATA 垫牌 ≥4.5:1(WCAG AA·色值对表)", + all(r[1] >= 4.5 for r in iratios), + "最弱 %s=%.2f;全部 %s" % (iweak[0], iweak[1], iratios)) # S2 整屏②明度三档带 + 世界底层两子带(§2;舞台=实测区域读数,格底=实测板面;WCAG 0–1 域) stage_l = _region_wcag(scr, (300, 190, 600, 220)) bx, by = board_origin diff --git a/tools/run_all_gates.sh b/tools/run_all_gates.sh index 4c38787b..341b4efe 100644 --- a/tools/run_all_gates.sh +++ b/tools/run_all_gates.sh @@ -413,6 +413,14 @@ if [ $QUICK -eq 1 ] || [ $NONBEHAVIOR -eq 1 ]; then else gate "05 渲染闸" "render.log" bash "$REPO/tools/render_gate.sh" "$GAME" fi +# ── 5b. 色板闸(§4.1 新色双门②:素材新增色 vs 基线〔token∪素材快照〕近色判红; +# 门①语义检查属设计面人工核对不入机检;基线刷新=tools/gen_palette_baseline.py,素材批收尾动作)── +if [ $QUICK -eq 1 ] || [ $NONBEHAVIOR -eq 1 ]; then + NAMES+=("05b 色板闸"); EXITS+=("SKIP"); LOGS+=("") + echo ""; echo "[gates] 05b 色板闸 → SKIP(--quick 或 影响面选闸:素材色板面不随测量面改动开闸)" +else + gate "05b 色板闸" "palette.log" "$PY" "$REPO/tools/palette_check.py" "$GAME/assets/art" --baseline "$REPO/game/tests/golden/palette_baseline" +fi fi # ══ 文档域(6–8e)══ if in_domain docs; then diff --git a/待办清单.md b/待办清单.md index a7ac2e85..9f0900c5 100644 --- a/待办清单.md +++ b/待办清单.md @@ -2,22 +2,6 @@ 本清单是流水线的唯一登记处:以后才做的事在此登记一条,随流水线段推进改状态,做完整条删除(条目记进度,不是各段的开工前置);各系统文档的「待办」节只留一行指路存根,不再自建条目。条目格式(标题=登记元数据含可选优先级,正文=实况/缺口/改动面/状态四属性)与状态机以 [doc-conventions §12.1](design/engineering/doc-conventions.md) 为权威。 -#### palette_check 基线建档与双门机检化(2026-11-02 登记,来源=批次移交) - -**实况**:证据=迭代 47 实现报告 §7.2(已按吸收即死退役,git 提交 3443890d 可考)——卡④ V10 素材级读数:15 张素材 palette_check 只读模式 0 红灯 0 新增色;但 48 令牌 baseline 目录在库缺位(机检无对照基线),§4.1 两道门(语义检查+RGB 三通道差)的双门机检化缺承载。归工程改动批:建 baseline 目录+闸件双门判据落地。 - -**改动面**:工具代码 - -**状态**:待执行 - -#### ui_kit CAMP_HEADER_BAND 令牌退役评估(2026-11-02 登记,来源=批次移交) - -**实况**:证据=迭代 47 审计记档 2 订正在案(git 提交 3443890d 可考)——营地域柜台头带消费面已随迭代 47 四柜台覆盖层退役注销(ui_contrast 令牌表四行随形态注销),现役消费面仅剩 keystone_badge 工厂与关卡屏/商店两处非营地域用途。处置口径(实现批备案):退役归 ui_kit 令牌批顺带处置、非独立强删;届时逐点核消费面后删令牌或改名。 - -**改动面**:游戏代码 - -**状态**:待执行 - #### hobgoblin 内容三件套补齐(2026-11-01 登记,来源=审计发现) **实况**:敌人表 hobgoblin 行(寻址键 (1, battle, 3))数值完整在役、战斗正常运行,但内容三件套未交付——立绘、敌种语义模板、敌人系统.md 敌种表行均缺,呈现面因语义模板未成文无定义可依。登记凭据=[敌人系统](design/gdd/systems/战斗循环/敌人系统.md) v1.1「hobgoblin 缺口登记」节(2026-10-13 迭代 24 反哺④)。 @@ -38,22 +22,6 @@ **状态**:待文档设计 -#### ui_kit.gd 立绘注释陈旧顺带换代(2026-11-02 登记,来源=批次移交) - -**实况**:证据=迭代 48 实现报告§六与验收审计观察项(已退役,git 提交 4c94eee3 可考)——`ui_kit.gd` TEX_HERO_PORTRAIT 行注释仍写「48px 档」(现行=原稿分辨率+显示档缩放),`path_check.py` 一处注释表述也已改指外;零行为,随下次触碰该两件的批次顺带换代(顺带件,不独立出批)。 - -**改动面**:游戏代码 - -**状态**:待执行 - -#### 迭代 43 批后移交小件——能力清单补行+四色墨断言(2026-10-30 登记,来源=批次移交) - -**实况**:证据=迭代 43 反哺点清单 9/13(已按吸收即死退役,git 历史可考)。逐条:①**能力清单补行**——game/tests/README.md 能力清单无战斗一屏样张批 V5–V9 代表用例行(卡片成文早于清单 2026-10-29 改版定稿),归写卡段随下一写卡会话按 test-conventions §8.3 补行(能力=站桩呈现定值与素材绑定;代表用例=`game/tests/unit/presentation/standee_present_values_test.gd:_init`,真实入口=`UiKit.load_tex()`/`StandeeBody.name_line_probe()`),并同步覆盖域表「战斗表现.md」行。②**意图徽标四色墨补机检断言**——样张脚本 S1 文字对比为绘图用色值对表,意图徽标四色墨(对 PANEL_DATA 垫牌)未入 CHECKS;独立审计复算 4.97–5.62 全 ≥4.5 事实成立仅缺机检断言,`tools/render_sample_sheet_v3.py` CHECKS 补一条对表断言(values 全在册,零新增色)。**2026-10-31 写卡会话落位**:①能力清单补行已随「站桩名字行提档与地台色合并批」卡片成文同批入表(能力行+覆盖域表战斗表现.md 行);②四色墨断言仍待执行。 - -**改动面**:游戏代码+工具代码 - -**状态**:待执行 - #### 架构审查优化讨论——全库架构审计读数的逐条裁决与整改分批(2026-10-29 登记,来源=审计发现) **实况**:2026-10-29 全库架构静态审计完成,读数见 reports/审计-全库架构审查-2026-10-29.md(七节:总评/健康面/P0/P1/P2/待裁点/取证口径;零测试执行零引擎运行,全部结论带 文件:行号)。健康面已逐条核干净:Core 零 UI 八项判据全零命中、core 内 RNG 单点 100% 成立、字符串式信号连接全库 0 处、core 层零超长函数、19 表 ↔ 19 schema 一一对应、无循环 preload。问题集中在三条「写了没闸守」的纪律被实际破坏:①数值单一事实源被 18 处硬编码击穿,最危险两处是 `presentation/main.gd:787` 与 `:790` 把 `rap_refresh_cost=8` 与 `refresh_cap_per_round=2` 写死进提示文案(紧邻 783 行是正确读表的),表改文案不改、玩家直接受错误数字;另有 4 组代码自标「机制结构常量/产出约束」的字面量(`node_map_generator.gd:12` `MAX_WIDTH`、`action_economy.gd:14` `CHARGE_LAYER_CAP`、`board_data.gd:9` `SPAWN_AREA_CELLS`、`node_map_generator.gd:83-94` 域字面量)是否入表待裁。②`game/sim/` 与 `game/core/` 四组平行实现——扫雷推理引擎双份(`board_generator.gd` `measure_inferability` 族 vs `auto_player.gd` `_deduce` 族,输入集口径不同:前者含 safe_set oracle、后者 no-peek)、伤害掷点期望重算(`damage_probe.gd:196-201`)、档位排序与驱动循环双份(`level_autoplay.gd` vs `treasure_item_table.gd:44` 与 `battle_driver.gd:17`)、FakeDB 伪造表喂生成器——直接威胁「模拟读数 = 游戏真实数值」这一数值验证前提。③RNG 单点纪律在 core 外失守(sim 4 处/probe 1 处/tests 3 处自建 `RandomNumberGenerator`,均显式定种、确定性尚存),而 `static_scan.sh` 的 S1/S2 扫描面只含 `DIR_CORE` + `DIR_PRES`。守卫面另有三缺口:S8 是 9 文件显式清单(新增结算文件忘登记=静默不扫,缺位自检只防删改不防增)、S9 类型闸与 S13 质量闸扫描面止步于 core+data+presentation(sim/probe/tests 三层除 S11/S12 外零闸)、S13 三处豁免常态化到最大户文件(`battle_orchestrator`/`main.gd`/`tune_sim_controller`);另有四个 core 文件零测试点名(`attune_loadout`/`battle_fx_host`/`meta_state_store`/`slot_store`)。P2 级:`core/settlement/` 五段类直读写编排器私有成员 20+ 处(`oc._damage.*`/`oc._enemy_system.*`,GDScript 无编译期检查、改名静默断裂);架构文档三处漂移(`architecture.md:110` 登记的 `core/hero_ledger.gd` 盘上不存在且 `hero_ledger_test.gd:171` 显式断言它必须不存在、`:135` 行数过期、EC8 热重载门后 `ConfigDb.reload()` 零调用方且走 `load()` 拿不到磁盘新值);class_name 级双向依赖(`core/config_db` → `data/schemas/board_gen_table` → `core/board_data.SPAWN_AREA_CELLS`)与 `NODE_TYPES` 词表双份;`MetaProgression` 是唯一用 `get_node("/root/...")` 取依赖、唯一跨 Autoload 直调的单例。 @@ -87,14 +55,6 @@ **状态**:文档设计已闭合 -#### 断言提取器改版——覆盖 Kit.check_quiet 静默通道(2026-10-29 登记,来源=会话提及) - -**实况**:`tools/extract_checks.py:67` 的 `CALL_RE = check\(` 只认即时通道,静默收集通道 `Kit.check_quiet(cond, desc)` 静态站点实测 407 个在提取口径外(证据=`grep -rn "check_quiet(" game/tests --include="*.gd"` 实数;test-conventions §5.2 已备案该工具局限)。能力清单以 `文件:函数` 为锚,不受影响;但要把断言面全账纳入机器对账(重建账本或全量断言面审计),须先改版提取器:识别 `check_quiet(` 并按反参序(cond 在前)提取标签与 cond。改版后须以全量套件跑一遍 `--diff` 自证提取面覆盖、且 `Kit.check(` 与 `check_quiet(` 不双计。 - -**改动面**:工具代码 - -**状态**:待执行 - #### 能力清单覆盖缺口补齐——六类无断言面或设计未定项(2026-10-29 登记,来源=会话提及) **实况**:证据=`game/tests/README.md` 覆盖域表 25 篇对照行(2026-10-29 立)。以下部分覆盖/未覆盖项作为缺口指针,逐项:①增益状态——只验契约词表与布尔受理,叠层/衰减/清除结算链无断言;②设置与本地化——减动效开关本体仅系统测试与冒烟覆盖、无单元/集成断言,多语言切换面未建;③音频——MVP 无音频,P1 后置无断言面;④战斗表现——死亡灰化与减动效演出档只有探针与人工目检;⑤难度曲线与Boss——难度曲线整链与 Boss 出场门控无专项断言;⑥锻造工坊——价格梯仅长剑路线逐级验,GDD 无验收标准节(`capability_audit` 验收标准豁免在册)。教学引导与生涯两篇的缺口归各自在册条目(「教学形态未定」「「生涯」界面——冒险中数据回看的唯一承接处」),不在本条。补齐时同批刷新覆盖域表与能力行,新增断言按 test-conventions §8.4 绑真实入口。 @@ -103,14 +63,6 @@ **状态**:待执行 -#### run_all_gates 02 关联档多套件词传参修复(2026-10-31 登记,来源=批次移交) - -**实况**:证据=iter45 实现报告 §5 遗留观察(已按吸收即死退役,git 历史可考)——`tools/run_all_gates.sh` 02 关联档以逗号连接多套件词传单个 `--only=a,b` 参数,而 `game/tests/run_all.gd` 选跑解析器不切逗号(多词整串做子串匹配→零命中 quit(2));iter45 施工时以多 `--only=` 旗标形态绕过。合回后 CI 跑全量档不经此路径不受影响,只挡开发期关联档窄跑。修法两案待裁:闸脚本改传多旗标,或解析器补逗号切分。 - -**改动面**:工具代码 - -**状态**:待执行 - #### 战斗域结构深拆批——效果发射端口+掷格/受理分件(2026-10-31 重立,来源=批次移交) **实况**:本条为 2026-10-27 原条目的重立版(原条目含宿主瘦身子项,该子项完成后随净零重立一并出清,git 历史可考)。三条同病根的结构债,需先一次设计讨论定端口形态,再谈切卡;`RewardEconomy` 的最小缝拆样本已由迭代 40 卡② 落卡。**宿主瘦身子项已完成(2026-10-30 随迭代 44 卡② 战斗编排归约批合回,合并提交 bee73db5——RoundCycle/BattleFacts 两新件建件,宿主实测 15 类变量/811 行,验收审计通过;原需求卡片与设计过程稿已按吸收即死退役,git 历史可考)。** @@ -126,14 +78,6 @@ **状态**:文档设计已闭合+已写卡+已编迭代 49 -#### main.gd 拆件遗留死 preload 清理(2026-10-31 登记,来源=批次移交) - -**实况**:证据=iter44 反哺点 11(已按吸收即死退役,git 历史可考;实现报告实现决定记录同载)——迭代 44 卡① 组合根注册面批拆件后,main.gd 遗留零使用 preload 常量 8 条(UiAssembler/TuneSimController/DebugSessionScript/TreasureInteractController/CurioInteractController/CampShopPresenter/BoardResolversScript/三场景 preload 中 main 零使用者三件);卡① 施工时仅清理与迁移直接相关的 ModalStack/RowPacer 两条,其余属存量债不扩范围,归工程改动直改批顺路清理。清理前须逐条 grep 复核零使用(布局批与 iter45 合回后消费面或有变化)。 - -**改动面**:游戏代码 - -**状态**:待执行 - #### 数值标定窗口总挂账——原九条数值类条目合并(2026-10-28 登记,来源=会话提及) **实况**:2026-10-28 用户令把九条数值类挂账合并为一条:削弱档位的最终数值/迭代 10 奖励重构联动欠账/调参批数值点评登记/三方向各自的解锁清单与定价/GP 经济换算失衡/天赋树实装批登记欠账余两件/商店独立刷新机制两参数/基线通关率越带加难杠杆扫描/成长系数节奏——原九条同步删除,内容全量迁入汇总文档,git 历史可考(本提交)。共同背景:M4 数值批卡已随 2026-10-16 删卡令退役;2026-10-18 用户裁=各条留待办清单、未设计未启动、不另行归属,未来数值标定窗口重开时重走设计段再写卡——本条沿用该裁定,重启条件=用户发令开窗口。合并动机=九条共享同一重启条件与同一执行形态(窗口内一次 MC 批量统一覆盖各条对比需求:全冒险期望+奖励期望),分散登记徒增维护面。逐条挂账明细、裁定史与相关文档见汇总文档。