收尾(迭代49批后收尾·用户令): ①反哺点九条落文——architecture v1.31(轴戊两件换代已建件现状[EffectPort六Callable路由/掷格件roll批束四键/选行算子返表行]+功能层action/reward/fx_host/damage四行端口接线与类变量实数10/11/15/12+ui_registry行三域句柄分域换代[run/menu两子容器新建/ModalFlow升格注册面直驻/register_layer迁驻]+寻址ui.flow两处换代+UiCampModals行平铺面清零)+术语表v1.26立「效果端口件」「掷格件」两条〔用户裁〕+camp.md v2.6叠层与开合补窗壳形态已实装注记+08-Alpha v1.25三·界面营地行补窗壳形态在役注记+体验验证清单㊽登记目检两项(五窗观感/窗内滚动手感)+static_scan.sh S8头注计数句订正10→14(入批前存量漂移); ②能力审计闸件补探针通道〔用户令〕: 代表用例「代码在」渠道扩game/probe/探针件(文件在库+func在件内即认), 对齐test-conventions §8.9双通道原文——迭代49三卡退役暴露潜伏缺陷(探针行向来只靠卡片正文字符串作保,13条代表用例红/9行), 修后13行全经代码在锚定且核对比卡在更严; ③产出物退役六件(吸收即死+证据只留最新): 三需求卡片+iter49反哺点+实现报告+验收审计(审计通过缺漏0例外1在案,合并提交549683a5可考; shot_career读数盯守经CI渲染闸绿0782d46c了结); ④账面: 待办清单三卡条目整条删除(状态机出口)+roadmap迭代49行已完成(2026-11-02)两列退役保留字+当前位换代(迭代1-49全完成,下一步=迭代50编排待发令,候选=断言补齐批卡)+README两能力行「计划用例」锚随卡退役摘除(用例已落地,断言尾缀标记保留); C4生涯.md核查零义务仅记录; 修复区审计红0; --docs全绿后合并回master

This commit is contained in:
DKChan committed 2026-11-02 08:58:00 +08:00
1 parent 0782d46ca6
commit ecdd77e15f
16 files changed
+44 -1172

No files matched your search

