Files
gplan-2/design/engineering/architecture/architecture.md
T

94 KiB
Raw Blame History

Dungeon Sweeper — 总体架构文档

文档状态

  • 版本:1.36
  • 引擎:Godot 4.7.2-stable(GDScript 单语言;2026-09-07 锁定)
  • 评审模式:solo(review-mode.txt,2026-09-12 用户拍板——TD/LP 门禁按 solo 跳过,用户授权架构产出自主推进、迭代期回调)
  • 覆盖 GDD:现行全集(根索引=design/gdd/02-系统清单.md,文档树构成以根索引为准)
  • 事实源地位:本文是架构事实的唯一来源——分层/所有权/数据流/API 边界/测试与质量域均以本文为准;历史决策沿革查 git commit log,不另设决策文档体系
  • 实现实证:game/(2026-09-10 起开发,现为完整游戏开发版本,已非垂直切片;测试层级=冒烟/单元/集成/系统四级+UI 探针与渲染 golden(2026-10-22 用户裁),闸机按改动域分跑在役)——本文档的分层/所有权/数据流均经实现验证,非纯纸面设计
  • 主程序可行性:跳过 — solo 模式

引擎知识缺口摘要

  • 引擎事实现行事实源=design/engineering/engine-reference/godot/(VERSION / breaking-changes / deprecated-apis / current-best-practices 四件)——迁移核实结论、语义变化与编码注意一律查那里,本文不重复。
  • 渲染器与窗口基座=gl_compatibility + 1280×800(2026-09-12 裁);UI/渲染域为引擎风险集中地,采纳引擎增量前对照 engine-reference 核实。
  • 写码纪律不变:不确定的 API 一律查 docs.godotengine.org/en/4.7/ 核实后再用;4.8(dev 阶段)稳定版发布后跑 /setup-engine refresh。

系统分层图

20 系统按 design/gdd/02-系统清单.md 依赖分层表映射到标准五层。实现已验证该分层(core/ 纯逻辑零 UI 依赖 headless 可跑、presentation/ 组合根模式)。

┌────────────────────────────────────────────────────────────┐
│  呈现层                                                     │
│    D1 HUD 与界面框架 (MVP) · B5 战斗表现                    │
│    D4 音频 (Beta) · D5 教学引导 (Beta)                      │
├────────────────────────────────────────────────────────────┤
│  功能层                                                     │
│    B1 战斗结算编排 (MVP) · C1 关卡节点地图 (lite 已实装)    │
│    C2 冒险结构 · C3 难度曲线 · C4 元进度 (Alpha)            │
├────────────────────────────────────────────────────────────┤
│  核心层                                                     │
│    A1 扫雷棋盘生成 · A2 排雷玩法规则 · B2 敌人系统          │
│    B4 地图战斗资源 · A5 扫雷秘宝                            │
├────────────────────────────────────────────────────────────┤
│  基础层                                                     │
│    D2 数据配置与数值表 · A3 行动经济 · A4 地形变异          │
│    B3 增益/状态系统 · D3 存档序列化 (Alpha) · D6 设置/本地化│
├────────────────────────────────────────────────────────────┤
│  平台层                                                     │
│    Godot 4.7.2 引擎 API 面(GDScript / Resource /          │
│    SceneTree / Control / InputEvent)——无游戏系统          │
└────────────────────────────────────────────────────────────┘

层名对照:基础层=Foundation、核心层=Core、功能层=Feature、呈现层=Presentation、平台层=Platform——本文一律用中文名;跨文档与代码目录仍见英文名(game/core/、game/presentation/ 等目录名不改)。

系统 层 里程碑 headless 约束 引擎风险域
D2 数据配置 基础层 MVP ✅ 完整可跑 LOW(Resource/.tres 基线稳定)
A3 行动经济 基础层 MVP ✅ 完整可跑 LOW(纯逻辑)
A4 地形变异 基础层 MVP ✅ 完整可跑 LOW(纯逻辑)
B3 状态系统 基础层 MVP ✅ 完整可跑 LOW(RefCounted 纯逻辑)
A1 棋盘生成 核心层 MVP ✅ 完整可跑 LOW(纯逻辑)
A2 排雷规则 核心层 MVP ✅ 完整可跑 LOW(零表读取零 UI)
B2 敌人系统 核心层 MVP ✅ 完整可跑 LOW(纯逻辑)
B4 地图战斗资源 核心层 MVP ✅ 完整可跑 LOW(纯逻辑)
B1 战斗结算编排 功能层 MVP ✅ 完整可跑(禁 await) LOW(纯逻辑)
C1 关卡节点地图 功能层 MVP(切片期实装) ✅(切片 level_runner 先例) LOW
C2 冒险结构 功能层 MVP(切片期实装) ✅ LOW
C3 难度曲线 功能层 MVP(切片期实装) ✅ LOW
C4 元进度 功能层 Alpha ✅ LOW
D1 HUD 呈现层 MVP ❌(UI 层——场景级探针测试承载) MEDIUM(Control/Input/文本域)
B5 战斗表现 呈现层 切片后立项(未实装,前置战斗表现美术测试) ❌ MEDIUM(Animation/Tween/渲染)
D4 音频 / D5 教学 呈现层 Beta(2026-10-13 Alpha 版本标准裁:与游戏内容无关者一律排 Beta) 部分 LOW-MEDIUM
D3 存档序列化 基础层 Alpha ✅ LOW
D6 设置/本地化 基础层 完整愿景 ✅ LOW

依赖分层与唯一回边:A2 只外发三事件(cell_revealed / flag_judged / round_end),B4/B1 订阅后回调——A2 不依赖任何下游(TD-SYSTEM-BOUNDARY 裁决,全项目唯一允许回边)。


模块归属

命名遵循 design/engineering/code-conventions.md:领域命名、禁 ID 前缀(文件头注不写文档链接——「实现 GDD:xxx」一类已废止,代码↔设计追溯由 GDD 文档承担)。

基础层

