chore: initial commit

This commit is contained in:
DKChan committed 2026-09-14 18:18:49 +08:00
commit ddd2960fa6
317 files changed
+41717

No files matched your search

@@ -0,0 +1,129 @@
# ADR-0001: 事件总线与编排载体(Event Bus & Orchestration Carrier)
## Status
Accepted(2026-09-12,solo 模式用户授权代决;用户迭代期可随时推翻重议——推翻时须走本 ADR 修订 + 下游 AC 连锁复核)
## Date
2026-09-12
## Engine Compatibility
| Field | Value |
|-------|-------|
| **Engine** | Godot 4.7.2-stable |
| **Domain** | Core / Scripting(Signal/Callable/生命周期) |
| **Knowledge Risk** | LOW(4.x 基线稳定;4.5–4.7 变更清单零命中,godot-specialist 校验通过) |
| **References Consulted** | `docs/engine-reference/godot/`(VERSION / breaking-changes / deprecated-apis / current-best-practices);godotengine/godot#6360 |
| **Post-Cutoff APIs Used** | None |
| **Verification Required** | None(切片 88/88 冒烟已实证:双源 round_end 汇聚、可回放步骤流) |
## ADR Dependencies
| Field | Value |
|-------|-------|
| **Depends On** | None |
| **Enables** | ADR-0003(场景结构引用本 ADR 的接线纪律);A2/B1 全部事件序类 AC 从纸面契约转为可执行 |
| **Blocks** | 正式工程骨架搭建(架构文档 Required ADRs 条件) |
| **Ordering Note** | 与 ADR-0008(切片机制正式化)并行无冲突;B1 结算触发语义以本 ADR 载体承载 |
## Context
### Problem Statement
A2(三事件外发)、A3(stopped 直发 round_end,双发射源)、B1(结算触发 = Waiting 相位编排点、不依赖事件到达序)之间的信号载体需要一个落地形态——GDD 层只定行为契约(A2 OQ2 / B1 OQ1 均登记为"实现期 ADR 确认项")。
### Constraints
- 单线程回合制(D2 EC13);Core 层零 UI 依赖、headless 可跑(D2 Rule 7)
- 结算可回放是硬承诺(B1 Core Rule 15:禁 await、零随机)
- 事件序契约:`flag_judged` < `round_end` 全路径统一,但到达序不承载语义
- RefCounted 纯逻辑类无场景表示,无法在 .tscn 编辑器里对接信号
### Requirements
- 支持 A2 三事件面 + A3 stopped 直发的双发射源汇聚
- 支持多订阅者(B1 facts 缓冲;呈现层只订 B1/runner)
- 测试可捕获事件序列(A2/B1 AC 的事件捕获断言面)
- 生命周期确定(无悬挂连接、无循环引用)
## Decision
**组合根直连 signal 接线 + B1 Waiting 相位触发;否决 autoload 全局事件总线。**
1. **信号载体**:A2(RefCounted)声明并发射 GDD 三事件——`cell_revealed` / `flag_judged` / `round_end_board`(GDD 概念名 `round_end` 棋盘路径的实现实名);A3 停手路径发射 `round_end_stopped`(payload 与棋盘路径同构)。回发 `next_round_mode` / `battle_over` 同为 A3/B1 侧 signal。
2. **接线位置**:全部 signal.connect 发生在**组合根**(主场景 Node 的装配代码)——core↔core 无静态耦合,依赖单向由接线拓扑保证。RefCounted 无 .tscn 编辑器对接能力,组合根是唯一自然落点。
3. **B1 触发**:订阅 A3 相位变更(→Waiting)触发结算事务;触发判定只读 A3 相位观测量与 `last_round_end`,**不消费事件到达序**(同步发射 + 双发射源的正确防御—— specialist 确认信号为同步发射、多订阅者投递序 = 连接序 FIFO)。
4. **订阅纪律**:呈现层**永不直接订阅 A2/A3**——只订 B1 步骤流 / runner(切片现状固化,防呈现层绕过编排读核心生命周期状态——切片缺陷②教训)。
### Architecture Diagram
```
[A2 minesweeper_rules]──cell_revealed/flag_judged/round_end_board──┐
[A3 action_economy]────round_end_stopped / phase→Waiting──────────┤
▼
[组合根 main 装配接线]→[B1 battle_orchestrator]
│ 步骤流行协议
▼
[D1 视图单元(只订 B1/runner)]
```
### Key Interfaces
- 信号均为 **方法 Callable 连接**(见禁令);信号参数带类型标注仅作文档,无运行时检查——payload 校验由消费侧断言承载(A2 AC 前言口径)。
- A2 事件捕获测试 API:冒烟经 signal connect 到捕获数组(AC 前言"事件捕获断言面"的落地形态)。
## Alternatives Considered
### Alternative 1: autoload 全局事件总线
- **Description**: 中心 autoload 单例持有全部具名信号,系统经总线收发。
- **Pros**: 解耦发射者/订阅者;全局可发现。
- **Cons**: 全局耦合(任何系统可达任何信号——与"依赖单向"原则冲突);单线程回合制无此需求;事件溯源变难。
- **Rejection Reason**: 过度设计;切片直连形态已验证且更简单。
### Alternative 2: 轮询(B1 每帧查 A3 相位)
- **Description**: B1 在 process 中轮询 A3 相位观测量。
- **Cons**: 延迟(帧粒度)+ 空转;与"回合制无逐帧玩法逻辑"原则冲突。
- **Rejection Reason**: 无收益;信号已同步即时。
### Alternative 3: 回调注册表(A2 持有 handler 列表)
- **Description**: A2 暴露 register(handler) API,非 signal。
- **Cons**: 非 GDScript 惯用;多订阅者接线繁琐;丢掉引擎信号工具链(.tscn 对接、调试器可视)。
- **Rejection Reason**: signal 即本用途的引擎原生方案。
## Consequences
### Positive
- 事件生命周期**确定性优于 Node 方案**:RefCounted 引用计数归零即双向自动断连,无 queue_free 帧末窗口(specialist 核实)——不存在"向半死对象发射"
- 组合根接线使依赖方向可视化、可审计;切片 88/88 已验证
### Negative
- 组合根承担全部接线职责——视图单元增多时接线代码线性增长(切片 main.gd 433 行已容纳;演进为装配器函数分组即可)
- 信号同步发射的再入语义需实现者理解(本 ADR 的"不依赖到达序"即防御)
### Risks
- **lambda 捕获 self 的循环引用**:GDScript lambda 捕获持强引用——短命 RefCounted 以捕获 self 的 lambda 连到长命发射者会延长生命周期乃至成环,自动断连永不触发 → **缓解(固化为本 ADR 静态规则)**:core↔core 信号连接只许方法 Callable;发射者禁止持有对订阅者的反向引用
- 信号参数无运行时类型检查 → 缓解:消费侧断言(既有 AC 口径)+ 呈现载荷 schema 成文义务(code-conventions)
## GDD Requirements Addressed
| GDD System | Requirement | How This ADR Addresses It |
|------------|-------------|--------------------------|
| a2-minesweeper-rules.md | Core Rule 2 三事件回边契约(发射面封闭);OQ2 事件外发载体 | signal 载体 + 实名映射(round_end→round_end_board)+ 组合根接线;捕获 API 承载 AC 断言面 |
| b1-settlement.md | Core Rule 2 结算触发 = Waiting 相位编排点;OQ1 事件总线载体 | 订阅 A3 相位触发、只读 last_round_end、不依赖到达序 |
| a3-action-economy.md | Rule 9 round_end 双发射源(stopped 直发、payload 同构) | round_end_stopped 独立信号,同构 payload 由组包纪律保证 |
| systems-index.md | 唯一回边裁决(A2 只外发、B4/B1 订阅) | 组合根接线拓扑 = 裁决的落地形态 |
## Performance Implications
- **CPU**: 信号发射 = 同步调用链,回合制下每事务个位数次发射——可忽略
- **Memory**: 方法 Callable 弱引用目标、不延长生命周期;lambda 禁令消除成环风险
- **Load Time**: 无
- **Network**: 不适用
## Migration Plan
切片即本决策的实现(`core/minesweeper_rules.gd` 三信号、`action_economy.gd` round_end_stopped、`battle_orchestrator.gd` 双源汇聚)——无迁移,正式化 = 把接线纪律与静态规则写入扫描域(ADR-0004)。
## Validation Criteria
- A2/B1 冒烟事件捕获断言面全绿(既有 88 条覆盖)
- 静态扫描:core↔core 连接零 lambda;发射者零反向引用(ADR-0004 扫描域承载)
- 回放确定性:同种子同输入步骤流逐行相同(B1 AC-33 先例,切片已证)
## Related Decisions
- ADR-0003(场景结构与组合根)、ADR-0004(测试载体与静态扫描域)
- docs/architecture/architecture.md(Data Flow §2 事件路径)
@@ -0,0 +1,119 @@
# ADR-0002: 渲染器与窗口配置(Renderer & Window Config)
## Status
Accepted(2026-09-12,solo 模式用户授权代决;迭代期可推翻重议)
## Date
2026-09-12
## Engine Compatibility
| Field | Value |
|-------|-------|
| **Engine** | Godot 4.7.2-stable |
| **Domain** | Rendering |
| **Knowledge Risk** | MEDIUM(渲染域为 4.5–4.7 变更集中地——本 ADR 相关项已逐条核实,godot-specialist 校验通过) |
| **References Consulted** | `docs/engine-reference/godot/`(四文件);Godot 4.3 release notes(Compatibility 特性补齐);Godot Docs Environment and post-processing |
| **Post-Cutoff APIs Used** | None |
| **Verification Required** | 首次正式导出时核对 gl_compatibility 在目标硬件清单上的实际表现(首次 release 导出 checklist 既有项) |
## ADR Dependencies
| Field | Value |
|-------|-------|
| **Depends On** | None |
| **Enables** | ADR-0003(工程骨架的 project.godot 基线);D1 正式化 |
| **Blocks** | 正式工程骨架搭建 |
| **Ordering Note** | B5 战斗表现若需 HDR 2D 届时复议(见 Risks) |
## Context
### Problem Statement
technical-preferences 将渲染器选择(Forward+ vs gl_compatibility)登记为实现期 ADR;project.godot 的窗口/stretch 基线需要显式定稿——4.7 新项目默认值与训练数据不同(stretch mode canvas_items / aspect expand / Windows 驱动 D3D12),必须显式落盘防漂移。
### Constraints
- 2D 回合制;draw calls < 200 预算;无 3D、无移动端
- headless 测试链路不初始化渲染器(dummy DisplayServer)——测试与渲染器解耦
- 引擎知识 MEDIUM 风险:渲染域选型必须基于已核实清单
### Requirements
- 满足视觉锚(数字可读性、双通道、绘制优先级)所需的渲染能力
- PC(Steam)硬件门槛尽量低
- project.godot 各键显式写入(防未来 config_version 升级漂移)
## Decision
**渲染器 = gl_compatibility;窗口基座 1280×800(切片已验证值)、stretch mode = canvas_items、aspect = expand;全部键显式写入 project.godot。**
```ini
rendering/renderer/rendering_method="gl_compatibility"
rendering/renderer/rendering_method.mobile="gl_compatibility" ; PC 无关,显式对齐防混淆
display/window/size/viewport_width=1280
display/window/size/viewport_height=800
display/window/stretch/mode="canvas_items"
display/window/stretch/aspect="expand"
; display/window/dpi/allow_hidpi —— 4.x 默认 true,无需写入(勿关闭)
```
- **否决 Forward+**:2D 重 UI 无收益;4.6 起 Windows 新项目 D3D12 默认只作用于 Vulkan 系(Forward+/Mobile)——选 gl_compatibility(OpenGL 3.3)**完全绕开 D3D12 新驱动线**,这是 MEDIUM 风险域里的降险选择;GPU 门槛最低。
- **stretch/aspect 与 4.7 新项目默认一致**(canvas_items/expand)——仍显式落盘,防引擎默认未来变化。
- **基座 1280×800** = 切片验证值(非引擎默认 1152×648,亦非本 ADR 初稿设想的 1920×1080);expand 使 16:9 全屏显示正常适配,D1 正式化时如需调整走本 ADR 修订。
### Architecture Diagram
(不适用——配置决策;headless dummy DisplayServer 与本决策完全解耦,冒烟链路不受影响)
### Key Interfaces
- project.godot 键集如上(显式全落盘);渲染器相关代码面 = CanvasItem/Control 绘制(三渲染器共用管线,重 UI 场景 Compatibility 开销最低——specialist 核实)。
## Alternatives Considered
### Alternative 1: Forward+(Vulkan/D3D12)
- **Description**: 4.7 新项目默认渲染器。
- **Pros**: HDR 2D、高级后处理全量可用。
- **Cons**: 2D 回合制无收益;D3D12 为 4.6 起新默认驱动线(成熟度风险敞口);GPU 门槛更高。
- **Rejection Reason**: 零收益 + 增加风险敞口;B5 若需 HDR 2D 届时复议。
### Alternative 2: 沿用引擎新项目默认不显式配置
- **Cons**: 渲染方法默认 forward_plus;基座默认 1152×648 与切片验证值不符;未来 config_version 升级可能漂移。
- **Rejection Reason**: 违背"显式落盘防漂移"要求。
## Consequences
### Positive
- 绕开 D3D12 驱动线与 Vulkan 门槛——MEDIUM 风险域降险
- headless 测试与渲染器解耦(已核实),CI 零 GPU 依赖
- **B5 复议空间存在**:Compatibility 自 4.3 起已支持 2D 灯光+阴影与 glow/bloom——多数 2D 表现需求无需离开本渲染器
### Negative
- 无 HDR 2D(Forward+/Mobile 专属);glow 实现不同且部分属性隐藏——B5 视觉上限受此约束
- Compatibility 已知渲染问题两条登记(GH-110670 HDR2D+tonemap glow 压暗 / GH-90259 开阴影灯光变亮)——B5 采用相关特性时核对
### Risks
- B5 需要超出现有能力的表现 → 缓解:复议通道 = 本 ADR 修订(迁移成本 2D 项目可控)
- OpenGL 3.3 在极旧硬件的覆盖 → 缓解:目标平台 PC Steam 主流硬件;首次导出 checklist 核对
## GDD Requirements Addressed
| GDD System | Requirement | How This ADR Addresses It |
|------------|-------------|--------------------------|
| technical-preferences.md | Renderer 选择留实现期 ADR;draw calls < 200 | gl_compatibility + 自绘/控件混合渲染在此预算内宽裕 |
| game-concept.md | 视觉锚三条硬约束 | canvas_items stretch 保证数字缩放清晰;Compatibility 2D 管线满足绘制优先级栈 |
| d2-data-config.md | Rule 7 headless 工程债 | dummy DisplayServer 与渲染器解耦(已核实) |
## Performance Implications
- **CPU**: Compatibility 2D 管线开销最低(重 UI 场景——specialist 核实)
- **Memory**: 三渲染器中最低
- **Load Time**: 无差异
- **Network**: 不适用
## Migration Plan
切片 project.godot 已写 gl_compatibility——正式工程直接继承;补齐基座尺寸与 stretch 键显式落盘。
## Validation Criteria
- draw calls 实测 < 200(D1 集成时用编辑器 profiler 核对)
- 16:9 全屏 / 窗口两种形态下数字可读性目检(视觉锚 1)
- headless 冒烟不受渲染器影响(88/88 维持)
## Related Decisions
- ADR-0003(场景结构——project.godot 同批落盘)、ADR-0010(B5 战斗舞台,未立项)
- docs/engine-reference/godot/current-best-practices.md §1(新项目默认值差异)
@@ -0,0 +1,138 @@
# ADR-0003: 场景结构与棋盘渲染(Scene Structure & Board Rendering)
## Status
Accepted(2026-09-12,solo 模式用户授权代决;迭代期可推翻重议)
## Date
2026-09-12
## Engine Compatibility
| Field | Value |
|-------|-------|
| **Engine** | Godot 4.7.2-stable |
| **Domain** | Core / Scripting + UI |
| **Knowledge Risk** | LOW-MEDIUM(结构决策 LOW;渲染呈现项 MEDIUM——CanvasItem 线条 AA 羽化移除已核实,godot-specialist 校验含 2 项实质修正后通过) |
| **References Consulted** | `docs/engine-reference/godot/`(四文件);godotengine/godot#6360(--script 无 autoload) |
| **Post-Cutoff APIs Used** | None |
| **Verification Required** | CJK 字体随包发行的显示核对(首次正式导出 checklist 增补项);D1 正式化时若执行 _draw 迁移则另核命中测试/无障碍 |
## ADR Dependencies
| Field | Value |
|-------|-------|
| **Depends On** | ADR-0001(组合根接线纪律)、ADR-0002(project.godot 基线同批落盘) |
| **Enables** | 正式工程骨架搭建;D1 正式化 |
| **Blocks** | ADR-0004 扫描域(引用本 ADR 的 core 隔离规则) |
| **Ordering Note** | 棋盘渲染形态裁决(本 ADR §Decision 3)与 ADR-0004 探针耦合——见 Decision 3 的迁移工作项 |
## Context
### Problem Statement
正式工程骨架需要定稿:autoload 清单、core/presentation 的类形态与目录结构、棋盘渲染的实现路径。切片已验证一套形态,但初稿 ADR 把"自绘 _draw()"当作切片事实——godot-specialist 校验发现切片 BoardView 实为 **GridContainer + 逐格常驻控件**,本 ADR 按校验修正。
### Constraints
- Core 层零 UI 依赖、headless 可跑(D2 Rule 7);--script 模式下 core 禁裸引用 autoload 全局标识符(编译期即炸——见 ADR-0004)
- 同屏 draw calls < 200;棋盘 ≤12×12(MVP 量级)+数字/小人/旗/变异多层叠加(视觉锚绘制优先级栈)
- 领域命名规范(docs/code-conventions.md:禁 ID 前缀、头注溯源)
### Requirements
- 切片验证过的结构不推倒(用户拍板"按常规老路子")
- 呈现层与核心的写边界:核心写调用唯一发生在组合根
- 中文文案可显示(运行时默认字体无 CJK 字形——specialist 核实)
## Decision
**1. autoload 清单 = {ConfigDB, RngService}(定名锁定),仅此两个。**
战斗编排器等核心类为普通类、由组合根按局实例化——非 autoload、非场景节点。
**2. 类形态与目录结构:core/ 纯逻辑类 = RefCounted;ConfigDB/RngService = autoload Node 单例(引擎约束:autoload 脚本必须 extends Node);presentation/ = Control 派生视图单元。**
```
res://
├── core/ # RefCounted 纯逻辑(board_generator / minesweeper_rules /
│ # action_economy / battle_orchestrator / unit_container /
│ # status_container / reward_economy / level_runner / 数据类)
│ # —— 零 Control 引用、零 .tscn preload、零 autoload 全局标识符裸引用
├── data/
│ ├── schemas/ # D2 schema 类(Resource 派生——D2 体系,非本 ADR 变更项)
│ └── tables/ # .tres 数值表(单一事实源)
├── presentation/
│ ├── views/ # 九单元:BoardView / HUDView / BattleLogView / ItemWindowOverlay /
│ │ # NodeOverlay / LevelStripView / TunePanel / UiKit
│ ├── hud_presenter.gd
│ └── main.tscn + main.gd # 组合根:模式流转 + 信号接线 + 核心写调用唯一落点
├── smoke/ # 冒烟脚本 + 探针场景(ADR-0004)
└── docs/architecture/
```
**3. 棋盘渲染形态:MVP 沿用切片已验证形态——GridContainer + 逐格常驻控件(BoardView 持 `_cells`,refresh 内逐格更新);自绘 `_draw()` 迁移登记为 D1 正式化候选工作项(非本 ADR 承诺)。**
- specialist 校验事实:切片 BoardView = GridContainer + 逐格 Button(`_paint_cell` 逐格更新),三探针与该形态耦合(ui_probe 断言 `_cells` 非空、click_probe 依赖 `click_cell` 入口)。初稿"_draw 是切片形态的正式化"**不成立**,按事实修正。
- 形态对比留档:逐格控件(现状)= 命中测试/悬停/焦点由引擎承担、探针兼容;代价 = 控件树随格数增长(12×12=144 控件,实测无压力)。`_draw()` = 单 draw call、绘制优先级栈完全可控;代价 = 自建命中测试/悬停 + **三个探针改造**(`_cells` 断言与 `click_cell` 入口失效)+ 无障碍面缺失 + 需补 `Viewport.push_input` 端到端输入探针。
- 裁决:D1 正式化 GDD 评审时按当时视觉需求(biome 色板、雾纹理、动效复杂度)二选一;在此之前禁盲目迁移(探针改造是隐藏成本)。任一形态下 CanvasItem 线条 AA 羽化移除(4.7)需注意——格边框用填充 `draw_rect` 不受影响。
**4. CJK 字体前置(specialist 补登,两种形态都受影响)**:Godot 运行时默认字体不含 CJK 字形——全部中文文案(按钮/标签/结算明细)必须**随包发行 CJK 字体并设为 theme 默认字体**。登记为 D1 正式化硬性前置项 + 首次导出 checklist 项。
### Architecture Diagram
见 `docs/architecture/architecture.md` System Layer Map + Module Ownership(本 ADR 是其工程形态落点)。
### Key Interfaces
- 组合根 = 唯一核心写调用落点(settle_batch / submit_window_selection / runner 推进)——切片纪律转正
- 视图单元 = 信号外发 + setter 只读注入(BoardView 只读 A2、动作信号外发不碰核心写)
## Alternatives Considered
### Alternative 1: 战斗编排器设为 autoload
- **Cons**: 编排器持有跨局状态却永生——生命周期与战斗域契约冲突(Uninit/BattleOver 状态机要求按局重建);与"autoload = 全局基础设施"边界冲突。
- **Rejection Reason**: 切片形态(按局实例化)已验证且语义正确。
### Alternative 2: 棋盘 = 每格一个 Node2D
- **Pros**: 独立节点动画/模组方便。
- **Cons**: 每节点处理开销与 Control/Node2D 混管复杂度;无必要(specialist 指出 2D 同材质有批处理,draw call 论据最弱,但节点开销与混管论据成立)。
- **Rejection Reason**: 逐格控件已覆盖需求且已验证。
### Alternative 3: TileMapLayer 承载棋盘
- **Cons**: 4.5 物理分块默认变更(纯视觉不踩,但物理用途即触);瓦片语义与"变体标记/数字/旗多层叠加"不匹配。
- **Rejection Reason**: 语义不匹配是硬伤;现形态无此问题。
## Consequences
### Positive
- 结构与切片零迁移成本;core 隔离规则可静态扫描(ADR-0004)
- 棋盘形态留有 D1 期复议空间且复议成本已如实登记
### Negative
- 逐格控件形态在 D1 需要高表现力时可能仍需迁移 _draw(成本已登记:探针改造 + 命中测试自建 + push_input 端到端探针)
- CJK 字体为新增资产义务(发行体积 +)
### Risks
- D1 正式化时遗漏"探针与形态耦合"约束 → 缓解:本 ADR Decision 3 + ADR-0004 探针节双登记
- core 类被随手加 autoload 裸引用 → 缓解:ADR-0004 静态扫描(parse 期即炸的事实使该风险自暴露)
## GDD Requirements Addressed
| GDD System | Requirement | How This ADR Addresses It |
|------------|-------------|--------------------------|
| d2-data-config.md | Rule 7 零 UI 依赖;Rule 2 单点访问 | core 隔离规则 + autoload 清单固化(ConfigDB/RngService 定名) |
| game-concept.md | 视觉锚(绘制优先级栈、双通道) | 棋盘形态两案对比留档,D1 正式化按锚需求裁决 |
| b1-settlement.md | Core Rule 1 编排器按局生命周期 | 编排器非 autoload、组合根按局实例化 |
| docs/code-conventions.md | 领域命名 / 组合根纪律 | 目录结构与 Key Interfaces 转正 |
## Performance Implications
- **CPU**: 144 常驻控件逐格更新——切片实测无压力;_draw 迁移后更优(单 draw call)
- **Memory**: 可忽略
- **Load Time**: CJK 字体载入一次性成本
- **Network**: 不适用
## Migration Plan
切片即目标形态(结构零迁移);CJK 字体接入与 _draw 复议归 D1 正式化批次。
## Validation Criteria
- 冒烟 88/88 + 三探针在正式工程维持全绿
- 静态扫描:core/ 零 Control extends / 零 .tscn preload / 零 autoload 全局标识符裸引用(ADR-0004 域)
- 中文文案在导出包内显示正常(导出 checklist)
## Related Decisions
- ADR-0001(接线纪律)、ADR-0002(渲染器与窗口键)、ADR-0004(扫描域与探针)
- docs/architecture/architecture.md(Module Ownership / Required ADRs——本 ADR 落定后其 §Required ADRs 第 3 项闭合)
@@ -0,0 +1,132 @@
# ADR-0004: 测试载体与 CI(Test Carrier & CI)
## Status
Accepted(2026-09-12,solo 模式用户授权代决;迭代期可推翻重议)
## Date
2026-09-12
## Engine Compatibility
| Field | Value |
|-------|-------|
| **Engine** | Godot 4.7.2-stable |
| **Domain** | Core / Scripting(测试与工具链) |
| **Knowledge Risk** | LOW(--script/探针模式为 4.x 基线;godot-specialist 校验通过,含两条规则升格) |
| **References Consulted** | `docs/engine-reference/godot/`(四文件);godotengine/godot#6360(--script 模式不加载 autoload + 不注册全局标识符——官方立场) |
| **Post-Cutoff APIs Used** | None |
| **Verification Required** | None(切片 88/88 + 三探针已实证;CI 外部超时在正式 CI 接入时核对) |
## ADR Dependencies
| Field | Value |
|-------|-------|
| **Depends On** | ADR-0003(core 隔离规则是扫描域的输入) |
| **Enables** | 全部 GDD AC 的可执行化;正式 CI 接入 |
| **Blocks** | `/gate-check` 前置项之一(`/test-setup` 以本 ADR 为基线) |
| **Ordering Note** | gdUnit4 复议登记为 D2 OQ1 的关闭形态(推迟,非否决) |
## Context
### Problem Statement
D2 GDD 定下 `--headless --script` 冒烟载体(脚本 extends SceneTree、autoload 显式实例化),D2 OQ1 留下"gdUnit4 是否引入"待决;切片新增了场景级 UI 探针形态;项目级静态扫描域散落在各 GDD AC(AC-9/17/21/22/43 等)需要一处统一登记。
### Constraints
- headless 全套 < 30s 预算(technical-preferences)
- 致命类用例独立进程协议("调用 → 期望退出码" runner manifest,D2 AC-2b 起)
- 呈现层测试必须有承载(切片教训:已定稿 AC 全覆盖 core、呈现层零测试承载 → 缺陷 ①②④⑤ 漏网)
### Requirements
- 双模式边界明确:逻辑冒烟(无 autoload)vs 场景探针(完整项目引导)
- 静态扫描规则统一载体,覆盖 D2/A1–B4 各 AC 登记的扫描项
- CI 可接入且防挂死
## Decision
**双载体 + 统一静态扫描域;gdUnit4 推迟到正式 CI 期。**
**1. 逻辑冒烟(`--headless --script`)**:脚本 extends SceneTree 以获得 `quit(code)`;ConfigDB/RngService 由脚本显式实例化(引擎事实:--script 模式**不加载 autoload 且不注册全局标识符**——裸引用 = parse error 编译期即炸,GH #6360 官方确认)。Windows 用 console 版 exe 取 stdout。承载:D2/A1–B4 全部纯逻辑 AC + 致命类独立进程 manifest。
**2. 场景探针(headless 跑 .tscn 探针场景)**:以探针场景为运行目标(`godot --headless --path . res://smoke/<probe>.tscn`)走正常项目引导——autoload 在位、真实 SceneTree、`await process_frame` 有效。承载:呈现层场景级测试(切片三探针 ui_probe / ui_click_probe / ui_tune_probe 为先例)。
- **口径修正(specialist 校验)**:click_probe 走 `BoardView.click_cell` 是"真实翻译出口",**绕过 Viewport GUI 管线**(无命中测试/悬停/焦点)。表述定为"合成输入走真实翻译出口";真正的端到端输入测试 = `Input.parse_input_event()` / `Viewport.push_input` 带坐标——若 ADR-0003 的 _draw 迁移执行(Button 命中测试消失),push_input 探针从加分项变为**必需项**(登记入迁移工作项)。
**3. 项目级静态扫描域(统一登记,CI 与冒烟前置双跑)**:
| # | 规则 | 来源/动机 |
|---|---|---|
| S1 | 玩法代码禁 `randomize()`、自建 `RandomNumberGenerator` | D2 Rule 5(既有) |
| S2 | **禁全局随机函数 `randi()` / `randf()` / `randf_range()`**(全局 RNG 绕开 RngService——specialist 补登漏洞) | D2 Rule 5 补全 |
| S3 | core/ 禁 ConfigDB 外 data 表加载(`load(` / `preload(` / `ResourceLoader.load`;schema class_name 直引豁免) | D2 Rule 2(既有) |
| 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);发射者禁持有订阅者反向引用 | ADR-0001(防循环引用/生命周期延长) |
| S7 | B1 编排唯一性:B2/B3/B4 API 符号命中文件 ⊆ B1 文件集;A2/B3/B4 零相互直调 | B1 AC-43(既有) |
| S8 | 结算路径 `await` 零命中(B1 结算/编排文件集);字面量扫描 = warning 级 + 人工三要素复核(D2 AC-14 口径) | B1(既有) |
**4. CI 防挂死**:任何探针/冒烟调用旁必须配**外部 wall-clock 超时**(命令行 timeout)——引擎自身无死锁探测;探针内 30 帧停滞检测(click_probe 先例)是第一道、外部超时是最后防线。headless 全套 < 30s 预算不变。
**5. gdUnit4:推迟到正式 CI 期再议**(D2 OQ1 以"deferred"关闭)。它运行在项目模式(autoload 在位),与 SceneTree 冒烟机制正交,引入不废弃既有用例。
### Architecture Diagram
```
提交 → [静态扫描 S1–S8(秒级)] → [逻辑冒烟 --script(独立进程 manifest,<30s)]
→ [场景探针 ×N(headless + 外部超时)] → 全绿放行
```
### Key Interfaces
- 冒烟 runner manifest:条目 = "调用 → 期望退出码"(独立进程、游戏通道)——D2 AC-2b 协议延续
- 探针退出码:0 = PASS;非 0 = 失败类别;停滞 quit(2)
## Alternatives Considered
### Alternative 1: 立即引入 gdUnit4 并迁移全部冒烟用例
- **Pros**: 标准 assertions/参数化/报告;编辑器面板。
- **Cons**: 88 条用例迁移成本即刻发生;切片框架已验证且快(~3s);MVP 期无 CI 基建需求。
- **Rejection Reason**: 收益在 CI 期才兑现——推迟(非否决),D2 OQ1 关闭形态。
### Alternative 2: 仅保留逻辑冒烟、UI 靠人工
- **Cons**: 切片缺陷 ①②④⑤ 全部漏过既有 AC 的教训直接否定——呈现层无承载 = 呈现层缺陷零防线。
- **Rejection Reason**: 呈现层契约测试是 code-conventions 硬性要求。
## Consequences
### Positive
- 双模式边界以引擎事实固化(parse 期炸 vs 完整引导),不再靠约定俗成
- S2/S5/S6 三条 specialist 补登规则堵住静默翻车路径(全局随机绕开、裸引用编译炸、lambda 成环)
- 呈现层探针形态沉淀为项目标配(code-conventions 承载)
### Negative
- 静态扫描规则 8 条的维护成本(新规则须挂真实反面案例——code-conventions 纪律)
- "真实 UI 路径"表述收窄后,端到端输入覆盖存在已知缺口(_draw 迁移前可接受)
### Risks
- 未被停滞检测覆盖的死锁挂死 CI → 缓解:外部 wall-clock 超时为硬性要求
- 扫描规则漏报(启发式)→ 缓解:行为级硬证据并行(可回放断言、headless 实跑合成判定——D2 AC-9/10 模式)
## GDD Requirements Addressed
| GDD System | Requirement | How This ADR Addresses It |
|------------|-------------|--------------------------|
| d2-data-config.md | Rule 6 校验双通道;AC-2b 独立进程协议;OQ1 gdUnit4 | 冒烟框架定稿;manifest 延续;OQ1 关闭为 deferred |
| a1–b1 各 GDD | 各自静态扫描 AC(AC-9/17/18/19/21/22/43 模式) | S1–S8 统一登记为项目级域,各 AC 引用本 ADR |
| docs/code-conventions.md | 场景探针标配 / 提交前全量 | 双载体 + CI 链路承载 |
| b1-settlement.md | AC-43 编排唯一性单向扫描 | S7 载体 |
## Performance Implications
- **CPU**: 全套冒烟 ~3s(切片实测),预算 <30s 富余
- **Memory**: headless dummy server 极低
- **Load Time**: 探针场景引导一次性
- **Network**: 不适用
## Migration Plan
切片 smoke/ 目录即载体(零迁移);正式 CI 接入时补外部超时包装与 S1–S8 脚本化;`/test-setup` 以本 ADR 为基线脚手架。
## Validation Criteria
- 冒烟 + 探针全绿为提交门(code-conventions"提交前全量")
- 扫描域脚本化后:新增违规案例必须先补扫描规则再修码(缺陷-规范对照表纪律)
- `<30s` 预算在 CI 环境复核
## Related Decisions
- ADR-0001(S6 规则来源)、ADR-0003(S4/S5 规则来源、探针形态耦合)
- docs/code-conventions.md(缺陷-规范对照表)、各 GDD AC 前言(规范源)
@@ -0,0 +1,104 @@
# ADR-0005: 存档契约与版本化(Save Contract & Schema Versioning)
## Status
Accepted(2026-09-12,solo 模式用户授权代决;轻量契约 ADR——实现归 D3 Alpha,本 ADR 只锁契约使 Foundation 层 TR 覆盖闭合)
## Date
2026-09-12
## Engine Compatibility
| Field | Value |
|-------|-------|
| **Engine** | Godot 4.7.2-stable |
| **Domain** | Core(数据/序列化契约) |
| **Knowledge Risk** | LOW(契约层; FileAccess/JSON 基线稳定) |
| **References Consulted** | `docs/engine-reference/godot/`(四文件);D2 GDD Rule 8 / EC9 / RNG 生命周期 |
| **Post-Cutoff APIs Used** | None |
| **Verification Required** | None(D3 实现期按契约验证) |
## ADR Dependencies
| Field | Value |
|-------|-------|
| **Depends On** | None |
| **Enables** | D3 存档序列化(Alpha)——契约先行,实现期免重议 |
| **Blocks** | None |
| **Ordering Note** | 清零 Foundation 层 TR 覆盖缺口(requirements-traceability.md 的最后两条 pending) |
## Context
### Problem Statement
Technical Setup → Pre-Production 门要求"Foundation 层需求 ADR 覆盖零缺口"。63 条 TR 基线中 Foundation 层尚有两条无 ADR 承载:TR-d2-010(SCHEMA_VERSION 版本化)与 TR-gc-002(RNG 快照存续契约)。两者的契约在 D2 GDD 已定但散落,未 ADR 化——本 ADR 收拢,D3 Alpha 实现时照契约执行。
### Constraints
- MVP 无元进度存档(C4/D3 归 Alpha)——本 ADR 不引入任何 MVP 实现
- RNG 快照语义已被 D2 GDD(RNG 生命周期)与 B1 GDD(回放切点)锁定——本 ADR 只做契约归集,不改语义
### Requirements
- 版本不匹配拒绝读取(高版本拒读,D2 EC9)
- 续玩/复盘可从快照精确恢复随机序列
- 快照切点与在飞流实例的互斥有明确归属
## Decision
**1. 版本化契约**:`SCHEMA_VERSION` 常量归 D2(既定);存档文件携带该版本号;**比较逻辑归 D3**(D2 EC9 既有分工)——存档版本 > 当前 SCHEMA_VERSION → 拒绝读取 + 明确错误信息;低版本存档的迁移策略归 D3 Alpha 设计时定(候选:拒读 / 迁移器——届时另议,非本 ADR 范围)。
**2. RNG 快照契约(从 D2/B1 GDD 收拢为 ADR 登记)**:
- 快照内容 = `master_seed` + 各封闭流 scope 计数器 + 意图序列 + 窗口选择序列
- **切点规则**:快照切出必须发生在 scope 事件边界之外(无在飞 `open_stream` 实例时);运行期 scope 事件边界 = board install(A1 取号 / B4 取号)——B1 编排保证无在飞实例跨界(消费侧遵守义务,B1 GDD 回放切点条款)
- 违反后果:续玩/复盘与实况分叉(D2 AC-15 语义失效)——该前提由 D3 消费侧遵守,B1 侧编排义务已在位
**3. 存档内容归属预告(D3 Alpha 实现的输入清单,非本 ADR 决策)**:冒险结构(C2 域)、关卡进度(C1 域)、HP/库存(B1/B4 关卡域)、代币/天赋(C4 MetaTable)、RAP 不持久(战斗域清零)。D3 GDD 立项时按此清单展开。
### Architecture Diagram
(不适用——契约 ADR;数据流见 architecture.md §Data Flow 3)
### Key Interfaces
- D3 → D2:读取 `SCHEMA_VERSION`(比较方向:存档版本 ≤ 当前才可读)
- D3 → RngService:只读计数器接口(D2 已暴露)+ `set_master_seed`(仅 C2 调用——D3 只读快照、恢复时经 C2 重放接线)
## Alternatives Considered
### Alternative 1: 不立 ADR,依赖 D2/D3 GDD 散落条款
- **Cons**: gate 的 Foundation 零缺口检查失败;契约散落三处(D2 EC9 / D2 RNG 生命周期 / B1 回放切点),D3 实现时需跨三文档拼装。
- **Rejection Reason**: 收拢成本一次会话内,收益是门检查全绿 + D3 立项输入就绪。
### Alternative 2: 现在就设计存档格式(JSON vs 二进制 vs Resource)
- **Cons**: C4/D3 未设计,过早——MVP 无存档需求牵引。
- **Rejection Reason**: 违背"schema 先行、数值回填"的项目节奏;格式决策留给 D3 GDD。
## Consequences
### Positive
- Foundation 层 TR 覆盖零缺口(门检查全绿)
- D3 立项时的硬输入就绪(版本比较方向、快照内容、切点规则、内容归属清单)
### Negative
- 无(纯收拢,零新约束)
### Risks
- D3 Alpha 实现时偏离切点规则 → 缓解:本 ADR + D2 AC-15 / B1 AC-34 双侧断言承载
## GDD Requirements Addressed
| GDD System | Requirement | How This ADR Addresses It |
|------------|-------------|--------------------------|
| d2-data-config.md | Rule 8 版本化;EC9 高版本拒读;RNG 快照生命周期 | 契约收拢 + 版本比较归属(D3)成文 |
| b1-settlement.md | 回放切点契约(快照语义 = seed + 计数器 + 两类输入序列) | 切点规则 ADR 化(无在飞实例时切出,scope 边界 = board install) |
| game-concept.md | 存档/冒险/关卡术语层级(C4/D3 Alpha 范围) | 存档内容归属预告清单 |
## Performance Implications
- **CPU / Memory / Load Time / Network**: 无(MVP 零实现;Alpha 期存档体积预期 < 1MB 量级)
## Migration Plan
无迁移(MVP 零实现)。D3 GDD 立项(Alpha 期)以本 ADR 为硬输入。
## Validation Criteria
- D3 实现后:同快照恢复 → 随机序列逐位一致(D2 AC-15 / B1 AC-34 形态)
- 版本不匹配路径拒绝读取且错误信息含两侧版本号
- tests/integration/ 收录存档往返测试(D3 落地时)
## Related Decisions
- ADR-0001(回放输入序列的载体)、ADR-0004(集成测试载体)
- docs/architecture/requirements-traceability.md(TR-d2-010 / TR-gc-002 覆盖闭合)
+295
View File
@@ -0,0 +1,295 @@
# Dungeon Sweeper — Master Architecture
## Document Status
- Version: 1.0
- Last Updated: 2026-09-12
- Engine: Godot 4.7.2-stable(GDScript 单语言;2026-09-07 锁定)
- Review Mode: solo(`production/review-mode.txt`,2026-09-12 用户拍板——TD/LP 门禁按 solo 跳过,用户授权架构产出自主推进、迭代期回调)
- GDDs Covered: game-concept · game-pillars · systems-index · d2-data-config · a3-action-economy · a4-terrain-variation · b3-status-effect · a1-board-generation · a2-minesweeper-rules · b2-enemy-system · b4-reward-item-economy · b1-settlement(12 份;A5/C1–C4/B5/D3–D6 未设计,按 systems-index 依赖分层预留)
- ADRs Referenced: 无(0 份现存)——本文档 Phase 5/6 列出的实现期裁决项即为首批 ADR 候选
- Implementation Evidence: 垂直切片 `prototypes/dungeon-sweeper-vertical-slice/`(2026-09-10 起,冒烟 88/88、三 UI 探针 PASS)——本文档的分层/所有权/数据流均经切片实现验证,非纯纸面设计
- Technical Director Sign-Off: 2026-09-12 — APPROVED WITH CONDITIONS(条件:Required ADRs 于正式工程骨架搭建前定稿;`.claude/docs/director-gates.md` 缺失已登记技术债)
- Lead Programmer Feasibility: SKIPPED — Solo mode
---
## Engine Knowledge Gap Summary
- **风险等级:MEDIUM**(2026-09-12 `/setup-engine refresh` 后由 HIGH 降级)。4.5→4.7 官方迁移指南已逐条核实并入 `docs/engine-reference/godot/breaking-changes.md` 与 `deprecated-apis.md`;**结论:无一条破坏 GDD 已锁架构契约**(autoload 体系 / .tres 单一事实源 / Callable 信号 / int64 二补数 / headless SceneTree 协议均不受影响)。
- 写码纪律不变:不确定的 API 一律查 `docs.godotengine.org/en/4.7/` 核实后再用;4.8(dev 阶段)稳定版发布后跑 `/setup-engine refresh`。
- 三类必须入编码纪律的引擎事实(详见 `docs/engine-reference/godot/current-best-practices.md`):
1. **GDScript 4.7 两条语义变化**:打包数组元素赋值不再触发属性 setter;类型化返回的方法覆盖必须显式 `return`。
2. **新项目默认值已变**:stretch mode `canvas_items` / aspect `expand`(4.7);Windows 渲染驱动 D3D12(4.6,仅 Forward+ 线)——创建 project.godot 后逐项核对。
3. `Resource.duplicate(true)` 深复制不再覆盖外部子资源——D2 表资源复制语义注意。
- 残余风险敞口:modules/ 分域参考未建(按实现期需要建,非阻塞);UI/渲染域(D1/B5)为 MEDIUM 风险集中地,随 ADR-0002/0003 裁决时对照引擎文档核实。
---
## System Layer Map
20 系统按 systems-index 依赖分层表(systems-design 门禁已评审)映射到标准五层。切片实现已验证该分层(core/ 纯逻辑零 UI 依赖 headless 可跑、presentation/ 组合根模式)。
```
┌────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ D1 HUD 与界面框架 (MVP) · B5 战斗表现 (切片后) │
│ D4 音频 (Alpha) · D5 教学引导 (Alpha) │
├────────────────────────────────────────────────────────────┤
│ FEATURE LAYER │
│ B1 战斗结算编排 (MVP) · C1 关卡节点地图 (切片已含 lite) │
│ C2 冒险结构 · C3 难度曲线 · C4 元进度 (Alpha) │
├────────────────────────────────────────────────────────────┤
│ CORE LAYER │
│ A1 扫雷棋盘生成 · A2 排雷玩法规则 · B2 敌人系统 │
│ B4 奖励与道具经济 · A5 扫雷辅助道具 (垂直切片) │
├────────────────────────────────────────────────────────────┤
│ FOUNDATION LAYER │
│ D2 数据配置与数值表 · A3 行动经济 · A4 地形变异 │
│ B3 增益/状态系统 · D3 存档序列化 (Alpha) · D6 设置/本地化│
├────────────────────────────────────────────────────────────┤
│ PLATFORM LAYER │
│ Godot 4.7.2 引擎 API 面(GDScript / Resource / │
│ SceneTree / Control / InputEvent)——无游戏系统 │
└────────────────────────────────────────────────────────────┘
```
| 系统 | 层 | 里程碑 | headless 约束 | 引擎风险域 |
|---|---|---|---|---|
| D2 数据配置 | Foundation | MVP | ✅ 完整可跑 | LOW(Resource/.tres 基线稳定) |
| A3 行动经济 | Foundation | MVP | ✅ 完整可跑 | LOW(纯逻辑) |
| A4 地形变异 | Foundation | MVP | ✅ 完整可跑 | LOW(纯逻辑) |
| B3 状态系统 | Foundation | MVP | ✅ 完整可跑 | LOW(RefCounted 纯逻辑) |
| A1 棋盘生成 | Core | MVP | ✅ 完整可跑 | LOW(纯逻辑;性能姿态归 ADR-0005) |
| A2 排雷规则 | Core | MVP | ✅ 完整可跑 | LOW(零表读取零 UI) |
| B2 敌人系统 | Core | MVP | ✅ 完整可跑 | LOW(纯逻辑) |
| B4 奖励经济 | Core | MVP | ✅ 完整可跑 | LOW(纯逻辑) |
| B1 战斗结算编排 | Feature | MVP | ✅ 完整可跑(禁 await) | LOW(纯逻辑;事件载体归 ADR-0001) |
| C1 关卡节点地图 | Feature | 垂直切片(lite 已入切片) | ✅(切片 level_runner 先例) | LOW |
| C2 冒险结构 | Feature | 垂直切片 | ✅ | LOW |
| C3 难度曲线 | Feature | 垂直切片 | ✅ | LOW |
| C4 元进度 | Feature | Alpha | ✅ | LOW |
| D1 HUD | Presentation | MVP | ❌(UI 层——场景级探针测试承载) | **MEDIUM**(Control/Input/文本域) |
| B5 战斗表现 | Presentation | 垂直切片 | ❌ | **MEDIUM**(Animation/Tween/渲染) |
| D4 音频 / D5 教学 | Presentation | Alpha | 部分 | LOW-MEDIUM |
| D3 存档序列化 | Foundation | Alpha | ✅ | LOW |
| D6 设置/本地化 | Foundation | 完整愿景 | ✅ | LOW |
**MVP 关键路径**(切片已验证):D2 → A3/A4/B3 → A1 → A2 → B2/B4 → B1 → D1-lite。
**依赖分层与唯一回边**:A2 只外发三事件(cell_revealed / flag_judged / round_end),B4/B1 订阅后回调——A2 不依赖任何下游(TD-SYSTEM-BOUNDARY 裁决,全项目唯一允许回边)。
---
## Module Ownership
> 命名遵循 `docs/code-conventions.md` + CLAUDE.md 代码规范:领域命名、禁 ID 前缀、头注溯源行(实现 GDD:design/gdd/…)。切片已按此规范完成领域命名批。
### Foundation 层
| 模块 | Owns(独占) | Exposes | Consumes | 引擎 API |
|---|---|---|---|---|
| **ConfigDB**(autoload,D2) | 全部玩法数值表(`data/tables/*.tres` + `data/schemas/*.gd`);SCHEMA_VERSION;加载/校验/override/诊断状态机 | 类型化属性读取;`load_tables(root, collect_only)`;`resolve()`(R1 floor);debug override;`set_reload_gate()`;诊断收集器 | 无(Foundation 顶点) | Resource/.tres 加载、autoload 生命周期——LOW |
| **RngService**(autoload,D2) | master_seed、各流 scope 计数器(封闭流:board_gen / reward_roll;增流走 P1 评审) | `set_master_seed()`(唯一调用方 C2);`open_stream(stream)` 有状态门面;`derive_at(stream, scope)` 纯函数;只读计数器 | ConfigDB(无) | 无——纯逻辑 |
| **action_economy**(A3) | AP/RAP 账本、last_round_end、轮次相位机 {Idle, Active, Waiting}、结束仲裁 | 8 API 全布尔面:notify_round_start / request_dig / request_flag_place / request_flag_pull / request_stop / request_refresh / notify_settlement_done / notify_combat_end;ap/rap/phase 只读 | ConfigDB(ActionEconomyTable);B1 回发 next_round_mode/battle_over | 无 |
| **variation 定义**(A4) | VariationTable schema 与 MVP fog 行、F1 候选池门控谓词 | `variant_pool_gate(level_index, board_biome)` | ConfigDB(VariationTable) | 无 |
| **status_container**(B3) | 状态实例容器(战斗域生命周期、跨轮跨图延续) | 5 API:notify_battle_start / apply_effect / query_active / decay_round / notify_battle_end | ConfigDB(StatusEffectTable) | 无(RefCounted) |
| **save_system**(D3,Alpha) | 存档格式与版本比较 | (未设计——契约锚:SCHEMA_VERSION + master_seed + 各流 scope 计数器快照,须在无在飞 open_stream 实例时切出) | ConfigDB、RngService 只读计数器 | FileAccess——LOW |
| **settings/localization**(D6,愿景) | 设置项、翻译数据 | (未设计) | ConfigDB | 无 |
### Core 层
| 模块 | Owns | Exposes | Consumes | 引擎 API |
|---|---|---|---|---|
| **board_generator**(A1) | 生成算法(五阶段管线)、BoardGenTable 回填、八项生成期指标、合法性谓词(clearable / R₀≠S / min_safe)、可推理率度量(metric_version) | `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)`(唯一提交入口);try_dig / try_flag_place / try_flag_pull / try_move(便捷形);`compute_move_path(cell)` 只读;`retire_board()`;三源拒绝(board_face / resource_face / phase)+ sub_reason 封闭枚举 | A1 产物(Board class_name 数据契约);A3 try_spend / last_round_end / 相位 | 无(零表读取、零 UI——切片实证) |
| **unit_container**(B2) | hero/enemy 单位实例(hp/atk/行为环指针)、行值快照 | 9 API:spawn / query_alive / query_beat / query_attack / apply_damage / advance / default_target / ambush_grant_plan / despawn_all | ConfigDB(EnemyTable/HeroTable) | 无 |
| **reward_economy**(B4) | 板级身份映射(install 期预分配、Ready 只读)、关卡域库存(逐件实例)、**RewardSupplyController**(切片新增私有组合件:注入占比 + 指数递减、行值快照、零自有随机) | 10 API:roll_board / query_identity / grant / grant_clear / stock / use / query_inventory / clear_inventory / retire_mapping / equivalence_supply;另 query_full_snapshot(轮内刷新 facts 隔离)、grant_node_active(C1-lite 接口漂移) | ConfigDB(RewardTable/RewardConfigTable);reward_roll 流(scope = 每次 install 批) | 无 |
| **helper_items**(A5,垂直切片) | HelperItemTable、探测显影语义 | (未设计——桥接位:A2 查询接口 + A4 counter_item_ids) | A2 / A4 / B4 | 无 |
### Feature 层
| 模块 | Owns | Exposes | Consumes | 引擎 API |
|---|---|---|---|---|
| **battle_orchestrator**(B1) | 段序骨架(七段结构冻结)、轮 facts 缓冲、可回放步骤流、明细行协议(13 类行 + 字段分层)、条款③⑤闭合对账、**战斗域全部跨系统调用权** | `begin_battle(encounter)`;窗口/刷新意图提交面(扮演 D1);`level_clear()`;步骤流(输出契约) | B2/B3/B4 全调用面(**唯一调用方**);A3 request_refresh 代理 + 回发;A2 install/retire + 三事件订阅;A1 generate(attempt 非 scope 事件);D2 SettlementTable + set_reload_gate | 无(零随机、禁 await——切片 88 冒烟实证可回放) |
| **level_runner**(C1-lite,切片已建) | 关卡域生命周期(节点链推进、共享 B4 + HP 携带、关卡末 level_clear) | 节点推进接口;LevelTable(`level.tres`——节点 enum {battle,reward,rest,boss}、末节点必须 Boss、ConfigDB 跨表校验⑧) | B1 begin_battle、B4 grant_node_active、ConfigDB LevelTable | 无 |
| **run_structure**(C2) | 冒险/关卡序列、失败重开、**master_seed 唯一接线方** | (未设计) | RngService.set_master_seed、C3/D2 | 无 |
| **difficulty**(C3) | DifficultyTable 回填、全部曲线数值调参所有权、战斗期望表(切片 monte_carlo 为工具原型) | 调参输出(经 D2 R1 解析/编排器传递,禁反向调用生成) | ConfigDB、B1 对账输出(调参约束清单)、A1 报告 C | 无 |
| **meta_progression**(C4,Alpha) | MetaTable、代币/天赋 | (未设计) | D3、C2、ConfigDB | 无 |
### Presentation 层
| 模块 | Owns | Exposes | Consumes | 引擎 API |
|---|---|---|---|---|
| **D1 HUD**(切片 lite 已拆 9 单元:BoardView / HUDView / HudPresenter / BattleLogView / ItemWindowOverlay / NodeOverlay / LevelStripView / TunePanel / UiKit + 组合根 main.gd) | 全部 Control/CanvasLayer、输入→意图翻译(**唯一提交路径 = settle_batch,不直调 A3**)、呈现义务台账(A2×6 / B2×4 / B3×4 / B4×5 / B1×3 / A4×2) | 视图单元接口(信号外发、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 图片参数两轮变化) |
| **battle_presentation**(B5,垂直切片后) | 结算动画 / 伤害数字 / 战斗舞台 | (未设计——前置"战斗表现美术测试"锁双舞台陷阱) | B1 步骤流(回放脚本源)、D1 | **MEDIUM**:AnimationPlayer(String→StringName 变更)/ Tween |
| **audio**(D4,Alpha) | 音频挂点 | (挂点 = B1 明细行类型流;负反馈聚合——单结算至多一次) | B1 流水 | AudioStreamPlayer(4.7 area_mask 默认 1→0 注意) |
| **tutorial**(D5,Alpha) | 教学条目 | (口径来源:A2/A3/A4/B3/B1 各教学条目) | 各上游 | 无 |
**依赖单向性**:上层可消费下层,禁止反向(C3 禁调用 A1 生成、D1 不直调 A3、A2/B3/B4 零相互直调)。全项目唯一回边 = A2 事件订阅面。
---
## Data Flow
### 1. 帧更新路径(2D 回合制:无逐帧玩法逻辑)
```
Input(鼠标)→ D1 输入翻译 → 意图对象 → A2.settle_batch(唯一提交入口)
→ A3.try_spend(原子扣减)→ A2 棋盘效果(挖/连锁/旗/移动)→ 三事件外发
→ [棋盘渲染:D1 BoardView 按事件增量重绘;无事件帧 = 静态 + 动效]
→ 轮次结束 → A3 Waiting → B1 结算编排(段序七段)→ 明细步骤流 → D1 结算屏逐行呈现
```
- 回合制下每帧只做:输入采样、呈现刷新、动效推进——**玩法状态只在意图事务内变更**(单意图帧输入收集:stop 点击终结当帧)。
- 无跨线程玩法数据流(Godot 主线程假设,D2 EC13);A1 生成若引入 WorkerThread 须走 ADR-0005 裁决(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 / stock / advance...──▶ B3/B2/B4(唯一调用方)
B1 ──install_board / retire_board──▶ A2 B1 ──generate(L,D)──▶ A1
D1 ◀──呈现数据源:A2 事件流 / B1 步骤流 / A3 ap-rap / ConfigDB display_name
```
- **载体裁决待 ADR-0001**:切片事实 = 组合根直连信号接线 + B1 Waiting 相位触发(不依赖事件到达序);推荐沿用(单线程回合制,KISS),autoload 全局事件总线为否决倾向。
- 事件规范序:A2 发射序 = 触发格 BFS、8 邻行主序;事件序契约 `flag_judged` < `round_end` 全路径统一。
### 3. 存档/读档路径(MVP 无存档;契约已锁)
- MVP 无元进度持久化(C4/D3 归 Alpha)。**已锁契约**:续玩/复盘快照 = master_seed + 各流 scope 计数器 + 意图序列 + 窗口选择序列;快照切出须发生在无在飞 `open_stream` 实例时(scope 事件边界外——B1 编排保证:切点 = board install 边界)。
- 可回放性已实证:切片冒烟同种子双跑步骤流逐行相同(B1 AC-33 前身)。
- D3 Alpha 期按此契约设计格式;SCHEMA_VERSION 高版本拒读。
### 4. 初始化顺序
```
进程启动
→ autoload 实例化:ConfigDB → RngService(顺序固定;战斗编排器为普通类、由组合根按局实例化——切片形态)
→ 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)
→ 关卡末:level_clear()(clear_inventory 恰一次 + 快照计数)
```
---
## API Boundaries
> 完整 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;调用序钉死(query_attack→apply_damage→advance;先兑付后衰减) | 禁第二调用方(静态扫描域: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 参数) | 编排不把重试当取号 | 八项指标输出(含 fog_burden_ratio) |
| B4 → B3 | buff 类经 B1 调 apply_effect(B4 零跨系统读、零直接接口) | 满层拒绝 = 零兑付 + 明细行(无折算) | 授予时数值快照(抗热重载) |
| B1 → D1 | 步骤流行协议(13 类封闭枚举 + 公共字段 type/source_class/origin_cell/round_index/display_name/value/highlight? + 特有字段 target/effect_id/pool_value) | 无来源行 = 断言失败;呈现侧禁按行序重演 B2 状态机 | 可回放步骤流(同种子逐行相同) |
**引擎类型核验注记**:接口使用的引擎类型 = Resource / .tres(D2 全表)、RefCounted(容器类)、Signal/Callable(事件载体,ADR-0001)、Control/CanvasLayer/Drawing(D1)、SceneTree headless 协议(测试)——均属 4.x 基线稳定面;4.7 Control 域增量(offset_transform_* 等)已在 breaking-changes.md 登记,D1 采纳前对照核实。
---
## ADR Audit
**现存 ADR:0 份**(`docs/architecture/` 本文档为首个产物;此前架构约束由 GDD 门禁评审 + CLAUDE.md + code-conventions 事实承载)。
### 已锁决策盘点(GDD 层已定稿,不重复立项 ADR)
| 决策 | 锁定来源 |
|---|---|
| GDScript 单语言;autoload = ConfigDB + RngService(定名勿改) | technical-preferences + D2 GDD |
| 全部玩法数值 .tres 单一事实源;零字面量;R1 floor 解析;fail-fast 双通道 | D2 Core Rules 1–8 |
| RNG 封闭流 + scope 派生(R2 黄金向量);可回放 = 硬承诺 | D2 R2 + B1 Core Rule 15 |
| A2 纯规则引擎(零随机/零表读取/零 UI)+ 三事件面封闭 | A2 Core Rule 1/2 |
| B1 编排唯一性 + 七段段序骨架 + 明细行协议 | B1 Core Rule 1/4/14 |
| 多敌 side-wide / 行为环确定性 / 固定顺位 / 伏击 cap=4 | B2(2026-09-09 用户拍板) |
| 奖励五值两类交付轴 / install 预分配 / 关卡域库存 / 窗口单件制 | B4(2026-09-11 用户裁决批) |
| weake­n 锚 F0 瞬时当量 / 条款①③⑤闭合对账 owner = B1 | B1 F0–F5 |
| 领域命名禁 ID 前缀 / 组合根模式 / 呈现层契约成文 | CLAUDE.md + docs/code-conventions.md(切片教训批) |
### GDD 登记的"实现期 ADR 裁决项"汇总(= Required ADRs 的来源)
A2 OQ2(事件外发载体)· B1 OQ1(事件总线载体,与 A2 OQ2 同一裁决)· A1 OQ2/OQ3(生成性能姿态 + 度量独立入口)· B2 OQ1(query_attack/ambush_grant_plan 两 face 归属)· B2 OQ5(HeroTable 单行校验落点)· B2 OQ9(零伤害死局跨字段护栏落点)· D2 OQ1(gdUnit4 取舍)· technical-preferences(渲染器选择)· 切片新增正式化批(轮内刷新方案 A / RewardSupplyController / LevelTable / grant_node_active / clear_blast——GDD+registry 修订义务在切片 README)。
### Traceability Coverage Check
Technical Requirements Baseline 63 条 → ADR 覆盖 0 条(无 ADR 存在);按覆盖载体分层:
| 覆盖载体 | TR 数 | 说明 |
|---|---|---|
| ✅ 本架构文档(分层/所有权/数据流/API 边界)+ GDD 契约 | 46 | 数据/RNG/核心行为/编排协议类——已锁且切片实证,无需 ADR |
| 🔶 待 ADR 裁决 | 12 | 引擎/测试/实现形态类:TR-gc-008(渲染器)、TR-a1-011/012(生成姿态)、TR-d2-014/016(测试载体)、TR-a3-004+TR-b1-001/002(事件载体)、TR-b2-005/006(face 归属)、TR-d2-010+TR-gc-002(D3 契约正式化) |
| ⏳ 未设计系统预留 | 5 | A5/C1–C4/D3 关联 TR(随各系统 GDD 立项) |
**结论:0 条孤儿需求**——46 条由本文档+GDD 承载、12 条待 ADR(见下)、5 条随未设计系统。**2026-09-12 更新:ADR-0001~0004(Foundation 四项)已落定 → 正式工程骨架解冻**;ADR-0005~0008 随对应系统开工前裁决(切片代码可作为参考实现,生产化迁移待 ADR-0008 正式化批)。
---
## Required ADRs
### 必须在正式编码开始前(Foundation 裁决)——✅ 已全部落定(2026-09-12,solo 授权代决,godot-specialist 校验通过)
1. **✅ ADR-0001 `event-bus-and-orchestration-carrier`**(`adr-0001-event-bus-and-orchestration-carrier.md`):组合根直连 signal 接线 + B1 Waiting 相位触发;autoload 全局事件总线否决。specialist 增补两条静态规则(方法 Callable only / 发射者禁反向引用)。
2. **✅ ADR-0002 `renderer-and-window-config`**(`adr-0002-renderer-and-window-config.md`):gl_compatibility(绕开 D3D12 新驱动线);基座 1280×800 + canvas_items + expand 显式落盘。
3. **✅ ADR-0003 `scene-structure-and-board-rendering`**(`adr-0003-scene-structure-and-board-rendering.md`):autoload 仅 {ConfigDB, RngService};core RefCounted / presentation 九单元组合根;**棋盘渲染 MVP 沿用切片逐格控件形态**(specialist 纠正:切片并非自绘 _draw——迁移登记为 D1 候选工作项含探针改造);CJK 字体随包为硬性前置。
4. **✅ ADR-0004 `test-carrier-and-ci`**(`adr-0004-test-carrier-and-ci.md`):双载体 + 静态扫描域 S1–S8(specialist 增补 S2 全局 rand* 禁令 / S5 core 禁裸引用 autoload 标识符)+ CI 外部超时;gdUnit4 deferred(D2 OQ1 关闭形态)。
实现级立场已登记 `docs/registry/architecture.yaml`。
### 相关系统开工前应有
5. `/architecture-decision "board-generation-performance"` → ADR-0006:A1 生成性能与异步化(F2c 常数 C 定稿;切片证据 = 10×10/12×12 同步生成可接受——推荐 MVP 同步+加载幕,WorkerThread 留扩展);度量独立入口确认(切片已实现三入口)。
6. `/architecture-decision "unit-api-face-ownership"` → ADR-0007:B2/B1 两 face 归属(query_attack / ambush_grant_plan)+ HeroTable 单行校验落点。
7. `/architecture-decision "zero-damage-guard-locus"` → ADR-0008:零伤害死局跨字段/跨表护栏落点(推荐落 D2 跨表校验——切片 LevelTable 校验⑧先例)。
8. `/architecture-decision "slice-mechanism-formalization"` → ADR-0009:切片新增机制正式化批(轮内刷新方案 A / RewardSupplyController / LevelTable / grant_node_active / clear_blast)——GDD+registry 接口漂移修订的 ADR 化登记。
### 已落定(2026-09-12 追加)
0. **✅ ADR-0005 `save-contract-and-schema-versioning`**(`adr-0005-save-contract-and-schema-versioning.md`):Foundation 层收口——SCHEMA_VERSION 比较归属 + RNG 快照切点契约 ADR 化(TR-d2-010 / TR-gc-002),Foundation 零缺口闭合。
### 可推迟
- ADR-0010 A1 EC5 运行期熔断(连续降级确定性回退已知好种子)
- ADR-0011 B5 战斗舞台(棋盘上 vs 独立场景)——"战斗表现美术测试"后裁决
- ADR-0012 A5 探测显影接口
- ADR-0013 D3 存档格式(RNG 快照契约已由 ADR-0005 锁定,格式归 Alpha)
- C2/C3/C4 结构性决策随各系统 GDD 立项
---
## Architecture Principles
1. **Core 纯逻辑、headless 完整可跑**——Core/Feature 玩法逻辑零 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 探针测试为标配(切片缺陷 ①②④⑤ 教训沉淀)。
---
## Open Questions
| ID | Summary | Priority | Resolution Path |
|----|---------|----------|-----------------|
| QQ-01 | 渲染器选择(Forward+ vs gl_compatibility)与项目窗口基线 | High | ADR-0002(正式骨架前) |
| QQ-02 | 事件总线载体与 A2 事件捕获测试 API | High | ADR-0001(正式骨架前) |
| QQ-03 | gdUnit4 是否引入并迁移冒烟用例 | Medium | ADR-0004(可推迟到正式 CI 期;D2 OQ1) |
| QQ-04 | 轮内刷新数值连锁(清图支配性条款⑤ / 真人刷图行为获取期望)重算 | Medium | playtest 实测 + ADR-0008 正式化批 |
| 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 前) | 战斗表现美术测试 → ADR-0010 |
| QQ-09 | C3 消费 B1 对账输出的事实依赖回写 systems-index | Low | C3 GDD 定稿时 |
| QQ-10 | `.claude/docs/director-gates.md` 缺失(TD-ARCHITECTURE/LP-FEASIBILITY 判据无载体) | Low | 补建 gate 定义文件或维持 solo/lean 模式约定 |
@@ -0,0 +1,132 @@
# 代码架构审查报告 — 代码组织与封装
> 日期:2026-09-13
> 载体:`prototypes/dungeon-sweeper-vertical-slice/`(9707 行 GDScript:core 12 文件 / data 11 / presentation 28 / smoke 10)
> 基线:`docs/architecture/architecture.md` v1.0 + ADR-0001~0005 + `docs/code-conventions.md`
> 触发:用户在 code-review 之后要求补充「代码组织问题 + 封装问题」专项审查
> 审查方式:core/presentation 关键文件全读 + S1–S8 静态规则逐条 grep 验证 + 跨层引用面扫描
>
> **Verdict: CONCERNS** — 分层纪律实测扎实(S1–S7 零违例、仅 2 处已登记例外),但封装收口存在
> 一条系统性欠账:核心模块内部状态以公有字段暴露,呈现层已形成链式穿透的既成事实。
> 原型期无害;是 ADR-0009「切片机制正式化批」应收口的主题。
---
## 1. 正面观察(实测合规项)
| 规则 | 结论 | 证据 |
|---|---|---|
| S1/S2 零随机 | ✅ | core 内唯一 `RandomNumberGenerator.new` 在 rng_service.gd:76(所有者本体);`stream.randf()`(reward_supply_controller.gd:32)取号经 B4 注入封闭流 |
| S3 零表加载 | ✅ | core 内唯一 `load()` 在 config_db.gd:81(单点本体) |
| S4 core 零 UI | ✅ | core/ 无 Control/Node2D/.tscn 引用(grep 命中均为 `RewardSupplyController` 类名误报与注释) |
| S5 零裸引用 autoload | ✅ | core/ 内 ConfigDB/RngService 命中均为日志前缀字符串 |
| S6 core↔core 方法 Callable | ✅ | level_runner.gd:130-134 全部方法转发;lambda 仅用于 sort_custom(不捕获 self) |
| S7 编排唯一性 | ✅ | B2/B3/B4 调用面 core 内收口于 battle_orchestrator.gd;仅 level_runner.gd:112(grant_node_active,已登记接口漂移)与 :168(in_stock_count 只读)两处例外 |
| 呈现层零核心引用 | ✅ | 28 个视图/装配器文件中仅 main.gd(组合根)与 hud_presenter.gd(授权翻译点)触 core |
| 封装典范 | — | status_container / reward_supply_controller / b4.query_inventory():私有状态 + 投影查询 + 授予时快照;battle_orchestrator.diagnostic_snapshot()(:660)为「成文只读出口」正确先例 |
---
## 2. 封装问题(按根因 → 表征排序)
### E1(根因)编排器协作对象全公开,呈现层链式穿透已成既成事实 — P1
- **位置**:core/battle_orchestrator.gd:20-27(`var a1/a2/a3/b2/b3/b4` 全公有)
- **表征**:`b1.a2.board`、`b1.b2.hero.hp`、`b1.a3.phase` 式层层下钻——main.gd 18 处、hud_presenter.gd 15 处。
- **影响**:组合根与 presenter 是授权翻译点,但访问形态是「恰好字段公开」而非「B1 提供成文读取面」。
S7 只能做文件级扫描(防另写调用方),防不了呈现层意外调用写 API,也防不了读取路径随重构漂移。
- **建议**:B1 补聚合呈现快照/查询面(`hud_state()` 一类,先例 = `diagnostic_snapshot()`);
a2–b4 下划线化后经命名代理暴露只读操作。
### E2(表征)视图绕过 A2 查询面直读原始状态字典 — P1
- **位置**:core/minesweeper_rules.gd:18-20(`board/revealed/flags` 公开可变);
presentation/views/board_view.gd:278、:303 直接 `_a2.revealed.get(c, {})`
- **矛盾点**:board_view.gd:7 头注自称「只读 A2 查询面」——直读 `.revealed` 恰是绕过查询面。
B1 自身亦直读(battle_orchestrator.gd:565-569 `a2.board.width/height`)。
- **建议**:`revealed/flags` 私有化;补 `reveal_record(c) -> Dictionary`、`board_dimensions()` 查询面。
调用点仅 B1 + board_view + main 三处,成本很低。
### E3(表征)B2 裸字典句柄跨模块传递,API 缺「含死亡残位」查询面 — P2
- **位置**:core/unit_container.gd:13-14(`hero/enemies` 公开;句柄 = Dictionary 本体,任何持有者可
`u.hp = 999` 绕过 apply_damage)
- **现症**:hud_presenter.gd:78-79 为渲染死亡残位直读 `b1.b2.enemies` 原始数组——
B2 的 `query_alive` 不含死亡单位,API 缺口迫使呈现层越界(B2 头注已登记此痛点)。
- **建议**:短期补 `query_all_units()` 投影面把 presenter 需求收进 API;
正式化(ADR-0007 两 face 归属裁决时)再决定是否升级 Unit 类型。
### E4 `db.hero` 表值运行时改写——测试覆盖通道用共享可变单例传参 — P2
- **位置**:presentation/main.gd:327-329、core/level_runner.gd:60-61,75-76 直接写 `db.hero.atk/max_hp`;
B2.spawn 经读表间接获得加成值
- **前科**:双写叠加 6→18→54 教训、双基线同步义务(main.gd:187-189 注释)——纪律已成文但机制脆弱。
- **建议**:切片保留;将「运行时表可变」登记进 ADR-0009 候选;正式化改参数传递(`spawn(atk_override=...)`)。
### E5 「只读」字段仅靠纪律,无机制约束 — P2
- **位置**:core/action_economy.gd:17-20(`phase/ap/rap/last_round_end` 架构文档定义为只读,实际公开可变);
core/rng_service.gd:19(`master_seed` 可绕过 set_master_seed 的计数器全零断言)
- **现状**:当前调用方全部合规(A2 经 try_spend/request_dig,B1 经 notify_*,呈现层只读)。
- **建议**:下划线化 + 查询方法(`phase()/ap()/rap()`),趁调用方少时收口,成本极低。
### E6 小项 — P3
| 项 | 位置 | 说明 |
|---|---|---|
| 返回类型多态 | core/reward_economy.gd(grant/stock/use 失败返 `false`,query_* 返 `null`) | B1 消费处被迫 `if not (snap is Dictionary)`;统一 `null` 更符合 GDScript 惯例 |
| 泄漏原始表行 | core/reward_economy.gd:256-265 `equivalence_supply` 返回 `db.reward.rows` 行引用(可变) | 工具观测面,建议 `duplicate()` |
| BoardData 全公开 | core/board_data.gd:8-18「生成后不可变」仅靠注释;视图持板即可读全部雷位(当前未作弊) | 正式化时 duplicate 冻结或下划线化 + 访问器 |
| 成员声明位置 | core/action_economy.gd:121 `var _next_round_mode` 声明在中部、使用在前 | 集中到顶部 |
---
## 3. 代码组织问题
### O1 main.gd 回涨至 667 行,再越 ~400 行审视线(规范 1.1)— P1
- **位置**:presentation/main.gd(667 行);ui_assembler.gd:3 自记「回涨 761 行触发审视线——拆出」历史
- **增长主因**:调试模式(`_start_single/_start_debug_levels/_start_battle/_on_battle_finished` 的
`_level_mode` 分支约 100+ 行)糊在组合根。
- **建议**:照 tune_sim_controller.gd 先例把调试模式抽成独立控制器,组合根回到纯接线。
### O2 调试模式与 LevelRunner 平行实现,语义漂移风险 — P1
- **位置**:「库存跨战斗延续 + HP 携带 + 层级推进」存在两份实现——core/level_runner.gd(正式)与
main.gd 调试分支(历史入口);`level_clear()` 调用时点已各有细节(main.gd:367,376 vs level_runner.gd:167)。
- **建议**:调试两层模式直接复用 LevelRunner(其设计目标即此),或抽 `DebugBattleSession`。
### O3 B1 体量与纯函数沉淀 — P2
- **位置**:core/battle_orchestrator.gd 718 行(审视线超 300+);
伤害公式族 `_resolve_damage/_charge_damage_component/_armor_effectiveness/_clamped_pool`
(约 80 行)为零状态纯算术。
- **建议**:按规范 1.2 抽 `DamageMath` 静态宿主类;段序骨架不动、可回放承诺无风险。
- **顺带**:core/board_generator.gd:50-55 对同一张合法板调用两次 `measure_inferability`
(全库最贵求解器)——合并为一次。
### O4 呈现层反向依赖 smoke 工具域 — P2
- **位置**:presentation/tune_sim_controller.gd:23 `load("res://smoke/level_autoplay.gd")`——
UI 控制器依赖测试工具目录。
- **建议**:「关卡自动模拟循环」上移为共享组件(core 或 lib),smoke 与 tune_sim 共同消费。
- **顺带**:main.gd:106,188 与 tune_sim_controller.gd:23 用运行时字符串 `load()`,
与 main.gd:16-19 的 `preload` 常量风格混用——统一 `preload`(编译期路径校验)。
### O5 头注溯源缺失(规范 1.4)— P3
core/ 12 文件中 4 个缺标准 `# 实现 GDD:...` 行:
`board_data.gd`(有 A1 描述但非标准格式)、`config_db.gd`、`rng_service.gd`、`reward_supply_controller.gd`。
---
## 4. 建议行动顺序
1. **P1 三连(合计约 2 天)**:
E2(A2 状态私有化 + 查询面)→ E1(B1 呈现快照面)→ O1+O2(调试模式抽离/复用 runner)。
完成后 board_view / hud_presenter / main 与 core 的接触面全部变为命名 API,封装收口完成。
2. **P2 项并入 ADR-0009「切片机制正式化批」裁决**:E4 表值改写参数化、E3 单位句柄形态、
O3 DamageMath 拆分、O4 模拟循环上移。
3. **P3 顺手清**(头注补齐、返回值统一、声明位置、preload 统一)。
> 复审触发:P1 三连落地后重跑本审查核对接触面收口;ADR-0009 落定后正式工程骨架迁移前复核 E3/E4 裁决结果。
@@ -0,0 +1,60 @@
# Requirements Traceability Matrix — Dungeon Sweeper
> 生成:2026-09-12 · 源:`docs/architecture/architecture.md` §Technical Requirements Baseline(63 条)+ ADR-0001~0005
> 门检查口径:**Foundation 层零缺口** = 每条 Foundation TR 都有明确裁决载体(专项 ADR,或经 design-review 门禁的 Approved GDD 契约 + 本架构文档章节),无未决项。
> 状态图例:✅ 已覆盖 · 🔶 待 ADR(非 Foundation,随对应系统开工前裁决)· ⏳ 随未设计系统
## 覆盖总览
| 层 | TR 数 | 专项 ADR 覆盖 | GDD 契约 + 架构文档覆盖 | 待裁决 |
|---|---|---|---|---|
| Foundation | 36 | ADR-0001(a3-004)· ADR-0004(d2-014/016)· ADR-0005(d2-010/gc-002) | 32 条(D2/A3/A4/B3 GDD 均 Approved + 架构文档所有权/API 节) | **0** ✅ |
| Core | 21 | ADR-0001(b1-001/002)· ADR-0002(—) | 19 条 | 2(a1-011/012 → ADR-0006) |
| Feature | 2 | — | b1 对账协议等 | 0(b1-010 文档承载) |
| Presentation / Platform | 4 | ADR-0002(gc-008) | gc-006/007 文档 | 2(gc-004/005 随 D1/B5) |
## Foundation 层逐条(36 条——零缺口核验)
| TR | 需求 | 裁决载体 |
|---|---|---|
| d2-001~003 | 单一事实源 / ConfigDB 单点 / schema 先行 10 表 | D2 GDD(Approved)+ architecture.md §Module Ownership |
| d2-004 | 进度键 + R1 floor 解析 | D2 GDD R1 + architecture.md §API Boundaries |
| d2-005/006 | RngService 封闭流 / R2 派生与黄金向量 | D2 GDD R2 + architecture.md 原则 3 |
| d2-007 | 校验双通道 + 夹具注入 | D2 GDD + ADR-0004(载体) |
| d2-008 | 加载期/运行期致命 | D2 GDD Rule 6 |
| d2-009 | D2 零 UI 依赖 | D2 GDD Rule 7 + ADR-0003(core 隔离)+ architecture.md 原则 1 |
| **d2-010** | SCHEMA_VERSION 版本化 | **ADR-0005** |
| d2-011 | debug override 链 | D2 GDD R3 |
| d2-012 | 热重载状态机 + reload gate | D2 GDD + B1 GDD(唯一调用方) |
| d2-013 | 诊断收集器 | D2 GDD 校验双通道节 |
| **d2-014** | 冒烟框架协议 | **ADR-0004** |
| **d2-015** | RNG 快照 = seed + 计数器 | **ADR-0005** |
| **d2-016** | 项目级静态扫描域 | **ADR-0004**(S1–S8) |
| a3-001~003/005~008 | AP/RAP 账本、仲裁、相位机、refresh、表承载、last_round_end | A3 GDD(Approved)+ architecture.md |
| **a3-004** | round_end 双发射源 | **ADR-0001**(round_end_board / round_end_stopped) |
| a4-001/002 | 变异框架 + 雾行跨字段校验 | A4 GDD(Approved) |
| a4-003/004 | 生成期布置执行归 A1 / 零特判 | A4 GDD + A1/A2 GDD |
| b3-001~006 | 统一容器 / 时限量纲 / 五 API / 三分支 / 快照 / 不 clamp | B3 GDD(Approved) |
## Core / Feature / Presentation 层(27 条)
| TR | 需求 | 载体 | 状态 |
|---|---|---|---|
| a1-001~010, a2-001~010, b2-001~004/006, b4-001~009, b1-003~009/011 | 各系统行为契约(详见 architecture.md §TR Baseline) | 各 GDD(Approved)+ architecture.md §Module Ownership / §API Boundaries;事件类(a2-002/003、b1-001/002)由 **ADR-0001** 承载 | ✅ |
| **a1-011** | 度量独立入口三函数 | 🔶 待 **ADR-0006**(生成性能与异步化——A1 OQ2/OQ3) | 🔶 |
| **a1-012** | F2c 成本闸 / 生成性能姿态 | 🔶 待 **ADR-0006**(Core 层,A1 开工前裁决;切片证据已背书同步方案) | 🔶 |
| **b2-005**(注:face 归属实为 b2 OQ1 项) | query_attack/ambush_grant_plan 两 face | 🔶 待 **ADR-0007**(单位 API face 归属——B2 OQ1/OQ5) | 🔶 |
| **gc-004** | 双舞台资产管线 | ⏳ B5 前美术测试 → ADR-0011 | ⏳ |
| **gc-005** | 视觉锚三硬约束 | 🔶 D1 GDD(未写——MVP 层最后一块;切片教训四条为其硬输入) | 🔶 |
| gc-006/007 | 性能预算 / 平台输入 | technical-preferences + ADR-0002(窗口基座) | ✅ |
| **gc-008** | 渲染器选择 | **ADR-0002** | ✅ |
## 待裁决 ADR 队列(全部非 Foundation)
| ADR | 议题 | 触发时机 |
|---|---|---|
| ADR-0006 | 生成性能与异步化(A1 OQ2/OQ3 + 度量独立入口确认) | A1 生产实现前 |
| ADR-0007 | B2/B1 两 face 归属 + HeroTable 单行校验落点 | B2 生产实现前 |
| ADR-0008 | 零伤害死局跨字段护栏落点 | D2 生产化前 |
| ADR-0009 | 切片机制正式化(轮内刷新 / RewardSupplyController / LevelTable / grant_node_active / clear_blast) | 正式化批 |
| ADR-0010~0013 | A1 熔断 / B5 舞台 / A5 显影 / D3 存档格式(契约已由 ADR-0005 锁定) | 各系统 GDD 立项时 |
+155
View File
@@ -0,0 +1,155 @@
# 代码规范(Dungeon Sweeper)
> 生效:2026-09-11 · 来源:用户在垂直切片评审中逐一指出的真实陋习与缺陷,全部成文。
> 每条规则附本项目真实反面案例(标注缺陷编号/日期)——规则不是抽象美德,是踩过的坑。
> 约束范围:`prototypes/` 与正式 `production` 代码同尺度;与 CLAUDE.md「Conventions」节既有硬约束
> (数值表单点 / RNG 封闭流 / Core 零 UI / fail-fast / spec-AC 一致性)并行生效,冲突以用户裁决为准。
**写任何代码前必须通读本文件。**
---
## 1. 结构纪律——高内聚、低耦合
### 1.1 禁止上帝对象
一个类只承载一个职责。场景主脚本(main)= **组合根**:模式流转、信号接线、核心写调用的唯一出口;
渲染、文案拼装、状态装配一律拆分为独立视图/装配器类。单文件超过 ~400 行即触发审视。
> **反面案例(2026-09-11,用户:"一个工程师看了想吐")**:main.gd 随功能追加长到 ~1100 行——棋盘渲染、
> HUD、结算日志格式化、四种模态覆盖层、调整板、蒙特卡洛模拟器、关卡流程全部糊在一个类里。
> 已拆分为 9 个单一职责单元(views/ + hud_presenter),main 降到 433 行组合根。
### 1.2 一切功能以类封装,禁止裸函数堆
设计稿与实现同尺度:功能 = 类(状态 + 行为 + 信号),类是封装的最小交付单位。
工具性纯函数只允许挂在明确的宿主类下(静态装配器/工厂),不允许无主散落。
> **反面案例(2026-09-11,用户:"我看你都是函数的方式……没有对象封装吧")**:供给控制器的伪代码
> 以裸函数呈现被否;正式实现按"B4 私有组合件 RewardSupplyController"封装。
### 1.3 依赖单向,核心写调用收口
依赖方向唯一:`views →(信号)→ 组合根 →(写调用)→ core`。
视图零核心写调用(纯 setter / 信号外发优先);"读核心状态 → 拼展示文案"集中于装配器(presenter);
核心写接口(settle_batch / submit_window_selection / runner 推进)只允许在组合根出现。
### 1.4 命名 = 领域命名,禁止系统 ID 前缀
文件名与类名禁止 `a1_`/`b1_`/`c1_` 等系统 ID 前缀(`a1_board_generator.gd` → `board_generator.gd`)。
设计追溯不靠前缀:每个核心实现文件头注必须带一行
`# 实现 GDD:design/gdd/<id>-<slug>.md(系统 ID Xn)`;系统 ID 只作为文档与 registry 的追溯锚。
豁免:D2 schema 类与 autoload(本就领域命名);文档/夹具登记名(如 b4_golden)属文档层。
> **反面案例(2026-09-11,用户:"是没有代码规范吗")**:ID 前缀是跟随 GDD 文档名的事实约定,
> 从未成文;同目录 `config_db`/`rng_service` 无前缀与 A/B/C 系列并存——两套命名即规范缺失的铁证。
### 1.5 禁止事实约定
任何"大家默认这么做"的惯例必须成文进本文件(或 CLAUDE.md)才算存在。
写代码时发现未成文但必须遵守的约定 → 当场补条文,不许靠惯性延续。
---
## 2. 契约纪律——跨层/跨类调用的语义
### 2.1 信号与事件契约成文
每个跨类信号:参数语义、发送时点、消费方依赖,必须在发送方头注成文(参照 A2 三事件面先例)。
状态机的每次迁移路径都必须发出对应事件——**缺一条路径的事件 = 消费方永久等待 = 软锁**。
> **反面案例(playtest 缺陷②)**:A2 旗动作花完末点 AP 后相位翻 Waiting 但不发 round_end,
> B1 结算点依赖该事件 → 整局软锁。v1 冒烟没抓到是因为自动玩家不用旗——路径覆盖不全的代价。
### 2.2 跨层标识符语义单一且成文
位置(index)/ 句柄(handle)/ 键(key)是三种不同的东西。跨类传递标识符时,
传递方的语义必须与接收方契约逐字一致,禁止凭"当前恰好相等"传值。
> **反面案例(playtest 缺陷④)**:窗口选择契约 = 窗口条目位置,UI 却传库存数组句柄——
> 未消耗时二者巧合相等;消耗一件后错位 → 选中件不消耗、邻件被误耗。
### 2.3 模态覆盖层层级规则
覆盖层遮挡关系由场景树加入顺序决定。打开任何模态覆盖层时,必须显式隐藏会遮挡它的全屏层;
新增覆盖层必须登记其在 z 序中的位置,并提供"打开可见性"的场景断言。
> **反面案例(playtest 缺陷⑤)**:数值调整板已实现,但打开时被不透明的开始覆盖层完全遮住
> = "点击无反应"。功能存在 ≠ 功能可达。
### 2.4 状态字段语义显式
跨战斗/跨场景携带或恢复的状态字段,其语义来源必须显式(表值 / 明确入参),禁止用入参隐式定义。
> **反面案例**:B2 spawn 把 hero 的 max_hp 设为入参 hero_hp——跨战斗携带 HP 时上限被压扁,
> 恢复点/治疗包的满血守卫全部失效。
---
## 3. 测试纪律——"存在"必须证明"可达且正确"
### 3.1 场景级探针标配
每新增一个可交互 UI 区域(视图/覆盖层/面板),必须配套场景级 headless 探针:
真实实例化场景 → 驱动真实输入路径 → 断言可见性与状态。**只有 core 层 AC 通过不算有测试**
(GDScript 编译不查字典字段与时序,呈现层错误只在运行时暴露)。
### 3.2 覆盖层/面板必测"打开后可见"
凡模态覆盖层,探针必须断言:打开后自身 visible 且遮挡物已隐藏(缺陷⑤回归断言)。
### 3.3 缺陷修复必须沉淀回归断言
每个缺陷修复必须在探针或冒烟中留下能抓住该缺陷的断言(旗动作耗尽 AP → 必须进入第 2 轮;
选用道具 → 库存态必须变 Used)。没有回归断言的修复视为未完成。
### 3.4 提交前全量验证
交付前必须全绿:`smoke_all.gd` + 全部场景探针(ui_probe / ui_click_probe / ui_tune_probe)。
行为探针使用随机化玩家行为(旗/停手/刷新/无效点击)——自动玩家不做的动作就是测试盲区。
---
## 4. 语言纪律——GDScript 4.x 实战坑(本项目踩实)
1. **多行 lambda 内禁止嵌套 match / 复杂控制流**(解析不可靠,报"Expected expression for match
pattern")——信号处理体一律抽成命名方法 + `bind` 传状态。
2. **Dictionary 取值返回 Variant,无类型推断**——参与算术或传参前显式声明类型(`var x: float = ...`)。
3. **RichTextLabel:`append_text()` 不回写 `text` 属性**——读可见文本用 `get_parsed_text()`。
4. **lambda 捕获循环变量按创建时值**——循环内先落地局部变量再捕获,或用 `bind`。
5. **重命名脚本必须同步 `.uid` 文件**(资源身份稳定);新增 `class_name` 后必须跑一次编辑器扫描
刷新全局类缓存,否则 `--headless --script` 模式解析失败。
6. **`print` 格式占位符与实参类型必须匹配**(`%d` 配 String = 静默输出字面量)——工具输出错
等于没有输出。
---
## 5. 数值与汇报纪律
### 5.1 数值口径必须显式标注尺度
任何期望值/均值汇报必须写明口径:**每格 / 每板 / 每战 / 每关**。混用口径 = 误导
("可选类 3.32"不加"每板",会被读成每格期望 >1)。
### 5.2 调参先测量,改后复测
改任何玩法数值前,先用扫描工具产出基线(`level_monte_carlo.gd` / `reward_expectation.gd`);
改完必须复测回填数据。禁止拍脑袋调参。
### 5.3 数值设计必须跨尺度推演
在单一尺度校准的数值,必须推演其在更大尺度的复合结果(每战合理 × 关内囤积 = 关卡灾难)。
> **反面案例(2026-09-11)**:可选类 25% 格子配比在单战斗尺度校准(击杀需求 18/54),
> ×"库存关内延续"× 5 张板复合后 = 每关 24.8 件、刀总伤 180 > Boss 130 HP——预警⑥在关卡尺度坐实。
### 5.4 用户拍板的实现零发挥
拍板范围外的细节一律不自行补全——以"待拍板问题"清单列出等裁决。
(反面案例:清图奖励被自行设计成入库刀,用户纠正为"一次性高额伤害不入库"。)
---
## 6. 流程纪律
1. **大改动三段走**:设计稿/伪代码 → 用户审阅 → 实现 → 修改记录(README + session-state)。实现不得先于审阅。
2. **实现批收尾双登记**:切片 README 修改记录 + `production/session-state/active.md` 条目,缺一不可。
3. **规范变更必须成文进本文件**——发现未成文约定、或用户裁决产生新规则,当场补条文。
4. **呈现层缺陷的教训回写 D1 GDD 设计输入**(信号载荷 schema / 场景级测试 / 时点状态可见性)。
---
## 附:缺陷-规范对照表(本项目真实案例,2026-09-11)
| 缺陷 | 现象 | 根因 | 对应规则 |
|---|---|---|---|
| ① UI 抖动/"第3轮"消失 | 悬停文案换行推挤侧栏,末行被挤出视口 | 动态内容参与布局回流 | 1.1 拆分 + 视图定长槽(HUDView) |
| ② Boss 战 AP 用完不结算(软锁) | 插旗耗尽末点 AP 后整局冻结 | 旗动作路径缺轮末事件 | 2.1 事件发射完整性 |
| ④ 道具使用后不消失 | 选用件留存、邻件被误耗 | 窗口位置 vs 库存句柄错位 | 2.2 标识符语义单一 |
| ⑤ 调整板点击无反应 | 面板已实现但被开始层遮挡 | 模态打开未隐藏遮挡物 | 2.3 层级规则 + 3.2 |
| 上帝对象 | main.gd ~1100 行 | 职责无边界持续堆积 | 1.1–1.3 |
| ID 前缀命名 | a1_/b1_ 与领域命名并存 | 事实约定未成文 | 1.4–1.5 |
| 可选类每关 24.8 件 | 速杀退化、囤刀秒 Boss | 单尺度校准未做跨尺度推演 | 5.3 |
+38
View File
@@ -0,0 +1,38 @@
# Consistency Failure Log
<!-- Auto-maintained by /consistency-check. Do not edit manually. -->
<!-- One entry per detected conflict, in chronological order. -->
| Date | GDD A | GDD B | Conflict Type | Status |
|------|-------|-------|---------------|--------|
| 2026-09-09 | b4-reward-item-economy | registry (rng_service) | 🔴 错引条目名 + 过期语义 | RESOLVED 同日 |
| 2026-09-09 | b4-reward-item-economy | registry (status_effect.b1_obligations) | 🔴 义务编号错引 | RESOLVED 同日 |
| 2026-09-12 | registry (reward_table/reward_config) | b4-reward-item-economy / d2-data-config | 🔴 09-11 批 fields 行漏网 ×2 | RESOLVED 同日 |
### 2026-09-09 — /consistency-check — 🔴 CONFLICT
**Domain**: 奖励经济 × 数据配置(RNG 流语义)
**Documents involved**: b4-reward-item-economy.md(Overview/Rule 2/Dependencies 三处)vs registry entities.yaml(rng_service.scope_event_binding)
**What happened**: B4 三处引用 "`board_gen.scope_event_binding`…每次奖励结算"——条目名错引(该属性属 rng_service)且为 Phase 5b 改写前旧语义;定稿批回写 registry 后 GDD 正文未同步。
**Resolution**: B4 三处改引 `rng_service.scope_event_binding` + 新语义(每次 board install 批)+ 回写义务标已兑现。EXECUTED 同日。
**Pattern**: 接口漂移回写 registry 后,**发起 GDD 自身正文中的旧写法必须同批清扫**——回写义务条款在兑现后要标记状态,否则留下"义务已尽但正文仍说待办"的自相矛盾;跨条目引用(scope_event_binding 属 rng_service 非 board_gen)写全条目名可避免。
### 2026-09-09 — /consistency-check — 🔴 CONFLICT
**Domain**: 奖励经济 × 状态系统(义务清单交叉引用)
**Documents involved**: b4-reward-item-economy.md(Rule 3)vs registry entities.yaml(status_effect.b1_obligations ⑥/⑧)
**What happened**: B4 Rule 3 引"(B1 义务⑥ 同款协议)"指代满层"奖励未生效"明细行协议——但 B3 清单⑥ = decay_round 恰一次、B4 自有清单⑥ = roll_board 恰一次;该协议实际落点是 B3 ⑧ / B4 B1×6 ②。项目内并存多套"B1 义务清单",裸编号"义务⑥"产生歧义引用。
**Resolution**: 改为"B1 义务②〔本 GDD 清单〕/ B3 义务⑧ 同款协议"。EXECUTED 同日。
**Pattern**: **义务清单编号引用必须带清单限定词**("B3 义务⑧"而非裸"义务⑥")——同一接收方(B1)已累积 4 套清单(B3×8/B2×6/A2×3+2/B4×6),裸编号在多清单语境下不可解析。
### 2026-09-10 — /consistency-check — 🔴 CONFLICT
**Domain**: 战斗结算(B1 内部 AC 交叉引用)
**Documents involved**: b1-settlement.md(AC 节内部——qa-lead 代理交付稿)
**What happened**: 9 处 AC 编号误引——AC-13×2/AC-28 引"AC-34"(应为 AC-35/AC-36)、AC-24/AC-27 引"AC-30"(应为 AC-31)、前言负空间引"AC-29/AC-14"(应为 AC-30 腿1/AC-15 腿1)、AC-12 腿4 引"AC-27"(应为 AC-28)、out-of-scope 调参重跑清单缺 AC-36/37/40。
**Resolution**: 9 处同日修正(定向 /consistency-check 抓获——写入后即查)。
**Pattern**: **专家代理交付的长 AC 稿必须做编号引用自洽扫描**(引用的 AC 号 vs 被引 AC 实际内容)——qa-lead 起草过程中 AC 编号重排后交叉引用未随批更新,与"义务清单编号引用必须带清单限定词"同族的编号可解析性问题;建议 /design-system 的 AC 节写入后固定跑一次 `grep "AC-\d+" 交叉核对`。
### 2026-09-12 — /consistency-check — 🔴 CONFLICT
**Domain**: 奖励经济 × 数据配置(2026-09-11 两级奖励批 registry 回写完整性)
**Documents involved**: registry entities.yaml(reward_table.fields.category / reward_config.fields.p_min)vs b4-reward-item-economy.md L56 / d2-data-config.md L42–43
**What happened**: 2026-09-11 两级奖励批回写时 registry 同条目"改了 mechanics/头注、漏了 fields 行"×2——① category fields 行仍三值(同条目 mechanics 行已五值,自相矛盾);② p_min fields 行仍默认 4(同文件头注已记"p_min 4→8"、D2 行已 8)。
**Resolution**: 已执行(2026-09-12 用户批准):registry 两行修正完成(category 五值 / p_min 默认 8),复查扫描旧值清零。
**Pattern**: **接口漂移批的高发漏网点 = "散文/注释行改了、YAML fields 行没改"**——registry 条目内 fields 与 mechanics/头注是三处独立文本,批量改写须逐处 grep 旧值;本例与 2026-09-09"错引条目名"教训同族(回写完整性核查),修复后应将"fields 行 vs mechanics 行一致性"纳入 /consistency-check 固定检查项。
+31
View File
@@ -0,0 +1,31 @@
# Consistency Check Report — 2026-09-08(B3 定稿后定向 · 第二次)
- **Scope**: full · Registry 条目: 9(config_db / rng_service / stream_seed_derivation / difficulty_row_resolution / schema_version / action_economy / variation_table / variant_pool_gate / **status_effect✨ 新增**)
- **GDDs scanned**: d2-data-config · a3-action-economy · a4-terrain-variation · **b3-status-effect✨**
- **触发**: /design-system B3 定稿同日回填后的漂移检查
## Conflicts Found
无 🔴 冲突。
## Stale / Pending Write-backs(2 项——均已同日执行)
⚠️ **D2 Tuning Knobs 占位未随 B3 定稿删除**(d2-data-config.md Tuning Knobs 节)
- D2 自家规则"占位参考值定稿时必须删除对应条目"(A3 三轮回填先例同款);"增伤 1.5× / 减伤 0.5× / 持续 2 次结算(B3)"已随 B3 四行定稿失效
- → Resolution: **已执行(2026-09-08 同日)**——三值删除(划线保留痕迹),事实登记归 registry `status_effect`;owner 行 B3 标 ✓
⚠️ **B3 Overview 内部口径滞后**(b3-status-effect.md Overview 第二段)
- "标中旗 debuff 档位归 B4、敌方增益归 B2"写于 Rule 10 收编决策之前,与 Rule 10"四行定稿权归 B3"存在读法张力
- → Resolution: **已执行(2026-09-08 同日)**——Overview 改写为"经济归属归各锚 owner(锚验收权 B4/B2/B1),四行 MVP 初值定稿权经 Rule 10 收编归本 GDD",与 Rule 10 / registry ownership_note / 索引门禁记录四方对齐
## Unverifiable / Informational
ℹ️ **A3 GDD"档位归 B4"表述 vs B3 Rule 10 收编**:已治理分叉——systems-index 门禁增补记录(2026-09-08 B3 块)明文"A3 GDD(Approved)不改,以索引条 + registry ownership_note 为准"。非冲突。
ℹ️ **A4 三条定价硬约束的"最低档安全格 buff 当量"**:B3 定稿后参照对象 = attack_up 行(+50%×d2);A4 未曾定值,零数值冲突;对照闭合归 B1(条款 1 对照表)。
ℹ️ **weaken 条款 2 锚红色预警**:已知项(B3 Formulas 预警 + registry status_effect.anchor_warning + 索引 B1 强制检查点输入登记),非本次新发现;B1 对照验收优先裁决。
## Clean Entries
✅ config_db · rng_service(流封闭清单一致,combat_var 无复现)· stream_seed_derivation · difficulty_row_resolution · schema_version · action_economy(AP 8 跨文档引用一致;referenced_by 已增 B3——F2 AP 界只读消费)· variation_table(fog 行 GDD/D2/registry 三方一致)· variant_pool_gate · status_effect(GDD/D2 Core Rules 行/registry 三方同日同步一致)
**Verdict: PASS**(0 冲突;2 项 drift——同日核销)
+25
View File
@@ -0,0 +1,25 @@
# Consistency Check Report — 2026-09-08
- **Scope**: 定向(A4 定稿回填后)· Registry 条目:8(config_db / rng_service / stream_seed_derivation / difficulty_row_resolution / schema_version / action_economy / variation_table✨ / variant_pool_gate✨)
- **GDDs scanned**: d2-data-config · a3-action-economy · a4-terrain-variation
## Conflicts Found
无 🔴 冲突。
## Stale / Pending Write-backs
⚠️ **D2 Core Rules 表 VariationTable 行(占位描述落后于 owner 回填)**
- D2 占位:`变异类型枚举 + biome/tag 数据字段(AD 门禁)| 按 variant_id(含 unlock_level 列)| A4`
- A4 已定稿:8 字段 schema + fog 行(D2 接口漂移规则的**预期演化**,非冲突);按漂移规则,owner 回填须回写 D2 Core Rules 表行 + Status 行——**待执行**(A3 三次回填同款义务)。
- → Resolution: ~~更新 D2 Core Rules 表行与 Status 行~~ **已执行(2026-09-08 同日核销)**:VariationTable 行已标注"已回填定稿(2026-09-08 A4)+ Rule 4 豁免注明",D2 Status 行已登记 A4 回填。
## Unverifiable / Informational
ℹ️ **A3 F1 条款 5 括注示例被 A4 定稿超越**:A3 原文"可推理率越低(迷雾/终局 50/50 越多)"——A4 承重规则(雾区无雷)下迷雾不再产生 50/50,不再作为可推理率减项。条款本体(B1 闭合对账)不变;A4 Interactions 与 registry `variation_table.fog_ap_note` 已登记 B1 对账注记,随 B1 GDD 消化。Approved 文档 A3 不改。
## Clean Entries
✅ rng_service/board_gen(scope 绑定口径一致)· config_db(单点访问)· action_economy(AP 8 / 旗 1 AP 引用一致)· variation_table / variant_pool_gate(源=A4,自洽)· difficulty_row_resolution / stream_seed_derivation(A4 显式不消费,文档化)· schema_version(间接承载)。
**Verdict: PASS**(0 冲突;1 项漂移规则回写——已执行)
+26
View File
@@ -0,0 +1,26 @@
# Consistency Check Report — 2026-09-09(A1 定稿后定向)
- **Scope**: full · Registry 条目: **10**(config_db / rng_service / stream_seed_derivation / difficulty_row_resolution / schema_version / action_economy / variation_table / variant_pool_gate / status_effect / **board_gen_table✨ 新增**)
- **GDDs scanned**: d2-data-config · a3-action-economy · a4-terrain-variation · b3-status-effect · **a1-board-generation✨**
- **触发**: /design-system A1 定稿同日回填后的漂移检查(本会话第二次收口检查)
## Conflicts Found
无 🔴 冲突。
## Stale / Pending Write-backs(1 项——已同日执行)
⚠️ **D2 Dependencies 表 A1 行滞后于回填**(汇总行未含 BoardGenTable 回填字样;权威的 Core Rules 表行已更新)
- → Resolution: **已执行(2026-09-09 同日)**——A1 行改为 "BoardGenTable 回填(首个进度键表)+ VariationTable schema + board_gen 流",与 A3/A4 行口径对齐
## Unverifiable / Informational
ℹ️ **rng_service 快照契约的 A1 具体化**:A1 F5 "attempt 边界 = 生成函数完整返回"是 D2 快照契约(消费方 D3)的 A1 侧操作定义——补充细化非冲突,registry `board_gen_table.mechanics` 已登记。
ℹ️ **combat_var 零复现**:仅存于 registry 历史注记与 `gdd/reviews/` 归档备份(非活文档)。
ℹ️ **B3 上轮核销项复核在位**:Overview 收编括注 ✓ · D2 Tuning Knobs 三值删除 ✓ · status_effect 三方一致 ✓。
## Clean Entries
✅ config_db · rng_service(board_gen scope 绑定与 A1"一图一取号"一致)· stream_seed_derivation · difficulty_row_resolution · schema_version · action_economy(referenced_by 含 A1,dig_ap_cost 只读引用一致)· variation_table(f≤8d/⑫ 与 A1 F2 一致)· variant_pool_gate · status_effect · **board_gen_table(GDD/D2/registry 三方同日同步)**——全部 GDD 零占位残留。
**Verdict: PASS**(0 冲突;1 项 drift——同日核销)
+60
View File
@@ -0,0 +1,60 @@
# Consistency Check Report(B4 定稿后定向)
Date: 2026-09-09
Registry entries checked: 17(services 2 · schema_data 8 · formulas 3 · constant_set 1 · glossary 1 · constant 1 · 其他 1)
GDDs scanned: 8(d2 / a3 / a4 / b3 / a1 / a2 / b2 / b4)+ game-concept(两处登记对齐项专查)
Scope: B4 定稿后定向(沿 B3/A1 定稿后定向检查先例)
---
## Conflicts Found
### 🔴 C1 — B4 引用错误条目名 + 过期语义(3 处)
- Registry(source: rng_service):`scope_event_binding.reward_roll = "每次 board install(格奖励批 + 清图奖励批)"`(2026-09-09 B4 定稿批改写)
- B4 GDD 三处(Overview / Rule 2 语义注记 / Dependencies ②)写作 "`board_gen.scope_event_binding` … '每次奖励结算'"——**条目名错引**(board_gen 无该属性)且为回写前旧语义
- Resolution(EXECUTED 同日):B4 三处改为 `rng_service.scope_event_binding` + 新语义;Rule 2/Dependencies 回写义务标"已兑现"。registry 为权威侧(owner 授权漂移),B4 文本系回写前写法,非设计分歧。
### 🔴 C2 — B4 Rule 3 义务编号错引
- B3 registry `status_effect.b1_obligations` ⑧ = "溢出未生效"行进结算明细协议;B4 自有 B1×6 之② = 满层零兑付 + "奖励未生效"行
- B4 Rule 3 原文"(B1 义务⑥ 同款协议)"——两套清单的⑥(decay_round / roll_board 恰一次)均非该协议
- Resolution(EXECUTED 同日):改为"B1 义务②〔本 GDD 清单〕/ B3 义务⑧ 同款协议"。同文件另两处"义务⑥"(资格格清单供给,AC 节/Dependencies)指向 roll_board 恰一次,**引用正确、未动**。
### ⚠️ S1 — game-concept 第 144 行过期(主动道具)
- game-concept(待定问题):"[ ] 主动道具——后续版本加入;B4 GDD 预留'使用时机'字段"
- B4 定稿(2026-09-09 用户拍板):MVP 激活(轮末结算前道具使用窗口;use_timing 单值 pre_settlement 承重)
- Resolution(EXECUTED 同日):game-concept 改为 [x] 定稿条目(沿第 145-147 行 A3 修订注记同款格式)。
### ⚠️ S2 — game-concept 第 3 行参照口径(Peglin 道具跨循环累积)
- game-concept 参考行:"道具跨循环累积"(Peglin 参照特性,无战斗域界定)
- B4 定稿:库存 = 战斗域(跨轮次跨图累积、battle_over 全清不跨战斗)
- Resolution(EXECUTED 同日):参考行加 B4 定稿口径括注(与 Peglin 跨战斗持有显式区分)。非锁值冲突——参照描述对齐。
### ℹ️ T1 — 术语登记补漏
- B4 首创术语"资格格"(GDD 内已有白话内联定义)未入 registry terminology——用语纪律(CLAUDE.md 2026-09-09)要求登记
- Resolution(EXECUTED 同日):terminology 增词条 + referenced_by 增 B4。
---
## 核实一致的关键声称(抽样)
✅ B3 source_class 四值枚举 `{safe_cell, flag_hit, mine_hit, clear_reward}`(B3 Rule 3 原文核对)——B4"已在枚举内"声称成立
✅ A2 `reward_eligible` 口径(initial false / chain·dig∧safe true 含雾格 / mine false)与 B4 F1 资格格集 = S∖R₀ 等价
✅ enemy hp=18 ×unit_count 3 = 54(B4 Tuning Knobs "3 单位 54 需求")与 registry enemy.hp 一致
✅ dig_ap_cost=1(B4 缺口预检 2 分母引用)与 registry action_economy 一致
✅ defense_up max_stack=2(B4 E3/F 预警④ "13 格链 × max_stack=2")与 registry status_effect 一致
✅ B4 AC-20① 断言的 registry 措辞与实际写入逐字一致
✅ D2 六处回写与 B4 Rule 9 字段清单/registry reward_table 八键一致
✅ A3 条款④⑤、A4 三约束的引用措辞与 registry action_economy.downstream_contract / variation_table.pricing_constraints 一致
---
## Verdict
**PASS(修正后)**——2 🔴 + 2 ⚠️ + 1 ℹ️ 全部同日修正落盘(drift write-back EXECUTED);无未决冲突。
修正涉及文件:`b4-reward-item-economy.md`(4 处)· `game-concept.md`(2 处)· `entities.yaml`(terminology 词条 + referenced_by)
+78
View File
@@ -0,0 +1,78 @@
# 一致性检查报告(2026-09-12,lore 换轴概念层增补后全量)
> Scope: full · 触发:世界观换轴(惩罚格类型化/控制/坍塌显形)落地后的例行检查 · 方法:grep-first + 疑点定点深查
> Registry: 23 登记项(实体 14 / 公式 6 / 常量与公式集、词汇表 27 词条)
> 扫描面:GDD ×10(a1–a4 / b1–b4 / c3 / d2)+ 专查 game-concept / game-pillars / design/ux/battle.md / design/ux/interaction-patterns.md / registry / production/session-state(33+ 条目)
## 结论
**CONFLICTS FOUND**——2 项 🔴(registry 2026-09-11 批行内字段漏网,文本级、修复分钟级)+ 2 项 ⚠️(概念层措辞/命名登记级)+ 4 项 ℹ️(核实为在案事项)。**零数值冲突、零结构冲突、零接口冲突、零阻断**;23 项登记项中 21 项跨文档零冲突。
---
## 🔴 冲突(须修,均已定位到行)
### 🔴-1 registry `reward_table.fields.category` 三值残留(2026-09-11 批漏网)
- registry fields 行:`enum {buff, damage_item, heal_pack}——MVP 恰三值`
- 事实源:B4 GDD L56 与 D2 L42 均为 **五值** `{buff, damage_item, heal_pack, instant_aoe, instant_heal}`(两类交付轴);**registry 同条目的 mechanics 行也已写"category 五值枚举"**——同条目内自相矛盾,fields 行漏改。
- 修复:registry fields 行改五值(owner=B4 口径代修)。
### 🔴-2 registry `reward_config.fields.p_min` 默认 4 残留(同批漏网)
- registry fields 行:`默认 4 = 默认根最低刀 power`
- 事实源:D2 L43 = `默认 8`(2026-09-11 批);**registry 本文件头部修订注释自己记了"reward_config p_min 4→8"**——注释改了、字段行没改。
- 修复:registry 默认 4→8(owner=B4 口径代修)。注:entry 21(可选类供给控制器)批将再度改写刀供给/K_dmg=0/active_p0 等(已登记"B4/registry 改写待文档批"),p_min 最终语义随该批走;4→8 这个中间态修正无争议可先行。
---
## ⚠️ 漂移(登记级,本检查新抓)
### ⚠️-1 概念层换轴措辞碰撞:B1 L29 / B3 L22 "雷是赌桌不是陷阱"
- 2026-09-12 lore 换轴后"陷阱"成为惩罚格类型词表一员(未来类型:直接扣血),该句字面可误读为"雷格不是陷阱类型的惩罚格"。句子本意(雷是争夺中的资源、非单向环境危险)在新正典下反而更成立——实际风险低。
- 处置:不动机制 GDD;登记进 lore 记录③;措辞更新归 B1/B3 各自下一批修订(候选替换:"雷是赌桌不是死局")。
### ⚠️-2 lore ② 敌种叙事行与切片 DND 命名错位
- session-state entry 91(2026-09-12 v3 批):切片 enemy_id 已更名 **goblin / bugbear / ogre_chief**(DND 命名批);registry / B2 / D2 / C3 GDD 仍为 grub / ambusher / boss_guardian(待文档批,与 entry 37 同族)。
- lore 记录②"敌种叙事身份轴"以 grub(蛆虫=腐巢爬虫)为锚——DND 名下"巢居虫群"意象需换皮(goblin/bugbear 仍可作"巢穴居民",蛆虫意象作废)。
- 处置:随 enemy 文档对账批一并处理;lore 侧届时按正式 enemy_id 重写叙事行。
---
## ℹ️ 核实为"已知/在案"(非新发现,列出以防重复登记)
1. **C3 L236/267 `refresh_max_per_round` vs registry/A3/B1 `refresh_cap_per_round`**——session-state entry 35 已登记:切片 provisional 名 vs GDD 正式名、语义一致,正式 D1 批统一命名。在案。
2. **B3 正文 weaken −25 ×4 处 + 🔴 预警两处(L195/237)未关**——2026-09-10 检查已裁定 documented-exception(registry F0 回执"正文不改以本条为准"收编先例覆盖),维持原判。建议 B3 下一批补一行 F0 关闭回执注记(两处红警读作已裁决),并顺带更正 B1 L422 回执措辞("B3 GDD 行表"实际未回写,按收编先例口径)。
3. **registry `reward_table.direction_precheck` 旧预检(40%×5=2|资格格|)**——B4 L219 已重算(19%×9.7≈1.8|资格格|),entry 21 供给控制器批再 supersede 且已登记"B4/registry 改写待文档批"。随批。
4. **D2 三处文本级残留**:L225"category 三值封闭/AOE 不入 MVP"(五值批前旧注);L44 SettlementTable 行"七字段/pool_clamp_lo_hi/p_perfect [100,999]"(clamp 部分已有收编注记,**p_perfect 域 {100,200} 无收编覆盖——D2 schema 层与 B1 载体域两层校验分歧,建议随批优先**);L42 RewardTable 默认根枚举小滑差(旧五行集并列残留 / 八行枚举漏 clear_knife / attack_up 缺 _basic 后缀)。→ 归入 entry 21/37 文档对账批。
---
## 已登记待办批(session-state 在案,本检查确认仍在册——对账批输入清单)
| 来源批 | 待回写面 |
|---|---|
| entry 21 可选类供给控制器 | clear_blast 40 / active_inject 60-30-10 / active_p0-decay / K_dmg=0 → B4 GDD F5 + registry reward_table/reward_config |
| entry 27/35 轮内刷新 | A3/B1/B4 GDD + game-concept 层级措辞 + registry;refresh 字段名统一归正式 D1 批 |
| entry 33 遭遇随机化 | EnemyTable.unit_count_max → registry enemy.fields + D2 EnemyTable 行;**D2 Rule 5 流清单缺 encounter 行**(registry rng_service 已登记) |
| entry 37 伤害×护甲批 | EnemyTable.armor_type / B1 三分量构成+armor_effectiveness / B3 六行状态表 / **A2 OQ1(标错惩罚三选一 + 重复性=每雷实例一次)** / registry enemy·settlement·status_effect / C3 数值接管 |
| entry 91 v3 数值批 | DND 命名(goblin/bugbear/ogre_chief)→ B2/registry/D2 enemy 行 |
| C3 SLICE-TUNED 转正 | C3 L42 自declare 回写责任 → registry enemy/hero + D2 行值(grub 24/伏击兽 36/守卫 130、hero 50 等) |
---
## 概念层专项(2026-09-12 lore 换轴 · 本会话范围核验)
1. game-concept 世界观与命名节 + 视觉锚原则 5:已带 2026-09-12 版本注记落地 ✓;机制节"雷/旗"用词为机制名、按设计不动 ✓
2. game-pillars P4:引用式写法(指向 game-concept)自动随流,零改动 ✓
3. registry terminology:概念层术语不入 registry(2026-09-09 概念层增补先例)✓
4. B1/B3"不是陷阱"措辞碰撞:⚠️-1 登记
5. battle.md 玩家可见文案"插旗"→"控制"采纳点:文案 pass / D1 批执行(battle.md L258 明载文案定稿权归实现期文案 pass)——登记
6. **A2 OQ1 重复性已被切片实现事实收口**(entry 37:每雷格实例一次去重,确定性派生三选一)→ lore ⑤-3(c) 措辞可定"**当轮反扑**",待 A2 GDD 修订批确认后回写 lore
7. game-concept 待定问题"标错惩罚"挂 Open:正确状态(机制落点走 A2 OQ1 修订批)——known-open
---
## 干净项
✅ 21/23 登记项跨 GDD 零冲突:config_db · rng_service(流语义/scope 绑定一致)· stream_seed_derivation · difficulty_row_resolution · schema_version · action_economy(AP 8/价目/RAP 规则全一致)· variation_table · variant_pool_gate · status_effect(D=1/+3/cap=4)· board_gen_table([0.85,1]/0.25/16384/min_safe)· a2_event_surface · a2_initial_expansion · terminology · enemy(cap=4/行集规则)· hero(atk=6/拒 0)· reward_table(mechanics/mvp_content 行)· settlement_table(registry↔B1 一致)· clause3_supply · clause5_dominance(C3 承接"非支配设计态"= 约束包②选择权行使 ✓)· difficulty_table · difficulty_expectation_table · boss_dmax_convention(Boss=Dmax+charge 拍 ✓)
**Verdict: CONFLICTS FOUND**(2 🔴 文本级 · 零阻断 · 修复清单见上)
+46
View File
@@ -0,0 +1,46 @@
# Godot — Version Reference
| Field | Value |
|-------|-------|
| **Engine Version** | 4.7.2-stable(2026-08-18 发布) |
| **Project Pinned** | 2026-09-07 |
| **LLM Knowledge Cutoff** | May 2025(训练数据覆盖 ~4.3/4.4) |
| **Risk Level** | **MEDIUM**(2026-09-12 降级)——4.5→4.7 API 级破坏性变更已逐条核实(源:官方迁移指南),无一条破坏本项目架构契约;残余风险 = 4.8(dev 阶段)未来升级 + 未覆盖的运行期边角行为,代理写码规则不变:不确定的 API 一律查 `docs.godotengine.org/en/4.7/` 或 WebSearch 核实后再用 |
| **Last Docs Verified** | 2026-09-12(4.5/4.6/4.7 迁移指南逐条核实 + 版本检查:4.7.2 仍为最新稳定版,4.8 仅 dev 快照) |
## Post-Cutoff Version Timeline
| Version | 发布 | 与本项目相关要点 |
|---|---|---|
| 4.4 | 2025-03(训练覆盖边缘) | — |
| 4.5-stable | 2025-09-15 | stencil 效果、无障碍改进;4.5.2(2026-03-19)为末版维护;**逐条变更已核实(2026-09-12)** |
| 4.6-stable | 2026-02 起(4.6.1 2026-02) | Modern 主题、flexible docks、编辑器 QoL;4.6.3 维护;**逐条变更已核实(2026-09-12)** |
| **4.7-stable** | 2026-06(**4.7.2 = 2026-08-18,本项目锁定**) | 见下;**逐条变更已核实(2026-09-12)** |
| 4.8 | dev 快照 1–4(开发中) | 无稳定版发布日期;稳定版发布后跑 `/setup-engine refresh` |
## 4.7 与本项目相关的变更(已核实)
- `Tween.tween_await()`(信号等待)——**不影响** B1"结算逻辑禁 await"约束(那是设计约束,非引擎限制)
- Control `offset_transform_*`(平移/旋转/缩放 Control 而不影响容器布局)——D1 HUD 可用
- DrawableTexture2D、AreaLight3D、HDR 输出、新 Asset Store——本项目暂不依赖
- 2D:CollisionShape2D 单向碰撞方向属性、conic gradient、AtlasTexture 进 TextureRect
- **GDScript 两条语义变化**(打包数组元素赋值不触发属性 setter;类型化返回覆盖必须显式 return)——详见 `current-best-practices.md`
- **新项目默认值已变**(stretch mode `canvas_items`、aspect `expand`;4.6 起 Windows 驱动 D3D12)——详见 `current-best-practices.md`
- Android/iOS/XR 增强——本项目 PC 先行,无关
## Migration Guides(升级/写码前必读)
- 4.7: https://docs.godotengine.org/en/4.7/tutorials/migrating/upgrading_to_godot_4.7.html
- 4.6 / 4.5 同路径模式:`.../tutorials/migrating/upgrading_to_godot_4.6.html`、`..._4.5.html`
- 三份指南的逐条中文对照与项目相关性标注见 `breaking-changes.md`(2026-09-12 版)
## Note
**MEDIUM 风险处置(2026-09-12 更新)**:4.5→4.7 的 API 级破坏性变更清单已逐条核实并入 `breaking-changes.md`,deprecated → replacement 对照已并入 `deprecated-apis.md`;对本项目的结论 = **无一破坏 GDD 已锁架构契约**。残余风险两项:① 4.8 未来升级(dev 阶段,稳定版后 refresh);② 运行期边角行为(迁移指南未覆盖的引擎内部行为差异)——代理写码规则保持不变:**不确定的 API 一律查 `docs.godotengine.org/en/4.7/` 或 WebSearch 核实后再用**。
## Verification History
| 日期 | 动作 |
|---|---|
| 2026-09-07 | 初次锁定 4.7.2;核实版本时间线与 4.7 特性清单 |
| 2026-09-12 | `/setup-engine refresh`:4.5/4.6/4.7 官方迁移指南逐条核实(breaking-changes.md 逐条清单 + deprecated-apis.md 对照表 + 新建 current-best-practices.md);版本检查确认 4.7.2 仍为最新稳定版(4.8 仅 dev);风险等级 HIGH → MEDIUM |
@@ -0,0 +1,115 @@
# Godot Breaking Changes(4.4 → 4.7)
> **Last verified: 2026-09-12**(官方迁移指南三份逐条核实——4.5/4.6/4.7 API 级清单已补全,原 2026-09-07"待 refresh"状态解除)
> 训练数据覆盖至 ~4.4:4.4 及以前的变更视为"已知基线",4.5+ 为超出截止的增量。
> 官方迁移指南(升级/写码前必读):
> - 4.5:https://docs.godotengine.org/en/4.7/tutorials/migrating/upgrading_to_godot_4.5.html
> - 4.6:https://docs.godotengine.org/en/4.7/tutorials/migrating/upgrading_to_godot_4.6.html
> - 4.7:https://docs.godotengine.org/en/4.7/tutorials/migrating/upgrading_to_godot_4.7.html
>
> 项目相关性图例:🔵 需要留意(本项目域内)/ ⚪ 本项目不用(3D/XR/网络/移动/GLTF/编辑器插件)。
> 本项目形态:2D 回合制、GDScript 单语言、Control 重 UI、autoload + .tres、无 3D/物理/网络。
## 4.5(2025-09-15)
### API 级变更
| 类/方法 | 变更 | GDScript 兼容 | 项目相关性 |
|---|---|---|---|
| `Resource.duplicate(true)` | 深复制**不再覆盖外部子资源**;旧行为需 `duplicate_deep(DEEP_DUPLICATE_ALL)` | 行为变更 | 🔵 D2 schema/表资源复制语义注意 |
| `Node.set_name` | 参数 `String` → `StringName` | 兼容 | 🔵 |
| `JSONRPC.set_scope` | 更名 `set_method` | ❌ | ⚪ |
| `Node.get_rpc_config` | 更名 `get_node_rpc_config` | ❌ | ⚪(RPC 不用) |
| `RenderingServer.instance_reset_physics_interpolation` | **移除** | ❌ | ⚪(3D 插值) |
| `RenderingServer.instance_set_interpolated` | **移除** | ❌ | ⚪ |
| TextServer/Font/CanvasItem/TextLine/TextParagraph 全部 draw 方法 | 新增可选 `oversampling` 参数 | 兼容 | 🔵 D1 自绘文字 |
| `TextServerExtension` 四个 draw 虚方法 | 同上签名变化 | ❌(全不兼容) | ⚪(不实现 TextServer 扩展) |
| `RichTextLabel.add_image`/`update_image` | `size_in_percent` → `width_in_percent` + `height_in_percent` | 兼容 | 🔵(低——富文本用图时) |
| C# `RenderingDevice.Features.Address` | 更名 `BufferDeviceAddress` | 仅 C# | ⚪(C# 不用) |
| GLTF Accessor/BufferView 十字段 | int32 → int64 / 枚举化 | 仅 C# | ⚪(GLTF 不用) |
### 行为变更
- **TileMapLayer 物理分块默认开启**;`get_coords_for_body_rid()` 返回值变化;需 4.4 精确行为设 `physics_quadrant_size=1` —— 🔵 若棋盘实现走 TileMapLayer(当前设计倾向自绘,未定)
- 3D 模型导入 skeleton 行为修复(新文件新行为;旧文件需改 Import Naming Version)—— ⚪
- Navigation 区域默认异步线程更新;navmesh 合并次序变化 —— ⚪(A2 用自研 BFS,不用 NavigationServer)
- Jolt:`areas_detect_static_bodies` 设置移除 —— ⚪
- `ProjectSettings.add_property_info()` 对缺失/非法键(含 `usage`)告警 —— 🔵(若程序化注册设置项)
## 4.6(2026-02)
### API 级变更
| 类/方法 | 变更 | GDScript 兼容 | 项目相关性 |
|---|---|---|---|
| `FileAccess.get_as_text` | `skip_cr` 参数**移除** | ❌ | 🔵 文本读取路径 |
| `FileAccess.create_temp` | `mode_flags` int → `ModeFlags` 枚举 | 兼容性检查变化 | 🔵 |
| AnimationPlayer `assigned_animation`/`autoplay`/`current_animation` | `String` → `StringName`(`get_queue()`、`current_animation_changed` 信号参数同步) | ❌(类型不兼容) | 🔵 B5 期 |
| SpringBoneSimulator3D 三个枚举 | 移至 `SkeletonModifier3D` | ❌ | ⚪ |
| StreamPeerTCP / TCPServer | `disconnect_from_host`/`get_status`/`poll`、`is_connection_available`/`is_listening`/`stop` 上移至 `StreamPeerSocket`/`SocketServer` 基类 | 兼容(继承) | ⚪(网络不用) |
| `Control.grab_focus`/`has_focus`、`LineEdit.edit`、`SplitContainer.clamp_split_offset`、`FileDialog.add_filter` | 新增可选参数 | 兼容 | 🔵 D1 |
| EditorFileDialog | `add_side_menu` **移除**;17 方法 / 8 属性 / 4 信号并入 `FileDialog` 基类 | 兼容(继承) | ⚪(编辑器) |
| `Performance.add_custom_monitor` | 新增可选 `type` 参数 | 兼容 | 🔵(调试遥测可选) |
### 行为 / 格式变更
- **TSCN 格式**:`load_steps` 不再写入、节点唯一 ID 入文件——双向兼容,但 VCS diff 变大(可 Project > Tools > Upgrade Project Files 预升级)—— 🔵
- **Glow 默认值大改**(blend mode Soft Light → Screen、intensity 0.8 → 0.3、各 level 重排);Mobile 渲染器 glow 重写 —— 🔵 D1/B5 用 2D Glow 时注意视觉基底已变
- AStar2D/AStar3D/AStarGrid2D:`from_id` 被禁用/固体时返回空路径 —— ⚪(自研 BFS)
- **新项目默认值**:Windows 渲染驱动 D3D12;3D 物理引擎 Jolt —— 🔵 创建 project.godot 时须知(本项目 2D、无 3D 物理,渲染驱动选择归实现期 ADR)
## 4.7(2026-06;4.7.2 = 本项目锁定版本)
### API 级变更
| 类/方法 | 变更 | GDScript 兼容 | 项目相关性 |
|---|---|---|---|
| **GDScript 语义 ①** | 打包数组元素赋值不再触发整属性 setter(GH-113228) | 语义变化 | 🔵 全部 .gd 代码 |
| **GDScript 语义 ②** | 覆盖类型化返回方法:返回类型自动继承,必须显式 `return`(GH-115763) | 语义变化 | 🔵 全部 .gd 代码 |
| `Object.is_class()` | 参数 `String` → `StringName` | 兼容 | 🔵 |
| `PhysicsServer2D.body_set_shape_as_one_way_collision` | 新增可选 `direction`(= CollisionShape2D 单向碰撞方向属性的 server 层) | 兼容 | 🔵(已核实特性的 API 面) |
| `PhysicsServer2DExtension._body_set_shape_as_one_way_collision` | 新增**必填** `direction` | ❌ | ⚪(不写 PhysicsServer 扩展) |
| `CanvasItem` 线条绘制 | 不再自动加抗锯齿羽化;粗线需手动绘制(GH-105122) | 行为变更 | 🔵 D1 自绘 |
| Input 设备 ID | 鼠标/键盘设备 ID `0` → `InputEvent.DEVICE_ID_MOUSE` / `DEVICE_ID_KEYBOARD` 常量 | 行为变更 | 🔵 D1 输入 |
| `Control.accessibility_live` | 枚举类型 `DisplayServer.` → `AccessibilityServer.AccessibilityLiveMode` | 仅 C# 不兼容 | 🔵(低) |
| RichTextLabel 图片参数 | `add_image`/`update_image` width/height int→float;`width_in_percent/height_in_percent` → `width_unit/height_unit`;常量 `UPDATE_WIDTH_IN_PERCENT` → `UPDATE_WIDTH_UNIT` | ❌(常量更名) | 🔵(低) |
| `Animation.length` | 元数据 float → double | 仅 C# 不兼容 | 🔵(低,B5 期) |
| AnimationNodeBlendSpace1D/2D | 布尔 `sync` 属性 → `SyncMode` 枚举(`sync_mode`) | 行为变更 | ⚪(3D 动画树) |
| `Font.find_variation` / `TreeItem.select` / `ZIPPacker.start_file` / `Image.save_exr`×2 | 新增可选参数 | 兼容 | ⚪/🔵 |
| `AudioEffectSpectrumAnalyzer.tap_back_pos` | **移除** | ❌ | ⚪(D4 Alpha 期若用频谱分析注意) |
| `EditorSceneFormatImporter` 七常量 | 并入 `ImportFlags` 枚举 | 仅 C# 源不兼容 | ⚪ |
| `EditorVCSInterface._commit` | 新增 `amend` 参数 | ❌ | ⚪ |
| `OptimizedTranslation.generate` | 返回 void → bool | 仅 C# 二进制 | ⚪ |
| `AudioStreamPlayer.area_mask` | 默认 1 → 0 | 行为变更 | ⚪(D4 Alpha 期注意) |
### 行为 / 默认值变更
- `LinearToSRGB` visual shader 不再 clamp 到 [0,1](Mobile/Forward+)—— 🔵(若写 shader)
- **新项目默认值**:stretch mode `disabled` → `canvas_items`、stretch aspect `keep` → `expand` —— 🔵 **创建 project.godot 时须知(训练数据默认值已过时)**
- macOS 最低版本 10.13 → 11 —— ⚪
- `LookAtModifier3D.relative` 默认 true → false —— ⚪
- `ResourceImporterDynamicFont.hinting` 默认 1 → 3 —— 🔵(字体导入)
- `rendering/reflections/sky_reflections/roughness_layers` 默认 7 → 8 —— ⚪(3D)
## 已知基线(≤4.4,训练数据内,低风险)
- 4.x 系列:Tween 一律经 `create_tween()` 获取(Tween 节点已废);信号连接用 `Callable` 语法;`@onready`/`@export` 注解体系;int 恒 64 位(D2 R2 规约依赖此语义,4.x 内稳定)
## 本项目影响评估(2026-09-12 复核)
| 变更 | 影响 |
|---|---|
| 4.7 全部已核实特性 | 均为增量,无破坏 D2/A3 已批准规约的项 |
| **4.5–4.7 逐条 API 变更** | **无一破坏 GDD 已锁架构契约**(autoload 体系 / .tres 单一事实源 / Callable 信号 / int64 二补数 / headless SceneTree 协议均不受影响) |
| 需入编码规范的项 | GDScript 两条新语义(打包数组 setter / 显式 return)→ `current-best-practices.md` |
| 需项目设置留意的项 | 新项目默认值已变(stretch mode / aspect / D3D12)→ `current-best-practices.md` |
| `Resource.duplicate(true)` 语义收窄 | D2 表资源含外部子资源时的复制语义注意 |
## Pending
- [x] 4.4→4.5 breaking changes 逐条清单(2026-09-12 官方迁移指南)
- [x] 4.5→4.6 breaking changes 逐条清单(2026-09-12 官方迁移指南)
- [x] 4.6→4.7 breaking changes 逐条清单(2026-09-12 官方迁移指南)
- [x] 各版本 deprecated → replacement 对照表(见 `deprecated-apis.md`,2026-09-12)
- [ ] 4.8 逐条清单(当前仅 dev 快照;稳定版发布后跑 `/setup-engine refresh`)
- [ ] modules/ 分域参考(按实现期需要建,非阻塞)
@@ -0,0 +1,49 @@
# Godot 当前最佳实践(4.7 视角,post-cutoff)
> **Last verified: 2026-09-12**(源:官方迁移指南 4.5/4.6/4.7 逐条核实 + 4.7 release 页)
> 用途:训练数据(~4.4)之后的实践差异速查。写码代理在以下事项上**不要**按训练数据默认值行事。
## 1. 新建 project.godot 的默认值差异(最易踩坑)
| 设置 | 训练数据默认(≤4.4) | 4.7 实际新项目默认 | 生效版本 |
|---|---|---|---|
| `display/window/stretch/mode` | `disabled` | `canvas_items` | 4.7(新项目) |
| `display/window/stretch/aspect` | `keep` | `expand` | 4.7(新项目) |
| `rendering/rendering_device/driver.windows` | Vulkan(Forward+) | D3D12 | 4.6(新项目) |
| `physics/3d/physics_engine` | GodotPhysics3D | Jolt | 4.6(新项目;本项目 2D、无 3D 物理,无关) |
本项目为 2D 棋盘 UI:stretch mode / aspect 的最终选择归渲染器实现期 ADR,但须知道**引擎新项目默认值已不是训练数据里的那个**——新建工程后检查这三项。
## 2. GDScript 4.7 两条语义变化(建议入编码规范)
1. **打包数组元素赋值不再触发属性 setter**(4.7,GH-113228):`my_packed_array[i] = v` 不再调用所在对象的 property setter——依赖 setter 副作用的写法必须改为显式赋回 + 显式调用 setter。D2 schema 类若以 setter 做校验,注意此差异。
2. **类型化返回的方法覆盖必须显式 `return`**(4.7,GH-115763):覆盖带返回类型的方法时返回类型自动继承,缺少 return 直接报错(旧版隐式返回 null)——虚方法覆盖一律显式写 return。
## 3. 资源与文件
- `Resource.duplicate(true)`(4.5 起):深复制**只覆盖内部子资源**,不再覆盖外部子资源;需旧行为用 `duplicate_deep(DEEP_DUPLICATE_ALL)`。D2 表资源含外部子资源时注意复制语义。
- `FileAccess.get_as_text()` 的 `skip_cr` 参数已移除(4.6)——换行处理如需自定义须自行实现。
- TSCN 格式(4.6):`load_steps` 不再写入、节点唯一 ID 入文件——双向兼容,但 VCS diff 会变大(可 Project > Tools > Upgrade Project Files 预升级,减少一次性大 diff)。
- `ProjectSettings.add_property_info()`(4.5):对缺失/非法键(含 `usage`)告警;改用 `set_as_basic()` / `set_restart_if_changed()` / `set_as_internal()`。
## 4. 2D / UI / 文本
- `CanvasItem` 线条绘制**不再自动加抗锯齿羽化**(4.7)——粗线/描边需手动方案(D1 自绘棋盘格边框时注意)。
- 输入设备 ID:比较输入来源时用 `InputEvent.DEVICE_ID_MOUSE` / `DEVICE_ID_KEYBOARD` 常量,**不要硬编码 0**(4.7)——D1 输入路由。
- 字体导入 `hinting` 默认 1 → 3(4.7);TextServer/Font/CanvasItem 全部 draw 方法新增可选 `oversampling` 参数(4.5)——自绘文字(数字标签)可显式控制过采样。
- RichTextLabel 图片参数两轮变化:4.5 `size_in_percent` → `width_in_percent`+`height_in_percent`;4.7 → `width_unit`/`height_unit`(bool → `ImageUnit`),常量 `UPDATE_WIDTH_IN_PERCENT` → `UPDATE_WIDTH_UNIT`。
- **Glow 默认值大改**(4.6):blend mode Soft Light → Screen、intensity 0.8 → 0.3、各 level 重排——2D 后处理发光的视觉基底已变,调参以 4.7 默认为起点。
- `Control.grab_focus` / `has_focus` 新增可选参数(4.6,`hide_focus` / `ignore_hidden_focus`)——焦点可视化管理更细。
## 5. 4.7 已核实新特性(本项目可用的增量)
- `Tween.tween_await()`:信号等待语法糖——**注意** B1 结算逻辑禁 await 是设计约束(可回放步骤流),该 API 不改变该约束
- Control `offset_transform_*`:平移/旋转/缩放 Control 不影响容器布局——D1 HUD 局部动效可用
- CollisionShape2D 单向碰撞方向属性(+ `PhysicsServer2D.body_set_shape_as_one_way_collision` 的 `direction` 参数)——本项目棋盘非物理驱动,暂不依赖
- conic gradient、AtlasTexture 进 TextureRect——D1 贴图/着色可选
- DrawableTexture2D、AreaLight3D、HDR 输出、内置 VirtualJoystick、新 Asset Store——本项目暂不依赖
- `Font.find_variation` 扩展(palette_index / custom_colors)、`TreeItem.select` 扩展——低相关
## 6. 本项目不消费的域(相关变更可忽略)
3D 渲染与物理(Jolt 行为变化 / SoftBody / WorldBoundary / SpringBone / LookAtModifier)、XR/OpenXR、网络(StreamPeerTCP/TCPServer 方法上移、RPC 更名)、GLTF 导入(int64 字段)、移动端导出(Android 模板结构变化、.NET 9)、编辑器插件 API(ImportFlags / VCS / ExportPlatform)。
@@ -0,0 +1,51 @@
# Godot Deprecated APIs(Don't use X → Use Y)
> **Last verified: 2026-09-12**
> 4.5–4.7 移除/更名/签名变化对照已补全(源 = 官方迁移指南,2026-09-12 逐条核实)。仍不含 4.8(dev 阶段)。**不要向本表添加未经验证的条目。**
## 4.7 release 页核实
- 4.7 release 页未列出新的 API 弃用;完整清单以其迁移指南为准(已逐条核实,见下节)
## 4.5–4.7 移除 / 更名 / 签名变化对照(源 = 官方迁移指南)
| Don't use | Use | Since | GDScript 影响 | 项目相关性 |
|---|---|---|---|---|
| `RenderingServer.instance_reset_physics_interpolation()` | (无替代——API 移除) | 4.5 | ❌ 移除 | ⚪ |
| `RenderingServer.instance_set_interpolated()` | (无替代——API 移除) | 4.5 | ❌ 移除 | ⚪ |
| `JSONRPC.set_scope()` | `set_method()` | 4.5 | ❌ 更名 | ⚪ |
| `Node.get_rpc_config()` | `get_node_rpc_config()` | 4.5 | ❌ 更名 | ⚪ |
| `Node.set_name(name: String)` | `set_name(name: StringName)` | 4.5 | 兼容(自动转换) | 🔵 |
| `TextServerExtension` 四个 draw 虚方法 | 签名新增 `oversampling` | 4.5 | ❌(虚方法覆盖不兼容) | ⚪ |
| RichTextLabel `size_in_percent` 参数 | `width_in_percent` + `height_in_percent` | 4.5 | 兼容(参数拆分) | 🔵(低) |
| `FileAccess.get_as_text(skip_cr)` | `get_as_text()`(**skip_cr 参数移除**) | 4.6 | ❌ 参数移除 | 🔵 |
| `EditorFileDialog.add_side_menu()` | (无替代;EditorFileDialog 17 方法/8 属性/4 信号并入 `FileDialog`) | 4.6 | ❌ 移除 | ⚪ |
| AnimationPlayer `assigned_animation` / `autoplay` / `current_animation`(String) | `StringName`(含 `get_queue()`、`current_animation_changed` 参数) | 4.6 | ❌ 类型不兼容 | 🔵(B5 期) |
| SpringBoneSimulator3D 三个枚举 | `SkeletonModifier3D.BoneDirection` / `.RotationAxis` | 4.6 | ❌ | ⚪ |
| `AudioEffectSpectrumAnalyzer.tap_back_pos` | (无替代——属性移除) | 4.7 | ❌ 移除 | ⚪(D4 期注意) |
| AnimationNodeBlendSpace1D/2D `sync: bool` 属性 | `sync_mode: SyncMode` 枚举 | 4.7 | ❌ 属性类型变化 | ⚪ |
| RichTextLabel `ImageUpdateMask.UPDATE_WIDTH_IN_PERCENT` | `UPDATE_WIDTH_UNIT`;`width/height_in_percent` 参数 → `width/height_unit`(bool → `ImageUnit`) | 4.7 | ❌ 常量/参数更名 | 🔵(低) |
| `Object.is_class("X")`(String 字面量) | `is_class(&"X")`(StringName) | 4.7 | 兼容 | 🔵 |
| `EditorVCSInterface._commit()` | 签名新增 `amend` | 4.7 | ❌(虚方法覆盖不兼容) | ⚪ |
| `PhysicsServer2DExtension._body_set_shape_as_one_way_collision()` | 签名新增必填 `direction` | 4.7 | ❌(虚方法覆盖不兼容) | ⚪ |
| C# `RenderingDevice.Features.Address` | `BufferDeviceAddress` | 4.5 | 仅 C# | ⚪ |
| GLTF Accessor/BufferView 十字段(int) | int64 / 强类型枚举 | 4.5 | 仅 C# | ⚪ |
## 训练数据内基线(≤4.4,高置信,本项目相关)
| Don't use | Use | Since | 备注 |
|---|---|---|---|
| `Tween` 节点 / `create_tween()` 以外的补间获取 | `create_tween()` / `tween_property()` | 4.0 | Tween 节点已移除 |
| 旧式 `connect("sig", instance, "method")` | `signal.connect(callable)` | 4.0 | Callable 语法 |
| `onready var` | `@onready var` | 4.0 | 注解体系 |
| `export var` | `@export var` | 4.0 | |
| `RandomNumberGenerator` 自建实例(玩法侧) | `RngService.open_stream(stream)` | 本项目 | D2 Rule 5(项目级禁令,非引擎弃用) |
| `randomize()`(玩法代码) | 禁止——种子归 `RngService.set_master_seed()`(C2 调用) | 本项目 | D2 Rule 5 |
| `yield` | `await` | 4.0 | 4.7 新增 `Tween.tween_await()`;但 B1 结算逻辑禁 await(设计约束) |
## Pending
- [x] 4.5 deprecated → replacement 对照(2026-09-12)
- [x] 4.6 deprecated → replacement 对照(2026-09-12)
- [x] 4.7 deprecated → replacement 对照(2026-09-12)
- [ ] 4.8 对照(dev 阶段;稳定版发布后 `/setup-engine refresh`)
+311
View File
@@ -0,0 +1,311 @@
# B1 战斗结算规则(lean 格式样例)
> **状态**:格式样例——用新格式重排现有 `b1-settlement.md` 的内容域,供评审,非生效文档
> **版本**:lean-sample · 2026-09-13 · 作者:user + agents
> **一句话**:B1 把每轮扫雷的结果逐行兑现为战斗结果,并判定胜负。
## 速览
| 关键问题 | 答案 |
|---|---|
| 定位 | 战斗域编排与结算中枢;轮次生命周期唯一 owner |
| 拥有 | 段序、判定时机、伤害消费侧语义、明细流水协议、上游义务账本(B3×8 / B2×6 / A2×3 / B4×6) |
| 不拥有 | 单位状态(B2)· 状态实例(B3)· 奖励内容(B4)· 行动价目(A3)· 棋盘规则(A1/A2)· 呈现(D1/B5) |
| 上游输入 | A2 三事件流 · A3 相位观测量 · 各表值快照 |
| 下游输出 | 结算步骤流(D1/B5/D4 消费)· 条款③⑤对账结论(C3 约束输入) |
| 硬约束 | 零随机 · 零 UI 依赖 · 结算禁 await——同种子同输入 ⇒ 步骤流逐行相同 |
## 体验锚点
| 支柱 | 关键词 | 机制承诺 |
|---|---|---|
| P2 因果归因 | "都是我算出来的" | 每行明细携带来源标注;无来源行 = 断言失败(AC-42) |
| P1 掌控感 | "挖下去值得" | 条款③不等式由本系统闭合签字 |
| P3 雷的两面 | "赌桌不是陷阱" | 敌方伏击行与标中旗削弱行同框、同呈现语言 |
| 高光节拍 | "完美被加倍兑现" | 完美排雷双份兑付 + 标中旗行高光 |
## 全局流程
### 战斗开始
```
begin_battle(encounter)
│ ① set_reload_gate(true) [D2] 调试门置位
│ ② notify_battle_start() [B3] 容器开域
│ ③ spawn(L, D, hero_hp) [B2] 行值快照实例化
│ ④ install_board + roll_board [A2/B4] 恰一次;资格格清单 = S ∖ R₀
│ ⑤ notify_round_start() [A3] → Active
▼
RoundActive(挖掘期,B1 只缓冲事件流)
```
### 每轮结算(七段骨架,全序执行、段序结构冻结)
```
轮末触发:Waiting 相位编排点(只读 A3 相位观测量,不依赖事件到达序)
│
▼
①授予段 ──── cell_revealed 批 → flag_judged 批 → 清图奖励(仅 cleared 轮)
│ (转化规则见下方两表)
▼
②道具使用窗口 ─ 玩家至多选一件或跳过(全流程唯一玩家输入点)
│ 满血禁选治疗包;空库存可整体不弹窗
▼
③增益/减益段 ─ query_active 双侧读值 → SettlementTable 语义映射 → 效果明细行
│
▼
④道具段 ───── 伤害道具:恒定表值打 default_target;治疗包:clamp 回复
│ 施加时无存活敌 → 照常消耗 + "已消耗未生效"行
▼
⑤战斗段 ───── 主角先手攻击(D_hero = atk ×(1+attack_up))
│ → 逐存活敌(行主序):query_attack → apply_damage → advance
│ ※ hero hp=0 → 立即短路,剩余敌不作用,直入 ⑦
▼
⑥衰减段 ───── decay_round() 恰一次(含末轮;先兑付后衰减的时序契约)
│
▼
⑦判定段 ───── hero hp=0 → 失败 │ 存活敌=∅ → 胜利 │ 否则 → 下一轮
```
### 出口分发
| 结局 | 触发 | 动作序列 | 约束 |
|---|---|---|---|
| 继续 | 判定=下一轮 | `notify_settlement_done(same_board)` → `notify_round_start()` | 同图续轮 |
| 换图 | cleared 轮 | `retire_board` → `retire_mapping` → A1 `generate` → `install_board` → `roll_board` 恰一次 → `notify_settlement_done(new_board)` → `notify_round_start()` | stopped/ap_exhausted 恒 same_board,违约 fail-fast |
| 挖掘期刷新 | 玩家经 D1 发起 | A3 `request_refresh` 扣费 → 换图全序(无结算段、无 round_end、轮次不终结) | RAP 不足→拒绝上抛;每图 cap 2;刷新图无清图奖励 |
| 战斗结束 | 判定=胜/负 | `retire_mapping` → `despawn_all` → `notify_battle_end` → `notify_combat_end` → `set_reload_gate(false)` | 库存不清(关内延续) |
| 关卡结束 | 上层显式调用 | `clear_inventory()` 恰一次,清空前快照计数返回 | victory/defeat 皆然 |
## 核心规则
| # | 规则 | 要点 |
|---|---|---|
| 1 | 编排唯一性 | B1 是战斗域全部跨系统调用的唯一发起方;B2/B3/B4 零相互直调 |
| 2 | 结算触发 | Waiting 相位编排点;不依赖事件到达序 |
| 3 | facts 缓冲 | 按轮缓冲事件、轮末统一转化;事实→授予恰一次(B4 幂等仅兜底) |
| 4 | 段序骨架 | 七段全序(见上图);修订走 GDD 流程,非调参 |
| 5 | 授予段 | 三批转化,见下两表 |
| 6 | 伏击转化 | `ambush_grant_plan(mines_r, cap)`;前 granted_r 颗逐颗授予;池 L side 共享、dur=1 轮末清零 |
| 7 | 道具窗口 | B4 `query_inventory` 投影 + B1 守卫预判;至多一件;选择序列入回放 |
| 8 | 增益/减益 | 读值→语义映射→池合成(F2);明细按授予流水逐条标注来源 |
| 9 | 道具段 | 伤害恒定表值不吃修正;满血守卫拒治疗;零效果判定读 B2 存活集 |
| 10 | 战斗段 | 主角先手攻击 + 逐敌循环(调用序钉死);死亡即不动手;hero 死亡短路 |
| 11 | 衰减段 | 恰一次、恒执行、含末轮 |
| 12 | 判定段 | hero 先判(防御性优先级);胜负明细行 |
| 13 | 高光节点 | #2 完美排雷=清图奖励双份兑付;#3 标中旗=行字段 highlight(见枚举表) |
| 14 | 明细流水协议 | 13 类行封闭枚举 + 公共字段(见枚举表)——D1/B5/D4 的统一数据源契约 |
| 15 | 可回放性 | 零随机 + 确定性输入 + 表值快照 ⇒ 同种子同输入步骤流逐行相同 |
| 16 | 数值承载 | 全部数值在 D2 SettlementTable;B1 代码零数值字面量;战斗中热重载被门拒绝 |
### 授予段:三批转化
| 批 | 输入 | 转化 | 产出 |
|---|---|---|---|
| cell_revealed | `kind=mine` | 调 `ambush_grant_plan`,事件规范序逐颗 `apply_effect(ambush)` | 伏击池 L;溢出产"溢出未生效"行 |
| cell_revealed | `kind=safe ∧ reward_eligible` | 按 category 分流(见下表) | 每格受理恰一次 |
| flag_judged | `hit=true` 且资格未消费 | `apply_effect(weaken)` + 资格消费 | 标中旗行(highlight=`flag_hit`) |
| flag_judged | `hit=true` 且资格已消费 | 去重跳过(每雷实例一次) | 零新增行 |
| flag_judged | `hit=false` | 零兑付 | "标旗未中"零值行(highlight=`perfect_broken`) |
| cleared 轮 | — | `grant_clear()` 恰一次;完美板(零误标 ∧ ≥1 标中)追加第二份同身份兑付 | 清图奖励行;完美高光行 |
### 授予段:奖励分流
| category | 兑付方式 | 拒绝语义 |
|---|---|---|
| buff | `apply_effect`(入池,结算段生效) | 满层 → "奖励未生效"行,无折算 |
| instant_aoe | 全体存活敌各 `power` 点(逐个 apply_damage) | 当场兑付,不进库存 |
| instant_heal | 主角回复 `power`(clamp) | 满血 → "奖励未生效"行 |
| damage_item / heal_pack | `stock()` 入关卡域库存 | 窗口选用时兑付 |
## 枚举
### 明细行类型(封闭枚举,13 类)
| 行类型 | 特有字段 | 产出点 | 说明 |
|---|---|---|---|
| 效果行 | `effect_id` `pool_value` | 增益/减益段 | value=该次授予贡献值;pool_value=池合成值(防 −130%×2 行误读为 −260%) |
| 伤害行 | `target` | 道具段 / 战斗段 | 分量二元组 + 减伤终值 + 击杀标记 |
| 治疗行 | — | 道具段 | clamp 后真实回复量 |
| 道具行 | `target` | 授予段 / 道具段 | 入库 / 生效 / 语境注记 |
| 奖励未生效行 | 聚合计数 | 授予段 | 满层拒绝、满血、雾板等合法例外 |
| 已消耗未生效行 | — | 道具段 | 施加时已无存活敌(Used 不可逆) |
| 使用被拒行 | — | 道具段 | 满血治疗包守卫 |
| 溢出未生效行 | — | 授予段 | 伏击/奖励族同名协议 |
| 标旗未中行 | highlight=`perfect_broken` | 授予段 | 零值归因行;每雷实例一次去重 |
| 蓄力行 | — | 战斗段 | charge 拍零作用 |
| 衰减行 | — | 衰减段 | 移除数 k(呈现聚合归 D1) |
| 判定行 | — | 判定段 | 胜负 / 继续 |
| 高光行 | — | 授予段(清图) | 完美排雷;value=实际有效兑付,禁记名义值 |
**公共字段**(13 类全必有):`type` `source_class` `origin_cell`(板级行可空)`round_index` `display_name` `value` `highlight?`
**断言**:无来源行 = 失败(AC-42)。
### source_class(封闭枚举)
| 值 | 来源 |
|---|---|
| safe_cell / flag_hit / mine_hit / clear_default | B3 既有四源 |
| 道具/判定扩展 | B4 交付语义 |
| enemy_action | 敌方行动行(伤害/蓄力) |
| flag_miss | 标旗未中零值行 |
| hero_attack | 主角先手攻击伤害行 |
新增值 = 接口漂移,须同步 `source_label_map` 键集。
### highlight(可空枚举)
| 值 | 含义 |
|---|---|
| `flag_hit` | 标中旗削弱兑付行强调 |
| `clear_reward_h2` | 清图奖励行强调 |
| `perfect_broken` | 本板完美谓词已破的归因锚 |
## 数值结论与推导
> 章节纪律:**结论先行**(加粗一行),下接「推导」小标题给公式与验算表。F1 对照表 / F3 伤害合成迁移时同模式展开(Variables 表 + Example 一行)。
### F0 当量归一口径(weaken 锚裁决)
**结论**:采用"每结算瞬时当量"口径;m_w 值域 [60, 85]、默认 −65;地板交叉层数 = 2;B3/B4 零接口修订(值变更走 registry 回写)。
#### 推导
- **同分母性**:weaken 与 defense_up 作用于同一伤害流,"严格大于"在百分点读法与 HP 读法下等价,锚判定无量纲歧义。
- **机制同构**:B3 本就按结算逐次兑付,瞬时口径是容器原生口径;"每 AP 总暴露"需跨结算累计账本,与已锁的"单结算自然边界"冲突。
- **schema 禁止**:总暴露口径需 m_w > 100,越出 percent ∈ [−100, 100] 域,改域 = 三侧换算连锁,成本不成比例。
### F2 乘区合成
**结论**:池内加算 → 每池独立 clamp [−100, +100] → 池间乘算 → floor 单一取整;免伤轮(D'=0)是合法设计态,产零值伤害行、不调 apply_damage。
#### 公式
```
P_pool = Σ(同池实例 L×m) 池内加算
P_pool ← clamp(P_pool, −100, +100) 每池独立地板
M_pool = 1 + P_pool ÷ 100 域 [0, 2]
D' = floor(D_raw × M_hero × M_enemy) 池间乘算,单一取整
```
例:D_raw=20、weaken L=2 → P=−130 → clamp −100 → M=0 → D'=0(零值伤害行)。
### F4 条款③挖掘风险不等式
**结论**:默认行值通过(锚行口径 L1≈2.0× / L2≈2.6×;跨行期望口径 1.2× / 1.5×,二元结论一致);满配 unit_count=3 破线 → 登记 C3 调参约束。actuals p10 交付后强制重跑。
#### 公式与验算
```
主式:P(安全) × V_safe > P(雷) × V_mine (决策单位=单格挖掘;评估点=残余盲猜端最坏点)
P(雷) = |M| ÷ (|M| + (1−ι)×|S|) (残余盲猜端上界)
V_safe = D_ref(锚行满寿命恒等式);V_mine = unit_count × m_amb
域守卫:(1−ι)×|S| < 1 ⇒ 主式不评估,信息端平凡腿接管
```
| 板形 | P(雷) | 左臂 | 右臂 | 裕度 | 判定 |
|---|---|---|---|---|---|
| L1(\|M\|=9,\|S\|=91,ι=0.95) | 0.664 | 4.03 | 1.99 | ≈2.0× | ✓ |
| L2(\|M\|=16,\|S\|=128,ι=0.92) | 0.610 | 4.68 | 1.83 | ≈2.6× | ✓ |
| 满配(unit_count=3,V_mine=9) | 0.664 | 4.03 | 5.98 | <1 | ✗ 破线 → C3 约束 |
注:C3 不得以锚行读数(2.0×/2.6×)作为 unit_count=2 的放行依据。
### F5 条款⑤清图支配性
**结论**:**未闭合**(挖穿残余池计价,两态为负)→ C3/B4 约束包:C 量级上调,或裁"清图非严格支配"为设计态,二选一归 C3。
#### 公式
```
Δ_clear = [R_res + C_eff] − [X_res + Δr × s_ref] (主判式,≥0 为闭合)
E[踩雷] = |M| × n_s ÷ (n_s + 1) (挖穿残余池期望,均匀交错模型)
```
### 边界参数总表
| 参数 | 边界 | 默认 | 出处 |
|---|---|---|---|
| percent 池 clamp | [−100, +100] pp,每池独立收口 | — | F2 |
| 池乘数域 | [0, 2](= 1 + pp/100) | — | F2 |
| m_w(weaken 行值) | [60, 85] | −65 | F0 裁决(瞬时当量口径) |
| 地板交叉层数 | ⌈100/m_w⌉ = 2(值域内恒 2) | — | F0 |
| P_perfect 载体域 | **{100, 200}**,域外加载致命 | 200(×2 双份交付) | Core Rule 13 |
| D_ref(当量参考敞口) | [1, 999] | 12 | SettlementTable |
| HeroTable.atk | [1, 999],0 加载拒绝 | 6 | 2026-09-11 拍板 |
| 伤害 D' | 整数 [0, ∞),零负值分支 | — | F3 |
| D' = 0 | **不调** apply_damage,产零值伤害行 | — | 负值分支禁令 |
| 取整 | floor,单一规则(结构性,非 knob) | — | F2 |
| 溢杀 | 丢弃,不转移、无负 hp 态 | — | F3 |
| 治疗 | hp' = min(hp + power, max_hp) | — | F3 |
### SettlementTable schema(单行全局,B1 回填 owner)
| 字段 | 类型/域 | 默认 | knob |
|---|---|---|---|
| equivalence_ref_damage(D_ref) | int [1,999] | 12 | ✓(变更触发全对账重跑) |
| p_perfect | percent {100, 200} | 200 | ✓ |
| effect_pool_map | effect_id → {hero_offense, hero_defense, enemy_output, flat_attach} | — | ✗ |
| rounding_direction | floor(结构性) | floor | ✗ |
| pool_clamp_lo / pool_clamp_hi | int | −100 / +100 | ✗ |
| source_label_map | 键集 = source_class 全集 | — | 随接口漂移 |
## 状态
| 状态 | 进入条件 | 行为/出口 |
|---|---|---|
| Uninit | 冷启动 / 清理完成 | 唯一出口 `begin_battle` |
| BattleSetup | `begin_battle` 受理 | 战斗开始序列;任一步拒绝 = fail-fast 上抛 |
| RoundActive | `notify_round_start` | 不干预挖掘,只缓冲事件流 |
| RoundWaiting | 轮次结束事务达成 | 执行七段结算;窗口段为唯一玩家输入点 |
| BattleOver | 判定段产胜负 | 战斗结束序列 → Uninit |
不变式:同时刻至多一个结算事务在飞;段序恒全序(短路是段内规则非跳段);跨系统调用集中在 B1。
## 边界情况
| 条件 | 行为 | 依据 |
|---|---|---|
| 末图清图即胜利 | 清图奖励先兑付 → 窗口可选用 → 战斗段空转 → 衰减 → 判胜 | B4 E15 |
| 战斗段 hero hp=0 | 立即短路,剩余敌不作用不产行 | 用户拍板 |
| 判定时敌我双 hp=0 | 结构不可达;防御规则 hero 先判 | Core Rule 12 |
| 合成后 D'=0 | 不调 apply_damage,产零值伤害行 | 负值分支禁令 |
| 伤害溢出 | 溢出丢弃;行 value=D'、击杀布尔,不记溢出量 | F3 |
| charge 拍本轮踩雷 | 伏击授予照常;战斗段零伤害,池 dur=1 蒸发 | B2 EC8 |
| 全体存活敌同拍 charge | N 行蓄力行、零伤害——合法状态 | B2 EC |
| 伏击池 L=0 时敌攻击 | D_raw=纯基线 atk,自然读值非缺失分支 | B2 F2 |
| 刀施加时已无存活敌 | 照常消耗 + "已消耗未生效"行 | B4 E10 |
| 窗口打开时库存空 | 跳过合法;D1 可不弹窗;段序零停顿 | B4 E8 |
| 挖掘期刷新 RAP 不足 | `request_refresh` 返回 false,原样上抛拒绝 | A3 EC13 |
| 同轮多次刷新(cap 内) | 每次独立走换图全序,取新 scope | A3 EC15 |
| 清图槽 buff 且满层 | 零兑付 + "奖励未生效"行;完美高光降级不发 | B4 E11 |
| 完美谓词在刷新图上 | 刷新图无兑付点,不触发;flag 计数随 install 重置 | Core Rule 13 |
| 板内既有标中又有误标 | 完美不成立;首个误标产"标旗未中"行(perfect_broken) | 单档完美,两档扩展被否 |
| 多敌同结算攻击 | 行主序逐敌、共享 L;任一作用后 hero 死 → 短路 | Core Rule 10 |
| battle_over 清理中被拒 | 诊断 + 幂等兜底;清理序列必须完成 | 防半清理态泄漏 |
| 战斗中热重载请求 | 门已置位 → D2 拒绝返回 false | D2 EC8 |
## 依赖
**上游**(除 C1/C2 外全部 Approved——B1 是首个上游全就绪的系统):
| 系统 | 性质 | 接口要点 |
|---|---|---|
| D2 | hard | SettlementTable(B1 回填)+ `set_reload_gate` 唯一调用方 |
| A3 | hard | 五条款下游契约(B1 为①②③⑤闭合 owner)+ 结算回发 + `last_round_end` |
| A2 | hard(订阅) | 三事件流 + `install_board`/`retire_board` + Waiting 观测量 |
| B2 / B3 / B4 | hard | 全调用面 + 各自义务清单(义务明细在 registry,不在本文) |
| A1 | 间接 hard | `generate` 换图 + actuals p10 对账输入 |
| C1/C2 | provisional(未设计) | encounter 上下文由 `begin_battle` 入参封装隔离 |
**下游**:D1(明细流水=统一数据源契约,呈现义务台账在 registry)· B5(步骤流=动画回放脚本源)· D4/D5(音频/教学事件源)· C3(对账结论=调参约束)。
## 版本历史
| 版本 | 日期 | 改动 |
|---|---|---|
| lean-sample | 2026-09-13 | 格式重排样例:修订注记出正文→版本表;规则/枚举/边界/边界情况转表格;流程转字符图。语义与 b1-settlement.md Rev 1 对齐,未改任何现行规则 |
| Rev 1 | 2026-09-10 | design-review 8 项 blocking 核销(完美排雷双份载体、条款⑤计价模型重推、流水协议分层、hit=false 零值行、P_perfect 换算成文等)——明细见 review log |
| v1 | 2026-09-10 | 一次会话定稿(F0–F5 + 43 条 AC + 23 条上游义务落位) |
| D4 修订 | 2026-09-12 | 刷新决策前移挖掘期:新增"挖掘期刷新"出口行,作废原 Waiting 期代理调用 |
| 2026-09-11 拍板批 | 2026-09-11 | 主角先手攻击(hero_attack 来源)、两级奖励、窗口单件制、库存关内延续 |
@@ -0,0 +1,45 @@
# 概念原型报告:扫雷 × 自动战斗
- **原型位置**:`prototypes/minesweeper-battle-concept/`(Godot 4.x,Engine 路径)
- **日期**:2026-09-06 · 迭代 v1 → v3
- **可证伪假设**:如果玩家通过扫雷决策为自动战斗获取道具,他们会感受到"每一步排雷都在影响战斗结果"的策略联动感。(验证信号:扫雷阶段主动规划目标;主动想进入下一轮)
## 假设判定:CONFIRMED(核心) / 部分确认(表现层)
用户(唯一测试者)在 v2 后反馈:"**目前整体轮次的玩法是没有问题的**",且确认小人边缘探索"更像地牢探险,氛围上 OK"。三层联动(挖雷→攒道具→结算兑现)作为循环骨架被接受并持续投入迭代——没有出现"战斗是过场"的否定信号。表现层(逐行结算文字)被判定"无所谓"(正式版将替换为战斗动画),兑现的**情绪强化**仍有待战斗动画验证。
## 迭代记录
| 版本 | 内容 | 用户反馈 |
|---|---|---|
| v1 | 全图点击挖雷,AP 12,逐格即时奖励 | AP 太多;想要小人控制;开/未开格难分辨;结算应统一画面而非即时生效 |
| v2 | 小人控制(参考 MS Minesweeper Adventure 模式)、初始 3×3 安全区、AP 8、统一战斗结算画面、色块区分 | 地牢氛围 OK;结算画面无所谓(正式版上战斗动画);**整体轮次玩法没有问题** |
| v3 | 行动经济统一(插旗 1AP+1旗)、标雷判定(标中+5 拆弹奖励/标错无惩罚)、修延续图旗子重置 bug | 待终验 |
## 最好时刻
小人控制上线后循环"活"了:从"选格子"变成"走位规划",挖/旗被锁定在小人相邻——位置本身成为资源(用户认可地牢探险感)。
## 最糟时刻 / 已修复问题
- v1 的 12 AP 节奏拖沓 → v2 降到 8 并引入走位成本
- v1 奖励即时生效导致"点一格就像结算一次" → v2 改为统一入库、轮末结算
- v3 前的 bug:延续图上旗子未随轮次重置(旗子资源凭空变多)→ 已修
## 意外发现
- 标雷判定把"插旗"从记账动作变成了**赌注式动作**——风险与收益同源原则(P3)的雏形在测试中自然浮现
- 用户主动要求的"小人控制"与 Microsoft Minesweeper Adventure 模式高度吻合,验证了参考方向的合理性
## 遗留验证点(下阶段处理,不阻塞 PROCEED)
1. 标雷"赌注式动作"的实际使用率与手感(v3 终验)
2. 标错惩罚是否需要(候选方案已登记,A2 GDD 前用小补丁实测)
3. 停手折算比例(×2)的数值合理性(A3 GDD 定稿)
4. 兑现的情绪强化(战斗动画)——垂直切片的 B5 验证
## Verdict: **PROCEED**
核心假设成立:扫雷决策与战斗结果的联动被测试者确认,循环骨架定稿并全部落入系统索引。下一步进入正式系统设计(GDD),用原型结论作为 Tuning Knobs 素材。
**PIVOT 记录**:无 PIVOT 链。原型代码不进生产(生产实现按 GDD 从零写,原型仅作参数与规则参考)。
+64
View File
@@ -0,0 +1,64 @@
# Architecture Registry — Dungeon Sweeper
# 生成:2026-09-12(/architecture-decision solo 批:ADR-0001~0004;用户授权代决)
# 规则:只增不改;立场变更 = 旧条目标 status: superseded_by + 新增条目(永改既有条目)
# 设计层立场(状态归属/接口契约/锚验收)登记在 design/registry/entities.yaml——本文件只登记实现级架构立场
interfaces:
- name: a2_event_surface
adr: ADR-0001
signals: [cell_revealed, flag_judged, round_end_board]
note: GDD 概念名 round_end 的 A2 实现实名 = round_end_board;A3 直发 = round_end_stopped(payload 同构)
- name: b1_settlement_trigger
adr: ADR-0001
contract: B1 订阅 A3 相位→Waiting 触发结算;只读 last_round_end + 相位观测量;不依赖事件到达序
- name: presentation_subscription_rule
adr: ADR-0001
contract: 呈现层永不直接订阅 A2/A3——只订 B1 步骤流 / level_runner(切片缺陷②教训固化)
api_decisions:
- name: renderer
adr: ADR-0002
decision: gl_compatibility(Forward+ 否决——D3D12 新驱动线降险;B5 出现 HDR 2D 需求时复议)
- name: window_base
adr: ADR-0002
decision: 1280×800 基座 + stretch canvas_items + aspect expand(全部键显式落盘,防引擎默认漂移)
- name: autoload_set
adr: ADR-0003
decision: 仅 {ConfigDB, RngService}(定名锁定);战斗编排器等核心类由组合根按局实例化,非 autoload
- name: board_rendering
adr: ADR-0003
decision: MVP 沿用切片 GridContainer + 逐格控件形态(探针耦合事实);_draw() 迁移 = D1 正式化候选工作项(含三探针改造 + push_input 端到端探针 + 命中测试自建)
- name: cjk_font
adr: ADR-0003
decision: CJK 字体随包发行并设 theme 默认字体(运行时默认字体无 CJK 字形)——D1 正式化硬性前置 + 导出 checklist 项
- name: test_carrier
adr: ADR-0004
decision: 双载体(--headless --script 逻辑冒烟 + headless 场景探针)+ 静态扫描域 S1–S8 + CI 外部 wall-clock 超时;gdUnit4 deferred(D2 OQ1 关闭形态)
- name: save_contract
adr: ADR-0005
decision: SCHEMA_VERSION 比较逻辑归 D3(存档版本 > 当前 = 拒读);RNG 快照 = master_seed + 各流 scope 计数器 + 意图/窗口选择序列,切出须在 scope 事件边界外(无在飞 open_stream 实例——B1 编排保证)
forbidden_patterns:
- pattern: autoload_global_event_bus
adr: ADR-0001
detail: 否决中心事件总线——组合根直连 signal 接线
- pattern: lambda_capture_self_cross_lifetime
adr: ADR-0001
detail: core↔core 信号连接只许方法 Callable;发射者禁持有订阅者反向引用(防循环引用/生命周期延长)
- pattern: bare_autoload_global_identifier_in_core
adr: ADR-0004
detail: core/ 禁裸引用 ConfigDB/RngService 全局标识符(--script 模式不注册——parse error;构造注入 only)
- pattern: global_rand_functions_in_gameplay
adr: ADR-0004
detail: randi()/randf()/randf_range() 与 randomize() 同禁(全局 RNG 绕开 RngService——D2 Rule 5 补全)
- pattern: core_extends_control_or_tscn_preload
adr: ADR-0004
detail: core/ 禁 extends Control/Node2D、禁 .tscn preload(D2 Rule 7)
- pattern: second_caller_of_battle_domain_apis
adr: ADR-0004
detail: B2/B3/B4 战斗域 API 唯一调用方 = B1;A2/B3/B4 零相互直调(静态扫描 S7——B1 AC-43)
- name: hero_override_parameter_passing
adr: ADR-0009(候选——切片机制正式化批)
decision: 主角加成值经 encounter 显式参数传入(begin_battle 增 hero_atk/hero_max_hp 字段;B2.spawn 增 atk_override/max_hp_override 参数,-1 = 表值兜底)——db.hero 表值运行期只读(切片原表写通道 _apply_hero_override/runner 写表废除)
note: 2026-09-13 E4 收口;接口漂移 = B2.spawn 签名 +2 参数、B1 encounter +2 字段(正式侧 B1/B2 GDD 修订随 ADR-0009 批);ui_tune_probe ⑦⑧ 为表不可变 + 单次加成的回归断言载体