Compare commits

..
Author SHA1 Message Date
DKChan 8ab93b3cd2 Merge branch 'master' into iter41 2026-10-28 23:51:21 +08:00
DKChan 9568b0b925 卡①T10+卡②T5(收尾产出物): 实现报告+反哺点清单两份落reports——报告含各卡状态/键账终局对拍(基线168=卡①85+卡②71+卡外12;终局16键在册NEW=0恶化=0;消失152=卡①85/85+卡②67;卡②两键inner class展平计数在案改善+两豁免申报v1.22:183/:311指针)/新件键账8件实测在阈/并master处置(冲突6文件并案+无点形态盲区17处+访问器迁移漏网3处修复+清单重生成1587对账)/实现决定记录(T7回滚事故+u14补做+白名单等价微调5笔)/测试移交清单(用户特许执行,全量档+按卡抽查套件+撤销证明+独立审计+基线refresh时机)/目检登记4项;反哺点=architecture v1.22四行现状改写+:104方法形态注记+两GDD行号随动+:267先行漂移疑似项呈报+卡②零改动核对结论;文本闸自检三件全绿 2026-10-28 23:50:30 +08:00
DKChan 38c9a0eba6 Merge branch 'master' into iter41
# Conflicts:
#	game/tests/unit/battle_settlement/roll_multiplier_test.gd
#	game/tests/unit/core/adventure_feats_test.gd
#	game/tests/unit/core/config_db_resolver_test.gd
#	game/tests/unit/core/level_shop_economy_test.gd
#	game/tests/unit/core/save_boot_no_activate_test.gd
2026-10-28 23:46:10 +08:00
DKChan 9bef58f99a 卡②T4补(呈现层结构收敛批): u14 ap_bar_view补做——T2b(525529ad)提交信息有记实际漏做,本次补齐——_init拆构建私有族四域(_build_ap_face AP计量+停手域/_build_rap_face RAP读数域[贴消费口]/_build_refresh_confirm破坏性确认异位chips域/_build_legend_refresh图例与弃图刷新域),装配序逐行原序保持零像素变化,S7源锚句(FS_CAPTION+STONE_DEEP行)逐字在位;_init 69行键消失,gdstyle 17→16键NEW=0恶化=0 2026-10-28 23:27:56 +08:00
DKChan 836c25e41c 卡②T4(呈现层结构收敛批): u13/u19–u24——u13 curio_interact_controller引用束注入(16抄写成员删除,正文读点改址ctx三束键名34处,构造单点零随动)+u19 hud_presenter参数束收拢(refresh 8→4ctx五键{settlement,runner,level_active,db,refresh_remaining}/_refresh_out_of_battle 6→4同ctx/tune_sim_report 10→5 stats六键)+消费点改址(main:819 ctx束形/tune_sim stats束形)+u20 CurioFlowContext三束收拢(16参16成员→4参4成员,views/getters/flow字典)+u21 CampFlowContext同形(12→4)+main_ui_build两构造行改束传参+u22 battle_narrator(bonus_card_text模板表化9→4返回+档位尾注/秘宝卡两域)+u23 tune_sim(print删除[信息由logger JSONL承载]+run统计束收拢stats字典+单局模拟提函数;await零触碰=v1.19测量面豁免在册)+u24 playtest_logger(print×2删除,路径信息已由toast/JSONL承载);gdstyle基线内28→24键[await与main两键豁免在册] 2026-10-28 15:15:42 +08:00
DKChan 525529ad88 卡②T2b(呈现层结构收敛批): u8–u17——u9 battle_stage_view(_init拆背景/光柱/世界/文本半区[轮次牌/中段行]/伴随件六族+_enemy_portrait_tex查表化+_spawn_enemy_standee循环提函数)+u10 curio_pick(_init拆顶条/主体两域+_icon_for_id映射表化)+u11 settings(_build拆头部/音量/全屏/演出/返回五行域)+u12 battle_log_view(_format_row按行型拆九私有格式化函数[effect/damage/ineffective/seal_miss/verdict/simple三型/default]+dispatch出参聚合)+u14 ap_bar(_init拆AP计量/RAP/确认/图例刷新四域)+u15 board_zone(_init拆视图/角标+棋盘子件域)+u16 board_fx(光带循环提_spawn_sweep_band)+u17 legend(行构建提_legend_row)+u8 ui_assembler(build_start_overlay拆双列/左列/右列/单立绘四族);gdstyle基线内45→28键 2026-10-28 15:09:02 +08:00
DKChan 123d7c7832 卡②T3a(呈现层结构收敛批): u18 ui_kit 公开面收敛——删frame_skinned/verb_button(全库零消费S8普查)+私有化四件(modal_dim/beams_rect/gradient_base/switch_toggle,消费方随动改址)+modal_shell六参→五参哨兵收拢(PANEL_DEFAULT常量三态:null=无面板/哨兵=默认样式盒/StyleBox=自定义,八消费点改址含settlement_review哨兵形)+bcard/BCard._init六参→五参opts束{price,footnote}(curio_pick/shop_overlay改址)+beams_rect像素循环拆_paint_beams(常量提类作用域)+BCard._init图标槽提_build_icon_slot;公开方法26→20键清偿,五键全清 2026-10-28 14:59:45 +08:00
DKChan 2cb6dd13e7 卡②T2a修: main.gd嵌套键归绿——战末账行束提_end_victory_opts装配单点(两调用点共用,opts键构成不变) 2026-10-28 14:54:16 +08:00
DKChan b33469ac09 卡②T2a(呈现层结构收敛批): u5/u6——u5 hero_info_panel_view(_init拆数据行/秘宝槽/三区段构建私有族+单槽/槽图标/字形标签/浮窗四域+set_treasure_inventory填充域拆分,循环体提函数)+u6 battle_end_overlay(_EndOverlayState战末呈现与演出态状态件[fx三计数并一字典]+探针冻结4住宿主+_init拆头部[蜡封图/庆祝立绘]/三行账构建域+open_victory可选尾参收拢opts束4参[键gp_summary/ks_summary/bonus_summary/gp_gain/gp_total缺省逐字]+四处演出循环提函数[封印光点/纹章碎砖/坐砖尘絮/尘金粒子])+消费点5处改址(main×2束形/main_adventure_flow×2/ui_struct_probe×1,三参调用缺省兼容零改动) 2026-10-28 14:53:17 +08:00
DKChan f878c3c45f 卡②T1补(呈现层结构收敛批): u4 standee_body——_StandeeState站桩演出状态件(24成员收拢含setter语义_owner回引/hp_value与意图动画tween属性路径随迁)+外部直访冻结4住宿主(box/font/slot_row/has_world_hp_bar)+源码锚承载成员_intent_charge住宿主(theme源锚句行逐字保留)+_draw拆五绘制域(地面/血条/立绘/意图徽标/护甲名行)+死亡碎块与命中火花循环体提函数(_spawn_death_shard/_spawn_hit_spark);类变量29→19在册键计数下降=改善,锚四句逐字在位 2026-10-28 14:47:47 +08:00
DKChan 98ac923938 卡②T1(呈现层结构收敛批): 营地与地图面四件——u1 camp_overlay_view(四柜台子域状态件_TreeState/_ForgeState/_AttuneState/_SideState+冻结5住宿主+_init拆顶栏/四柜台/底栏构建私有族+树行板/Fork行/锻造卡[标量束+状态文案+三钮域]/秘宝匣卡/同调行构建域+刷新三域;类变量19→9)+u2 level_map_screen(_MapState运行态状态件+_layer_decor装饰域字典[图标/石纹/tint]+冻结6住宿主+_init拆顶栏/画布/状态栏/头像/加成五族+_draw_graph拆上下文束/通道层/房间/图标/标签五域+_room_color共享;类变量22→6恶化债归绿键消失)+u3 board_cell_unit(_CellPaintState单格绘制输入集[26成员含setter语义_owner回引逐字]+冻结4住宿主+_draw拆底层/接触/中层/顶层四域+九绘制域;类变量31→30在册键计数下降=改善)+u3随动board_view写入行56处(u.X=u.st.X机械改址,接收者白名单u/hu/_contact_unit/_cells,探针冻结4成员与Dictionary键零触碰);源码锚S2两组逐字保留(STONE等式11处/336三处/SIZE_FILL四处);工作区gdstyle闸64键NEW=0恶化=0 2026-10-28 14:43:35 +08:00
DKChan 070a5340b3 卡①T9(核心数据面结构收敛批): 散条组——K5 action_economy(删_next_round_mode死存储+_ap_exhausted_last派生合并(ap_exhausted_last_round改_last_round_end.path_tag派生读,同源同刻等值)+last_round_end属性→方法,消费方minesweeper_rules:495改址)/reward_economy roll_board规范化域提取(_normalize_eligible开流前零RNG)+_skewed_cell_rows两域(_skew_families分族+_apply_skew权重装配,守恒assert随段迁移)/minesweeper_rules _do_dig拆_reveal_chain(cell_revealed发射序即链序整体随段搬迁)/K6′ unit_container spawn签名束化(10→1 req Dictionary,束键封闭词表缺省逐字)+体内拆_spawn_hero_unit/_spawn_rowset/_row_instance_counts+调用点24处9文件改束形(orchestrator+测试8,断言标签字面量零触碰);gdstyle 92→83键NEW=0 2026-10-28 08:46:22 +08:00
DKChan 2bd2625194 卡①T8(核心数据面结构收敛批): adventure_table拆段+.tres等值迁移——三段件建件(AdventureQuotaSegment 13/ValueSegment 13/CapSegment 9,段内槽名逐字不动)+宿主44→12(3段成员+9 knob留置)+curio_quota/curio_value/curio_cap三访问器签名与返回语义逐字(内部改读段成员,未列组合=0/缺省99语义保持)+adventure.tres等值迁移(22在册值逐槽照抄嵌套段sub_resource,单.tres保持;rap/time_sand与cap缺省槽保持缺省语义)+测试改址4处(adventure_feats:206读段路径/pool_case_d:164:165:190段路径读写,断言语义不变);表值等值载体=deck_total结构锚+访问器全组合读数[用户运行验证] 2026-10-28 08:41:01 +08:00
DKChan a9a163f924 卡①T7(核心数据面结构收敛批): config_db归位+域容器——三容器建件(ConfigDomainCombat 7表/Run 7表/Crossrun 5表,类型化纯持有)/config_db瘦身44→8公开(push_diag/is_fatal/reset_diagnostics/diagnostics/diagnostics_count/load_tables/set_reload_gate/reload)+类变量9(容器3+is_ready+诊断/resolver/validator/reload_gate/fatal_flag)/溶解16+迁移14+委托3访问器归位表类(shop_table 7方法/meta_table 2/forge_table 3[route_rows避routes属性]/variation_table 2/level_table level_count)+resolver装配段注入三表(board_gen.resolve_row/enemy.resolve_rowset/difficulty.resolve_modifiers委托,resolver文件零搬移)/删2(meta_conversion_row/forge_weapon_route_by_type生产零消费)/私1(validate_skill_pool_links→_);全域改址86文件(组①db.<表>→db.<容器>.<表>组②33访问器归位新名+删2消费面直扫同判据+桩件三处适配FakeDB/_BoardRowStub嵌套holder+treasure_items has_method改crossrun探测);首跑清扫漏表名bug已整树回滚重跑修正;gdstyle 168→92键NEW=0;[测试动作移交用户:套件停跑] 2026-10-28 08:37:22 +08:00
DKChan ced64d9cb3 卡①T6补: meta_progression两键收口——hero_override抽_forge_axis_bonus轴加值原语(11→8局部)/tree_can_buy出参聚合(8→2返回,判据逐字禁early-return合并语义等价) 2026-10-28 08:23:23 +08:00
DKChan 52661761c3 卡①T6(核心数据面结构收敛批): meta_progression瘦身(31→20公开=K3′封闭面定稿)+status_container/treasure_items拆分——纯转发退役2(keystone_balance/is_item_unlocked消费方直连meta.meta_state)/内联3(hero_override收编锻造加值与树淬炼flat,输出逐字)/私3(_forge_route_unlocked/_tree_spent_total/_tree_gate_text)/并组3组(forge_select(kind,rid)/hero_type_axes{attack,armor}/tree_camp_status{rows,fork_groups})/补meta_state装配成员+本类读写全改经meta_state;status_container apply_effect三臂域拆(_grant_snapshot/_apply_refresh/_apply_stack公共尾部单点+_new_instance 7→5参snap束)/treasure_items validate_use三域(_spatial_reject_reason/_window_cells/_preview_window_dead);消费方9文件改址(camp/hud/main/verifier/treasure_interact/forge/tree_requires/save_slot_isolation/theme_projection);[测试动作移交用户:套件停跑] 2026-10-28 08:22:37 +08:00
DKChan b182073941 卡①T5(核心数据面结构收敛批): 存档域拆件——SlotStore建件(槽位族10公开+槽位态随迁+_migrate_legacy_save/_copy_file/_remove_file随迁,_rename_overwrite留save IO单点)/MetaStateStore建件(写口原语13+只读投影6+add_keystone私有)/save_manager瘦身(52→7公开:load_from_disk/write_to_disk/register_migration+断点族4;_load_parsed/_peek_migrated读盘域提取,迁移链文案经fail数组逐字带出;类变量6)/全域改址449处(槽位族→save.slots.,元进度族→save.meta_state.,读面投影改形career/tree/forge/attune_state;meta转发与GainJournal.vision_used按卡留T6);[用户特许2026-10-28:本批测试动作移交用户,套件与闸停跑,实现继续] 2026-10-28 08:14:14 +08:00
DKChan 989c489c55 卡①T4(核心数据面结构收敛批): 效果引擎四域拆分——rebuild三装载域(_load_feat_triggers/_load_attune_triggers/_push_tree_rules+单规则助手,调用序feats→treasure→tree逐字=装载声明序冻结)/_cond_ok四算子域(_cmp_ok出参聚合/_ends_with_ok/_has_ok/_counter_op_ok,unknown-op致命路径与判定语义逐字)/bucket_of elif收口if序(前缀判定序round→lvl→adv→battle逐字)/validate_trigger_row三键域(_vtr_when_keys/_vtr_do_keys+_vtr_from_refs悬空域,static同形,错误追加序逐字);四词表常量零diff,8键全清,效果面6套件全绿(138checks adventure_feats) 2026-10-28 08:03:31 +08:00
DKChan 331d6b039a 卡①T3(核心数据面结构收敛批): 生成器族两文件拆分——board_generator generate收束(_board_params快照+_attempt_loop重试主循环+_accept_fallback三分出口)+_attempt布雷剃雷两域(_populate_mines Fisher-Yates取号段整体随迁+_shave_ring零RNG)+measure三算子域(_apply_chain_rule/_apply_single_rules/_derived_constraints/_apply_derived_rules)+_finalize删_db参5参化;node_map_generator validate_output六阶段域(_vo_node_fields/_vo_edges/_vo_flow_facts/_vo_depth_reach/_vo_shop_counts/_vo_terminal_shops/_vo_terminal_depths/_vo_width_rules/_vo_params_check)+check_params两分(_cp_domain/_cp_structural)+_build主链区域两段(_build_trunk/_build_region零RNG)+_add_forks锚收集段零RNG提取+_assign_types两分(_fill_ratios取号序整体搬迁+_fix_detour_heads零RNG)+_check_fork_rules签名两助手;RNG消费序冻结同种子逐位一致,17键全清,node_map三件+generator套件全绿 2026-10-28 07:24:56 +08:00
DKChan 9646ce545d 卡①T2(核心数据面结构收敛批): 校验族小表组+跨表校验器+解析器八文件拆分——board_gen 行/约束/收窄三域/level_gen_params 行头(skip)/形态/计数三域+层深尾段/meta_table 三行族域/skill_table 行头(skip)/公共/四类型域+表不变量/variation 行域+效果互锁+全局互锁/status_effect 行头+量纲域/cross_validator 七编号块域函数化(_cv_reward_dangling/_cv_reward_treasure/_cv_poolmap/_cv_source_labels/_cv_skill_pool/_cv_shelf_pool/_cv_counter_closure+decls/reads分层)+validate_skill_pool_links计数束化/resolver resolve_enemy_rowset三纯行扫描+_resolve_progress三段(坐标对束化);错误清单与告警序逐字,23键全清,data面13套件全绿 2026-10-28 07:14:57 +08:00
DKChan c56b816fee 卡①T1(核心数据面结构收敛批): 数据校验族大表组五文件validate拆私有域函数族——meta_tree 4域+两尾段(requires/requires_level)/treasure_item 行头+订阅+活行+N值+充能档位+积点闸+解锁互斥+效果数值+谓词九域(enemy skip语义经aux同款信号承载)/enemy 行头基面+数值+atk区间+池模板+攻防类型+行序违例+锚行尾段/reward 轴+aux投放(skip信号)+池标签+数值+区间+表闭合/forge 行头(skip)+数值+解锁通道+初始覆盖尾段;错误清单类别/文案/追加序逐字保持(契约1①),17键全清(gdstyle直扫5文件零warning),data_config 12套件+下游5套件全绿 2026-10-28 07:07:03 +08:00
34 changed files with 2818 additions and 140 deletions

