61 KiB
需求卡片:架构审查 5.1 封装修复批(2026-11-03)
来源:待办清单「架构审查优化讨论——全库架构审计读数的逐项裁决与整改分批(2026-10-29 登记,来源=审计发现)」条目 5.1 部分(唯一事实源:reports/处置-架构审查5.1封装修复-2026-11-03.md——处置记录与本卡并行成文,本卡开工时该件尚未落盘;T1 首步核其已落盘且与本卡第 3 节逐条一致,冲突即 L3 停卡。设计闭合凭据=2026-11-03 设计讨论会话裁决+审计报告 §5.1+architecture.md:119/:124/:137-146)。 状态:已写卡(v1.1,2026-11-03 修订——godot-master 终审两中等发现与四低项折入+SlotStore→SaveManagerCore 反向私取终审补查并入 T3;处置记录已落盘并与本卡第 3 节核过一致)。改动面:游戏代码(含随逻辑写/改的测试代码)。
1. 目标与完成定义
这批做什么:把 2026-11-03 设计讨论裁决的五处跨对象私有访问修复方案全部落码——封装收口、零行为变更:
| # | 处置对象 | 现状 | 终态 |
|---|---|---|---|
| 1 | settlement 七段 → 编排器 | 七文件对编排器 oc._ 私取 105 行/107 处/19 符号(本卡第 3 节 grep 实核) |
段类构造收引用束(六子对象+编排器公开协作件引用)+七个编排器方法回调(Callable 交付)+公开读数注入;段类对编排器引用归零 |
| 2 | 编排器五个放错位置的方法 | _hero_atk/_feat_yield_adjust/_harmful_variants/_harmful_adjacent/_hits_of 留宿主、段类经宿主引用直调(architecture.md:145「现状形态」) |
各归领域宿主(伤害域/奖励域/地形棋盘域),宿主原方法删除禁留壳 |
| 3 | adventure_runner → BreakpointStore | _bp_store._ 直读写 37 处(32 行;adventure_runner.gd:37 注释自述「宿主读写经件」未落实) |
BreakpointStore 公开方法面承接,宿主私取清零 |
| 4 | save_manager ↔ SlotStore | save_manager→SlotStore:slots._path ×8+slots._migrate_legacy_save 私有方法调用 ×1(save_manager.gd:51/66/69/105/111/118-119/285-286);SlotStore→SaveManagerCore 反向私取约 13 处(slot_store.gd:26-28/38-39/61-76/92-97/119/129/134/159-162——直用 _save._read_only/_reset_to_default/_data/_rename_overwrite/_peek_summary_at,godot-master 终审补查) |
save_manager 侧=SlotStore 公开读投影 active_path()+迁移方法公开化承接;SlotStore 侧=SaveManagerCore 补公开方法面承接(T3 定死) |
| 5 | grant_segment → BattleFxHost;config_db → 三表容器 | grant 直写 fx_host._fx_new_resource_types(:82/:84)与 fx_host._fx_bonus_delta(:169-170/:378-379)共 6 行;config_db.gd:157-159 三行装配直写三表 _resolver |
BattleFxHost 两个公开累积方法;三表 schema 各加公开挂载方法 bind_resolver |
什么状态算完:五处的每一条改动都落码、都有第 8 节对照表配对的验收断言在当轮真实跑批中通过;主证=同种子逐项比对(改前改后动作序列快照逐位同,T1 固化、全程保持绿)+battle_settlement 套件全绿;结构性证据=core 五处跨对象私取 grep 恒零(扫描面非空前置+零命中);代码域闸全绿(冒烟+单元+探针+渲染/静态);两份 reports/ 产出物(实现报告+反哺点清单)写齐。
排序义务:本卡实现排队在 reports/需求卡片-架构审查3.1+3.2整改批-2026-11-02.md 之后(已编迭代 50,未开工)——combat_segment.gd 同文件避让(该卡甲案删 attack_segments 分支 :59-70,本卡第 3 节 combat 行号在其合回后漂移,T1 复核以 grep 符号锚定位)。
2. 设计事实源
- 处置记录(输入合同,逐条一致):
reports/处置-架构审查5.1封装修复-2026-11-03.md——五处裁决方案、段类终态、出卡边界。本卡第 3 节现状实查与第 4/7 节签名设计是其机械承载;T1 复核两件一致(冲突=上游缺陷,L3 停卡)。口径注:处置记录「公开读数一并改注入」=形态族措辞,涵盖本卡第 4 节「调用参数现值交付」(round_index/battle_result 两变值标量构造期注入必陈旧——现值交付即注入的形态之一),T1 核对不按字面机械比对、按此口径核。 - 审计背景:
reports/审计-全库架构审查-2026-10-29.md§5.1(settlement 五段类直读写编排器私有成员 20+ 处;行号已漂移,以本卡第 3 节实查为准)。 - 架构登记:
design/engineering/architecture/architecture.md——:119(battle_orchestrator 保留面与 B1 域文件集)、:124(BoardInstaller 引用束注入先例——「构造=引用束注入(……防 _init max-parameters 新键)」)、:137-146(战斗编排域拆件定稿::140 轴丙、:141 编排器保留面登记、:143 跨件单向接线、:145 段类随动现状句)。
3. 现状事实(2026-11-03 worktree arch51-card 实查,基点 6261b36e;开工自行复核)
3.1 五处私取面盘点
处 1·settlement 七段 → 编排器(game/core/settlement/):grep -c 'oc\._' 逐文件=grant_segment 54/combat_segment 23/round_cycle 10/verdict_segment 9/battle_refresh_flow 5/aura_segment 2/decay_segment 2,合计 105 行;grep -o "oc\._[a-z_]*" | wc -l=107 处(grant:131 与 grant:424 两行各含 2 处);符号 19 种=_facts×24、_enemy_system×22、_damage×18、_emit_row×16、_reward_economy×5、_hits_of×5、_status_effects×2、_feat_yield_adjust×2、_emit_composition_effects×2、_battle_over×2、_rounds×1(:42 oc._rounds._grant_seg 跨两层)、_install_and_reset×1、_hero_atk×1、_harmful_variants×1、_harmful_adjacent×1、_fx_host×1、_fatal×1、_exit_distribution×1、_emit_settlement_snapshot×1。另有对编排器公开成员访问:action_economy×11、db×7、minesweeper×6、round_index×3、fx_host()×3、battle_result×2、rng×2、attune_param_sum()×1(grant:280)、perfect_sweep_earned()×1(grant:284)。
处 2·搬家五方法(均在 battle_orchestrator.gd,仅段类与编排器自用):
| 方法 | 现址 | 调用面 |
|---|---|---|
_hero_atk() -> int |
battle_orchestrator.gd:70-71(读 _facts.encounter hero_atk 键、缺省 db.combat.hero.atk——E4 派生读,禁快照成员) |
combat_segment:55;编排器 spawn 消费点 :282;测试 roll_multiplier_test.gd:45-59 经真实链路覆盖(零直调) |
_feat_yield_adjust(snap, positive, pos_m, neg_m) |
:452-461(读 _reward_economy.polarity_row) |
grant_segment:99/:140 |
_harmful_variants(vids) |
:466-473(读 db.combat.variation) | grant_segment:87;_harmful_adjacent 内部 :484 |
_harmful_adjacent(cell) |
:478-485(读 minesweeper.current_board) | grant_segment:339 |
_hits_of(hits, kind) |
:489-494(纯过滤) | grant_segment:110/:115/:138/:356、combat_segment:62(该行随 3.1+3.2 批甲案删除)、测试 adventure_feats_test.gd:671/:691/:727 |
处 3·adventure_runner → BreakpointStore:grep -o "_bp_store\._[a-z_]*" | wc -l=37 处(32 行)=_resume_bp×8、_pending_next_level×7、_save_manager×6、_bp_read×5、_loadout_seeded×5、_last_level_payload×4、_last_treasure_cleared×2。分布:adventure_runner.gd:107/:115/:157/:168/:180/:185/:189/:191/:201/:220/:235/:241/:300-302/:325-326/:376-378/:388/:412/:421/:430/:438/:456/:464/:467-468/:474-476。BreakpointStore(breakpoint_store.gd)类变量 15(:48-63——贴顶禁再增,architecture.md:113 同款登记);公开方法现 5(snapshot/restore_ledger/restore_curio_state/apply_resume_params/restore_stop_bank_fragments);_bp_read(:196-202)内部消费点 :160。测试面:feat_vouchers_test.gd 与 meta_progression_forge_test.gd 等 12 处 orch._rounds._grant_seg._judge_seal(...) 直调与 orch._rounds.mines_hits 7 处——_grant_seg/mines_hits 成员名与归属不变,零波及。
处 4·save_manager ↔ SlotStore(双向):save_manager→SlotStore=save_manager.gd:51(slots._migrate_legacy_save(LEGACY_SAVE_PATH, slots.slot_path(1), ...))+:66/:69/:105/:111/:118/:119/:285/:286(slots._path ×8)。SlotStore→SaveManagerCore 反向私取(godot-master 终审补查,2026-11-03 本会话 grep 精确实数)=21 处/21 行:_save._read_only×8(:26/:38/:65/:69/:74/:87/:91/:96)、_save._reset_to_default×5(:28/:39/:70/:92/:119)、_save._data×4(:66/:75/:88/:97)、_save._peek_summary_at×2(:129/:134)、_save._rename_overwrite×2(:159/:162)。SlotStore(slot_store.gd)_path :9;_migrate_legacy_save :150-163(唯一外部调用方=save_manager:51;件内零调用);公开读投影先例=has_write_target() :53-54(_path != "")。SlotStore 类变量 4、公开方法 10。SaveManagerCore 私有被用面五成员=_read_only :23、_data :24、_reset_to_default :279、_peek_summary_at :217(save_manager 件内调用方 :217 定义、slot_store 两处外部)、_rename_overwrite :317(件内调用方 :118/:286);公开方法现 7、类变量 5。
处 5·grant_segment → BattleFxHost+config_db → 三表容器:grant_segment.gd:82-84(fx_host._fx_new_resource_types.has(ctype) 读+[ctype] = true 写——空串短路边界在 :82)与 :169-170、:378-379(fx_host._fx_bonus_delta.has(axis) 守卫+[axis] += delta)。BattleFxHost 类变量 15(battle_fx_host.gd:23-37——贴顶禁再增,头注 :10-16 自封)、公开方法 16、两私 members 无成员外读者(grep 全库仅 grant 四处)。config_db.gd:157-159 三行 combat.board_gen._resolver = _resolver/combat.enemy._resolver = _resolver/run.difficulty._resolver = _resolver;三表 _resolver 声明=board_gen_table.gd:113、enemy_table.gd:212、difficulty_table.gd:33(均无类型注解;消费点 :118/:217/:38)。表实例经 load() 出 .tres、无法带构造参,装配期注入是唯一时点(config_db.gd:131-159 _assign_loaded)。
3.2 写 T 卡依据的其他现状
- 段类现状形态:五段构造=grant/combat 三参(host/fx_host_ref/reward_grant_ref)、aura/decay/verdict 单参(host);RoundCycle 三参直构(host/fx_host_ref/reward_grant_ref,round_cycle.gd:22-29);battle_refresh_flow 全 static(can_refresh/execute 收
oc入参,:15-43)。编排器_init(battle_orchestrator.gd:211-237)建件序=facts(218)→reward_economy(219)→damage(221)→fx_host(223)→reward_grant(225)→RoundCycle(237);类变量 15(38→15 后贴顶)。 - 编排器回调宿主方法现签名:
_emit_row(head, ri, display, value, extra):750;_fatal(msg):791;_install_and_reset(during_round := false) -> bool:392;_battle_over(result):610;_exit_distribution():575(内含 :593_rounds.roll_round_actions());_emit_settlement_snapshot(verdict):534;_emit_composition_effects(side, ri):524;公开读投影先例=_attune_safe_seen_read:139(RewardGrant attune_safe_seen_cb)、_pool_effective:513(pool_effective_cb)——读投影 Callable 交付是既有形态(architecture.md:121)。 - 编排器三调用点:
can_refresh()/player_request_refresh()单行转发(:598-607);_on_round_end→_rounds.settle_if_due()(:445-447);begin_battle →_rounds.roll_round_actions()(:262)。facade 公开签名零参(presentation 路径)。 - 测试连带面:settle_segments_test.gd:20-24 五段
new(oc, ...)直构断言、:28-34 宿主回指断言(oc._rounds._grant_seg.oc == oc等 6 条)——随束形态换代改写;adventure_feats_test.gd:671/:691/:727orch._hits_of直调——随搬家改指。其余 orch._ 访问(_facts×6、_rounds×13、_emit_row×2)所涉宿主成员全保留,零波及。round_flow_skill_pool_test/seal_polarity_test/refresh_feats_test/effect_port_test 等走公开入口,零改写。 - gdstyle 基线:tools/gdstyle_baseline.txt 仅 5 键(adventure_runner 类变量 23、level_runner 两键、board_view 两键)——本卡触件均无登记值,T1 现场读数即对账基线。S13 默认阈值:公开方法 ≤20/类变量 ≤15/单函数分支 ≤8/返回 ≤6。
- 静态闸:S7_B1_SET 与 S8_FILES(game/tests/static_scan.sh:317/:361)已含七段文件——本批零闸件改动。S9 R1A 判据=
var x: Dictionary|Array裸注解(tools/audit_type_hints.py:22)——新增成员一律具体类名或参数化泛型。 - 能力清单:game/tests/README.md 在役(本卡判据引用行=:59/:63/:86/:89/:92/:124/:174,能力名见第 8 节对照表)。
4. 设计契约(违反即返工红线)
- 🔴 逐条一致:本卡一切内容与处置记录逐条一致;实现段发现卡面与处置记录冲突=上游缺陷,停卡退回写卡段(L3)。
- 🔴 零行为变更:同种子同输入下动作序列、明细行流、结算快照、信号顺序逐位一致(T1 golden 主证全程保持绿);RNG 消费序零漂移(behavior_roll/encounter/fx_reveal/gp_drop 四封闭流的流名、开流时点、取号序逐字);明细行协议词表零触碰。
- 🔴 段类对编排器引用归零:七个 settlement 文件(grant/combat/round_cycle/verdict/battle_refresh_flow/aura/decay)全文
\boc\b标识符零命中(含头注与行内注释——随改写一并清除)。 - 🔴 编排器保留面零增减:architecture.md:141 登记原样——战斗状态机与生命周期、行发射基建(_emit_row/_assert_row_source/_fatal)、呈现投影、刷新面、nest_preview_count。七回调的宿主方法体零改动(Callback 交付不搬家:_emit_row/_fatal/_install_and_reset/_battle_over/_exit_distribution/_emit_settlement_snapshot/_emit_composition_effects 全部留宿主)。
- 🔴 搬家五方法禁留壳:宿主原方法删除,禁兼容别名、禁转发壳、禁注释化残段(第 13 节全款适用)。
- 🔴 束形态(引用束注入,BoardInstaller 先例 architecture.md:124):
- 编排器束(
_init组装一个Dictionary,封闭 20 键):facts/units/damage/status_effects/reward_economy/reward_grant/fx_host/minesweeper/db/action_economy/rng+emit_row_cb/fatal_cb/install_cb/battle_over_cb/exit_distribution_cb/emit_snapshot_cb/emit_composition_cb+attune_param_sum_cb/perfect_sweep_cb。前 11 键=六子对象(BattleFacts/UnitContainer/DamageController/RewardEconomy/StatusContainer/BattleFxHost)+四个既有公开协作件引用(minesweeper/rng/reward_grant——段类现役消费面所需)+两公开读数引用(db/action_economy);后 9 键=七个编排器方法回调(Callable 绑宿主对应方法)+两个公开读投影回调(attune_param_sum(kind) -> int/perfect_sweep_earned() -> bool——RewardGrant attune_safe_seen_cb/pool_effective_cb 同款先例)。 - 接收方各取所需:RoundCycle 收全束并分发五段(各段构造收同一束);RoundCycle 解包自用七键(facts/units/fx_host/db/action_economy/rng/emit_row_cb);各段断言各自必需键在束(BattleFxHost :41-42 assert 缺键先例)。必需键分配=grant 12(facts/units/damage/reward_economy/fx_host/minesweeper/db/action_economy/reward_grant/emit_row_cb/attune_param_sum_cb/perfect_sweep_cb)、combat 10(facts/units/damage/status_effects/fx_host/minesweeper/db/emit_row_cb/fatal_cb/reward_grant)、aura 1(emit_composition_cb)、decay 2(status_effects/emit_row_cb)、verdict 5(units/emit_row_cb/emit_snapshot_cb/battle_over_cb/exit_distribution_cb)。
- 换图刷新流程件同批同形:BattleRefreshFlow 由 static(oc 入参)改实例——
_init(bundle: Dictionary)收 8 键(facts/db/action_economy/fx_host/reward_economy/minesweeper/install_cb/grant_seg);can_refresh/execute 两入口的oc入参改依赖交付,编排器两公开方法单行转发形态不变(architecture.md:123)。grant_seg 键=段间引用(RoundCycle 构造五段后写入副本束再建本件——授予段引用直接交换图流程件,oc._rounds._grant_seg跨两层私取随之消灭)。 - 公开读数注入:db/action_economy=引用注入(构造期稳定);round_index/battle_result=调用参数现值交付(两标量每拍变值,构造期值注入必陈旧)——
settle_if_due(battle_result: String, ri: int)、roll_round_actions(ri: int)、can_refresh(battle_result: String)、execute(battle_result: String, round_index: int),编排器调用点传现值(:262/:447/:593/:598-607 四处),facade 零参签名不变。
- 编排器束(
- 🔴 跨件单向接线:段类↔编排器只经束注入(引用+Callable),禁双向强引用;注入 Callable 亦属接线面、禁为省参数改持对象引用(architecture.md:143 同款;段类/编排器均 RefCounted,环引用随每战新建泄漏)。
- 🔴 读投影消费形态:Callable.call 返回 Variant,消费一律
int(...)/bool(...)包裹(battle_fx_host.gd:128 facts_cb.call 消费先例)。 - 🔴 S9 参数化形态:本批全部新增成员声明与函数注解——具体类名(
var facts: BattleFacts)或参数化泛型(Dictionary[Variant, Variant]);裸Dictionary/Arrayvar 注解=S9 R1A 红。迁移函数(五方法)注解逐字保持原形(原签名已过 S9)。 - 🔴 fail-fast:束缺键 assert 致命;零软回退。Core 零 UI 依赖不破(全套件
--headless --script可跑通)。 - 🔴 测试纪律:禁变异类测试、禁撤销类取证;禁删断言/放宽阈值换绿(第 8 节申报清单之外零删改)。
5. 范围边界
收件=第 1 节表五行全部(settlement 七段解耦+搬家五方法+breakpoint_store 公开面+存档双向公开面〔save_manager↔SlotStore 两方向〕+battle_fx_host 两累积方法+三 schema 挂载方法,及各自的调用点改址与测试适配)。
不收件(去向已指认):
- presentation 层约 227 行私取面——另开设计讨论(本卡裁决范围外;去向=待办清单本条目实况,非本批)。
- sim/probe/tests 的测量面直构惯例与测试受控例外——零清扫(orch._facts/orch._rounds/orch._emit_row 等测试直连维持现状)。
- 段类→协作件残余私取一处:grant_segment.gd:197
oc._damage._emit_hero_damage_taken(...)随本批改经damage.emit_hero_damage_taken(...)(DamageController 该方法去下划线公开化,见 T2)——除此之外段类对 damage/fx_host/reward_grant 公开成员的直读(counters_ctx/engine/facts_inject/defer)零触碰。 - 职责归属零改动(除搬家五方法——已裁的五处归位);编排器七回调宿主方法体零改动;架构七段结构零改动(五段段序、SettlementTable.segment_order、RoundCycle/BattleRefreshFlow/五段段类的文件与职责登记全部在案不动)。
- 闸件(static_scan.sh)零改动;MC/模拟零跑(无数值改动);
tools/gdstyle_baseline.txt零改动(本批无键恶化,见第 14 节)。
6. 关联文档同步面
实现批禁写 design/ 整个目录、两份根流程清单与 game/tests/README.md;下表每条的落文义务全部进 reports/iter<N>-反哺点-<日期>.md(N=编排段定),由用户裁决后归文档批落文:
| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务(反哺点清单逐条承载) |
|---|---|---|
| design/engineering/architecture/architecture.md | :125 RoundCycle 行「三参直构(host/fx_host_ref/reward_grant_ref——五段构造透传不落成员)」→ 束注入+持有 BattleRefreshFlow+公开方法 3→4+类变量 8→15(贴顶);:123 BattleRefreshFlow 行 static 两入口收 oc → 实例束注入、宿主改经 RoundCycle 交接 grant_seg、类变量 0→8;:127 settlement/ 五段段类行构造形态句 → 束注入、对编排器零引用;:122 damage_controller 行实测类变量 12→13+公开面净增(hero_atk/hits_of/emit_hero_damage_taken);:121 RewardGrant 行 +feat_yield_adjust;:120 BattleFxHost 行 +两累积方法(类变量 15 不变);核心层表 A2 minesweeper_rules 行公开面 18→20(贴顶);核心层表 breakpoint_store 行公开方法面 5→18;核心层表 save_manager 行公开面 7→14(+5 承接方法+peek_summary_at/rename_overwrite 两更名公开化)+slot_store 行「双向公开面」(21 处反向私取清零) | 反哺点清单逐条列行号与改后登记内容——机械面文档禁直改 |
| design/gdd/systems/战斗循环/战斗结算.md | 无陈述变化(明细流水词表、五段段序、段边界全部零触碰——零行为变更批) | 反哺点清单写「零反哺」确认行 |
| 术语表 | 无新术语(引用束注入/读投影/公开方法面均仓库现行词) | 确认行「零新增术语」 |
(机检口径:本表同步义务格无一条写「随批」。)
7. 任务卡 T1..T5
卡前·文件结构图
全部行为面=非行为改动(零行为变更批),行标【非行为】+对照表 R 行号;测试件全部为随逻辑写/改的测试代码。一起改的按职责放一起——段类七文件同卡(T2)、存档断点两对同卡(T3)。
core 层(编排域)
game/core/battle_orchestrator.gd 【非行为 R1/R2】_init 束组装(20 键);:70-71/:452-461/:466-473/:478-485/:489-494 五方法删除;:282 hero_atk 改指 _damage.hero_atk();:262/:447/:593 三调用点传参;:598-607 facade 改经 _rounds.refresh_flow()
game/core/settlement/round_cycle.gd 【非行为 R1】束注入(15 成员贴顶)+持有/构建 BattleRefreshFlow+settle_if_due/roll_round_actions 签名扩展+refresh_flow() 读出口
game/core/settlement/grant_segment.gd 【非行为 R1/R2/R3】束解包 12 成员+54 处改址+:82-84/:169-170/:378-379 改公开累积方法+头注改写
game/core/settlement/combat_segment.gd 【非行为 R1/R2】束解包 10 成员+23 处改址+hero_atk 改指
game/core/settlement/aura_segment.gd 【非行为 R1】单回调成员+头注改写
game/core/settlement/decay_segment.gd 【非行为 R1】两成员+改址
game/core/settlement/verdict_segment.gd 【非行为 R1】束解包 5 成员+四回调改址
game/core/settlement/battle_refresh_flow.gd 【非行为 R1】static 改实例+束注入 8 成员+grant_seg 段间引用
game/core/damage_controller.gd 【非行为 R2】+facts 成员(12→13)+hero_atk()+static hits_of()+_emit_hero_damage_taken 公开化(:449/:561 内部调用点随改)
game/core/reward_grant.gd 【非行为 R2】+feat_yield_adjust()
game/core/minesweeper_rules.gd 【非行为 R2】+harmful_variants()/harmful_adjacent()(公开 18→20 贴顶)
game/core/battle_fx_host.gd 【非行为 R3】+mark_new_resource_type()/+add_bonus_delta()(成员 15 不变)
core 层(冒险/存档域)
game/core/breakpoint_store.gd 【非行为 R4】+13 公开读写方法面(成员 15 不变;_bp_read 更名 bp_read 公开化——:160 内部调用点随改)
game/core/adventure_runner.gd 【非行为 R4】37 处改址(:107..:476 逐处)
game/core/save_manager.gd 【非行为 R5】+5 公开方法(set_read_only/read_only/reset_to_default/data_snapshot/restore_data)+_peek_summary_at/_rename_overwrite 更名公开化(件内调用点随改);:51/:66/:69/:105/:111/:118-119/:285-286 九行改址
game/core/slot_store.gd 【非行为 R5】+active_path();_migrate_legacy_save 更名 migrate_legacy_save 公开化;反向私取 21 处改址(_save._ → save_manager 公开面)
game/core/config_db.gd 【非行为 R6】:157-159 三行改经 bind_resolver()
game/data/schemas/board_gen_table.gd 【非行为 R6】+bind_resolver(resolver: ConfigDbResolver)
game/data/schemas/enemy_table.gd 【非行为 R6】同上
game/data/schemas/difficulty_table.gd 【非行为 R6】同上
测试件(随逻辑写/改)
tests/unit/battle_settlement/settlement_wiring_snapshot_test.gd 【非行为 R1·新增】同种子逐项 golden 对拍(主证)
tests/unit/core/encapsulation_sweep_test.gd 【非行为 R1–R6·新增】五处结构性零命中扫描(非空前置+正锚)
tests/unit/core/settle_segments_test.gd 【非行为 R1】:20-34 束构造与同一性断言适配
tests/unit/core/adventure_feats_test.gd 【非行为 R2】:671/:691/:727 hits_of 改指 DamageController.hits_of
tests/run_all.gd 【非行为】manifest +2 行(snapshot/sweep)
文档件
game/tests/README.md 写卡段判断=零编辑(第 8 节能力行判断依据)——实现批禁写,批末只核对表上能力名与对照表引用一致
T1 基线固化与主证落盘(估时 0.25 工作日;区间 0.25–0.5) 取用:无(本卡起点)。产出:golden 基线(改前读数冻结)+S13 对账基线+grep 底账;本卡实现排序核对。
- 核对实现排序在案:3.1+3.2 卡(迭代 50)未合回则本批不开工(第 1 节排序义务);combat_segment.gd 现址复核(甲案 :59-70 分支已删则以 grep 符号锚定位,行号漂移即记录进实现报告,禁改判据)
- 核对处置记录
reports/处置-架构审查5.1封装修复-2026-11-03.md已落盘且与本卡第 3 节逐条一致(冲突=L3 停卡) - 新增 tests/unit/battle_settlement/settlement_wiring_snapshot_test.gd(extends SceneTree+Kit.check 主通道,全类型标注):手搭驱动=
ConfigDbScript.new()+load_tables("res://data/tables", true)→RngServiceCoreset_master_seed(4242)→BattleOrchestrator.new(db, rng);捕获面=step_row全量行数组+settlement_snapshot全量载荷数组+battle_finished载荷+收束时presentation_snapshot()关键键(round/battle_result/hero.hp/enemies.size())。驱动序(逐字定死):①begin_battle({"level_index": 1, "node_depth": 1, "hero_hp": int(db.combat.hero.max_hp), "voucher_rap": 20});②轮 1:AutoPlayer.choose_dig(minesweeper)返{dig_cell, hero_cell}非空则settle_batch([{"action": "move", "cell": hero_cell}])→settle_batch([{"action": "dig", "cell": dig_cell}])→对首个未揭示且与主角相邻的格 csettle_batch([{"action": "seal_place", "cell": c}])(封印已揭示格在棋盘面必拒〔target_revealed〕——封印子链 _judge_seal_hit/_seal_hit_effects/_judge_seal_miss 及封印匠/示警烟火/完美保险扩展行必须真实进入 golden 行流;「封已揭示安全格」的拒绝路径由 seal_polarity_test 既有回归兜底,不入 golden 主证)→settle_batch([{"action": "stop"}]);③轮 1 结算后player_request_refresh()(voucher_rap=20 保证 RAP 抵折后价——覆盖换图刷新链:can_refresh/execute/install_cb/grant_seg 成功事实);④轮 2:choose_dig 一挖一停;⑤轮 3:径直settle_batch([{"action": "stop"}])。断言=捕获序列与const GOLDEN(行字典逐位含 type/source_class/origin_cell/round_index/display_name/value/其余载荷键)逐位相等〔封装5.1 V1〕 - 改前取数:本步骤在任何生产码改动之前执行——先写测试与空跑转储通道(GOLDEN 为空时打印捕获序列 JSON 后按预期码退出),在未改树上跑出 golden、填入 GOLDEN 常量、复跑全绿;golden 即改前基线读数(不构成验收,验收=改后全程保持绿)
- S13 对账基线:对本卡全部 core/data 存量触件(第 14 节清单 15 件)现场跑 gdstyle 记读数为基线(既有登记仅 adventure_runner 类变量 23 一件照登对账);跑
python tools/run_smoke.py冒烟基线全绿读数落实现报告 - grep 底账五件落实现报告:
oc\._(settlement 七文件)、_bp_store\._(adventure_runner)、slots\._(save_manager)、_save\._(slot_store——反向私取 21 处)、_fx_new_resource_types|_fx_bonus_delta(grant)与\._resolver =(config_db)——命中行号清单=T5 sweep 的改前底账
T2 settlement 七段解耦+搬家五方法(估时 1.25 工作日;区间 1–1.5) 取用:T1 golden 基线。产出:处 1+处 2 清零——段类对编排器引用归零、五方法归位。
- battle_orchestrator.gd
_init(:211-237):RoundCycle 构造改RoundCycle.new(束)——束 20 键逐字(第 4 节束形态表;Callable 键绑自对应方法:"emit_row_cb": _emit_row、"fatal_cb": _fatal、"install_cb": _install_and_reset、"battle_over_cb": _battle_over、"exit_distribution_cb": _exit_distribution、"emit_snapshot_cb": _emit_settlement_snapshot、"emit_composition_cb": _emit_composition_effects、"attune_param_sum_cb": attune_param_sum、"perfect_sweep_cb": perfect_sweep_earned) - 搬家五方法落位(宿主体逐字迁移、注解逐字保持):
- damage_controller.gd:
_init加第五参facts_ref(成员var facts: BattleFacts,:49 构造体加行);新增func hero_atk() -> int(体=battle_orchestrator.gd:70-71 逐字,_facts→facts);新增static func hits_of(hits: Array, kind: String) -> Array(体=:489-494 逐字);_emit_hero_damage_taken更名emit_hero_damage_taken公开化(体逐字;内部调用点 :449/:561 随改) - reward_grant.gd:新增
func feat_yield_adjust(snap: Dictionary, positive: bool, pos_m: int, neg_m: int) -> Dictionary(体=:452-461 逐字——reward_economy 为本件既有成员 :22) - minesweeper_rules.gd:新增
func harmful_variants(vids: Array) -> Array与func harmful_adjacent(cell: Vector2i) -> Array(体=:466-473/:478-485 逐字——db 为本件构造参、current_board() 自有;:484 内部自呼_harmful_variants(board.variant_ids(n))随更名改harmful_variants(board.variant_ids(n)),禁留旧名) - battle_orchestrator.gd:五方法整段删除(:70-71/:452-461/:466-473/:478-485/:489-494);:282
hero_atk_override: _hero_atk()→_damage.hero_atk()
- damage_controller.gd:
- round_cycle.gd 重写:
_init(bundle: Dictionary)——断言 7 必需键(facts/units/fx_host/db/action_economy/rng/emit_row_cb)后解包为同名成员;五段构造改XxxSegment.new(bundle);复制束写入"grant_seg": _grant_seg后构建BattleRefreshFlow.new(束副本);settle_if_due(battle_result: String, ri: int)(:35→参数、:40 删、段驱动用 ri);roll_round_actions(ri: int)(:67/:80 用 ri);新增func refresh_flow() -> BattleRefreshFlow;全文oc.改址(映射表=oc._facts→facts、oc._enemy_system→units、oc._emit_row→emit_row_cb.call、oc._fx_host→fx_host、oc.db→db、oc.action_economy→action_economy、oc.rng→rng);头注「耦合边界」段改写(束注入+签名扩展+随编排器每战新建同灭语义不变) - grant_segment.gd 重写:
_init(bundle: Dictionary)断言 12 键解包 12 成员(第 4 节分配表);54 处改址——除上表映射外加:oc._reward_economy→reward_economy、oc.minesweeper→minesweeper、oc._hero_atk()→(无此调用)、oc._feat_yield_adjust(...)→reward_grant.feat_yield_adjust(...)(:99/:140)、oc._harmful_variants→minesweeper.harmful_variants(:87)、oc._harmful_adjacent→minesweeper.harmful_adjacent(:339)、oc._hits_of→DamageController.hits_of(:110/:115/:138/:356)、oc.attune_param_sum("rap_transfer_mult")→int(attune_param_sum_cb.call("rap_transfer_mult"))(:280)、oc.perfect_sweep_earned()→bool(perfect_sweep_cb.call())(:284)、oc._damage._emit_hero_damage_taken(...)→damage.emit_hero_damage_taken(...)(:197);:82-84 改var is_new_type := fx_host.mark_new_resource_type(ctype);:169-170 与 :378-379 改fx_host.add_bonus_delta(String(h.get("axis", "")), int(h.get("delta", 0)));头注改写 - battle_fx_host.gd 新增两公开累积方法(成员零增,头注类变量封闭面句不动):
func mark_new_resource_type(ctype: String) -> bool——if ctype == "": return false;if _fx_new_resource_types.has(ctype): return false;置位后return true(空串短路边界=原 :82 形态逐位等价)。func add_bonus_delta(axis: String, delta: int) -> void——if _fx_bonus_delta.has(axis): _fx_bonus_delta[axis] += delta - combat_segment.gd 重写:
_init(bundle)断言 10 键解包;23 处改址(映射同上+oc._fatal→fatal_cb.call、oc._status_effects→status_effects、oc._hero_atk()→damage.hero_atk());oc._hits_of行随 3.1+3.2 批已删——复核以 grep 为准;头注改写 - aura_segment.gd(成员
var emit_composition_cb: Callable,:15-16 改emit_composition_cb.call("hero", ri)/("enemy", ri))、decay_segment.gd(成员 status_effects+emit_row_cb)、verdict_segment.gd(成员 units+四回调,:18/:20units.hero_unit()/units.query_alive("enemy")、:22emit_snapshot_cb.call(verdict)、:25/:29battle_over_cb.call(...)、:32exit_distribution_cb.call())三件重写+头注改写 - battle_refresh_flow.gd 重写:去 static——
_init(bundle: Dictionary)断言 8 键(facts/db/action_economy/fx_host/reward_economy/minesweeper/install_cb/grant_seg)解包;_effective_refresh_cost()无参实例方法(:15-20 体逐字,oc.db→db、oc.fx_host().fx_emit→fx_host.fx_emit);can_refresh(battle_result: String) -> bool(:24-28 体逐字,oc.battle_result→参数、oc._facts.refresh_used→facts.refresh_used);execute(battle_result: String, round_index: int) -> bool(:32-43 体逐字——oc._facts.refresh_used += 1→facts.refresh_used += 1、oc._reward_economy.retire_mapping()→reward_economy.retire_mapping()、oc.minesweeper.retire_board(true)→minesweeper.retire_board(true)、oc._install_and_reset(true)→bool(install_cb.call(true))、oc._rounds._grant_seg.apply_board_refreshed(oc.round_index)→grant_seg.apply_board_refreshed(round_index));头注「调用路径」句改写(编排器单行转发形态不变) - battle_orchestrator.gd 收口::598-599
return BattleRefreshFlow.can_refresh(self)→return _rounds.refresh_flow().can_refresh(battle_result);:606-607 →return _rounds.refresh_flow().execute(battle_result, round_index);:262roll_round_actions()→roll_round_actions(round_index);:447settle_if_due()→settle_if_due(battle_result, round_index);:593 →roll_round_actions(round_index);can_refresh/player_request_refresh/_on_round_end/begin_battle/_exit_distribution五处体注释同步+:280-281 注释(「_hero_atk派生读=受理后不变量」句引用将删除的方法名)随 :282 改指一并改写 - 测试适配:settle_segments_test.gd :20-24 五段直构断言改束形态(以真实编排器协作件组装束逐段
new(bundle)成功断言);:28-34 宿主回指断言 6 条改同一性断言(oc._rounds._grant_seg.facts == oc._facts、oc._rounds._combat_seg.fx_host == oc.fx_host()等——同一性强度对应回指,削减弱化申报 1);adventure_feats_test.gd :671/:691/:727orch._hits_of(...)→DamageController.hits_of(...)(削减弱化申报 2) - 孤立验证新增段 → 出红只跑红件最小单元 → 并入全套(回归措辞:里程碑卡出口跑一次全套闸;卡内修复只做出红最小单元的最窄确认);本卡出口=golden 快照绿+battle_settlement 套件全绿+冒烟全绿
T3 断点与存档公开面(估时 0.625 工作日;区间 0.5–0.75) 取用:T1 底账。产出:处 3+处 4 双向清零。
- breakpoint_store.gd 新增公开方法面(13 个,成员零增——类变量 15 贴顶):
func bind_save_manager(sm: SaveManagerCore) -> void、func save_manager() -> Variant(读投影,可 null)、func set_pending_next_level(v: bool) -> void/func pending_next_level() -> bool、func set_loadout_seeded(v: bool) -> void/func loadout_seeded() -> bool、func set_resume_bp(bp: Dictionary) -> void/func clear_resume_bp() -> void/func resume_bp() -> Dictionary(返引用零拷贝——宿主读侧只读)、func bp_read(key: String, bp: Dictionary, fallback: Variant = null) -> Variant(=_bp_read 更名公开化,:160 内部调用点随改)、func set_last_level_payload(payload: Dictionary) -> void/func last_level_payload() -> Dictionary、func set_last_treasure_cleared(v: int) -> void/func last_treasure_cleared() -> int(方法体一律一行转发自有成员,零逻辑增量) - adventure_runner.gd 37 处改址(逐处)::107/:157/:180/:185/:241/:438 →
set_pending_next_level(...);:235 →pending_next_level();:115/:191/:201 →set_loadout_seeded(false);:300-301 →loadout_seeded()/set_loadout_seeded(true);:189 →set_resume_bp(bp.duplicate(true));:388 →clear_resume_bp();:302/:376/:377/:378 →resume_bp()(读侧零拷贝语义不变);:168/:302/:377/:378/:412_bp_read→bp_read;:220 →bind_save_manager(sm);:325-326 →var sm = _bp_store.save_manager()后if sm != null: first = not sm.meta_state.career_state()...;:421 →set_last_level_payload(payload.duplicate(true));:464/:467-468 →last_level_payload();:430 →set_last_treasure_cleared(...);:456 →last_treasure_cleared();:474-476 →var sm = _bp_store.save_manager()后sm.clear_breakpoint()/sm.write_to_disk();:37 头注自述句核改(「宿主读写经件」落实后注释与实态一致) - slot_store.gd:新增
func active_path() -> String: return _path(读投影——has_write_target :53 同族);_migrate_legacy_save更名migrate_legacy_save公开化(:150 体逐字;禁留旧名壳);反向私取 21 处改址(第 3.1 节处 4 清单):_save._read_only写 4 处(:26/:38/:69/:91)→_save.set_read_only(false)、读 2 处(:65/:87)→var prev_ro: bool = _save.read_only()、恢复写 2 处(:74/:96)→_save.set_read_only(prev_ro);_save._reset_to_default×5(:28/:39/:70/:92/:119)→_save.reset_to_default();_save._data读 2 处(:66/:88)→var prev_data = _save.data_snapshot()、恢复写 2 处(:75/:97)→_save.restore_data(prev_data)(引用零拷贝语义不变——snapshot 返_data本引用);_save._peek_summary_at×2(:129/:134)→_save.peek_summary_at(...);_save._rename_overwrite×2(:159/:162)→_save.rename_overwrite(...) - save_manager.gd 新增公开方法面承接 SlotStore 反向私取(类变量零增;公开 7→14):
func set_read_only(v: bool) -> void/func read_only() -> bool(体一行转发_read_only)、func reset_to_default() -> void(体=:279 逐字公开化——件内调用点零改,同名);func data_snapshot() -> Dictionary[String, Variant]: return _data/func restore_data(data: Dictionary[String, Variant]) -> void: _data = data(零拷贝——还原引用);_peek_summary_at更名peek_summary_at公开化(:217 体逐字;件内调用点复核——slot_store :129/:134 为外部消费,件内若另有调用随改);_rename_overwrite更名rename_overwrite公开化(:317 体逐字;件内调用点 :118/:286 随改) - save_manager.gd 九行改址::51 →
slots.migrate_legacy_save(...);:66/:69/:105/:111/:118/:119/:285/:286slots._path→slots.active_path()(:118-119 两处同名调用间_path无变更窗口——单线程同步段,逐位等价)
T4 效果宿主累积面与配置挂载面(估时 0.375 工作日;区间 0.25–0.5) 取用:T2(grant 已改指)。产出:处 5 清零(本卡 T2 已落 grant 改址与 battle_fx_host 两方法——本卡复核其孤立验证读数)。
- 复核 T2 步骤中 battle_fx_host.gd 两方法与 grant_segment.gd 四处改址已落(T2 内联实装——本卡不重复列);孤立验证:grant_segment 相关套件(seal_polarity/round_flow)出红最小单元
- board_gen_table.gd / enemy_table.gd / difficulty_table.gd 各新增
func bind_resolver(resolver: ConfigDbResolver) -> void(体一行_resolver = resolver;三件注解同型) - config_db.gd:157-159 三行改
combat.board_gen.bind_resolver(_resolver)/combat.enemy.bind_resolver(_resolver)/run.difficulty.bind_resolver(_resolver)(_assign_loaded 装配序零变化) - 三 schema 解析冒烟(类型环验证义务):bind_resolver 引入 schema→ConfigDbResolver 参数类型注解,与 resolver 既有反向引用(config_db_resolver.gd:41/:61 引 EnemyTable.ROW_KINDS/band_of——:3-8 头注「类型环断根」先例)构成类型引用环——孤立验证必含 config_db_resolver_test 全套当轮真实跑(三 schema 经
load()实例化+resolver 注入+resolve_row/resolve_rowset/resolve_modifiers 真实解析,类型环若引入解析失败当轮即炸);出红即 L3 停卡(禁改走 type-hint: ignore 通道——保 schema 类型注解完整)
T5 结构性扫描与批收口(估时 0.375 工作日;区间 0.25–0.5) 取用:全部前卡。产出:五处结构性恒零证据+批收口两件。
- 新增 tests/unit/core/encapsulation_sweep_test.gd(extends SceneTree+Kit.check,全类型标注;源读取手法沿 player_copy_sweep_test 源 token 扫描先例)——七段断言组,全部带「扫描面非空前置+正锚」:
①七段文件集(settlement/ 七 .gd)逐件:文件存在且非空+含对应
class_name正锚+\boc\b全文零命中〔封装5.1 V2〕 ②battle_orchestrator.gd:非空+func _hero_atk|func _feat_yield_adjust|func _harmful_variants|func _harmful_adjacent|func _hits_of零命中(五方法零残留)〔封装5.1 V3〕 ③adventure_runner.gd:非空+_bp_store\._零命中+_bp_store.bp_read(正锚(新面在用)〔封装5.1 V4〕 ④save_manager.gd:非空+slots\._零命中+slots.active_path()正锚;slot_store.gd:非空+_save\._零命中+_save\.(set_read_only|read_only|reset_to_default|data_snapshot|restore_data|peek_summary_at|rename_overwrite)正锚〔封装5.1 V5〕 ⑤grant_segment.gd:非空+_fx_new_resource_types|_fx_bonus_delta零命中+mark_new_resource_type(正锚〔封装5.1 V6〕 ⑥config_db.gd:非空+\._resolver\s*=零命中+bind_resolver(_resolver)正锚〔封装5.1 V7〕 - run_all.gd manifest 追加 2 行:settlement_wiring_snapshot_test(expect 0,注记「R1 同种子逐项 golden 对拍主证〔封装5.1〕」)+encapsulation_sweep_test(expect 0,注记「R1–R6 结构性零命中扫描〔封装5.1〕」)
- 实现报告
reports/iter<N>-实现报告-<日期>.md:各卡状态+S13 键改前改后对账表(T1 基线逐件核)+golden 改前改后对拍读数+实现决定记录(代拍板白名单逐条回填) - 反哺点清单
reports/iter<N>-反哺点-<日期>.md:第 6 节同步面表逐条落点(architecture.md 八行登记内容、GDD/术语确认行) - 批末核对:game/tests/README.md 能力名与对照表引用一致(本卡零编辑);独立验收审计(第 8 节末)未过不合并;.uid 收口=
--editor --quit一次后确认 2 件新测试件 .uid 已生成随批提交
估时汇总
T1 0.25|T2 1.25|T3 0.625|T4 0.375|T5 0.375。 区间合计 2.25–3.75 工作日;精确汇总 2.875 工作日(切分预案:若 T2 超 1.5 工日,把 T3 切出为独立半日卡顺延,其余不动;合计超 3 工作日=超卡面估时域,须用户确认后方可续批)。
8. 验证闸(改动—验收对照表)
测试方式两分法:下表全部走调试接口验证(单元/集成套直构夹具与真实入口调用);正常流程体验验证=零项(零行为变更批,无目检点——实机观感逐位同改前)。判据全部绑被测改动特有的可观测提交面(同种子行流逐位/束引用同一性/源码零命中带非空前置与正锚)。
| 需求点 | 改动(文件:行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|---|---|---|---|---|---|---|
| R1 七段解耦+束交付 | settlement 七文件重写+battle_orchestrator 束组装与三调用点+RoundCycle/BattleRefreshFlow 形态换代 | settlement_wiring_snapshot_test.gd:_init 主对拍〔封装5.1 V1〕;settle_segments_test.gd 束构造与同一性断言;round_flow_skill_pool_test/seal_polarity_test/refresh_feats_test 既有全套回归 | 单元+集成 | BattleOrchestrator.begin_battle()→MinesweeperRules.settle_batch()→player_request_refresh()(全程公开入口) |
同种子行流与快照逐位同 golden(改前固化);段持注入引用==编排器实例同一性;\boc\b 七文件零命中 |
既有:轮内流与结算五段全序 |
| R2 搬家五方法归位 | damage_controller +hero_atk/hits_of/emit_hero_damage_taken 公开化+facts 成员;reward_grant +feat_yield_adjust;minesweeper_rules +harmful_variants/harmful_adjacent;编排器五方法删除+:282 改指 | settlement_wiring_snapshot_test〔封装5.1 V1〕(五方法消费路径全在行流内——主角攻击 base_value/奖励乘区/terrain_kind 事实/奥术矢开单);roll_multiplier_test.gd:_smoke_hero_atk_derived 既有回归;adventure_feats_test hits_of 面回归;encapsulation_sweep_test 编排器五方法定义零命中〔封装5.1 V3〕 | 单元 | begin_battle()(enc hero_atk override→spawn→攻击单)/授予段真实结算链 |
攻击单基值随 enc override 走(派生读贯通);行流逐位同;五方法宿主定义唯一(编排器零残留) | 既有:伤害公式与掷点乘区 |
| R3 grant→BattleFxHost 累积方法 | battle_fx_host +mark_new_resource_type/+add_bonus_delta;grant :82-84/:169-170/:378-379 改址 | seal_polarity_test/round_flow_skill_pool_test 既有全套回归(血税 bonus_delta 与地质学家 new_resource_type 两订阅行行为面);encapsulation_sweep_test grant 私键零命中+正锚〔封装5.1 V6〕 | 单元 | 授予段真实结算链(mine_hit/seal_hit fx 发射→施加面) | bonus_delta 轴累积值与 new_resource_type 首见判定逐位同;grant 源零私键直写 | 既有:封印与极性路由/不可逆 |
| R4 adventure_runner→BreakpointStore | breakpoint_store +13 公开方法面(_bp_read 更名 bp_read);adventure_runner 37 处改址 | save_rng_roundtrip_test.gd:_test_old_version_save_migrates_and_resumes+:_test_disk_roundtrip_preserves_breakpoint 既有回归(断点组装/回放/续玩全链真实入口);encapsulation_sweep_test _bp_store\._ 零命中〔封装5.1 V4〕 |
单元+集成 | AdventureRunner.resume_adventure()/start_adventure()→write_to_disk()/load_from_disk() |
断点续玩逐位同(27 键冻结);adventure_runner 源零 _bp_store._ 直读写 |
既有:旧档迁移链与断点续玩零跳号(集成) |
| R5 save_manager↔SlotStore 双向公开面 | save_manager→SlotStore=slot_store +active_path/_migrate 更名公开化+save_manager 九行改址;SlotStore→SaveManagerCore=save_manager +5 公开方法/2 更名公开化+slot_store 21 处改址 | save_manager_domain_test.gd:_smoke_save+save_slot_isolation_test 既有回归;encapsulation_sweep_test slots\._ 与 _save\._ 双向零命中+双正锚〔封装5.1 V5〕 |
单元 | SaveManagerCore.write_to_disk()/load_from_disk()/_ready() 迁移口/SlotStore.activate_slot()(三态恢复路径——read_only/data 快照还原)/peek_slot_summary()(窥视委托) |
写盘/读回/迁移/激活-恢复/窥视路径逐位同(tmp+rename 原子序、零拷贝还原语义不变);save_manager 源零 slots._+slot_store 源零 _save._ |
既有:存档写盘⇄读回往返保真 |
| R6 config_db→三表挂载 | 三 schema +bind_resolver;config_db :157-159 改址 | config_db_resolver_test.gd 既有全套回归(_test_rowset_order_preserved/_test_row_kind_routing/_test_difficulty_clamp——resolver 注入后解析面逐位同);encapsulation_sweep_test \._resolver = 零命中+正锚〔封装5.1 V7〕 |
单元 | ConfigDB.load_tables()(装配段)→ConfigDbResolver.resolve_*() |
行集解析/难度 clamp 逐位同;config_db 源零 _resolver 直写 |
既有:行集寻址、行序保序与难度乘数 clamp |
零行为改动面的证据义务:本卡全部六行均为非行为改动(零行为变更批)——不设「行为改动」行;每行的零变更证明=T1 golden 同种子逐项比对(改前固化、改后全程绿)+既有套件零转红+结构性 sweep 恒零。能力行全部「既有」、零新增——判断依据:本批零行为变更=玩家可观测能力面零变化,无新能力可登记;受影响存量行的真实入口与代表用例名零变化(settle_segments_test/adventure_feats_test 文件名与其在册引用不变),故能力清单零编辑(批末核对义务在 T5)。覆盖登记(test-conventions §8.3 新增 core 件覆盖登记义务,2026-11-04 并 master 后适配):本批触碰且曾被审计点名的三件按「经宿主链覆盖」申报——breakpoint_store=R4 行 AdventureRunner.resume_adventure()/start_adventure()→write_to_disk()/load_from_disk() 链+新增 sweep 源扫描;slot_store=R5 行 SaveManagerCore.write_to_disk()/load_from_disk()/_ready() 迁移口链;battle_fx_host=R1/R3 行 begin_battle() 全结算链;三件申报面之外零新增点名义务,meta_state_store 本卡零触碰。
闸口径:重闸=tools/run_all_gates.sh 按本批改动域选档(改动含 game/ 下非 .md 行为载体 → --code);所选域全绿才合并。卡内不写死闸件名单。回归措辞:里程碑卡(T 段)出口跑一次全套闸;卡内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套。
测试削弱申报(允许改/删的旧断言全清单;未申报的删改由独立验收审计判红):
- settle_segments_test.gd:20-24 五段直构断言——构造签名换代(host 三参/单参 → 束单参),断言对象从构造签名改束构造成功;段类可独立实例化的断言意图保持,强度不减(R1)。
- settle_segments_test.gd:28-34 宿主回指断言 6 条(
.oc == oc)——段类对编排器引用归零后回指对象消失;改注入引用同一性断言(段持 facts/fx_host==编排器实例),装配面断言意图保持,强度不减(R1)。 - adventure_feats_test.gd:671/:691/:727
orch._hits_of(...)→DamageController.hits_of(...)——方法搬家改址,断言内容(attack_bonus 命中过滤)零改动(R2)。 以上 3 条均为「随被测改动同步的引用形态迁移」,无一条删除断言或放宽阈值。
独立验收审计:入口=批末 T5 后、合并前;报告=reports/iter<N>-验收审计-<日期>.md;由没参与实现的会话或子代理执行,核对:对照表逐行断言真实存在且在当轮跑批通过、golden 改前改后对拍读数在案、测试削弱申报 3 条之外零删改、第 13 节无效成员零残留、S13 键只降不升对账。未过不合并。
9. 异常分级
- L1 自救:测试断言笔误、束键名拼写、注释错字、改址遗漏一处编译级报错的就地修复——就地改,记录进实现报告。
- L2 记录继续:行号 ±5 行内的漂移(以 grep 符号锚定位后继续);测试失败经排查属既有缺陷且与本批改动无因果——登记跳过并报用户。
- L3 停机写报告等用户:①卡面与处置记录冲突、或处置记录未落盘/与本卡第 3 节不一致(上游缺陷,退写卡段);②golden 改后读数与改前基线出现任何非预期漂移(零行为变更契约被破=上游缺陷停卡,禁就地调和);③束形态与 S13 预算互斥——任一触件成员数超第 14 节预算(RoundCycle 15/BattleFxHost 15/BreakpointStore 15/orchestrator 15 四贴顶件禁再增成员)=上游缺陷停卡退写卡段,禁实现段自行拆件或砍面;④实现中发现第 4 节未登记的第五处编排器私取消费面或搬家方法第 4 个调用方(行为语义不明,禁代裁);⑤机检键与卡片契约互斥(含 schema 校验/静态闸判据冲突)=一律停卡呈报,不得自造第三条路。
10. 代拍板白名单
- 测试内部夹具命名与组织(束组装辅助函数名、golden 序列化键序、sweep 正则的具体写法——判据面不变)。
- 注释与断言消息中文措辞微调(尾缀〔封装5.1 Vn〕与判别词保留)。
- 段类/编排器头注的改写措辞(模块介绍职责不变)。
- 束 assert 缺键报错文案(「引用束缺键」判别词保留)。
- 逐卡内「孤立验证→出红最小单元→并入全套」的执行顺序细节。
- T1 golden 转储通道的实现方式(打印格式/临时旗标,用后即删)。 超清单的决断记入实现报告「实现决定记录」节。
11. 待裁点
零待裁点,开工门=U0——五处修复方案、段类终态(六子对象+七回调+段间引用+公开读数注入+对编排器零引用)、搬家五方法宿主、出卡边界、排序义务均已在 2026-11-03 设计讨论会话由用户裁决;束键分配、回调精确签名、T 卡分解、验收断言由本卡写卡期实查定死(第 3/4/7 节)。本卡未新增任何备选案。
12. 落位与可复用性预检
新增文件(2 件,全部测试件):
- tests/unit/battle_settlement/settlement_wiring_snapshot_test.gd——为什么不能复用:同种子逐项 golden 对拍需冻结改前全行流为常量基线,既有套件(round_flow_skill_pool 等)断言的是段内序与行为面、无整流 golden;battle_settlement 目录落点(夹具对象=战斗结算全链);grep 同名零命中。驱动夹具复用既有件:ConfigDBScript 显式构造+AutoPlayer.choose_dig(roll_multiplier_test.gd:14-16 同款装配先例,引用不复制)。
- tests/unit/core/encapsulation_sweep_test.gd——为什么不能复用:五处结构性零命中是本批特有扫描面(七文件集+五方法残留+四处私取模式),player_copy_sweep_test 扫的是 presentation 文案面——复用其源 token 扫描手法但不并件(并件会让两批扫描面与尾缀语义混乱)。唯一落点 tests/unit/core;grep 同名零命中。
新增函数/成员(逐条唯一性核查,grep 同名全库实核):
DamageController.hero_atk/hits_of/emit_hero_damage_taken——编排器_hero_atk/_hits_of改名迁移非并存(禁别名);_emit_hero_damage_taken去下划线公开化非新增体;facts成员为该件第 13 个类变量(预算内)。grepfunc hero_atk/func hits_of全库零第二处。RewardGrant.feat_yield_adjust——_feat_yield_adjust改名迁移;RewardGrant 持 reward_economy 引用(:22 既有)故体零改动可行。grep 唯一。MinesweeperRules.harmful_variants/harmful_adjacent——改名迁移;db 为构造参(:44 既有)。grep 唯一。BattleFxHost.mark_new_resource_type/add_bonus_delta——新方法旧账面(成员零增);grep 同名零命中,命名与既有 apply_ac_bonus/counter_add 动词族同型。SlotStore.active_path——grep 全库零同名;has_write_target 同族读投影。- SaveManagerCore 五公开面(承接 slot_store 反向私取)——
set_read_only/read_only/reset_to_default/data_snapshot/restore_datagrep 作方法名全库零第二处(现仅为成员名或私有方法);peek_summary_at/rename_overwrite为私有方法更名公开化非并存(禁别名,第 13 节适用);reset_to_default件内既有调用点同名零改。 BreakpointStore13 方法——greppending_next_level|loadout_seeded|resume_bp|last_level_payload|last_treasure_cleared|bp_read|bind_save_manager作为方法名全库零命中(现仅为成员名);成员到方法一一对应,无第二落点。- 三 schema
bind_resolver——grep 零同名;参数类型 ConfigDbResolver 与 config_db.gd:43 既有协作类同一实例。 RoundCycle.refresh_flow——grep 零同名;读出口与 stats()/wallet() 组件出口先例同型(adventure_runner.gd:60-82)。
复用既有(不新增):束注入形态=BoardInstaller/BattleFxHost/RewardGrant/BreakpointStore 四先例;读投影 Callable=attune_safe_seen_cb/pool_effective_cb/facts_cb 三先例;源扫描测试=player_copy_sweep_test 手法;manifest 登记=run_all.gd 既有条目族。零新增生产文件(全部落在既有件——架构七段结构零改动的直接后果)。
分层与交互面:段类→六子对象/协作件=既有 B1 域内调用关系(architecture.md:119 B2/B3/B4 全调用面唯一调用方=B1 域文件集——S7_B1_SET 已含七段,零新增跨域路径);段类→编排器=单向 Callable(禁双向强引用);三 schema bind_resolver=既有 config_db→schema 装配方向(:131-159 同向,禁反向);RngService 红线零触碰(本批零新增随机源);Core 零 UI 红线零触碰(全套件 --headless 可跑);数值单一事实源零触碰(零表改动)。
13. 禁为机检文本保留无效成员
本卡为重构类卡,全卡适用以下条款(code-conventions §1.1 ⑤同款):禁止为迎合机检消息文本(含计数、sweep 正则、grep 面)而保留或新增无效成员/别名/转发壳;搬家五方法宿主原方法删除后禁留同名或别名转发壳;_migrate_legacy_save 更名后禁留旧名壳;_bp_read 更名后禁留旧名壳;_emit_hero_damage_taken 公开化后禁留私有旧名;BreakpointStore 新方法面禁在成员外另立镜像账本。机检键与卡片契约互斥时(如 S13 贴顶件、sweep 正则与签名冲突),实现段一律停卡呈报,不得自造第三条路。
14. 实现规范预算
新增 .gd 文件仅 2 个测试件(SceneTree 测试脚本,全类型标注、零公开生产面——接口块预算余量充足)。生产代码全部落既有件,按「存量触面一查」逐件对账(S13 默认阈值:公开方法 ≤20/类变量 ≤15/分支 ≤8/返回 ≤6):
- 贴顶四件(禁再增成员,T1 读数锁定):battle_orchestrator.gd 15(本批成员零净增——五方法删除不涉成员);round_cycle.gd 8→15(束解包 7+_refresh_flow 1+既有 7——贴顶,头注记「贴顶禁再增」);battle_fx_host.gd 15(零增,方法-only);breakpoint_store.gd 15(零增,方法-only)。
- 类变量净增件:grant_segment 3→12、combat_segment 3→10、verdict 1→5、aura 1→1、decay 1→2(两件现各持 oc 一员——aura 换单回调成员 1→1、decay 换两成员 1→2)、battle_refresh_flow 0→8、damage_controller 12→13——全部 ≤15。
- 公开方法净增件:minesweeper_rules 18→20 贴顶(+2)、damage_controller 9→12(+hero_atk/hits_of+emit_hero_damage_taken 公开化——2026-11-03 终审实核现值 9)、reward_grant 9→10、battle_fx_host 16→18、slot_store 10→11、breakpoint_store 5→18、save_manager 7→14(+5 承接方法+peek_summary_at/rename_overwrite 两更名公开化)、RoundCycle 3→4、三 schema 各 +1——全部 ≤20。
- 迁移函数对账:搬家五方法+
_migrate_legacy_save+_bp_read+_emit_hero_damage_taken+_peek_summary_at+_rename_overwrite逐个查tools/gdstyle_baseline.txt源键——基线无此 10 键(默认阈值内),迁移即原体;若 T1 读数发现任一源函数 branches/returns 超默认登记值,迁移即拆函数(拆分不改语义,不算迎合机检——与第 13 节区分)。 - 存量触面 S13 预期:本卡触件 15 件(第 3.2 节清单)S13 键较 T1 现场基线只降不升(净删为主:五方法约 45 行迁出、107 处 oc._ 改址不增行数;净增面=两累积方法+13 bp 方法面+束解包成员行);adventure_runner 既有登记键(类变量 23)照登对账零变化。降不达即检查是否夹带超预算成员,L3 ③兜底。
- 指标例外申报:无(零新件、零超默认阈值新增面;若实现中发现例外,走本卡异常分级 L3 ③停卡,禁就地豁免)。
15. 拆分边界纪律
见第 4 节红线(结构类卡必填条款,判据权威=code-conventions §1.1):本卡零新拆件——段类七件、RoundCycle、BattleRefreshFlow、DamageController、RewardGrant、MinesweeperRules、BattleFxHost、BreakpointStore、SlotStore 全部架构在册既有件,本批只做接线形态换代与五方法归位。逐件职责语句不变:五段段类=B1 每轮结算序列的分段逻辑件(architecture.md:127)、RoundCycle=轮结算周期推进结构单点(:125)、BattleRefreshFlow=换图刷新流程唯一承载(:123)、五方法归位=各领域宿主既有职责面内的原语归位(伤害基值派生读归伤害管线、奖励乘区调整归授予管线、地形伤害型变异过滤归棋盘状态域、效果命中过滤归伤害域)。单一变化原因=封装边界(跨对象私取清零),非阈值驱动。禁凑计数袋:段类成员束解包以消费面为准(第 4 节分配表逐段列明),无「剩下的成员」式打包。先例=迭代 41 两卡 v1.2(核心数据面契约 7/呈现层契约 9)。