模块 独占职责 对外暴露 消费依赖 引擎 API
ConfigDB(autoload,D2) 全部玩法数值表与表现层布局配置表(data/tables/*.tres + data/schemas/*.gd);加载/校验/override/诊断状态机。行族访问器归位各 schema 表类(表管自己的行查询),本类只留加载/校验/override/诊断门面;表持有成员按域收进四张域容器 Resource(config_domain_combat/run/crossrun/presentation.gd——四张域容器均已建件,类型化成员 7/7/5/1);三张 resolver 表(board_gen.resolve_row/enemy.resolve_rowset/difficulty.resolve_modifiers)经 load_tables 装配段注入各容器,resolver 文件与键零搬移——红线不变:本类仍是唯一加载与持有单点,"经 ConfigDB 单点读取"=经其持有的表对象 类型化域容器属性(每域一张容器);公开面 8(push_diag/is_fatal/reset_diagnostics/diagnostics/diagnostics_count/load_tables/set_reload_gate/reload)、类变量 10 无(基础层顶点) Resource/.tres 加载、autoload 生命周期——LOW
SlotStore(core/slot_store.gd,D3 存档槽位域件,已建件) 存档三槽位文件域唯一所有者:槽位挂载与模板、激活与建删、槽位摘要窥视(peek 族);改名覆盖原语(_rename_overwrite)留 save_manager(IO 原语单点) 槽位读写原语族+摘要投影(公开 11:active_path 读投影、migrate_legacy_save 公开化;对 SaveManagerCore 反向私取 21 处清零=双向公开面;类变量 4;SaveManager 与菜单消费方经 save.slots. 直连) save_manager(注入路径与模板配置);FileAccess——LOW
MetaStateStore(core/meta_state_store.gd,D3 存档内元进度数据件,已建件) 存档内元进度数据的读写唯一层(钥石/道具解锁/树节点与叉侧/锻造路线/同调/真视/计数器/摘要——数据读写原语,不含业务规则);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
MetaProgression(autoload,core/meta_progression.gd,D3 元进度业务层) 元进度账本服务:钥石收束入账、营地消费定价与秘宝解锁判定的纯被动服务,零信号零外发;数据读写全经注入的 MetaStateStore(save.meta_state. 直连);hero_override() 现算不写表(全零=白板合法态——生效注入只走冒险开始参数面显式传参) 写口族(天赋树购买/叉侧切换/锻造解锁与升级与选中/同调装配切换等)+解锁判定与读投影;构造双形态=autoload 装配走 .new() 零参+_ready 从 autoload 链取依赖(工程序 ConfigDB→RngService→SaveManager→MetaProgression,注册顺序即依赖序),单测/工具走 .new(db, save) 直构形态(不入树零 _ready)——四个 Autoload 中唯一有跨 Autoload 依赖的件(ConfigDB/SaveManager) ConfigDB(定价与档位表值);SaveManager(存档访问器,经节点路径延迟取用) autoload 生命周期——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 只读;实测类变量 10 ConfigDB(ActionEconomyTable);EffectPort(效果端口件——发射经端口单点,effect_engine 直连退役);B1 回发 next_round_mode/battle_over 无
variation 定义(A4) VariationTable schema(现行 6 行:六 region——贫矿脉 global 行已屏蔽删行,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 零运行时可变状态的系统(见「架构原则」条 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 已退役,桶字典由 adventure_runner 持有) 无(零随机全确定)
save_system(D3,Alpha;已升格 autoload「SaveManager」) 存档格式与版本比较 save_manager 公开面 14(set_read_only/read_only/reset_to_default/data_snapshot/restore_data 五承接方法+peek_summary_at/rename_overwrite 两更名公开化);(契约规范源:../../gdd/systems/表现与支撑/存档序列化.md——契约锚:SAVE_FORMAT_VERSION + master_seed + 各流 scope 计数器快照,须在无正在执行中的 open_stream 实例时切出) ConfigDB、RngService 只读计数器 FileAccess——LOW
settings/localization(D6,愿景) 设置项、翻译数据 (契约规范源:../../gdd/systems/表现与支撑/设置与本地化.md) ConfigDB 无

核心层

模块 独占职责 对外暴露 消费依赖 引擎 API
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) 只读;preview_reveal(cell) 只读预览口(零写入零事件——0 格连锁传播闭包);retire_board();+harmful_variants/harmful_adjacent 两有害判定面(编排器归位);三源拒绝(board_face / resource_face / phase)+ sub_reason 封闭枚举;公开方法面 20(safe_remaining 已私有化为 _safe_remaining,唯一生产消费点=同类 clear_map_cleared),gdstyle S13 归绿零基线键 A1 产物(Board class_name 数据契约);A3 try_spend / last_round_end/ 相位 无(零表读取、零 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(query_beat/query_attack/advance 已随行为环退役;rollable_skills/special_skills/check_trigger_unlocks 带 facts 参——情境条件触发器在役,事实缺键=条件假拦下,百分比事实走阈值式折算) ConfigDB(EnemyTable/SkillTable/HeroTable) 无
reward_economy(B4) 格面资源身份映射(install 期预分配、Ready 只读、换图映射消亡)、极性路由字典面((类型, 极性)→ 字典行查询;路由执行归 B1 授予段)、F6 当量供给投影;装配期摇号面已拆出掷格件 RewardRoller(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 秘宝域令牌池件) 三选一/商店共享池的持久多重集、抽签(候选抽取)、cap 库存与专长凭证三计数与判定唯一所有者——件只管池与判定,停点编排与兑付推进留冒险编排器 draw_candidates(channel) 抽签;consume_deck_token / consume_pool_purchase 池消耗;cap_ok 上限判定;feat_ticket_consider 凭证判定;stock_snapshot / pool_stock 只读投影;商店购买消费经注入 Callable 链至 CurioStop 兑付单点(已转纯池——bind_handlers 反向回调已退役) ConfigDB(秘宝令牌行集);注入 RngServiceCore(reward_pick 封闭流,禁自建随机) 无(RefCounted 纯逻辑)
ShopSession(core/shop_session.gd,商店会话件) 关卡商店双模式(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 裁定),直连消费的方法=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 供给(构造期内部直调),测试面直连 shop.set_shop_pool ConfigDB(商店行集);注入 RngServiceCore;宿主钱包/账本引用;pool 模式令牌消耗与判定经注入 Callable 转 CurioDeck 无
HeroStats(core/hero_stats.gd,主角数值账件,已实装) 冒险生命周期主角数值域唯一所有者:生命账与特性持有集(活引用注入——关内兑付当关生效)、锻造强化快照、调试百分比通道、攻击/甲类型轴快照、生效上限/攻击/护甲公式与回血封顶公式单点、续玩生命钳制收口;生效公式经注入 GainJournal 只读引用取加算区汇总(无反向引用不成环) 构造注入;单写原语族+只读投影;断点自交片段(账本键) ConfigDB(表值读取);注入 GainJournal(只读);由 AdventureRunner 冒险开始创建、注入战斗 encounter 无(RefCounted 纯逻辑)
GainJournal(core/gain_journal.gd,加算日记件,已实装) 统一冒险加算区与获得记录唯一所有者:获得记录三层结构=记录列表(三选一件/商店购买/战末奖励各一条)→属性增益明细(带来源指回)→四轴汇总(由明细同步维护);三写通道统一走 gain_bonus 单写原语(source_class=curio_pick/shop_product/battle_export);本局钥石增量与逐杀明细、真视使用记录、商店已购档数记账同域 gain_bonus 单写原语;记录与汇总只读投影;断点自交片段(获得日记键) 由 AdventureRunner 冒险开始创建、注入 CurioStop/level_runner/ShopSession/战斗 encounter(战末 bonus 四轴经 gain_bonus 汇入) 无(RefCounted 纯逻辑)
GpWallet(core/gp_wallet.gd,GP 钱包件,已实装) 冒险局内货币唯一所有者(LevelRunner 与 ShopSession 读写全指此单点;冒险开始=0、收束清零,不入存档不入摘要) gain/spend/clear 单写原语 由 AdventureRunner 冒险开始创建;宿主与商店经注入引用读写 无(RefCounted 纯逻辑)
RefreshBank(core/refresh_bank.gd,刷新账件,已实装) 三选一刷新三源账唯一所有者:X 刷新件每碰三选一重给(优先消耗不结转)/Y 营地升级行冒险周期池(用完即无)/刷新券存量账(冒险级跨停点持久)+GP 付费刷计数与报价公式;零停点态依赖(免费/付费支出的编排归 CurioStop,本件只记账) 支出与余量原语+报价公式;断点自交片段(refresh_stock/attune_refresh_y 两键,Y 缺键回退参数面) ConfigDB(刷新件与营地升级行表值);注入 CurioStop 支出路径 无(RefCounted 纯逻辑)
AttuneLoadout(core/attune_loadout.gd,同调配装件,已实装) 装备中的秘宝件对象集唯一所有者(每件内含充能单位与重置周期);同调充能的物化行为唯一事实源——种行/补行改写时同步(RunLedger 充能字典轨与差额对账函数退役);旧档 aux_items 同调行迁移归件 构造注入;充能查询/消耗/按周期重置原语;断点自交片段(attunement_charges 键,键名与策略不变) ConfigDB(秘宝行集);TreasureItems(同调行投放面);注入战斗使用路径 无
CurioStop(core/curio_stop.gd,三选一停点件,已实装) 三选一停点编排唯一所有者(架构原则 9 本域承载):停点三态(关卡完成三选一在途/已兑付待推进/奖励节点三选一在途)、刷新编排(三源账面归 RefreshBank 件、查停点态→支出→重抽重发编排留本件)、兑付方法族(pick/refresh/redeem/skip)、凭证出箱(RAP/时沙待注入);三选一信号面自带;零自动推进停点语义承载 对外=开停点/刷新/兑付/放行谓词/交断点片段五组入口+信号面(curio_choice_presented/curio_resolved);由 AdventureRunner 关卡完成受理时调用 ConfigDB;注入 CurioDeck(抽签/摘牌)、HeroStats 与 GainJournal(兑付落账单写原语)、RefreshBank(刷新支出);随机只经 CurioDeck 的 reward_pick 封闭流 无
breakpoint_store(core/breakpoint_store.gd,冒险域·断点组装与回放件,已建件) 存档断点组装与回放唯一承载:断点快照拼盘、回放回填、读侧策略分发;BREAKPOINT_FIELDS 27 键登记单源随件(键名/策略标签/键序冻结) 构造=引用束注入(九引用束成员解包为原名成员——保迁移函数体逐字);resume_adventure 留宿主(壳+宿主侧回填语句——R2 所有权缝分家);断点键面零变化;公开方法面 18(13 新面承接 adventure_runner 私取清零+bp_read 公开化);实测类变量 15(贴顶禁再增) adventure_runner(宿主);注入主角账三件与 curio/stop/bank/loadout 引用 无(RefCounted 纯逻辑)

功能层

模块 独占职责 对外暴露 消费依赖 引擎 API
battle_orchestrator(B1) 段序骨架(七段结构冻结)、轮 facts 缓冲、可回放步骤流、明细行协议(基础行型+扩展行两层 + 字段分层,词表以 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 域·效果引擎宿主件,已建件) 效果引擎挂点施加面唯一承载:事件发射与事实判定(_fx_emit/_fx_fact)、主角 AC 基线与本轮/本战 AC 累积、bonus_delta 四轴累积(战末宿主 drain 汇入账本)、揭示待兑队列与兑付(含 _fx_revealing 再入闸——同步信号回环防二次缓冲二次兑付)、树规则合成订阅的 round/battle 桶计数器持有(桶随编排器生灭语义不变);效果端口件为业务类朝向机房的窄门面——端口在本件组建、bind_port 组装期转注两业务类,计数器账面收归本件;实测类变量 15 构造=引用束注入(防 _init max-parameters 新键);bind 时注入 emit Callable(行发射经宿主协议面单点)与兑付 Callable(RewardGrant 授予面——揭示队列 flush 回调);+mark_new_resource_type/+add_bonus_delta 两公开累积方法(grant 消费面——类变量 15 不变,方法-only);只读投影分两类消费方: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 读);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 经组合根现值回调直连);授予入口(结算段类直调);+feat_yield_adjust(专长收益调整——自编排器归位);只读投影(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 揭示回调注入位;+hero_atk()/static hits_of()/emit_hero_damage_taken 公开化(_emit 去下划线非并存——编排器与段类消费);实测类变量 13(facts 构造注入) B2 单位实例(单据目标传入);B1 注入(EffectPort 端口引用——发射经端口;EffectContext 引用束与编排回调收归宿主侧 BattleFxHost 域,业务类零引擎直连) 无
BattleRefreshFlow(core/battle_refresh_flow.gd,B1 域·换图刷新流程件,已建件) 弃图刷新流程唯一承载:刷新可用性门(相位/每轮上限/储备门槛)、折后价单点(_effective_refresh_cost——专长行声明序第一命中、floor 取整、can 与执行同源)、换图执行序(扣储备→used+1→旧资源退役→旧板退役→装新板→board_refreshed 成功事实登记) can_refresh/execute 两公开入口(构造=实例束注入 8 键——facts/db/action_economy/fx_host/reward_economy/minesweeper/install_cb/grant_seg;类变量 8);调用路径呈现层→编排器两公开方法单行转发→RoundCycle.refresh_flow() 取件→本件;grant_seg 段间引用直接交接(编排器 _rounds._grant_seg 跨两层链式取段消灭);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 域·轮循环驱动件,已建件) 轮循环驱动域唯一承载:结算五段段件持有与驱动、重入门闸、开轮摇号、踩雷账 引用束注入(编排器 20 键封闭束,解包自用七键后原束分发五段;持有 BattleRefreshFlow);段驱动入口由宿主接线调用;公开方法 4(refresh_flow() 读出口);实测类变量 15(贴顶禁再增) B1 宿主;settlement/ 五段段类;A3 相位读 无
BattleFacts(core/battle_facts.gd,B1 域·战斗事实件,已建件) 战斗事实域唯一承载:受理事实(encounter)、轮 facts 缓冲(reveals/seals/path)、封印判定账、事实溯源、同调快照读面;attune 状态两成员随件(行为函数留宿主) 零参直构;宿主与段类经注入引用读写;实测类变量 15(贴顶)/公开方法 4(reset_round+三 mark 写口) B1 宿主;A2/A3 只读 无
settlement/ 五段段类(B1 域·结算段件) B1 每轮结算序列的五段逻辑件(授予/增益减益/战斗/衰减/判定——细则见下「战斗域装配现状」节) 段处理入口(B1 接线调用);构造=引用束注入(各段断言各自必需键);段类对编排器零引用(注入 Callable 亦属接线面);可直接 new() 单测 B2/B3/B4 兑付面与 B1 轮 facts 缓冲(各段按职责) 无
level_runner(C1-lite,切片已建) 关卡域生命周期(节点链推进、共享 B4 + HP 携带、关卡末 level_clear) 节点推进接口;LevelTable(level.tres——节点 enum {battle,reward,rest,boss}、末节点必须 Boss、ConfigDB 跨表校验⑧) B1(直构 BattleOrchestrator 接线战斗)、ConfigDB LevelTable 无
run_structure(C2) 冒险/关卡序列、失败重开、master_seed 唯一接线方 (契约规范源:../../gdd/systems/冒险循环/冒险结构.md) RngService.set_master_seed、C3/D2 无
difficulty(C3) DifficultyTable 回填、全部曲线数值调参所有权、战斗期望表(切片 monte_carlo 为工具原型) 调参输出(经 D2 R1 解析/编排器传递,禁反向调用生成) ConfigDB、B1 对账输出(调参约束清单)、A1 报告 C 无
meta_progression(C4,Alpha) MetaTable、钥石账本、天赋树域(MetaTreeTable 12 节点 v0.8——Fork 一节点双态/row 字段退役/RULE_KEY_PARAMS 六键参数字典/彩蛋特化觉醒)+ 同调位槽位判定(树点亮数单源)。存档内元进度数据读写原语归 MetaStateStore——已落地:本类纯转发读已退役(消费方直连 meta_state),业务规则与写口编排留本类;hero_override 内联锻造加值与树淬炼 flat;并组三组(forge_select(kind,route_id)/hero_type_axes()→{attack,armor}/tree_camp_status()→{rows,fork_groups});补 meta_state 成员装配 公开面 20 定稿:buy_treasure_unlock / refresh_treasure_unlocks / treasure_shop_status / forge_buy_level / forge_buy_unlock / forge_select / hero_type_axes / forge_shop_status / settle_adventure / hero_override / tree_can_buy / tree_buy / tree_toggle_fork / tree_buy_fork / tree_rules(返参数字典)/ tree_camp_status / toggle_attunement / attune_camp_status / attune_refresh_charges / buy_attune_refresh D3、C2、ConfigDB 无

战斗域装配现状(RunLedger 段已退役,四账去向见下「冒险域拆分(现状登记)」节)

  • 结算五段:B1 编排器的每轮结算序列拆为 game/core/settlement/ 五个段类——GrantSegment(①授予段,含封印判定与 counter/grant 助手单点、成功刷新事实消费面 apply_board_refreshed 与轮末治疗计数兑付面)→ AuraSegment(②增益/减益段)→ CombatSegment(③战斗段)→ DecaySegment(④衰减段)→ VerdictSegment(⑤判定段,返回裁定,终局早退语义留 B1)。段序骨架冻结于 SettlementTable.segment_order 语义,B1 退为段序编排+接线;段类可直接 new() 单测(settle_segments_test 在役)。

战斗编排域拆件定稿(本节为现状登记)

  • 轴甲两件:battle_orchestrator按变化原因拆出 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 复核)。
  • 轴戊两件(已建件):①效果端口件 EffectPort(core/effect_port.gd)——职责语句「战斗业务类唯一的效果发射出口:收事件与载荷、交效果引擎结算、取回命中批」;实测形态=六 Callable 路由、bind_port 组装期转注、闭面四键 biz_fact(dig_streak/hp_ratio/rider_tier_bonus/rider_tier_crit——charge_layers 键退役后宿主应答 null)、未绑零扰动缺省;DamageController/ActionEconomy 各持端口引用(同一实例、构造注入),EffectEngine/EffectContext 引用与计数器账面(value_counter 层值读后清零)收归宿主侧(BattleFxHost 域),业务类零引擎直连、零账面触碰;facts 取值束(dig_streak/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 自描述键观测面不回退(甲案在案)、EV/MC 锚同种子逐位零漂移——round_flow 逐位回放 134 检查为主证(红线成立);RewardEconomy 实测类变量 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),宿主侧三单点记账(RunLedger 类已退役,直持对象引用无处可指)。
  • 战斗域读面(RunLedger 退役后):账本读经编排器 _journal()/_attune_loadout() 现值派生(GainJournal/AttuneLoadout,enc 派生、无成员接收);冒险桶经 enc["adv_bucket"] 下传 battle_fx_host.mount_buckets;战末 bonus 四轴经 GainJournal.gain_bonus 汇入。
  • settlement/ 段类随动(2026-11-04 迭代51卡② 换代):段类构造=引用束注入(编排器 20 键封闭束分发——各段断言各自必需键),段类对编排器零引用(跨件单向接线,注入 Callable 亦属接线面)。四个授予段 helper 归位:_feat_yield_adjust→RewardGrant(feat_yield_adjust)、_harmful_variants/_harmful_adjacent→minesweeper_rules(harmful_variants/harmful_adjacent)、_hits_of→damage_controller(static hits_of);_pool_effective/perfect_sweep_earned 留宿主(段类经编排器公开读投影消费)。
  • attune 族处置:attune 状态两成员归 BattleFacts、行为函数留宿主——AttuneLoadout 充能单源化语义领地不破,外部三面消费点零改址;RewardGrant 经宿主 attune 读投影取 _attune_safe_seen 形态不变。
  • 呈现零变化:两快照出口签名与载荷逐字不变,内部改读两件只读投影(快照本体不读揭示态——揭示态投影消费方=宿主 A2 订阅旁路判定);treasure_interact_controller 三触点分家——use_treasure 经组合根现值回调改注 RewardGrant(每战新建编排器,禁一次性直引防悬挂),minesweeper 读与 attune_convert_state 仍走宿主取值回调(双取值面);nest_preview_count 直读面零变化。
  • 验收红线:游戏行为零变化(RNG 消费序零漂移——fx_reveal 封闭流随件迁移取号序不变、信号顺序契约冻结、明细行协议词表零触碰、同种子逐位一致);battle_orchestrator 头注发射点指址随拆件改写(词表不动,指址须真)。
  • S7/S8 登记:RewardGrant 调 B4 API,两新件一并登记进 S7 B1 域文件集与 S8 结算路径 await 文件集(static_scan.sh 两清单独立、同步更新——防 await 面漏闸);轴丙 BoardInstaller 同规(调 B4 roll_board,已登记进两清单)。

冒险域拆分(现状登记——本节各条即现行形态)

  • 应用层形态:adventure_runner 退出上帝对象、转薄应用层(DDD 应用层形态)——只留冒险状态机、关序推进、结算受理、建件接线、效果引擎冒险桶字典持有(桶=效果引擎域数据,应用层只锚定生命周期);零领域决策。核心层表新件行(主角账三件与刷新账件/AttuneLoadout/CurioStop——见基础层与功能层登记)即本拆分目标。
  • CurioDeck 转纯池:bind_handlers 反向回调退役;商店购买消费经注入 Callable 链至 CurioStop 兑付单点——牌库只管抽签/消耗/cap 判定/凭证计数。
  • RunLedger 退役:四账各归其主——加算区/购买记录/钥石增量/真视记录归 GainJournal、特性集归 HeroStats(GP 钱包归 GpWallet),充能归 AttuneLoadout,冒险桶字典归应用层持有;战斗侧 encounter 注入面由单一账类引用改为多路(桶字典+实体账+配装件);ShopSession 账本引用面同步换代,商店属性商品加算改经 GainJournal 单写原语。
  • level_runner:依赖改构造注入一次给齐(后置 setter 群与商店重绑机制退役;注入活引用禁快照——特性集共享引用语义保留);商店白盒转发属性撤除;战斗→关卡信号转发族保留(战斗实例每节点新建,关卡层做战斗域稳定面)。
  • 断点片段化:各件自写自读自己的键(关卡层交关卡域五键片段:node_id/visited_ids/aux_items/shop_shelf/shop_visit_buys),缺键回退策略随领域知识归各件;应用层唯一落盘口(收齐各件片段拼成顶层快照后写盘),写触发点不变(五处);既有 27 键逐键冻结;新增获得日记键沿扩列不升版先例——旧档缺日记回退汇总键直载并跳过比对,日记在档时由日记推导汇总、与留存值不符即报错中止(迁移正确性自检)。拼盘与读侧策略机组拆出 breakpoint_store(核心层表新行),应用层落盘口与写触发点不变——宿主经件组装快照后写盘,27 键冻结不变。
  • 信号直连:adventure_runner 六转发信号族(node_entered/choices_presented/step_row/round_started/board_changed/wallet_changed)退役;呈现层在 level_started 重取点重订阅关卡对象信号(旧实例连接随引用释放消亡);「关卡开始信号前零发射」契约写进关卡件头注;「恰好连接一次」断言用 is_connected 守卫(release 模板剥 assert);三选一信号面归 CurioStop。
  • 调用直连:不留中间人委托壳(纯转传=Middle Man 反模式,2026-10-26 用户裁定);呈现控制器经取值回调持件——回调只许捕获长活根对象,禁件方法 Callable(防悬挂);测试/探针直连件读写。
  • 验收红线:游戏行为零变化(RNG 流名 reward_pick 与消费序零漂移、信号顺序契约冻结、同种子逐位一致);gdstyle 基线禁改(类变量计数下降属改善);怪物寻址 resolve_enemy_rowset 调用面与关卡参数档装配零变化(未来关卡主题的数据缝不堵)。

呈现层

模块 独占职责 对外暴露 消费依赖 引擎 API
D1 HUD(呈现面拆分持续换代:组合根 main.gd + 三屏壳(MenuScreen/CampScreen/AdventureScreen)+ views/ 视图单元(现行承载面见「呈现层装配与会话生命周期」节;早期 9 单元清单与 LevelStripView 已随场景换代退役)+三画面件内部数据类=宿主画面登记表(关卡地图屏 _MapState/战末弹层 _EndOverlayState/调试浮窗 _DebugState 各 14 字段公开数据成员,文件外零消费者,sweep 断言承载);营地面=场景根+四子界面功能窗口+Esc 浮窗+顶栏 HUD 栏〔四柜台覆盖层已退役〕) 全部 Control/CanvasLayer(例外:BoardView 棋盘本体与 BattleStageView 站桩本体 = Control 壳 + SubViewportContainer + SubViewport + Node2D 世界〔BoardWorld/CellUnit;StageWorld/StandeeBody——B 区 slot_row 伴随件留壳层〕,探针契约面不变)、输入→意图翻译(唯一提交路径 = settle_batch,不直调 A3)、呈现义务状态记录(A2×6 / B2×4 / B3×4 / B4×5 / B1×3) 视图单元接口(信号外发、setter 只读注入);组合根交接面=公开服务面 18(refresh_presentations/sync_status_entry/fatal_screen/quit_game/begin_session/start_debug_levels/check_board_hints/show_board_fx_for_node/replay_locked_click/sync_settlement_visuals/wire_battle/sync_debug_overlay/open_settings/open_save_select/status_data/gp_summary_text/seed_value/current_master_seed)+句柄读投影/设置口 12(set_treasure_ui/treasure_ui/set_bonus/bonus/set_camp_pres/camp_pres/set_debug/debug/set_tune_sim/tune_sim/set_confirm_consumer/set_confirm_consumer_slot)+on_* 处理器保私有经 Callable 束交付(束参=main_ui_build.build 31 键、main_adventure_flow.wire_adventure 2+6 键);指标例外=main.gd 公开方法 32 落 gdstyle 基线(先例=level_runner 33 在册);UiKit 三工厂(gradient_base/beams_rect/switch_toggle)公开化 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,界面注册面,已建件) 呈现层接口面唯一承载:层序合同(LAYER_CONTRACT)迁驻与合同寻址、三域句柄容器 ui_screens(9 屏壳与覆盖层句柄)/ui_battle(5 战区句柄)/ui_modals(模态句柄按域分三子容器——局内冒险域 run/菜单与跨语境域 menu〔两子容器〕/营地域 camp=既有 UiCampModals〔六句柄、两段式寻址 modals.camp.*〕,三子容器纯字段、两段式寻址 modals.run.*/modals.menu.*/modals.camp.*)+模态编排件 ModalFlow 直驻本面(自 UiModals 升格 UiRegistry 直持);层序合同营地槽=camp_scene+四子界面+camp_esc_overlay(camp_overlay 已退役);组合根经其一级寻址接线,探针挂载假设迁移为 main.ui.<域容器>.<句柄> 三容器属性+flow+合同寻址口(RefCounted 门面,不挂树、零会话期引用);register_layer 迁驻注册面;四件类变量 UiRegistry 4/UiScreens 9/UiBattle 5/UiModals 3(run/menu/camp 三子容器纯字段——ui_modals 平铺面清零,分域纪律册级化);ModalFlow 随 UiRegistry 构造建立(注册面构造点先于装配) 构造注入:三屏壳、覆盖层、战区句柄、ModalFlow(main_ui_build 交付随之改型) 无(RefCounted)
UiCampModals(presentation/ui_camp_modals.gd,营地域句柄子容器,已建件) ui_modals 营地域六句柄唯一容器(场景根/四子界面/Esc 浮窗/HUD 栏),句柄寻址两段式 modals.camp.*;ui_modals 平铺面已清零(分域纪律册级化) 子容器属性+六句柄只读投影;main_ui_build 装配交付 构造注入(六视图句柄);ui_modals(父容器挂载) 无(RefCounted)
CampSceneView(views/camp_scene_view.gd,营地场景根视图,已建件) 营地场景图唯一呈现件:十层贴图铺底(层序按 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,功能窗口公共壳+四件,已建件) 营地五功能窗口的四个承载视图(锻造工坊/天赋树/秘宝匣/图鉴)+公共壳(窗口壳/行板/关闭钮;生涯页挂笔记本路由不经此族);模态栈单口 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 浮窗视图+四态路由件,已建件) Esc 浮窗三钮视图(返回主菜单/设置/退出)+Esc 四态路由静态件(根态唤起/再按关窗/功能窗开着先关最上层窗〔camp.md v2.3 定稿〕/设置开态不误关;菜单语境不唤起);main._unhandled_input=产品码首个键盘输入入口(契约 9——事件驱动、禁 Input 轮询、不挂 ui_cancel、pressed 非 echo) flow.open/close 路由口;三钮 pressed 意图信号(经组合根接线);入口方法公开化(main 转发调用的入口去下划线——on_esc_input/is_camp_context 先前已公开) 组合根(_unhandled_input 前置与意图消费);模态栈(关窗单口);screen_flow(设置/返回动线) Control+静态件
CampHudBand(views/camp_hud_band.gd,营地顶栏 HUD 件,已建件) 顶栏 48px 全宽窄条:钥石余额 badge 唯一呈现(单口取现值、显式刷新才变);set_hud_band 预留位落座 badge 文本投影;refresh 时取现值 CampRefreshBus(挂册广播);MetaProgression 钥石读 Control
CampRefreshBus(views/camp_refresh_bus.gd,营地刷新单口件,已建件) 营地刷新单口唯一承载:进档尾与营地写口尾触发 refresh 广播(八写口尾改路由),现开界面与 HUD 同步取现值 挂册/refresh 广播 组合根(触发点接线);四子界面与 CampHudBand(消费) 无(RefCounted 信号件)
board_hover(views/board_hover.gd,悬停预承诺呈现域件,已建件) 悬停反馈域唯一承载:三语义光标、目标格边框、BFS 路径预览、chord 双击首遇锚;_r0 出生展开区成员留宿主 构造=引用束注入 7 项(cells/minesweeper/diggable 引用+格命中换算/光标写入/hover_forbidden/chord_attempted 四 Callable);三入站口留宿主委托;hover_probe 读面留宿主;公开方法面 7(七口公开化——rebind/reset/refresh_after_paint/hover_at/detect_chord/on_shell_mouse_exited/hover_pos) board_view(宿主);输入事件经宿主入站口 无(RefCounted)
cell_base_layer/cell_mark_overlay(views/,单格两绘制域件,已建件) 单格绘制域拆分(入参与该层绘制命令同件):基座层(底面/描边/立面/投影/接触带/倒角,12 成员)与标识叠加层(标记/字形/徽章/点迹/高亮/退色,14 成员);徽章遮罩走构造交付 Callable(_mask_set);宿主 _draw 退为六步时序器,宿主实测类变量 10 构造注入;绘制命令由宿主 _draw 按层序调用 board_cell_unit(宿主);gdstyle 键各文件独立计数(12/13 均 ≤15) 无(RefCounted)
standee_vitals/standee_motion(views/,站桩两状态件,已建件) 站桩状态域拆分:身份命值(hp/atk/状态值族,12 成员)与资产演出(动作/姿态/位移演出族,11 成员);三个演出探针计数器留宿主,宿主实测类变量 10 构造注入;st(沿用)/mo 两实例由宿主持有;公开方法面 vitals 14/motion 14(站桩两状态件公开面换代,成员计数零增) standee_body(宿主);battle_stage_view 写入面逐字保持 无(RefCounted)
HudPresenter(presentation/hud_presenter.gd) 战斗屏数据投影+文案拼装静态族——核心状态→呈现文案的全部翻译集中于此(B/C/D 区文案与投影),静态无状态 refresh(…) 全量重查装配(组合根每次动作/结算返回后调用,漏调即陈旧呈现)+只读静态投影族 核心读取只走 settlement.presentation_snapshot() 成文快照面(禁链式穿透结算内部);ConfigDB display_name 无(RefCounted 静态)
board_resolvers(presentation/board_resolvers.gd) 棋盘每格渲染数据的只读解析回调四函数(奖励徽章身份——挖掘期 Active 相位内、地形变异数字遮蔽与角标、调试加成生效值)——有态绑定件,与无态静态投影族 HudPresenter 职责互斥 构造注入 db、调试浮窗与结算活态取值,产出绑定 Callable 供组合根接线 ConfigDB / DebugOverlay / 结算活态取值 Callable 无(纯投影)
main_ui_build(presentation/main_ui_build.gd) _build_ui 八步拆分件——组合根 UI 装配分步承接(三屏壳实例化、视图句柄接线、覆盖层装配与模态编排注入按步拆开);main 侧留同名薄委托,装配序与 z 序零改动 分步静态函数(成员访问经 root 显式传入);入口方法公开化(main 转发调用的入口去下划线) 层序逻辑不在此件——唯一事实源=ui_registry.LAYER_CONTRACT+ui.apply_layer_contract(root)(已迁驻注册面) 同 D1(Control 装配面)
main_adventure_flow(presentation/main_adventure_flow.gd) main 冒险流程族——菜单开局/续玩后的冒险编排接线、节点事件分发、终局面与选路屏开合;逐字搬运,main 侧留同名薄委托(探针 main.X 路径零迁移) 流程静态函数(root 显式);入口方法公开化(main 转发调用的入口去下划线) 局态全局住 run_scope 节点——本件零成员态、零新增信号连接(连接语句随原段搬运) 无
main_overlay_flow(presentation/main_overlay_flow.gd) main 浮层流程族——设置/状态面板/生涯页/选档界面/图例/钱包事件的开合与数据投喂;逐字搬运,main 侧留同名薄委托 流程静态函数(root 显式);入口方法公开化(main 转发调用的入口去下划线) 全部开合走组合根模态编排口(root.ui.flow.open/close——ModalFlow 自 UiModals 升格 UiRegistry 直驻)——本件零成员态 同 D1
main_debug_flow(presentation/main_debug_flow.gd) main 调试流程族——调试浮窗开合与上下文同步、批量模拟入口、两层调试对局起手、诊断转储;逐字搬运,main 侧留同名薄委托 流程静态函数(root 显式);入口方法公开化(main 转发调用的入口去下划线) 调试会话状态机归 debug_session.gd——本件只接线与出 UI,零成员态 同 D1
TilePalette(presentation/views/tile_palette.gd) 瓦片排版/装载:高墙/地面瓦片整批装载与运行时镜像合成、地板明度归一、数字墨族按板自适应判据、格坐标确定性散列与十六正交情形墙瓦片查表 查表族(读件持棋盘引用——棋盘视图 rebuild 经 bind_board 同步);装载缓存七成员持于件内(同板型零重载、换板重载时序同源) 零绘制面、零玩法数据写入(绘制调用面留棋盘视图);纹理路径单点在件内 Resource 纹理加载——LOW
HeroSprite(presentation/views/hero_sprite.gd) 英雄精灵四态与落位装配(落位与位移演出、撞墙帧闪、挖掘弹跳、脚底锚与持握手位出口) 由棋盘视图 _init 建为子件(注入世界根与壳层容器引用)——精灵本体经世界根 ensure_hero 建于 SubViewport 世界内,本件只驱动其状态 BoardWorld 世界根;素材缺位=零精灵(棋盘视图字形「人」回退路径在役) Node2D / create_tween(Tween 系 Node 方法——MEDIUM 域对照 breaking-changes.md)
BoardWorld(presentation/views/board_world.gd) 棋盘 Node2D 世界根(SubViewport 内 CellUnit 容器):世界级去饱和材质与字体注入挂点、英雄精灵持有位;封印印记=参数化绘制子件 seal_mark_layer(CellUnit 新公开属性 seal_on:on 才建/off 撤/edge 重注入/fog_state 联动;棋盘侧 tex_seal 贴图槽退役——seal_mark.png 只余战末蜡封贴图专用) 无 class_name——使用方经 preload 引用挂树 BoardView 壳层(SubViewportContainer + SubViewport 结构不变) Node2D/SubViewport——同 D1
battle_presentation(B5,垂直切片后) 结算动画 / 伤害数字 / 战斗舞台 (契约规范源:../../gdd/systems/战斗循环/战斗表现.md——前置「战斗表现美术测试」锁双舞台陷阱) B1 步骤流(回放脚本源)、D1 MEDIUM:AnimationPlayer(String→StringName 变更)/ Tween
audio(D4,Alpha) 音频挂点 (挂点 = B1 明细行类型流;负反馈聚合——单结算至多一次) B1 流水 AudioStreamPlayer(4.7 area_mask 默认 1→0 注意)
tutorial(D5,Alpha) 教学条目 (口径来源:A2/A3/B3/B1 各教学条目) 各上游 无