+11 -11
View File
@@ -2,8 +2,8 @@
## 文档状态
- 版本:1.30
- 最近更新:2026-11-02(迭代 48 批后收尾随动——ConfigDB 行版本常量失真句订正;沿革查 git)
- 版本:1.31
- 最近更新:2026-11-02(迭代 49 批后收尾随动——轴戊两件与功能层四行换代已建件现状、ui_registry 行三域句柄分域换代;沿革查 git)
- 引擎:Godot 4.7.2-stable(GDScript 单语言;2026-09-07 锁定)
- 评审模式:solo(`review-mode.txt`,2026-09-12 用户拍板——TD/LP 门禁按 solo 跳过,用户授权架构产出自主推进、迭代期回调)
- 覆盖 GDD:现行全集(根索引=`design/gdd/02-系统清单.md`,文档树构成以根索引为准)
@@ -89,7 +89,7 @@
| **SlotStore**(`core/slot_store.gd`,D3 存档槽位域件,已建件——迭代 41 存量债批) | 存档三槽位文件域唯一所有者(自 save_manager 收编槽位族):槽位挂载与模板、激活与建删、槽位摘要窥视(peek 族);改名覆盖原语(_rename_overwrite)留 save_manager(IO 原语单点) | 槽位读写原语族+摘要投影(公开 10/类变量 4;SaveManager 与菜单消费方经 `save.slots.` 直连) | save_manager(注入路径与模板配置);FileAccess——LOW |
| **MetaStateStore**(`core/meta_state_store.gd`,D3 存档内元进度数据件,已建件——迭代 41 存量债批) | 存档内元进度数据的读写唯一层(自 save_manager 收编 accessor 族:钥石/道具解锁/树节点与叉侧/锻造路线/同调/真视/计数器/摘要——数据读写原语,不含业务规则);save_manager 与 meta_progression 双 God Class 的共同病根=该数据域摊在两文件,本件即其归一 | 写口原语 13+只读投影 6(tree_state/forge_state/attune_state/career_state 四投影+keystone_balance/item_unlocked)=公开 19(add_keystone 私有 `_add_keystone`),零 _data 副本零缓存;MetaProgression 业务层与营地/锻造 UI 消费方经 `save.meta_state.` 直连(meta 的纯转发读方法已退役) | save_manager(序列化接线);FileAccess——LOW |
| **RngService**(autoload,D2) | master_seed、各流 scope 计数器(封闭流词表现值以 `RngServiceCore.PURPOSE_TAGS` 为准;增流走 P1 评审) | `set_master_seed()`(唯一调用方 C2);`open_stream(stream)` 有状态门面;`derive_at(stream, scope)` 纯函数;只读计数器 | ConfigDB(无) | 无——纯逻辑 |
| **action_economy**(A3) | AP/RAP 账本、last_round_end、轮次相位机 {Idle, Active, Waiting}、结束仲裁;dig_paid 命中施加抽私有单点(_apply_dig_paid_hits——矿脉储能入池面) | 意图与通知布尔面:notify_round_start / request_dig / request_stop / request_refresh(收折后价入参——折价计算归 BattleRefreshFlow 单点)/ notify_settlement_done / notify_combat_end;预授权通道:grant_reserve_ap / finish_round_stop;ap/rap/phase 只读 | ConfigDB(ActionEconomyTable);effect_engine(事件发射 dispatch——基础层内同层引用;2026-11-02 轴戊设计闭合:业务类发射改经效果端口件,实现批建件);B1 回发 next_round_mode/battle_over | 无 |
| **action_economy**(A3) | AP/RAP 账本、last_round_end、轮次相位机 {Idle, Active, Waiting}、结束仲裁;dig_paid 命中施加抽私有单点(_apply_dig_paid_hits——矿脉储能入池面) | 意图与通知布尔面:notify_round_start / request_dig / request_stop / request_refresh(收折后价入参——折价计算归 BattleRefreshFlow 单点)/ notify_settlement_done / notify_combat_end;预授权通道:grant_reserve_ap / finish_round_stop;ap/rap/phase 只读;实测类变量 10 | ConfigDB(ActionEconomyTable);EffectPort(效果端口件——发射经端口单点;2026-11-02 轴戊设计闭合、迭代 49 卡① 建件,effect_engine 直连退役);B1 回发 next_round_mode/battle_over | 无 |
| **variation 定义**(A4) | VariationTable schema(现行 6 行:六 region——贫矿脉 global 行 2026-10-16 用户令屏蔽删行,global 型机制代码保留)与 F1 候选池门控谓词 | `variant_pool(level_index, board_type, node_type="")`(门控三维:unlock+board_types+节点身份——global 行仅 boss/elite 入池,缺省跳过零扰动);`global_variant_row(level_index, board_type, node_type)`(全局型单行决议访问器) | ConfigDB(VariationTable) | 无 |
| **status_container**(B3) | 状态实例容器(战斗域生命周期、跨轮跨图延续) | 5 API:notify_battle_start / apply_effect / query_active / decay_round / notify_battle_end | ConfigDB(StatusEffectTable) | 无(RefCounted) |
| **effect_engine**(内容数据驱动扩展批 iter17 建域) | 零运行时可变状态的系统(见「架构原则」条 8):全同步解释器——事件由宿主在明确代码点位显式调 dispatch 进件,命中序=装载声明序(feats→treasure→树规则)写死保种子复放,不是事件总线/事件循环;事件/事实/效果类型/算子四词表封闭 + 树规则合成订阅六键(posture 每关首轮窗/sense 两组限次 counter 闸·adv_ 前缀走冒险桶跨战斗持久) | rebuild(每战重建订阅表)/`dispatch(ctx, event, payload, facts)`/`validate_trigger_row` + 静态计数口 `counter`·`counter_add`·`counter_spend`·`bucket_of`·`counter_id_legal`(计数器读写只经 EffectContext 引用束,无导出/灌入接口) | ConfigDB(feats/treasure 行集)、EffectContext(四桶引用由宿主持有:round/battle 桶归编排器、level 桶归关卡域、adventure 桶归应用层——RunLedger 已随迭代 39 拆件批退役,桶字典由 adventure_runner 持有) | 无(零随机全确定) |
@@ -103,7 +103,7 @@
| **board_generator**(A1) | 生成算法(五阶段管线)、BoardGenTable 回填、生成期指标集、合法性谓词(clearable / R₀≠S / min_safe)、可推理率度量(metric_version);生成姿态 = MVP 同步生成 + 加载幕(切片实证 10×10/12×12 同步可接受,WorkerThread 留扩展) | `generate(L, D, rng) -> Board`;度量独立入口×3(推理器 / F3 度量 / 合法性谓词——独立纯函数、同一实现) | ConfigDB(BoardGenTable/VariationTable);board_gen 流(一次 open_stream = 一张图);dig_ap_cost 只读 | 无 |
| **minesweeper_rules**(A2) | 棋盘状态(已开集 O / 封印集 G / 小人位)、三事件面、批次仲裁、install 四不变式 | `install_board(board)`;`settle_batch(intents)`(唯一提交入口);查询只读面(current_board / hero_pos / is_revealed / has_seal 等);`compute_move_path(cell)` 只读;`retire_board()`;三源拒绝(board_face / resource_face / phase)+ sub_reason 封闭枚举 | A1 产物(Board class_name 数据契约);A3 try_spend / last_round_end(迭代 41 由属性改方法)/ 相位 | 无(零表读取、零 UI——切片实证) |
| **unit_container**(B2) | hero/enemy 单位实例(hp/atk/实例池:池快照+冷却+摇定动作+保底计数)、行值快照 | spawn / query_alive / rollable_skills / special_skills / check_trigger_unlocks / set_pending_action / pending_action / basic_streak / commit_action / tick_cooldowns / apply_damage / heal / default_target / check_skill_unlocks / despawn_all(2026-09-16 敌人技能池批:query_beat/query_attack/advance 随行为环退役;rollable_skills/special_skills/check_trigger_unlocks 带 facts 参——2026-10-27 情境条件触发器实装,事实缺键=条件假拦下,百分比事实走阈值式折算) | ConfigDB(EnemyTable/SkillTable/HeroTable) | 无 |
| **reward_economy**(B4) | 格面资源身份映射(install 期预分配、Ready 只读、换图映射消亡)、极性路由字典面((类型, 极性)→ 字典行查询;路由执行归 B1 授予段)、F6 当量供给投影;2026-11-02 轴戊设计闭合:装配期摇号面拆出掷格件(受理账面留守),实现批建件 | 封闭 API:roll_board / query_identity / query_full_snapshot / grant / grant_clear / retire_mapping / polarity_row / phase / weighted_pick;另有 is_mapped 静默布尔投影(批量工具用) | ConfigDB(RewardTable);BattleFxHost 经注入 Callable `luck_bias_query` 取偏运合计(reward_roll 发射与 bias_rewards 求和移至效果层完成);reward_roll 流(scope = 每次 install 批) | 无 |
| **reward_economy**(B4) | 格面资源身份映射(install 期预分配、Ready 只读、换图映射消亡)、极性路由字典面((类型, 极性)→ 字典行查询;路由执行归 B1 授予段)、F6 当量供给投影;装配期摇号面已拆出掷格件 RewardRoller(2026-11-02 轴戊设计闭合、迭代 49 卡① 建件——roll_board 装配序=守卫→复位→委托→收纳→ready;受理账面留守) | 封闭 API:roll_board / query_identity / query_full_snapshot / grant / grant_clear / retire_mapping / polarity_row / phase(weighted_pick 退役——返行选行算子迁掷格件);另有 is_mapped 静默布尔投影(批量工具用);实测类变量 11 | ConfigDB(RewardTable);BattleFxHost 经注入 Callable `luck_bias_query` 取偏运合计(reward_roll 发射与 bias_rewards 求和移至效果层完成);reward_roll 流(scope = 每次 install 批,取号经掷格件) | 无 |
| **helper_items**(A5,切片已实装秘宝域) | HelperItemTable、探测显影语义 | (契约规范源:`../../gdd/systems/跨局循环/秘宝.md`——桥接位:A2 查询接口 + A4 counter_item_ids) | A2 / A4 / B4 | 无 |
| **CurioDeck**(`core/curio_deck.gd`,A5 秘宝域令牌池件,迭代 37 自 AdventureRunner 拆出) | 三选一/商店共享池的持久多重集、抽签(候选抽取)、cap 库存与专长凭证三计数与判定唯一所有者——件只管池与判定,停点编排与兑付推进留冒险编排器 | `draw_candidates(channel)` 抽签;`consume_deck_token` / `consume_pool_purchase` 池消耗;`cap_ok` 上限判定;`feat_ticket_consider` 凭证判定;`stock_snapshot` / `pool_stock` 只读投影;商店购买消费经注入 Callable 链至 CurioStop 兑付单点(迭代 39 起转纯池——bind_handlers 反向回调已退役) | ConfigDB(秘宝令牌行集);注入 RngServiceCore(reward_pick 封闭流,禁自建随机) | 无(RefCounted 纯逻辑) |
| **ShopSession**(`core/shop_session.gd`,商店会话件,迭代 37 自 LevelRunner 拆出) | 关卡商店双模式(legacy 固定三件加定价/pool 共享令牌池)的货架、定价、购买与刷新唯一宿主——账本/钱包/装配集归宿主 LevelRunner(共享引用经 `bind` 注入,出账直接落同一引用改写宿主账本);legacy 模式零 RNG 零池消费(off 对照承载) | 货架与定价只读面(`shop_products` / `shop_shelf` / `current_price` / `shop_refresh_cost`)+写入口(`buy_product` / `buy_pool_item` / `shop_refresh` / `player_request_refresh` / `open_pool`);外部调用面=调用方经宿主 LevelRunner 公开成员 `shop` 直连(调用直连不留委托壳,2026-10-26 Middle Man 裁定;迭代 42 拆除),直连消费的方法=`shop_products`/`current_price`/`purchased_tier`/`buy_product`/`player_request_refresh`/`set_shop_pool`/`pool_price`/`shop_shelf`/`shop_refresh_free_left`/`shop_refresh_cost`/`shop_refresh`/`spend_gp`/`buy_pool_item`/`is_shop_pool`/`shop_bp_shelf`/`shop_bp_visit_buys`(另白盒两入口仅测试侧:`_draw_shelf`/`_spend_discounted`);set_shop_pool 调用面=pool 注入经 LevelRunner 构造 ctx 供给(构造期内部直调,原委托块注释「AdventureRunner._start_current_level 唯一调用方」系陈旧表述、随壳删除作废),测试面直连 `shop.set_shop_pool` | ConfigDB(商店行集);注入 RngServiceCore;宿主钱包/账本引用;pool 模式令牌消耗与判定经注入 Callable 转 CurioDeck | 无 |
@@ -117,9 +117,9 @@
| 模块 | 独占职责 | 对外暴露 | 消费依赖 | 引擎 API |
|---|---|---|---|---|
| **battle_orchestrator**(B1) | 段序骨架(七段结构冻结)、轮 facts 缓冲、可回放步骤流、[明细行协议](../../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)(基础行型+扩展行两层 + 字段分层,词表以 owner「明细流水」节为准)、条款③⑤闭合对账、**战斗域全部跨系统调用权**、效果引擎宿主面与树规则挂点施加面(**已拆出 BattleFxHost 并实装(2026-10-28 迭代 40——battle_fx_host.gd/reward_grant.gd 两件在库,效果引擎宿主面归 BattleFxHost 行承载,拆件细则见「战斗编排域拆件定稿」节);2026-10-29 零豁免裁设计闭合:RoundCycle/BattleFacts 两新件随批(宿主 38→15、S13 豁免第三条注销——见下两行与定稿节轴丁)**) | `begin_battle(encounter)`;窗口/刷新意图提交面(扮演 D1);`level_clear()`;步骤流(输出契约) | B2/B3/B4 全调用面(**唯一调用方=B1 域文件集:battle_orchestrator.gd + settlement/ 五段段类 + damage_controller + 拆件后三新件**);A3 request_refresh 代理 + 回发;A2 install/retire + 三事件订阅;A1 generate(attempt 非 scope 事件);D2 SettlementTable + set_reload_gate | 无(零随机、禁 await——切片 88 冒烟实证可回放) |
| **BattleFxHost**(`core/battle_fx_host.gd`,B1 域·效果引擎宿主件,2026-10-26 编排域拆件设计定稿——实现批建件) | 效果引擎挂点施加面唯一承载(自 battle_orchestrator 收编 fx 族):事件发射与事实判定(_fx_emit/_fx_fact)、主角 AC 基线与本轮/本战 AC 累积、bonus_delta 四轴累积(战末宿主 drain 汇入账本)、揭示待兑队列与兑付(含 _fx_revealing 再入闸——同步信号回环防二次缓冲二次兑付)、树规则合成订阅的 round/battle 桶计数器持有(桶随编排器生灭语义不变);2026-11-02 轴戊设计闭合:新增效果端口件为业务类朝向机房的窄门面,计数器账面收归宿主侧(实现批建件) | 构造=引用束注入(防 _init max-parameters 新键);bind 时注入 emit Callable(行发射经宿主协议面单点)与兑付 Callable(RewardGrant 授予面——揭示队列 flush 回调);只读投影分两类消费方:AC 累积/bonus_delta 供宿主呈现快照与战末 drain,揭示态供宿主 A2 订阅旁路判定;`luck_bias_for(cell_count) -> int` 偏运合计查询口(体内三参形 dispatch——reward_roll 发射与 bias_rewards 求和自 RewardEconomy 收回本件,RewardEconomy 经注入 Callable 消费) | EffectEngine(EffectContext 引用束);RngServiceCore(fx_reveal 封闭流——除该流外零随机);A2 minesweeper(板读与 fx_reveal 调用);A3 action_economy(queue_ap_delta/charge_layers 读);B3 status_container 读;B2 unit_container 读(hp_ratio);DamageController(set_hero_ac_override);ConfigDB;encounter 引用 | 无(零 await——效果引擎全同步解释器) |
| **BattleFxHost**(`core/battle_fx_host.gd`,B1 域·效果引擎宿主件,2026-10-26 编排域拆件设计定稿——已建件(迭代 40 实装)) | 效果引擎挂点施加面唯一承载(自 battle_orchestrator 收编 fx 族):事件发射与事实判定(_fx_emit/_fx_fact)、主角 AC 基线与本轮/本战 AC 累积、bonus_delta 四轴累积(战末宿主 drain 汇入账本)、揭示待兑队列与兑付(含 _fx_revealing 再入闸——同步信号回环防二次缓冲二次兑付)、树规则合成订阅的 round/battle 桶计数器持有(桶随编排器生灭语义不变);2026-11-02 轴戊设计闭合落地(迭代 49 卡①):效果端口件为业务类朝向机房的窄门面——端口在本件组建、bind_port 组装期转注两业务类,计数器账面收归本件;实测类变量 15 | 构造=引用束注入(防 _init max-parameters 新键);bind 时注入 emit Callable(行发射经宿主协议面单点)与兑付 Callable(RewardGrant 授予面——揭示队列 flush 回调);只读投影分两类消费方:AC 累积/bonus_delta 供宿主呈现快照与战末 drain,揭示态供宿主 A2 订阅旁路判定;`luck_bias_for(cell_count) -> int` 偏运合计查询口(体内三参形 dispatch——reward_roll 发射与 bias_rewards 求和自 RewardEconomy 收回本件,RewardEconomy 经注入 Callable 消费) | EffectEngine(EffectContext 引用束);RngServiceCore(fx_reveal 封闭流——除该流外零随机);A2 minesweeper(板读与 fx_reveal 调用);A3 action_economy(queue_ap_delta/charge_layers 读);B3 status_container 读;B2 unit_container 读(hp_ratio);DamageController(set_hero_ac_override);ConfigDB;encounter 引用 | 无(零 await——效果引擎全同步解释器) |
| **RewardGrant**(`core/reward_grant.gd`,B1 域·奖励授予件,2026-10-26 编排域拆件设计定稿——实现批建件) | 奖励授予唯一兑付管线(自 battle_orchestrator 收编 grant 族):极性字典路由与封印溢价兑付(_grant_routed)、三种行应用(flat/percent/gp)、伤害单据提交面(_submit 族)、清图奖励与身份授予、秘宝使用编排(use_treasure 四步)、战斗域 GP 缓冲 escrow 与授予段暂存伤害闸(_defer_board_damage/_deferred_board) | use_treasure 编排入口(treasure_interact_controller 经组合根现值回调直连);授予入口(结算段类直调);只读投影(escrow 读与 GP 掉落合计——宿主呈现快照与 _roll_gp_drop 消费) | B4 RewardEconomy(polarity_row/grant);B1 域 DamageController(开单);BattleFxHost 引用(treasure_used 事件发射与计数器消耗);A2 minesweeper(校验回调/fx_reveal/remove_mines_in);A3 action_economy(相位闸/grant_ap/queue_ap_delta);B3 status_container(apply_effect/池读);B2 unit_container(hero_unit/heal);ConfigDB;注入 emit Callable、宿主 fatal Callable(battle_result 状态机唯一写点留宿主)、宿主 attune 读投影(_attune_safe_seen)、encounter 账本引用;TreasureItems 经宿主 setter 转发注入(库存注入时序在宿主构造之后) | 无(零随机零 await——授予期零随机口径,roll 值授予前已定) |
| **damage_controller**(B1 域·伤害单据管线) | 伤害单据唯一兑现管线(单据九栏目声明→分量掷点/克制修正/伤害下限归一→明细行发射;双方同规);`damage_taken` 唯一发射口(_emit_hero_damage_taken)+唯一消费族(_apply_hero_damage_effects)——敌方攻击/地形/危险格/错误封印直伤四路径统一发射,board_flat_hero 结账前统一发射 | 兑付入口(编排侧开单)+ fx 揭示回调注入位 | B2 单位实例(单据目标传入);B1 注入(EffectContext 引用束与编排回调;轴戊设计闭合:改经效果端口件) | 无 |
| **damage_controller**(B1 域·伤害单据管线) | 伤害单据唯一兑现管线(单据九栏目声明→分量掷点/克制修正/伤害下限归一→明细行发射;双方同规);`damage_taken` 唯一发射口(_emit_hero_damage_taken)+唯一消费族(_apply_hero_damage_effects)——敌方攻击/地形/危险格/错误封印直伤四路径统一发射,board_flat_hero 结账前统一发射 | 兑付入口(编排侧开单)+ fx 揭示回调注入位;实测类变量 12 | B2 单位实例(单据目标传入);B1 注入(EffectPort 端口引用——轴戊设计闭合改经端口发射,迭代 49 卡① 建件;EffectContext 引用束与编排回调收归宿主侧 BattleFxHost 域,业务类零引擎直连) | 无 |
| **BattleRefreshFlow**(`core/battle_refresh_flow.gd`,B1 域·换图刷新流程件,已建件——迭代 46) | 弃图刷新流程唯一承载(自编排器收编):刷新可用性门(相位/每轮上限/储备门槛)、折后价单点(_effective_refresh_cost——专长行声明序第一命中、floor 取整、can 与执行同源)、换图执行序(扣储备→used+1→旧资源退役→旧板退役→装新板→board_refreshed 成功事实登记) | can_refresh/execute 两公开入口;调用路径呈现层→编排器两公开方法单行转发→本件;A3 request_refresh 收折后价入参 | 编排器(宿主,B1 域内唯一调用方约束同族适用);A3 action_economy(折价扣费与拒绝判据);A2 装板壳(装板与退役);RewardGrant(apply_board_refreshed 成功事实消费);feats 折价行经 ConfigDB;static_scan S7_B1_SET 已增补本件(判据口径不变) | 无(零随机零 await) |
| **BoardInstaller**(`core/board_installer.gd`,B1 域·装板域件,2026-10-29 尾波清偿批设计闭合——实现批建件,细则见「战斗编排域拆件定稿」节轴丙) | 棋盘安装与变异布置域唯一承载(自 battle_orchestrator 收编装板族六函数):生成受理、全局作用域变异决议、资源摇号资格域组装(roll_board 恰一次)、region 变异决议与连通片布置;BoardGenerator 实例随件自建自接线(宿主成员退役)——宿主侧装板后状态复位(封印/完美计数清零、板序推进、board_changed 发射、秘宝叠加层退役)留宿主薄壳,时序逐字保持 | `install(during_round) -> bool` 单入口;构造=引用束注入(rng/db/minesweeper/reward_economy/encounter 只读引用+宿主 fatal Callable——防 _init max-parameters 新键) | A1 board_generator(件内持有);A2 install_board;B4 roll_board/board_skew 写;A4 变异决议行集经 ConfigDB;board_gen/variant_place 两封闭流随件、流名与开流时点零漂移 | 无(零 await——装板全同步) |
| **RoundCycle**(`core/round_cycle.gd`,B1 域·轮循环驱动件,已建件——迭代 44) | 轮循环驱动域唯一承载(自宿主收编 7 成员):结算五段段件持有与驱动、重入门闸、开轮摇号、踩雷账 | 三参直构(host/fx_host_ref/reward_grant_ref——五段构造透传不落成员);段驱动入口由宿主接线调用;实测类变量 8/公开方法 3 | B1 宿主;settlement/ 五段段类;A3 相位读 | 无 |
@@ -139,7 +139,7 @@
- **轴甲两件**:battle_orchestrator(1313 行/50 成员,S13 全库单文件最大户)按变化原因拆出 BattleFxHost(效果引擎宿主域)与 RewardGrant(奖励授予域)两协作件;宿主保留架构在册职责全部——战斗状态机与生命周期、轮 facts 缓冲(_facts_reveals/seals/path)、A2 三事件订阅、结算五段驱动、attune 族原位、行发射基建(_emit_row/_assert_row_source/_fatal)、呈现投影(presentation/diagnostic_snapshot 唯一出口不变)、刷新面、nest_preview_count(巢穴预告读数口——外部直读面 main.gd 与 treasure_effects_test 随批点名冻结)。拆件动机与残留债口径见待办清单「gdstyle 存量债全量清偿」条目。
- **轴丙一件(2026-10-29 尾波清偿批设计闭合——实现批建件)**:battle_orchestrator 装板域六函数(`_install_new_board`/`_resolve_global_variant`/`_place_variants`/`_place_variants_apply`/`_variants_fringe`/`_adjacent_to_packs`,约 140 行;全仓仅宿主三调用点——begin_battle/中途刷新受理/player_request_refresh,实查零外部调用)按变化原因拆出 BoardInstaller,职责语句「棋盘安装与变异布置域」(生成→全局变异决议→装板受理→资源摇号→变异布置;单一变化原因=棋盘设置顺序与变异布置算法)。形态两修正(实测裁,与初案「逐字搬运」之差):①宿主复位块不随件——`_install_new_board` 体内五处计数清零、板序推进、board_changed 发射与秘宝叠加层退役留宿主薄壳 `_install_and_reset`,三调用点改调薄壳、时序逐字;②`_board_generator` 全文件仅装板族使用——实例随件自建自接线(fatal 经注入 Callable),宿主成员退役(类变量 38→37,禁无效成员义务)。encounter(23 处跨宿主)与 _reward_economy(18 处)确认留宿主、经引用束注入。文件长键(1035/1000)随本件迁出归绿;attune 族与 begin_battle 受理段序禁动不变。
- **轴丁两件(2026-10-29 零豁免裁设计闭合——实现批建件)**:RoundCycle(轮循环驱动件)与 BattleFacts(战斗事实件)见功能层表两行——宿主 38(轴丙落地后 37)→15,S13 豁免第三条注销;宿主保留面改登记为「战斗状态机与生命周期、行发射基建(_emit_row/_assert_row_source/_fatal)、呈现投影(两快照出口签名不变)、刷新面、nest_preview_count」;attune 族处置由下一条改判;treasure_inventory 注入改址追认——原「外部赋值路径零改址」句失效,level_runner 经 RewardGrant 出口直注;成员级对账以需求卡片为卡内契约(开工 T0 复核)。
- **轴戊两件(2026-11-02 用户裁甲案设计闭合——实现批建件,登记条目=待办清单「战斗域结构深拆批」)**:①**效果端口件**(暂名 `EffectPort`,文件名随卡定)——职责语句「战斗业务类唯一的效果发射出口:收事件与载荷、交效果引擎结算、取回命中批」;`DamageController`/`ActionEconomy` 各持端口引用(同一实例、构造注入),`EffectEngine`/`EffectContext` 引用与计数器账面(value_counter 层值读后清零)收归宿主侧(BattleFxHost 域),业务类零引擎直连、零账面触碰;facts 取值束(dig_streak/charge_layers/rider_tier_*)与入站回调束(reveal/ac)随发射契约归宿主侧注入面;端口**单实现零接口抽象**(无基类无多态——GDScript 无 interface,本案不需要);端口持 BattleFxHost 引用或经注入 Callable 卡内定,跨件单向接线条款适用(禁双向强引用)。②**掷格件**(暂名 `RewardRoller`)——职责语句「装配期格面资源摇号:池行装配、区间行 roll、权重合成(偏运硬币/board_skew 两路投影)」;受理账面(grant/身份查询/快照/retire/polarity_row)留 `RewardEconomy`,衔接面=格→奖励身份映射(掷格件产出、受理件接收);掷格件经注入 RngServiceCore 取号(roll_board 流 scope=每次 install 批不变、取号序零漂移)。行为零变化红线沿本节「验收红线」全款:命中序=声明序、明细行协议词表零触碰、`_ineffective_row` 载荷 deferred 自描述键观测面不回退(2026-11-02 迭代 48 卡① 甲案在案)、EV/MC 锚同种子逐位零漂移;两新件 S13 预算随卡「实现规范预算」三查,`RewardEconomy` 类变量随掷格面迁出只降不升;S7 B1 域文件集随批增行。
- **轴戊两件(2026-11-02 用户裁甲案设计闭合——已建件,迭代 49 卡① 合回,git 提交 848723b5)**:①**效果端口件 EffectPort**(`core/effect_port.gd`)——职责语句「战斗业务类唯一的效果发射出口:收事件与载荷、交效果引擎结算、取回命中批」;实测形态=六 Callable 路由、bind_port 组装期转注、闭面五键 biz_fact、未绑零扰动缺省;`DamageController`/`ActionEconomy` 各持端口引用(同一实例、构造注入),`EffectEngine`/`EffectContext` 引用与计数器账面(value_counter 层值读后清零)收归宿主侧(BattleFxHost 域),业务类零引擎直连、零账面触碰;facts 取值束(dig_streak/charge_layers/rider_tier_*)与入站回调束(reveal/ac)随发射契约归宿主侧注入面;端口**单实现零接口抽象**(无基类无多态——GDScript 无 interface,本案不需要);端口与宿主经注入 Callable 束协作、零宿主对象引用(跨件单向接线条款适用,禁双向强引用)。②**掷格件 RewardRoller**(`core/reward_roller.gd`)——职责语句「装配期格面资源摇号:池行装配、区间行 roll、权重合成(偏运硬币/board_skew 两路投影)」;实测形态=roll 批束四键(mapping/power_roll/clear_identity/clear_power)、选行算子 `_weighted_pick_row` 返表行、fatal 经构造 Callable 链;受理账面(grant/身份查询/快照/retire/polarity_row)留 `RewardEconomy`,衔接面=格→奖励身份映射(掷格件产出、受理件接收);掷格件经注入 RngServiceCore 取号(roll_board 流 scope=每次 install 批不变、取号序零漂移)。行为零变化红线沿本节「验收红线」全款:命中序=声明序、明细行协议词表零触碰、`_ineffective_row` 载荷 deferred 自描述键观测面不回退(2026-11-02 迭代 48 卡① 甲案在案)、EV/MC 锚同种子逐位零漂移——round_flow 逐位回放 134 检查为主证(红线成立);两新件 S13 预算随卡「实现规范预算」三查已过(新件全默认阈值内、gdstyle 基线外新违规 0),`RewardEconomy` 类变量随掷格面迁出 15→11;S7 B1 域文件集与 S8 await 文件集已随批增行。
- **跨件单向接线**:RewardGrant 持 BattleFxHost 引用(treasure_used 事件发射与计数器消耗);BattleFxHost 对授予面走 bind 时注入的兑付 Callable(揭示队列 flush 回调)——禁双向强引用(两件均 RefCounted,环引用随每战新建泄漏)。行发射经 bind 时注入的 emit Callable(协议面单点留宿主——CurioDeck bind_handlers 同款先例,禁件回调宿主私有族);轮 facts 缓冲留宿主、fx 件经注入取值;_seal_consumed 留宿主(与 A2 seal_judged 订阅同域);fatal 经注入 Callable 转宿主 _fatal(battle_result 状态机唯一写点不变)。注入 Callable 亦属接线面、同单向纪律——禁为省参数改持对象引用。授予件对账本零强引用:战斗期消费经 `battle_hooks` 三键回调束(attune_consume/vision_add/negative_blast,bind_battle 缺键 assert),宿主侧三单点记账(2026-10-28 迭代 40 合并适配实装——RunLedger 类已随迭代 39 退役,直持对象引用无处可指)。
- **战斗域读面(RunLedger 退役后)**:账本读经编排器 `_journal()`/`_attune_loadout()` 现值派生(GainJournal/AttuneLoadout,enc 派生、无成员接收);冒险桶经 `enc["adv_bucket"]` 下传 `battle_fx_host.mount_buckets`;战末 bonus 四轴经 `GainJournal.gain_bonus` 汇入(2026-10-27 迭代 39 主角账三件落地、迭代 40 合并适配承接)。
- **settlement/ 段类随动**:段类构造注入直持宿主+两新件三引用(Middle Man 禁令封转发壳——调用点改指),授予段读写面点名:_grant_routed×5/_submit×6/escrow 写/_fx_new_resource_types/_feat_first_dig_used/_fx_bonus_delta 写/_apply_ac_bonus/_fx_enqueue_reveal/_flush_pending_reveals/_grant_clear_reward/counters_ctx;战斗段 _defer_board_damage 复位与 _deferred_board 结账改指 RewardGrant。四个授予段 helper(_feat_yield_adjust/_harmful_variants/_harmful_adjacent/_hits_of)与 _pool_effective/perfect_sweep_earned 留宿主(段类经宿主引用直调,现状形态)。
@@ -166,8 +166,8 @@
|---|---|---|---|---|
| **D1 HUD**(呈现面拆分持续换代:组合根 main.gd + 三屏壳(MenuScreen/CampScreen/AdventureScreen)+ views/ 视图单元(现行承载面见「呈现层装配与会话生命周期」节;早期 9 单元清单与 LevelStripView 已随场景换代退役);营地面=场景根+四子界面功能窗口+Esc 浮窗+顶栏 HUD 栏〔迭代 21 四柜台覆盖层已随迭代 47 卡④⑤ 退役〕) | 全部 Control/CanvasLayer(例外:BoardView 棋盘本体与 BattleStageView 站桩本体 = Control 壳 + SubViewportContainer + SubViewport + Node2D 世界〔BoardWorld/CellUnit;StageWorld/StandeeBody——B 区 slot_row 伴随件留壳层〕,探针契约面不变——棋盘 Node2D 迁移批 Phase A 2026-09-23 / 战斗舞台 Phase B 2026-09-26)、输入→意图翻译(**唯一提交路径 = settle_batch,不直调 A3**)、呈现义务状态记录(A2×6 / B2×4 / B3×4 / B4×5 / B1×3) | 视图单元接口(信号外发、setter 只读注入) | A2 compute_move_path / ActionOutcome;A3 ap/rap;B1 步骤流行协议(数据源);ConfigDB display_name | **MEDIUM**:Control / CanvasLayer / draw_* / InputEvent / RichTextLabel——对照 breaking-changes.md 4.5–4.7 条目(CanvasItem 线条无抗锯齿羽化、设备 ID 常量、RichTextLabel 图片参数两轮变化) |
| **组合根拆件**(呈现侧写口子件:curio_interact_controller / camp_shop_presenter / treasure_interact_controller) | 代组合根执行核心写调用(冒险节点后续推进/营地购买与刷新/道具使用——依赖与回调由 main 构造注入) | 各拆件的写入口(仅组合根装配面可达;视图零直连) | 构造注入的核心写引用(推进/商店/道具各域——详见各拆件头注) | 无 |
| **ui_registry**(`presentation/ui_registry.gd`,界面注册面,已建件——迭代 44) | 呈现层接口面唯一承载:层序合同(LAYER_CONTRACT)迁驻与合同寻址、三域句柄容器 ui_screens(9 屏壳与覆盖层句柄)/ui_battle(5 战区句柄)/ui_modals(平铺模态句柄+营地域 UiCampModals 子容器〔六句柄、两段式寻址 `modals.camp.*`——迭代 47 卡⑥〕+ModalFlow;层序合同营地槽换代=camp_overlay 退役、换 camp_scene+四子界面+camp_esc_overlay——迭代 47 卡④⑤);组合根经其一级寻址接线,探针挂载假设迁移为 `main.ui.<域容器>.<句柄>`;七个探针别名/转发成员随批消灭 | 三容器属性+合同寻址口(RefCounted 门面,不挂树、零会话期引用);四件(UiRegistry/UiScreens/UiBattle/UiModals)类变量 3/9/5/14,ModalFlow 随 UiModals 容器构造即建;UiCampModals 营地域子容器随卡⑥(ui_modals 类变量 14→14——删六平铺增一子容器引用) | 构造注入:三屏壳、覆盖层、战区句柄、ModalFlow(main_ui_build 交付随之改型) | 无(RefCounted) |
| **UiCampModals**(`presentation/ui_camp_modals.gd`,营地域句柄子容器,已建件——迭代 47 卡⑥) | ui_modals 营地域六句柄唯一容器(场景根/四子界面/Esc 浮窗/HUD 栏),句柄寻址两段式 `modals.camp.*`;ui_modals 平铺面收窄 | 子容器属性+六句柄只读投影;main_ui_build 装配交付 | 构造注入(六视图句柄);ui_modals(父容器挂载) | 无(RefCounted) |
| **ui_registry**(`presentation/ui_registry.gd`,界面注册面,已建件——迭代 44) | 呈现层接口面唯一承载:层序合同(LAYER_CONTRACT)迁驻与合同寻址、三域句柄容器 ui_screens(9 屏壳与覆盖层句柄)/ui_battle(5 战区句柄)/ui_modals(模态句柄按域分三子容器——局内冒险域 run/菜单与跨语境域 menu〔两子容器迭代 49 卡② 新建〕/营地域 camp=既有 UiCampModals〔六句柄、两段式寻址 `modals.camp.*`——迭代 47 卡⑥〕,三子容器纯字段、两段式寻址 `modals.run.*`/`modals.menu.*`/`modals.camp.*`)+模态编排件 ModalFlow 直驻本面(自 UiModals 升格 UiRegistry 直持——迭代 49 卡②);层序合同营地槽换代=camp_overlay 退役、换 camp_scene+四子界面+camp_esc_overlay——迭代 47 卡④⑤;组合根经其一级寻址接线,探针挂载假设迁移为 `main.ui.<域容器>.<句柄>`;七个探针别名/转发成员随批消灭 | 三容器属性+flow+合同寻址口(RefCounted 门面,不挂树、零会话期引用);register_layer 迁驻注册面;四件类变量 UiRegistry 4/UiScreens 9/UiBattle 5/UiModals 3(run/menu/camp 三子容器纯字段——ui_modals 平铺面清零,12 平铺句柄全数迁 run/menu 两子容器,分域纪律册级化);ModalFlow 随 UiRegistry 构造建立(构造时点与原形态等价——注册面构造点先于装配,迭代 49 卡②) | 构造注入:三屏壳、覆盖层、战区句柄、ModalFlow(main_ui_build 交付随之改型) | 无(RefCounted) |
| **UiCampModals**(`presentation/ui_camp_modals.gd`,营地域句柄子容器,已建件——迭代 47 卡⑥) | ui_modals 营地域六句柄唯一容器(场景根/四子界面/Esc 浮窗/HUD 栏),句柄寻址两段式 `modals.camp.*`;ui_modals 平铺面已清零(12 平铺句柄全数迁 run/menu 两子容器——分域纪律册级化,迭代 49 卡②) | 子容器属性+六句柄只读投影;main_ui_build 装配交付 | 构造注入(六视图句柄);ui_modals(父容器挂载) | 无(RefCounted) |
| **CampSceneView**(`views/camp_scene_view.gd`,营地场景根视图,已建件——迭代 47 卡④) | 营地场景图唯一呈现件:十层贴图铺底(层序按 layout 表 z 序;`camp_scene_layout.tres` fail-fast 校验+七命中区几何红线——camp_scene_layout_test 承载)、七物件命中区命中即发 object_pressed(组合根路由大门/篝火/笔记本/四界面)、反参照纪律(场景根零文字按钮)、登记模态初始隐(boot 态不盖菜单) | 构造注入(贴图经 `UiKit.TEX_CAMP_*`、layout 表经 ConfigDB 表现域容器);object_pressed 信号外发;open/close 经营地域子容器寻址 | camp_screen(宿主挂载);ConfigDB;组合根(路由消费) | Control+TextureRect 树 |
| **营地四子界面视图**(`views/camp_sub_view_base.gd`+forge_view/tree_view/treasure_view/codex_view,功能窗口公共壳+四件,已建件——迭代 47 卡④) | 营地五功能窗口的四个承载视图(锻造工坊/天赋树/秘宝匣/图鉴)+公共壳(窗口壳/行板/关闭钮;生涯页挂笔记本路由不经此族);模态栈单口 open/close、五窗互斥单开;presenter 承接面零回表(树购买/锻造三意图经既有写口族) | 各 view open/close+意图信号外发;关闭钮 pressed | camp_shop_presenter/MetaProgression 写口(经组合根);CampRefreshBus(刷新广播消费) | Control |
| **camp_esc_overlay+MainEscFlow**(`views/camp_esc_overlay.gd`+`presentation/main_esc_flow.gd`,Esc 浮窗视图+四态路由件,已建件——迭代 47 卡⑤) | Esc 浮窗三钮视图(返回主菜单/设置/退出)+Esc 四态路由静态件(根态唤起/再按关窗/功能窗开着先关最上层窗〔camp.md v2.3 定稿覆盖卡面 Q1 甲〕/设置开态不误关;菜单语境不唤起);**main._unhandled_input=产品码首个键盘输入入口**(契约 9——事件驱动、禁 Input 轮询、不挂 ui_cancel、pressed 非 echo) | flow.open/close 路由口;三钮 pressed 意图信号(经组合根接线) | 组合根(_unhandled_input 前置与意图消费);模态栈(关窗单口);screen_flow(设置/返回动线) | Control+静态件 |
@@ -180,7 +180,7 @@
| **board_resolvers**(`presentation/board_resolvers.gd`,迭代 37 拆出) | 棋盘每格渲染数据的只读解析回调四函数(奖励徽章身份——挖掘期 Active 相位内、地形变异数字遮蔽与角标、调试加成生效值)——有态绑定件,与无态静态投影族 HudPresenter 职责互斥 | 构造注入 db、调试浮窗与结算活态取值,产出绑定 Callable 供组合根接线 | ConfigDB / DebugOverlay / 结算活态取值 Callable | 无(纯投影) |
| **main_ui_build**(`presentation/main_ui_build.gd`,迭代 37 拆出) | `_build_ui` 八步拆分件——组合根 UI 装配分步承接(三屏壳实例化、视图句柄接线、覆盖层装配与模态编排注入按步拆开);main 侧留同名薄委托,装配序与 z 序零改动 | 分步静态函数(成员访问经 root 显式传入) | 层序逻辑不在此件——唯一事实源=`ui_registry.LAYER_CONTRACT`+`ui.apply_layer_contract(root)`(迭代 44 迁驻注册面) | 同 D1(Control 装配面) |
| **main_adventure_flow**(`presentation/main_adventure_flow.gd`,迭代 37 拆出) | main 冒险流程族——菜单开局/续玩后的冒险编排接线、节点事件分发、终局面与选路屏开合;逐字搬运,main 侧留同名薄委托(探针 `main.X` 路径零迁移) | 流程静态函数(root 显式) | 局态全局住 run_scope 节点——本件零成员态、零新增信号连接(连接语句随原段搬运) | 无 |
| **main_overlay_flow**(`presentation/main_overlay_flow.gd`,迭代 37 拆出) | main 浮层流程族——设置/状态面板/生涯页/选档界面/图例/钱包事件的开合与数据投喂;逐字搬运,main 侧留同名薄委托 | 流程静态函数(root 显式) | 全部开合走组合根模态编排口(`root.ui.modals.flow.open/close`)——本件零成员态 | 同 D1 |
| **main_overlay_flow**(`presentation/main_overlay_flow.gd`,迭代 37 拆出) | main 浮层流程族——设置/状态面板/生涯页/选档界面/图例/钱包事件的开合与数据投喂;逐字搬运,main 侧留同名薄委托 | 流程静态函数(root 显式) | 全部开合走组合根模态编排口(`root.ui.flow.open/close`——ModalFlow 自 UiModals 升格 UiRegistry 直驻,迭代 49 卡②)——本件零成员态 | 同 D1 |
| **main_debug_flow**(`presentation/main_debug_flow.gd`,迭代 37 拆出) | main 调试流程族——调试浮窗开合与上下文同步、批量模拟入口、两层调试对局起手、诊断转储;逐字搬运,main 侧留同名薄委托 | 流程静态函数(root 显式) | 调试会话状态机归 debug_session.gd——本件只接线与出 UI,零成员态 | 同 D1 |
| **TilePalette**(`presentation/views/tile_palette.gd`,迭代 37 拆出) | 瓦片排版/装载:高墙/地面瓦片整批装载与运行时镜像合成、地板明度归一、数字墨族按板自适应判据、格坐标确定性散列与十六正交情形墙瓦片查表 | 查表族(读件持棋盘引用——棋盘视图 rebuild 经 `bind_board` 同步);装载缓存七成员持于件内(同板型零重载、换板重载时序同源) | 零绘制面、零玩法数据写入(绘制调用面留棋盘视图);纹理路径单点在件内 | Resource 纹理加载——LOW |
| **HeroSprite**(`presentation/views/hero_sprite.gd`,迭代 37 拆出) | 英雄精灵四态与落位装配(落位与位移演出、撞墙帧闪、挖掘弹跳、脚底锚与持握手位出口) | 由棋盘视图 `_init` 建为子件(注入世界根与壳层容器引用)——精灵本体经世界根 ensure_hero 建于 SubViewport 世界内,本件只驱动其状态 | BoardWorld 世界根;素材缺位=零精灵(棋盘视图字形「人」回退路径在役) | Node2D / create_tween(Tween 系 Node 方法——MEDIUM 域对照 breaking-changes.md) |
@@ -198,7 +198,7 @@
### 三屏壳与组合根句柄面
- 呈现场景拆为三屏壳:MenuScreen(开始菜单屏)/CampScreen(营地屏)/AdventureScreen(冒险屏——内含关卡地图与战斗两容器)。
- 屏成员寻址自实现批起迁经界面注册面(**已建件——迭代 44**):探针挂载假设 `main.X` 迁移为 `main.ui.<域容器>.<句柄>`(ui_screens/ui_battle/ui_modals 三域容器,约 867 处探针与系统测试引用随批改址);原 S13 豁免登记〔2026-10-27「组合根类变量面即探针契约面」〕注销;main.gd 类变量 49→15,注册面形态见「模块归属·呈现层」表 ui_registry 行;ModalFlow 实例随 UiModals 容器构造建立(装配早期注入点依赖其先在座);取证探针 shot_probe/fx_shot_probe 随批改址;局态一律住 RunScope 节点,禁在屏/视图侧持有局态引用。
- 屏成员寻址自实现批起迁经界面注册面(**已建件——迭代 44**):探针挂载假设 `main.X` 迁移为 `main.ui.<域容器>.<句柄>`(ui_screens/ui_battle/ui_modals 三域容器,约 867 处探针与系统测试引用随批改址);原 S13 豁免登记〔2026-10-27「组合根类变量面即探针契约面」〕注销;main.gd 类变量 49→15,注册面形态见「模块归属·呈现层」表 ui_registry 行;ModalFlow 实例随 UiRegistry 构造建立(构造时点与原 UiModals 形态等价——注册面构造点先于装配,迭代 49 卡② 升格直驻);取证探针 shot_probe/fx_shot_probe 随批改址;局态一律住 RunScope 节点,禁在屏/视图侧持有局态引用。
- **组合根拆件**=组合根构造注入、代组合根执行核心写调用的呈现侧子件(现行三件:curio_interact_controller/camp_shop_presenter/treasure_interact_controller——冒险节点后续推进、营地购买与刷新、道具使用)。视图禁直连拆件;核心写调用的可达路径仍是「视图→信号→组合根(含拆件)→核心」,依赖规则与组合根单点装配不变。成员见「模块归属·呈现层」表。
### 视觉层装配合同
+2 -2
View File
@@ -2,7 +2,7 @@
> **一句话定位**:本文定义这个项目的 **Alpha 版本包含哪些东西**——它是里程碑 M3 的完成标准,也是判断"还差什么"的对照表。
> **本文只列条目,不写内容**:每样东西是什么、规则怎么走,一律归各自的权威文档,本文只给指路链接。想知道某样东西的定义,请点链接,不要在本文里找解释。
> **状态**:**已定稿(v1.24)**——2026-10-13 用户令定稿,历次升版明细见 git 提交史。Alpha 的内容范围自此冻结:增删条目一律须经用户裁决。
> **状态**:**已定稿(v1.25)**——2026-10-13 用户令定稿,历次升版明细见 git 提交史。Alpha 的内容范围自此冻结:增删条目一律须经用户裁决。
> **成文**:2026-10-13。
## 本文怎么用
@@ -103,7 +103,7 @@ Alpha 内以玩法循环本身的内容与表现为主(棋盘、关卡、战
| 主菜单 | —— | 在役(迭代 33 卡②三入口化:进入存档/设置/退出游戏——入口拓扑=进入存档→选档界面→进档/新档→营地覆盖层→〔营地交互重做卡④〕营地场景图与生涯笔记本;2026-10-22 用户裁换代〔反哺 #13〕) |
| 开始覆盖层 | —— | 在役 |
| 选档界面(3 存档位) | —— | 在役(迭代 33 卡③——空槽新档/有档进档/删档二次确认+摘要三项;2026-10-22 用户裁增行〔反哺 #8〕) |
| 营地(天赋树 / 锻造工坊 / 秘宝匣 / 图鉴) | [camp](ux/camp.md) | 在役(迭代 47 卡④⑤ 落地——场景图+七物件点选+Esc 浮窗与顶栏,2026-11-01 合回) |
| 营地(天赋树 / 锻造工坊 / 秘宝匣 / 图鉴) | [camp](ux/camp.md) | 在役(迭代 47 卡④⑤ 落地——场景图+七物件点选+Esc 浮窗与顶栏,2026-11-01 合回;五功能页呈现=居中定尺寸功能窗口、场景根留底、窗内滚动——窗壳形态 2026-11-02 迭代 49 卡③实装) |
| 营地交互重做(五卡:存档制数据层/主菜单三入口/选档界面/营地场景图/Esc 浮窗与营地顶栏) | [camp](ux/camp.md) | 在役(五卡全部落地——卡①②③ 迭代 33 批合回、卡④⑤ 迭代 47 批合回,卡⑥ 句柄子容器为同批前置基建卡。设计过程件已按吸收即死退役,沿革查 git 提交史。2026-10-21 用户裁:五卡整体列入 Alpha。出口=五卡各自验收标准通过+营地屏用户目检〔登记体验验证清单 ㊺〕) |
| 生涯页 | [生涯](systems/跨局循环/生涯.md) | 在役(期一) |
| 关卡地图屏 | [level-map](ux/level-map.md) | 在役 |
+2 -2
View File
@@ -1,6 +1,6 @@
# 营地场景 UX spec(camp)
> 状态:v2.5(现行)
> 状态:v2.6(现行)
> 事实源:本 spec(呈现)+ [元进度](../systems/跨局循环/元进度.md)(机制)
> 美术画法:[art-bible](../../art/art-bible.md) §6.2/§7.5;素材命名与路径:[asset-path-map](../../art/asset-path-map.md)
> 相邻:[level-map.md](level-map.md)(主菜单语境)
@@ -42,7 +42,7 @@
## 叠层与开合
各界面开合走模态栈单口,层序按模态栈契约登记。**承载形态已定稿**:五个功能界面(锻造工坊/秘宝匣/天赋树/奖励格图鉴/生涯记录)各以**功能窗口**打开——窗口为统一居中定尺寸窗壳(起点 720×640,窗明显小于屏、营地场景大面积可见;终值随样张目检校准,属普通设计决策),窗之下垫半透明压暗遮罩(交互聚焦用,复用既有模态遮罩件,现值锚黑色 0.6;观感随样张目检校准,属普通设计决策),内容超高时窗内滚动;生涯页与四子界面同壳同形态。**五窗互斥单开**(模态栈深恒 1,不开窗叠窗);各窗自带关闭钮。ESC 优先序:有功能窗口开着 → 先关最上层窗;无窗 → 才进 ESC 浮窗(返回主菜单/设置/退出游戏)。
各界面开合走模态栈单口,层序按模态栈契约登记。**承载形态已定稿**:五个功能界面(锻造工坊/秘宝匣/天赋树/奖励格图鉴/生涯记录)各以**功能窗口**打开——窗口为统一居中定尺寸窗壳(起点 720×640,窗明显小于屏、营地场景大面积可见;终值随样张目检校准,属普通设计决策)——**该窗壳形态已实装**(2026-11-02 迭代 49 卡③落码:窗壳几何单点定值、五窗共用同一石板皮窗板;起点值 720×640 为实装现值,样张目检校准意见回填终值〔登记体验验证清单 ㊽〕),窗之下垫半透明压暗遮罩(交互聚焦用,复用既有模态遮罩件,现值锚黑色 0.6;观感随样张目检校准,属普通设计决策),内容超高时窗内滚动;生涯页与四子界面同壳同形态。**五窗互斥单开**(模态栈深恒 1,不开窗叠窗);各窗自带关闭钮。ESC 优先序:有功能窗口开着 → 先关最上层窗;无窗 → 才进 ESC 浮窗(返回主菜单/设置/退出游戏)。
## 口径
+3 -1
View File
@@ -1,7 +1,7 @@
# 术语表
> 全库专用术语的唯一对照表(2026-10-11 用户令建立)。规矩:新术语先登记本表、再在文档使用;退役词见文末对照表,文档正文一律使用现行词。文档中遇到看不懂的词,查本表。用词纪律(禁用词、替换值、豁免范围)见「用语规范」节。
> 状态:**现行 v1.25**——2026-10-11 建立;历次升版明细见 git 提交史。
> 状态:**现行 v1.26**——2026-10-11 建立;历次升版明细见 git 提交史。
## 格与棋盘
@@ -94,6 +94,8 @@
| 术语 | 定义 |
|---|---|
| 效果端口件 | 战斗业务类(伤害管线/行动经济)唯一的效果发射出口:收事件与载荷、交效果引擎结算、取回命中批——业务类零引擎直连(机制归属见架构文档「战斗编排域拆件定稿」节轴戊;实现类 EffectPort) |
| 掷格件 | 装配期格面资源摇号的承载件:池行装配、区间行 roll、权重合成(偏运硬币/board_skew 两路投影);受理账面留守地图战斗资源件(机制归属同上;实现类 RewardRoller) |
| `seal_missed` | 封印落空事件(旧名已换代):封印动作落在安全格上时发出,订阅面据此做限次与豁免判定(迭代 31 卡② 落地) |
| `forgive_seal_miss` | 本场首次封印落空豁免——专长「完美保险」的效果类型,`domain=battle` 首例;有效误标=误标总数 − 豁免数,豁免不改写误标账(迭代 31 卡② 落地) |
+2 -2
View File
@@ -84,7 +84,7 @@ tests/
|---|---|---|---|
| 伤害公式与掷点乘区 | 战斗结算 | `DamageMath.pool_damage()`/`roll_discount_percent()`/`rolled_component()` | `damage_math_test.gd:_test_pool_damage`;`damage_math_test.gd:_test_roll_discount_percent`;`roll_multiplier_test.gd:_smoke_armor_roll` |
| 伤害单据编排与回放 | 战斗结算 | `DamageController.submit()`/`open_ticket()`/`flush()` | `damage_controller_test.gd:_run_recipe_sequence`;`damage_controller_test.gd:_test_five_recipes_and_replay` |
| 效果发射端口单点 | 战斗结算 | `BattleOrchestrator.begin_battle()`(真实装配链端口接线+合成行闭面守卫经 `DamageController.flush_submit()` 承伤路径) | `effect_port_test.gd:_smoke_effect_port_wiring`;`effect_port_test.gd:_test_business_classes_engine_free`;`effect_port_test.gd:_test_biz_fact_face_closed`〔计划用例——锚定 `reports/需求卡片-效果端口与掷格分件批-2026-11-02.md`〕〔效果端口与掷格分件批 V1/V2/V3〕 |
| 效果发射端口单点 | 战斗结算 | `BattleOrchestrator.begin_battle()`(真实装配链端口接线+合成行闭面守卫经 `DamageController.flush_submit()` 承伤路径) | `effect_port_test.gd:_smoke_effect_port_wiring`;`effect_port_test.gd:_test_business_classes_engine_free`;`effect_port_test.gd:_test_biz_fact_face_closed`〔效果端口与掷格分件批 V1/V2/V3〕 |
| 轮内流与结算五段全序 | 战斗结算 | `BattleOrchestrator.begin_battle()` | `round_flow_skill_pool_test.gd:_smoke_full_battle`;`round_flow_skill_pool_test.gd:_smoke_settlement_segments` |
| 技能池数据面与回放独立 | 敌人系统 | `BattleOrchestrator.begin_battle()`(技能池抽号/校验) | `round_flow_skill_pool_test.gd:_smoke_skill_pool_data`;`round_flow_skill_pool_test.gd:_smoke_skill_pool_replay_independence` |
| Boss 半血解锁技门控 | 敌人系统 | `BattleOrchestrator.begin_battle()`(Boss 行) | `skill_unlock_test.gd:_test_gate_predicate`;`skill_unlock_test.gd:_test_latch_irreversible` |
@@ -154,7 +154,7 @@ tests/
| Esc 浮窗唤起与三出口动线 | 营地 Esc 流 | 营地场景根态合成 Esc 键事件→ `main_esc_flow.on_esc_input()` → `ui.flow.open/close`;浮窗三钮 `pressed` → 三出口 | `screen_flow_probe.gd:_ready`(Esc 唤起/子界面开态不唤起/再按关窗/非营地不唤起段)〔ESC批 V1〕;`screen_flow_probe.gd:_ready`(返回动线/设置双路径段)〔ESC批 V3/V4〕 |
| 减动效开关存储契约(持久化回读/缺省值/引擎动效档应用) | 设置与本地化 | `SettingsStore.load_settings()`/`save_settings()`/`apply()` | `settings_store_test.gd:_test_settings_roundtrip`;`settings_store_test.gd:_test_settings_default`;`settings_store_test.gd:_test_settings_apply_chain` |
| 营地顶栏 HUD 钥石读数与刷新单口同步 | 营地 HUD 栏 | 隔离存档实例 `meta_state._add_keystone()`→ 显式触发 `CampRefreshBus.refresh(camp_data)` → `camp_hud_band.refresh()` → `keystone_badge` 读数 | `screen_flow_probe.gd:_ready`(HUD 余额读数/刷新段)〔ESC批 V6〕;`ui_struct_probe.gd:_ready`(顶栏位结构段) |
| 营地五窗统一窗壳形态 | 营地五界面 | 七物件命中区/笔记本 → `CampSceneView._gui_input()`(`object_pressed` 信号)→ 组合根分派开窗;窗板几何(居中定尺寸 720×640 起点)/遮罩/窗内滚动面为呈现提交面 | `screen_flow_probe.gd:_step_camp_window_shell`(窗壳形态段,计划用例——锚定 `reports/需求卡片-营地五界面真窗口化批-2026-11-02.md`)〔窗口化批 V1–V8〕 |
| 营地五窗统一窗壳形态 | 营地五界面 | 七物件命中区/笔记本 → `CampSceneView._gui_input()`(`object_pressed` 信号)→ 组合根分派开窗;窗板几何(居中定尺寸 720×640 起点)/遮罩/窗内滚动面为呈现提交面 | `screen_flow_probe.gd:_step_camp_window_shell`(窗壳形态段)〔窗口化批 V1–V8〕 |
**旅程段七:数据配置与跨系统契约**
+1 -1
View File
@@ -308,7 +308,7 @@ fi
# 可回放纯逻辑步骤流(同种子同输入逐位复现),await 会打断确定性——「模块归属」B1 行已写明
# 「禁 await——切片 88 冒烟实证」。本闸为防回归防线(2026-10-24 人工 grep 盘面干净)。
# 扫描面:B1 域文件集(与 architecture.md「模块归属」B1 行同口径)=battle_orchestrator.gd
# + battle_fx_host.gd + reward_grant.gd + board_installer.gd 三拆件 + settlement/ 五段段类 + damage_controller.gd,共 10 文件,显式清单见 S8_FILES。
# + battle_fx_host.gd + reward_grant.gd + board_installer.gd 三拆件 + settlement/ 五段段类 + damage_controller.gd,共 14 文件,显式清单见 S8_FILES。
# 执行侧字面值豁免:脚本必须带字面值才能工作;文件集与架构文档冲突时以 B1 域文件集为准。
# 判据:文件集内出现 await 关键字即红(词边界 \bawait\b,任何形态——await 信号/协程/
# get_tree());排除注释行(行首 #/##)与字符串字面量(双引号包裹段内的 await 非代码),
-32
View File
@@ -1,32 +0,0 @@
# 迭代 49 反哺点清单(2026-11-02)
> 实现批产出物:要写进 `design/` 与根流程清单的点逐条列落点(哪个文件哪一节、改成什么、依据是什么),由用户裁决后经文档批(doc-design 技能)写入并清条。实现批禁写 `design/` 与根规则文件。
## A. 卡①效果端口与掷格分件
| # | 落点 | 改成什么 | 依据 |
|---|---|---|---|
| A1 | `design/engineering/architecture/architecture.md`「战斗编排域拆件定稿」节轴戊两条+功能层 B4 行/BattleFxHost 行/damage_controller 行/action_economy 行/reward_economy 行 | 「实现批建件」待建注记换代为已建件现状:EffectPort(`game/core/effect_port.gd`,六 Callable 路由、bind_port 组装期转注、闭面五键 biz_fact、未绑零扰动缺省)与 RewardRoller(`game/core/reward_roller.gd`,roll 批束四键 mapping/power_roll/clear_identity/clear_power、选行算子 `_weighted_pick_row` 返表行、fatal 经构造 Callable 链);B4 公开面 weighted_pick 退役(返行选行算子迁掷格件)、roll_board 装配序(守卫→复位→委托→收纳→ready)、类变量实数(economy 11、damage 12、action 10、fx_host 15、orchestrator 15) | 本批提交 848723b5 实况 |
| A2 | `design/gdd/术语表.md` | 「效果端口件」「掷格件」两机制名是否登记由文档批裁决(首现定义在 architecture 轴戊条款) | 卡① §6 同步面声明 |
| A3 | `tools/static_scan.sh` S8 清单头注 | 「共 10 文件」计数句与实列(14 文件)失符——入批前存量漂移,随批订正 | 本批件核发现(实现报告 §七) |
## B. 卡②模态句柄分域
| # | 落点 | 改成什么 | 依据 |
|---|---|---|---|
| B1 | `design/engineering/architecture/architecture.md` ui_registry 行(v1.30 行号漂移,以内容锚「三域句柄容器」定位) | 换代为「三域句柄容器+模态编排件直驻」:screens/battle/modals+flow(ModalFlow 自 UiModals 升格 UiRegistry 直驻)+register_layer 迁驻注册面;类变量实数 UiRegistry 3→4、UiModals 14→3(run/menu/camp 三子容器纯字段) | 本批提交 bc5dd4ec 实况 |
| B2 | 同上 UiCampModals 行 | 「ui_modals 平铺面收窄」现状化为平铺面清零(分域纪律册级化——12 平铺句柄全数迁 run/menu 两子容器) | 同上 |
| B3 | 同上 ModalFlow 行(「实例随 UiModals 容器构造即建」句) | 换代为「随 UiRegistry 构造建立」(构造时点等价——注册面构造点先于装配) | 同上 |
## C. 卡③营地五界面真窗口化
| # | 落点 | 改成什么 | 依据 |
|---|---|---|---|
| C1 | `design/gdd/ux/camp.md`「叠层与开合」节 | 补实装注记:五窗统一居中定尺寸窗壳起点 720×640 已落码(窗几何单点=CampSubViewBase.WINDOW_SIZE、窗板石板皮、遮罩复用模态遮罩件现值 0.6);样张目检校准意见回填终值(观感校准=普通设计决策) | 本批提交 1f0a8bd3 实况+camp.md v2.5 定稿值 |
| C2 | `design/gdd/08-Alpha版本标准.md`「三·界面」营地行 | 在役陈述补窗壳形态注记(营地五功能页=居中定尺寸功能窗口、场景根留底、窗内滚动) | 卡③ §6 同步面 |
| C3 | `体验验证清单.md` | 登记目检项三条:①五窗观感与场景可见度样张判定(720×640 起点/遮罩 0.6 观感校准)②窗内滚动手感(天赋树长列表/生涯页)③(迭代 48 批后无新增卡①卡②目检项——行为零变化) | 实现报告 §六(真人检测只登记不阻塞) |
| C4 | `design/gdd/systems/跨局循环/生涯.md` :72 | 核查结论记档:现行「营地场景图+五功能窗口形态」陈述与本批一致,零冲突零义务 | 卡③ §6 零义务条(仅记录) |
## D. 退役提醒(吸收即死)
本清单各条经文档批写入后逐条清除;本文件与实现报告、三张需求卡片按「证据只留最新」在批后收尾(batch-closure)退役。
-101
View File
@@ -1,101 +0,0 @@
# 迭代 49 实现报告(2026-11-02)
> 批性质=代码实现批(三卡:效果端口与掷格分件+模态句柄分域+营地五界面真窗口化)。工作区 `g-plan2-iter49`(分支 `iter49`),定义面(roadmap/待办清单/三卡 v1.1)已在 HEAD 预入库、零搬运提交。卡序=核心域先行(端口分件→句柄分域→窗口化),整迭代单工作区串行。
## 一、各卡状态
| 卡 | 终态提交 | 状态 | 里程碑步闸 |
|---|---|---|---|
| ①效果端口与掷格分件 | 848723b5 | 完成(T0–T4 全落) | `--code` 全绿(红件修复后复验) |
| ②模态句柄分域 | 53c1536c | 完成(T0–T2 全落) | `--code` 全绿(S10 头注修正后复验) |
| ③营地五界面真窗口化 | 1f0a8bd3+2d325d3e(件核) | 完成(T0–T3 全落) | `--code` 全绿(7 闸全绿) |
## 二、S13 读数对照(改前 → 改后,卡① §14 预算全数达成)
| 文件 | 类变量 | 公开方法 | 判定 |
|---|---|---|---|
| battle_orchestrator.gd | 15 → 15 | 14 → 14 | 持平(硬预期)✓ |
| battle_fx_host.gd | 14 → 15 | 12 → 16 | 贴顶 ≤15 ✓(+facts_inject 一成员+四法) |
| damage_controller.gd | 15 → 12 | 9 → 9 | 只降 ✓(set_fx 退役/bind_port 增补相抵) |
| action_economy.gd | 11 → 10(plain 口径;raw 15 含 4 属性访问器) | 15 → 15 | 只降 ✓ |
| reward_economy.gd | 15 → 11 | 12 → 9 | 只降 ✓(掷格五成员十二函数三常量迁出+roller 增补) |
| ui_modals.gd(卡②) | 14 → 3 | 1 → 0 | 只降 ✓(转纯字段容器) |
| ui_registry.gd(卡②) | 3 → 4 | 2 → 3 | 上限内不产新键 ✓ |
| 新件三查 | effect_port 6/6、reward_roller 2/6、ui_run_modals 0/6、ui_menu_modals 0/6 | — | 全默认阈值内 ✓;gdstyle 基线外新违规 0(roll 局部变量 12→10 内联收敛后) |
## 三、实际改动—验收对照表
### 卡①(断言尾缀〔效果端口与掷格分件批 V1/V2/V3〕,载体 `game/tests/unit/battle_settlement/effect_port_test.gd`)
| 需求点 | 验收断言(文件:行) | 真实入口 | 结果 |
|---|---|---|---|
| R1 端口单实例与真实发射路由 | effect_port_test.gd:66(端口同一性——内部字段直查受控例外:端口同一性无公开查询面,对照表行 1 注明);:69-79(attack_commit 经真实回合命中可观测:蓄力层预置 3→攻击行在流→层账 3→0 全处理→delta 读数非零) | `BattleOrchestrator.begin_battle()` 装配链+真实停手回合(settle_batch 同步五段) | 绿(15/15) |
| R2 业务类零引擎直连 | effect_port_test.gd:89-95(两业务文件全文零 `EffectEngine`/`EffectContext` token,扫描面非空前置在案) | 测试直读源码(源码契约锚惯例) | 绿 |
| R3 伤害域事实面闭集 | effect_port_test.gd:107-137(阳性:hp_ratio 载荷 when→承伤减量恰 1;阴性:battle_index 不答→零减量;合成行 effect 段逐字抄现役铁壁 shield 行、订阅面换代独占) | `DamageController.flush_submit()` board_flat_hero 真实单据流 | 绿 |
| R4 端口接线时序与入站路由等价 | 既有套件照跑:refresh_feats_test/effect_words_t1_test/adventure_feats_test(原判据零改) | 真实玩法路径 | 绿 |
| R5 掷格件建件与摇号等价 | 既有 board_gen_reward_test 照跑(全 API);round_flow EV 锚+事件流逐位回放 134 检查 | `begin_battle()` install 链 roll_board 恰一次 | 绿 |
| R6 economy 收纳与键账只降不升 | T3 读数对账(15→11/12→9,见 §二)+既有受理面套件照跑 | 既有受理 API | 绿 |
| R7 装板域与编排域改址 | 既有 variant_placement_test 照跑(白盒指址换代 18 行 22 处、判据零删改) | 装板摇号链 | 绿 |
| R8 行为零变化总证 | round_flow_skill_pool_test 134 检查全绿(EV 锚+逐位回放 ×2 关) | 全战斗回放 | 绿 |
| R9 闸清单随动 | static_scan.sh S7_B1_SET/S8_FILES 各增两新件、B4 符号清单 weighted_pick 行删除;run_all.gd manifest 登记;代码域闸全绿 | 静态扫描域闸 | 绿 |
### 卡②(断言尾缀〔句柄分域批 V1〕,载体 `game/probe/ui_struct_probe.gd` _modal_registry_contract 段尾 :606-625)
| 需求点 | 验收断言(文件:行) | 真实入口 | 结果 |
|---|---|---|---|
| R1 局内冒险域六件抽容器 | ui_struct_probe.gd:610-613(run 六件经 `modals.run.*` 逐件非 null) | 真实实例化主场景 `_ready` 装配→registry 合同段 | 绿 |
| R2 菜单与跨语境域六件抽容器 | ui_struct_probe.gd:614-616(menu 六件逐件非 null) | 同上 | 绿 |
| R3 平铺面清零+编排口升格+登记口迁驻 | ui_struct_probe.gd:617-625(V1b 12 件 get() 逐件 null+V1c `ui.flow` 在座且 modals 无 flow);S13 静态判据 14→3/3→4(gdstyle 闸) | 同上 | 绿 |
| R4 全仓寻址换代行为零变化 | 既有断言群改址照跑:smoke 15 检查/system_test 69 检查/探针族全绿/presentation 17 套件(原判据零改,theme_projection :719 期望串两侧一致换代已申报) | 真实开机路径→真实输入/信号路径 | 绿 |
| R5 登记册合同序不破 | ui_struct_probe ①②③④段(装配生命批 V1)改址照跑绿 | 同上 | 绿 |
| R6 诊断转储接线断言字面换代 | theme_projection_test.gd:719 照跑绿(V6 段) | run_all presentation 套件 | 绿 |
全仓旧形零残留:`grep -rnE "modals\.flow|modals\.(12 平铺名)" --include=*.gd game` 零命中(唯一命中=ui_struct_probe.gd:624 V1c 断言消息字面,非寻址代码)。
### 卡③(断言尾缀〔窗口化批 V1–V8〕,载体 `game/probe/screen_flow_probe.gd` _step_camp_window_shell :298-455)
| 需求点 | 验收断言(文件:行) | 真实入口 | 结果 |
|---|---|---|---|
| 四窗统一窗壳 720×640 起点居中 | screen_flow_probe.gd:342(V1 四窗窗板 global_rect ≈(280,80,720,640) 容差 0.01) | 选档层进档→场景点选 `object_pressed` 真实信号路由 | 绿 |
| 窗明显小于屏+场景根留底 | :345-349(V2 camp.scene.visible+四边距 ≥80px) | 同上 | 绿 |
| 遮罩 0.6 回归 | :352-357(V3 遮罩 ColorRect alpha≈0.6+全屏) | 同上 | 绿 |
| 各窗关闭钮回归 | :324-331 与 :432-439(V4 四窗「返回营地」/生涯「返回」真实 pressed→窗隐+场景根留底) | 窗内真实 Button 信号 | 绿 |
| 五窗互斥单开回归 | :362-381(V5a 逐窗五窗计数==1+V5b 树窗开态推真实鼠标点零点穿) | 同上+push_input | 绿 |
| ESC 优先序回归 | :388-399(V6 生涯窗开态 Esc 先关窗、浮窗不唤起) | push_input 真实 Esc 键 | 绿 |
| 内容超高窗内滚动 | :405-428(V7 加长行册喂入后窗板 rect 仍等值+内容实高>滚动视口) | `object_pressed(&"dummy")`+`refresh_camp` 真实投喂 | 绿 |
| 生涯页同壳同形态 | :433-451(V8 生涯窗板同几何+「返回」在位+纵向 EXPAND_FILL 滚动面);theme_projection_test 全件照跑绿 | 笔记本点选路由;单元侧 `open_career()` | 绿 |
shot_probe 窄验:exit 0;shot_career.png 通用判据读数 std=70.2(阈 ≥8)、唯一色数 157(阈 ≥40)、尺寸 1280×800——生涯窗壳形态下双达标,读数记档盯 CI。
## 四、实现决定记录(超白名单事项)
1. **int(null) 构造拒(卡①)**:卡内断言「int(null)=0/bool(null)=false」在本引擎(4.7.2)不成立——`int()` 拒 null 构造(SCRIPT ERROR: Nonexistent 'int' constructor)。三调用点(open_ticket dig_streak 载荷键/rider_tier_bonus/rider_tier_crit 读)改 `or 0`/`or false` 空值合并:合法值域(非负 int/bool)上与「缺省 0/false」逐位等价。撤销方式=还原为直包 int()/bool()(会红)。代价:无(缺省语义逐位同,V1-V3 与全量闸为主证)。
2. **V8 字符串 Callable 硬零闸(卡①)**:effect_port 组建初版用 `Callable(self, "…")` 六枚——source_guard_test V8(产品码字符串 Callable 零命中,迭代 27 换装闸)红。改方法直引用形态(`"emit_cb": fx_emit_biz`),与 bundle emit_cb/facts_cb 既有接线同型。撤销方式=无(直引用即既有形态)。
3. **roll() 局部变量预算(卡①)**:迁移后 roll() 12 局部(max 10,gdstyle 基线外新键)——清图选行与区间行查表两处临时内联,randi_range 求值位置不动、取号序与取号次数零变化(round_flow 逐位回放主证)。撤销方式=还原临时变量(会撞闸)。代价:行查表达式三连读(同一 dict 两次下标,无行为差)。
4. **定尺寸窗禁单行撑宽的标签适配(卡③)**:career hint 与行值标签实测单行 min 宽(hint ≈766px/「各关完成次数」值 742px)把窗板撑到 798——补 `AUTOWRAP_WORD_SMART`+横向 EXPAND_FILL(短值视觉零变,长值窗内换行)。属窗几何契约(720×640 不随内容涨)的伴随适配,非内容重排。撤销方式=去 autowrap(V8 立红)。
5. **V6/V8 测序前置清窗(卡③测试侧)**:模态栈语义=open 隐上方层+close 恢复——信号直发轮转给 board 层留遮挡账,钮关树窗把 board 复原出双窗态;真实 UI 中生涯入口只在无窗态可达(遮罩挡场景点选,V5b 钉死)。V6/V8 前置改经真实钮逐窗清账(_close_all_windows),不测不可达态。撤销方式=无(测试时序修正,非判据改)。
6. 其余全部按卡执行(端口注入 Callable 束/bind_port 时点/闭面五键/选行算子返表行/窗板石板皮/WINDOW_SIZE 单点等)——零超卡裁断。
## 五、T0 复核结论(卡① F1-F14)
11 条全符;三处纯引用漂移(不改设计前提,未停卡):F5 掷格面行号成簇漂移+phase/is_mapped 引用互换(成员清单与计数全证实);F11 卡内枚举漏列 feats.tres:633 dig_stop 订阅行 when fact=ap_left——ap_left 由 dig_stop 载荷携带(:178),payload 同名优先解析,事实回调不触,统一闭面零观测差结论经本会话逐行复核成立;F13 gdstyle 基线 5 键实际 :8-12。
## 六、实机目检总清单(真人检测只登记不阻塞)
1. 营地五窗观感与场景可见度样张判定(窗 720×640 起点/遮罩 0.6 观感校准意见)。
2. 窗内滚动手感(天赋树长列表/生涯页)。
3. 模态开合走查由既有探针族覆盖(卡②登记句;零新增目检项)。
登记面=体验验证清单(归文档批随反哺入册),不阻塞合并。
## 七、遗留读数义务与观测面局限
- shot_career 通用判据读数(std=70.2/色数 157)随 CI 渲染闸复验盯守。
- 卡③合同表零改动(红线 1)判据为静态:LAYER_CONTRACT 数据块 diff 零行变更由独立验收审计核对(观测面局限申报,非撤销类取证)。
- static_scan.sh S8 清单注释「共 10 文件」为入批前存量漂移(实列 13→今 14),未属本批申报面,未顺手改。
## 八、产出物与审计
- 反哺点清单:`reports/iter49-反哺点-2026-11-02.md`(architecture/camp.md/08-Alpha/术语表/体验验证清单)。
- 独立验收审计:`reports/iter49-验收审计-2026-11-02.md`(未参与实现的子代理执行;未过不得合并)。
- 能力清单核对:三卡能力行名与实际落地测试名一致(effect_port_test 三函数实名/ui_struct_probe._modal_registry_contract 实名/screen_flow_probe._step_camp_window_shell 实名)——零回表。
-146
View File
@@ -1,146 +0,0 @@
# 迭代 49 独立验收审计(2026-11-02)
> **接收方**:iter49 合并门(合回前独立验收审计——test-conventions §8.7;未过不得合并)。
> **审计员**:未参与实现的独立子代理(迭代 loop 内启动)。只读审计+最窄抽查跑批,除本报告外零改任何文件。
> **审计输入**:三卡 v1.1「验证闸(改动—验收对照表)」节、`reports/iter49-实现报告-2026-11-02.md` 实际对照表、分支 diff(`git diff master...iter49`,HEAD=52d87309,48 文件 +1553/−878)、测试文件实况、闸回执 `game/tests/.gates/receipt.json`。
## 结论先行
**通过=可合并。** 缺漏 0;例外 1(卡① 断言消息批名尾缀形态,依据在案,详见 §一卡① 末行与 §七)。
---
## 一、逐行核对(三卡对照表 ↔ 实现报告 ↔ 测试实况)
### 卡① 效果端口与掷格分件批(载体 `game/tests/unit/battle_settlement/effect_port_test.gd`,129 行实读)
| 对照表行 | 测试实况 | 真实入口核验 | 状态 |
|---|---|---|---|
| R1 端口单实例与真实发射路由 | `_smoke_effect_port_wiring`(:55-83)在库;端口同一性断言 :66;attack_commit 命中链 :68-83(蓄力层预置→攻击行在流→层账 3→0→同种子对照跑 delta≥1) | `BattleOrchestrator.new(_db, rng)`+`begin_battle`+`settle_batch([{"action":"stop"}])` 真实装配链与停手回合——**非裸 EffectEngine 直调**;文件内 EffectEngine 直调仅两处夹具预置/读数(:68/:74,注释注明与 refresh_feats_test V8 同法的调试注入,发射路径全经端口) | 通过 |
| R2 业务类零引擎直连 | `_test_business_classes_engine_free`(:88-94)源码锚直读两业务文件,扫描面非空前置在案(:92) | 测试直读源码(源码契约锚惯例) | 通过 |
| R3 伤害域事实面闭集 | `_test_biz_fact_face_closed`(:99-129)阳性 hp_ratio 载荷 when→承伤减量恰 1(:122);阴性 battle_index→零减量(:129);合成行 effect 段逐字抄现役铁壁行、rebuild 独占订阅面(:104-116) | `DamageController.open_ticket`+`flush_submit` board_flat_hero 真实单据流 | 通过 |
| R4 接线时序与路由等价 | 既有 refresh_feats_test/effect_words_t1_test/adventure_feats_test 照跑,原判据零改(diff 核清) | 真实玩法路径(CI gate 02 全绿) | 通过 |
| R5 掷格件建件与摇号等价 | board_gen_reward_test 照跑(全受理 API) | `begin_battle` install 链 roll_board 恰一次(CI gate 02) | 通过 |
| R6 economy 收纳与键账只降不升 | S13 读数对照在报告 §二(15→11/12→9)+受理面套件照跑 | 既有受理 API(CI gate 09 静态+gate 02 行为) | 通过 |
| R7 装板域与编排域改址 | variant_placement_test 指址换代 18 行 22 处、判据文本与阈值逐字保留(diff 逐行核) | 装板摇号链 | 通过 |
| R8 行为零变化总证 | round_flow_skill_pool_test 134 检查全绿(EV 锚+逐位回放 ×2 关) | 全战斗回放(CI gate 02) | 通过 |
| R9 闸清单随动 | static_scan.sh S7_B1_SET 与 S8_FILES 各增 effect_port.gd+reward_roller.gd、B4 符号清单删 weighted_pick 行;run_all.gd:199 manifest 登记 effect_port_test(expect 0)——diff 逐行核清 | 静态扫描域闸(CI gate 09 green) | 通过 |
| 断言尾缀 | 全 15 条断言消息带 V1/V2/V3 编号前缀;批名全称〔效果端口与掷格分件批 Vn〕未入消息字面——全称在文件头注(:1)与 run_all.gd manifest 注释在案 | — | 例外及依据:卡① §11 代拍板白名单第 8 条明文「断言消息文案——非契约面」,尾缀括注落消息文案内属卡内授权裁量;grep 定位面成立(按 V 号+文件名定位断言、按批名定位批次)。与卡②卡③全称尾缀形态不齐,随本报告知悉合并门;如需严格统一归一行字面修复批,不阻本批合并 |
### 卡② 模态句柄分域批(载体 `game/probe/ui_struct_probe.gd` `_modal_registry_contract` 段尾)
| 对照表行 | 测试实况 | 真实入口核验 | 状态 |
|---|---|---|---|
| R1 局内冒险域六件 | V1a(:608-612)run 六件经 `modals.run.*` 逐件非 null | main.tscn 真实实例化 `_ready` 装配→:33 无条件调 `_modal_registry_contract(main)` | 通过 |
| R2 菜单与跨语境域六件 | V1a(:613-615)menu 六件逐件非 null | 同上 | 通过 |
| R3 平铺清零+flow 升格+登记口迁驻 | V1b(:616-619)12 件 `get()` 逐件 null;V1c(:620-624)`ui.flow` 在座且 `modals.get("flow")` 为 null;S13 静态判据(CI gate 09) | 同上 | 通过 |
| R4 全仓寻址换代行为零变化 | 既有断言群改址照跑:smoke(CI 00)/system_test(CI 01)/探针族(CI 03)全绿;本审计自跑 ui_struct_probe+screen_flow_probe 双 PASS | **真实开机路径**(main.tscn 实例化+真实输入/信号) | 通过 |
| R5 登记册合同序不破 | ①②③④段〔装配生命批 V1〕(:561-605)改址照跑——实况寻址已为 `modals.run.*`/`modals.menu.*` 二段式,判据零改 | 同上 | 通过 |
| R6 诊断接线字面换代 | theme_projection_test:719 期望串换代与申报逐字一致(diff 核) | run_all presentation 套件(CI 02) | 通过 |
| 旧形零残留(完成定义 #3) | 全仓 `grep -rnE "modals\.flow|modals\.(12 平铺名)" --include=*.gd game` 唯一命中=ui_struct_probe.gd:624 断言消息字面(非寻址代码)——与报告 §三 陈述一致 | — | 通过 |
尾缀〔句柄分域批 V1〕grep 到(:612/:615/:619/:622/:624)。
### 卡③ 营地五界面真窗口化批(载体 `game/probe/screen_flow_probe.gd` `_step_camp_window_shell`)
| 对照表行 | 测试实况 | 真实入口核验 | 状态 |
|---|---|---|---|
| 四窗统一窗壳 720×640 起点居中 | V1(:336-342)窗板 `get_global_rect()` ≈(280,80,720,640) 容差 0.01 | `ProbeUiUtil.open_camp_via_savesel` 真实选档钮进档+`object_pressed.emit(k)` 真实信号路由(:303-332) | 通过 |
| 窗明显小于屏+场景根留底 | V2(:344-348)`camp.scene.visible`+窗板四边距视口边 ≥80px | 同上 | 通过 |
| 遮罩 0.6 回归 | V3(:350-356)首子节点 ColorRect alpha≈0.6+全屏尺寸容差判等(禁裸 == 落实) | 同上 | 通过 |
| 各窗关闭钮回归 | V4(:320-329 轮转间+:445-451 生涯+:457-467 清窗)真实 Button `pressed.emit()`→窗隐且场景根留底 | 窗内真实钮信号 | 通过 |
| 五窗互斥单开回归 | V5a(:357-363)五窗集 visible 计数==1;V5b(:364-381)`get_hotspot_rect(&"forge")` 公开读面+`push_input` 真实鼠标点→零点穿零新窗 | 同上+真实输入事件 | 通过 |
| ESC 优先序回归 | V6(:385-396)`push_input` 真实 Esc 键→生涯窗隐、浮窗不唤起 | 真实键盘事件 | 通过 |
| 内容超高窗内滚动 | V7(:397-419)真实投影口 `refresh_camp` 喂 30 行合成行→窗板 rect 仍等值+内容实高>滚动视口 | `object_pressed(&"dummy")`+真实数据投喂 | 通过 |
| 生涯页同壳同形态 | V8(:422-444)窗板同几何+「返回」钮在位+纵向 EXPAND_FILL 滚动面;theme_projection_test 全件照跑(CI 02) | 笔记本 `object_pressed(&"notebook")` 路由;单元侧 `open_career()` | 通过 |
| 契约 1/8/9 落码 | `WINDOW_SIZE := Vector2(720, 640)` 单点常量(camp_sub_view_base.gd:11,career 经类常量引用——grep 全库禁二处字面值成立);窗板 `panel_skinned(Vector4(14,12,14,12))` 石板皮;生涯内容板 BG_BRIGHT+顶行墨 INK_TITLE 订正(camp_sub_view_base.gd/career_overlay.gd diff 逐行核) | — | 通过 |
| 合同表零改动(红线 1) | `git diff master...iter49 -- game/presentation/ui_registry.gd`:**LAYER_CONTRACT 数据块零行变更**(diff 仅头注、flow 字段、register_layer 迁驻、node() 十二键、apply_layer_contract 三调用点) | — | 通过 |
尾缀〔窗口化批 V1–V8〕grep 到(V1 :305/336/342;V2 :345/348;V3 :352/356;V4 :324/329/451/464;V5 :363/369/381;V6 :389/394/396;V7 :401/415/419;V8 :426/430/435/437/444)。
---
## 二、抽查跑批读数(本审计自跑,工作目录 D:\code\g-plan2-iter49\game,不采信报告「已全绿」)
**a) effect_port_test**:`…console.exe --headless --path . --script res://tests/unit/battle_settlement/effect_port_test.gd`
```
[PASS] V1 端口单实例(两业务类持同一 EffectPort)
[PASS] V1 delta 读数非零(蓄力层加算进入主角攻击基值)
[PASS] V2 全文零引擎直连 token(EffectEngine/EffectContext):res://core/damage_controller.gd
[PASS] V2 全文零引擎直连 token(EffectEngine/EffectContext):res://core/action_economy.gd
[PASS] V3 阳性对照:hp_ratio 载荷 when 通过——承伤减量恰 1(10→9)
[PASS] V3 阴性对照:battle_index 不答——零减量(10→10,事实面未扩)
[effect_port_test] all green (15 checks)
EXIT=0
```
15 检查全 PASS、退出 0——与期望一致。
**b) screen_flow_probe**:`…console.exe --headless --path . res://probe/screen_flow_probe.tscn`
```
[screen_flow_probe] PASS — 六步主流程+回退路径全绿(屏级互斥:任意时刻 ≤1 屏可见)
EXIT=0
SCRIPT ERROR 计数=0(全日志 grep)
```
winshell 段执行证明:该段在 `_ready` 固定序列 :31 无条件 await(Esc 段之后、选档段之前);探针机制=problems 空才打 PASS、非空打 FAIL 并逐行打印——winshell 段任一断言失败或前置早退都会以〔窗口化批 Vn〕标记行现形。PASS+退出 0+零 SCRIPT ERROR ⇒ V1–V8 全部真实执行且零红。
**c) ui_struct_probe**:`…console.exe --headless --path . res://probe/ui_struct_probe.tscn`
```
[ui_struct_probe] PASS — 全屏结构断言零红
EXIT=0
SCRIPT ERROR 计数=0
```
`_modal_registry_contract` 于 :33 无条件调用;同机制证 V1a/V1b/V1c 三判据全执行零红。
**CI 回执**(`game/tests/.gates/receipt.json`):commit_short=1f0a8bd3、timestamp=2026-11-02T07:23:41+08:00、domain=code、scope=full、quick_mode=false、`all_green=true`——00 冒烟/01 系统测试/02 单元与集成/03 场景探针/05 渲染闸/09 静态扫描/10 熵增闸 七闸全 exit 0 green。
---
## 三、测试削弱核对(申报 ↔ diff 逐行)
| 文件 | 卡申报 | diff 实况 | 状态 |
|---|---|---|---|
| variant_placement_test.gd | 卡① 只申报白盒指址换代(判据零删改零放宽) | 18 行增删全为 `eco.*`→`eco.roller.*`/`woc._reward_economy.*`→`…roller.*`,判据文本与阈值逐字同(含 wr10② Callable 同一性比较、wr10③ 权重面),实测 18 行 22 处与报告登记一致(卡载「约 17 行 21 处」为写卡估数、T0 实数登记条款覆盖) | 通过 |
| theme_projection_test.gd | 卡② 申报 :719 期望串+寻址字面 | 唯一改动=:719 期望串 `ui.modals.debug_overlay.`→`ui.modals.menu.debug_overlay.`,判据语义不变 | 通过 |
| system_test.gd/smoke_boot.gd/pacing_queue_test.gd | 卡② 申报寻址字面换代 | 全部为 `modals.X`→`modals.run./menu.X` 二段式,check 文本逐字同 | 通过 |
| 探针 12 件(fx_shot/layout/probe_ui_util/screen_flow/shot/t17_defer/ui_click/ui_input/ui_probe/ui_struct/ui_tune) | 卡② 申报寻址换代+ui_struct 新段;卡③ 申报 screen_flow 纯增段 | 全探针 diff 删除行中断言类仅 5 行,逐行有 1:1 新增对应(判据文本同、仅址字面换);新增段为纯增面 | 通过 |
| 卡③ 其余测试面 | 申报零删改零放宽 | 未发现任何删断言/放宽阈值/缩小扫描面/换下层直调 | 通过 |
**未申报削弱:零。** 全 diff 删除行另核:reward_economy 侧退役的 4 assert+1 fatal 守卫全数逐字承接于 reward_roller.gd(:119/:150/:184/:194/:200,weighted_pick 改名选行算子为卡① 白名单 #5 授权),零守卫丢失。
---
## 四、内部字段直查受控例外与单点核对
- effect_port_test.gd:62-66 端口同一性直查 `orch_c.fx_host().damage._port`/`orch_c.action_economy._port`——行旁注释载理由(端口同一性无公开查询面);卡① 对照表行 1 与实现报告卡① R1 行均注明同一理由。**例外成立**。
- 单向接线:effect_port.gd 零 BattleFxHost 对象引用(仅头注纪律声明两处,非代码引用);battle_fx_host.gd :54-63 端口组建后 bind_port 转注两业务类、端口不落 host 成员——与卡契约 4 一致。
- damage_controller.gd/action_economy.gd 全文零 `EffectEngine`/`EffectContext` token(grep 0 命中;V2 断言当轮 PASS 双证)。
- 卡③ 合同表零改动:见 §一卡③ 末行——LAYER_CONTRACT 数据块 diff 零行变更。
---
## 五、实现决定记录复核(报告 §四 五项,均有等价论证与撤销方式)
| 决定 | 复核 | 状态 |
|---|---|---|
| 1 int(null) 构造拒→`or 0`/`or false` | 卡内 `int(…)/bool(…)` 包裹写法在本引擎(4.7.2)不可行;合法值域(非负 int/bool)上与缺省 0/false 逐位等价;V1-V3+全量闸承载 | 通过(已备案) |
| 2 字符串 Callable→方法直引用 | source_guard_test V8 闸约束(产品码字符串 Callable 零命中);与既有 bundle 接线同型 | 通过 |
| 3 roll() 局部变量内联收敛 | gdstyle 预算约束;取号序与次数零变化由 round_flow 逐位回放主证 | 通过 |
| 4 career 标签 autowrap+横向 EXPAND_FILL | 窗几何契约(720×640 不随内容涨)的伴随适配;V8 钉窗板 rect 兜底 | 通过 |
| 5 V6/V8 前置经真实钮清窗 | 测试时序修正(真实 UI 不可达态不测);V6/V8 断言本体与判据零改 | 通过 |
其余按卡执行(报告 §四 第 6 项「零超卡裁断」与本审计 diff 核对结论一致)。
---
## 六、总结论
**通过=可合并。**
- 缺漏:**0**。
- 例外:**1**——卡① 断言消息未带批名全称尾缀〔效果端口与掷格分件批 Vn〕(V1/V2/V3 编号前缀 15/15 全带;批名全称在文件头注与 run_all.gd manifest 在案)。依据=卡① §11 白名单第 8 条「断言消息文案——非契约面」;验收实质(测试存在/真实入口/当轮执行全绿/判据绑定面/零削弱)全部成立,不阻合并。合并门如需三卡尾缀形态严格统一,归一行字面修复批另行走批,不属本批缺漏。
@@ -1,314 +0,0 @@
# 需求卡片 · 效果端口与掷格分件批(v1.1)
> **版本**:v1.1(2026-11-02)——godot-master 终审阻断三处+建议五处全折入(裁决=修后即可开工);grilling 三轮在案、零待裁点。
> **用途**:迭代实现批的实施合同。战斗域结构深拆第二波(轴戊):效果发射端口件+掷格件两新件建件,业务类零引擎直连、受理账面留守。**行为零变化结构重构**——游戏可观测行为逐位不变。
> **来源**:待办清单「战斗域结构深拆批——效果发射端口+掷格/受理分件(2026-10-31 重立,来源=批次移交)」条目(状态=文档设计已闭合→已写卡)。
> **唯一事实源**:`design/engineering/architecture/architecture.md` v1.29「战斗编排域拆件定稿」节**轴戊两件**条款(2026-11-02 用户裁甲案设计闭合;职责语句/账面归属/衔接面/行为零变化红线全在案)。与待办清单条目实况凭据一致。
> **改动面**:游戏代码。 **估时**:≈2.63 个工作日(T0 0.25–0.5/T1 0.5–1/T2 0.5–1/T3 0.25–0.5/T4 0.25–0.5,中值合计 2.625)。
---
## 1. 目标与完成定义
**做什么**:按 architecture v1.29 轴戊建两件——
| 新件 | 职责语句(轴戊原文) | 承接 |
|---|---|---|
| **效果端口件**(EffectPort,`game/core/effect_port.gd`) | 战斗业务类唯一的效果发射出口:收事件与载荷、交效果引擎结算、取回命中批 | DamageController/ActionEconomy 各持端口引用(同一实例、组装期注入);EffectEngine/EffectContext 引用与计数器账面(value_counter 层值读后清零)收归宿主侧(BattleFxHost 域);facts 取值束与入站回调束随发射契约归宿主侧注入面;单实现零接口抽象 |
| **掷格件**(RewardRoller,`game/core/reward_roller.gd`) | 装配期格面资源摇号:池行装配、区间行 roll、权重合成(偏运硬币/board_skew 两路投影) | 自 RewardEconomy 迁出掷格面;受理账面(grant/身份查询/快照/retire/polarity_row)留守 RewardEconomy;衔接面=格→奖励身份映射(掷格件产出、受理件接收);经注入 RngServiceCore 取号(roll_board 流 scope=每次 install 批不变、取号序零漂移) |
**什么状态算完**:
1. 两新件在库、按本卡接口块落名;两宿主类与编排域改址全落;
2. **行为零变化**:既有 EV 锚与全战斗事件流逐位回放(round_flow 套件)、board_gen_reward_test 摇号受理面、variant_placement_test 指址换代后全绿——同种子逐位零漂移;
3. 结构断言全绿:端口单实例、业务类源文件零引擎直连 token、伤害域事实面闭集(新增 effect_port_test 三函数);
4. 存量触面 S13 键账只降不升:reward_economy 类变量 15→11、damage_controller 15→12、action_economy 11→10、battle_fx_host 14→15(贴顶 ≤15)、battle_orchestrator 15→15 持平;
5. 代码域闸全绿+产出物两份齐(实现报告/反哺点清单)+独立验收审计通过。
## 2. 设计事实源
`design/engineering/architecture/architecture.md` v1.29(2026-11-02)「战斗编排域拆件定稿」节**轴戊两件**条——两件职责语句、EffectEngine/EffectContext 引用与计数器账面归宿主侧(BattleFxHost 域)、facts 取值束(dig_streak/charge_layers/rider_tier_*)与入站回调束(reveal/ac)随发射契约归宿主侧注入面、端口单实现零接口抽象、端口持 BattleFxHost 引用或经注入 Callable 卡内定(跨件单向接线条款适用,禁双向强引用)、掷格件经注入 RngServiceCore 取号(roll_board 流 scope 与取号序零漂移);同节**「验收红线」全款**(命中序=声明序、明细行协议词表零触碰、`_ineffective_row` 载荷 deferred 自描述键观测面不回退、EV/MC 锚同种子逐位零漂移、S13 预算随卡三查、RewardEconomy 类变量只降不升、S7 B1 域文件集随批增行)与**「跨件单向接线」**「S13 键账收敛义务」「S7/S8 随动」各条。判据权威=`design/engineering/code-conventions.md` §1.1 拆分判据(拆分边界纪律)。
## 3. 现状事实(代码级,开工自行复核)
| # | 事实 | 出处 |
|---|---|---|
| F1 | damage_controller 直持引擎:`_fx`/`_ctx` 成员;`set_fx(fx, ctx)` 注入口;发射漏斗 `_fx_hits`(体内 `_fx.dispatch(_ctx, event, payload, _fx_fact)` 单点);五事件发射点=attack_commit(open_ticket 内)/armor_roll/clamp_check(主角攻击面+棋盘克制直伤面两处)/kill/damage_taken | damage_controller.gd:46-47、:73-75、:79-82(:82)、:173、:299、:318、:552、:422、:512 |
| F2 | damage 计数器账面直触:`EffectEngine.counter(_ctx,…)` 层值读、`EffectEngine.counter_add(_ctx,…)` 两处施加——value_counter 层值「疼痛记忆/弃图兑换/陷阱本能」读后清零语义 | damage_controller.gd:364、:370、:533 |
| F3 | damage 注入束:`inject` 4 键(dig_streak/charge_layers/rider_tier_bonus/rider_tier_crit;写点=编排器 begin_battle rider 复位两行+combat_segment 轮内写两行);`fx_calls` 2 键(reveal/ac;写点=编排器 begin_battle);`_fx_fact` 事实闭面(charge_layers/dig_streak/hp_ratio 三答,余 null);`_ineffective_row` 行载荷 deferred 自描述键(迭代 48 卡① 甲案观测面) | damage_controller.gd:53、:56、:89-98、:689-691;battle_orchestrator.gd:348-349、:343-344;combat_segment.gd:34、:37、:64 |
| F4 | action_economy 直持引擎:`_fx`/`_ctx`;`set_fx`;三发射点=dig_paid/dig_stop/charge_full;账面直触 `EffectEngine.counter_add` 三处 | action_economy.gd:41-42、:46-48、:120、:178、:205、:125、:128、:183 |
| F5 | reward_economy 15 类变量恰在阈值线上(:8-24 主体 13 枚+board_skew+_treasure_unlocked);掷格面(roll_board 三批取号、池行装配 `_pool_rows`/`_rollable_rows`、权重合成 `_biased_cell_rows`/`_skewed_cell_rows` 族、选行算子 weighted_pick)与受理账面(grant/grant_clear/query_identity/query_full_snapshot/retire_mapping/polarity_row/is_mapped/phase/快照 `_snapshot`/行查 `_row_by_id`)两职责同居一件 | reward_economy.gd:8-24、:192、:318、:35-75、:56-57、:61、:63、:68、:71、:203、:221、:304、:132、:147、:105、:120、:160、:174、:101、:96、:360、:353 |
| F6 | 偏运查询缝拆先例:economy `luck_bias_query` 单枚注入口(消费 :53-55)→ BattleFxHost `luck_bias_for` 查询口(三参形 dispatch);注入点在编排器 _init | reward_economy.gd:24、:53-55;battle_fx_host.gd:61-66;battle_orchestrator.gd:231 |
| F7 | 接线现状:编排器 _init 内 `set_fx` 双注+luck_bias 注入;begin_battle 内 fx_calls 写两行+rider 复位两行;combat_segment 轮内 inject 写读三行 | battle_orchestrator.gd:229-231、:343-344、:348-349;combat_segment.gd:34、:37、:64 |
| F8 | economy 消费面(全受理域):BoardInstaller(roll_board 调用+board_skew 写两处)、RewardGrant(query_full_snapshot/polarity_row/grant_clear)、GrantSegment(grant ×3+query_full_snapshot)、BattleRefreshFlow(retire_mapping)、编排器(query_full_snapshot/polarity_row/set_treasure_unlocked 转发/retire_mapping ×2/query_identity/phase)、board_view(query_identity 只读回调,组合根注入) | board_installer.gd:65、:80、:86;reward_grant.gd:73、:190、:389;grant_segment.gd:347、:393、:426、:440;battle_refresh_flow.gd:38;battle_orchestrator.gd:437、:461、:501-502、:583、:630、:726、:745 |
| F9 | 事实词汇封闭(引擎 FACTS 19 项)与取值序(payload 同名字段优先→facts 回调);宿主事实链现状=charge_layers 自答+facts_cb 转宿主五事实(nest_count/round_index/battle_index/seals_count/hp_ratio);伤害侧发射事实闭面=damage `_fx_fact` 三答 | effect_engine.gd:58-62、:365-377;battle_fx_host.gd:168-171;battle_orchestrator.gd:114-133;damage_controller.gd:89-98 |
| F10 | 🔴 posture_bulwark 树规则现行形态:on=damage_taken、when battle_index==1 且 round_index==1;伤害侧发射的事实回调不答 battle_index/round_index → when 恒不通过=**现行行为是「每关首轮承伤不加盾不触发」**;事实面若扩成宿主全链(答 battle_index)该行即翻活=行为变化 | effect_engine.gd:150-155(_push_tree_rule posture_bulwark);damage_controller.gd:89-98 |
| F11 | 经济域三事件(dig_paid/dig_stop/charge_full)订阅行 when 词汇实测:feats/treasure 两表全部订阅行 when ∈ {counter}∪∅,ap_left/ap_cost 均载荷携带;skills.tres/status_effects.tres 零 triggers;树规则合成行六键订阅面=round_start/damage_taken/mine_hit(无经济域三事件)——订阅行全域与 facts 回调无交集,统一闭面对经济域发射无观测差 | feats.tres/treasure_items.tres/skills.tres/status_effects.tres+effect_engine.gd:147-161(2026-11-02 写卡段全量实测) |
| F12 | 测试与工具消费面:damage_controller_test 41 检查(夹具直构四参、不接 fx——零扰动路径);round_flow_skill_pool_test 100 检查(EV 锚+全战斗事件流逐位回放 ×2 关);roll_multiplier_test 42;variant_placement_test 43 检查(economy 直构+board_skew 写+luck_bias_query 断言+economy 内部符号族白盒指址——_rollable_rows/_pool_weight/_biased_cell_rows/board_skew/luck_bias_query 约 17 行 21 处);board_gen_reward_test(economy 直构+受理面全 API);seal_polarity_test/refresh_feats_test(受理面);minesweeper_rules_test(A3 直构单参);system_contracts_test(damage 直构四参);sim/reward_expectation(economy 直构+roll_board/is_mapped/query_identity) | damage_controller_test.gd:51-63;round_flow_skill_pool_test.gd(:60、:690-726 逐位);roll_multiplier_test.gd:245;variant_placement_test.gd:223-265(符号族全量、T0 实数登记);board_gen_reward_test.gd:86-121;seal_polarity_test.gd:362、:729-748;refresh_feats_test.gd:113、:473;minesweeper_rules_test.gd:35;system_contracts_test.gd:99;reward_expectation.gd:18-58 |
| F13 | gdstyle 基线无本批触面键:`tools/gdstyle_baseline.txt` 仅 5 键(adventure_runner/level_runner/board_view)——三宿主与新件零基线登记(无「迁移即拆函数」义务源);S13 判定=基线外新违规红 | tools/gdstyle_baseline.txt:9-13 |
| F14 | 静态扫描两清单现状 12 文件(S8 await 集=S7 B1 域文件集同款清单独立两处);B4 符号清单 9 符号含 weighted_pick | game/tests/static_scan.sh:317、:361、S7 符号交替式段 |
### 3.1 受影响既有断言面核查(逐面实测)
| 既有断言面 | 核查结论 |
|---|---|
| damage_controller_test(41 检查) | 夹具不接 fx(_fx=null 路径)→ 本卡签名不变(bind_port 单独注入)→ **零改动照跑** |
| round_flow_skill_pool_test(100 检查,EV 锚+逐位回放) | 全链真实流 → **零改动照跑=行为零变化主证** |
| roll_multiplier_test(42 检查) | 消费 damage 公开面(clamped_pool/defender_ac)→ 零改动 |
| variant_placement_test(43 检查) | **economy 内部符号族全量白盒指址换代**(_rollable_rows/_pool_weight/_biased_cell_rows/board_skew/luck_bias_query → `eco.roller.*`,实测约 17 行 21 处、T0 实数登记)——判据零删改零放宽,申报为指址随件改写(非削弱,见 §9 申报表) |
| board_gen_reward_test/seal_polarity_test/refresh_feats_test/reward_expectation.gd | 全受理面(economy 保留 API、直构签名不变)→ 零改动照跑 |
| run_time_fatal_test | BoardInstaller 装配传 economy 引用(:75)+economy `_fatal` 直调(:83)——两触面均零变化 → 零改动照跑 |
| minesweeper_rules_test/system_contracts_test | A3/damage 直构签名不变 → 零改动 |
| adventure_feats_test :669-767 | 经 `fx_host().counters_ctx`/`fx_emit` 直发——host 公开面保留 → 零改动 |
## 4. 设计契约(违反即返工;标 🔴 触碰=L3 停机呈报)
1. 🔴 **行为零变化=本批最高契约**:RNG 消费序零漂移(roll_board 流 scope=每次 install 批不变、流开时点与取号序取号次数零变化;armor_roll/fx_reveal 流不动);命中序=声明序;明细行协议词表零触碰;`_ineffective_row` 载荷 deferred 自描述键观测面不回退;EV 锚同种子逐位一致。任何签名改动的观测面等价论证随对照表行在案。
2. 🔴 **业务发射事实面闭集**:经端口发射的事实回调=闭集**五键**——三 when 事实 {charge_layers, dig_streak, hp_ratio}(charge_layers=action_economy 现值活读、dig_streak=宿主侧轮内槽、hp_ratio=主角血量比例算式逐字)∪ 两 rider 运行态读数 {rider_tier_bonus, rider_tier_crit}(宿主 facts_inject 现值——redeem 两读经 `_fact_or` 路由的载体,行为与现行 inject 缺省逐位同),其余事实一律 null。battle_index/round_index/seals_count/nest_count **禁进**业务发射事实面——posture_bulwark 每关首轮窗在 damage_taken 的现行形态=事实未答不触发(F10),闭面守此现状(V3 阴性对照钉死);扩面=行为变化=L3。
3. 🔴 **业务类零引擎直连零账面触碰**:damage_controller/action_economy 两文件禁出现 EffectEngine/EffectContext 引用与计数器静态调用;账面唯一宿主侧(counters_ctx 归 BattleFxHost),业务类读写经端口路由。
4. 🔴 **跨件单向接线**:端口经注入 Callable 路由宿主,**禁持 BattleFxHost 对象引用**(宿主 bundle 已持两业务类——对象引用即成 host→damage→port→host 强引用环,两件均随每战新建=泄漏);掷格件零回指 economy(fatal 经构造注入 Callable 链);注入 Callable 同单向纪律,禁为省参数改持对象引用。
5. **端口单实现零接口抽象**:无基类无多态(GDScript 无 interface,本案不需要——轴戊条款)。
6. **拆分边界纪律**(判据权威=code-conventions §1.1,卡内执行条款):①每个拆出单元有可陈述的职责语句与单一变化原因(两件职责语句见 §1,实现报告逐件一行承载);②拆出单元有集体身份——命不出名字、只能说「剩下的成员」的打包=凑计数袋,禁;③「过阈值」只许作为发现信号,作为拆分或收拢的动机即违规;④按纪律拆不出内聚单元 → 停卡呈报走豁免/还债通道,禁硬拆凑绿。
7. **S13 键账**:两新件零基线外新键(默认阈值内);存量触面只降不升(§14 预算表);禁为迎合机检文本保留或新增无效成员/别名——机检键与卡片契约互斥时实现段一律停卡呈报,不得自造第三条路。
8. **数值纪律**:零数值改动(`data/tables/` 零触碰);无数值改动=零 MC——禁新跑 MC 批,行为零变化验收只用既有同种子锚与逐位对拍。
9. **RNG 单点/Core 零 UI/fail-fast** 不因新增而绕:掷格件随机只经注入 RngServiceCore;两新件 RefCounted 纯逻辑零 UI;违约 fatal 通道沿 economy 现形(push_error+fatal_handler+assert)。
## 5. 范围边界
**做什么**:两新件建件、两业务类与宿主域换线、编排域与装板域改址、受影响测试指址换代、新增 effect_port_test、闸清单随动(static_scan.sh 三处)、README 能力行增行(已随本卡提交)。
**不做什么(明示不收件)**:
- 零行为改动:任何结算算序/取值/行词表/信号顺序改动一律不属本批(发现必要=上游设计缺陷,停卡呈报)。
- BattleFxHost/RewardGrant 现有公开面不动(luck_bias_for/flush_pending_reveals/apply_ac_bonus/enqueue_reveal 原样——端口路由它们的既有方法)。
- reward_grant/grant_segment 现存 `EffectEngine.counter_*(fx_host.counters_ctx,…)` 直触**不在本批收编**(轴戊点名面=DamageController/ActionEconomy 两业务类;授予件账面触面归后续批次,去向=待办清单本条实现批后按实况判断是否留尾)。
- posture_bulwark 现行「不触发」形态是守卫对象不是缺陷——改它属行为变化,另走设计段。
- posture_first_strike 等宿主侧事件事实链(fx_emit 全链)零触碰。
- 文档面(architecture.md 换代注记/术语表)零直改——反哺点清单交付(§6)。
## 6. 关联文档同步面
| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 |
|---|---|---|
| design/engineering/architecture/architecture.md | 「战斗编排域拆件定稿」节轴戊两条与功能层 B4 行/BattleFxHost 行/damage_controller 行:「实现批建件」待建注记换代为已建件现状(文件名、公开面、账面归属、facts_inject 注入面、S7/S8 增行实况);B4 行对外暴露 9 符号中 weighted_pick 迁属掷格件(改造为返行选行算子) | 列反哺点清单由文档批落文(architecture.md 的已建件换代注记归收尾反哺) |
| design/gdd/术语表.md | 「效果端口件」「掷格件」两机制名是否登记(首现定义在 architecture v1.29) | 列反哺点清单由文档批落文(登记与否由文档批裁决) |
(`game/tests/README.md` 能力行=写卡段义务,已随本卡提交维护,不属实现批同步面;`game/tests/static_scan.sh` 清单字面值随动见 §7/T1/T2——工程随动,非文档。)
## 7. 卡前文件结构图
| 文件 | 新增/复用 | 职责 | 行为改动标注 |
|---|---|---|---|
| game/core/effect_port.gd | **新增** | 效果端口件:业务类唯一发射出口窄门面(六 Callable 路由宿主) | 非行为改动(结构断言=对照表行 1-3) |
| game/core/reward_roller.gd | **新增** | 掷格件:装配期格面资源摇号(池行装配/区间行 roll/权重合成) | 非行为改动(对照表行 5-6) |
| game/core/battle_fx_host.gd | 修改 | +facts_inject 注入束、+fx_emit_biz/counter_read/counter_add/biz_fact 四法、_init 尾段端口组建与 bind_port 转注、头注换代 | 非行为改动(闭面守卫=行 3;账面路由=行 4) |
| game/core/damage_controller.gd | 修改 | _fx/_ctx/set_fx/inject/fx_calls/_fx_fact 退役;+_port/bind_port;五发射点与计数器三处、rider 两读、reveal/ac 两回调改端口路由;头注换代 | 非行为改动(行 1/2/4/8) |
| game/core/action_economy.gd | 修改 | _fx/_ctx/set_fx 退役;+_port/bind_port;三发射点与计数器三处改端口路由;头注换代 | 非行为改动(行 1/2/4/8) |
| game/core/reward_economy.gd | 修改 | 掷格面迁出(函数/常量/成员清单见 T2);roller 随件自建;fatal_handler 属性 setter 转注;roll_board 改装配序(守卫→复位→委托→收纳→ready);头注换代 | 非行为改动(行 5-6) |
| game/core/battle_orchestrator.gd | 修改 | 接线块换代:set_fx 两行/fx_calls 两行退役;rider 复位改 facts_inject;luck_bias 注入与 set_treasure_unlocked 改 roller 指址;头注指址换代 | 非行为改动(行 4/7) |
| game/core/board_installer.gd | 修改 | board_skew 写址两行改 roller(`reward_economy.roller.board_skew`) | 非行为改动(行 7) |
| game/core/settlement/combat_segment.gd | 修改 | dig_streak 写/读改 `oc.fx_host().facts_inject`;charge_layers 注入行退役(事实面活读) | 非行为改动(行 2/8) |
| game/tests/unit/battle_settlement/effect_port_test.gd | **新增** | 端口验收断言三函数(对照表行 1/2/3 载体) | 验收载体(行 1/2/3) |
| game/tests/run_all.gd | 修改 | manifest 登记 effect_port_test(expect 0)——套件可达性 | 非行为改动(行 9——闸 manifest 字面值随动) |
| game/tests/unit/battle_settlement/variant_placement_test.gd | 修改 | economy 内部符号族全量白盒指址换代(约 17 行 21 处,判据零删改零放宽) | 非行为改动(行 5/7,§9 申报) |
| game/tests/static_scan.sh | 修改 | S7_B1_SET 增 effect_port.gd+reward_roller.gd(T1/T2 各增一件——轴戊「S7/S8 随动」两新件全登);S8_FILES 增 effect_port.gd+reward_roller.gd;B4 符号清单 weighted_pick 行随符号退役删除 | 非行为改动(行 9——闸清单字面值随动,判断依据=闸清单与架构文档同批对齐、判据口径不变) |
| game/tests/README.md | 修改 | 能力行增行「效果发射端口单点」(**已随本卡提交**——写卡段义务) | 非行为改动(义务清单维护) |
(结构图与 §12 落位预检互指:两新增件均标「新增」,理由与唯一落点见 §12。)
## 8. 任务卡 T0..T4
### 8.1 T0——开工复核与读数(估时 0.25–0.5 个工作日)
**取用**:无(首卡)。 **产出**:复核结论与改前读数(实现报告读数节素材)。
- [ ] 逐条复核 §3 现状事实 F1-F14 的 file:line(五存量文件+combat_segment+五个测试件+sim 工具)——与卡不符处停该卡呈报(上游缺陷),禁内联求裁
- [ ] 记录改前 gdstyle/S13 读数:battle_orchestrator 15 类变量、battle_fx_host 14、damage_controller 15(公开方法 9)、action_economy 11、reward_economy 15(公开方法 12)——写实现报告读数节,改后对读(T3 步核只降不升)
- [ ] 拷主区 `.godot/` 目录与字体 `.import` 边车(涉代码域跑闸批环境准备)
### 8.2 T1——效果端口件与业务类换线(估时 0.5–1 个工作日)
**取用**:§3 现状(F1-F4/F7/F9/F10)。 **产出**:`effect_port.gd` 全量;BattleFxHost 端口组建面(后续卡经 `orch.fx_host()` 取用);damage/action_economy 端口路由调用面;effect_port_test 三函数。
- [ ] 新建 `game/core/effect_port.gd`,头注=`##` 模块文档注释(端口职责+闭面红线+单向接线声明,零文档链接零变更叙事)。签名(全类型标注,S9 口径):
```gdscript
class_name EffectPort
extends RefCounted
var emit_cb: Callable # func(event: String, payload: Dictionary) -> Array——宿主 fx_emit_biz
var counter_read_cb: Callable # func(counter_id: String) -> int——宿主 counter_read
var counter_add_cb: Callable # func(counter_id: String, value: int, set_form: bool) -> void——宿主 counter_add
var fact_cb: Callable # func(name: String) -> Variant——宿主 biz_fact(伤害域闭面)
var reveal_cb: Callable # func() -> void——宿主 enqueue_reveal
var ac_cb: Callable # func(h: Dictionary) -> void——宿主 apply_ac_bonus
func _init(bundle: Dictionary) -> void
# 六键 ["emit_cb","counter_read_cb","counter_add_cb","fact_cb","reveal_cb","ac_cb"] 缺一 assert(引用束注入先例)
func emit(event: String, payload: Dictionary) -> Array # 未绑→[](零扰动缺省)
func counter_read(counter_id: String) -> int # 未绑→0
func counter_add(counter_id: String, value: int, set_form: bool) -> void # 未绑→no-op
func fact(name: String) -> Variant # 未绑→null
func reveal_effect() -> void # 未绑→no-op
func apply_ac(h: Dictionary) -> void # 未绑→no-op
```
- [ ] `battle_fx_host.gd`:增 `var facts_inject := {"dig_streak": 0, "rider_tier_bonus": 0, "rider_tier_crit": false}`(类变量 14→15,贴顶);增四法——`fx_emit_biz(event, payload) -> Array`(`engine.dispatch(counters_ctx, event, payload, _biz_fact)`)、`counter_read(counter_id) -> int`(`EffectEngine.counter(counters_ctx, counter_id)`)、`counter_add(counter_id, value, set_form) -> void`(`EffectEngine.counter_add(counters_ctx, …)`)、`biz_fact(name) -> Variant` 闭面五键(charge_layers→`action_economy.charge_layers`;dig_streak→`int(facts_inject["dig_streak"])`;hp_ratio→逐字承 damage_controller.gd:96-97 算式读 `damage.units.hero_unit()`;rider_tier_bonus→`int(facts_inject["rider_tier_bonus"])`;rider_tier_crit→`bool(facts_inject["rider_tier_crit"])`;余→null);`_init` 尾段=建 `EffectPort.new({六 Callable 绑 self 对应方法})` 后 `bundle.damage.bind_port(port)`+`bundle.action_economy.bind_port(port)`(端口不落 host 成员——单向接线,host 零回持);头注换代(封闭面 14→15、端口组建与转注、facts_inject 键集封闭声明)
- [ ] `damage_controller.gd`:删 `_fx`/`_ctx`/`set_fx`/`inject`/`fx_calls`/`_fx_fact`;增 `var _port: EffectPort`(**可空成员,缺省 null=未绑**——与原 `_fx == null` 零扰动同语义;不用成员初始化器建端口——`_init(bundle)` 必传参,无参可建不成立)与 `func bind_port(port: EffectPort) -> void`(组装期单点注入,BattleFxHost._init 调用);守卫写法:`_fx_hits` 漏斗体 `if _port == null: return []` 后 `return _port.emit(event, payload)`;未绑 fact 直读统一经私有 `_fact_or(name: String) -> Variant`(`return null if _port == null else _port.fact(name)`——调用点 `int(…)`/`bool(…)` 包裹,`int(null)=0`/`bool(null)=false` 与现行 inject 缺省值逐位同);计数器三处(:364/:370/:533)改 `_port.counter_read(…)`/`_port.counter_add(…)`(均在 hits 非空循环内——`_port` 已由漏斗守卫保证非空);open_ticket dig_streak 载荷键与 `_per_value` 回落、redeem rider 两读(:400/:408)改 `_fact_or` 路由;kill 揭示回调与 damage_taken ac 回调改 `_port.reveal_effect()`/`_port.apply_ac(h)`(均在 hits 非空分支内);头注换代(**头注含注释全域零 `EffectEngine`/`EffectContext` 英文类名 token**——V2 源码锚扫描面为全文)
- [ ] `action_economy.gd`:删 `_fx`/`_ctx`/`set_fx`;增 `var _port: EffectPort`(可空,同上语义)与 `bind_port`;三发射点(:120/:178/:205)外层守卫原位换写 `if _port != null:`(原 `if _fx != null`),体内改 `_port.emit(…)`;计数器三处(:125/:128/:183)改 `_port.counter_add(…)`(守卫外层已保证);头注换代(同零 token 口径)
- [ ] `battle_orchestrator.gd`::229-230 set_fx 两行与 :343-344 fx_calls 两行删除(host._init 组装期接线取代,先于任何发射——时序等价论证见 §12);:348-349 rider 复位改 `_fx_host.facts_inject["rider_tier_bonus"] = 0`/`["rider_tier_crit"] = false`;头注发射点指址换代(词表不动,指址须真)
- [ ] `combat_segment.gd`::34 改 `oc.fx_host().facts_inject["dig_streak"] = 0 if round_mine else round_safe`;:37 charge_layers 注入行删除(活读等价论证=唯一写点时序:finish_round_stop 于上轮授予段尾写→:37 拷贝点→本轮授予段 :197 发射前无第二写点;ActionEconomy 随战新建〔编排器 :214〕首战活读恒 0=旧缺省——同种子逐位回放为等价证明载体);:64 改读 `int(oc.fx_host().facts_inject["dig_streak"])`
- [ ] `static_scan.sh`:S7_B1_SET 与 S8_FILES 两清单各增 `game/core/effect_port.gd`
- [ ] 新建 `game/tests/unit/battle_settlement/effect_port_test.gd`(extends SceneTree+Kit 收口样板,三函数):
- `_smoke_effect_port_wiring`〔效果端口与掷格分件批 V1〕:真实 `BattleOrchestrator.new(db, rng)` 装配链——①断言 `damage._port` 与 `action_economy._port` 同一实例(内部字段直查=受控例外,对照表行 1 注明理由:端口同一性无公开查询面);②attack_commit 经真实战斗流(begin_battle+自动玩家最小回合)取回命中批可观测——期望输出=命中批非空且订阅 attack_commit 的专长行命中效果在事件流载荷可见(订阅锚=整备军备 attack_bonus per charge_layers 族,F3 载荷键在案;断言读数面=事件流该行 delta 读数非零);
- `_test_business_classes_engine_free`〔效果端口与掷格分件批 V2〕:源码契约锚(theme_projection_test 源码锚惯例)——读两业务文件全文,断言零 `EffectEngine`/`EffectContext` token(扫描面>0 前置:两文件读出非空字数);
- `_test_biz_fact_face_closed`〔效果端口与掷格分件批 V3〕:begin_battle 后直改 `db.crossrun.feats.rows` 追加两条合成行(调试注入两层·数据面粒度:行键 feat_id+triggers,on=damage_taken;effect 段 kind/value 逐字抄现役铁壁 shield per 表行——行构造零推表;rebuild 走持有 id 过滤真实表行——合成行经直改表行进入装载域)→ `rebuild_subscriptions([两条合成 feat_id], [], [])`(订阅面换代为合成行独占,确定性)→ 真实 `flush_submit` board_flat_hero 单据(base_value 足量避开伤害下限保底,shield 减量可观测):合成行 (a) when hp_ratio lte 100(载荷携带恒真——阳性对照,证 harness 能见命中)→ 断言承伤减量恰 1;合成行 (b) when battle_index eq 1 → 同路径断言零减量(闭面——F10 现状形态守卫)
- [ ] `run_all.gd` manifest 登记 effect_port_test(expect 0)
- [ ] 孤立验证:先跑 `--editor --quit` 刷新全局类名缓存(新 class_name 两枚——`--headless --script` 模式解析在册坑),再 effect_port_test 单套直跑绿(新断言先行,禁以全套闸首跑充当首验)
### 8.3 T2——掷格件与 economy 收纳(估时 0.5–1 个工作日)
**取用**:T1 产出无交叉依赖(奖励域与端口域独立);§3 F5/F6/F8。 **产出**:`reward_roller.gd` 全量;economy 收纳后形态;装板域与编排域改址。
- [ ] 新建 `game/core/reward_roller.gd`,头注=`##` 模块文档注释(掷格职责语句+取号流声明+零回指声明)。签名:
```gdscript
class_name RewardRoller
extends RefCounted
var db: ConfigDb
var rng: RngServiceCore
var fatal_cb: Callable = Callable() # 协作件违约→宿主 fatal 封印(BoardInstaller 先例)
var luck_bias_query: Callable = Callable() # 偏运合计查询口(缝拆形态随件迁移)
var board_skew: int = 0 # 图级偏斜旋钮(写点=BoardInstaller 装板决议)
var _treasure_unlocked := {}
func _init(bundle: Dictionary) -> void # ["db","rng","fatal_cb"] 缺一 assert
func roll(eligible: Array) -> Dictionary[Variant, Variant]
# 批束键集封闭:{"mapping": Dictionary(cell→reward_id 行主序插入序),
# "power_roll": Dictionary(cell→int), "clear_identity": String, "clear_power": int}
# 体序=normalize(行主序+去重,零 RNG)→ 开 reward_roll 流(恰一 scope 批)→ luck_bias 查询
# → 池行装配(_biased_cell_rows/_pool_rows)→ 身份批逐格取号 → 清图批尾 → 区间行追加取号
# ——取号序与取号次数零变化(逐字承 reward_economy.gd:43-74 流程体)
func set_treasure_unlocked(ids: Dictionary) -> void
# 迁入:_normalize_eligible/_biased_cell_rows/_skewed_cell_rows/_skew_families/_apply_skew/
# drops_total/_largest_remainder_split(static)/_rollable_rows/_pool_rows/_pool_weight
# 与常量 LUCK_BIAS_KINDS/SKEW_DOWN_KINDS/SKEW_UP_KINDS(逐字迁移)
# 改造:_weighted_pick_row(rows, r) -> Dictionary——weighted_pick 算术逐字(acc 累加/断言/fatal
# 通道),返回值由 reward_id 换为表行,调用侧取 row.reward_id;取号算术与次数零变化
```
- [ ] `reward_economy.gd` 收纳:增 `var roller: RewardRoller`(_init 内自建自接线——`roller = RewardRoller.new({"db": db_ref, "rng": rng_ref, "fatal_cb": fatal_handler})`,BoardInstaller.generator 先例);`fatal_handler` 改属性 setter(赋值同拍转注——`set(v): fatal_handler = v; if roller != null: roller.fatal_cb = v`,构造序防:economy._init 不触该成员、编排器 :220 注入晚于 _init);`roll_board(eligible)` 保留签名改装配序=相位守卫(E5,先行——违约路径零取号不变)→ 空清单 fatal(E1)→ 受理面复位五拍(逐字)→ `var batch := roller.roll(eligible)` → 收纳 `_mapping = batch.mapping`/`_power_roll = batch.power_roll`/`_clear_identity = batch.clear_identity`/`_clear_power = batch.clear_power` → `_phase = "ready"`;退役清单=rng/_eligible/luck_bias_query/board_skew/_treasure_unlocked 五成员+set_treasure_unlocked/weighted_pick/drops_total/_pool_weight/_pool_rows/_rollable_rows/_normalize_eligible/_biased_cell_rows/_skewed_cell_rows/_skew_families/_apply_skew/_largest_remainder_split 十二函数+三常量(类变量 15→11、公开方法 12→9);保留面=_phase/_mapping/_power_roll/_clear_power/_granted/_clear_identity/_clear_granted/_clear_snapshot/is_mapped/query_identity/query_full_snapshot/grant/grant_clear/retire_mapping/polarity_row/phase/_row_by_id/_snapshot/_diag/_fatal;头注换代(两职责分家声明+衔接面批束键集)
- [ ] `battle_orchestrator.gd`::231 改 `_reward_economy.roller.luck_bias_query = _fx_host.luck_bias_for`;:501-502 `set_treasure_unlocked` 内部改 `_reward_economy.roller.set_treasure_unlocked(ids)`(编排器公开面不动——level_runner :522 零改址)
- [ ] `board_installer.gd`::80/:86 两行改 `reward_economy.roller.board_skew = …`(写时序在 roll_board 前——不变)
- [ ] `variant_placement_test.gd` economy 内部符号族全量指址换代:_rollable_rows/_pool_weight/_biased_cell_rows/board_skew/luck_bias_query 五符号全仓消费行改 `eco.roller.…`(:224/:225/:227-242/:228/:231/:232/:238/:240/:243/:244/:259/:260/:262/:264-265,约 17 行 21 处、T0 实数登记)——判据零删改零放宽
- [ ] `static_scan.sh`:S7_B1_SET 增 `game/core/reward_roller.gd`(轴戊 S7/S8 随动——两新件全登);S8_FILES 增 `game/core/reward_roller.gd`;S7 B4 符号清单 weighted_pick 行随符号退役删除(注释同步——符号全库零调用后清单与架构文档对齐)
- [ ] 孤立验证:board_gen_reward_test+variant_placement_test 单套直跑绿
### 8.4 T3——受影响面窄测与逐位主证(估时 0.25–0.5 个工作日)
**取用**:T1/T2 产出。 **产出**:触碰面套件全绿记录+S13 改后对读数。
- [ ] 本批触碰面套件跑绿(卡内只测自己改的——选择依据=§3.1 受影响面并集):effect_port_test/board_gen_reward_test/variant_placement_test/round_flow_skill_pool_test(EV 锚+事件流逐位=行为零变化主证)/damage_controller_test/refresh_feats_test(计数器行为与受理链)/seal_polarity_test(受理面+reward_ineffective 观测面)/minesweeper_rules_test(A3 dig 路径端口换线)/settle_segments_test(段件链)/run_time_fatal_test(装板装配与 economy fatal 通道)/effect_words_t1_test(词表接线——R4 点名)/adventure_feats_test(fx_host 直发面——R4 点名)/roll_multiplier_test(damage 公开面消费)/system_contracts_test(damage 直构签名)
- [ ] 改后 gdstyle 读数对照:五存量文件 S13 键较 T0 读数只降不升(reward_economy 15→11、damage 15→12、action_economy 11→10、battle_fx_host 14→15、orchestrator 15→15 持平)——超预期即停卡呈报
- [ ] 里程碑步(T3)出口跑一次代码域闸(按本批改动域选档);波内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套
### 8.5 T4——产出物落位卡(估时 0.25–0.5 个工作日)
**取用**:T0-T3 全部记录。 **产出**:reports/ 两份+审计。
- [ ] `reports/iter<N>-实现报告-<日期>.md`:各卡状态+改前改后 S13 读数对照+实机目检总清单(本批行为零变化、无玩家可见面——**零新增目检项声明**)+实现决定记录(超白名单事项逐条记「决了什么/为什么/代价/撤销方式」,全部按卡执行则写一行「零拍板」)
- [ ] `reports/iter<N>-反哺点清单-<日期>.md`:§6 同步面逐条落点(architecture.md 轴戊换代注记与 B4 行符号换代;术语表登记裁决)——每条写清哪个文件哪一节、改成什么、依据是什么
- [ ] 独立验收审计:未参与实现的会话或子代理执行,报告落 `reports/iter<N>-验收审计-<日期>.md`——逐行核对对照表(断言存在/真执行/尾缀可 grep/真实入口未绕改动点)、抽查判据绑定面、核对测试削弱申报与内部字段直查受控例外;**未过不得合并**
- [ ] 轻闸全绿后、合并前收口核对:能力清单行名与实际落地测试名一致(改名则回表)
- [ ] 产出物落位:两份报告+审计报告只落 `reports/`(实现批禁写 `design/` 与根规则文件、`game/tests/README.md`)
## 9. 验证闸(改动—验收对照表)
测试方式两分法:本批结构断言全部走自动化载体(单元套件+源码契约锚);**用户目检项=零新增**(行为零变化、无新玩家可见面——登记义务以本句声明了结,不阻塞)。断言尾缀统一〔效果端口与掷格分件批 Vn〕。措辞纪律:里程碑步出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套;全量验证归合回后本地 CI。
| 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|---|---|---|---|---|---|---|
| R1 端口单实例与真实发射路由 | effect_port.gd 新件;battle_fx_host.gd _init 尾段组建与 bind_port;damage_controller.gd:79-82 漏斗改路由 | effect_port_test.gd:`_smoke_effect_port_wiring`〔效果端口与掷格分件批 V1〕:装配后 `damage._port == action_economy._port`;attack_commit 经真实回合命中可观测 | 单元 | `BattleOrchestrator.new()` 装配链+`begin_battle()` 真实战斗流 | 端口引用同一性+真实结算流命中效果(事件流/明细行可见)。内部字段直查受控例外:端口同一性无公开查询面,对照表本行注明理由 | 新增:效果发射端口单点 |
| R2 业务类零引擎直连零账面触碰 | damage_controller.gd(_fx/_ctx/inject/fx_calls/_fx_fact 退役)、action_economy.gd(_fx/_ctx/set_fx 退役)、两业务类计数器读写共六处改端口路由 | effect_port_test.gd:`_test_business_classes_engine_free`〔效果端口与掷格分件批 V2〕:两业务文件全文零 `EffectEngine`/`EffectContext` token(扫描面>0 前置) | 单元(源码契约锚) | 测试直读两业务文件源码(源码锚惯例) | 源码 token 面(直连/账面触碰的唯一机械可判面) | 新增:效果发射端口单点 |
| R3 伤害域事实面闭集 | battle_fx_host.gd fx_emit_biz/biz_fact 闭面;combat_segment.gd:34/:37/:64 注入改址与退役 | effect_port_test.gd:`_test_biz_fact_face_closed`〔效果端口与掷格分件批 V3〕:合成行 (a) hp_ratio 载荷 when → 承伤减量恰 1(阳性对照);(b) battle_index when → 零减量 | 单元 | `DamageController.flush_submit()` 真实单据流(board_flat_hero 承伤路径) | when 判定命中面(shield 是否入交付减量)——F10 现状形态的特有提交面 | 新增:效果发射端口单点 |
| R4 端口接线时序与入站路由等价 | battle_orchestrator.gd:229-230/:343-344 退役、:348-349 改 facts_inject;reveal/ac 回调组装期绑定(先于任何发射——发射点全部在 begin_battle 之后,接线提前不可观测) | 既有套件照跑:refresh_feats_test(计数器施加行为 test_reserve_on_accepted_dig 等)、effect_words_t1_test(词表接线)、adventure_feats_test(fx_host 直发面) | 单元 | `MinesweeperRules.settle_batch()`/`BattleOrchestrator.begin_battle()` 真实玩法路径 | 计数器桶值与事件流(既有断言原样执行即判据) | 既有:换图基座:挖格产 RAP 与刷新折扣;既有:换图系刷新链路与效果词表接线;既有:专长(奇物)授予与凭证保底 |
| R5 掷格件建件与摇号等价 | reward_roller.gd 新件(roll/选行算子改造/权重合成族迁入);reward_economy.gd:35-75 装配序换代 | 既有 board_gen_reward_test 照跑(roll_board 受理/双掷拒绝/五型封闭/清图批/受理幂等全 API);sim/reward_expectation.gd 静态核零改动(直构签名与受理 API 未变——无数值改动禁跑调参批量,不属当轮执行面) | 单元 | `BattleOrchestrator.begin_battle()`(install 链 roll_board 恰一次) | 摇号映射分布与受理面返回结构(既有断言原样执行即判据——判据不绑行号绑 API 行为) | 既有:同参数同种子逐位复现、异种子不退化;既有:装板与开局免费展开(封锁格无资源、计入清图) |
| R6 economy 收纳与键账只降不升 | reward_economy.gd 类变量 15→11、公开方法 12→9、掷格十二函数与三常量退役 | T3 读数步骤:改后 gdstyle 读数对照(只降不升)+既有 board_gen_reward_test/seal_polarity_test/refresh_feats_test 受理面照跑 | 单元+读数 | 既有受理 API 真实调用面 | 成员/函数计数(机检判据面)+受理行为逐位 | 既有:清图奖励双份与零路径 |
| R7 装板域与编排域改址 | board_installer.gd:80/:86、battle_orchestrator.gd:231/:501-502 改 roller 指址 | 既有 variant_placement_test 照跑(指址换代后 43 检查全绿——board_skew 投影/luck_bias 注入/白盒权重面判据原样) | 单元 | `BattleOrchestrator.begin_battle()`(全局变异决议→装板摇号链) | board_skew 投影行集与偏运注入回调同一性(既有断言原样执行即判据) | 既有:变异布置门控 |
| R8 行为零变化总证 | 全域(本批 diff 全部非行为改动——逐面等价论证见本表各行) | 既有 round_flow_skill_pool_test 照跑:EV 锚+全战斗事件流逐位回放 ×2 关(含 roll_board 取号序/armor_roll 流/命中序/明细行词表/_ineffective_row deferred 键观测面的链路覆盖) | 单元 | `BattleOrchestrator.begin_battle()` 全战斗回放 | 事件流 JSON 逐位等值(既有断言原样执行即判据) | 既有:轮内流与结算五段全序;既有:伤害单据编排与回放 |
| R9 闸清单随动与能力行维护 | static_scan.sh S7_B1_SET/S8_FILES/B4 符号清单三处;README 能力行增行(随卡提交);run_all.gd manifest 登记 | 代码域闸全绿(清单缺位自检通过=S7/S8 文件集存在性判据)+批末收尾核对能力行名与落地名一致 | 闸 | 静态扫描域闸(随代码域闸跑批执行) | 清单缺位判红面+manifest 套件可达性 | 新增:效果发射端口单点 |
**测试削弱申报**:本卡允许的旧断言改动=variant_placement_test **economy 内部符号族全量指址换代**(_rollable_rows/_pool_weight/_biased_cell_rows/board_skew/luck_bias_query → `eco.roller.*`,实测约 17 行 21 处、T0 实数登记——拆件随件改写,判据表达式与阈值零删改零放宽);此外零申报——实现期任何未申报的删断言/放宽阈值/缩小扫描面/换下层直调由独立验收审计判红。
## 10. 异常分级
- **L1 自救**:环境故障(.godot 缓存失配假红、user 目录隔离失败)——自愈重试(闸壳自检);测试夹具笔误(本卡新增测试自身红)——就地修复重跑。
- **L2 记录继续**:既有套件红且初判与本批无关——记录现场、跑红件最小单元定位;确认无关后继续并在实现报告备案。
- **L3 停机写报告等用户**:①🔴 任何行为零变化红线触发(逐位对拍出漂移/词表触碰/RNG 序漂移);②🔴 事实面闭集破(battle_index 等进业务发射面);③机检预算互斥——两新件或存量触面超出 §14 预算、或机检键与本卡契约互斥(含 S13 键不降反升、默认阈值出不落基线的新违规)=上游缺陷停卡退回写卡段,禁自造第三条路;④现状复核与 §3 不符(file:line 漂移改变设计前提);⑤拆分边界纪律第④款触发(拆不出内聚单元)。
## 11. 代拍板白名单(超清单必呈报)
1. **暂名定名**:EffectPort→`effect_port.gd`/RewardRoller→`reward_roller.gd`(暂名即定名——两件均见名知意,architecture v1.29 暂名在案)。
2. **端口持引用 vs 注入 Callable**:定**注入 Callable 束**。否决备选理由=端口持 BattleFxHost 对象引用:宿主 bundle 已持两业务类引用,端口再持宿主引用即成 host→damage→port→host 强引用环(轴戊禁双向强引用——两件均 RefCounted、随每战新建泄漏);Callable 注入=BattleFxHost emit_cb/facts_cb 既有接线形态。
3. **端口注入时点**:BattleFxHost._init 尾段 bind_port(组装期单点)。否决备选理由=业务类构造函数注入:端口 Callable 绑宿主方法而宿主 bundle 又需两业务类引用——构造序成环;bind_port 与现行 set_fx 同为组装期一次接线、先于 begin_battle 任何发射(全部发射点在战斗流内),时序等价。
4. **端口事实面形态**:单一伤害域闭面统一两业务类发射。否决备选理由=按事件分面(伤害域闭面/经济域无面):现状数据表下经济域三事件订阅行 when 词汇={counter}∪∅(F11 实测),counter 取值与 facts 回调无关、ap_left 载荷携带——分面机制无观测差,单面省一套事件分域机;闭面红线+V3 断言守扩面风险。
5. **选行算子改造**:weighted_pick(返 reward_id)→掷格件内 `_weighted_pick_row`(返表行)。否决备选理由=掷格件自备 `_row_by_id` 副本:同逻辑两处落点违唯一落点;改造后取号算术逐字、取号次数零变化、economy 的 `_row_by_id` 保留受理面单点。
6. **迁移成员清单微调权**:以职责语句为界——凡属摇号域(池行装配/区间行 roll/权重合成/投放门控)的成员与函数随 T2 实测归掷格件,受理域留守;边界争议以两件职责语句裁定,禁凑计数袋。
7. **端口缺省未绑形态**:业务类 `_port` 为可空成员(缺省 null)+调用点 null 守卫。否决备选理由=成员初始化器自建端口(`var _port := EffectPort.new()`):`_init(bundle)` 必传参、无参可建不成立;且六 Callable 束缺键 assert 的引用束先例不为「空端口」开缺省口——可空成员与原 `_fx == null` 守卫同形态,忠实现状。
8. 头注措辞、断言消息文案、测试内局部夹具命名——非契约面。
## 12. 落位与可复用性预检
**复用面(为什么不能复用既有那一个)**:
- **效果端口件为什么不复用 BattleFxHost 本尊**:BattleFxHost 是效果引擎机房(订阅重建/揭示兑付队列/AC 累积/桶计数器持有/树规则施加——architecture B1 域 BattleFxHost 行),业务类需要的是**收窄的发射出口**;轴戊条款即「业务类朝向机房的窄门面」——门面与机房分离。若业务类直持宿主引用,一者业务类面暴露整个宿主(可触 rebuild/flush 等非发射职责)破窄出口,二者宿主 bundle 已持两业务类引用、再加深引用即双向环(🔴4)。也不复用 luck_bias_query 缝拆形态(单枚注入 Callable):两业务类事件多且带计数器账面读写与事实束——缝拆不成立(待办清单条目实况在案,RewardEconomy 单查询口是能缝拆的最小样本、正是本条的对照面)。
- **掷格件为什么不能复用 RewardEconomy**:两职责单一变化原因不同——摇号域(池结构/权重投影/取号流程)对受理域(幂等受理/快照/退役/极性字典)各自变化;15 类变量贴顶、加第 16 枚即出闸(条目登记起因);轴戊裁切向=掷格面迁出、受理账面留守。
- **同义件排查(grep 在案)**:CurioDeck 抽签=秘宝域令牌池多重集抽签,非格面摇号;BoardGenerator=棋盘生成非资源摇号;`weighted_pick` 全库仅 economy 内部消费(F12)——两新件盘上无第二实现、无同名同义标识符冲突。
**唯一面**:端口组建单点(BattleFxHost._init);掷格件实例单点(economy 自建自持有,外部经 `reward_economy.roller` 组件出口直达——调用直连不留委托壳);伤害域事实面单点(host biz_fact);计数器账面单点(host counters_ctx);选行算子单点(roller `_weighted_pick_row`);行查 `_row_by_id` 单点(economy 受理面)。
**分层与交互面**:业务类→端口→(Callable)→宿主→引擎,单向无回指;economy→roller 单向(roller 零回指,fatal 经构造 Callable 链转宿主 fatal);BoardInstaller/编排器经 `reward_economy.roller` 组件出口写旋钮/接线(Middle Man 禁令下的直连形态);随机只经注入 RngServiceCore(roller 持 economy 传入的同一实例——流身份不变);Core 零 UI 不变;两新件 RefCounted 纯逻辑。
## 13. 拆分边界纪律适用性声明
本卡为结构类卡,§4 第 6 条全文载纪律四条款(判据权威=code-conventions §1.1,不复制定文)。逐件归属:效果端口件=职责语句「战斗业务类唯一的效果发射出口」、单一变化原因=发射契约与账面归属;掷格件=职责语句「装配期格面资源摇号」、单一变化原因=池结构与权重投影算法。两件命名即集体身份,非「剩下的成员」打包;「过阈值」(economy 15 贴顶、damage 15 贴顶)在卡内仅作发现信号记录(F5/F12),拆分动机=轴戊设计定稿。实现报告逐件一行承载职责语句执行情况。
## 14. 实现规范预算
**新件三查**(对照 gdstyle 默认阈值:公开方法 ≤20、类变量 ≤15、单函数分支 ≤8、返回 ≤6):
| 新件 | 公开方法 | 类变量 | 迁移函数对账(tools/gdstyle_baseline.txt 源键) |
|---|---|---|---|
| effect_port.gd | 6(emit/counter_read/counter_add/fact/reveal_effect/apply_ac)≤20 ✓ | 6(六 Callable)≤15 ✓ | 零迁入函数——纯新件,对账空集 |
| reward_roller.gd | 2(roll/set_treasure_unlocked)≤20 ✓(board_skew/luck_bias_query 为公开成员变量非方法) | 6(db/rng/fatal_cb/luck_bias_query/board_skew/_treasure_unlocked)≤15 ✓ | 迁入十二函数对基线源键对账=**空集**(基线无 reward_economy 键,F13)——无「迁移即拆函数」义务源;`_weighted_pick_row` 为改造新名(算术逐字) |
**存量触面一查**(S13 键较登记值只降不升;基线无登记键的文件按默认阈值判 NEW):
| 存量文件 | 改前→改后预期 | 达成手段 |
|---|---|---|
| reward_economy.gd | 类变量 15→11、公开方法 12→9(只降) | 掷格五成员十二函数三常量迁出,零新增无效成员 |
| damage_controller.gd | 类变量 15→12(只降);公开方法 9→9(set_fx 退役/bind_port 增补相抵) | 四束成员退役、_port 单成员补位 |
| action_economy.gd | 类变量 11→10(只降) | 同上 |
| battle_fx_host.gd | 类变量 14→15(贴顶 ≤15 合格);公开方法 12→16 ≤20 ✓ | 仅 facts_inject 一成员与四法——头注封闭面清单随批换代 |
| battle_orchestrator.gd | 类变量 15→15(持平,零增——硬预期) | 端口随 host 自建、掷格件随 economy 自建——宿主零新成员 |
| board_installer.gd/combat_segment.gd | 计数不变 | 纯改址 |
**指标例外申报**:无——零件超默认阈值;实现期出现超预算面=L3 停卡(§10)。
## 15. 待裁点
**零待裁点,开工门=U0**(轴戊全条款在案——两件职责语句/账面归属/衔接面/单向接线/取号流/红线全款已在 architecture v1.29 定稿;端口接线形态与迁移边界属 §11 代拍板白名单,附否决备选理由)。
## 16. 估时与切分预案
| T 卡 | 估时(工作日) | 中值 |
|---|---|---|
| T0 开工复核与读数 | 0.25–0.5 | 0.375 |
| T1 效果端口件与业务类换线 | 0.5–1 | 0.75 |
| T2 掷格件与 economy 收纳 | 0.5–1 | 0.75 |
| T3 受影响面窄测与逐位主证 | 0.25–0.5 | 0.375 |
| T4 产出物落位卡 | 0.25–0.5 | 0.375 |
| **合计** | 1.75–3.5 | **≈2.63** |
**切分预案**(超软盒预挂):T1 与 T2 相互独立(端口域/奖励域零交叉),超时域闸口径下可拆两批各自合回——拆分点=T2 起手;拆出批仍按本卡对照表各自承接(R1-R4 归端口批、R5-R7 归掷格批、R8/R9 两批各自全跑)。迭代层估时与冻结线归编排段(iter-plan)核。
@@ -1,255 +0,0 @@
# 需求卡片——模态句柄分域批
> v1.1 · 2026-11-02 · 零待裁点(开工门=U0)· godot-master 终审折入(阻断两处+建议六处,裁决=修毕可直接开工;grilling 四轮在案)
> 来源=待办清单条目「[模态句柄册分域重构](../待办清单.md)(2026-11-01 登记,来源=会话提及)」,状态已到「待写卡」
> 批性质=重构类需求性工程条目(行为零变化、纯句柄搬家);改动面=游戏代码
## 1. 目标与完成定义
**做什么**:把模态句柄册(`UiModals`)里按技术角色平铺的 12 个模态句柄按域分组抽成两只子容器——局内冒险域六件、菜单与跨语境域六件(营地六件已随迭代 47 卡⑥先例落 `UiCampModals`,不动);`ModalFlow` 编排件自 `UiModals` 升格为注册面(`UiRegistry`)直驻字段;模态登记口 `register_layer` 随登记职责迁驻注册面。全仓探针深员寻址、`ui_registry.gd node()` 合同寻址与 `main_ui_build.gd` 装配面随迁。
**什么状态算完**(逐条可核):
1. `UiModals` 类变量面=`run`/`menu`/`camp` 三只子容器,类变量 14→3,零平铺句柄残留;
2. `ModalFlow` 实例由 `UiRegistry` 构造并直驻(`ui.flow`),`UiModals` 无 `flow` 成员;`register_layer` 在 `UiRegistry`(函数体逐字迁移);
3. 全仓旧寻址形(`modals.flow.*` 与 `modals.<12 个平铺名>`)grep 零命中;营地二段式 `modals.camp.*` 与 `LAYER_CONTRACT` 合同表逐字不变;
4. 行为零变化成立——既有模态开合、输入锁、登记合同序断言全部保留原判据,仅寻址字面换代,改址后照跑全绿;
5. 新结构断言〔句柄分域批 V1〕落码(`ui_struct_probe` registry 段扩展)并在当轮真实跑批执行且通过;
6. `game/tests/README.md` 能力行两处落位(存量行入口字面换代+新增分域寻址行);
7. 实现报告与反哺点清单落 `reports/`(末卡 T2);合回 master 后由本地 CI 按改动域跑闸判定(非卡内人手义务)。
## 2. 设计事实源
三选一之第③种——跳过设计线的证据指认(重构类需求性工程条目,凭代码证据+在册条目):
1. **在册条目**:`待办清单.md`「模态句柄册分域重构(2026-11-01 登记,来源=会话提及)」,状态段「待写卡」,改动面=游戏代码;目标形态已在条目实况定稿(按域分组抽容器+ModalFlow 升格独立持有+行为零变化)。
2. **代码证据(2026-11-02 实测复核)**:`game/presentation/ui_modals.gd:7-20`——类变量 14(`flow`+12 平铺句柄+`camp` 子容器),与条目所记一致;迭代 47 卡⑥后营地域六句柄已迁 `game/presentation/ui_camp_modals.gd:4-12`,平铺面余 12 件。
3. **工程债事件沿革**:迭代 47 卡④⑤平铺句柄合计 19 越过 S13 类变量上限 15(停机呈报件已按「吸收即死」退役,`reports/` 现无此件;事件沿革见待办条目实况与 git 提交 a5c89d67)。阈值顶格只作发现信号,本卡的拆分动机是域归组(见 §5 契约 3)。
4. **拆分判据权威**:`design/engineering/code-conventions.md` §1.1 拆分判据;容器先例=`ui_camp_modals.gd`(迭代 47 卡⑥);注册面归属=`design/engineering/architecture/architecture.md:169`(ui_registry 行,v1.30 现行——行号随文档换代漂移,T2 反哺落文以内容锚为准)。
## 3. 现状事实(代码级实测,2026-11-02)
| # | 事实 | 证据(file:line) |
|---|---|---|
| 1 | `UiModals` 类变量 14:`flow`+12 平铺句柄+`camp` 子容器;`_init` 建 `flow` 与 `camp` | `ui_modals.gd:7-20,23-25` |
| 2 | 模态登记唯一口 `register_layer` 在 `UiModals`(锚预设撑满+`flow.register`) | `ui_modals.gd:28-33` |
| 3 | 营地域子容器先例:`UiCampModals` 纯字段六句柄;头注带「禁平铺回 ui_modals」分域纪律 | `ui_camp_modals.gd:1-12` |
| 4 | 注册面持三域容器(screens/battle/modals),`_init` 逐只构造 | `ui_registry.gd:42-50` |
| 5 | `node()` 合同寻址 24 键:12 平铺键直指 `modals.<名>`,营地六键两段式 `modals.camp.*`,另 6 键 screens/node/flow 域 | `ui_registry.gd:54-80`(平铺 59-64,72-75,77-78;营地 66-71) |
| 6 | `apply_layer_contract` 三处调 `modals.register_layer`;`LAYER_CONTRACT` 合同表 24 项(含 tags/host/shell 特例) | `ui_registry.gd:15-40,86-111`(调用点 97/106/111) |
| 7 | `ModalFlow` 纯逻辑类:依赖仅 ModalStack+查询 Callable,零节点构建零信号连接;类本体与本批无关 | `modal_flow.gd:1-15` |
| 8 | 装配面寻址:12 平铺句柄命中 50 行+`flow` 注入 14 行(Callable 注入段与 early 取 `flow.pump_ended`);营地二段式 28 行不动 | `main_ui_build.gd:49,60,89-92,99-158,168-174,189-218,232-253,269-286` |
| 9 | 组合根与四拆件寻址(命中行含注释):main 27;四拆件 38/43/13/8 | `main.gd:94,107-765`;`main_adventure_flow.gd`/`main_overlay_flow.gd`/`main_debug_flow.gd`/`main_esc_flow.gd` |
| 10 | 全仓 `modals.` 寻址 25 文件 595 行:营地二段式 116 行(约 10 混行含 flow/flat 旧形随换代、camp 部分不动);`flow` 87 行;12 平铺句柄 442 行(两者去重唯一行 482) | 复核命令与分文件计数表见 §8 结构图注(口径=`grep -c` 命中行数,含注释行) |
| 11 | 测试与探针消费面 15 件:探针 11+系统测试+冒烟 2 行+单元 2 行;registry 合同断言段钉登记册序 | `ui_struct_probe.gd:562-580,584-606`;`system_test.gd:108-122,316,384-387,491`;`smoke_boot.gd:74-75`;`pacing_queue_test.gd:61`;`theme_projection_test.gd:719` |
| 12 | S13 类变量默认上限 15;基线文件 12 行无本批触碰文件键(14 与 3 均未越限) | `tools/gdstyle.toml`(阈值取默认);`tools/gdstyle_baseline.txt:1-12` |
## 4. 目标结构与域归组
```
main.ui(UiRegistry,类变量 3→4)
├─ screens: UiScreens(9,不动)
├─ battle: UiBattle(5,不动)
├─ modals: UiModals(类变量 14→3,转纯字段容器)
│ ├─ run: UiRunModals(新件,6 句柄=局内冒险域)
│ ├─ menu: UiMenuModals(新件,6 句柄=菜单与跨语境域)
│ └─ camp: UiCampModals(6,不动)
└─ flow: ModalFlow(升格直驻注册面;register_layer 随迁)
```
12 只平铺句柄的域归属与判据(每句柄以真实入口证据归域,非按数量凑袋):
| 句柄 | 现寻址(平铺) | 目标寻址 | 域归属判据(真实入口) |
|---|---|---|---|
| legend_overlay | `modals.legend_overlay` | `modals.run.legend_overlay` | 局内——战斗中图例,棋盘角标触发(`main_ui_build.gd:77` → `main_overlay_flow.gd:184-187`) |
| node_overlay | `modals.node_overlay` | `modals.run.node_overlay` | 局内——节点结算窗(`main_adventure_flow.gd:73-74`) |
| level_screen | `modals.level_screen` | `modals.run.level_screen` | 局内——关卡地图屏(`main_adventure_flow.gd:206`;tags=screen_state `ui_registry.gd:21`) |
| curio_overlay | `modals.curio_overlay` | `modals.run.curio_overlay` | 局内——奖励三选一(`main_ui_build.gd:157,172-174`) |
| end_overlay | `modals.end_overlay` | `modals.run.end_overlay` | 局内——终局面板(`main.gd:290-299`) |
| status_panel | `modals.status_panel` | `modals.run.status_panel` | 局内——状态面板,地图/棋盘两角标入口(`main_ui_build.gd:126`、`main_overlay_flow.gd:32`) |
| shop_overlay | `modals.shop_overlay` | `modals.menu.shop_overlay` | 跨语境——冒险商店节点(`main_adventure_flow.gd:80-87`)+营地商店(`camp_shop_presenter.gd:10`) |
| settings_overlay | `modals.settings_overlay` | `modals.menu.settings_overlay` | 跨语境——开始层(`main_overlay_flow.gd:9`)+营地 Esc 双路径(`main_esc_flow.gd:51`) |
| career_overlay | `modals.career_overlay` | `modals.menu.career_overlay` | 跨语境——开始层笔记本+营地语境(`main_overlay_flow.gd:42,47`) |
| save_select_overlay | `modals.save_select_overlay` | `modals.menu.save_select_overlay` | 跨语境——开始层+营地大门流(`main_overlay_flow.gd:73,96,128`) |
| confirm_dialog | `modals.confirm_dialog` | `modals.menu.confirm_dialog` | 全语境——确认框(`main.gd:129,147,156`、`main_overlay_flow.gd:73,79,83,128`) |
| debug_overlay | `modals.debug_overlay` | `modals.menu.debug_overlay` | 全语境——调试浮窗(non_locking,`ui_registry.gd:37`;`main_debug_flow.gd` 全件) |
寻址合同换代三形:`ui.modals.flow.X` → `ui.flow.X`;`ui.modals.<平铺名>` → `ui.modals.run.<名>` 或 `ui.modals.menu.<名>`;`ui.modals.camp.*` 不变。
## 5. 设计契约(红线条款,违反即返工;🔴=触碰即 L3 停机呈报)
1. 🔴 **行为零变化**:装配序、登记序、树序、模态开合语义、输入锁谓词、遮挡记账、T17 演播后排窗挂起逐位不变;`LAYER_CONTRACT` 合同表零改动;`ModalFlow`/`ModalStack` 类本体零改动(搬家不改性)。判据=§10 对照表 R4/R5 行既有断言原判据照跑全绿。
2. 🔴 **分域纪律册级化**:任何模态句柄禁平铺回 `UiModals`(营地先例条款 `ui_camp_modals.gd:3` 推广为全册纪律);`UiModals` 终态=三子容器纯字段,与 `UiScreens`/`UiBattle` 同型。
3. 🔴 **拆分边界纪律**(条款在卡,判据权威=`code-conventions.md` §1.1 拆分判据,不复制定文):①每个拆出单元须有可陈述的职责语句与单一变化原因(本卡两新件的职责语句见 §8 结构图,实现报告逐件一行承载);②拆出单元须有集体身份——命不出名字、只能说「剩下的成员」的打包=凑计数袋,禁;③「过阈值」(S13 类变量 14 顶格 15)只许作为发现信号,作为拆分动机即违规——本卡动机=域归组(营地先例的册级推广),阈值顶格是发现信号;④按纪律拆不出内聚单元→停卡呈报走豁免/还债通道,禁硬拆凑绿(进 §11 L3)。
4. 🔴 **Core 层零 UI 依赖不因新容器破坏**:两新件=RefCounted 纯句柄容器,不挂树、零信号连接、零核心写调用(与既有四容器同型);`--headless --script` 全链不受影响。
5. **构造时序不变**:`flow` 改由 `UiRegistry._init` 构造——注册面构造点 `main.gd:94` 先于 `_build_ui`,装配早期注入点(`main_ui_build.gd:60` 取 `flow.pump_ended`)依赖其先在座的时序前提逐位保持。
6. **数值纪律**:本卡零数值面;禁数值字面量进代码方案。
7. **命名随仓库法**:新件类名对齐 `UiCampModals` 命名法;子容器成员名沿用原平铺名逐字(12 个句柄零改名——纯句柄搬家)。
## 6. 范围边界
**做**:§4 目标结构全部;全仓寻址换代(探针 11 件+测试 4 件+产品码 8 件);新结构断言落码;README 能力行两处。
**不做(明示去向)**:
| 不收件 | 去向 |
|---|---|
| CAMP_HEADER_BAND 令牌退役 | 另一待办条目(归 ui_kit 令牌批顺带),本卡不收 |
| 任何行为变化(开合时序/遮挡/锁语义/登记序/树序/文案/交互) | 本卡范围外;发现即 L3 停机呈报 |
| `UiCampModals` 再拆分或营地六句柄改名 | 先例已立且职责单一,不动 |
| `ModalFlow`/`ModalStack` 职责重划或类体改写 | 本卡只搬家;重划属新需求 |
| 测量件(`game/sim/`)适配 | 实测零 `modals.` 寻址(§3 表#10 复核命令可验),零触碰 |
| `architecture.md` ui_registry/UiCampModals/模态编排三处记述换代 | 反哺点清单(§7),文档批落文 |
## 7. 关联文档同步面
| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 |
|---|---|---|
| design/engineering/architecture/architecture.md | :169 ui_registry 行(v1.30 现行行号)——「三域句柄容器…+ModalFlow」「四件类变量 3/9/5/14,ModalFlow 随 UiModals 容器构造即建」→ 换代为三域容器+两新子容器+flow 直驻注册面+类变量实数(UiRegistry 3→4、UiModals 14→3);:170 UiCampModals 行——「ui_modals 平铺面收窄」可现状化为平铺面清零;:201——「ModalFlow 实例随 UiModals 容器构造建立」→ 随 UiRegistry 构造建立 | 列反哺点清单由文档批落文(实现批禁写 design/) |
| game/tests/README.md | 能力行两处:存量行「Esc 浮窗唤起与三出口动线」真实入口字面 `ui.modals.flow.open/close`→`ui.flow.open/close`;新增「模态句柄分域寻址面」行+覆盖域表 HUD框架 行随补 | 写卡段同批落位(本卡随批写入,非实现批义务) |
| design/gdd/术语表.md | 无新术语——「分域」「子容器」「注册面」均为仓库既有说法 | 无关联文档 |
## 8. 文件结构图(卡前)
| 文件 | 新建/修改 | 职责(职责语句) | 行为改动 |
|---|---|---|---|
| game/presentation/ui_run_modals.gd | 新建 | 局内冒险域六句柄唯一容器——冒险会话内开合的模态呈现面句柄册(纯字段 RefCounted) | 行为改动(寻址合同换代)→对照表 R1 |
| game/presentation/ui_menu_modals.gd | 新建 | 菜单与跨语境域六句柄唯一容器——菜单层与多语境共用模态的句柄册(纯字段 RefCounted) | 行为改动(寻址合同换代)→对照表 R2 |
| game/presentation/ui_modals.gd | 修改 | 模态层域句柄册转纯字段容器:三子容器 run/menu/camp;`register_layer` 与 `flow` 成员迁出 | 行为改动→对照表 R3 |
| game/presentation/ui_registry.gd | 修改 | 注册面增持 `flow` 编排件与 `register_layer` 登记口;`node()` 十二键换代两段式 | 行为改动→对照表 R3/R5 |
| game/presentation/main_ui_build.gd | 修改 | 装配面寻址换代(句柄赋值/接线两段式 50 行;`flow` 取 `ui.flow` 14 行);装配序零变化 | 行为改动→对照表 R4 |
| game/presentation/main.gd | 修改 | 组合根寻址换代(27 行,含头注) | 行为改动→对照表 R4 |
| game/presentation/ui_camp_modals.gd | 修改 | 头注两句随 flow 升格失真等长改写(:2「与 flow 同拍」句——flow 改由 UiRegistry._init 建;:3「全量分家另立批」句——本批即分家) | 非行为改动(注释漂移随批消化)——由 R3 覆盖 |
| game/presentation/main_adventure_flow.gd / main_overlay_flow.gd / main_esc_flow.gd / main_debug_flow.gd | 修改 | 四拆件寻址换代(38/43/8/13 行) | 行为改动→对照表 R4 |
| game/tests/smoke_boot.gd | 修改 | 装配检查两行寻址换代 | 非行为改动(测试面同步)——由 R4 覆盖 |
| game/tests/system_test.gd / unit/presentation/pacing_queue_test.gd / unit/presentation/theme_projection_test.gd | 修改 | 测试面寻址换代;theme_projection 源码字面断言期望串换代(判据语义不变) | 非行为改动(测试面同步)——由 R4 覆盖,字面换代申报见 §10 |
| game/probe/ 下 11 件(fx_shot/layout/probe_ui_util/screen_flow/shot/t17_defer/ui_click/ui_input/ui_probe/ui_struct/ui_tune) | 修改 | 探针深员寻址换代;ui_struct_probe registry 段增结构断言 | 非行为改动+结构断言新增→对照表 R1/R2/R3/R5 |
| game/tests/README.md | 修改 | 能力行两处落位(存量行换代+新增行+覆盖域表 HUD框架 行补名) | 非行为改动(写卡段义务,随本卡入库) |
分文件寻址计数表(2026-11-02 实测,`grep -c` 命中行数、含注释行;实现复核用同一命令):main.gd flow=10 flat=17;main_adventure_flow flow=9 flat=29;main_debug_flow flow=4 flat=9;main_esc_flow flow=5 flat=3;main_overlay_flow flow=16 flat=27;main_ui_build flow=14 flat=50;ui_registry flat=12(node() 键行);ui_modals flow=1(头注);探针 11 件 flat=271 flow=27;测试 4 件 flat=24 flow=1。合计换代命中行=flat 442+flow 87=529(唯一行 482)。
## 9. 任务卡 T0–T2
估时:T0 0.5–1.0 工作日;T1 0.5–1.0 工作日;T2 0.25–0.5 工作日;合计中值 ≈1.9 个工作日(编排段汇总用)。
### T0 抽容器与注册面换代(产品码+冒烟测试件)
**取用**:无(本卡首卡)。**产出**(T1 起引用,名字逐字):寻址合同三形 `ui.flow.<编排口>`(open/close/open_after_playback/locks_input/badge_greyed_map/badge_greyed_battle/register 入 stack 不变)、`ui.modals.run.<六名>`、`ui.modals.menu.<六名>`;新类名 `UiRunModals`/`UiMenuModals`。
- [ ] 新建 `game/presentation/ui_run_modals.gd`:`class_name UiRunModals extends RefCounted`,纯字段六枚全类型标注 `var legend_overlay: LegendOverlay`/`var node_overlay: NodeOverlay`/`var level_screen: LevelMapScreen`/`var curio_overlay: CurioPickOverlay`/`var end_overlay: BattleEndOverlay`/`var status_panel: StatusPanel`;头注=职责语句(局内冒险域六句柄唯一容器——与 §8 结构图逐字同句)
- [ ] 新建 `game/presentation/ui_menu_modals.gd`:`class_name UiMenuModals extends RefCounted`,纯字段六枚全类型标注 `var shop_overlay: ShopOverlay`/`var settings_overlay: SettingsOverlay`/`var career_overlay: CareerOverlay`/`var save_select_overlay: SaveSelectOverlay`/`var confirm_dialog: ConfirmDialog`/`var debug_overlay: DebugOverlay`;头注=职责语句(菜单与跨语境域六句柄唯一容器)
- [ ] 改 `game/presentation/ui_modals.gd`:删 `flow` 与 12 平铺句柄成员,增 `var run: UiRunModals`/`var menu: UiMenuModals`(`camp` 保留);`_init` 改建 run/menu/camp 三容器;`register_layer` 函数体(含锚预设纪律注释)迁出;头注换代为纯字段容器+三子容器+分域纪律全册化句
- [ ] 改 `game/presentation/ui_registry.gd`:增 `var flow: ModalFlow`,`_init` 增建(构造时点与今等价——注册面先于装配);`register_layer` 自 `ui_modals.gd:28-33` 逐字迁入(含注释);`apply_layer_contract` 三处 `modals.register_layer` 改直调;`node()` 十二平铺键换代 `modals.run.*`/`modals.menu.*`(营地六键不动);头注「三域容器」句换代
- [ ] 改 `game/presentation/main_ui_build.gd`:句柄赋值与接线换代两段式(计数表 flat=50);`flow` 注入与取用改 `root.ui.flow.*`(flow=14::60、:123、:168-169、:201、:251、:269-286);:273 注释「实例随 ui.modals 容器构造建立」句随迁
- [ ] 改 `game/presentation/main.gd`:寻址换代(计数表 flat 17+flow 10,含 :4 头注「模态开合只走 ui.modals.flow」句改 `ui.flow`);:46 持有面注释核对(注册面单点宿主句仍成立,不改)
- [ ] 改四拆件 `main_adventure_flow.gd`/`main_overlay_flow.gd`/`main_esc_flow.gd`/`main_debug_flow.gd`:寻址换代 38/43/8/13 行(flat+flow 合计,逐件 grep 该文件旧形零命中)
- [ ] 改 `game/tests/smoke_boot.gd:74-75`:`modals.legend_overlay`→`modals.run.legend_overlay`;`modals.status_panel`→`modals.run.status_panel`
- [ ] 验证①(产品码旧形零残留——当步换代域):`grep -rnE "modals\.flow|modals\.(legend_overlay|node_overlay|level_screen|curio_overlay|end_overlay|shop_overlay|settings_overlay|status_panel|career_overlay|save_select_overlay|confirm_dialog|debug_overlay)" --include="*.gd" game/presentation` =零命中;正检三形各 >0:`grep -rc "modals\.run\." --include="*.gd" game/presentation`/`grep -rc "modals\.menu\." --include="*.gd" game/presentation`/`grep -rc "ui\.flow\." --include="*.gd" game/presentation`
- [ ] 验证②(真实开机路径):`python tools/run_smoke.py` PASS(真实装配走新寻址——闸 00 最窄确认)
- [ ] 验证③(静态纪律):`bash game/tests/static_scan.sh` 零 FAIL(S9 新件全类型标注;S13 无新键——预期 `ui_modals` 类变量 14→3、`ui_registry` 3→4 均在上限内不产键);跑闸前先 `--editor --quit` 刷类名缓存(新 class_name 生效前提);新件 `.uid` 边车随扫描生成、随批入库(存量 80 件 presentation `.uid` 均在 git,同法)
### T1 测试与探针面换代+结构断言落码
**取用**:T0 的寻址合同三形与 12 句柄归属表(§4)。**产出**:结构断言〔句柄分域批 V1〕;测试面全量新寻址。
- [ ] 探针 11 件机械改址(分文件计数表:fx_shot flat=3;layout flat=2;probe_ui_util flat=1;screen_flow flat=19 flow=0;shot flat=20;t17_defer flat=6 flow=1;ui_click flat=109 flow=14;ui_input flat=13 flow=4;ui_probe flat=12 flow=1;ui_struct flat=54 flow=2;ui_tune flat=32 flow=5)——判据零改动,只换代址字面
- [ ] `game/tests/system_test.gd` 改址(flat=20 flow=1::108-122 句柄清单数组、:316 `var mf = main.ui.flow`、:384-387、:491 终局弹起等);`pacing_queue_test.gd:61` 改址
- [ ] `game/tests/unit/presentation/theme_projection_test.gd` 改址+:719 源码字面断言期望串换代:`"ui.modals.debug_overlay.diagnose_requested.connect(_on_diagnose_pressed)"` → `"ui.modals.menu.debug_overlay.diagnose_requested.connect(_on_diagnose_pressed)"`(判据语义不变——申报见 §10)
- [ ] `ui_struct_probe.gd` `_modal_registry_contract` 段尾增结构断言块,尾缀〔句柄分域批 V1〕,三条判据:**V1a 分域在座**——run 六件经 `main.ui.modals.run.<名>` 逐件非 null、menu 六件经 `main.ui.modals.menu.<名>` 逐件非 null(12 检);**V1b 平铺面清零**——`main.ui.modals.get(<旧平铺名>)` 12 件逐件为 null(旧寻址成员不存在);**V1c 编排口独立**——`main.ui.flow` 非 null 且 `main.ui.modals.get("flow")` 为 null
- [ ] 验证①(探针层):`godot --headless --path game res://probe/ui_struct_probe.tscn` 单跑零 problems(先孤立验证新断言);`bash tools/probe_gate.sh --full` 探针族绿
- [ ] 验证②(系统层):`python tools/run_system_test.py` PASS
- [ ] 验证③(单元层):工作目录 game/ 跑 `godot --headless --script tests/run_all.gd -- --only=presentation` 绿(开发期窄测形态,不产闸回执)
- [ ] 验证④(全仓旧形零残留——§1 完成定义 #3):`grep -rnE "modals\.flow|modals\.(legend_overlay|node_overlay|level_screen|curio_overlay|end_overlay|shop_overlay|settings_overlay|status_panel|career_overlay|save_select_overlay|confirm_dialog|debug_overlay)" --include="*.gd" game` =零命中(探针与测试面 T1 换代后的全仓口径)
- [ ] 里程碑步出口跑一次代码域闸(`bash tools/run_all_gates.sh --code`);波内修复只做出红最小单元的最窄确认
### T2 产出物落位卡
**取用**:T0/T1 全部落地事实。**产出**:批收口两件+收尾核对。
- [ ] 写 `reports/iter<N>-实现报告-<日期>.md`:各卡状态+实机目检总清单(本批行为零变化,零新增目检项——登记「模态开合走查由既有探针族覆盖」一句)+实现决定记录(零拍板或逐条:决了什么/为什么/代价/撤销方式)+实际改动—验收对照表(逐行补测试文件:行)
- [ ] 写 `reports/iter<N>-反哺点清单-<日期>.md`:§7 同步面所列 architecture.md 三处(:168/:169/:200)逐条写清哪一节、改成什么、依据是什么
- [ ] 收尾核对:`game/tests/README.md` 能力行名字与实际落地一致(新增行代表用例 `ui_struct_probe.gd:_modal_registry_contract` 实名核对;改名则回表)
- [ ] 合回后由 post-merge 钩子自动跑本地 CI 按域闸(非卡内人手义务);红项走修复 worktree 追绿
## 10. 验证闸(改动—验收对照表)
判据口径:每行断言从真实入口进入、绑被测改动特有的可观测提交面、在当轮真实跑批中执行并通过;禁变异类测试与撤销类取证。断言尾缀新增统一〔句柄分域批 V1〕;既有断言尾缀保留原样(装配生命批 V1/ESC批 V1/注册面 V2 等)。
| # | 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|---|---|---|---|---|---|---|---|
| R1 | 局内冒险域六件抽容器 | `ui_run_modals.gd` 新建;`ui_modals.gd:7-20` 六件成员迁出;`ui_registry.gd:59-64,72-78` 中六键换代;装配面六件赋值换代 | `ui_struct_probe.gd:_modal_registry_contract` V1a run 六件逐件非 null〔句柄分域批 V1〕 | 探针 | 真实实例化主场景 `_ready` 装配→registry 合同段 | 注册面新寻址取值面(`modals.run.*` 六句柄在座) | 新增:模态句柄分域寻址面 |
| R2 | 菜单与跨语境域六件抽容器 | `ui_menu_modals.gd` 新建;`ui_modals.gd` 六件成员迁出;`ui_registry.gd` 六键换代;装配面六件赋值/接线换代 | 同段 V1a menu 六件逐件非 null〔句柄分域批 V1〕 | 探针 | 同上 | 注册面新寻址取值面(`modals.menu.*` 六句柄在座) | 新增:模态句柄分域寻址面 |
| R3 | 平铺面清零+编排口升格独立持有+登记口迁驻 | `ui_modals.gd:7,23-33`(flow/register_layer 迁出);`ui_registry.gd:42-50`(增 flow+_init 建)、:28-33 迁入 register_layer | 同段 V1b 12 件 get() 逐件 null+V1c flow 在注册面且 modals 无 flow〔句柄分域批 V1〕;S13 静态判据(类变量 14→3 无新键,`bash game/tests/static_scan.sh`) | 探针+静态 | 同上 | 旧平铺成员缺位+`ui.flow` 在座(被测改动的特有提交面) | 新增:模态句柄分域寻址面 |
| R4 | 全仓寻址换代行为零变化 | 装配面 `main_ui_build.gd`(flat=50/flow=14)+`main.gd` 27 行+四拆件 102 行+`ui_registry.gd node()` 12 键;测试探针 15 件改址 | 既有断言群改址照跑(原判据):`system_test.gd` V3 终局面板弹起(:491)与模态锁段(:316 `locks_input` 矩阵);`ui_struct_probe.gd` node_overlay 开合段(:251-262);`screen_flow_probe.gd` Esc 三动线段;`ui_click_probe.gd` 各模态交互段;`ui_tune_probe.gd` 调试浮窗段;`smoke_boot.gd:74-75` 装配两检 | 探针+系统+冒烟 | 真实开机路径→真实输入/信号路径(模态经 `ui.flow.open/close` 开合) | 模态可见性与信号开合面(既有断言原样保留,见保留声明) | 既有:模态覆盖层编排与输入锁 |
| R5 | 登记册合同序不破 | `ui_registry.gd:86-111` apply_layer_contract 直调 register_layer;登记序/树序数据零改动 | `ui_struct_probe.gd:_modal_registry_contract` ①②③④段(登记册序==合同序逐位、树序邻接对、宿住/同槽特例)改址照跑〔装配生命批 V1〕 | 探针 | 同上 | 登记册栈序==LAYER_CONTRACT 序逐位 | 新增:模态句柄分域寻址面 |
| R6 | 诊断转储入口接线断言字面换代 | `theme_projection_test.gd:719` 期望串换代(`ui.modals.debug_overlay.`→`ui.modals.menu.debug_overlay.`) | 该断言照跑绿(V6 段,`run_all` presentation 套件;由 R4 之系统与单元跑批同轮执行) | 单元 | 套件直跑(`tests/run_all.gd`) | 组合根接线源码字面(既有源码锚定断言形态) | 既有:模态覆盖层编排与输入锁 |
非行为改动覆盖注记:各文件头注/注释随址换代、README 能力行两处=非行为改动,其装配与开合后果由 R4 行断言从真实入口承载;R6 为测试侧字面换代(判据语义不变),单独列行申报。合同表零改动(红线 1)的判据为静态——`LAYER_CONTRACT` 表常量无运行期可观测面(登记册序断言以表为参照系,表随登记同动时不互证),由独立验收审计核对 diff 中该数据块零行变更(观测面局限申报,非撤销类取证)。
**测试削弱申报**(允许的旧断言改动,全部为字面换代、零判据削弱):①`theme_projection_test.gd:719` 期望串换代(R6);②全部既有模态断言的寻址字面换代(R4/R5 所列段)——判据、阈值、真实入口全部保留;零删除断言、零放宽阈值。除上述外任何断言削弱=上游缺陷,停卡退回写卡段。
**闸口径**:本批改动含 `game/` 行为载体→代码域闸;合回后本地 CI 为唯一强制验证点(判读归 CI 回执,卡内不重复人手跑)。回归措辞按模板:里程碑步(T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增断言先行孤立验证再并入全套(T1 验证①已含)。
**测试方式两分法**:本批全部归能力验证(自动化断言);零新体验面,用户目检零新增项(T2 登记句即了结义务,登记不阻塞)。
**独立验收审计**:合回前由未参与实现的会话或子代理执行,报告落 `reports/iter<N>-验收审计-<日期>.md`;审计至少核对对照表六行两端对上、真实入口未绕过改动点、判据绑定面钉在寻址合同与开合面上;未过不得合并。
## 11. 异常分级
- **L1 自救**:改址漏点(编译/寻址报错指名文件行)——按 §8 计数表补点后重跑该件所在最窄验证。
- **L2 记录继续**:注释/头注换代引发的 S11 注释禁词误报——按扫描面豁免通道核对后记录实现报告;探针偶发超时——单件重跑一次并记录。
- **L3 停机写报告等用户**(逐条):①行为零变化破口(任何开合/锁/序差异);②拆不出内聚单元(契约 3④);③**机检预算互斥=上游缺陷停卡退回写卡段**——S13/S9 键与卡片契约互斥、或需保留无效成员才能过闸时,禁自造第三条路;④判据绑不上(R3 结构断言若造不出可观测面)=静态判据+评审注记申报观测面局限,禁自造注入破坏或回退 hunk 取证。
## 12. 代拍板白名单(授权 agent 实现期自行拍板的微决策)
1. 分组命名:子容器字段名 `run`/`menu`,类名 `UiRunModals`/`UiMenuModals`(对齐 `UiCampModals` 命名法;「局内冒险域」「菜单与跨语境域」两职责语句随件入头注)。
2. 子容器成员名沿用原平铺名逐字(12 个句柄零改名)。
3. `ModalFlow` 独立持有的落点=`UiRegistry` 直驻字段 `flow`:注册面是寻址与登记的单点宿主,构造时点与今等价;备选「main 直持」被否——破坏 `main.ui.<域容器>.<句柄>` 单点寻址面与注册面门面定位。
4. `register_layer` 随登记职责迁驻 `UiRegistry`(`UiModals` 转纯字段容器,与 `UiScreens`/`UiBattle` 同型;登记口语义逐字不变)。
5. 注释与头注随寻址换代等长改写(零语义新增,禁变更叙事)。
超白名单事项记入实现报告「实现决定记录」节备案,不另立追认单。
## 13. 待裁点
**零待裁点,开工门=U0。** 目标形态(分组抽容器+flow 升格独立持有+行为零变化)已在待办条目实况定稿;命名与落点微决策已授权(§12);本卡不触碰用户设计权保留面(无玩法、无文案、无数值、无美术)。
## 14. 落位与可复用性预检
**新增文件两枚**(`ui_run_modals.gd`/`ui_menu_modals.gd`):
- **复用面**:grep 全仓无同职责件——`UiCampModals` 只收营地域六句柄(句柄集不相交,`ui_camp_modals.gd:1-12`),`UiScreens` 收屏壳与全屏态、`UiBattle` 收战区视图(`ui_screens.gd`/`ui_battle.gd` 头注自陈域界)——把 run/menu 域句柄塞进任何一只既有容器=域错位,直接违反分域纪律(§5 契约 2);确需新增的理由成立。
- **唯一面**:类名 `UiRunModals`/`UiMenuModals` 与字段名 `run`/`menu` 全仓 grep 零命中(盘上无第二处同名/同义件);12 只句柄各自唯一落点=自 `ui_modals.gd` 迁入而非复制(迁移后旧成员已删,`get()` 判 null 有断言钉住——R3)。
- **分层与交互面**:两新件被 `UiModals._init` 构造、被 `main_ui_build` 装配赋值、被 `ui_registry.node()` 寻址——调用路径与既有三容器同型(`UiRegistry._init` → 容器构造;装配写句柄;寻址读句柄);RefCounted 不挂树、零信号、零核心触碰,Core 层零 UI 依赖与 RngService/ConfigDB 红线零接触(本批零随机、零数值)。
**新增函数一件**:`UiRegistry.register_layer`——自存量逐字迁移(非新逻辑),对账见 §15。
**新增数据件**:无。
## 15. 实现规范预算
对照 `tools/gdstyle.toml` 默认口径(gdstyle v0.4.0:公开方法 ≤20、类变量 ≤15、单函数分支 ≤8、返回 ≤6;基线=`tools/gdstyle_baseline.txt`):
**新件三查**:
| 新件 | 公开方法 | 类变量 | 迁移函数对账 |
|---|---|---|---|
| ui_run_modals.gd | 0(纯字段,≤20 ✓) | 6(≤15 ✓) | 无迁入函数 |
| ui_menu_modals.gd | 0(纯字段,≤20 ✓) | 6(≤15 ✓) | 无迁入函数 |
**存量触面一查**(预期与手段):
| 存量件 | 键现状 | 预期 | 手段 |
|---|---|---|---|
| ui_modals.gd | 基线无键(14 未越限) | 类变量 14→3、公开方法 1→0——只降不升 | 成员迁出后即删,禁留别名(§16) |
| ui_registry.gd | 基线无键(3 未越限) | 类变量 3→4、公开方法 2→3——均在上限内不产新键 | register_layer 迁入为唯一增量 |
| main_ui_build.gd | 基线无键 | 行数 ±0(改址等长)、函数面零增 | 只换代址字面与随迁注释 |
| main.gd 与四拆件 | 基线无键 | 零新成员、零新函数 | 只换代址字面 |
**迁移函数对账**:`register_layer`(源=`ui_modals.gd:28-33`,函数体 5 行、零分支、单返回)——`gdstyle_baseline.txt` 无源函数键,branches/returns 均在默认值内,迁移即原样、无需拆函数。
**指标例外申报**:无。
## 16. 禁为机检文本保留无效成员(重构类卡必填条款)
禁止为迎合机检消息文本(含计数)而保留或新增无效成员/别名——`UiModals` 迁出的 13 个成员(12 句柄+flow)不设转发属性、不设 get 兜底、不保留空壳 var;`ui_registry.node()` 十二键直接指向新两段式寻址,不留旧键双轨。机检键与卡片契约互斥时,实现段一律停卡呈报(§11 L3③),不得自造第三条路。
@@ -1,269 +0,0 @@
# 需求卡片 · 营地五界面真窗口化批(v1.1)
> **版本**:v1.1(2026-11-02)——godot-master 终审阻断一处+建议三处全折入(裁决=修后即可开工);grilling 四轮在案、零待裁点。
> **用途**:迭代实现批的实施合同。把营地五个功能界面的承载形态从「近全屏面板/全屏深色叠层」换成统一居中定尺寸窗壳;开合路由、互斥、关闭钮、ESC 序等行为面(迭代 47 已落地)零改。
> **来源**:待办清单「营地五界面窗口化批——营地功能页点开后的呈现形态(2026-10-22 登记,来源=会话提及)」条目(状态=文档设计已闭合+已写卡)。
> **唯一事实源**:`design/gdd/ux/camp.md` v2.5「叠层与开合」节(2026-11-01 三点裁决+2026-11-02 两点补裁全在案;美术凭据=art-bible v3.32 禁令删除批)。
> **改动面**:游戏代码。 **估时**:≈2.75 个工作日(T0 0.5–1/T1 0.25–0.5/T2 1–1.5/T3 0.25–0.5,中值合计 2.75)。
---
## 1. 目标与完成定义
**做什么**:营地五界面(锻造工坊/秘宝匣/天赋树/奖励格图鉴/生涯记录)各以**功能窗口**打开——
| 形态项 | 定稿值(camp.md v2.5) |
|---|---|
| 窗壳 | 统一居中定尺寸窗壳,起点 **720×640**(窗明显小于屏、营地场景大面积可见;终值随样张目检校准,属普通设计决策) |
| 遮罩 | 窗之下垫半透明压暗遮罩,复用既有模态遮罩件,现值锚黑色 **0.6**(观感随样张目检校准) |
| 滚动 | 内容超高时**窗内滚动** |
| 生涯页 | 与四子界面**同壳同形态**(全屏深色叠层退役) |
| 行为面 | 五窗互斥单开(模态栈深恒 1)、各窗自带关闭钮、ESC 优先序(有窗先关最上层窗、无窗才进 ESC 浮窗)——**零改** |
**什么状态算完**:
1. 四子界面壳与生涯页统一为居中定尺寸窗壳:基准档 1280×800 下窗板(窗壳最外层面板容器,窗口可见外缘)实测矩形 = 左上 (280, 80)、尺寸 720×640;
2. 窗开态营地场景根留底可见(场景根 visible 且窗四周有留边);
3. 遮罩 0.6 与全屏锚回归不变;
4. 天赋树长列表内容超高时在窗内滚动(窗尺寸不随内容增长);
5. 五窗互斥单开、各窗关闭钮、ESC 优先序回归全绿(既有行为面断言+本卡新增回归钉);
6. 代码域闸全绿+产出物两份齐(实现报告/反哺点清单)+独立验收审计通过。
---
## 2. 设计事实源
`design/gdd/ux/camp.md` v2.5「叠层与开合」节(:43-45)——五窗统一居中定尺寸窗壳(起点 720×640)、遮罩 0.6、内容超高窗内滚动、生涯页同壳同形态、五窗互斥单开、各窗关闭钮、ESC 优先序。与待办清单条目实况凭据(camp.md v2.5+art-bible v3.32)一致。本批为**行为改动批(呈现形态换壳)**:迭代 47 落地的开合路由/互斥/关闭钮/ESC 序(行为面)不动,只换承载几何。
---
## 3. 现状事实(代码级,开工自行复核)
| # | 事实 | 出处 |
|---|---|---|
| F1 | 四子界面共用壳 `_build_shell`:手搓全屏遮罩 dim(`Color(UiKit.DIM, 0.6)`)+ MarginContainer `PRESET_FULL_RECT`(边距 16/16/12/12)+ VBox+内容体 PanelContainer `SIZE_EXPAND_FILL`——内容撑满全屏=近全屏面板形态的成因 | camp_sub_view_base.gd:14-37(dim 在 :16) |
| F2 | 顶栏铭牌+钥石徽;`_balance_label` = 徽值标签(ui_probe 直读面) | camp_sub_view_base.gd:41-62(:62) |
| F3 | 底栏「返回营地」钮 → `closed` 信号 → presenter 关层 | camp_sub_view_base.gd:66-75、:87-88 |
| F4 | 四子界面内容根全为 ScrollContainer(横向禁滚):锻造 :46-51、秘宝 :36-48、天赋树 :18-22、图鉴 :12-16——内容超高滚动面现成 | forge_view.gd:46-51/treasure_view.gd:36-48/tree_view.gd:18-22/codex_view.gd:12-16 |
| F5 | 生涯页=`UiKit.page_shell` 全屏页壳+base 色改 `Color(UiKit.DIM, 0.6)`;顶行「生 涯」标题+「返回」钮(pressed→`_emit_closed`);内容列无滚动面 | career_overlay.gd:18-30(:20-21 页壳与遮罩色) |
| F6 | 生涯开合:组合根 `_open_career`/`_on_career_closed` 模态栈单口;入口=帐篷旁笔记本(营地语境) | main_overlay_flow.gd:40-47、:67-68;句柄 ui_modals.gd:17 |
| F7 | 四子界面开层路由:presenter `open_camp_forge/treasure/tree/codex`(`_open_modal`+投影投喂);关层单口 `on_camp_sub_closed` | camp_shop_presenter.gd:52-69、:73-75;场景点选分派 main_overlay_flow.gd:57-75 |
| F8 | 营地域句柄子容器六枚:scene/forge/treasure/tree/codex/esc_overlay | ui_camp_modals.gd:4-12 |
| F9 | ESC 优先序:`on_esc_input` ①窗开→关最上层窗(`_topmost_camp_window` 五窗集含生涯页)→②设置在浮窗上无反馈→③关浮窗→④营地语境唤起浮窗 | main_esc_flow.gd:17-30、:33-39 |
| F10 | 层序合同 LAYER_CONTRACT:camp_scene(:25)→四子界面(:26-29)→esc 浮窗(:30)→设置(:31)→状态面板(:32)→生涯页(:33);`apply_layer_contract` 是唯一层序落位点 | ui_registry.gd:15-40、:86-112 |
| F11 | 模态栈语义:open 只隐登记序在后的可见层、close 恢复——窗(低层位)开态不隐场景根(更低),生涯页(高层位)开态同此 | modal_stack.gd:21-53 |
| F12 | **既有居中定尺寸壳工厂**:`UiKit.modal_shell(parent, dim_color, min_size, separation, panel_sb)` 返回 `{dim, center, panel, box}`——全屏 dim+CenterContainer 全屏锚居中+可选 PanelContainer+VBox;窗板两条现役选型:`UiKit.panel_skinned(margin)` 石板皮(暖亮模态惯例,9 消费面含营地自家 Esc 浮窗 camp_esc_overlay.gd:19)与 `PANEL_DEFAULT` 哨兵(主题未定义 PanelContainer 默认面板=引擎灰板,仅暗语境 settlement_review 在用);min_size 定尺寸先例=settlement_review 760×560 | ui_kit.gd:501-517(哨兵 :486-498)、:596-607(panel_skinned,缺位回退 PANEL_DATA 素板);settlement_review_overlay.gd:13、legend_overlay.gd:26-27、camp_esc_overlay.gd:18-19 |
| F13 | 遮罩件 `_modal_dim`:全屏锚 ColorRect(默认 mouse_filter STOP=交互聚焦兜底);`DIM` 基色 Color(0.08, 0.06, 0.05) | ui_kit.gd:478-483、:180 |
| F14 | 探针现状五窗 rect 全为 (0,0,1280,800) 全屏(2026-11-02 主会话真渲染取证);仓库内**零**把营地域窗口几何钉成全屏的断言(grep 全探针/测试无 camp 窗 rect/margin 断言) | 本卡写卡段实测(2026-11-02) |
## 3.1 受影响既有断言面核查(逐面实测)
| 既有断言面 | 核查结论 |
|---|---|
| ui_struct_probe〔camp〕段(:41-86):场景审计/STONE 源扫描/点选路由/HUD 预留位 | 不受影响——审计根=场景根非子界面;源扫描按文件名(不改名) |
| ui_struct_probe〔career〕段+三契约(:89-106、:433-612):可见性/只读连接数=2/零动效/导航禁词 | 不受影响——换壳保持返回钮 pressed→`_emit_closed` 与 closed→`_on_career_closed` 两条连接、零 AnimationPlayer/零动效令牌、「返回」文案不含禁词(写进设计契约 4) |
| screen_flow_probe Esc 段(:238-294):四态路由/三出口/HUD 读数 | 不受影响——行为面零改 |
| ui_probe 营地段(:26-66):`tree._balance_label` 余额文案/秘宝 12 行 | 不受影响——顶栏钥石徽保留(设计契约 5) |
| ui_click_probe 树/秘宝/图签段:行板标签收集与写口链 | 不受影响——内容件零改 |
| shot_probe ①c 生涯段(:103-121):`_open_career` 函数直调、「返回」钮、「生 涯」meta 取样 | 入口与文案锚全保留;shot_career.png 像素面换代(全屏页→窗壳),shot_checker 通用判据(工程档尺寸/灰度 std≥8/唯一色数≥40)预期仍过——实现批窄验确认,若红按 S1 停机点呈报,禁放宽阈值 |
| shot_probe ②营地段(:122-131)+render golden 基线 | 不受影响——营地截图=根态(无窗);golden 逐像素只对 board 区三基线(tools/render_gate.sh 头注段③),战斗屏不动 |
| forge_workbench_test(直例化 ForgeView 断言行板/钮态/意图信号) | 不受影响——壳改不动内容件;`_balance_label` 与 `open_camp`/`refresh_camp` 签名不变 |
| theme_projection_test 生涯投影段(:796-874):标签投影/可见性 | 不受影响——成员标签与 `open_career` 签名不变 |
| layout_probe(战斗三区几何)/system_test.gd:122 层清单 | 不受影响——战斗屏不触;层清单只核登记在场 |
**测试削弱申报**:本批不删不改任何既有断言、不放宽任何阈值;新增段为纯增面。shot_career.png 像素换代属设计内形态变化(无 golden 基线、通用判据不变)。
---
## 4. 设计契约(违反即返工;标 🔴 触碰=L3 停机呈报)
1. 🔴 **窗几何起点值 720×640 单点**:生产码只落 `CampSubViewBase.WINDOW_SIZE := Vector2(720, 640)` 一个常量(camp.md v2.5 定稿值),生涯页经 `CampSubViewBase.WINDOW_SIZE` 引用,禁第二处字面值;测试断言写死规格字面值(280/80/720/640)作规格锚,双端对账由对照表承担(先例=立绘显示档批 V13 档高钉值)。
2. 🔴 **行为面零改**:开合路由(presenter `open_camp_*`/`on_camp_sub_closed`/组合根 `_open_career` 族)、模态栈语义、关闭钮 closed 信号接线、ESC 优先序(main_esc_flow)、LAYER_CONTRACT 表序与登记——本批全部零改;diff 出现上述面逻辑改动即违约。
3. 🔴 **遮罩现值维持**:遮罩=复用既有模态遮罩件(`UiKit.modal_shell` 内 `_modal_dim`),色值 `Color(UiKit.DIM, 0.6)`、全屏锚、STOP 兜底(camp.md v2.5 现值锚黑色 0.6)。
4. 🔴 **生涯页文案锚不动**:返回钮文案维持「返回」(禁含「营地」——ui_struct_probe nojump 契约在闸);标题「生 涯」文案不动(shot_probe meta 锚)。
5. 🔴 **四子界面顶底栏构件不动**:顶栏铭牌+钥石徽(`_balance_label`)与底栏「返回营地」钮维持现签名与文案(ui_probe 余额断言与关闭钮回归依赖)。
6. 🔴 **窗内滚动**:窗体尺寸不随内容增长——内容超高由既有内容滚动面(F4)在窗内滚动承载;生涯页内容列补同款滚动面(同壳同形态)。
7. 🔴 **零新美术素材**:窗壳程序化,全部经 UiKit 工厂既有 token;禁新色值/新贴图。
8. 🔴 **窗板选型=石板皮**:窗板样式盒=`UiKit.panel_skinned(Vector4(14, 12, 14, 12))`(暖亮模态惯例 9 消费面、camp_esc 浮窗同款;禁 `PANEL_DEFAULT`——主题无 PanelContainer 默认面板,落引擎灰板与营地暖亮档冲突)。
9. 🔴 **生涯页文字与底色耦合维持**:生涯页文字 token(WARM/WARM_SOFT/CANDLE/INK_L_GOLD)全部对深棕 BG_BRIGHT 调校(career_overlay.gd:38-40 对比度口径)——生涯窗内容板底色维持 BG_BRIGHT(`UiKit.panel_flat(BG_BRIGHT, PANEL_BORDER, RADIUS_OBJECT, 1, 边距)`),token 零改零重测(**范围=BG_BRIGHT 内容板上的文字**);窗板石板皮上的顶行标题墨随亮底惯例订正 `WARM`→`INK_TITLE`(§8.2 T1 明写——亮面板配深墨族,设置/状态面板先例;WARM 压亮石板 ≈1.1:1 违 §7.2,非本契约破约);禁把生涯文字压上米色 PANEL_DATA 底(亮字亮底 <4.5:1 违 art-bible §7.2)。
10. 🔴 **判据口径**:验收断言从真实入口进入(进档→场景点选真实信号路由)、判据绑窗板几何/可见性/树序/滚动实高等可观测提交面;全批无变异类测试、无撤销类取证;浮点几何判等用 `is_equal_approx`/`absf < 0.01`(禁裸 `==` 假红)。
---
## 5. 范围边界
**做**:`camp_sub_view_base._build_shell` 换壳(四窗同时生效);`career_overlay._init` 换壳+内容滚动面;探针新增窗壳形态段(V1–V8);`game/tests/README.md` 能力行(写卡段本卡同批);文件头注与行内注释随形态订正。
**不做(去向明示)**:
- 不动开合路由/模态栈/ESC 流程/层序合同(行为面零改——设计契约 2)。
- 不动四子界面与生涯页内容件(行板/钮/标签/投影逻辑零改)。
- 不出任何新美术素材;窗终值(720×640 之外)与遮罩观感校准=样张目检后的普通设计决策,实现批只按起点值落码,目检意见走反哺点。
- 不动 ESC 浮窗、设置面、选档面、确认弹窗等其他模态的形态。
- 不做窗拖拽/缩放/位置记忆(设计未含,定尺寸窗)。
- 不改 `design/` 任何文件与根规则文件(同步面义务全部列反哺点,见 §7)。
---
## 6. 关联文档同步面
| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 |
|---|---|---|
| `design/gdd/ux/camp.md`「叠层与开合」节 | 设计即本批依据(起点值已定稿 v2.5);样张目检若校准窗终值或遮罩观感 | 列反哺点清单由文档批落文 |
| `design/gdd/08-Alpha版本标准.md`「三·界面」营地行 | 在役陈述「场景图+七物件点选+Esc 浮窗与顶栏」可补窗壳形态注记 | 列反哺点清单由文档批落文 |
| `design/gdd/systems/跨局循环/生涯.md` :72 | 「营地场景图+五功能窗口形态」陈述与本批一致,无冲突 | 零义务(核查结论记实现报告) |
| `game/tests/README.md` 能力清单 | 新增能力行「营地五窗统一窗壳形态」 | **写卡段已同批补行**(本卡同一提交);实现批禁写该文件 |
| `待办清单.md` 本条 | 状态推进(文档设计已闭合→+已写卡) | 写卡段本卡同批推进;后续段由编排/收尾段推进 |
| `体验验证清单.md` | 实机目检项(窗观感/终值校准/滚动手感) | 列反哺点清单由文档批落文;目检清单先落实现报告(登记不阻塞) |
---
## 7. 卡前文件结构图
| 文件 | 职责 | 改动性质 | 验收行 |
|---|---|---|---|
| `game/presentation/views/camp_sub_view_base.gd` | 增 `WINDOW_SIZE` 常量;`_build_shell` 原地改写为 `UiKit.modal_shell` 窗壳骨架(dim 0.6+居中窗板 720×640+内容列);顶/底栏构件调用不变 | **行为改动** | V1 V2 V3 V5 |
| `game/presentation/views/career_overlay.gd` | `_init` 原地改写为同款窗壳(引用 `WINDOW_SIZE`);顶行迁入窗内容列;内容列包滚动面+BG_BRIGHT 内容板(设计契约 9) | **行为改动** | V4 V6 V8 |
| `game/probe/screen_flow_probe.gd` | 新增 `_step_camp_window_shell` 段(V1–V8 断言,插 `_step_camp_esc_and_hud` 之后) | 新增测试 | V1–V8 |
| `game/tests/README.md` | 能力清单增行「营地五窗统一窗壳形态」 | 写卡段义务(非行为) | — |
| `game/presentation/ui_registry.gd`、`game/presentation/main_ui_build.gd` | 行内注释「独立全屏页/只读全屏页」(:26/:100/:139)随形态订正 | 非行为改动(注释零逻辑) | — |
| 两视图文件头注 | 壳形态描述随动(窗壳) | 非行为改动(注释零逻辑) | — |
结构图与 §12 落位预检互指:本批**零新增文件**;两处壳改写=存量触面原地改写(复用既有件,见 §12)。
---
## 8. 任务卡 T0..T3
### 8.1 T0——四子界面窗壳改造(估时 0.5–1 个工作日)
- [ ] 环境就绪:worktree 内拷主区 `.godot/` 导入缓存(或跑 `D:\code\godot\Godot_v4.7.2-stable_win64_console.exe --headless --editor --quit --path game` 刷);跑 `python tools/gdstyle_gate.py` 记录改前 S13 读数(camp_sub_view_base.gd/career_overlay.gd 现行零基线键),存实现报告改前基线。
- [ ] `camp_sub_view_base.gd` 增类常量 `const WINDOW_SIZE := Vector2(720, 640)`(注释注明 camp.md v2.5 起点 定值单点)。
- [ ] `_build_shell` 原地改写:`var shell := UiKit.modal_shell(self, Color(UiKit.DIM, 0.6), Vector2.ZERO, 8, UiKit.panel_skinned(Vector4(14, 12, 14, 12)))`,随后 `shell.panel.custom_minimum_size = WINDOW_SIZE`(窗板外缘即 720×640,`min_size` 参数保持 ZERO 使窗板尺寸精确可钉;panel_skinned 边距被 PANEL_SLICE 钳到 16——ui_kit.gd:597-598 既有工厂行为);`_build_top_bar(shell.box, title, icon_path)`、内容体 PanelContainer(PANEL_DATA 样式盒与 EXPAND_FILL 沿用)挂 `shell.box`、`_build_bottom_bar(shell.box)` 三段调用不变;删除全屏 MarginContainer 16/16/12/12 骨架;`visible = false` 初始隐维持。
- [ ] 文件头注随动(近全屏面板形态描述→居中定尺寸窗壳)。
- [ ] 确认 forge/treasure/tree/codex 四视图 `_init` 零 diff(壳改即四窗全换——F4 内容滚动面不动)。
- [ ] 孤立验证:`…console.exe --headless --path game --script res://tests/unit/presentation/forge_workbench_test.gd` exit 0(行板/钮态/意图信号回归)。
- [ ] 复跑 `python tools/gdstyle_gate.py`:camp_sub_view_base.gd 零新键(S13 只降不升达成)。
**取用**:无。**产出**:`CampSubViewBase.WINDOW_SIZE`(Vector2 常量)+四窗窗壳化(窗板=shell.panel、内容列=shell.box 的结构形态——T1/T2 取用)。
### 8.2 T1——生涯页同壳改造(估时 0.25–0.5 个工作日)
- [ ] `career_overlay.gd` `_init` 原地改写:`UiKit.page_shell` 调用与 `page.base.color` 字面量退役;换 `var shell := UiKit.modal_shell(self, Color(UiKit.DIM, 0.6), Vector2.ZERO, 8, UiKit.panel_skinned(Vector4(14, 12, 14, 12)))`+`shell.panel.custom_minimum_size = CampSubViewBase.WINDOW_SIZE`;顶行(「生 涯」标题+spacer+「返回」钮,文案与连接零改)迁入 `shell.box`,**标题墨 token 订正 `WARM`→`INK_TITLE`**(亮面板配深墨族——设置/状态面板先例;契约 9 的「token 零改」范围=BG_BRIGHT 内容板上的文字,顶行压石板皮不在此列);内容列(hint+组一行板)包 ScrollContainer(`SIZE_EXPAND_FILL`、横向禁滚——同 F4 形态)进 `shell.box`;滚动面外再垫内容板 PanelContainer(样式盒=`UiKit.panel_flat(UiKit.BG_BRIGHT, UiKit.PANEL_BORDER, UiKit.RADIUS_OBJECT, 1, Vector4(12, 12, 12, 12))`——原页底色随壳迁移,内容板文字 token 零改,设计契约 9);成员标签变量与 `open_career` 签名零改。
- [ ] 文件头注随动(只读全屏页→只读功能窗口);头注 :3 陈旧入口陈述(「入口唯一在开始覆盖层『营地与系统』组」——卡④ T3 改挂帐篷旁笔记本后遗留)一并订正为笔记本入口。
- [ ] 孤立验证:`…console.exe --headless --path game --script res://tests/unit/presentation/theme_projection_test.gd` 生涯投影段与全件 exit 0。
- [ ] 复跑 `python tools/gdstyle_gate.py`:career_overlay.gd 零新键。
**取用**:T0 的 `CampSubViewBase.WINDOW_SIZE`。**产出**:生涯页同壳(同构窗板/内容列——T2 取用)。
### 8.3 T2——探针窗壳形态段(估时 1–1.5 个工作日)
- [ ] `screen_flow_probe.gd` 新增 `func _step_camp_window_shell() -> void`,插 `_ready` 中 `_step_camp_esc_and_hud()` 之后;前置 `ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_winshell")`(真实进档入口)。断言明细(新码全类型标注;每断言带〔窗口化批 Vn〕尾缀):
- **V1 四窗几何**:循环 `[&"forge", &"chest", &"dummy", &"board"]` 逐一键 `object_pressed.emit(k)`(每窗先经真实关闭钮关前窗),经视图子树取 CenterContainer 下的 PanelContainer 为窗板,断 `get_global_rect()` 位置 ≈ (280, 80)、尺寸 ≈ (720, 640)(浮点容差 0.01)。
- **V2 场景根留底**:每窗开态断 `main.ui.modals.camp.scene.visible == true` 且窗板矩形四边距视口边 ≥80px((800−640)/2 恰等 80——判等沿 V1 容差 0.01;V1 等值蕴含,独立断言钉场景根可见)。
- **V3 遮罩 0.6**:每窗开态断视图首个子节点 ColorRect(遮罩件)`color.a ≈ 0.6` 且 `size` 与视口尺寸沿 V1 容差 0.01 判等(禁裸 `==`——契约 10)。
- **V4 关闭钮回归**:四窗经底栏「返回营地」、生涯窗经顶行「返回」真实 Button `pressed.emit()` → 断窗隐(visible==false)且场景根仍 visible。
- **V5 互斥单开与点选遮挡**:每窗开态断五窗集(forge/treasure/tree/codex/career_overlay)visible 计数 == 1(轮转开合逐窗断);另在树窗开态取锻炉命中区中心(`camp_scene.get_hotspot_rect(&"forge")` 公开读面,camp_scene_view.gd:83——场景根全屏锚下局部==全局)`push_input` 真实鼠标点击事件 → 断无任何新窗打开、树窗仍开(窗下场景点选被遮罩挡——模态遮挡可达性探针标配)。
- **V6 ESC 先关窗**:`object_pressed.emit(&"notebook")` 开生涯窗 → `push_input` 真实 Esc 键事件(:114-120 同款)→ 断生涯窗隐且 esc 浮窗未开。
- **V7 内容超高窗内滚动**:`object_pressed.emit(&"dummy")` 开树窗 → `tree_view.refresh_camp()` 喂真实 `main._camp_data()` 投影追加 30 行合成行(行结构与树投影同型:vein=spine/kind=stat/node_id=probe_row_i/can_buy=false)→ 喂入后 `await` 帧再断(queue_free 摘行与 min size 重算帧末延迟——探针 `_frames()` 惯例)→ 断(a)窗板 rect 仍 ≈ (280, 80, 720, 640)(窗不随内容涨)(b)树滚动容器内容实高(`_tree_holder.size.y`)> 滚动容器实高(超高实据)。
- **V8 生涯同壳**:`object_pressed.emit(&"notebook")` 开生涯窗 → 断窗板 rect 同 V1 等值+「返回」钮在位+内容列滚动面在(窗内容子树 ScrollContainer 存在且纵向 EXPAND_FILL——同壳滚动面结构钉)。
- [ ] 段尾收闭:最后开的窗(含生涯窗——`on_camp_closed` 关闭名单只含场景根+四子界面+选档层,不含 career_overlay)经各自真实关闭钮关闭后,再 `main._on_camp_closed()` 复归菜单语境(防生涯窗残留开态泄入后续段——后续 `_step_save_select_open_back` 段前提不受扰)。
- [ ] 孤立验证:`…console.exe --headless --path game res://probe/screen_flow_probe.tscn` exit 0(新段+既有段全绿)。
- [ ] 窄验 shot_probe:窗口化跑 `…console.exe --path game res://probe/shot_probe.tscn -- <临时目录>` exit 0,确认生涯段(「返回」钮/「生 涯」meta)与七屏自检在窗壳形态下通过(shot_career.png 通用判据 std/色数读数记实现报告)。
**取用**:T0 窗板结构(CenterContainer→PanelContainer)与 `WINDOW_SIZE`;T1 生涯窗同构。**产出**:V1–V8 断言段+shot_probe 窄验读数。
### 8.4 T3——产出物落位卡(估时 0.25–0.5 个工作日)
- [ ] 代码域闸全绿:`bash tools/run_all_gates.sh --code`(里程碑步出口跑一次全套;波内修复只做出红件最窄确认;新增测试已先行孤立验证)。
- [ ] `reports/iter<N>-实现报告-<日期>.md`:各卡状态+实机目检总清单(登记不阻塞:①五窗观感与场景可见度样张判定;②窗终值 720×640 与遮罩 0.6 观感校准意见;③窗内滚动手感)+遗留读数义务+实现决定记录(超白名单事项逐条记决了什么/为什么/代价/撤销方式)。
- [ ] `reports/iter<N>-反哺点-<日期>.md`:§6 同步面每条落点(camp.md 校准注记/08-Alpha 行注记/体验验证清单入册)。
- [ ] 独立验收审计:`reports/iter<N>-验收审计-<日期>.md`(没参与实现的会话或子代理执行;未过不得合并)。
**取用**:T0–T2 全部产出。**产出**:闸全绿回执+两份产出物+审计报告。
---
## 9. 验证闸(改动—验收对照表)
| 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|---|---|---|---|---|---|---|
| 四子界面统一窗壳 720×640 起点居中 | camp_sub_view_base.gd `_build_shell`(:14-37 原地改写)+`WINDOW_SIZE` 常量 | 「四窗窗板 global_rect 位置≈(280,80)、尺寸≈(720,640)」`screen_flow_probe.gd:_step_camp_window_shell`〔窗口化批 V1〕 | 探针 | 选档层进档(`open_camp_via_savesel` 真实钮信号)→场景点选 `object_pressed` 真实信号路由 | 窗板全局 rect 浮点等值(容差 0.01) | 新增:营地五窗统一窗壳形态 |
| 窗明显小于屏+场景根留底大面积可见 | 同上(窗居中+dim 全屏不遮场景根——F11 栈语义) | 「窗开态 camp.scene.visible==true 且窗板四边距视口边≥80px」〔V2〕 | 探针 | 同 V1 | 场景根可见性状态源+窗板 rect 边距 | 新增:营地五窗统一窗壳形态 |
| 遮罩 0.6 回归 | modal_shell dim 件(`Color(UiKit.DIM, 0.6)`) | 「五窗开态遮罩 ColorRect alpha≈0.6 且全屏」〔V3〕 | 探针 | 同 V1 | 遮罩件 color/size 状态源实读 | 新增:营地五窗统一窗壳形态 |
| 各窗关闭钮回归(行为面零改的回归钉) | 零改动行——`_build_bottom_bar`/`_emit_closed`/career「返回」钮沿用(F3/F5) | 「四窗『返回营地』/生涯『返回』真实钮 pressed→窗隐且场景根留底」〔V4〕 | 探针 | 窗内真实 Button pressed 信号 | 钮信号→窗 visible 终态 | 既有:四柜台拆解后五界面入口改挂与写口零回归 |
| 五窗互斥单开回归(行为面零改的回归钉) | 零改动行——模态栈语义+遮罩 STOP 兜底(F8/F11/F13) | 「逐窗轮转开合五窗 visible 计数恒 1+窗开态向锻炉命中区(`get_hotspot_rect` 读面)推真实鼠标点无新窗打开(点选被遮罩挡)」〔V5〕 | 探针 | 同 V1 路由+V4 关闭钮+`push_input` 真实鼠标事件 | 五窗 visible 计数+点穿零响应 | 既有:模态句柄分域寻址面 |
| ESC 优先序回归(行为面零改的回归钉) | 零改动行——`_topmost_camp_window` 五窗集含生涯页(F9) | 「生涯窗开态 Esc 先关生涯窗、浮窗不唤起」〔V6〕 | 探针 | `push_input` 真实 Esc 键事件 | 窗 visible 终态+esc 浮窗 visible | 既有:Esc 浮窗唤起与三出口动线 |
| 内容超高窗内滚动(树长列表实据) | 壳改后窗体定尺寸+F4 既有滚动面承载;生涯页补滚动面(career_overlay `_init`) | 「加长行册喂入后窗板 rect 仍等值(窗不涨)+滚动内容实高>滚动视口实高」〔V7〕 | 探针 | `object_pressed(&"dummy")` 开树窗+`refresh_camp`(presenter 同款真实数据投喂口)喂加长行册 | 窗板 rect 不变量+内容实高差 | 新增:营地五窗统一窗壳形态 |
| 生涯页同壳同形态 | career_overlay.gd `_init`(:18-58 原地改写) | 「生涯窗板 rect 同 V1 等值+『返回』钮在位+内容列滚动面在+投影标签回归(theme_projection_test 全件 exit 0)」〔V8〕 | 探针+单元 | 笔记本点选 `object_pressed(&"notebook")` 路由;单元侧 `CareerOverlay.new().open_career()` 真实数据口 | 同一几何判据+文案锚+滚动面结构+标签投影 | 新增:营地五窗统一窗壳形态 |
**非行为改动声明(反向覆盖)**:注释随动六处(ui_registry.gd:26、main_ui_build.gd:100 与 :139、camp_sub_view_base.gd:2 头注、career_overlay.gd:2 头注与 :19 行注——「独立全屏页/全屏页壳」陈述随窗壳化订正)=非行为改动——零逻辑、零签名、零接线变化,行为判据由上表 V1–V8 行覆盖。
**判据口径**:全批无变异类测试、无撤销类取证;每行从真实入口进入、绑被测改动特有的可观测提交面;扫描类判据带非空前置。
**测试削弱申报**:见 §3.1 末——零删改零放宽。
**代码域闸命令(里程碑步出口跑一次全套,波内修复只做出红件最窄确认;新增测试先行孤立验证再并入全套)**:`bash tools/run_all_gates.sh --code`。
---
## 10. 异常分级
- **L1 自救**:`.godot` 缓存失配 → 重跑 `--editor --quit` 刷导入;探针隔离档陈旧 → 重跑 `isolate_save` 前置。
- **L2 记录继续**:加长行册喂入后滚动条部件读数因主题样式偏差不可靠 → 改绑内容实高差判据(V7b)并记录读数,禁删断言;shot_probe 生涯段通用判据读数贴近带缘 → 读数记实现报告盯 CI。
- **L3 停机写报告等用户**:
1. V1–V8 任一断言在真实跑批中做不出(判据绑不上可观测提交面)→ 停卡呈报,禁放宽阈值、禁换下层直调;
2. `UiKit.modal_shell` 骨架与本卡契约互斥(如窗板无法精确等值钉 720×640)→ 停卡退回写卡段,禁自造第三条路;
3. 机检预算互斥=上游缺陷停卡退回写卡段(S13 键与卡片契约冲突时禁为过闸保留无效成员);
4. 实现中冒出卡片未写清的形态分歧 → 停该卡退上游,禁内联求裁。
---
## 11. 代拍板白名单(超清单必呈报)
1. 窗板样式盒微调:`panel_skinned` 边距取值(Vector4 各分量 ±8px 内)与 tint——观感随样张目检校准面;选型本身(石板皮)与生涯内容板底色(BG_BRIGHT)属设计契约 8/9 不在白名单。
2. `WINDOW_SIZE` 常量等价命名(如 `CAMP_WINDOW_SIZE`)与生涯页引用写法——单点定义与引用关系不变。
3. 探针段测试参数取值:加长行册行数(30)与合成行字段值——非断言值的夹具参数。
4. 断言消息尾缀〔窗口化批 Vn〕括注用词格式。
5. 窗内容列 separation 等间距微调(±4px 内)——观感校准面。
---
## 12. 落位与可复用性预检
| 新增件 | 复用面(盘上是否已有同职责件) | 唯一面 | 分层与交互面 |
|---|---|---|---|
| `CampSubViewBase.WINDOW_SIZE` 常量 | 无同类常量(现行壳无定值几何);不新增文件,落壳基类 | 窗几何值 GDScript 侧只此一处;生涯页经类常量引用不自设值 | 呈现层内部常量,不跨层 |
| `_build_shell` 窗壳骨架 | **复用 `UiKit.modal_shell`**(ui_kit.gd:501-517,现役九消费者含 settlement_review 定尺寸先例)+`_modal_dim` 遮罩件+`panel_skinned` 石板皮窗板(:596-607,9 消费面惯例)——不新造工厂、不新造遮罩、不新造窗板样式 | 居中定尺寸壳骨架全仓唯一落点=UiKit.modal_shell;本批零新工厂 | 纯呈现层;视图零核心写调用不变;开合仍走模态栈单口(presenter/组合根零改);RngService/ConfigDB 不触及 |
| 生涯页滚动面 | 复用 ScrollContainer 既有形态(F4 四子界面同款) | 生涯内容列滚动面只此一处 | 同上 |
| 探针 `_step_camp_window_shell` | 复用 screen_flow_probe 既有步骤框架与 ProbeUiUtil 隔离样板(不新增探针文件) | 窗几何断言只落此段一处(段内五窗循环) | 测试侧只读,不反向驱动呈现 |
**为什么不能复用更多**:`_build_shell` 现行手搓的全屏 MarginContainer 骨架(F1)正是本批要退役的形态——改写为调用 modal_shell 即完成复用;生涯页 page_shell 为全屏页专用工厂(设置面/选档面仍在用),退役的是调用点不是工厂本体。
---
## 13. 拆分边界纪律适用性声明
本批为呈现形态换壳(行为改动批),非拆分/收敛/重构类卡——零职责重组、零成员迁移(`_build_top_bar`/`_build_bottom_bar`/成员变量原地沿用)。壳内构件沿用既有职责边界:顶栏=铭牌+余额徽、底栏=关闭钮、内容体=子类内容滚动面,单一变化原因=承载几何。若实现期为凑 S13 键而拆分或收拢成员,一律停卡呈报(L3 #3)。
---
## 14. 实现规范预算
- **新件三查**:本批**零新增 .gd 文件**(§12 复用面已定),接口块公开方法数与成员变量数三查不适用;新增类常量 1 个(const 非成员变量,不触 var 上限)。
- **存量触面一查(S13 键只降不升)**:`camp_sub_view_base.gd`(在面,现行零基线键)——`_build_shell` 原地改写不增成员、不增公开方法、分支数不升(dim/center/panel/box 直列无分支);`career_overlay.gd`(在面,现行零基线键)——`_init` 原地改写同上。T0/T1 各带改前改后 `python tools/gdstyle_gate.py` 读数对账(§8.1/§8.2 末步)。
- **测试侧纪律**:探针新段全类型标注(test-conventions §6 义务);断言内规格字面值(280/80/720/640/0.6)为规格锚非第二事实源(设计契约 1 双端对账口径)。
- **指标例外申报**:无。
---
## 15. 待裁点
**零待裁点,开工门 = U0。** 三点裁决(2026-11-01:功能窗口形态/遮罩 0.6+互斥+关闭钮/ESC 优先序)与两点补裁(2026-11-02:五窗统一居中定尺寸窗壳起点 720×640+生涯页同壳同形态)全在案于 camp.md v2.5「叠层与开合」节与待办清单条目实况;窗观感终值与遮罩观感校准属样张目检后的普通设计决策(camp.md v2.5 明文),归代拍板白名单与反哺点,不构成本卡待裁点。
---
## 16. 估时与切分预案
≈2.75 个工作日(T0 0.5–1/T1 0.25–0.5/T2 1–1.5/T3 0.25–0.5,中值合计 2.75)。
切分预案:T0 与 T1 同壳同骨架、可独立验收(四窗先换、生涯页随后),若 T2 探针段压超软盒,切分点=把 T2 拆成「四窗+回归钉段」与「生涯同壳+滚动实据段」两卡同迭代合回,不拆迭代;若实机样张判窗观感不可受(终值需大调),本卡止于 L3 呈报走反哺点,校准后另立微调批。
+3 -3
View File
@@ -5,8 +5,8 @@
## 当前位(只回答「现在该做什么」;三行内随批次换代,禁止在此扩写成状态快照)
- **阶段**:M3——Alpha 版本的完整实现(2026-10-09 立规:未明令宣布完成前停留 M3,迭代只排 M3 需求,M4 不排期;根目录 stage.txt 为旧阶段开关仅存档)。
- **迭代位**:迭代 1–48 全部已完成——迭代 48(状态合并累加制+立绘显示档+战斗区背景替换三卡)2026-11-02 合回(合并提交 4c94eee3,独立验收审计首轮窄口径三项缺漏修齐后复审通过;CI 红三项随 fix-iter48ci 追绿,提交 4b626261),批后收尾闭合(2026-11-02):反哺点十六条处置闭合(art-bible v3.36 §6.1 背景三句实装化+§4.1 换色合并登记③ STAGE_BG 退役改指/art-prompts v2.14 产出状态已落位/battle-stage-prompts v1.9 ground_h 已回填与四柱已退役/battle.md 布局字段补 ground_h 与光柱氛围层退役句/HUD框架 B 区行补三关背景+连续地面层/数据配置 v1.2 布局表用途句补地面层高/增益状态 v1.4 字段表词表换代累加+现行十行补护身 defensive_stance 行〔存量漏登补录〕/08-Alpha v1.24 立绘显示清晰度行换在役〔用户裁〕/术语表立「显示档」条〔用户裁〕/art-status-checklist 与 art-assets-checklist 站桩行已交付换代;architecture v1.30 ConfigDB 行 SCHEMA_VERSION 失真句订正〔迭代 41 测试债批遗留义务〕)、目检十项登记体验验证清单 ㊻+迭代 41 测试债批三项补登记 ㊼、产出物退役九件(三需求卡片+反哺点+实现报告+验收审计+停机呈报+代拍板追认单+迭代 41 测试债批实现报告〔遗留义务已清:闸基线换代随工程小件批落地〕)、待办清单三卡条目整条删除(状态机出口)+status_effects.tres 陈旧批注处置〔待用户裁〕与 ui_kit.gd 注释顺带换代两条新登记(未决先迁)。迭代 47 收尾记录见 git 提交 bd54d1f4,迭代 46 见 73fc11eb。
- **下一步**:迭代 49(效果端口与掷格分件+模态句柄分域+营地五界面真窗口化三卡,≈7.25 个工作日,卡序=核心域先行——端口分件 EV 锚逐位主证早曝、表现两卡殿后集中目检)已编排待 `/iter` 发令开工。待编池:冒险前资源配比预设(冻结备选)、迭代 30 原卡②③(2026-10-17 已剔出迭代 30 规划、退回待设计,待美术/设计定稿后重新立卡)。
- **迭代位**:迭代 1–49 全部已完成——迭代 49(效果端口与掷格分件+模态句柄分域+营地五界面真窗口化三卡)2026-11-02 合回(合并提交 549683a5,独立验收审计通过〔缺漏 0、例外 1 在案〕),批后收尾闭合(2026-11-02):反哺点九条处置闭合(architecture v1.31 轴戊两件与功能层四行换代已建件现状〔EffectPort 六 Callable 路由/RewardRoller 掷格面迁出、B4 公开面 weighted_pick 退役、roll_board 装配序五步、五件类变量实数在案〕+ui_registry 行三域句柄分域换代〔run/menu 两子容器新建、ModalFlow 升格注册面直驻、寻址 `modals.run.*`/`modals.menu.*` 换代〕/术语表 v1.26 立「效果端口件」「掷格件」两条〔用户裁〕/camp.md v2.6 叠层与开合补窗壳形态已实装注记/08-Alpha v1.25 三·界面营地行补窗壳形态在役注记/体验验证清单 ㊽ 登记目检两项/static_scan.sh S8 头注计数句订正 10→14)、产出物退役六件(三需求卡片+反哺点+实现报告+验收审计——吸收即死+证据只留最新)、待办清单三卡条目整条删除(状态机出口)。迭代 48 收尾记录见 git 提交 aa396eb9,迭代 47 见 bd54d1f4。
- **下一步**:迭代 50 编排待发令(`/iter-plan`)——候选=断言补齐批卡(V1–V16 四域断言补齐,已写卡 2026-11-02)。待编池:冒险前资源配比预设(冻结备选)、迭代 30 原卡②③(2026-10-17 已剔出迭代 30 规划、退回待设计,待美术/设计定稿后重新立卡)。
## 里程碑时间线
@@ -82,7 +82,7 @@
| 迭代 46 | 已完成(2026-11-01) | 已退役(git 历史可考) | 2026-11-01 | ≈8.625 个工作日 | 已退役(git 历史可考) |
| 迭代 47 | 已完成(2026-11-01) | 已退役(git 历史可考) | 2026-11-01 | ≈15 个工作日〔用户特批 2026-11-01 超 10 个工作日〕 | 已退役(git 历史可考) |
| 迭代 48 | 已完成(2026-11-02) | 已退役(git 历史可考) | 2026-11-01 | ≈6.1 个工作日 | 已退役(git 历史可考) |
| 迭代 49 | 待开工 | reports/需求卡片-效果端口与掷格分件批-2026-11-02.md<br>reports/需求卡片-模态句柄分域批-2026-11-02.md<br>reports/需求卡片-营地五界面真窗口化批-2026-11-02.md | 2026-11-02 | ≈7.25 个工作日 | — |
| 迭代 49 | 已完成(2026-11-02) | 已退役(git 历史可考) | 2026-11-02 | ≈7.25 个工作日 | 已退役(git 历史可考) |
- 迭代 38 收口为带红合并〔用户特批 2026-10-26〕:09 静态扫描 S13 gdstyle 恶化 2 条经批准记入基线存量红(git 提交 c4c69701),卡② 停卡退上游,处方已于 2026-10-26 修订定稿 v1.3(git 提交 b3ea7532),随「gdstyle 存量债全量清偿」条目波 7 待编排。
- 迭代 39 收口为带红合并〔用户特批 2026-10-27〕:02 EV 锚 goblin 0.9148∉[1.00,1.20](触发器批有意行为改动,fp f74b9a48ef4a)已随 EV 锚重锚批换带归绿(git 提交 ba5105aa);08d 生涯.md:55 行号漂移已随 2026-10-28 批后收尾反哺落文修复归绿。三卡拆分后终局 gdstyle 恶化 2 条(battle_orchestrator max-file-length、level_map_screen max-class-variables)归迭代 40 卡①还债与迭代 41 存量债序列。
+8 -2
View File
@@ -7,7 +7,8 @@ r"""capability_audit.py — 能力清单、覆盖域表与 GDD 纯度机检(
B 验收标准:design/gdd/systems/** 每篇须有非空的「## 验收标准」节(豁免件具名在册,附理由)。
C 能力行结构:game/tests/README.md 能力表四列齐、逐行四格非空。
D 代表用例可核(双通道):能力行「代表用例」的每条 `文件:函数`——代码在(文件在 run_all.gd 套件
manifest 内且该文件有 `func 函数名(`)或卡在(该文件名或函数名能在 reports/需求卡片*.md 中找到,
manifest 内且该文件有 `func 函数名(`,或该文件是 game/probe/ 下的探针件且件内有 `func 函数名(`——
探针不进 run_all manifest,单独认探针面)或卡在(该文件名或函数名能在 reports/需求卡片*.md 中找到,
供写卡时当场入表的计划用例锚定);两头都无=红(清单挂了无凭证义务)。
E 真实入口可核(双通道):能力行「真实入口」的每个 `类.方法()`——产品码(game/ 除 tests//probe//sim/)
有 `func 方法(`,或该方法名能在 reports/需求卡片*.md 中找到(计划入口同 D 口径);两头都无=红。
@@ -225,12 +226,17 @@ def check_cases(no, name, cell, suite_by_base, funcs, cards):
"「%s」格格式应为 `文件.gd:函数`:%s" % (name[:16], chunk[:40]))
continue
fname, fn = m.groups()
# 双通道(test-conventions §8.9):代码在(套件 manifest 内且 func 在文件里)
# 双通道(test-conventions §8.9):代码在(套件 manifest 内且 func 在文件里;
# 探针不进 run_all manifest——game/probe/ 下探针件在库且 func 在件内同样算代码在)
# 或卡在(文件名/函数名见于 reports/需求卡片*.md——写卡时当场入表的计划用例)。
hits = suite_by_base.get(fname, [])
code_ok = bool(hits) and any(
re.search(r"^(?:static\s+)?func\s+%s\s*\(" % re.escape(fn), read(RUN_ALL.parent / rel), re.M)
for rel in hits)
if not code_ok:
probe = REPO / "game" / "probe" / fname
code_ok = probe.is_file() and bool(
re.search(r"^(?:static\s+)?func\s+%s\s*\(" % re.escape(fn), read(probe), re.M))
card_ok = bool(cards) and (fname in cards or fn in cards)
if not code_ok and not card_ok:
red(README.relative_to(REPO), no, "代表用例",
+12
View File
@@ -578,3 +578,15 @@
| 3 | 调参面板批量模拟 | 模拟运行期间浮窗置灰、全部局结束后解除 |
- **红灯信号**:数字垫牌错族、胜利总结面开不出、置灰态失灵即报缺陷。
## ㊽ 迭代 49——营地五窗真窗口化目检(2026-11-02 随批后收尾登记)
> 三卡合回(2026-11-02,合并提交 549683a5):卡③ 营地五界面真窗口化批交付真窗口化形态(统一居中定尺寸窗壳,起点 720×640;遮罩压暗锚 0.6);卡①② 行为零变化、零新增目检项。独立验收审计通过(缺漏 0、例外 1 在案);机检读数与论证详见实现报告(git 提交 549683a5 一线可考)。登记不阻塞(2026-10-12 真人检测立规)。
| # | 目检项 | 判据 |
|---|---|---|
| 1 | 五窗观感与场景可见度样张判定 | 五窗(锻造工坊/天赋树/秘宝匣/图鉴/生涯)在 720×640 起点窗壳与遮罩压暗 0.6 下观感可接受、营地场景大面积可见;校准意见回填 camp.md「叠层与开合」节终值 |
| 2 | 窗内滚动手感 | 内容超高窗(天赋树长列表/生涯页)滚动顺滑、无卡滞与内容截断 |
- **红灯信号**:窗壳挤压屏面、场景几乎不可见、滚动卡滞或内容溢出窗板即报缺陷。
- **结论回流**:观感校准意见回填 camp.md 终值(普通设计决策);呈现缺陷归待办清单登记新条目。
-31
View File
@@ -69,21 +69,6 @@
**状态**:文档设计已闭合+已写卡
#### 战斗域结构深拆批——效果发射端口+掷格/受理分件(2026-10-31 重立,来源=批次移交)
**实况**:本条为 2026-10-27 原条目的重立版(原条目含宿主瘦身子项,该子项完成后随净零重立一并出清,git 历史可考)。三条同病根的结构债,需先一次设计讨论定端口形态,再谈切卡;`RewardEconomy` 的最小缝拆样本已由迭代 40 卡② 落卡。**宿主瘦身子项已完成(2026-10-30 随迭代 44 卡② 战斗编排归约批合回,合并提交 bee73db5——RoundCycle/BattleFacts 两新件建件,宿主实测 15 类变量/811 行,验收审计通过;原需求卡片与设计过程稿已按吸收即死退役,git 历史可考)。**
- 效果发射端口(设计题本体):`game/core/damage_controller.gd:46/47/71` 与 `game/core/action_economy.gd:44/45/50` 仍直持 `EffectEngine`+`EffectContext`——前者用 attack_commit/armor_roll/clamp_check/kill/damage_taken 五枚事件并带计数器读写回写(:348/:354),后者用 dig_paid/dig_stop/charge_full 三枚事件。`RewardEconomy` 同款直连已由迭代 40 卡② p5 缝拆实装合回(单枚查询口 `luck_bias_query`——成员 −2+2、类变量净 15、判定归 `BattleFxHost.luck_bias_for`),最小样本在库可考;另两处事件多且带计数器回写,缝拆不成立,必须先设计「业务类只持一个回调、取回命中批」的端口形态。
- reward_economy 分件:`RewardEconomy` 现 15 类变量恰在阈值线上(加第 16 枚即出闸 09 新增红——迭代 40 卡② 施工实测撞见,正是本条登记起因),掷格面(install 期 roll/池行装配/权重合成)与受理账面(grant/身份查询/快照/retire)两职责同居一件。
- 相关文档:design/engineering/architecture/architecture.md(系统分层图与功能层 B1/B4 行、「战斗编排域拆件定稿」节轴戊——2026-11-02 定稿)· reports/审计-gdstyle存量债清点与清偿方案-2026-10-26.md(216 键波次方案与残留债口径;在册「尾波」只覆盖迭代 39 三宿主,不含本条)· 结构小件定点修批卡已随迭代 40 合回退役(git 历史可考,合并提交 514457d1;缝拆样本与 2026-10-27 用户裁史见该卡 git 版本)
**2026-11-02 设计闭合(用户两点裁甲案)**:端口形态=独立端口小件(单实现零接口抽象)、分件切向=掷格面迁出(受理账面留守)——[architecture](design/engineering/architecture/architecture.md) v1.29「战斗编排域拆件定稿」节轴戊定稿(职责语句/账面归属/衔接面/行为零变化红线全在案),缺口清零。
**2026-11-02 写卡**:需求卡片 reports/需求卡片-效果端口与掷格分件批-2026-11-02.md(v1.0,零待裁点,开工门=U0);能力行「效果发射端口单点」同批入 game/tests/README.md 能力清单。
**改动面**:游戏代码
**状态**:文档设计已闭合+已写卡+已编迭代 49
#### 数值标定窗口总挂账——原九条数值类条目合并(2026-10-28 登记,来源=会话提及)
**实况**:2026-10-28 用户令把九条数值类挂账合并为一条:削弱档位的最终数值/迭代 10 奖励重构联动欠账/调参批数值点评登记/三方向各自的解锁清单与定价/GP 经济换算失衡/天赋树实装批登记欠账余两件/商店独立刷新机制两参数/基线通关率越带加难杠杆扫描/成长系数节奏——原九条同步删除,内容全量迁入汇总文档,git 历史可考(本提交)。共同背景:M4 数值批卡已随 2026-10-16 删卡令退役;2026-10-18 用户裁=各条留待办清单、未设计未启动、不另行归属,未来数值标定窗口重开时重走设计段再写卡——本条沿用该裁定,重启条件=用户发令开窗口。合并动机=九条共享同一重启条件与同一执行形态(窗口内一次 MC 批量统一覆盖各条对比需求:全冒险期望+奖励期望),分散登记徒增维护面。逐条挂账明细、裁定史与相关文档见汇总文档。
@@ -110,14 +95,6 @@
**状态**:待文档设计
#### 营地五界面窗口化批——营地功能页点开后的呈现形态(2026-10-22 登记,来源=会话提及)
**实况**:营地场景图(卡④)把旧四柜台换成「一张可点击的场景图」,从场景图点进去的**五个功能界面**——锻造工坊/秘宝匣/天赋树(树淬炼)/奖励格图鉴/生涯记录——其呈现形态原属卡④ §9 代拍板白名单第 2 条,故单独立批。**2026-11-01 用户裁三点闭合**:①承载形态=功能窗口·场景根留底+半透明压暗遮罩(交互聚焦用,复用既有模态遮罩件,现值锚 0.6)+五窗互斥单开(模态栈深恒 1)+各窗自带关闭钮(卡④ v1.1 承诺面);②ESC 优先序=有功能窗口开着先关最上层窗、无窗才进卡⑤ ESC 浮窗四态;③前置冲突消解=art-bible §2「情绪明暗禁令」整块删除(用户裁:明亮基调为正向方向,压暗属普通设计决策逐案走样张目检——该禁令查无正向拦截实例,同批修 art-bible 七处引用站)。**与「营地美术素材怎么生成」无关联**(不影响出图/分层/提示词);零新美术素材。定稿凭据:[camp](design/gdd/ux/camp.md) v2.5「叠层与开合」节+[art-bible](design/art/art-bible.md) v3.32(禁令删除批)。**2026-11-02 真窗口化补裁(用户令重开设计)**:迭代 47 实装把「功能窗口」落成近全屏面板(四周约 16px 暗边、场景几乎不可见),用户裁重走窗口化设计并两点补裁——①五窗统一居中定尺寸窗壳(起点 720×640,窗明显小于屏、场景大面积可见,终值随样张目检校准,内容超高窗内滚动);②生涯页与四子界面同壳同形态(全屏深色叠层退役)。实现属后续卡(卡④已完工)。**2026-11-02 写卡**:需求卡片 reports/需求卡片-营地五界面真窗口化批-2026-11-02.md(v1.0,零待裁点,开工门=U0);能力行「营地五窗统一窗壳形态」同批入 game/tests/README.md 能力清单。
**改动面**:文档+游戏代码
**状态**:文档设计已闭合+已写卡+已编迭代 49
#### UI 贴图重构批——元进度件仍是程序化占位(2026-10-13 登记,来源=审计发现)
**实况**:营地的柜台场景贴图与元进度图标目前都是程序化画出来的临时形态,没有上贴图。这条债原先只写在美术侧的资产清单里([美术资产清单](design/art/art-assets-checklist.md) 第 134 行与第 175 行,原文注明"营地现为程序化占位,状态记录 121⑧ 口径,排期归 UI 贴图重构批"),2026-10-13 由 UI 美化三层诊断转立本清单专条。规格其实已经定了——烛光黄 `#F6C667` 配木色 `#8A5A34`(见 [美术圣经](design/art/art-bible.md) §4.4),素材来源允许走"通用图标改色复用"这条低成本渠道。2026-10-21 用户裁营地交互重做五卡整体列入 Alpha:营地柜台贴图随之转入卡④营地场景图新建批(新场景取代现四柜台覆盖层),本条只余元进度件贴图终稿,排 Beta。**2026-11-01 迭代 47 卡④ 落地注记**:四柜台覆盖层已退役(场景图五功能窗口形态,camp.md v2.4),卡④ 侧义务终结;本条余元进度件贴图终稿与九宫格切片核对,排 Beta。
@@ -367,11 +344,3 @@
**改动面**:美术素材
**状态**:待美术设计
#### 模态句柄册分域重构(2026-11-01 登记,来源=会话提及)
**实况**:重构证据=`game/presentation/ui_modals.gd:7-20`(类变量 14 实测)+停机呈报-迭代47机检预算互斥-2026-11-01.md(卡④⑤ 平铺合计 19>S13 上限 15)——按技术角色平铺 13 模态句柄+flow,迭代 47 营地域新增六句柄顶格 S13 类变量上限 15(2026-11-01 用户裁:最小改动先走——营地六句柄落 `ui_camp_modals.gd` 子容器,随迭代 47 卡⑥/卡④/卡⑤ 落地,本条只登记**全量分家**)。目标形态=存量句柄按域分组抽容器(局内 run 六件/菜单与跨语境归组)+ModalFlow 自 UiModals 升格独立持有;行为零变化、纯句柄搬家;返工面=全仓探针深员寻址+`ui_registry.gd node()` 寻址+`main_ui_build.gd` 装配。拆分判据权威=code-conventions §1.1(沿职责轴;营地子容器先例=`ui_camp_modals.gd`,随迭代 47 落地后为准)。需求卡片:reports/需求卡片-模态句柄分域批-2026-11-02.md(2026-11-02 写卡会话落位,零待裁点,开工门=U0)。
**改动面**:游戏代码
**状态**:已写卡+已编迭代 49