No files matched your search

+1 -1
View File
@@ -97,7 +97,7 @@
- **反向**:diff 里每个行为改动至少一行;没有对应行的改动,必须写明「非行为改动」或「由第 X 行覆盖」。
- **测试侧**:新增或改写的每条断言至少挂一行;挂不上的孤儿断言删掉或补挂到需求点。
**能力清单维护锚(2026-10-28 用户裁,验证与清单体系整改阶段 1;阶段 2 后定稿)**:逐断言账本 `game/tests/验证集清单.md` 已随阶段 2「存量断言精简」完成退役——冻结对账基准(基点 `b9260138`/1587 条)与精简对账结果(33 站点并为 7、1587→1561,合回 `87d241c1`)留 git 历史。覆盖索引由 `game/tests/README.md`「能力清单 v1」唯一承担:每行一个能力,给真实入口与 2–3 个代表用例(`文件:函数`)。维护义务——**每批收口核对本批受影响能力行**:代表用例可 grep、在本批真实跑批中执行、真实入口未绕过改动点,并刷新「最后验证批次」;新增能力加行,能力退役删行。改动—验收对照表纪律不变:新增或改写的每条断言仍须挂一行(上文「测试侧」);断言改判仍受 §8.4 真实入口口径约束。
**验证集清单冻结与能力清单维护锚(2026-10-28 用户裁,验证与清单体系整改阶段 1)**:`game/tests/验证集清单.md` 自 2026-10-28 起**整册冻结**——不再随断言新增、删除或改判同步;它只作阶段 2「存量断言精简」的对账基准(基点 `b9260138`/1587 条),阶段 2 精简完成后删除。覆盖索引改由 `game/tests/README.md`「能力清单 v1」承担:每行一个能力,给真实入口与 2–3 个代表用例(`文件:函数`)。维护义务随之转移——**每批收口核对本批受影响能力行**:代表用例可 grep、在本批真实跑批中执行、真实入口未绕过改动点,并刷新「最后验证批次」;新增能力加行,能力退役删行。改动—验收对照表纪律不变:新增或改写的每条断言仍须挂一行(上文「测试侧」);断言改判仍受 §8.4 真实入口口径约束。
### 8.4 真实入口断言(验收闭合的主判据)
+1 -1
View File
@@ -680,7 +680,7 @@ func _roll_round_actions() -> void:
# 容器内直读主角行)
var facts := {
"round_index": round_index,
"last_round_end": "none" if action_economy.last_round_end().is_empty() else String(action_economy.last_round_end().get("path_tag", "none")),
"last_round_end": "none" if (action_economy.last_round_end as Dictionary).is_empty() else String((action_economy.last_round_end as Dictionary).get("path_tag", "none")),
"mines_hit_last": int(_mines_hits["last"]),
"mines_hit_total": int(_mines_hits["total"]),
}
-1
View File
@@ -1 +0,0 @@
uid://dpy0a6fcggbwe
-1
View File
@@ -1 +0,0 @@
uid://du0gxv0lnrxnp
-1
View File
@@ -1 +0,0 @@
uid://jaxlqd8ml3co
+6 -6
View File
@@ -145,7 +145,7 @@ func forge_buy_level(route_id: String) -> bool:
var row: Dictionary[Variant, Variant] = db.crossrun.forge.route(route_id)
if row.is_empty() or not _forge_route_unlocked(route_id):
return false
var lvl: int = meta_state.forge_state().levels.get(route_id, 0)
var lvl := meta_state.forge_state().levels.get(route_id, 0)
if lvl >= int(row.get("cap", 0)):
return false
var price := ForgeTable.level_price(row, lvl)
@@ -206,13 +206,13 @@ func forge_shop_status() -> Array:
var out: Array[Dictionary] = []
for row in db.crossrun.forge.route_rows():
var rid := String(row.get("route_id", ""))
var lvl: int = meta_state.forge_state().levels.get(rid, 0)
var lvl := meta_state.forge_state().levels.get(rid, 0)
var cap_v := int(row.get("cap", 0))
var unlocked := _forge_route_unlocked(rid)
var prereq := String(row.get("prereq_route", ""))
var plvl: int = meta_state.forge_state().levels.get(prereq, 0) if prereq != "" else 0
var plvl := meta_state.forge_state().levels.get(prereq, 0) if prereq != "" else 0
var pcap := int(db.crossrun.forge.route(prereq).get("cap", 0)) if prereq != "" else 0
var selected: bool = (String(row.get("kind", "")) == "weapon" and meta_state.forge_state().weapon == rid) \
var selected := (String(row.get("kind", "")) == "weapon" and meta_state.forge_state().weapon == rid) \
or (String(row.get("kind", "")) == "armor" and meta_state.forge_state().armor == rid)
out.append({
"route_id": rid,
@@ -362,7 +362,7 @@ func tree_buy(node_id: String) -> bool:
func tree_toggle_fork(group: String, side: String) -> bool:
if not db.crossrun.meta_tree.FORK_GROUPS.has(group) or not (side == "a" or side == "b"):
return false
var cur: String = meta_state.tree_state().fork_sides.get(group, "")
var cur := meta_state.tree_state().fork_sides.get(group, "")
if cur == "" or cur == side:
return false # 未解锁走购买面;同态零操作
meta_state.set_fork_side(group, side)
@@ -521,7 +521,7 @@ func attune_camp_status() -> Dictionary:
"equipped": equipped.has(iid),
"unlocked": meta_state.item_unlocked(iid),
})
var lvl: int = meta_state.attune_state().refresh_level
var lvl := meta_state.attune_state().refresh_level
var next_row: Dictionary[Variant, Variant] = db.crossrun.meta.attune_refresh_row(lvl + 1)
return {
"slots": Attunement.slots(db, save),
-1
View File
@@ -1 +0,0 @@
uid://bc5perm32w2yp
-1
View File
@@ -1 +0,0 @@
uid://dylsba7whx5ql
@@ -1 +0,0 @@
uid://b88nnsq53mium
@@ -1 +0,0 @@
uid://bi52mqsld3mpc
@@ -1 +0,0 @@
uid://c0y3hcpqyv1li
+1 -1
View File
@@ -115,4 +115,4 @@ var _resolver # R1 解析协作件(ConfigDB load_tables
## 进度行解析委托(消费面 db.combat.board_gen.resolve_row——R1 ceil/clamp 语义归 ConfigDbResolver)
func resolve_row(L: int, D: int) -> Dictionary:
return _resolver.resolve_board_gen(L, D)
return _resolver.combat.board_gen.resolve_row(L, D)
+1 -1
View File
@@ -35,4 +35,4 @@ var _resolver # R1 解析协作件(ConfigDB load_tables
## 难度修饰解析委托(消费面 db.run.difficulty.resolve_modifiers——clamp 语义归 ConfigDbResolver)
func resolve_modifiers(L: int, D: int) -> Dictionary:
return _resolver.resolve_difficulty_modifiers(L, D)
return _resolver.run.difficulty.resolve_modifiers(L, D)
+1 -1
View File
@@ -214,4 +214,4 @@ var _resolver # R1 解析协作件(ConfigDB load_tables
## 带寻址行集解析委托(消费面 db.combat.enemy.resolve_rowset——D 维 band_of 落带语义归 ConfigDbResolver)
func resolve_rowset(L: int, D: int, row_kind: String) -> Array[Dictionary]:
return _resolver.resolve_enemy_rowset(L, D, row_kind)
return _resolver.combat.enemy.resolve_rowset(L, D, row_kind)
+1 -1
View File
@@ -65,7 +65,7 @@ func camp_data() -> Dictionary:
"attune": meta.attune_camp_status() if meta != null else {}, # 同调装配面投影
"tree": meta.tree_camp_status()["rows"] if meta != null else [], # 树面投影(含 forge_workshop/ks_workshop 钥匙门判据行)
"fork_groups": meta.tree_camp_status()["fork_groups"] if meta != null else [],
"recent": _save_get.call().meta_state.career_state()["recent_summaries"] if _save_get.call() != null else [],
"recent": _save_get.call().recent_summaries() if _save_get.call() != null else [],
}
+15 -13
View File
@@ -8,16 +8,18 @@ extends RefCounted
const Narrator := preload("res://presentation/battle_narrator.gd")
var db
var ctx: CurioFlowContext # u13 引用束注入:构造注入 context 活引用(views/getters/flow 三束键名)
# _pending_curio/_curio_context 纯内部态保持宿主
# u13 引用束注入:16 个 _init 抄写成员删除——正文读点改址 ctx 束(u20 三束键名;
# _pending_curio/_curio_context 纯内部态保持宿主)
var _pending_curio := {} # 三选一停点载荷暂存(战斗总结结算确认后开三选一面;续玩停点复用)
var _curio_context := "level_clear" # 三选一面上下文(level_clear=关卡完成停点→推进下一关 / reward_node=奖励节点→回图选路)
func _init(ctx_ref: CurioFlowContext) -> void:
ctx = ctx_ref
func _init(ctx: CurioFlowContext) -> void:
# 构造参数收拢 context 对象(16 参长签名收一处命名面)
db = ctx.db
ctx.flow.fatal_screen = ctx.fatal_screen
ctx.flow.gp_summary = ctx.gp_summary
# 停点在途判据(组合根 _on_battle_end_continue 分派面——战斗总结确认后开三选一)
@@ -39,7 +41,7 @@ func resume_if_pending() -> bool:
#(continue_to_next_level 的「停点未兑付拒推进」守卫因此放行)。
func _skip_empty_stop() -> bool:
ctx.views.toast.show_toast("可用战利品为空——本次三选一跳过", "info")
var adventure = ctx.getters.adventure_get.call()
var adventure = _adventure_get.call()
if adventure != null:
adventure.stop().skip_empty_curio() # core 停点消化(其守卫=仅空候选放行)
if _curio_context == "reward_node":
@@ -86,7 +88,7 @@ func on_presented(payload: Dictionary) -> void:
# 奖励节点三选一(与关卡完成三选一共享同池同权重同上限;CurioPickOverlay 共用面)。
# 无替换子交互(同调装配不可变,见类头)。
func present_node_curio() -> void:
var adventure = ctx.getters.adventure_get.call()
var adventure = _adventure_get.call()
_curio_context = "reward_node"
var node_draw: Dictionary[Variant, Variant] = adventure.stop().node_curio_candidates()
var node_cands: Array[Variant] = node_draw.get("candidates", []) as Array
@@ -109,7 +111,7 @@ func show_pick() -> void:
var payload: Dictionary[Variant, Variant] = _pending_curio
ctx.flow.open_modal.call(ctx.views.curio_overlay)
ctx.views.curio_overlay.open_pick(Narrator.curio_pick_header(payload), _curio_card_texts(payload.get("candidates", []) as Array))
var adventure = ctx.getters.adventure_get.call()
var adventure = _adventure_get.call()
if adventure != null:
_feed_refresh_display(adventure) # 刷新面投喂单点
ctx.flow.refresh_presentations.call()
@@ -117,7 +119,7 @@ func show_pick() -> void:
# 刷新呈现投喂单点(免费余量 X/Y + GP 付费价 + 冒险钱包可付——读数与商店 set_refresh_display 同构)
func _feed_refresh_display(adventure: AdventureRunner) -> void:
var runner = ctx.getters.runner_get.call()
var runner = _runner_get.call()
var gp := int(runner.gp) if runner != null else 0
var cost: int = adventure.refresh_bank().gp_cost()
ctx.views.curio_overlay.set_refresh_display(adventure.refresh_bank().free_left(), cost, gp >= cost)
@@ -152,10 +154,10 @@ func _curio_card_texts(candidates: Array) -> Array:
# 同 shop_refresh_cost_base/curve 旋钮、同冒险钱包 runner.gp;关卡完成停点经重发 curio_choice_presented 直落
# 选择面,节点停点在此读在途态重 present——零自动推进契约不破,停点仍在途)
func on_refresh() -> void:
var adventure = ctx.getters.adventure_get.call()
var adventure = _adventure_get.call()
if adventure == null or not adventure.stop().curio_stop_pending():
return
var runner = ctx.getters.runner_get.call()
var runner = _runner_get.call()
var refreshed: bool = adventure.stop().refresh_curio()
if not refreshed:
# 免费位(X/Y)已穷——GP 付费档(先扣钱包后重抽,余额不足拒绝零副作用)
@@ -174,7 +176,7 @@ func on_refresh() -> void:
func on_pick_confirmed(item_id: String) -> void:
var adventure = ctx.getters.adventure_get.call()
var adventure = _adventure_get.call()
if adventure == null:
return
# TP0 令牌池——卡片 id "kind|tier|feat_id" 拆键(缺 | = 旧载荷防御归普通档;relic 三段)
@@ -204,7 +206,7 @@ func on_resolved(result: Dictionary) -> void:
func on_continue() -> void:
ctx.flow.close_modal.call(ctx.views.curio_overlay)
ctx.views.curio_overlay.close_pick()
var adventure = ctx.getters.adventure_get.call()
var adventure = _adventure_get.call()
if _curio_context == "feat_ticket":
return # T5 店内专长凭证面——专长兑付完成后关面回店(无推进/无回图)
if _curio_context == "reward_node":
@@ -221,7 +223,7 @@ func on_continue() -> void:
# 数据源=treasure 装配词表 12 件
func item_name_lookup() -> Dictionary:
var lookup := {}
var meta = ctx.getters.meta_get.call()
var meta = _meta_get.call()
if meta != null:
for row in db.crossrun.treasure_items.attunement_rows():
lookup[String(row.get("item_id", ""))] = String(row.get("display_name", ""))
+1 -6
View File
@@ -144,7 +144,7 @@ static func _build_curio(root: Variant) -> void:
{"open_modal": root._open_modal, "open_modal_after_playback": root._open_modal_after_playback,
"close_modal": root._close_modal, "refresh_presentations": root._refresh_presentations,
"fatal_screen": root._fatal_screen,
"gp_summary": _gp_summary_cb(root)})) # 构造参数收拢 context(u20 三束)
"gp_summary": func() -> String: return root._gp_summary_text({"gp_dropped": root.run_scope.last_gain_amount}}))) # 构造参数收拢 context(u20 三束)
root.curio_overlay.pick_confirmed.connect(root._bonus.on_pick_confirmed)
root.curio_overlay.continue_pressed.connect(root._bonus.on_continue)
root.curio_overlay.refresh_requested.connect(root._bonus.on_refresh)
@@ -251,8 +251,3 @@ static func fatal_screen(root: Variant, msg: String) -> void:
var l := UiKit.label(msg,UiKit.FS_SUB, true, UiKit.RED_ALERT)
l.set_anchors_preset(Control.PRESET_CENTER)
root.add_child(l)
# GP 总结行回调(gp_summary 束键——单行 lambda 内嵌字典实参收尾歧义,提函数承载)
static func _gp_summary_cb(root: Variant) -> Callable:
return func() -> String: return root._gp_summary_text({"gp_dropped": root.run_scope.last_gain_amount})
@@ -271,7 +271,12 @@ func _spawn_seal_dot(i: int, base: Vector2) -> void:
tw.tween_callback(dot.queue_free)
# ---- 演出密度(程序化 tween,确定性散布,零新帧资产;计数与碎砖驻留面在 _EndOverlayState) ----
# ---- 演出密度(程序化 tween,确定性散布,零新帧资产) ----
var st._crest_bricks: Array[ColorRect] = [] # 纹章碎砖驻留面(close 时回收)
var st._fx_crest_shards := 0
var st._fx_dust_motes := 0
var st._fx_seal_dots := 0
# 碎砖拼纹章(胜利 §2.4——蜡封落定后十枚碎砖自四周向蜡封外环收拢拼成纹章环,驻留至 close)
+1 -1
View File
@@ -323,7 +323,7 @@ func _draw_bevel() -> void:
## 变异标记域:真视格=危险红内缩框/未开格伤害型变异=左下角危险红三角
func _draw_mutation_marks() -> void:
if st.treasure_mark == "mine_reveal":
if treasure_mark == "mine_reveal":
var inset := st.edge * 0.14
draw_rect(Rect2(inset, inset, st.edge - inset * 2.0, st.edge - inset * 2.0),
Color(UiKit.RED_MINE, 0.9), false, 2.0)
+4 -3
View File
@@ -24,6 +24,7 @@ func _init() -> void:
vb.add_theme_constant_override("separation", 4)
add_child(vb)
_build_views(vb)
_build_status_corner()
## 视图三件域:AP 条+棋盘区(含动效与 toast 叠层)
@@ -36,11 +37,11 @@ func _build_views(vb: VBoxContainer) -> void:
vb.add_child(board_area)
_board_area = board_area
board_area.resized.connect(_on_board_area_resized)
_build_board_children(board_area, vb)
_build_board_children(board_area)
## 棋盘子件域:视图+动效+toast 三叠层挂接+状态角标+操作提示条(hint 回挂 vb——树序与拆分前一致)
func _build_board_children(board_area: Control, vb: VBoxContainer) -> void:
## 棋盘子件域:视图+动效+toast 三叠层挂接
func _build_board_children(board_area: Control) -> void:
board_view = BoardView.new()
board_view.set_anchors_preset(Control.PRESET_FULL_RECT)
board_area.add_child(board_view)
@@ -62,6 +62,28 @@ func _build_top_row(top: HBoxContainer) -> void:
## 主体域:入账信息行+三竖卡列+底部确认/继续钮与免费选择注记
func _build_body(box: VBoxContainer) -> void:
_label = UiKit.label("",UiKit.FS_BODY, false, UiKit.WARM_SOFT)
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(_label)
_choice_box = HBoxContainer.new()
_choice_box.add_theme_constant_override("separation", 26) # demo .cards gap 26(T7 对齐)
_choice_box.alignment = BoxContainer.ALIGNMENT_CENTER
_choice_box.size_flags_vertical = Control.SIZE_EXPAND_FILL
box.add_child(_choice_box)
var foot := HBoxContainer.new()
foot.alignment = BoxContainer.ALIGNMENT_CENTER
foot.add_theme_constant_override("separation", 16)
box.add_child(foot)
_confirm_btn = UiKit.primary_button("确认选择")
_confirm_btn.pressed.connect(_on_confirm_pressed)
_confirm_btn.visible = false
foot.add_child(_confirm_btn)
_continue_btn = UiKit.button("继续")
_continue_btn.pressed.connect(_emit_continue_pressed)
_continue_btn.visible = false
foot.add_child(_continue_btn)
_foot_hint = UiKit.label("免费选择 · 刷新不消耗 AP",UiKit.FS_HINT, false, UiKit.WARM_FAINT)
foot.add_child(_foot_hint)
_label = UiKit.label("",UiKit.FS_BODY, false, UiKit.WARM_SOFT)
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(_label)
+3 -4
View File
@@ -351,7 +351,7 @@ const BEAMS_PEAK := 0.05
## 光带像素域(循环体提函数——12° 斜向光带双三角衰减:带内峰值×纵向衰减逐像素着色)
static func _paint_beams(img: Image) -> void:
func _paint_beams(img: Image) -> void:
var ca := BEAMS_TILT_CA
var sa := BEAMS_TILT_SA
var beam_col := Color(1.0, 236.0 / 255.0, 200.0 / 255.0)
@@ -464,13 +464,12 @@ const PANEL_DEFAULT := true # modal_shell 面板哨兵(非 StyleBox 实例
# 面板哨兵解析(六参收拢五参——三态:null=无面板〔原 with_panel=false〕/PANEL_DEFAULT=默认样式盒面板
# 〔原 with_panel=true+panel_sb=null〕/StyleBox 实例=自定义样式盒面板〔原双参形态〕;
# 判别用 is StyleBox——StyleBox 与布尔哨兵直接 != 属异类操作数违例)
# 〔原 with_panel=true+panel_sb=null〕/StyleBox 实例=自定义样式盒面板〔原双参形态〕)
static func _resolve_shell_panel(panel_sb) -> PanelContainer:
if panel_sb == null:
return null
var panel := PanelContainer.new()
if panel_sb is StyleBox:
if panel_sb != PANEL_DEFAULT:
panel.add_theme_stylebox_override("panel", panel_sb)
return panel
+3 -3
View File
@@ -45,7 +45,7 @@ tests/
**能力清单 v1**(2026-10-28 立——验证与清单体系整改阶段 1 的覆盖索引:一行=一个玩家或系统可观测的能力,代表用例只给指针、不复制断言细节;原「集成旅程清单」五条跨系统旅程已并入本表。首期覆盖核心四域(29 行)+跨域条件闸 1 行,共 30 行;其余域按同一形态扩面):
> **与验证集清单的关系**:`tests/验证集清单.md` 已于阶段 2「存量断言精简」完成后删除——冻结对账基准(基点 `b9260138`/1587 条)与精简对账结果(33 站点并为 7、1587→1561,合回 `87d241c1`)留 git 历史。本表是该清单退役后的唯一覆盖索引(维护锚=test-conventions §8.3)。本表不是闸,不替代改动—验收对照表、体验验证清单与静态纪律;每行的唯一事实源仍是 `game/tests/` 下的测试代码。
> **与验证集清单的关系**:`tests/验证集清单.md` 已于 2026-10-28 整册冻结——不再随断言新增/删除/改判同步,只作阶段 2「存量断言精简」的对账基准(基点 `b9260138`/1587 条),阶段 2 精简完成后删除。覆盖索引职能改由本表承担(维护锚=test-conventions §8.3)。本表不是闸,不替代改动—验收对照表、体验验证清单与静态纪律;每行的唯一事实源仍是 `game/tests/` 下的测试代码。
>
> **代表用例口径**:写 `文件:函数`,每行 2–3 个;函数内可含 `Kit.check_quiet` 静默通道(逐断言提取器口径外,test-conventions §5.2 已备案)——本表以函数为锚,不受该工具局限影响。
>
@@ -53,7 +53,7 @@ tests/
>
> **旅程补录方法**:新旅程=加一行,「系统」列写涉及边界;源=architecture「API 边界」表+「数据流」存档/读档路径+各 GDD 登记的 deferral 集成用例。
>
> 「最后验证批次」列记回执 commit;多数行初值 `20c13c3a`=存量断言精简 A+B 首批的全量域闸回执,RNG 行随 C 档批刷新为 `fd6cf968`。
> 「最后验证批次」列记回执 commit;初值 `20c13c3a`=2026-10-28 存量断言精简 A+B 首批的全量域闸回执。
**旅程段一:开机与存档**
@@ -65,7 +65,7 @@ tests/
| 启动态无激活不写盘 | 存档序列化 | `SaveManagerCore.has_write_target()`/`write_to_disk()` | `save_boot_no_activate_test.gd:_test_write_rejected_without_target`;`save_boot_no_activate_test.gd:_test_out_of_range_slots_rejected` | `20c13c3a` | — |
| 旧档迁移链与断点续玩零跳号(集成) | 存档序列化×冒险结构 | `SaveManagerCore.load_from_disk()`(内置迁移链)× `AdventureRunner.resume_adventure()` | `save_rng_roundtrip_test.gd:_test_old_version_save_migrates_and_resumes` | `20c13c3a` | — |
| 存档⇄RNG 快照往返保真(集成) | 存档序列化×RNG 服务×冒险结构 | `AdventureRunner.start_adventure()` → `SaveManagerCore.write_to_disk()`/`load_from_disk()` | `save_rng_roundtrip_test.gd:_test_disk_roundtrip_preserves_breakpoint` | `20c13c3a` | — |
| RNG 统一流派生与取号账本 | RNG 服务 | `RngServiceCore.derive_at()`/`open_stream()`/`counter()` | `rng_service_test.gd:_test_derive_determinism`;`rng_service_test.gd:_test_stream_draw_determinism`;`rng_stream_boot_test.gd:_smoke_initialize` | `fd6cf968` | — |
| RNG 统一流派生与取号账本 | RNG 服务 | `RngServiceCore.derive_at()`/`open_stream()`/`counter()` | `rng_service_test.gd:_test_derive_determinism`;`rng_service_test.gd:_test_stream_draw_determinism`;`rng_stream_boot_test.gd:_smoke_initialize` | `20c13c3a` | — |
| 断点片段往返与续玩幂等 | 冒险结构×关卡节点地图 | `LevelRunner.breakpoint_fragment()`/`restore_fragment()`;`AdventureRunner.resume_adventure()` | `breakpoint_resume_test.gd:_init` | `20c13c3a` | — |
| 跨系统附随面:事件日志落盘与断点附随件(集成) | RNG 服务×存档序列化×冒险结构 | `RngServiceCore.new_adventure()`(开事件日志会话);`SaveManagerCore.breakpoint_snapshot()`(断点附随键) | `cross_system_flow_test.gd:_rng_event_log_session`;`cross_system_flow_test.gd:_feats_breakpoint_roundtrip` | `20c13c3a` | 日志面仅此一条会话覆盖 |
+1 -1
View File
@@ -38,7 +38,7 @@ func _check_autoloads() -> void:
var node: Node = get_node_or_null(NodePath("/root/" + autoload_name))
check(node != null, "autoload %s 在位" % autoload_name)
var db: Node = get_node_or_null(NodePath("/root/ConfigDB"))
check(db != null and bool(db.get("is_ready")) and db.get("combat") != null and db.get("combat").get("hero") != null,
check(db != null and bool(db.get("is_ready")) and db.get("hero") != null,
"ConfigDB 就绪且配置表全载(is_ready+hero 表在座,校验失败会致命中止)")
check(load(MAIN_SCENE_PATH) != null, "主屏场景资源可加载(%s)" % MAIN_SCENE_PATH)
check(load(FONT_PATH) != null, "全局字体资源可加载(%s)" % FONT_PATH)
+5 -5
View File
@@ -318,11 +318,11 @@ func _face_snapshot(main: Node) -> Dictionary:
return {
"treasure_settlement": tu._settlement_get.call(),
"treasure_runner": tu._runner_get.call(),
"bonus_meta": bo.ctx.getters.meta_get.call(),
"bonus_save": bo.ctx.getters.save_get.call(),
"bonus_adventure": bo.ctx.getters.adventure_get.call(),
"bonus_runner": bo.ctx.getters.runner_get.call(),
"bonus_mode": bo.ctx.getters.adventure_mode_get.call(),
"bonus_meta": bo._meta_get.call(),
"bonus_save": bo._save_get.call(),
"bonus_adventure": bo._adventure_get.call(),
"bonus_runner": bo._runner_get.call(),
"bonus_mode": bo._adventure_mode_get.call(),
"camp_meta": cp._meta_get.call(),
"camp_save": cp._save_get.call(),
"camp_runner": cp._runner_get.call(),
+12 -12
View File
@@ -54,16 +54,16 @@ func _difficulty_table():
func _test_band_hit() -> void:
var hit: Array = _resolver.resolve_enemy_rowset(1, 4, "battle")
var hit: Array = _resolver.combat.enemy.resolve_rowset(1, 4, "battle")
Kit.check("带命中取偏难一侧:请求深度 4 命中带 5(逐字不回带 0)〔fv1〕",
hit.size() == 1 and String((hit[0] as Dictionary).get("enemy_id", "")) == "hobgoblin")
var exact: Array = _resolver.resolve_enemy_rowset(1, 5, "battle")
var exact: Array = _resolver.combat.enemy.resolve_rowset(1, 5, "battle")
Kit.check("精确落带:请求深度 5 命中带 5〔fv1〕",
exact.size() == 1 and String((exact[0] as Dictionary).get("enemy_id", "")) == "hobgoblin")
func _test_rowset_order_preserved() -> void:
var rows: Array = _resolver.resolve_enemy_rowset(1, 0, "battle")
var rows: Array = _resolver.combat.enemy.resolve_rowset(1, 0, "battle")
var ids: Array[String] = []
for r in rows:
ids.append(String((r as Dictionary).get("enemy_id", "")))
@@ -73,7 +73,7 @@ func _test_rowset_order_preserved() -> void:
func _test_top_band_clamp() -> void:
_diags.clear()
var rows: Array = _resolver.resolve_enemy_rowset(1, 99, "battle")
var rows: Array = _resolver.combat.enemy.resolve_rowset(1, 99, "battle")
Kit.check("越顶带 clamp 取顶带行集(battle 顶带 5)〔fv3〕",
rows.size() == 1 and String((rows[0] as Dictionary).get("enemy_id", "")) == "hobgoblin")
var clamp_hit := false
@@ -82,13 +82,13 @@ func _test_top_band_clamp() -> void:
clamp_hit = true
Kit.check("越顶带发 warning resolve_depth_clamp〔fv3〕", clamp_hit)
var warn_before: int = _diags.size()
_resolver.resolve_enemy_rowset(1, 99, "battle")
_resolver.combat.enemy.resolve_rowset(1, 99, "battle")
Kit.check("同键重复请求警告去重(四元组注册表)〔fv3〕", _diags.size() == warn_before)
func _test_row_kind_routing() -> void:
var battle_rows: Array = _resolver.resolve_enemy_rowset(1, 0, "battle")
var boss_rows: Array = _resolver.resolve_enemy_rowset(1, 0, "boss")
var battle_rows: Array = _resolver.combat.enemy.resolve_rowset(1, 0, "battle")
var boss_rows: Array = _resolver.combat.enemy.resolve_rowset(1, 0, "boss")
Kit.check("行类路由:同请求深度 battle 与 boss 命中不同键域〔fv4〕",
battle_rows.size() == 2 and boss_rows.size() == 1
and String((boss_rows[0] as Dictionary).get("enemy_id", "")) == "ogre_chief")
@@ -96,13 +96,13 @@ func _test_row_kind_routing() -> void:
func _test_request_oob() -> void:
_diags.clear()
_resolver.resolve_enemy_rowset(0, 0, "battle")
_resolver.combat.enemy.resolve_rowset(0, 0, "battle")
Kit.check("关卡序号 <1 → fatal request_oob〔fv5〕", _has_fatal_oob())
_diags.clear()
_resolver.resolve_enemy_rowset(1, -1, "battle")
_resolver.combat.enemy.resolve_rowset(1, -1, "battle")
Kit.check("节点深度 <0 → fatal request_oob〔fv5〕", _has_fatal_oob())
_diags.clear()
_resolver.resolve_enemy_rowset(1, 0, "elite")
_resolver.combat.enemy.resolve_rowset(1, 0, "elite")
Kit.check("row_kind 非法 → fatal request_oob〔fv5〕", _has_fatal_oob())
@@ -114,11 +114,11 @@ func _has_fatal_oob() -> bool:
func _test_difficulty_clamp() -> void:
var m: Dictionary = _resolver.resolve_difficulty_modifiers(1, 0)
var m: Dictionary = _resolver.run.difficulty.resolve_modifiers(1, 0)
Kit.check("难度乘数越域被 clamp:hp 99 → 上限 10", absf(float(m.get("hp_mult", 0.0)) - 10.0) < 0.001)
Kit.check("难度乘数越域被 clamp:atk 0.01 → 下限 0.1", absf(float(m.get("atk_mult", 0.0)) - 0.1) < 0.001)
Kit.check("未登记坐标返回空修饰(零值不伪装成 ×1)",
_resolver.resolve_difficulty_modifiers(3, 3).is_empty())
_resolver.run.difficulty.resolve_modifiers(3, 3).is_empty())
class _FakeDifficulty:
@@ -69,40 +69,37 @@ func _test_negative() -> void:
var base := [_row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, 4),
_row(2, 9, 0.5, [0.5, 0.2, 0.15, 0.15], 2, 2, 6),
_row(3, 13, 0.7, [0.55, 0.15, 0.15, 0.15], 2, 3, 8)]
Kit.check("合法三行域校验零错误(夹具自证)〔fv2〕", _table(base).validate().is_empty())
# ① L1 出口改 2 → 出口恒 1 断言红(负样本夹具)
var bad_l1_exit := [_row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 2, 4), base[1], base[2]]
Kit.check("L1 出口=2 被拒(出口 L1 恒 1 已锁)〔fv2〕", not _table(bad_l1_exit).validate().is_empty())
# ② 配比合计 0.5 → 合计 1 断言红(负样本夹具)
var bad_ratio := [_row(1, 6, 0.3, [0.2, 0.1, 0.1, 0.1], 1, 1, 4), base[1], base[2]]
Kit.check("配比合计 0.5 被拒(四类合计 1 已锁)〔fv2〕", not _table(bad_ratio).validate().is_empty())
# ③ 层深低于下限
var bad_layers := [_row(1, 5, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, 4), base[1], base[2]]
Kit.check("层深 5<6 被拒(层深下限已锁)〔fv2〕", not _table(bad_layers).validate().is_empty())
# ④ 增幅未变大(6/9/11:Δ12=3、Δ23=2)
var bad_growth := [base[0], _row(2, 9, 0.5, [0.5, 0.2, 0.15, 0.15], 2, 2, 6),
_row(3, 11, 0.7, [0.55, 0.15, 0.15, 0.15], 2, 3, 8)]
Kit.check("层深增幅倒挂被拒(递增且增幅变大)〔fv2〕", not _table(bad_growth).validate().is_empty())
# ⑤ 出口越上界(L3 出口 4)
var bad_exit := [base[0], base[1], _row(3, 13, 0.7, [0.55, 0.15, 0.15, 0.15], 2, 4, 8)]
Kit.check("出口 4 越域 [1,3] 被拒〔fv2〕", not _table(bad_exit).validate().is_empty())
# ⑥ 岔口去路数改 (2,4)
var bad_fork_row := _row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, 4)
bad_fork_row["fork_ways_max"] = 4
Kit.check("岔口去路数 (2,4) 被拒(恒 2/3 已锁)〔fv2〕",
not _table([bad_fork_row, base[1], base[2]]).validate().is_empty())
# ⑦ 键集非闭集(多塞未知键)
var bad_keys_row: Dictionary = _row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, 4)
bad_keys_row["mystery"] = 1
# 逐类负向表:[个案标签, 行集, 期望零错误]——每行仍逐案断言,消息带期望/实际与违例明细
var cases: Array = [
["合法三行域校验零错误(夹具自证)", base, true],
["L1 出口=2 被拒(出口 L1 恒 1 已锁)", bad_l1_exit, false],
["配比合计 0.5 被拒(四类合计 1 已锁)", bad_ratio, false],
["层深 5<6 被拒(层深下限已锁)", bad_layers, false],
["层深增幅倒挂被拒(递增且增幅变大)", bad_growth, false],
["出口 4 越域 [1,3] 被拒", bad_exit, false],
["岔口去路数 (2,4) 被拒(恒 2/3 已锁)", [bad_fork_row, base[1], base[2]], false],
["字段键集非 ROW_KEYS 闭集被拒", [bad_keys_row, base[1], base[2]], false],
["键重复行被拒", [base[0], base[0]], false],
["战斗保底 -1 被拒(≥0)", [_row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, -1), base[1], base[2]], false],
["空表域校验零错误(合法态)", [], true],
]
for c in cases:
var errs: Array = _table(c[1]).validate()
var expect_label := "零错误" if c[2] else "有违例"
var actual_label := "零错误" if errs.is_empty() else "违例 %d 条 %s" % [errs.size(), str(errs)]
Kit.check("域校验:%s(期望%s,实际%s)〔fv2〕" % [c[0], expect_label, actual_label],
errs.is_empty() == c[2])
Kit.check("字段键集非 ROW_KEYS 闭集被拒〔fv2〕",
not _table([bad_keys_row, base[1], base[2]]).validate().is_empty())
# ⑧ level_index 重复
Kit.check("键重复行被拒〔fv2〕", not _table([base[0], base[0]]).validate().is_empty())
# ⑨ 战斗保底负值
Kit.check("战斗保底 -1 被拒(≥0)〔fv2〕",
not _table([_row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, -1), base[1], base[2]]).validate().is_empty())
# ⑩ 空表=合法态(沿 difficulty_table 先例)
Kit.check("空表域校验零错误(合法态)〔fv2〕", _table([]).validate().is_empty())
@@ -34,11 +34,14 @@ func _smoke_initialize() -> void:
rng.set_master_seed(42)
# 统一流黄金向量(数据配置 AC-3:单盐沿用 board_gen 盐,
# scope 0-3 与 board_gen 向量逐位连续;Python 参考实现逐位交叉验证一致)
var golden := [8672514112661456564, 8834291164406037215, 7714373262647006282, 1280102845971471347,
82585501446482399, 8078924421474470922, 6638052740430622424, 8264196488417721294]
for i in golden.size():
Kit.check("统一流向量 m=42 scope=%d(黄金向量;scope0=旧 board_gen 连续性锚)" % i,
rng.derive_at(i) == golden[i])
Kit.check("统一流向量 m=42 scope=0(=旧 board_gen scope0 连续性锚)", rng.derive_at(0) == 8672514112661456564)
Kit.check("统一流向量 m=42 scope=1", rng.derive_at(1) == 8834291164406037215)
Kit.check("统一流向量 m=42 scope=2", rng.derive_at(2) == 7714373262647006282)
Kit.check("统一流向量 m=42 scope=3", rng.derive_at(3) == 1280102845971471347)
Kit.check("统一流向量 m=42 scope=4", rng.derive_at(4) == 82585501446482399)
Kit.check("统一流向量 m=42 scope=5", rng.derive_at(5) == 8078924421474470922)
Kit.check("统一流向量 m=42 scope=6", rng.derive_at(6) == 6638052740430622424)
Kit.check("统一流向量 m=42 scope=7", rng.derive_at(7) == 8264196488417721294)
Kit.check("derive_at 纯函数恒等", rng.derive_at(0) == rng.derive_at(0))
# scope 取号语义:首个 open_stream = 全局 scope 0;计数器单调;用途标签不参与派生(只进事件日志)
var s0 = rng.open_stream("board_gen")
@@ -58,12 +58,14 @@ func _run() -> void:
and rows.has("light") and rows.has("heavy") and rows.has("ward"))
# ③ 初始持有行(长剑/轻甲):购买钮现形带几何价、选中钮=当前禁用
# 两行同取谓词并集(轻甲行补 select_btn 非空 + buy_btn 可用两子句——原件少写,只增不减)
for pair in [["sword", "长剑"], ["light", "轻甲"]]:
var r: Dictionary = rows.get(pair[0], {})
Kit.check("%s行:购买钮「锻造 20」(0 级位几何价)+选中钮「当前」禁用〔锻造工坊批 V13〕" % pair[1],
r.get("buy_btn") != null and String(r.buy_btn.text) == "锻造 20" and not r.buy_btn.disabled
and r.get("select_btn") != null and String(r.select_btn.text) == "当前" and r.select_btn.disabled)
var rsw = rows.get("sword", {})
var rli = rows.get("light", {})
Kit.check("长剑行:购买钮「锻造 20」(0 级位几何价)+选中钮「当前」禁用〔锻造工坊批 V13〕",
rsw.get("buy_btn") != null and String(rsw.buy_btn.text) == "锻造 20" and not rsw.buy_btn.disabled
and rsw.get("select_btn") != null and String(rsw.select_btn.text) == "当前" and rsw.select_btn.disabled)
Kit.check("轻甲行:购买钮「锻造 20」+选中钮「当前」禁用〔锻造工坊批 V13〕",
rli.get("buy_btn") != null and String(rli.buy_btn.text) == "锻造 20"
and String(rli.select_btn.text) == "当前" and rli.select_btn.disabled)
# ④ 待解锁行(长枪/法杖/重甲/魔法护甲):解锁钮 200、无购买钮、无选中钮、状态含双通道文案
var rsp = rows.get("spear", {})
@@ -56,8 +56,9 @@ func _sweep_narrator() -> void:
var head := String(narrator.node_curio_header())
Kit.check("奖励点头部含「冒险牌库」(u3 机制事实①同库)〔wa4〕", head.contains("冒险牌库"))
Kit.check("奖励点头部含「属性值提升与补给」(u3 机制事实②渠道分流)〔wa4〕", head.contains("属性值提升与补给"))
for w in ["同权重", "同上限", "提升池"]:
Kit.check("奖励点头部零「%s」旧话(u3 清零)〔wa4〕" % w, not head.contains(w))
Kit.check("奖励点头部零「同权重」旧话(u3 清零)〔wa4〕", not head.contains("同权重"))
Kit.check("奖励点头部零「同上限」旧话(u3 清零)〔wa4〕", not head.contains("同上限"))
Kit.check("奖励点头部零「提升池」旧话(u3 清零)〔wa4〕", not head.contains("提升池"))
Kit.check("专长卡兜底==「专长\n???」(u11 换代——数据缺行真实兜底路径)〔wa3〕",
String(narrator.feat_card_text({})) == "专长\n???")
@@ -72,9 +73,8 @@ func _sweep_legend() -> void:
break
Kit.check("图例封印行含「标空」(u4——与「标中」成对)〔wa5〕", String(seal_row[2] if seal_row.size() > 2 else "").contains("标空"))
Kit.check("图例封印行含「受挖掘惩罚」(u4 雷字清零换代)〔wa5〕", String(seal_row[2] if seal_row.size() > 2 else "").contains("受挖掘惩罚"))
for w in ["插错", "挖雷"]:
Kit.check("图例封印行零「%s」〔wa5〕" % w,
not String(seal_row[2] if seal_row.size() > 2 else "").contains(w))
Kit.check("图例封印行零「插错」(u4 旗族遗留词干清零)〔wa5〕", not String(seal_row[2] if seal_row.size() > 2 else "").contains("插错"))
Kit.check("图例封印行零「挖雷」(u4 雷字清零)〔wa5〕", not String(seal_row[2] if seal_row.size() > 2 else "").contains("挖雷"))
# ⑤⑥ 来源名双源(u5/u6——状态槽消费半+表值 ConfigDB 真装载+battle_log 行消费半)
@@ -91,16 +91,14 @@ func _init() -> void:
Kit.check("无 target_id 时按名兜底同旧行为(首命中)〔wd12〕", c_fallback != null and c_fallback == c_fallback_expect)
# ---- ① 意图蓄力档可达(d2)----
# 蓄力判据表:[kind, skill_id, 期望 _intent_charge, 个案标签]
var charge_cases := [
["damage", "heavy", true, "蓄力技能(heavy)置 _intent_charge=true"],
["damage", "goblin_slash", false, "非蓄力攻击技(goblin_slash)零置位"],
["buff", "goblin_rage", false, "增益系零置位"],
["damage", "basic", false, "普攻零表示路径复位 _intent_charge"],
]
for c in charge_cases:
s1.set_pending(c[0], c[1])
Kit.check("%s〔wd2〕" % c[3], s1._intent_charge == c[2])
s1.set_pending("damage", "heavy")
Kit.check("蓄力技能(heavy)置 _intent_charge=true〔wd2〕", s1._intent_charge)
s1.set_pending("damage", "goblin_slash")
Kit.check("非蓄力攻击技(goblin_slash)零置位〔wd2〕", not s1._intent_charge)
s1.set_pending("buff", "goblin_rage")
Kit.check("增益系零置位〔wd2〕", not s1._intent_charge)
s1.set_pending("damage", "basic")
Kit.check("普攻零表示路径复位 _intent_charge〔wd2〕", not s1._intent_charge)
# ---- ② 庆祝 tween 句柄纪律(d4)----
var ov = BattleEndScript.new()
@@ -15,19 +15,10 @@ func _init() -> void:
var f: Font = UiKitScript.load_font(path)
Kit.check("随包字体守卫装载非空(res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf)", f != null)
if f != null:
# 字形集表:[个案标签, 须在集字符]——缺字明细进消息
var glyph_groups := [
["中文字形在集(攻/雷/旗/封)", "攻雷旗封"],
["中文字形在集(危——已开危险格字形换代前置,迭代36 u12/wa9)", "危"],
["ASCII/数字字形在集(A/0/%)", "A0%"],
]
for g in glyph_groups:
var missing := ""
for i in String(g[1]).length():
var ch := String(g[1])[i]
if not f.has_char(ch.unicode_at(0)):
missing += ch
Kit.check("%s(缺=%s)" % [g[0], missing if missing != "" else "无"], missing == "")
Kit.check("中文字形在集(攻/雷/旗/封)", f.has_char("攻".unicode_at(0)) and f.has_char("雷".unicode_at(0)) \
and f.has_char("旗".unicode_at(0)) and f.has_char("封".unicode_at(0)))
Kit.check("中文字形在集(危——已开危险格字形换代前置,迭代36 u12/wa9)", f.has_char("危".unicode_at(0)))
Kit.check("ASCII/数字字形在集(A/0/%)", f.has_char("A".unicode_at(0)) and f.has_char("0".unicode_at(0)) and f.has_char("%".unicode_at(0)))
var sz := 18
var w_cn: float = f.get_string_size("战斗胜利", HORIZONTAL_ALIGNMENT_LEFT, -1, sz).x
var w_label: float = f.get_string_size("攻击 2", HORIZONTAL_ALIGNMENT_LEFT, -1, sz).x
File diff suppressed because it is too large. Load diff
+15 -12
View File
@@ -4,28 +4,20 @@
#### 验证与清单体系整改——四方向分阶段推进(2026-10-28 登记,来源=会话提及)
**实况**:用户裁「验证及清单不合理」,经调研定四方向全做、分阶段推进:A 粒度整改(清单从断言级升到能力/行为级,逐断言账本退役)→ B 精简裁断(在新粒度上规则驱动删并)→ C 流程风险分级(P0/P1/P2 验收强度、审计抽样)→ D 文档减肥(待办条目限长、历史归 git);测试有效性度量暂不处理。阶段 0 盘点已毕:验证集清单零机器闸依赖(run_all_gates/hooks/五技能均不引用,仅 test-conventions §8.3 维护锚+2 份过程报告引用),退役无闸改动;但测试名尾缀仅覆盖 28/47 个有断言文件(19 个零尾缀,含 seal_polarity 69 条、variant_placement 42 条、roll_multiplier 35 条),故能力清单只能按「能力→代表用例」建,不要求逐断言尾缀。对照表列改动触 pipeline_gate+req-card/iter 两技能;待办正文压缩不触机检(无长度判据)。盘点明细见 reports/盘点-验证与清单体系-2026-10-28.md。**阶段 1 设计已闭合(2026-10-28 用户四裁点)**:能力清单 v1 落 `game/tests/README.md`——按系统归属与玩家旅程排序,首期核心四域(存档与随机、冒险循环、战斗结算、奖励与经济)29 行+跨域条件闸 1 行,共 30 行,每行真实入口+2–3 个代表用例(`文件:函数`),维护规则为每批收口核对本批受影响行并刷新「最后验证批次」;`design/engineering/test-conventions.md` §8.3 维护锚改写为「验证集清单整册冻结、能力清单承接覆盖索引、阶段 2 精简后删除」;`game/tests/验证集清单.md` 头注同步冻结声明,冻结快照(基点 `b9260138`/1587 条)留作阶段 2 对账基准;`tools/extract_checks.py` 保留为审计工具,不再承担常态同步。**阶段 2 已执行闭合(2026-10-28 C 档合回)**:存量断言精简 C 档 6 组手写断言族并为 7 个表驱动站点(33→7),冻结清单对账 1587→1561,验证集清单随阶段 2 完成退役(覆盖索引归能力清单,维护锚 test-conventions §8.3),删并申报与件核见 reports/工程改动报告-存量断言精简C档-2026-10-28.md;阶段 3–4 待各自设计推进:风险分级与审计抽样规则、条目限长是否入 pipeline_gate 均未定。
**实况**:用户裁「验证及清单不合理」,经调研定四方向全做、分阶段推进:A 粒度整改(清单从断言级升到能力/行为级,逐断言账本退役)→ B 精简裁断(在新粒度上规则驱动删并)→ C 流程风险分级(P0/P1/P2 验收强度、审计抽样)→ D 文档减肥(待办条目限长、历史归 git);测试有效性度量暂不处理。阶段 0 盘点已毕:验证集清单零机器闸依赖(run_all_gates/hooks/五技能均不引用,仅 test-conventions §8.3 维护锚+2 份过程报告引用),退役无闸改动;但测试名尾缀仅覆盖 28/47 个有断言文件(19 个零尾缀,含 seal_polarity 69 条、variant_placement 42 条、roll_multiplier 35 条),故能力清单只能按「能力→代表用例」建,不要求逐断言尾缀。对照表列改动触 pipeline_gate+req-card/iter 两技能;待办正文压缩不触机检(无长度判据)。盘点明细见 reports/盘点-验证与清单体系-2026-10-28.md。**阶段 1 设计已闭合(2026-10-28 用户四裁点)**:能力清单 v1 落 `game/tests/README.md`——按系统归属与玩家旅程排序,首期核心四域(存档与随机、冒险循环、战斗结算、奖励与经济)29 行+跨域条件闸 1 行,共 30 行,每行真实入口+2–3 个代表用例(`文件:函数`),维护规则为每批收口核对本批受影响行并刷新「最后验证批次」;`design/engineering/test-conventions.md` §8.3 维护锚改写为「验证集清单整册冻结、能力清单承接覆盖索引、阶段 2 精简后删除」;`game/tests/验证集清单.md` 头注同步冻结声明,冻结快照(基点 `b9260138`/1587 条)留作阶段 2 对账基准;`tools/extract_checks.py` 保留为审计工具,不再承担常态同步。阶段 2–4 待各自设计推进:删并判据与波次、风险分级与审计抽样规则、条目限长是否入 pipeline_gate 均未定。
**改动面**:文档+游戏代码+工具代码
**状态**:文档设计已闭合
#### 恒真与名实不符断言五条——判据缺陷修正(2026-10-29 登记,来源=会话提及)
#### 存量断言精简——验证内容不变下的断言收敛(2026-10-28 登记,来源=会话提及)
**实况**:存量断言精简 A+B 批余账④转正:五条断言属判据缺陷(恒真占位或名实不符),不是冗余合并可解的账,按 test-conventions §8.4 真实入口口径逐条修正,不计入精简条数。逐条:①`game/tests/unit/core/feat_vouchers_test.gd:51` cond 为 `deck_refresh_before == 0 or true`——恒真;②`game/tests/unit/core/treasure_effects_test.gd:263` cond 尾缀 `or true`——恒真;③`game/tests/unit/core/level_shop_economy_test.gd:593` `green_min_hp > 0`——初值 99999、仅 hp>0 分支取 min,恒真;④同文件 `:696` `green3_min_hp > 0`——同型恒真;⑤`game/tests/unit/contracts/system_contracts_test.gd:66-67` 标签称「非空且互异」而 cond 只查 `size() > 0`——互异半缺失,名实不符。修正方向:能绑判据的改绑真实可观测面(互异改值集去重计数、HP 读数改与门槛比对),造不出可观测面的按 §8.4 出口停卡呈报。
**实况**:目标=减少现有断言数量、更精简,配合 §8.2 接口测试导向(对外方法、功能行为验证),前提=验证清单的验证项目覆盖逐条不变。证据=判据达标专项批已完成(本清单已销号条目,59 改钉+35 例外——全部断言已钉公开可观测面,每条断言的验证对象已显式化,做减法有了干净基线);验证集清单 1604 静态调用点为对照基准。口径界定:验证项目≠check 调用点——验证项目(卡片验收条目/GDD 登记验证面)覆盖逐条不降,check 调用点可降;可删并的两类=①同一行为被多条断言重复钉(同族合并)②钉内部路径细节而该行为已被入口断言严格承载(逐条申报承接者)。删除属显式判据改判:逐条申报理由+承接者指认(写入阶段 2 删并申报表「处置/去向」列),禁批量拍删;删后被承接行为以保留断言复验(套件绿),禁变异法。执行形态=工程改动 worktree 批:盘点先行(逐套件标冗余候选两类清单)→ 用户逐批裁决删并清单 → 分波执行每波闸 → 件核(验证项目覆盖不变+清单对账 PASS+条数下降留痕)。盘点与第一波执行凭据:机器初筛(同文件标签近似 223 对/cond 全同 42 组 109 条/护栏类 41 条)+七路只读语义裁决+逐条抽验,判据线收紧为「同一读数面+同一输入+谓词字面等价或字面是承接者真子集」,候选由约 150 点核减至 19 点;第一波(A+B 档 19 站点,其中 17 在册+`smoke_boot.gd` 2 点口径外)已合回——删并申报表与承接者逐条指认 `reports/工程改动报告-存量断言精简AB档-2026-10-28.md`,清单 1604→1587 且 `--diff` 对账 PASS、15 条保留行「处置」列去向在册,全量域闸回执 commit `20c13c3a`(domain=full/all_green/09 静态扫描存量红零新增),合并提交 65054b1d。余账四条:①类别② 实测不成立(全仓内部面断言约 52 条被入口严格承载 0 条,后续波次只在类别① 内找)②C 档手写族改表驱动循环合并(静态约再省 25~35 点,代价=定位改用违例明细串)③D 档「是否同一验证项目」待 owner 认账四处(本批用户裁全保留)④恒真与名实不符断言五条属判据缺陷另账,走 §8.4 呈报通道非精简账;另 静默收集通道 `Kit.check_quiet` 静态站点 407 个在冻结口径外(test-conventions:38 已备案工具局限),要收该账先做提取器改版。
**改动面**:游戏代码
**状态**:待执行
#### 断言提取器改版——覆盖 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(` 不双计。
**改动面**:工具代码
**状态**:待执行
#### gdstyle 存量债全量清偿——216 键按病根分波整改(2026-10-26 登记,来源=会话提及,优先级=P0)
**实况**:S13 闸实测存量债 216 键/60 文件(2026-10-26,master f3b148ce,gdstyle v0.4.0 默认阈值;基线登记 234 键=实存 216+陈旧 18)。全量清单、波次方案与纪律见清点报告(本条目裁决源)。2026-10-26 用户裁:撤销「一条总账」与「按病根拆多条」两案,并为本条单账(存量债全部清除,紧急优先级);原「gdstyle 基线陈旧键待人工清理」条目并入波 0(基线对账刷新),原「结构审查未立项小件候审」条目并入波 7(卡已写;iter38 施工停卡后经用户裁于 2026-10-26 修订定稿 v1.3,待编排)。**2026-10-26 设计段闭合(逐波裁定全数落定)**:①段组织=逐波开设计段,纯代码波(波 0/2/3/4/5/6/8)写卡前确认零设计改动+按当时 master 重测读数即可写卡;②波 2 各文件内部拆、波 6 视图内部拆私有函数、波 8 config_db 纯代码收敛(三处零设计改动);③波 1 拆件定稿=轴甲两件——battle_orchestrator 拆出 BattleFxHost(效果引擎宿主域)+RewardGrant(奖励授予域),宿主保留状态机/facts 缓冲/订阅/段驱动/行发射基建/呈现投影,attune 族原位保留(迭代 39 副卡语义领地),emit 经 bind 注入 Callable,行数恶化债(c4c69701 挂账)本波还债归绿,残留债「改善非清零」口径预计 8–10 键;定稿落文 architecture.md v1.18(功能层两新件行+「战斗编排域拆件定稿」节);**同日独立审查折入**(grilling+godot-master 双子代理并行、双判回炉补裁级——骨架成立、接线未闭合):阻断 8 条去重 6 组+建议 5 条全数折入 v1.18——跨件单向接线裁死(RewardGrant 持 fx 件引用/fx 兑付走注入 Callable,禁 RefCounted 环)、settlement/ 段类随动(直持三引用封转发壳)、12 随迁键卡内收敛义务(禁波 0 refresh 吸收)、两新件消费依赖列补全+引用束注入、treasure_interact_controller 三触点分家(现值回调双取值面)、_fx_revealing 再入闸归 fx 件(裁定全文见清点报告 §六第 6 条);④全部波不改游戏规则与玩家可见行为,design/gdd/systems/ 零修订预期;波 5 已实查落定纯代码(open_ticket 12 参=单据声明形态)。波 7 的 wr5/wr6 验收载体重裁为写卡段用户裁点(卡 v1.2 在册,写卡补呈报)。裁定全文见清点报告 §六。**2026-10-28 迭代 40 合回出账(波 1+波 7 闭合,合并提交 514457d1)**:卡①(波 1)45 键清 44、宿主类变量键豁免第三条顺带落 architecture v1.22 S13 豁免登记,行数恶化债还清(实测 1036≤登记 1302;契约 2 残余 36 行系合并适配承接 master 迭代 39 内容带入,用户裁登记残余债归后续批);卡②(波 7)六件定点修+运行期违约通道负面套件(run_time_fatal_test)落地合回。余波 2/4/6/8 归迭代 41 两卡(在册)。
@@ -263,7 +255,7 @@
#### 棋盘格边长三方取值不一致——待扩板定档处置(2026-10-06 登记,来源=批次移交)
**实况**:扩板已落地(四档板型 10/12/13/14 在跑),2026-10-26 文档面已按单点维护归一:①格边长口径的唯一出处收敛到 [战斗屏规格](design/gdd/ux/battle.md)「棋盘格尺寸公式」——公式含格间距与垂直预留,可读下限 30px,1280 档算例 43/36/33/30 标注为随布局变化的非契约值;②[美术圣经](design/art/art-bible.md) §8.1 改为指路 battle.md、只锁资产侧两条比例,§8.2 甲类整数倍纪律已剔除砖面 tile(瓦片随格边长整格铺满,允许非整数倍);③[HUD框架](design/gdd/systems/表现与支撑/HUD框架.md) 只留装板可行性不等式,删去 36/45 定值档与旧算例;④demo 原型 44px 那一路随 `src/` 退役消失。剩余为代码面两处与口径不同步:`game/probe/layout_probe.gd:15` 的格子可读门槛 `MIN_CELL := 36.0` 仍取 12×12 的旧锚点值,比 battle.md 的可读下限 30px 严——现探针只进 10×10 的 L1 故仍全绿,一旦覆盖 13×13(33px)与 14×14(30px)即会误报红;`game/tests/unit/core/board_gen_reward_test.gd:53` 的格边长冒烟只跑 L1/L2,13×13 与 14×14 无覆盖。断言改动后按 `game/tests/README.md`「能力清单」核对受影响行(验证集清单已退役——test-conventions §8.3)。
**实况**:扩板已落地(四档板型 10/12/13/14 在跑),2026-10-26 文档面已按单点维护归一:①格边长口径的唯一出处收敛到 [战斗屏规格](design/gdd/ux/battle.md)「棋盘格尺寸公式」——公式含格间距与垂直预留,可读下限 30px,1280 档算例 43/36/33/30 标注为随布局变化的非契约值;②[美术圣经](design/art/art-bible.md) §8.1 改为指路 battle.md、只锁资产侧两条比例,§8.2 甲类整数倍纪律已剔除砖面 tile(瓦片随格边长整格铺满,允许非整数倍);③[HUD框架](design/gdd/systems/表现与支撑/HUD框架.md) 只留装板可行性不等式,删去 36/45 定值档与旧算例;④demo 原型 44px 那一路随 `src/` 退役消失。剩余为代码面两处与口径不同步:`game/probe/layout_probe.gd:15` 的格子可读门槛 `MIN_CELL := 36.0` 仍取 12×12 的旧锚点值,比 battle.md 的可读下限 30px 严——现探针只进 10×10 的 L1 故仍全绿,一旦覆盖 13×13(33px)与 14×14(30px)即会误报红;`game/tests/unit/core/board_gen_reward_test.gd:53` 的格边长冒烟只跑 L1/L2,13×13 与 14×14 无覆盖。断言改动后按 `game/tests/README.md`「能力清单」核对受影响行(验证集清单已整册冻结,不再重生成——test-conventions §8.3)。
**改动面**:游戏代码
@@ -311,6 +303,17 @@
**状态**:待写卡
#### 圣经口号型条款机检化批(2026-10-06 登记,来源=审计发现)
**实况**:审计 P2-4——圣经约 55% 条款属口号型(如「暖倾向无压抑」「同一圆角率」无值),与可机检条款混排。目标=逐条审查标注「可机检/目检/口号」三档分行,口号型逐步改写为带值或带判据条款。工程量=全文级(541 行逐条),非一轮能毕。**2026-10-06 三档标注格式已拍板**(←机检/←目检/←方向性,规范见 art-bible 头注「条款验收标注纪律」;数值类推荐「待定现用」态)——本批执行=按此格式分章补标,每章交付用户抽验。挂账:随整屏样张闸前整备批启动,分章推进。
**缺口**:还差整屏样张闸前整备批的启动——格式已定,差启动时点与分章执行。
- 相关文档:[art-bible](design/art/art-bible.md) 全文 · 样张批前置整备
**改动面**:文档+工具代码
**状态**:待文档设计(备选)
#### 战斗区背景图替换——B 区舞台插画 + 临时光柱退役(2026-10-07 登记,来源=会话提及)
**实况**:B 区舞台现行=程序化平色底(`UiKit.STAGE_BG`,`battle_stage_view.gd:47`)+ **顶光柱氛围层**(`:55-63` 四柱,x 基准 110/900/1055/1210@1280,60 段叠层矩形自顶向下渐宽窄渐隐〔顶 α26→0〕,层序=bg < 光柱 < 世界)——二者均系 §6.1 方向稿的**临时占位**,用户口径「光柱只是临时方案,换正式战斗背景后效果更好」。正式件已立资产契约:`stage/stage_bg.png`(源 1280×270,B 区全高含明细带底;三关换挡走 §4.3 `wall_ambient` tint 槽,不按板出三张),属审计 P1-2 查得的「B 区舞台背景插画 0 张」缺口。**光柱在背景到位后顺带退役或吸收进背景绘制**(不再作为独立程序层)。**与立绘探顶解耦**:大体档「允许向上溢出盒顶 N px」的判定(2026-10-07 用户裁甲案)**不依赖光柱是否存在**,换背景零返工。