依赖单向性:上层可消费下层,禁止反向(C3 禁调用 A1 生成、D1 不直调 A3、A2/B3/B4 零相互直调)。全项目唯一回边 = A2 事件订阅面。


呈现层装配与会话生命周期

三屏壳与组合根句柄面

  • 呈现场景拆为三屏壳:MenuScreen(开始菜单屏)/CampScreen(营地屏)/AdventureScreen(冒险屏——内含关卡地图与战斗两容器)。
  • 屏成员寻址迁经界面注册面(已建件):探针挂载假设 main.X 迁移为 main.ui.<域容器>.<句柄>(ui_screens/ui_battle/ui_modals 三域容器);main.gd 实测类变量 15,注册面形态见「模块归属·呈现层」表 ui_registry 行;ModalFlow 实例随 UiRegistry 构造建立(注册面构造点先于装配);取证探针 shot_probe/fx_shot_probe 已改址;局态一律住 RunScope 节点,禁在屏/视图侧持有局态引用。
  • 组合根拆件=组合根构造注入、代组合根执行核心写调用的呈现侧子件(现行三件:curio_interact_controller/camp_shop_presenter/treasure_interact_controller——冒险节点后续推进、营地购买与刷新、道具使用)。视图禁直连拆件;核心写调用的可达路径仍是「视图→信号→组合根(含拆件)→核心」,依赖规则与组合根单点装配不变。成员见「模块归属·呈现层」表。

视觉层装配合同

  • 树序 = 登记序 = z 序,同源派生;层序唯一事实源 = main.gd 的 LAYER_CONTRACT 常量表(kind 五类:shell=屏壳〔成员随壳不占独立树位〕/modal=模态层〔入登记册,tags 随登记〕/state=全屏态/node=非视觉节点/float=不注册 ModalStack 的最顶浮层〔任何 UI 打开都不遮挡它〕)。
  • 全仓唯一落位口 = _apply_layer_contract()(装配尾统一排序+登记);散落 move_child 由冒烟 V1d 源码断言判红;改层序只改合同表。
  • 具体层清单不复制进本文(双写失同步禁令)——查现行层项直接读 main.gd。

会话生命周期(RunScope)

  • run_scope.gd = 纯状态承载 Node:零信号连接、零视图构建、零核心写调用(连接只在组合根,组合根经 run_scope.X 读写)。
  • 会话更替机制:_begin_session() 新建会话节点挂树、旧会话节点整节点 queue_free()——无独立收束函数,跨局字段清理靠节点释放机制(新增跨局字段零新增泄漏点);_ready 即建闲时会话,run_scope 永非 null。
  • 存活性矩阵(九阶段 × 五引用面,2026-10-17 用户裁认账阶段划分;执行判据=冒烟 V3a–V3i):
阶段 run_scope adventure runner settlement
① 闲时 在树(闲时会话) null null null
② 开局停点 在树 alive alive null
③ 战斗中 在树 alive alive alive
④ 结算后(胜利停点)/⑤ 选路页 在树 alive alive both
⑥ 终局面 在树 alive alive null
⑦ 回菜单收束 新闲时会话即刻在树(旧会话已释放——无真空窗) null null null
⑧ 各模态开合后(设置/生涯/营地/调试) 闲时会话零扰动 null null null
⑨ 两连局+续玩断点 换全新会话在树 alive both both
  • 三态记号沿用冒烟参数:alive=应有实例、null=必须缺位(实测非空判红)、both=按分支可空可活(如胜停点后走向选路或直接终局)。对象有值但已失效一律判「悬挂」红。
  • 第五引用面=四持句柄件(_treasure_ui/_bonus/_camp_pres/_modal_flow,另有 _row_pacer):其会话取值 Callable 与 run_scope 成员逐面同源比对(回调悬挂=两值不等即红),会话更替零残留由矩阵每阶段顺带铁证。

模态编排(ModalFlow/ModalStack)

  • modal_flow.gd = 模态编排纯逻辑类(依赖仅 ModalStack + 查询 Callable,可直接 new() 单测):开合编排(遮挡记账单口 + 演播后排窗挂起)/棋盘输入锁谓词/角标置灰谓词三职责。
  • 互斥排除语义随层登记(register(node, tags)):debug_overlay=["non_locking"]、level_screen=["screen_state"],其余层零标签。

测试与质量域

定位:本节为测试域(本地闸、探针、静态扫描等横切关注点)的事实源。强制验证=合回后远端 CI(唯一强制验证点,post-merge 钩子推送触发、按改动域分流);开发期手动闸批内自跑,判定严密性即全仓质量下限。第三方测试框架(gdUnit4)经 2026-09-12 评估不引入,现行测试载体=本节自制闸体系。

模块归属

模块 载体 独占职责 对外暴露 判定口径
run_smoke(冒烟测试运行器) tools/run_smoke.py 冒烟测试总入口与判定权:headless 以项目运行目标拉起 res://tests/smoke_boot.tscn(极小启动场景——autoload 在位、配置表全载、主屏实例化,零逻辑判定)+ 三闸判定 进程退出码(0=PASS / 1=FAIL) 三闸齐备、判定无洞:①退出码 = 0;②摘要行「[smoke] 摘要:N 项检查,0 项失败」在案且失败数为 0;③输出扫 SCRIPT ERROR / Parse Error 标记行。外部 wall-clock 超时在位(超时 = FAIL)
run_system_test(系统测试运行器) tools/run_system_test.py 系统测试总入口:headless 跑真实玩法路径断言面(宿主=res://tests/system_test.gd)+ 三闸判定(口径同 run_smoke,摘要行兼容两种宿主格式) 进程退出码(0=PASS / 1=FAIL) 三闸齐备(同 run_smoke:退出码/摘要失败数/脚本错误扫描;wall-clock 超时在位)
run_all(单元与集成测试) game/tests/run_all.gd 64 套统一入口(61 单元+3 集成,2026-10-28 实数):套件 manifest 逐条「套件 → 期望退出码」,致命类 expect=1 独立子进程实跑;negative 字段标负面套件(仅豁免错误扫描一闸);选跑态 --only=<词[,词…]>(直跑形态对套件路径子串匹配只跑命中套件,零命中=用法错 quit(2),仅供开发期最窄确认——不产闸回执、不作验收凭据,批末全量闸不经选跑分支) 逐套件结果 + 汇总退出码(任一套件失败 quit(1)) 套件级退出码协议在位;三硬闸齐备(入口内扫子套件输出 + 编排层扫 unit.log;Kit.finish 零断言返回专用码 2)。子进程输出须经系统命令解释器重定向落盘再读——OS.execute 的输出管道在本机恒空
probe_gate(场景探针) tools/probe_gate.sh headless 场景探针段编排(单一形态十件恒跑):ui_input_probe / ui_struct_probe / layout_probe / ui_contrast_probe / screen_flow_probe(屏壳切换)/ ui_click_probe(行为走查)/ ui_probe / ui_tune_probe / t17_defer_probe / fx_probe;孤儿 Godot 预清 + 批末残留清点(必须 0) 段级 FAIL 输出 + 汇总退出码 每段 timeout 守卫在位(挂死 124/137 = FAIL,不静默);判定统一走 verdict 函数——退出码为唯一权威判据,PASS 串降级为附加判据,逐段跑 tools/error_scan.py
render_gate(视觉 golden) tools/render_gate.sh 窗口化渲染闸:①shot_probe 七屏截图 → shot_checker A-D 语义断言;②fx_shot_probe / board_shot_probe 取证(超时/零字节/文件缺失任一 = FAIL);③棋盘 golden 逐像素容差比对(差 ≤16 / changed ≤2%,provisional)+ 菜单 golden;④批末孤儿残留清零;⑤三段探针日志逐段脚本错误扫描 段级 FAIL 输出 + 汇总退出码 查退出码在位(每段 timeout 守卫 + 退出码/取证文件双检);SCRIPT ERROR 扫描在位(逐段 tools/error_scan.py,标记与 run_smoke 同源);断言数下限不适用(判定主体 = golden 容差与取证文件存在性,非断言计数)
static_scan(静态扫描域) game/tests/static_scan.sh 静态扫描域 S1–S10 可执行载体(grep 规则 + tools/audit_type_hints.py〔S9〕+ tools/audit_file_headers.py〔S10〕) fail 聚合退出码(任一硬失败规则命中即 exit 1) 查退出码在位;SCRIPT ERROR 扫描与断言数下限不适用(逐规则命中即红,无运行时错误面与断言计数);S3 现为 warning 级、不参与 fail 判定(见下表)

改动域划分(2026-10-17 用户裁「代码批只跑代码闸、文档批只跑文档闸」)

域 闸 本批改动落在这些路径即属该域
代码域 run_smoke、run_system_test、run_all、probe_gate、render_gate、static_scan 唯一触发=game/ 下非 .md 的行为载体(代码、测试脚本、探针、场景、数据表、素材)。game/ 内的 .md(README、生成清单)归文档域——2026-10-26 用户裁:判据按文件性质,不按路径前缀。2026-10-18 用户裁「跨领域执法禁绝」后,tools/、artwork/ 两前缀不把改动拉进代码域
文档域 gdd_lint、doc_link_audit、doc_term_audit、流水线闸 game/ 内的 .md 与 game/ 外的一切路径:design/、根规则文件(AGENTS.md/roadmap.md/待办清单.md/体验验证清单.md)、tools/ 工具脚本、.zcode/ 配置、sim-data/、reports/
两域都含 repo_structure_audit(熵增闸:顶层目录/根文件/图像白名单/退役路径/design 子目录五查——文档批新增或挪动 .md 同样会绊它;纯文本扫描秒级) —

口径三条:域划分的唯一出处是 tools/run_all_gates.sh(--code/--docs/不带参数=全量),本表是它的现状登记、不是第二份清单;改闸件本身或一次改动跨两域 → 跑全量档(§6.2 共享件例外);开发期手动档按本批改动域选 --code/--docs,合回后 CI 恒跑全量档。代码域跑前先过素材齐盘预检——game/assets/art/** 与一切 *.import 边车都不入 git(2026-09-29 裁定),worktree 冷检出必空盘,空盘态冒烟 V1 成片假红、渲染闸更是一段 golden 都不比。

车道分层执法(2026-10-31 用户裁「一切改动走 worktree」)

一切改动走独立 worktree,主工作区只作合并落点。执法全机械——判据只有 git 图与路径(豁免面 .zcode/、.qoder/ 不入 git,主区直改),不含「改动大小」等语义判断。

执法层 载体 职责 判据
worktree-guard(ZCode PreToolUse) .zcode/hooks/worktree-guard.sh(本机件,不入 git) agent 侧车道纪律:主工作区 Edit/Write 与主区非 merge git commit 拦截(豁免 .zcode/、.qoder/;worktree 内目标快速放行;合并收尾提交凭 MERGE_HEAD 豁免);git commit --no-verify 拦截(该旗标仅属用户);iter 分支合回一卡一提交数卡校验;规则闸 路径性质+分支名+MERGE_HEAD+git 图

验证收拢为合回后远端 CI(post-merge 钩子推送 origin master 触发 Gitea Actions,runner=Mac 本机 host 模式;按改动域分流,分流单点=tools/ci/domain_route.sh),commit 点零执法;主工作区防污染由 ZCode 层守卫承担——只约束 agent,用户手工改动不受限。子代理覆盖面(2026-10-26 冷启动评估实测):子代理的工具调用不经过 ZCode 层守卫——ZCode 层实际只覆盖主会话工具调用;残余暴露面=子代理写主工作区与蓄意 --no-verify(该旗标整族跳过 git 层钩子),属故意越权而非遗忘型失误,与防遗忘的设计目标正交。

三条判定硬闸现行状态

硬闸 run_smoke run_system_test run_all probe_gate render_gate static_scan
退出码优先 已落实(闸①) 已落实(闸①,口径同 run_smoke) 已落实(套件 manifest expect 协议) 已落实(verdict 函数逐段判退出码,PASS 串不作判据) 已落实(段级退出码 + 取证双检) 已落实(fail 聚合退出)
SCRIPT ERROR 扫描 已落实(闸③,外部扫描——GDScript 无脚本错误陷阱 API,闸设在外部包装) 已落实(闸③,标记清单与 run_smoke 同源) 已落实(入口内扫子套件输出;子进程的 stdout/stderr 须先落盘——OS.execute 管道在本机恒空) 已落实(逐探针段 tools/error_scan.py,标记与 run_smoke 同源) 已落实(三段探针日志逐段 tools/error_scan.py,标记与 run_smoke 同源) 不适用(静态域无运行时错误面)
断言数下限 无独立下限(闸②摘要行必须在案,防「跑一半仍 PASS」;脚本错误吞断言路径由闸③兜住) 同 run_smoke(过渡期宿主摘要行必须在案) 已落实(Kit.finish 零断言返回专用退出码 2——与「断言失败=1」区分,防致命类套件的 expect 协议放过) 已落实(退出码 0 但无该探针签名标记亦判红——防静默退出) 不适用(golden 容差 + 取证存在性判定) 不适用(逐规则命中判定;另有扫描面为空即判红的零命中自检)

背景事实(run_smoke 头注在案):GDScript 运行时脚本错误不改进程退出码、不计入冒烟失败数、且静默中断所在函数剩余断言——实证:「309 项 0 失败」实为断言未跑全。这是 SCRIPT ERROR 扫描必须存在于判定层的原因。

静态扫描域 S1–S13 承接清单

静态扫描域规则(2026-09-12 立,沿革见 git commit log;下表为现行事实登记):

# 规则 状态
S1 玩法代码禁 randomize()、自建 RandomNumberGenerator(D2 Rule 5) 在位(硬失败;扫描面 game/core + game/presentation)。非产品码三目录(game/tests/game/probe/game/sim)不进本闸与 S2——它们自建且显式定种的随机源是合法测量口径(同种子对拍改前改后读数),禁的是不定种形态;适用域分档与无机器闸的理由见 code-conventions §4 第 13 条(2026-11-03 架构审查 P1 余项裁:不扩扫描面,人工评审承载)
S2 禁全局随机函数 randi() / randf() / randf_range()——全局 RNG 绕开 RngService(specialist 补登) 在位(与 S1 同段硬失败;实例方法 .randi() 排除、rng-seed-exempt 豁免注记在案)
S3 core/ 禁 ConfigDB 外 data 表加载(load( / preload( / ResourceLoader.load;schema class_name 直引豁免)(D2 Rule 2) 在位(warning 级——class_name 直引误报需人工复核;路径=game/core;豁免 config_db.gd 自身=数值单一事实源的正主)。2026-11-03 架构审查 P1 余项裁维持 warning 级不升硬:升硬的前提是先有可靠的直引误报排除判据,该判据未立;本行状态即事实源,禁在别处另列
S4 core/ 禁 extends Control/Node2D、禁 .tscn preload(D2 Rule 7) 在位(硬失败)
S5 core/ 禁裸引用 autoload 全局标识符(ConfigDB / RngService 直接写 = --script 模式 parse error)——构造注入 only(specialist 升格) 在位(硬失败;形态=标识符后紧跟 . 的成员访问,排除注释行与字符串字面量)
S6 core↔core 信号连接只许方法 Callable(禁 lambda 捕获 self);发射者禁持有订阅者反向引用 在位(2026-10-25 落闸:内联 lambda 禁令机器闸——同行与跨行两形态、豁免注记 s6-signal-exempt、盘面零存量;「发射者禁反向引用」句静态判据不成熟,归人工评审面承接、不造弱判据)
S7 B1 编排唯一性:B2/B3/B4 API 符号命中文件 ⊆ B1 文件集;A2/B3/B4 零相互直调(B1 AC-43) 在位(2026-10-25 落闸:符号清单×B1 域文件集,族内自调用豁免、豁免注记 s7-b1-exempt、缺位自检;全符号形态盘面零存量)
S8 结算路径 await 零命中(B1 结算/编排文件集);字面量扫描 = warning 级 + 人工三要素复核(D2 AC-14 口径) 在位(2026-10-25 落闸:B1 域文件集 await 零命中,排除注释与字符串;盘面零存量。清单单点=static_scan.sh 的 B1_SET,S7 的豁免名单由它派生。自检两件:①清单内文件缺位即红;②目录域反向对账——game/core/settlement/ 实有 .gd 未登记进 B1_SET 即红(新段类忘登记=await 面静默失效)。反向对账只覆盖 settlement/:装板/授予/效果端口/掷格四件结算码住 game/core 根下,纯目录域覆盖不住,根下新增仍由本行「模块归属」B1 登记面+写卡段申报承接。本行后半句「字面量扫描=warning 级+人工三要素复核」为独立子项、仍归人工面

域外扩充五件:S9 类型闸(tools/audit_type_hints.py——产品码无类型容器/有值返回缺类型/参数缺类型;扫描面=产品码三目录);S10 文件头闸(tools/audit_file_headers.py——头注 ## 载体+日期/变更叙事黑名单;扫描面=产品码三目录);S11 代码注释禁用词闸(扫描面=game/ 全域 .gd/.tres/.md/.json/.sh,词表单点取 design/gdd/术语表.md);S12 效果引擎无状态化旧件零残留闸(扫描面=game/ 全域 .gd/.tres,旧符号与旧 id 字面清单为脚本字面值);S13 第三方质量规则闸(tools/gdstyle_gate.py,钉 gdstyle v0.4.0;扫描面=产品码三目录,存量以 tools/gdstyle_baseline.txt 欠账簿登记,判定=基线外新键红、同键数值恶化红)。

S11/S12 扫描面覆盖全域,故 sim/probe/tests 的术语与旧件面在册;其余十一闸(S1–S10、S13)扫描面止于产品码,非产品码三目录不受约束——分档理由与各目录的运行期承接通道见 code-conventions §4 第 13 条。防空转自检现行状态(本文「三层承载与判定原则」要求扫描面为空即判红):S1–S8 与 S11/S12/S13 各自带空面或缺位自检;S9/S10 两件已补齐同款自检(tools/audit_type_hints.py 与 tools/audit_file_headers.py 缺目录或扫描面零个 .gd 一律判红,并绿时打印扫描面件数供核)。

三层承载与判定原则

测试分标准四级+UI 探针(2026-10-22 用户裁),各有在册承载与入闸方式(细目见 game/tests/README.md):

层 判什么 承载 入闸
冒烟测试 这版活着吗(零逻辑判定) game/tests/smoke_boot.tscn/.gd run_smoke.py(冒烟测试闸)
单元测试 领域类的原子行为对不对(从对外方法进、钉对外可观测面——写法判据归 test-conventions §8.2) game/tests/unit/ run_all.gd(单元与集成测试闸)
集成测试 跨系统闭环对不对 game/tests/integration/ 同上(同一入口同一协议)
系统测试 真实玩法路径断言面 game/tests/system_test.gd run_system_test.py(系统测试闸)
UI 探针+渲染 golden 场景切换与观感 game/probe/*.tscn 探针 probe_gate.sh(场景探针闸)、render_gate.sh(渲染闸)

判定原则:验收不能只是「跑一遍没崩」。三硬闸(退出码/脚本错误扫描/断言数下限)是判定的底线, 缺一即判定有洞;「日志里写着 PASS」不作判据。另有两类静默失效必须机制性防范——规则扫描面为空 (路径写错即恒零命中恒绿)与子进程输出丢失(本机 OS.execute 管道恒空),两者都以显式自检拦住。

依赖约束

测试域禁止反向依赖呈现层具体实现。五闸及其调用的探针场景、审计脚本只允许依赖两类边界:

  1. autoload 边界——ConfigDB / RngService 的公开面(--script 模式不加载 autoload 且不注册全局标识符,测试文件自带显式实例化夹具);
  2. 场景契约——探针场景的信号外发面与视图单元接口(信号外发、setter 只读注入),禁直引呈现层实现内部(如 UiKit 工厂内部状态、BoardView 绘制细节)。

测试域是所有层的消费方,进入方式限于上述两类边界;除此之外的依赖方向一律与「模块归属」节依赖单向性同规。

事实源声明

本节为测试域(测试载体、判定口径、静态扫描域)的事实源。新增违规案例仍须先补 static_scan 规则再修码(code-conventions 缺陷-规范对照表纪律)。

S13 测量面豁免注销(2026-10-29 零豁免裁):tune_sim_controller 改 process_frame 信号常驻连接+步进状态机(每帧一局、帧相位逐点对齐,已建件);运行态收尾现行形态=run() 尾每批一次执行。

S13 豁免第三条注销(2026-10-29 零豁免裁):RoundCycle/BattleFacts 两新件设计闭合(宿主实测 15,已建件,见「战斗编排域拆件定稿」节轴丁)。

gdstyle 计数截断缺陷登记:gdstyle v0.4.0 对文件内 inner class 的成员计数存在截断——内嵌类中带行尾注释的属性声明截断其后续成员计数(standee_body 实测 31 声明仅记 19、board_cell_unit 33 仅记 30)。基线登记值属欠估;闸机扫描与基线同源、判定口径自洽不误报,债的真值以实查为准——按真实口径设计(实数低于阈值,不依赖解析缺陷)。登记待办:向 gdstyle 上游报 issue(仍在册)。


数据流

1. 帧更新路径(2D 回合制:无逐帧玩法逻辑)

Input(鼠标)→ D1 输入翻译 → 意图对象 → A2.settle_batch(唯一提交入口)
  → A3.try_spend(原子扣减)→ A2 棋盘效果(挖/连锁/封印/移动)→ 三事件外发
  → [棋盘渲染:D1 BoardView 按事件增量重绘;无事件帧 = 静态 + 动效]
  → 轮次结束 → A3 Waiting → B1 结算编排(段序七段)→ 明细步骤流 → D1 结算屏逐行呈现
  • 回合制下每帧只做:输入采样、呈现刷新、动效推进——玩法状态只在意图事务内变更(单意图帧输入收集:stop 点击终结当帧)。
  • 无跨线程玩法数据流(Godot 主线程假设,D2 EC13);A1 生成若引入 WorkerThread,join 必须先于任何快照切出(既定约束)。

2. 事件/信号路径(系统间通信,无紧耦合)

A2 ──cell_revealed / flag_judged / round_end(棋盘路径)──▶ B1(轮 facts 缓冲)
A3 ──round_end(stopped 直发,payload 同构)──────────────▶ B1
B1 ──notify_settlement_done(next_round_mode) / notify_combat_end──▶ A3
B1 ──apply_effect / apply_damage / grant / 伤害单据 submit…──▶ B3/B2/B4(唯一调用方;段内伤害序=主角先手→逐敌还手→地图账殿后〔案C 2026-10-06〕)
B1 ──install_board / retire_board──▶ A2     B1 ──generate(L,D)──▶ A1
D1 ◀──呈现数据源:A2 事件流 / B1 步骤流 / A3 ap-rap / ConfigDB display_name
  • 事件载体(已定):组合根直连信号接线 + B1 Waiting 相位触发(不依赖事件到达序);autoload 全局事件总线已否决(2026-09-12,沿革见 git 历史)——单线程回合制沿用组合根直连(KISS)。选型理由=可回放(架构原则 3):同步直连让调用顺序显式可见,「同种子逐位相同」才可断言;Godot 信号本身就是同步函数派发,全库不存在事件循环。事件驱动形态服务的是并发/IO 场景对外部不确定时序的反应性,与本作「顺序确定」的需求相反。
  • 事件规范序:A2 发射序 = 触发格 BFS、8 邻行主序;事件序契约 flag_judged < round_end 全路径统一。
  • 呈现层订阅禁令(切片缺陷②教训固化):呈现层永不直接订阅 排雷玩法/行动经济 的事件流,只订 战斗结算 步骤流与 level_runner——核心事件形态变化不得直接冲击界面。

3. 存档/读档路径

  • 存档系统已实装:格式、三槽位、断点域与迁移链的现行契约以 design/gdd/systems/表现与支撑/存档序列化.md(owner)为准。
  • RNG 快照契约(现行仍成立):断点续玩回填 = master_seed + 各流 scope 计数器;快照切出须发生在无正在执行中的 open_stream 实例时(scope 事件边界外——B1 编排保证:切点 = board install 边界);SAVE_FORMAT_VERSION 高版本拒读。

4. 打包与字体(CJK 随包发行)

CJK 字体随包发行并设为 theme 默认字体——运行时默认字体无中文字形。此项是 HUD框架 正式化的硬性前置,同时进导出 checklist 核对项。

5. 初始化顺序

进程启动
  → autoload 实例化:ConfigDB → RngService → SaveManager → MetaProgression(顺序固定;战斗编排器等核心类为普通类、由组合根按局实例化)
  → ConfigDB._ready():load_tables 加载 + 校验(致命通道;失败 = 构建中止 + 错误清单)
  → 主场景(D1 组合根)装配视图单元 + 信号接线
  → C2 begin_run:RngService.set_master_seed()(唯一接线方;两流计数器全零前提)
  → B1.begin_battle(encounter):set_reload_gate(true) → B3 开域 → B2 spawn → A2 install_board(A1.generate) + B4 roll_board(恰一次)→ A3 notify_round_start
  → 挖掘循环 …… → battle_over 清理序列 → set_reload_gate(false)
  → 关卡末:通关结算(钥石/GP/专长 level_clear 渠道——现行语义归 冒险结构 GDD)

启动后置条件(2026-10-17 用户裁入册;执行判据事实源在 game/tests/system_test.gd):

  1. ConfigDB 就绪且表已载(is_ready + hero 表在座)。
  2. 系统设置已落引擎态——Master 音量 mute/volume_db = settings_store 现值;减动效开关 = UiKit.motion_scale。
  3. 启动态菜单可见(boot 后自树顶向下第一个可见内容层 = 开始层——菜单被冒险屏盖住即红)。
  4. 续玩钮可见态恒等于断点在档态(双向:无断点隐藏/有断点可见/清断点回隐;boot 路径与刷新单口同源)。
  5. 闲时会话已在树(run_scope 非空、非冒险会话、在树——永非 null 契约的启动侧证明)。
  6. 调试浮窗 boot 不自动开(菜单优先,2026-10-16 用户令)+ 调试入口全局浮层角标 boot 可见。

API 边界

完整 API 面(含封闭枚举负空间、布尔受理口径、输入×相位矩阵)以各 GDD AC 前言为规范源——本节列边界契约与不变式,实现须与 GDD 逐字一致;冲突时以 GDD 为准并走接口漂移修订。

边界 契约要点 调用方必须遵守的不变式 模块保证
D1 → A2 意图经 settle_batch(intents) 提交;不直调 A3 单意图帧收集;stop 经批次委托 语义序仲裁 + voided 零副作用
A2 → A3 挖/插/拔 = 先棋盘面判定后 try_spend;A2 不可自行扣减 相位判定两侧一致(同一矩阵) 原子事务(余量+扣减+仲裁一体)
A2 → 下游 只外发三事件,payload 字段封闭(digit 恒真透传 / reward_eligible / variant_ids) 增删事件 = 接口漂移 发射面封闭 + 规范序
B1 → B2/B3/B4 全调用面集中 B1;调用序钉死(按摇定技能行兑现→apply_damage→commit_action;先兑付后衰减;段内伤害序=主角先手→逐敌还手→地图账殿后〔案C 2026-10-06〕) 禁第二调用方(静态扫描域:API 符号命中文件 ⊆ B1 文件集) 恰一次编排纪律(roll_board/decay/清理全序)
B1 ↔ A3 编排期代理 request_refresh(玩家意图,禁 RAP 满自动刷);回发 next_round_mode/battle_over stopped/ap_exhausted 未刷新回发 new_board = 违约 fail-fast 刷新受理契约(同 Waiting 多次合法)
各系统 → D2 ConfigDB 类型化属性单点读取 禁绕过 ConfigDB load 表、禁缓存副本、禁玩法数值字面量、禁 randomize()/自建 RNG 校验双通道 + fail-fast 致命
A1 → A2 Board 产物 class_name 数据契约 install 四不变式校验(violation = 拒绝 + 五类诊断枚举) 生成期合法性闸(R₀≠S / clearable / min_safe)
A1 ↔ B1 attempt 边界非 scope 事件;actuals p10 为对账输入(非 target 参数) 编排不把重试当取号 生成期指标集输出(实测可推理率 / 实际雷数与安全格数 / 重试次数 / 降级与非法产物标记)
B4 → B3 buff 类经 B1 调 apply_effect(B4 零跨系统读、零直接接口) 满层拒绝 = 零兑付 + 明细行(无折算) 授予时数值快照(抗热重载)
B1 → D1 步骤流行协议(基础行型+扩展行两层封闭 + 公共字段 type/source_class/origin_cell/round_index/display_name/value/highlight? + 特有字段 target/effect_id/pool_value) 无来源行 = 断言失败;呈现侧禁按行序重演 B2 状态机 可回放步骤流(同种子逐行相同)

引擎类型核验注记:接口使用的引擎类型 = Resource / .tres(D2 全表)、RefCounted(容器类)、Signal/Callable(事件载体)、Control/CanvasLayer/Drawing(D1)、SceneTree headless 协议(测试)——均属 4.x 基线稳定面;4.7 Control 域增量(offset_transform_* 等)已在 breaking-changes.md 登记,D1 采纳前对照核实。


架构原则

  1. 核心层纯逻辑、headless 完整可跑——核心层/功能层玩法逻辑零 Control/场景引用、零 UI 依赖;--headless --script 可跑完整战斗(D2 Rule 7 工程债;切片 88 冒烟实证)。输入是意图对象、输出是事件流/步骤流,D1 与输入设备皆可替换。
  2. 单一事实源与零字面量——玩法数值只存在于 data/tables/*.tres,经 ConfigDB 类型化单点读取;代码零玩法数值字面量;参数禁止跨系统复制(D2 Rule 1/2)。
  3. 封闭 RNG 与可回放——玩法代码零随机;一切随机经 RngService 具名封闭流(增流走 P1 评审);同种子 + 同输入序列 ⇒ 事件流/步骤流逐位相同(结算禁 await,B1 承重约束)。
  4. 编排唯一性与事件面封闭——战斗域跨系统调用权集中 B1(静态扫描承载);A2 三事件面封闭即负空间;每格受理、每雷转化、每次推进、每次衰减各恰一次。
  5. fail-fast + 零特判——数据错误一律致命中止(错误数值上线比崩溃更伤);API 非法 = 拒绝 + 诊断不静默;变异零运行时分支(行为差异全部由生成端约束保证)。
  6. 依赖单向 + 组合根模式——层间单向依赖、唯一回边 = A2 事件订阅面;核心写调用唯一发生在组合根;禁上帝对象(切片 1100 行 main.gd 反面案例 → 9 单元拆分)。
  7. 呈现层契约成文——面向呈现的信号载荷必须有成文 schema;模态覆盖层必须有"打开时遮挡物隐藏"场景级断言;场景级 UI 探针测试为标配(切片缺陷 ①②④⑤ 教训沉淀)。
  8. 系统无状态——效果引擎这类系统零运行时可变状态:数据由宿主对象持有并随宿主生灭,状态按参数传入系统,系统只做判定(立项判据=2026-10-19 用户会话裁定)。系统实例不持计数器——计数器住桶(round/battle/level/adventure 四桶,EffectContext 引用束),桶住宿主。
  9. 停点权威在核心层——玩家决策停点(选路、三选一、商店、恢复这类)的推进守卫住核心层状态机:停点未兑付,推进口一律拒绝(零自动推进契约);呈现层模态只做开合与输入锁——阻塞是两层结构,核心守卫为权威、模态为体验;停点态是核心状态、随断点序列化,headless 跑批与真实局同一套规则,中断续玩恢复到同一停点。

未决问题

ID Summary Priority Resolution Path
QQ-04 轮内刷新数值连锁(清图支配性条款⑤ / 真人刷图行为获取期望)重算 Medium playtest 实测
QQ-05 战斗末可选类"j==0 补发 1 件"兜底是否采纳(切片遗留待办) Medium playtest + B4 GDD 修订批
QQ-06 可选类退出格子池后 buff 频率被动上升(44%→59%)的难度对冲杠杆(敌 HP / 权重 / 幅度) High C3 调参 + 切片数据复测
QQ-07 标错惩罚(A2 OQ1:候选敌方伏击+1;hit=false 无去重的不对称裁决) Medium 原型小补丁实测会话(可与 v3 终验合并)
QQ-08 B5 双舞台陷阱(战斗发生在棋盘上还是独立场景) Low(B5 前) 战斗表现美术测试后裁决
QQ-09 C3 消费 B1 对账输出的事实依赖回写 design/gdd/02-系统清单.md Low C3 GDD 定稿时
QQ-10 .claude/docs/director-gates.md 缺失(TD-ARCHITECTURE/LP-FEASIBILITY 判据无载体) Low 补建 gate 定义文件或维持 solo/lean 模式约定
QQ-11 A1 生成性能姿态(F2c 常数 C 定稿;切片实证 10×10/12×12 同步生成可接受,WorkerThread 留扩展) Medium A1 GDD 修订批
QQ-12 零伤害死局跨字段/跨表护栏落点(B2 OQ9;推荐 D2 跨表校验——切片 LevelTable 校验⑧先例) Medium D2 校验设计批
QQ-13 A1 EC5 运行期熔断(连续降级确定性回退已知好种子) Low A1 GDD 修订批
QQ-14 A5 探测显影接口 / D3 存档格式(RNG 快照契约已在案,格式归 Alpha) Low 秘宝域正式化 / D3 Alpha 设计批