feat(迭代27 T6+T7): 波五b 卫生件包+文档同步闸——对拍全同
T6 卫生件(P2 组收口):
- 死代码 13 函数删除(审计 16 处复核=ui_kit:486 实读现役不删,追认单#14)+FeatsEngine
整文件退役(class_name 注销)
- 字符串 Callable×10 位→方法引用形态(编译期方法存在性校验;语法实证 METHOD_REF=true)
- 状态机 enum 化: adventure State(外部 String 契约 getter 词表逐位一致+外部纯读实证)/
standee HeroState(register/set String 形参零变化+probe 面恒等)
- ConfigDB _fatal 退出归根(核心层去 quit/crash→_fatal_flag,决策归组合根 fail-fast 通道)
+resolver 诊断/数据通道全面 Callable 化(ConfigDb↔Resolver 类型环断根)
T7 文档同步闸:
- 实现报告 design/qa/iter27-实现报告-2026-10-14.md(五波+闸表+追认单十五项+反哺点两条+目检五件)
- 06 迭代 27 条销号+GDD 反哺点两条新条;07 ㉖ 目检节+v1.0 版本行;roadmap ✅ 换代
- 审计报告本体按退役规则 git rm(吸收即死;修正计数由卡片承载);卡片来源行改指路
闸: 对拍三变体全同(第五跑)+冒烟 1081/0+run_all 27 套+probe click+render golden+static_scan 全绿
This commit is contained in:
1 parent
b605022001
commit
eea345882b
24 files changed
+200
-309
No files matched your search
@@ -593,13 +593,18 @@
|
||||
|
||||
**状态**:备忘(不阻塞,不排期)
|
||||
|
||||
|
||||
---
|
||||
|
||||
#### 代码架构技术债修复批——需求卡片已写(2026-10-14 登记)
|
||||
#### 迭代 27 代码架构技术债修复批——GDD 反哺点两条(2026-10-14 随批登记,待用户逐点裁决另批落文)
|
||||
|
||||
**现状**:[代码架构与实现质量审计报告-2026-10-14](../research/代码架构与实现质量审计报告-2026-10-14.md)(双席审计,基线 97de02c;同日第三方逐条复核:主体结论全部成立,五处计数级瑕疵已修正落文)确诊 2 条 P0(全产品单场景/局态手工复位清单)+ 6 条 P1(_settle 巨函数 259 行/刷新双账/GP 影子账/共享可变字典跨三层/组合根不可测/类型闸缺位)+ 7 组 P2 卫生件。用户已裁:全部技术债修复允许放行单一大迭代(12-14 个工作日,2026-10-14 裁决记录)。需求卡片=[需求卡片-代码架构技术债修复批-2026-10-14](../research/需求卡片-代码架构技术债修复批-2026-10-14.md)(**v1.2**,五波:场景拆分+局生命周期 → _settle 拆段 → 账本收口 → 组合根抽取+模态内聚 → 类型闸+卫生件;核心验收=重构前后同种子完整局输出逐位一致)。
|
||||
**现状**:五波全量入库(单会话交付;逐位一致对拍三变体五跑全同;实现报告=design/qa/iter27-实现报告-2026-10-14.md)。实现与设计权威文档的差异/缺口如下,经裁决后另批落文——**机械面随批已动的只有本条与 07/roadmap**。
|
||||
|
||||
**归属**:工程债/重构批(core/presentation 结构面;零行为变更契约)
|
||||
**归属**:工程债/重构批收口反哺(不阻塞,不排期)
|
||||
|
||||
**状态**:**🔄 U0 已开工(2026-10-14 用户令编入迭代 27 卡①+同日 /goal+iter 27 发令)**——卡片 v1.2 三点已裁全按推荐案(①SaveManager/MetaProgression=第三个 autoload/②Ledger=单类持四账/③_settle=审计五段),零待裁点;批入库后本条销号
|
||||
| # | 文档 | 反哺点 |
|
||||
|---|---|---|
|
||||
| 1 | design/dev/architecture/architecture.md + ADR 系列 | 场景分层(三屏壳+组合根句柄面)/会话生命周期(RunScope 物化)/结算五段 Segment(core/settlement/)/RunLedger 四账所有权/ModalFlow 模态编排层与互斥域 tags 协议——现行陈述滞后于实态 |
|
||||
| 2 | design/dev/code-conventions.md | §4 语言纪律机器化(S9+audit_type_hints.py 三规则);`:= {}` 推断形态豁免口径;`# type-hint: ignore` 行级白名单与 `# ADR-0007-exempt` S1/S2 标记豁免通道;--script 模式禁裸 autoload 标识符纪律(新);Variant 参数化口径与元素精化后续 |
|
||||
|
||||
**状态**:备忘(反哺点待裁决;代拍板追认单十五项见实现报告 §三;残留人闸=07 ㉖ 五件登记不阻塞)
|
||||
@@ -264,3 +264,17 @@
|
||||
| v0.7 | 2026-10-13 | 新增 ㉓ 敌人表内容修批三观测目检节(迭代 24 卡①随批登记:新招可见性/甲型体感/第一关节奏——登记不阻塞按 2026-10-12 真人检测立规) |
|
||||
| v0.8 | 2026-10-13 | 新增 ㉔ UI 全局主题批全屏巡检目检节(迭代 25 卡①随批登记:引擎默认灰清零巡检/音量滑轨两段可辨/专项观察点二(滑轨柄抢焦点·滚动条槽可见性)/预盖件无实役注记——登记不阻塞;能力验证半=冒烟 V1-V6) |
|
||||
| v0.9 | 2026-10-14 | 新增 ㉕ UI 交互与观感批逐屏巡检目检节(迭代 26 卡①随批登记:按钮五态反馈/键盘焦点环/全局 Nearest 巡检(含暗角与渐变白名单判据)/布局均衡(商店居中+营地四栏等高)/诊断钮清零——登记不阻塞;能力验证半=冒烟 V1-V6+T4 结构断言) |
|
||||
| v1.0 | 2026-10-14 | 新增 ㉖ 代码架构技术债修复批全流程走查目检节(迭代 27 卡①随批登记:全流程观感零变化走查/续玩断点恢复/调试浮窗对局中可开不锁棋盘〔:407-408 事故回归〕/刷新余量显示一致/DS_DEBUG 启动浮窗+两屏角标——登记不阻塞;能力验证半=冒烟 V1-V9+parity 三变体逐位一致对拍五跑全同) |
|
||||
|
||||
|
||||
## ㉖ 代码架构技术债修复批——全流程走查(迭代 27 卡①随批登记;能力验证半=冒烟 V1-V9+parity 三变体逐位一致对拍五跑全同)
|
||||
|
||||
> 场景拆分+会话物化+战斗域重构+账本收口+模态协议内聚后,玩家可见面唯一验收=观感零变化。登记不阻塞(2026-10-12 真人检测立规)。
|
||||
|
||||
| # | 目检项 | 判据 |
|
||||
|---|---|---|
|
||||
| 1 | 全流程走查 | 开始菜单→营地四柜台→开新冒险→选路→战斗(挖/旗/刷新/停手)→三选一→商店→Boss→终局——逐屏观感与重构前一致(演出时序/文案/布局零漂移) |
|
||||
| 2 | 续玩断点恢复 | 停点退出→「继续上局」文案与恢复落点正确(run-scope 物化后断点链回归) |
|
||||
| 3 | 调试浮窗对局中可开不锁棋盘 | 对局中开浮窗→棋盘可继续操作(:407-408 永久锁死事故回归——互斥域 tags 化后钉面) |
|
||||
| 4 | 刷新余量显示 | 刷新受理后 HUD 余量递减且与受理次数一致(双账删副本后 HUD 单源读快照) |
|
||||
| 5 | DS_DEBUG=1 启动 | 浮窗启动即开+两屏角标点亮可点(同步面随 ModalFlow 迁移后行为钉面) |
|
||||
@@ -0,0 +1,93 @@
|
||||
# 迭代 27 实现报告——代码架构技术债修复批(五波全量入库)
|
||||
|
||||
- 日期:2026-10-14(单会话 /goal+iter U0 交付,worktree g-plan2-iter27-techdebt 分支 iter27-techdebt-20261014)
|
||||
- 需求卡片:`design/research/需求卡片-代码架构技术债修复批-2026-10-14.md`(v1.2——三点待裁 2026-10-14 用户三裁全按推荐案:①SaveManager/MetaProgression=第三个 autoload/②Ledger=单类持四账/③_settle=审计五段)
|
||||
- 来源审计:代码架构与实现质量审计报告-2026-10-14(双席基线 97de02c;**本批收口时按退役规则 git rm——吸收即死,结论迁本报告与卡片**)
|
||||
- 核心验收(V1):**重构前后同种子完整局输出逐位一致**——parity_anchor 三变体(base/attune/shop)×40 局×RUNSUM+JSONL 剔 ts 双面哈希对拍,**五波出口五跑全同**(锚冻结于 T0,种子面 71000/72000/73000)
|
||||
|
||||
## 一、五波交付
|
||||
|
||||
### 波一 场景拆分+局生命周期物化(P0-1/P0-2,7a0d57d)
|
||||
|
||||
- 三屏壳场景 `presentation/scenes/`:menu_screen/camp_screen/adventure_screen(内含 level_map/battle 两容器)——视图代码原样构建(装配器/视图类零 .tscn 化,契约 2);组合根句柄全部保留(探针挂载假设 main.X 一级路径零迁移);树序=屏壳在前全模态之下(视觉共存对逐对验算:legend/battle、debug/level_screen、shop/level_screen 等全部保序)。
|
||||
- 会话物化 `run_scope.gd`:adventure/runner/settlement/局态旗/账本随会话节点承载;`_begin_session` 建会话(_ready 即建闲时态=永非 null)、终局整节点 queue_free()——`_reset_run_scope` 三项+`_on_battle_end_continue` 置空四件手工清单消亡。
|
||||
- SaveManager/MetaProgression 升格 autoload(裁点①甲;类名加 Core 后缀沿 RngService 先例);探针隔离改 attach_path 原地重置(set_master_seed 先例);**发现并修复**:屏壳根全屏 Control 默认 STOP 吃掉下层模态鼠标输入(ui_input 实证)——三屏壳根 mouse_filter=IGNORE+V2 回归闸。
|
||||
- V2 屏壳独立实例化 11 断言+V3 两连局复位 11 断言进 smoke。
|
||||
|
||||
### 波二 _settle 五段拆 Segment(P1-1,26301ba)
|
||||
|
||||
- `core/settlement/` 五段类:GrantSegment(授予段体+旗判随段迁入+counter_add 五位/grant_material 三位分支单点化)/AuraSegment/CombatSegment/DecaySegment/VerdictSegment(返回裁定,终局早退语义留宿主);编排器 1725→1325 行退为段序编排+行发射原语单点。
|
||||
- 姊妹病灶:`_resolve_hero_attack` 148 行拆四步(ctx 命中面→基值装配→掷点兑现→交付),ctx/redemption 字典穿线算序逐字保留。
|
||||
- V4 settle_segments_test 16 断言进 run_all。
|
||||
|
||||
### 波三 账本收口(P1-2/P1-3/P1-4,6fd7d78)
|
||||
|
||||
- `core/run_ledger.gd` RunLedger 单类持四账(裁点②甲):attune_charges/vision_counter/adventure_counters/bonus;战斗侧只拿 read/append 原语;AR 持账→LR set_run_ledger→enc 单键下传;编排器三裸引用成员退役;调试/单场缺省新账=零扰动面(vision_counter 缺省空=不计,原 enc 缺键守卫语义保留)。
|
||||
- 刷新双账:main 副本删除;presentation_snapshot 成文面升键 refresh_used(can_refresh 邻位)——HUD 余量/遥询单源读快照;V5 快照一致性断言×3。
|
||||
- GP 影子账:summary 增 gp_final 键(close_wallet 清账前快照);gp_shadow_ledger.gd 全件退役;终局面板 GP 行取数=summary 键;ui_probe 断言换代。
|
||||
|
||||
### 波四 组合根可测化+模态协议内聚(P1-5/P2-7,8b9e556)
|
||||
|
||||
- **重估结论(卡片 T4 前置义务)**:场景拆分落地后,模式状态机已随 RunScope 物化、屏构建已随屏壳迁出——抽取面收敛为**模态编排域**:`modal_flow.gd` ModalFlow 纯逻辑类(依赖仅 ModalStack+查询 Callable,审计处方形态)——开合编排(挂起兜底/排播排空/遮挡记账/开合同步)/输入锁谓词(三例外注入)/双形制角标谓词。
|
||||
- **V6 测试抓出并修正一处真分歧**:挂起兜底递归后误加 return(原 main 语义=先结挂起后继续开本层两拍都走)——单测缝的结构价值实证。
|
||||
- ModalStack 互斥域随层登记:register(m, tags)+TAG_NON_LOCKING/TAG_SCREEN_STATE 封闭词表+has_open_excluding_tags 组查询;原调用点排除式拼装(:404-409 输入锁等五处)退役;main._modals=flow.stack(ui_struct _list 断言缝保留)。
|
||||
- 控制器构造收拢 context:curio 16 参→CurioFlowContext/camp 13 参→CampFlowContext(字段逐一同名,控制器可独立实例化)。
|
||||
|
||||
### 波五 类型闸+卫生件(P1-6/P2 组,b605022+T6 笔)
|
||||
|
||||
- 类型闸:`tools/audit_type_hints.py` 机器闸(R1 无类型容器注解/R2 有值返回缺类型/R3 参数缺类型+行级白名单通道);368 处容器注解机械参数化(Array[Variant]/Dictionary[Variant, Variant] 零行为面)、13 处参数真类型;project.godot 拉起 untyped_declaration=1;static_scan 新 S9 规则。
|
||||
- 卫生件:死代码 13 函数删除(审计 16 处复核后其中 ui_kit:486 一处经实读为现役非死码,见追认单)+FeatsEngine 整文件退役;字符串 Callable×10 位换方法引用形态(编译期方法存在性校验);冒险状态机/standee 主角三态 enum 化(外部 String 契约逐位一致);ConfigDB `_fatal` 退出归根(核心层去 quit/crash,置 `_fatal_flag`,退出决策归组合根既有 fail-fast 通道)+resolver 诊断/数据通道全面 Callable 化(ConfigDb↔Resolver 类型环断根)。
|
||||
|
||||
## 二、闸记录(每波出口+批末)
|
||||
|
||||
| 闸 | 基线(T0 冻结) | 波一 | 波二 | 波三 | 波四 | 波五 |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 逐位一致对拍(V1 核心) | 锚冻结 | ✓ 全同 | ✓ 全同 | ✓ 全同 | ✓ 全同 | ✓ 全同 |
|
||||
| 冒烟 | 1055/0 | 1077/0 | 1077/0 | 1079/0 | 1079/0 | 1081/0 |
|
||||
| run_all | 25 套 | 25 | 26 | 26 | 27 | 27 |
|
||||
| probe_gate --click | 绿 | 绿 | 绿 | 绿 | 绿 | 绿 |
|
||||
| render_gate golden | 0.00% | 0.00% | 0.00% | 全绿 | 全绿 | 全绿 |
|
||||
| static_scan | (历史 cd 错位恒跳过) | — | — | — | — | S1/S2/S4/S9 全绿 |
|
||||
|
||||
批末(T6 后)run_all 27 套全绿+冒烟 1081/0+probe/render 全绿+对拍全同(T6 对拍见 /tmp/parity_check6.log 记录,exit 0)。
|
||||
|
||||
## 三、代拍板追认单(白名单九项执行实录+计划外决断,待用户逐项追认)
|
||||
|
||||
1. **屏场景命名/落位**(白名单①):`presentation/scenes/{menu,camp,adventure}_screen.tscn`——三屏壳与卡片三屏一一对应。
|
||||
2. **屏壳内部分层**(白名单②):adventure 屏壳内 battle_root+level_screen 平级(无同时可见态,层内先后零视觉差)。
|
||||
3. **Segment 五类命名/落位**(白名单③):`core/settlement/{grant,aura,combat,decay,verdict}_segment.gd`,类名 XxxSegment。
|
||||
4. **Ledger 命名/原语形状**(白名单④):`core/run_ledger.gd` RunLedger;原语=attune_charge_has/set/consume、vision_count_add、counters_seed_snapshot/merge_export、bonus_add_axis(各站点原语义逐字收拢)。
|
||||
5. **run-scope 物化形态**(白名单⑤):RunScope Node 挂 main;_ready 即建闲时态(永非 null——全组合根免空判);会话更替=旧节点 queue_free+新节点同拍建。
|
||||
6. **探针迁移最小改动**(白名单⑥):组合根句柄保留策略使 10 探针中 7 个零迁移、3 个仅 run_scope 路径换代;pacing 测试改 attach 隔离。
|
||||
7. **类型标注写法**(白名单⑦):368 处机械参数化取 `Array[Variant]`/`Dictionary[Variant, Variant]` 零行为面口径——**元素精化(如 Array[Dictionary])留后续批渐进**(机器闸已封住新增无类型)。
|
||||
8. **死代码删除切分**(白名单⑧):随 T6 单笔提交。
|
||||
9. **enum 命名**(白名单⑨):adventure `State`/standee `HeroState`(+_HS_NAME/_HS_VALUE 双向映射常量)。
|
||||
10. **〔计划外〕P2-2 autoload 直取降格实现**:审计处方「编译期全局名」与本仓 --script 模式编译器不解析裸 autoload 标识符**硬冲突**(run_all.gd 头注在案+pacing 实测 Parse Error)——降格为路径常量单点(AUTOLOAD_PATH_* 四常量)+T1 读视图属性;拼写风险收敛一处,类型面保留。
|
||||
11. **〔计划外〕board_generator 四 db 参白名单**:generate/_attempt/legality/_finalize 的 db 参保持鸭子型(测量面 _BoardRowStub 冒烟夹具注入,typed 参拒 stub)——`# type-hint: ignore` 显式白名单通道首用。
|
||||
12. **〔计划外〕static_scan 历史 cd 错位修复**:9-24 布局迁移后 `dirname/..` 落 game/ 致 `game/core` 守卫恒跳过=静默空转遗产——修 `/../..` 后 S1-S4/S9 首次实跑,暴露并处置两笔存量(S1/S2 main `_seed_value` randi=ADR-0007 文档化豁免面→标记豁免通道;S9 即本批闸)。
|
||||
13. **〔计划外〕V6 测试抓出挂起兜底分歧**:ModalFlow 初版在挂起兜底后误加 return(原 main 语义两拍都走)——以原语义为准修正;该处即单测缝价值的直接实证。
|
||||
14. **〔计划外〕审计「死代码 16 处」复核为 13 处**:ui_kit.gd:486 一处实读为现役代码(审计抽样误差),不删;其余 12 函数+FeatsEngine 整文件照删。
|
||||
15. **〔计划外〕刷新遥测取数面换代**:`ux_refresh_attempt` 的 round_refresh_index 从 main 副本改读快照(P1-2 连带,载荷键与数值语义零变化)。
|
||||
|
||||
## 四、GDD 反哺点(两条,已登记 06,待用户逐点裁决另批落文)
|
||||
|
||||
| # | 文档 | 反哺点 |
|
||||
|---|---|---|
|
||||
| 1 | design/dev/architecture/architecture.md + ADR 系列 | 场景分层陈述(三屏壳+组合根句柄面);会话生命周期(RunScope 物化+_begin_session/_end_session 语义);结算五段 Segment 结构(core/settlement/);RunLedger 四账所有权模型;ModalFlow 模态编排层与互斥域 tags 协议——architecture 现行陈述均滞后于实态 |
|
||||
| 2 | design/dev/code-conventions.md | §4 语言纪律机器化(S9+audit_type_hints.py 三规则);`:= {}` 推断形态=类型推断合法面不算债的口径;`# type-hint: ignore` 行级白名单通道;`# ADR-0007-exempt` S1/S2 标记豁免通道;--script 模式禁裸 autoload 标识符纪律(新);Variant 参数化口径与元素精化后续 |
|
||||
|
||||
## 五、实机目检总清单(登记 07 ㉖——真人检测不阻塞,2026-10-12 立规)
|
||||
|
||||
1. 全流程操作观感零变化走查:开始菜单→营地(四柜台)→开新冒险→选路→战斗(挖/旗/刷新/停手)→三选一→商店→Boss→终局逐屏过一遍(场景拆分+会话物化后唯一人闸面)。
|
||||
2. 续玩断点恢复:停点退出→继续上局(断点文案/恢复落点)。
|
||||
3. 调试浮窗对局中可开不锁棋盘(:407-408 事故回归——互斥域 tags 化后行为钉面)。
|
||||
4. 刷新按钮余量显示与受理一致(双账删副本后 HUD 单源读快照)。
|
||||
5. DS_DEBUG=1 启动即开浮窗+两屏角标(同步面随 ModalFlow 迁移)。
|
||||
|
||||
## 六、残留与去向
|
||||
|
||||
- 残留人闸:07 ㉖ 五件(登记不阻塞)。
|
||||
- 代拍板追认单十五项(上表)待用户逐项追认。
|
||||
- GDD 反哺点两条(06 在册)待裁决另批落文。
|
||||
- 审计报告本体已按退役规则 git rm(吸收即死;修正后计数已由需求卡片 v1.2 承载)。
|
||||
- 元素精化(Array[Variant]→具体元素型)为类型闸后续渐进面(06 反哺点②附带)。
|
||||
@@ -1,132 +0,0 @@
|
||||
# 代码架构与实现质量审计报告(2026-10-14)
|
||||
|
||||
**审计对象**:`game/` 目录全部实现(约 114 个 GDScript 脚本 / 3.4 万行,不含 tests)
|
||||
**审计方法**:godot-master 技能库(GD-Agentic-Skills 的本地镜像,Godot 4.7+ 专家知识库)双席审计——甲席走 Analyst 工作流审架构,乙席走 Auditor 工作流审实现规范与设计模式;两席均为**只读静态实读**,未运行游戏。实现席实跑了技能库自带扫描器(信号审计 / 类型标注审计),内存类扫描器需 Godot 运行时,按只读纪律跳过并注明。
|
||||
**审计日期**:2026-10-14(基线 master 97de02c)
|
||||
**基线事实**:全项目真实游戏场景只有 1 个(`presentation/main.tscn`,其余 13 个 .tscn 全在 smoke/ 下是测试探针);节点几乎全部由 GDScript 程序化构建,产品代码 `instantiate()` 调用数为 0;autoload 仅 2 个(ConfigDB / RngService);目录分层 core / data / presentation / assets / tests / smoke。
|
||||
|
||||
---
|
||||
|
||||
## 总评
|
||||
|
||||
**core 层实现质量显著高于垂直切片平均水准,两席审计独立确认核心域健康**;问题集中在场景层与生命周期层。两个 P0 是同一根因的两面:**整条应用生命周期(菜单/营地/冒险/战斗/每局复位)压缩在 main.gd 一个 1385 行的组合根里,靠手工清单维持局间隔离**——领域侧已经长出三层编排器(AdventureRunner 跨局持久 / LevelRunner 一关一生 / BattleOrchestrator 一战一生),场景层没有任何切缝与之对应。一句话定性:**领域分层是洋葱,场景组织是石头。**
|
||||
|
||||
---
|
||||
|
||||
## P0 发现(2 条,同根)
|
||||
|
||||
### P0-1 全产品单场景:场景作为「组合单元/生命周期单元」完全缺席
|
||||
|
||||
- **证据**:`project.godot`(main_scene 唯一);`presentation/main.tscn` 仅 1 个 Control 节点挂 main.gd;`presentation/main.gd:204-361` `_build_ui` 程序化构建全部四区 + 12 个模态层。
|
||||
- **为什么是问题**:Godot 中场景是复用、组合与生命周期的基本单元——节点进/出树(`_enter_tree`/`_exit_tree`/NOTIFICATION_READY)本可免费承载「每局/每屏」的状态建立与销毁。现在一局结束什么都不销毁,全靠手动清理;任何视图都无法 F6 独立运行或单独复用;13 个 smoke 探针里 10 个只能挂载整个 main.tscn 才能测任何 UI(`smoke/ui_probe.gd:15` 等)。
|
||||
- **修复方向**:按「屏」切场景,第一步只拆屏容器 .tscn,视图继续代码构建,不要求全面 .tscn 化。
|
||||
|
||||
### P0-2 每局状态靠手工复位清单,无局级生命周期边界
|
||||
|
||||
- **证据**:`presentation/main.gd:647-657`(`_on_battle_end_continue` 手工置空 runner/settlement/adventure/_adventure_mode 并调 debug_overlay.reset_sliders());`main.gd:555-559` `_reset_run_scope` 只清 3 项;局态旗至少 7 个散布类顶(`main.gd:53-56,76-78,129-131`)。这类手工清单已有前科:`main.gd:790-792` 注释记录了续玩分支 runner 未就绪导致的实机崩值。
|
||||
- **为什么是问题**:场景机制「打包一组节点,`free()` 即整体回收」正是为消灭这种清单而存在;清单是随新增状态线性膨胀的手工契约,每加一个跨局字段就多一个静默泄漏点,且泄漏表现为低频难复现的脏状态而非显式报错。
|
||||
- **修复方向**:把「一局」物化为可整体 `queue_free()` 的节点(或至少一个 run-scope 对象持全部局态),终局释放即复位。
|
||||
|
||||
---
|
||||
|
||||
## P1 发现(6 条)
|
||||
|
||||
### P1-1 战斗结算巨函数:259 行、嵌套 7 层、同构兑付块重复 ≥5 处(双席独立命中同一病灶)
|
||||
|
||||
- **证据**:`core/battle_orchestrator.gd:632` `_settle()` = 259 行;`:562-563` 嵌套达 7 层(该文件 ≥5 层缩进行共 80 行,全项目最高)。重复块实读确认:`counter_add` 兑付三行组 ×5(`:682-684, 741-743, 776-778, 838 附近, 1192-1193`);`grant_material` 二次兑付块 ×3(约 `:688-694, :789-792, :1206-1212`);`reveal_tiles` 检查 ×3。效果 kind 字符串分派(`get("kind","") ==`)散布 20 处于结算段内。姊妹病灶:`core/damage_controller.gd:272` `_resolve_hero_attack()` = 148 行。全文件 1725 行、类级状态约 40 个变量(:62-98)、fan-out 13 个 core 类。
|
||||
- **为什么是问题**:编排器**不是**纯上帝对象(伤害已单据化进 DamageController,敌人/状态/奖励各自成类),但效果引擎只做了「匹配」数据驱动,「施加」按既定裁决留在发射点——实际效果是新增一种 effect kind 要同时改引擎词表 + 编排器内联分支,编排器增量复杂度与内容量线性挂钩。
|
||||
- **修复方向**:不推倒重写——五段结算各抽成 Segment 类(grant/aura/combat/decay/verdict),编排器退为段序编排 + 行发射,20 处 kind 分支随段归位。
|
||||
|
||||
### P1-2 刷新次数双账本——所有权三问(谁拥有/谁可改/谁知道)不及格
|
||||
|
||||
- **证据**:权威计数在 `core/battle_orchestrator.gd:73`(`_refresh_used_this_round`,受理门槛 :1522);呈现/遥测另计一份 `presentation/main.gd:129`(`_refresh_used_round`),HUD 余量 = 表上限 − main 自己的计数(`main.gd:1240`)。
|
||||
- **为什么是问题**:core 是裁判、main 是记账员,两条路一旦分叉(新增受理路径、调试注入、断点恢复),HUD 显示与真实可刷次数静默不一致。
|
||||
- **修复方向**:`presentation_snapshot()` 已可携带本轮已刷次数——删 main.gd 副本,HUD 只读快照。
|
||||
|
||||
### P1-3 GP 影子账本:表现层持有权威态镜像,根因在 summary 载荷不全
|
||||
|
||||
- **证据**:`presentation/gp_shadow_ledger.gd:9-19`(表现侧镜像钱包余额);根因链:`core/adventure_runner.gd:1046`(close_wallet() 清零先于 adventure_finished.emit)+ `adventure_runner.gd:1022-1038`(summary 十一个键里没有 final GP),呈现层被迫在清账前从事件流自抄一份。
|
||||
- **为什么是问题**:表现层持久化核心态违反「表现禁存数据」;镜像与权威只靠 wallet_changed 事件序维持一致(影子账本文件头自己承认是手工镜像)。该上抛的数据应随信号载荷走,不该让下游自建账本补抄。
|
||||
- **修复方向**:summary 增加 `gp_final` 键(清账前快照),删影子账本。
|
||||
|
||||
### P1-4 共享可变字典跨三层:所有权「名义单点、实际三处可写」
|
||||
|
||||
- **证据**:`core/level_runner.gd:501-521` begin_battle 的 encounter 载荷携带 bonus_ref/adventure_counters/attune_charges/vision_counter 四个共享 dict 引用;`core/battle_orchestrator.gd:79,86-88` 持引用直写(_attune_charges_ref 注释自认「use_treasure 消费直改」);`level_runner.gd:50` 账本同为字典引用共享。
|
||||
- **为什么是问题**:这是确定性设计(回灌/导出时点已文档化),但共享可变引用在函数签名上不可见——「冒险加算区归 AdventureRunner 所有」只是头注契约,LevelRunner 与 BattleOrchestrator 都握着同一本账可写。
|
||||
- **修复方向**:共享账收拢为显式 Ledger 类,战斗侧只拿 read+append 原语;战末 export/开局 seed 已有的时点语义不变。
|
||||
|
||||
### P1-5 组合根(main.gd)不可独立测试:核心读面靠注释纪律维持
|
||||
|
||||
- **证据**:控制器不可独立实例化——`presentation/curio_interact_controller.gd:39-57` 构造 16 参(10 个组合根 Callable)、`presentation/camp_shop_presenter.gd:25-40` 13 参;测试代价:`tests/unit/presentation/pacing_queue_test.gd:17-18` 必须 load 整个 main.tscn 挂整树并篡改 main 内部字段才能驱动。25 个测试套件中 core/data 侧 22 个直接 new() 即测,presentation 侧只剩整树集成一条路。
|
||||
- **为什么是问题**:组合根本身没有单测缝;豁免面与 20+ 访问器(settlement.minesweeper.* 等)无结构强制,全靠 ADR 注释和评审盯。
|
||||
- **修复方向**:把 main 的「模式状态机 + 输入锁 + 模态编排」抽成无 UI 纯逻辑类(依赖仅 ModalStack + 查询 Callable),控制器构造参数收拢为 context 对象——不改行为即可获得单测缝。**注:本条应在场景拆分落地后重新评估,main.gd 缩水后抽取面可能大幅变小。**
|
||||
|
||||
### P1-6 静态类型闸缺位:类型规范有文、机器无闸
|
||||
|
||||
- **证据**:无类型 Array/Dictionary 游戏代码 73 处(core 53 / data 9 / presentation 11,如 `core/adventure_runner.gd:78,95`、`core/effect_engine.gd:94-95`、`presentation/main.gd:69`);core 无返回类型函数 12 处(`core/reward_economy.gd:109,124,136,151` 等);无类型参数(`core/attunement.gd:12`、`core/board_generator.gd:18,83,284,334`)。`project.godot` 全文 36 行没有任何 gdscript warning 配置——`untyped_declaration` 默认 Ignore。
|
||||
- **为什么是问题**:仓库 code-conventions §4.2 有明文(Dictionary 取值参与算术前显式声明类型),但无机器闸则规范只靠评审;Variant 容器在结算热循环里吃类型检查开销且放行拼写错。
|
||||
- **修复方向**:project.godot 提升 warning 级别让存量显形,新码一律收口;存量 73 处随批清理。**本条必须在其他重构全部落地之后做**,否则新重构代码又会产生新违规。
|
||||
|
||||
---
|
||||
|
||||
## P2 卫生件(建议打包随批,不需逐条裁决)
|
||||
|
||||
1. **死代码 16 处**:`core/battle_orchestrator.gd:216` `_attune_row`、`core/damage_controller.gd:102` `_fx_dispatch`(活实现 _fx_fact 的退役孪生)、`core/board_data.gd:61` `clear_variants`、`core/effect_engine.gd:417` `combo_of`、`core/treasure_items.gd:68,83`、`core/minesweeper_rules.gd:41`、`core/feats_engine.gd:13,38`、`core/config_db.gd:253,273`、`core/save_manager.gd:419`、`presentation/curio_interact_controller.gd:58`、`presentation/views/stage_world.gd:17`、`presentation/views/curio_pick_overlay.gd:170`、`presentation/views/ui_kit.gd:486`。其中 **FeatsEngine 整文件零调用**(仅注释提及,`data/schemas/feat_table.gd:22` 自注已随重设计退役)但 `class_name` 仍全局注册。
|
||||
2. **绝对路径取 autoload ×4**:`presentation/main.gd:174,190,481,1351` 用 `get_node("/root/…")` 字符串路径取 ConfigDB/RngService——Godot 4 有编译期注入的全局名,字符串路径改名/拼写零防护。
|
||||
3. **字符串式 Callable ×9**:`core/battle_orchestrator.gd:105,390,391`、`core/damage_controller.gd:98`、`core/adventure_runner.gd:940,951`、`core/level_runner.gd:166`、`presentation/main.gd:191`——`Callable(self, "方法名字符串")` 绕过编译期方法存在性校验,应改 `self._method` 引用形式。
|
||||
4. **裸字符串状态机 ×16**:`core/adventure_runner.gd:120,159,176,263,269,277,402,894,974,1049,1051,1071`(state = "idle"/"running"/"settling");`presentation/views/standee_body.gd:333,373,380,387`。本仓 `core/action_economy.gd:12-23` 已有「内部 enum + match + 外部 String 契约 getter」正解示范,应套用。
|
||||
5. **百行级装配/校验长函数 17 个**:`presentation/main.gd:204` `_build_ui()` 160 行、`level_map_screen.gd:72` 145 行、`camp_overlay_view.gd:55` 142 行、`debug_overlay.gd:159` 114 行、schema 校验器群(treasure_item_table.gd:87 = 149 行等)。线性装配圈复杂度不高,但区块级改动每次都在巨函数里动刀。**注:main._build_ui 在场景拆分中自然解体,不必单独修。**
|
||||
6. **ConfigDB 越权退出 + resolver 类型软环**:`core/config_db.gd:75-82` `_fatal` 直接 quit(1)/OS.crash(fail-fast 政策对,执行位置应归根——`main.gd:176-179` 已有同通道 fatal 屏);`config_db.gd:57-58` 持有并构造 ConfigDbResolver,resolver 反向 class_name 引用 ConfigDb——双向类型耦合,resolver 对门面改持 Callable 诊断通道即解(validator 已是此形态)。
|
||||
7. **模态「开态=可见性」协议**:`presentation/modal_stack.gd:39-63` has_open() 靠遍历 visible 位;`main.gd:404-409` 输入锁 = 栈查询 + 三例外 + 排除式;`main.gd:407-408` 注释记录过「DS_DEBUG 默认开 × 遮挡复活 × has_open 组合 = 棋盘永久锁死」事故。12 个层的状态散布在各自 visible 位上,约束只存在于调用点拼装。修法:ModalStack 内聚「互斥域/排除组」概念,开态谓词随层登记。
|
||||
|
||||
---
|
||||
|
||||
## 用户场景预想评估(审计席专门裁断)
|
||||
|
||||
用户预想:开始菜单做根场景 + 营地/冒险分开 + 冒险内分关卡/战斗两大块。
|
||||
|
||||
**裁断:方向支持,三条全部成立;需三处修正、一处明确反对。**
|
||||
|
||||
1. **支持「开始菜单做根场景」**——修正:拆场景后 SaveManager/MetaProgression 不能再由 main.gd new() 出来(`main.gd:182-189`),必须提升为跨场景持有者(第三个 autoload 或根场景常驻子节点),否则换场景即丢档。RngService 已有先例,模式现成。
|
||||
2. **支持「营地与冒险分开」**——营地全部读写已收口在 MetaProgression/SaveManager 访问器(camp_shop_presenter 零直写),营地当前只是覆盖层(camp_overlay),升格独立场景不碰任何 core 接口,切缝天然干净。
|
||||
3. **支持「冒险内关卡/战斗分块」**——最有力的论据是域侧三层生命周期已经存在,场景层只是补镜像:`level_screen` 已是独立屏雏形(`main.gd:76,259-263`,屏级互斥单出口 `main.gd:978-990`),`_battle_root` 是现成战斗屏宿主(`main.gd:77,207`)。预想与代码现实几乎一一对齐。
|
||||
4. **明确反对一条**:不要借机把 40+ 个 views/*.gd 转成 .tscn。「程序化构建」与「场景切分」是两个独立决策——.tscn 根节点 + `_ready` 程序化内容完全合法;全面 .tscn 化会破坏全部探针契约(`board_view.gd:8-14` 对探针零改造契约)且收益为零。
|
||||
5. **迁移安全网**:13 个 smoke 探针中 10 个假设「挂载 main.tscn 即全应用」,拆分时这批探针的挂载假设同批迁移,它们就是切分作业的回归保障。建议时序:垂直切片验证期「只拆不重写」——root 壳 + menu.tscn + camp 场景 + adventure.tscn(内含 level_map/battle 两容器),新内容一律进新场景,战斗屏视图代码原样搬。
|
||||
|
||||
---
|
||||
|
||||
## 实现规范面补充结论与扫描器运行记录
|
||||
|
||||
**四大高危面几乎无坑、无 P0 命中**:信号面、Tween 生命周期、数值单一事实源、autoload 卫生。
|
||||
|
||||
**扫描器实跑记录**(实现席如实登记):
|
||||
- 技能库 `auditor_audit_signals.py`(python 只读输出):74 处 lambda 连接(presentation 4 / smoke 62 / tests 8)。presentation 4 处逐一实读确认无泄漏(发射者与 lambda 同子树同生共死,refresh 先 queue_free 子树并清登记数组,`camp_overlay_view.gd:227-230`);smoke 62 处为一次性 headless 探针进程,不进游戏包。
|
||||
- 技能库 `auditor_audit_type_hints.py`:229 处(untyped Array 209 / Dictionary 20 / string connect 0);按目录 core 53 / data 9 / presentation 11 / smoke 133 / tests 23。
|
||||
- 手工 grep 等价检查(如实注明非扫描器):Godot 3 四参 connect 0;字符串 `.connect(` 0;`.disconnect(` 0;CONNECT_* 标志 0;绝对路径 get_node 4(见 P2-2);`Callable(self,"…")` 9(见 P2-3);call_deferred 10 处实读均为帧沿触发非初始化创可贴;await 1 处(dev 工具);全站 `_physics_process` 中 await 0;create_tween 20+ 处实读确认节点绑定+回调清理;print 3 处全在 dev 工具。
|
||||
- 跳过并注明:`auditor_audit_memory_fragmentation.gd`、`auditor_purge_report_generator.gd` 需 Godot 运行时,按只读纪律未跑。
|
||||
- 误报排除一例:battle_orchestrator 的 round_started/board_changed(:30-31)初判疑为死信号,实读确认 :447,488,1516 有发射、三层转发链全活,非发现。
|
||||
|
||||
---
|
||||
|
||||
## 做对了的事(防止报告纯负面失真)
|
||||
|
||||
1. **信号严格向上,core 零反向依赖**:全 core/ 无一处 presentation 引用、无 get_node/树访问;runner 转发族用命名方法 Callable(`core/adventure_runner.gd:918-924` 等,头注写明禁 lambda 捕获 self 成环);信号连接唯一归组合根(ADR-0001 落实到位)。
|
||||
2. **Autoload 克制且纯净**:仅两个、纯数据/服务形态、无子节点无 UI 知识;RngService 统一单盐流 + 全事件日志(`core/rng_service.gd:95-108`)使全游戏同种子逐位复现——确定性架构的业内水准做法,也是本次全部重构验收手段的基础。
|
||||
3. **效果引擎护栏设计**:事件/效果/事实/算子四词表封闭常量 + 加载期 schema 校验致命 + 组合规则成文(`core/effect_engine.gd:24-91,362-433`),失败模式 fail-fast 而非静默。
|
||||
4. **读面成文快照收口**:presentation_snapshot()/diagnostic_snapshot() 成文出口替代链式穿透,协作对象私有化 + 明文豁免面——封装边界是写下来的契约而非默契。
|
||||
5. **Tween 生命周期纪律全站一致**:节点绑定 create_tween + tween_callback(queue_free) + is_instance_valid 守卫 + rebuild 重入先杀——技能库最常判死刑的陷阱本项目零命中。
|
||||
6. **测试策略真实分层**:25 个 headless 套件直接实例化 core 类、表值现读不写死;确定性 RNG 使「逐位一致」断言成为可能,这在随机系统里是稀缺的测试能力。
|
||||
|
||||
---
|
||||
|
||||
## 修复排期估算与裁决记录
|
||||
|
||||
**逐项估算**:场景拆分 + 局生命周期物化 + 探针迁移 ≈ 4-5d;`_settle` 拆段 ≈ 1.5d;共享账本 Ledger 类化 ≈ 1d;类型闸拉起 + 73 处收口 ≈ 1.5d;组合根可测化抽取 ≈ 1-1.5d(场景拆分后重估);模态协议内聚 ≈ 0.5-1d;卫生件包 ≈ 1.5d。**合计约 12-14 个工作日。**
|
||||
|
||||
**裁决记录(2026-10-14 用户)**:全部技术债修复**允许放行单一大迭代**,12-14 个工作日在允许时间范围内。
|
||||
|
||||
**批内执行顺序约束**(审计席建议):①场景拆分与局生命周期先行(P0 根因,且决定 main.gd 终态形状);②战斗域重构(_settle 拆段 + Ledger 类化)随后;③组合根抽取在场景拆分后重估再动;④类型闸收尾(其他重构落地后才拉得起 Error 级);⑤卫生件随批顺手带。最大两件(场景拆分动 main.gd 1385 行 / _settle 拆段动战斗结算心脏)各自需要全量冒烟回归,同批内应分波提交、逐波全绿,避免回归时二分定位跨双巨改。
|
||||
|
||||
**核心验收手段**:确定性 RNG 架构给了杀手级验收——同种子逐位一致回放(重构前后跑完整局输出逐位一致);场景批验收 = 10 个探针迁移后全绿 + run_all 25 套;战斗域批验收 = 逐位一致 + 冒烟全量。
|
||||
|
||||
**写卡前待裁三点**(grilling 时闭):①SaveManager/MetaProgression 升格形态(第三个 autoload vs 根场景常驻节点);②共享账本 Ledger 类接口口径;③`_settle` 段边界切法。
|
||||
@@ -1,7 +1,7 @@
|
||||
# 需求卡片:代码架构技术债修复批(场景拆分 · 局生命周期 · 战斗结算拆段 · 账本收口 · 类型闸 · 卫生件)
|
||||
|
||||
- 版本:v1.2(2026-10-14 成文 v1.0;同日用户令**编入迭代 27 卡①**——roadmap 迭代行已更新,M4 数值批顺延 28+。v1.1→v1.2:**§10 三点待裁全裁**(2026-10-14 用户三裁,全按推荐案:①第三个 autoload/②单类持四账/③审计五段)——零待裁点,卡片成立)
|
||||
- 来源:[代码架构与实现质量审计报告-2026-10-14](代码架构与实现质量审计报告-2026-10-14.md)(双席审计,基线 master 97de02c;**同日已经第三方逐条复核:主体结论全部成立,五处计数级瑕疵已随批修正落文**)
|
||||
- 来源:代码架构与实现质量审计报告-2026-10-14(双席审计,基线 master 97de02c;同日第三方逐条复核五处计数级瑕疵修正落文;**该报告已按退役规则于本批收口 git rm——吸收即死,修正后计数由本卡承载,收口结案=design/qa/iter27-实现报告-2026-10-14.md**)
|
||||
- 归属:工程债/重构批(凭审计证据直接写卡,无设计定稿前置——2026-10-10 立规:缺陷修复/工程债/重构类工程需求无设计前置要求)
|
||||
- 排期:**已编入迭代 27 卡①**(2026-10-14 用户令;用户裁决记录:全部技术债修复允许放行单一大迭代,12-14 个工作日在允许时间范围内;**开工门=U0 已满足**——三点已裁(见版本行)+用户 /goal+iter 27 发令,U0=2026-10-14 开工;M4 数值批顺延 28+)
|
||||
|
||||
|
||||
@@ -54,7 +54,11 @@ signal wallet_changed(event: String, gp: int, extra: Dictionary)
|
||||
|
||||
var db: ConfigDb
|
||||
var rng: RngServiceCore
|
||||
var state := "idle" # idle / running / settling(冒险结构.md 三态)
|
||||
enum State { IDLE, RUNNING, SETTLING } # 会话状态机(迭代 27 T6——裸字符串 enum 化:内部 enum,外部 String 契约 getter 词表逐位一致)
|
||||
var _state: State = State.IDLE
|
||||
var state: String: # 外部契约面(只读——外部零写点实证;"idle"/"running"/"settling" 零变化)
|
||||
get:
|
||||
return State.keys()[_state].to_lower()
|
||||
var ledger := {"hero_hp": 0, "gp": 0} # 冒险账本(生命 + GP 钱包——经 start_level_external 注入 runner 共享)
|
||||
var run_ledger := RunLedger.new() # 共享四本账(迭代 27 T3——P1-4 收口:attune_charges/vision_counter/adventure_counters/bonus 单类持账;裁点②甲)
|
||||
var purchased := {} # product_id → 已购档数(跨关延续、冒险收束清零——递增定价输入)
|
||||
@@ -153,7 +157,7 @@ func start_adventure(seed_val: int, params: Dictionary = {}) -> bool:
|
||||
for r in feat_seed:
|
||||
_feats.append(String(r))
|
||||
ledger["hero_hp"] = effective_max_hp() # 生命账本置满(生效上限口径——T17 修复:含调试浮窗 pct,与战斗内同源)
|
||||
state = "running"
|
||||
_state = State.RUNNING
|
||||
return _start_current_level()
|
||||
|
||||
|
||||
@@ -257,13 +261,13 @@ func resume_adventure(bp: Dictionary, params: Dictionary = {}) -> bool:
|
||||
migrated.append({"kind": String(c), "tier": db.adventure.TIER_COMMON})
|
||||
_curio_pending = {"candidates": migrated}
|
||||
var payload: Dictionary[Variant, Variant] = (bp_pending.get("payload", {}) as Dictionary).duplicate(true)
|
||||
state = "running"
|
||||
_state = State.RUNNING
|
||||
curio_choice_presented.emit(payload)
|
||||
return true
|
||||
if not bp_result.is_empty():
|
||||
_pending_next_level = true
|
||||
_curio_result = bp_result.duplicate(true)
|
||||
state = "running"
|
||||
_state = State.RUNNING
|
||||
curio_resolved.emit(_curio_result.duplicate(true))
|
||||
return true
|
||||
_resume_bp = bp.duplicate(true)
|
||||
@@ -271,7 +275,7 @@ func resume_adventure(bp: Dictionary, params: Dictionary = {}) -> bool:
|
||||
var bp_charges = bp.get("attunement_charges", null)
|
||||
if bp_charges is Dictionary:
|
||||
run_ledger.attune_charges = (bp_charges as Dictionary).duplicate(true)
|
||||
state = "running"
|
||||
_state = State.RUNNING
|
||||
return _start_current_level()
|
||||
|
||||
|
||||
@@ -936,7 +940,7 @@ func _start_current_level() -> bool:
|
||||
_runner.set_run_ledger(run_ledger) # 迭代 27 T3——共享四账单类下传(原四 setter/参数散传收口;run_ledger=四账类,ledger=关卡账沿用旧名)
|
||||
_runner.sync_attune_inventory() # 迭代 11 第①批 T6 原语义——能力件骑库存面注入(随账下传同拍)
|
||||
var ok: bool = _runner.start_level_external(level_index, ledger, purchased,
|
||||
Callable(self, "apply_rest"), _base_override, true, template_pick, resume_state)
|
||||
apply_rest, _base_override, true, template_pick, resume_state)
|
||||
if ok:
|
||||
_runner.set_attunement(_attunement) # 迭代 11 第①批 T5——同调装配下传(enc 携带进战斗结算)
|
||||
_runner.set_feats(_feats) # 迭代 12 T1——特性持有集下传(begin_battle enc.feats 求值面)
|
||||
@@ -945,7 +949,7 @@ func _start_current_level() -> bool:
|
||||
if _shop_mode == "pool":
|
||||
# 商店共享池注入(迭代 11 第②批 T3——库存账本引用+消费 handler 双下传;legacy 模式零注入零扰动。
|
||||
# 迭代 20 T2——cap 检查回调四参注入)
|
||||
_runner.set_shop_pool(_curio_deck, Callable(self, "_consume_pool_purchase"), Callable(self, "_feat_ticket_consider"), Callable(self, "_curio_cap_ok"))
|
||||
_runner.set_shop_pool(_curio_deck, _consume_pool_purchase, _feat_ticket_consider, _curio_cap_ok)
|
||||
# 迭代 20 T4——凭证件三账注入(节点级/回合级一次性:注入即清零,未用即过期=寿命档语义)
|
||||
_runner.set_voucher_grants(_pending_rap, _time_sand_queue, _pending_insurance)
|
||||
_pending_rap = 0
|
||||
@@ -1043,9 +1047,9 @@ func _settle(result: String) -> void:
|
||||
if _save_manager != null:
|
||||
_save_manager.clear_breakpoint() # 三结局清断点(迭代 8 卡①/T3——退出冒险=放弃流程+清除断点)
|
||||
_save_manager.write_to_disk()
|
||||
state = "settling"
|
||||
_state = State.SETTLING
|
||||
adventure_finished.emit(summary)
|
||||
state = "idle"
|
||||
_state = State.IDLE
|
||||
|
||||
|
||||
# ---- 转发族(签名与 LevelRunner 同款——呈现层对接透明)----
|
||||
|
||||
@@ -108,7 +108,7 @@ var _fx: EffectEngine
|
||||
func _fx_emit(event: String, payload: Dictionary) -> Array:
|
||||
if _fx == null:
|
||||
return []
|
||||
return _fx.dispatch(event, payload, Callable(self, "_fx_fact"))
|
||||
return _fx.dispatch(event, payload, _fx_fact)
|
||||
|
||||
|
||||
# round_start 发射+施加(内容数据驱动扩展批 T3——grant_ap mode:queue=当轮入队,行动经济轮切换
|
||||
@@ -219,10 +219,6 @@ func attune_has(item_id: String) -> bool:
|
||||
|
||||
# 装备件表值读取(charge_n 等——TreasureItemTable 行;未装配不读表。magnitude 读数面随 T4
|
||||
# 秘宝订阅迁移退役——行值经 value_from 在 rebuild 定影,零运行期按件取值)
|
||||
func _attune_row(item_id: String) -> Dictionary:
|
||||
return db.treasure_item_row(item_id) if _attune_has(item_id) else {}
|
||||
|
||||
|
||||
# 装配集参数合计(迭代 22 秘宝批 T3——常时参数面 kind 的装配集 Σmagnitude 读数口;
|
||||
# kind 分发查询先例=_attune_refresh_x_total bonus_refresh。零装配=0)
|
||||
func attune_param_sum(kind: String) -> int:
|
||||
@@ -395,8 +391,8 @@ func begin_battle(enc: Dictionary) -> bool:
|
||||
_fx_bonus_delta = {"atk": 0, "max_hp": 0, "armor_class": 0, "ap": 0}
|
||||
var ledger_ref = enc.get("ledger", null)
|
||||
_ledger = ledger_ref if ledger_ref is RunLedger else RunLedger.new() # 缺省新账=调试/单场零扰动面
|
||||
_damage.fx_reveal_request = Callable(self, "_fx_enqueue_reveal")
|
||||
_damage.fx_ac_request = Callable(self, "_apply_ac_bonus")
|
||||
_damage.fx_reveal_request = _fx_enqueue_reveal
|
||||
_damage.fx_ac_request = _apply_ac_bonus
|
||||
var feat_ids: Array[Variant] = enc.get("feats", []) as Array
|
||||
# 迭代 20 T3 换代(V14 旧实现摘除)——流派档位质变随重设计退役(奇物.md v1「不设流派标签、
|
||||
# 不设档位机制」):FeatsEngine 求值与 rider_tier 注入拆除,散件单体效果=唯一形态
|
||||
|
||||
@@ -58,10 +58,6 @@ func board_variant_ids() -> Array[String]:
|
||||
|
||||
|
||||
# 中和格变异(迭代 12 T6 净化工兵——伤害型地形格变普通格;🔴 R4 甲仅限伤害型的过滤在调用方)
|
||||
func clear_variants(c: Vector2i) -> void:
|
||||
variants.erase(c)
|
||||
|
||||
|
||||
func neighbors8(c: Vector2i) -> Array:
|
||||
var out: Array[Vector2i] = []
|
||||
for dy in range(-1, 2):
|
||||
|
||||
+15
-20
@@ -60,7 +60,8 @@ var _reload_gate := false # 数据配置 EC8——战斗结
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
_resolver = ConfigDbResolver.new(self) # 协作类持门面引用(诊断/致命通道回呼)
|
||||
_resolver = ConfigDbResolver.new(Callable(self, "push_diag"), Callable(self, "reset_warn_dedup"),
|
||||
func() -> Variant: return board_gen.rows, func() -> Variant: return enemy.rows, func() -> Variant: return difficulty) # 协作类持门面引用(诊断/致命通道回呼)
|
||||
|
||||
|
||||
func push_diag(severity: String, category: String, message: String) -> void:
|
||||
@@ -71,20 +72,25 @@ func push_diag(severity: String, category: String, message: String) -> void:
|
||||
push_error("[ConfigDB/%s] %s" % [category, message])
|
||||
|
||||
|
||||
# 运行期数据致命(2026-09-18 用户拍板:越域记 Fatal 级日志后立即退出——数据配置通道 fail-fast 纪律补齐到查询期)
|
||||
# 运行期数据致命(2026-09-18 用户拍板 fail-fast;迭代 27 T6——退出执行归根:核心层不再自携
|
||||
# quit/crash,越域记 Fatal 级日志后置 _fatal_flag,进程退出决策归组合根(main._ready 表加载
|
||||
# 失败已有同通道 fatal 屏+fail-fast 边界)——查询期消费方按返回值安全面走既有默认值回退)
|
||||
func _fatal(category: String, message: String) -> void:
|
||||
push_diag("fatal", category, message)
|
||||
push_error("[ConfigDB/%s] FATAL: %s —— 数据配置致命,进程退出" % [category, message])
|
||||
var main_loop := Engine.get_main_loop()
|
||||
if main_loop is SceneTree:
|
||||
main_loop.quit(1) # 帧末退出,退出码 1——调用方须立即 return,勿再消费返回值
|
||||
else:
|
||||
OS.crash("ConfigDB/%s fatal: %s" % [category, message])
|
||||
push_error("[ConfigDB/%s] FATAL: %s —— 数据配置致命(退出决策归组合根)" % [category, message])
|
||||
_fatal_flag = true
|
||||
|
||||
|
||||
var _fatal_flag := false # 运行期致命旗(迭代 27 T6——退出归根承载;组合根/闸读面)
|
||||
|
||||
|
||||
func is_fatal() -> bool:
|
||||
return _fatal_flag
|
||||
|
||||
|
||||
func reset_diagnostics() -> void:
|
||||
_diagnostics.clear()
|
||||
_resolver.reset_warn_dedup() # R1 告警去重注册表(协作类持钥——清空时点与拆分前一致)
|
||||
_resolver._reset_warn.call() # R1 告警去重注册表(协作类持钥——清空时点与拆分前一致;通道 Callable 化随 T6)
|
||||
|
||||
|
||||
func diagnostics() -> Array:
|
||||
@@ -250,10 +256,6 @@ func level_count() -> int:
|
||||
# ---- GP+商店房实施批(2026-09-21):ShopTable 消费面(行集解析单点——runner/战斗编排禁自扫表)----
|
||||
# ── 秘宝访问器(迭代 7 T1——消费面一律走访问器,禁直读行集)──
|
||||
# 活行集(非 retired 非 deferred)——投放校验/奖励节点池/呈现可用性的唯一取数口径
|
||||
func treasure_active_rows() -> Array:
|
||||
return treasure_items.active_rows() if treasure_items != null else []
|
||||
|
||||
|
||||
func treasure_item_row(item_id: String) -> Dictionary:
|
||||
return treasure_items.row_by_id(item_id) if treasure_items != null else {}
|
||||
|
||||
@@ -270,13 +272,6 @@ func treasure_attunement_rows() -> Array:
|
||||
|
||||
|
||||
# 活行词表(掉落投放 effect_id 白名单——过渡渠道口径)
|
||||
func treasure_live_ids() -> Dictionary:
|
||||
var out := {}
|
||||
for row in treasure_transitional_rows():
|
||||
out[String(row.get("item_id", ""))] = true
|
||||
return out
|
||||
|
||||
|
||||
# ── 同调轴访问器已删除(迭代 21 T5——attunement_growth 谓词表随槽位收编退役:槽位数量=树同调位
|
||||
# 节点点亮数,判定源=Attunement.slots;boss_kill_count/clear_count 计数域保留——非槽位硬消费在册)──
|
||||
|
||||
|
||||
@@ -11,12 +11,21 @@
|
||||
class_name ConfigDbResolver
|
||||
extends RefCounted
|
||||
|
||||
var _db: ConfigDb # 门面引用(表读取 + 诊断/致命通道——_init 注入)
|
||||
var _diag: Callable # 诊断/致命通道(迭代 27 T6——门面类型反持解耦,validator 先例:签名 (level, category, message))
|
||||
var _reset_warn: Callable # 去重注册表清空通道(reset_diagnostics 时点由门面驱动)
|
||||
var _board_gen_rows_get: Callable # () -> Array——board_gen 行集活读(数据面经 Callable 注入,ConfigDb 类型环断根)
|
||||
var _enemy_rows_get: Callable # () -> Array——enemy 行集活读
|
||||
var _difficulty_get: Callable # () -> DifficultyTable(可空——表缺省合法态)
|
||||
var _warn_dedup: Dictionary[String, bool] = {} # R1 四元组去重注册表(自 ConfigDb 迁入)
|
||||
|
||||
|
||||
func _init(db_ref: ConfigDb) -> void:
|
||||
_db = db_ref
|
||||
func _init(diag_cb: Callable, reset_warn_cb: Callable, board_gen_rows_cb: Callable,
|
||||
enemy_rows_cb: Callable, difficulty_cb: Callable) -> void:
|
||||
_diag = diag_cb
|
||||
_reset_warn = reset_warn_cb
|
||||
_board_gen_rows_get = board_gen_rows_cb
|
||||
_enemy_rows_get = enemy_rows_cb
|
||||
_difficulty_get = difficulty_cb
|
||||
|
||||
|
||||
# 去重注册表清空(门面 load_tables / reset_diagnostics 调用——与拆分前清空时点逐位一致)
|
||||
@@ -27,21 +36,22 @@ func reset_warn_dedup() -> void:
|
||||
# ---- R1 难度行解析(2026-09-18 用户拍板修订:ceil 向上取整保证偏难;域越界与内容缺口 Fatal 退出)----
|
||||
|
||||
func resolve_board_gen(L: int, D: int) -> Dictionary:
|
||||
return _resolve_progress(_db.board_gen.rows, L, D, "board_gen")
|
||||
return _resolve_progress(_board_gen_rows_get.call(), L, D, "board_gen")
|
||||
|
||||
|
||||
func resolve_enemy_rowset(L: int, D: int) -> Array[Dictionary]:
|
||||
# 行集数组形态(2026-10-07 敌人表行集多行批——原单行 Dictionary 退役):ceil 命中 (l*,d*) 后
|
||||
# 返回该坐标全部行、按表文件行序(行序即契约——同坐标多行文件内相邻由 EnemyTable.validate 兜底)。
|
||||
# 空集表达 = 空数组(生产表下 ceil 命中坐标恒有行,空集仅表空时可达——validate 已拦)。
|
||||
return _resolve_progress(_db.enemy.rows, L, D, "enemy", true)
|
||||
return _resolve_progress(_enemy_rows_get.call(), L, D, "enemy", true)
|
||||
|
||||
|
||||
# 难度曲线与Boss DifficultyTable 消费面(敌人系统.spawn 调用):(L,D) 精确匹配修饰乘数,越域值 clamp(GDD Edge Case——组合事故非配置事故)
|
||||
func resolve_difficulty_modifiers(L: int, D: int) -> Dictionary:
|
||||
if _db.difficulty == null:
|
||||
var dt = _difficulty_get.call()
|
||||
if dt == null:
|
||||
return {}
|
||||
for row in _db.difficulty.rows:
|
||||
for row in dt.rows:
|
||||
if int(row.get("level_index", 0)) == L and int(row.get("node_depth", -1)) == D:
|
||||
return {
|
||||
"hp_mult": clampf(float(row.get("hp_mult", 1.0)), 0.1, 10.0),
|
||||
@@ -52,7 +62,7 @@ func resolve_difficulty_modifiers(L: int, D: int) -> Dictionary:
|
||||
|
||||
func _resolve_progress(rows: Array, L: int, D: int, table_id: String, return_all := false) -> Variant:
|
||||
if L < 1 or D < 0:
|
||||
_db._fatal("request_oob", "%s 请求越域 (%d,%d)——进度坐标低于合法域(关卡序号≥1、节点深度≥0)" % [table_id, L, D])
|
||||
_diag.call("fatal", "request_oob", "%s 请求越域 (%d,%d)——进度坐标低于合法域(关卡序号≥1、节点深度≥0)" % [table_id, L, D])
|
||||
return {}
|
||||
var level_keys: Array[int] = []
|
||||
for row in rows:
|
||||
@@ -60,7 +70,7 @@ func _resolve_progress(rows: Array, L: int, D: int, table_id: String, return_all
|
||||
if not level_keys.has(lv):
|
||||
level_keys.append(lv)
|
||||
if level_keys.is_empty():
|
||||
_db._fatal("structural", "%s 行集为空——锚行校验应已拦截" % table_id)
|
||||
_diag.call("fatal", "structural", "%s 行集为空——锚行校验应已拦截" % table_id)
|
||||
return {}
|
||||
level_keys.sort()
|
||||
var l_star := _ceil_key(level_keys, L)
|
||||
@@ -96,7 +106,7 @@ func _resolve_progress(rows: Array, L: int, D: int, table_id: String, return_all
|
||||
if not _warn_dedup.has(dedup_key):
|
||||
_warn_dedup[dedup_key] = true
|
||||
var verb := "clamp 解析(超出最大行取最大值)" if missing.contains("clamp") else "ceil 解析(向上取整保证偏难)"
|
||||
_db.push_diag("warning", "resolve_" + missing, "%s 请求 (%d,%d) %s → (%d,%d) [%s]——2026-09-18 拍板" % [table_id, L, D, verb, l_star, d_star, missing])
|
||||
_diag.call("warning", "resolve_" + missing, "%s 请求 (%d,%d) %s → (%d,%d) [%s]——2026-09-18 拍板" % [table_id, L, D, verb, l_star, d_star, missing])
|
||||
if return_all:
|
||||
var all_out: Array[Dictionary] = []
|
||||
for row in rows:
|
||||
|
||||
@@ -95,14 +95,10 @@ func set_fx(fx: EffectEngine) -> void:
|
||||
func _fx_hits(event: String, payload: Dictionary) -> Array:
|
||||
if _fx == null:
|
||||
return []
|
||||
return _fx.dispatch(event, payload, Callable(self, "_fx_fact"))
|
||||
return _fx.dispatch(event, payload, _fx_fact)
|
||||
|
||||
|
||||
# 事件发射薄面(免施加观测位——enemy_hp_threshold 等现无订阅者的事件保留零扰动面)
|
||||
func _fx_dispatch(event: String, payload: Dictionary) -> void:
|
||||
_fx_hits(event, payload)
|
||||
|
||||
|
||||
# 补充事实面(fact 取值第二优先源——payload 未携带的运行态读数:charge_layers 编排器每轮注入。
|
||||
# 迭代 20 T1——hp_ratio 补入〔背水 when 面,敌技 damage_taken 载荷不带血比例时回落〕;
|
||||
# fx_reveal_request=揭示效果回调〔斩首学者 kill 订阅面——编排器注入,入队授予段末兑付〕)
|
||||
|
||||
@@ -413,21 +413,4 @@ static func validate_trigger_row(rid: String, row: Dictionary, triggers: Array,
|
||||
## 按序改写族(收集→单点按声明序施加):modify_ticket 及一切改写窗口效果。
|
||||
## 按序消耗族(按订阅序消耗共享资源,耗尽即止;可选 fallback):counter_spend。
|
||||
## 即时执行族(每条命中各自执行一次,执行序=声明序):open_ticket、grant_ap(mode:transfer)、
|
||||
## rewrite_board、apply_status——发射点逐条执行。
|
||||
static func combo_of(kind: String) -> String:
|
||||
match kind:
|
||||
"add_ticket_rider", "attack_bonus", "grant_material", "counter_add", "shield", "heal", "ac_bonus", "damage_reduce", "bonus_delta":
|
||||
return "additive"
|
||||
"grant_ap":
|
||||
return "additive" # mode:transfer 由发射点即时执行族承载(转移非加法)
|
||||
"yield_mult", "damage_mult":
|
||||
return "multiplicative"
|
||||
"spawn_spell", "overflow", "spike":
|
||||
return "any_true"
|
||||
"modify_ticket":
|
||||
return "ordered_write"
|
||||
"counter_spend":
|
||||
return "ordered_spend"
|
||||
"open_ticket", "apply_status", "blast_scaled":
|
||||
return "immediate"
|
||||
return "immediate" # 默认即时执行(每条命中各自执行一次)
|
||||
## rewrite_board、apply_status——发射点逐条执行。
|
||||
@@ -1,39 +0,0 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# Date: 2026-10-04(双层 BD 实施批 T1——标签档位激活引擎)
|
||||
# 流派成型判据机制化(整合定稿 设计工具 1——以撒套装/小骨铭文先例):
|
||||
# 同流派标签 relic 计数 ≥2 → 档一(流派核心规则);≥4 → 档二(完全体);<2 = 散件(单体保底——
|
||||
# 每件效果独立生效,档位只做质变不做启动,反例 B-2)。
|
||||
# 纯函数零 await 零 RNG 零副作用(Attunement 求值服务同款纪律);核心层零特判延伸——引擎只读
|
||||
# feat_table 行集与持有集,接线点消费 tiers/hooks 投影。
|
||||
class_name FeatsEngine
|
||||
extends RefCounted
|
||||
|
||||
|
||||
## 档位求值:feat_ids 持有集 × 行集 → {archetype: tier}(tier ∈ 0/1/2;无行流派不出现)
|
||||
static func tiers_for(feat_ids: Array, table: FeatTable) -> Dictionary:
|
||||
var counts := {}
|
||||
for rid in feat_ids:
|
||||
var row: Dictionary[Variant, Variant] = table.row_by_id(String(rid)) if table != null else {}
|
||||
if row.is_empty():
|
||||
continue
|
||||
var arch := String(row.get("archetype", ""))
|
||||
counts[arch] = int(counts.get(arch, 0)) + 1
|
||||
var out := {}
|
||||
for arch in counts.keys():
|
||||
var n := int(counts[arch])
|
||||
if n >= 4:
|
||||
out[arch] = 2
|
||||
elif n >= 2:
|
||||
out[arch] = 1
|
||||
else:
|
||||
out[arch] = 0
|
||||
return out
|
||||
|
||||
|
||||
## 挂点投影随 T3 退役(内容数据驱动扩展批——hook 词族消亡:订阅投影=效果引擎 rebuild 装载序
|
||||
## (feats 表序),投影稳定性由 EffectEngine._triggers 声明序承载)
|
||||
|
||||
|
||||
## 成型判读(读数面口径):流派 tier ≥1 = 成型(档一即判——需求卡片完成定义「标签+档位激活引擎可判成型」)
|
||||
static func is_formed(tiers: Dictionary, archetype: String) -> bool:
|
||||
return int(tiers.get(archetype, 0)) >= 1
|
||||
@@ -1 +0,0 @@
|
||||
uid://6d12lkx5w2x8
|
||||
@@ -160,7 +160,7 @@ func start_level(level_index: int, seed_val: int, base_override_in: Dictionary =
|
||||
# 三键 {atk, max_hp, armor_class}、缺键/-1 = 0、负值 clamp 0。游戏直入口仍恒白板——
|
||||
# 注入面只服务数值验证工具,非玩家可达路径)
|
||||
_external = false
|
||||
_rest_handler = Callable(self, "rest_heal_amount")
|
||||
_rest_handler = rest_heal_amount
|
||||
_ledger = {"hero_hp": 0, "gp": 0}
|
||||
var row := _find_level_row(level_index)
|
||||
if row.is_empty():
|
||||
|
||||
@@ -38,10 +38,6 @@ func _init(db_ref: ConfigDb, action_economy_ref: ActionEconomy) -> void:
|
||||
|
||||
# ---- 板态 ----
|
||||
|
||||
func has_board() -> bool:
|
||||
return _board != null
|
||||
|
||||
|
||||
# 板产物只读出口(E2 收口——战斗结算 快照 / 组合根 rebuild / 探针经此取板,禁再直读字段)
|
||||
func current_board() -> BoardData:
|
||||
return _board
|
||||
|
||||
@@ -432,14 +432,6 @@ func set_attune_refresh_level(n: int) -> void:
|
||||
|
||||
# 同调位计数源组装(Attunement 服务取数口——clear_count = 逐关通关次数合计〔含重复关,底稿 §2.1 口径〕;
|
||||
# clear_count(level_index) 逐关访问器零改动复用)
|
||||
func attunement_counters() -> Dictionary:
|
||||
var total := 0
|
||||
var counts: Dictionary[Variant, Variant] = _data["meta"]["level_clear_counts"]
|
||||
for k in counts.keys():
|
||||
total += int(counts[k])
|
||||
return {"clear_count": total, "boss_kill_count": boss_kill_count()}
|
||||
|
||||
|
||||
func recent_summaries() -> Array:
|
||||
return _data["meta"]["recent_summaries"].duplicate(true) # 值拷贝出户(本类契约「禁碰内部结构」——消费方直改不得渗入存档内存态)
|
||||
|
||||
|
||||
@@ -65,14 +65,6 @@ func inventory_count() -> int:
|
||||
|
||||
|
||||
# 持有数(迭代 10 奖励重构批——同调位上限判定读数:只计未消耗件;Used 不可逆即不再持有)
|
||||
func holding_count() -> int:
|
||||
var n := 0
|
||||
for rec in _items:
|
||||
if not bool(rec.get("used", false)):
|
||||
n += 1
|
||||
return n
|
||||
|
||||
|
||||
# 同调位守卫谓词——迭代 11 第①批 T7 退役(读取源 transitional_sync_slots 过渡键已随表退役;
|
||||
# 容量闸正主 = 营地装配面 Attunement.slots 满位禁选。函数体保留空壳防四散引用误删遗漏——
|
||||
# T8 冒烟「过渡键读取点归零」断言覆盖)
|
||||
@@ -80,14 +72,6 @@ func holding_count() -> int:
|
||||
|
||||
# 持有件记录(迭代 10 追加批——奖励节点替换子交互数据源:只列未消耗件,handle 定位丢弃目标)
|
||||
# 丢弃(同调位替换交互节点渠道——腾位收新;与 Used 消费分轨的一次性移除,快照不再含)
|
||||
func discard_item(handle: int) -> bool:
|
||||
for i in _items.size():
|
||||
if int(_items[i].get("handle", -1)) == handle and not bool(_items[i].get("used", false)):
|
||||
_items.remove_at(i)
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
# 板级零信息可用性预判(图标置灰/入口禁用判据——GDD「整张图都没东西可看」级):
|
||||
# 真视恒可用(零雷窗口=信息非空);AP 类恒可用(组合判据取 OR——任一效果有信息即可用);
|
||||
# 纯预读行 = 板上还有未开格才可用。(积点件不入使用面——反哺批⑤自动兑付无玩家入口)
|
||||
|
||||
@@ -52,10 +52,6 @@ func _init(ctx: CurioFlowContext) -> void:
|
||||
|
||||
|
||||
# 停点在途判据(组合根 _on_battle_end_continue 分派面——战斗总结确认后开三选一)
|
||||
func has_pending() -> bool:
|
||||
return not _pending_curio.is_empty()
|
||||
|
||||
|
||||
# 续玩停点恢复入口(true=已接手呈现,调用方中止后续分派)。空候选降级(2026-10-06 用户令):
|
||||
# 候选 0 件不开选择面(空面无卡无钮=死面)——消化停点后按上下文直落后续推进(战斗总结面已
|
||||
# 给过玩家确认拍,三选一环节整体跳过)
|
||||
|
||||
@@ -42,6 +42,14 @@
|
||||
# autoload 占净名),存档读盘挂 autoload _ready(时序与旧 main._ready 读盘等价)。
|
||||
extends Control
|
||||
|
||||
# autoload 节点路径单点(迭代 27 T6 P2-2 降格实现:审计处方「编译期全局名」与本仓 --script
|
||||
# 模式编译器不解析裸 autoload 标识符冲突〔run_all.gd 头注+pacing 实证〕——字符串拼写风险
|
||||
# 收敛到四常量,类型面由读视图属性承载)
|
||||
const AUTOLOAD_PATH_CFG := "/root/ConfigDB"
|
||||
const AUTOLOAD_PATH_RNG := "/root/RngService"
|
||||
const AUTOLOAD_PATH_SAVE := "/root/SaveManager"
|
||||
const AUTOLOAD_PATH_META := "/root/MetaProgression"
|
||||
|
||||
const UiAssembler := preload("res://presentation/ui_assembler.gd")
|
||||
const Narrator := preload("res://presentation/battle_narrator.gd")
|
||||
const ModalStack := preload("res://presentation/modal_stack.gd")
|
||||
@@ -62,10 +70,10 @@ var run_scope = null # 会话状态承载(run_scope.gd——迭
|
||||
# 节点路径双模式通用;组合根调用点/探针挂载面 main.save_manager 语义零迁移)。
|
||||
var save_manager: SaveManagerCore:
|
||||
get:
|
||||
return get_node("/root/SaveManager")
|
||||
return get_node(AUTOLOAD_PATH_SAVE)
|
||||
var meta: MetaProgressionCore:
|
||||
get:
|
||||
return get_node("/root/MetaProgression")
|
||||
return get_node(AUTOLOAD_PATH_META)
|
||||
var logger = null # 试玩日志器(JSONL 持久化 + 卡死诊断转储——呈现层组件)
|
||||
var _debug_entry := false # 调试会话门控(迭代 18 卡⑦——DS_DEBUG=1:启动即开浮窗+两屏角标点亮;_ready 赋值)
|
||||
var _seed_edit: LineEdit
|
||||
@@ -175,7 +183,7 @@ func _begin_session(adventure_session: bool) -> void:
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
db = get_node("/root/ConfigDB")
|
||||
db = get_node(AUTOLOAD_PATH_CFG)
|
||||
if not db.is_ready:
|
||||
var ok: bool = db.load_tables("res://data/tables", false)
|
||||
if not ok:
|
||||
@@ -187,8 +195,8 @@ func _ready() -> void:
|
||||
settings_store = SettingsStore.new()
|
||||
settings_store.load_settings()
|
||||
settings_store.apply()
|
||||
_debug = DebugSessionScript.new(db, get_node("/root/RngService"),
|
||||
Callable(self, "_debug_hero_override"), Callable(self, "_seed_value"))
|
||||
_debug = DebugSessionScript.new(db, get_node(AUTOLOAD_PATH_RNG),
|
||||
_debug_hero_override, _seed_value)
|
||||
_debug.battle_created.connect(_on_debug_battle_created)
|
||||
_debug.battle_ready.connect(_on_debug_battle_ready)
|
||||
_build_ui()
|
||||
@@ -482,7 +490,7 @@ func _resume_from_menu() -> void:
|
||||
|
||||
# 冒险编排构建+接线(开新局/续玩共用——信号连接只在组合根,ADR-0001;断点注入同口)
|
||||
func _wire_adventure() -> void:
|
||||
run_scope.adventure = AdventureRunner.new(db, get_node("/root/RngService"))
|
||||
run_scope.adventure = AdventureRunner.new(db, get_node(AUTOLOAD_PATH_RNG))
|
||||
run_scope.adventure.step_row.connect(_on_step_row)
|
||||
run_scope.adventure.round_started.connect(_on_round_started)
|
||||
run_scope.adventure.board_changed.connect(_on_board_changed)
|
||||
@@ -1343,7 +1351,7 @@ func _debug_run_data() -> Dictionary:
|
||||
func _current_master_seed() -> int:
|
||||
if run_scope.adventure != null:
|
||||
return int(run_scope.adventure.master_seed)
|
||||
return int(get_node("/root/RngService").master_seed)
|
||||
return int(get_node(AUTOLOAD_PATH_RNG).master_seed)
|
||||
|
||||
|
||||
func _close_debug_overlay() -> void:
|
||||
|
||||
@@ -167,10 +167,6 @@ func press_refresh() -> void:
|
||||
_refresh_btn.pressed.emit()
|
||||
|
||||
|
||||
func selected_id() -> String:
|
||||
return _selected
|
||||
|
||||
|
||||
# 兑付反馈态(curio_resolved 到达——结果行追加在头部之后;唯一出口 = 继续)
|
||||
func show_result(text: String) -> void:
|
||||
_label.text = _header + "\n" + text
|
||||
|
||||
@@ -13,9 +13,4 @@ extends Node2D
|
||||
var world_font: Font = null # 字体注入槽位(null = ThemeDB.fallback_font——BattleStageView.set_world_font 注入)
|
||||
|
||||
# C6 headless 可验判据(ADR-0003 Decision 4):注入字体非空 + 中文字形 has_char + 采样文本宽度 > 0。
|
||||
# 实际光栅观感归批末目检清单。
|
||||
func font_probe() -> Dictionary:
|
||||
var f: Font = world_font if world_font != null else ThemeDB.fallback_font
|
||||
var has_char: bool = f.has_char("人".unicode_at(0))
|
||||
var width: float = f.get_string_size("兑现演出区", HORIZONTAL_ALIGNMENT_LEFT, -1, 14).x
|
||||
return {"font": f, "has_char": has_char, "width": width}
|
||||
# 实际光栅观感归批末目检清单。
|
||||
@@ -37,7 +37,10 @@ var _portrait_flip := false
|
||||
# 主角三态切换(迭代 6 T3):state 名 → 纹理(battle_stage_view 组合点注册);缺态=保持现纹理
|
||||
# (缺位回退链延伸——三态素材缺任一不炸不空)。敌站桩不注册不消费。
|
||||
var _hero_tex := {}
|
||||
var _hero_state := "idle"
|
||||
enum HeroState { IDLE, RESET, ATTACK, HIT } # 主角三态+复位哨兵(迭代 27 T6——裸字符串 enum 化;外部 String 契约=register/set 形参零变化)
|
||||
const _HS_NAME := {HeroState.IDLE: "idle", HeroState.RESET: "reset", HeroState.ATTACK: "attack", HeroState.HIT: "hit"}
|
||||
const _HS_VALUE := {"idle": HeroState.IDLE, "reset": HeroState.RESET, "attack": HeroState.ATTACK, "hit": HeroState.HIT}
|
||||
var _hero_state: int = HeroState.IDLE
|
||||
var _state_revert_tw: Tween
|
||||
var _order := 1
|
||||
var _intent_glyph := ""
|
||||
@@ -330,7 +333,7 @@ func _revive() -> void:
|
||||
modulate = Color(1, 1, 1)
|
||||
rotation_degrees = 0.0
|
||||
if _kind == "hero":
|
||||
_hero_state = "reset" # 强制回 idle 态(绕过同态早退)
|
||||
_hero_state = HeroState.RESET # 强制回 idle 态(绕过同态早退)
|
||||
set_hero_state("idle")
|
||||
_refresh_portrait_glyph()
|
||||
if slot_row != null:
|
||||
@@ -368,11 +371,12 @@ func register_hero_state(state: String, tex: Texture2D) -> void:
|
||||
# 状态切换:现纹理换注册态(attack/hit);未注册态名或缺位 = 保持现纹理不炸。
|
||||
# 非 idle 态自动短驻回归 idle(0.35s——演出一拍即回,结算收尾另有显式 idle 兜底)。
|
||||
func set_hero_state(state: String) -> void:
|
||||
if _kind != "hero" or state == _hero_state:
|
||||
var target: int = _HS_VALUE.get(state, -1)
|
||||
if _kind != "hero" or target == _hero_state:
|
||||
return
|
||||
if not _hero_tex.has(state) and state != "idle":
|
||||
return
|
||||
_hero_state = state
|
||||
_hero_state = target
|
||||
if _portrait_sprite != null and _hero_tex.has(state):
|
||||
_portrait_sprite.texture = _hero_tex[state]
|
||||
if _state_revert_tw != null and _state_revert_tw.is_valid():
|
||||
@@ -384,14 +388,14 @@ func set_hero_state(state: String) -> void:
|
||||
|
||||
|
||||
func _settle_hero_idle() -> void:
|
||||
_hero_state = "idle"
|
||||
_hero_state = HeroState.IDLE
|
||||
if _portrait_sprite != null and _hero_tex.has("idle"):
|
||||
_portrait_sprite.texture = _hero_tex["idle"]
|
||||
|
||||
|
||||
# 三态探针出口(fx_probe——当前态名+注册态集合)
|
||||
func hero_state_probe() -> Dictionary:
|
||||
return {"state": _hero_state, "registered": _hero_tex.keys()}
|
||||
return {"state": _HS_NAME.get(_hero_state, "idle"), "registered": _hero_tex.keys()}
|
||||
|
||||
|
||||
func _portrait_color() -> Color:
|
||||
|
||||
+3
-3
@@ -24,8 +24,8 @@
|
||||
## 当前位置(2026-10-14 刷新)
|
||||
|
||||
- **里程碑语义(2026-10-09 立规换代,详见下方里程碑表的换代注)**:现行里程碑 = **M3「Alpha 版本的完整实现」**——用户未明令宣布完成前停留 M3,迭代只排 M3 需求;M4=Beta 版本的完整实现,一律不排期。下文里程碑表的旧编号(M-3/M-4)保留作历史序列,语义以本节为准。
|
||||
- **迭代进度**:迭代 19 五卡全部已入库(2026-10-08);**迭代 20=专长实装批 ✅ 已入库**(2026-10-11,出口闸全绿;残留人闸=实机目检五件+V20/V21/V22 人工核对半,07 在册);**迭代 21=天赋树实装批 ✅ 已入库(2026-10-12 U0 开工单会话交付,T0-T7 全绿;残留人闸=实机目检四柜台)**;**迭代 22=秘宝体系实现重构落地批 ✅ 已入库(2026-10-12 单会话交付,T1-T7 全绿;残留人闸=实机目检秘宝解锁-装配流程)**;**迭代 23=锻造工坊实装批 ✅ 已入库(2026-10-12 单会话交付,T0-T7 全绿;残留人闸=实机目检工作间形态与购买交互)**;**迭代 24=敌人表内容修批(三关)✅ 已入库(2026-10-13 /goal+iter U0 开工单会话交付——N1 (1,2) 降档 hp22/ac2·N2 毒吐盾击两行六池·N3 敌方 attack_type 轴全填 normal+敌方结算克制消费点;冒烟 949/0+run_all 25 套+重闸全绿+MC 同种子配对 40 局×both 位移在带;实现报告=design/qa/iter24-实现报告-2026-10-13.md;残留人闸=实机目检三观测〔07 ㉓〕;代拍板追认单+GDD 反哺点五条待用户;**本迭代位仍预留后续追加卡——用户将把其他需求陆续编入本迭代**);;**迭代 25=UI 全局主题批 ✅ 已入库**(2026-10-13 用户令编入,/goal+iter U0 单会话交付:全局主题资源 main_theme.tres 挂载+两处局部做法退役+冒烟 V1-V6 断言 38 条,冒烟 987/0+重闸全绿;实现报告=design/qa/iter25-实现报告-2026-10-13.md;残留人闸=实机目检全屏巡检〔07 ㉔〕);**迭代 26=UI 交互与观感批已编入待开工**(2026-10-14 用户令;需求卡片 v1.2 零待裁点;开工门=U0——用户新会话 /iter 26 发令;本迭代位预留后续追加卡,同迭代 24 先例);**迭代 27=代码架构技术债修复批 🔄 U0 已开工**(2026-10-14 用户令编入+同日 /goal+iter 27 发令;需求卡片 v1.2 三点全裁零待裁——①第三个 autoload/②单类持四账/③审计五段);**迭代 28+**=M4 数值批(Beta 位·未排期——用户令 2026-10-07:后续新迭代一律不先做 M4;迭代 24/25/26/27 占位后本批顺延)。
|
||||
- **近期主战场**:迭代 20/21/22/23/24/25/26 残留人闸(实机目检六批,07 在册);**在飞=迭代 27 代码架构技术债修复批**(需求卡片 v1.2 零待裁,U0=2026-10-14 发令开工;M4 数值批殿后顺延 28+,各批 provisional 终值归其统一标定)。
|
||||
- **迭代进度**:迭代 19 五卡全部已入库(2026-10-08);**迭代 20=专长实装批 ✅ 已入库**(2026-10-11,出口闸全绿;残留人闸=实机目检五件+V20/V21/V22 人工核对半,07 在册);**迭代 21=天赋树实装批 ✅ 已入库(2026-10-12 U0 开工单会话交付,T0-T7 全绿;残留人闸=实机目检四柜台)**;**迭代 22=秘宝体系实现重构落地批 ✅ 已入库(2026-10-12 单会话交付,T1-T7 全绿;残留人闸=实机目检秘宝解锁-装配流程)**;**迭代 23=锻造工坊实装批 ✅ 已入库(2026-10-12 单会话交付,T0-T7 全绿;残留人闸=实机目检工作间形态与购买交互)**;**迭代 24=敌人表内容修批(三关)✅ 已入库(2026-10-13 /goal+iter U0 开工单会话交付——N1 (1,2) 降档 hp22/ac2·N2 毒吐盾击两行六池·N3 敌方 attack_type 轴全填 normal+敌方结算克制消费点;冒烟 949/0+run_all 25 套+重闸全绿+MC 同种子配对 40 局×both 位移在带;实现报告=design/qa/iter24-实现报告-2026-10-13.md;残留人闸=实机目检三观测〔07 ㉓〕;代拍板追认单+GDD 反哺点五条待用户;**本迭代位仍预留后续追加卡——用户将把其他需求陆续编入本迭代**);;**迭代 25=UI 全局主题批 ✅ 已入库**(2026-10-13 用户令编入,/goal+iter U0 单会话交付:全局主题资源 main_theme.tres 挂载+两处局部做法退役+冒烟 V1-V6 断言 38 条,冒烟 987/0+重闸全绿;实现报告=design/qa/iter25-实现报告-2026-10-13.md;残留人闸=实机目检全屏巡检〔07 ㉔〕);**迭代 26=UI 交互与观感批已编入待开工**(2026-10-14 用户令;需求卡片 v1.2 零待裁点;开工门=U0——用户新会话 /iter 26 发令;本迭代位预留后续追加卡,同迭代 24 先例);**迭代 27=代码架构技术债修复批 ✅ 已入库**(2026-10-14 /goal+iter U0 开工单会话交付:三屏场景化+会话物化+五段 Segment+RunLedger+ModalFlow+类型闸+卫生件五波全落;逐位一致对拍三变体五跑全同;实现报告=design/qa/iter27-实现报告-2026-10-14.md;残留人闸=实机目检五件〔07 ㉖〕;代拍板追认单十五项+GDD 反哺点两条待用户);**迭代 28+**=M4 数值批(Beta 位·未排期——用户令 2026-10-07:后续新迭代一律不先做 M4;迭代 24/25/26/27 占位后本批顺延)。
|
||||
- **近期主战场**:迭代 20/21/22/23/24/25/26 残留人闸(实机目检六批,07 在册);**下一前沿=待用户发令**(迭代 27 已入库收口;M4 数值批殿后顺延 28+,各批 provisional 终值归其统一标定;迭代 20~27 残留人闸七批 07 在册)。
|
||||
- **实时状态**:以根目录 [active.md](active.md) 顶部「当前状态快照」节为准(`stage.txt` 已定性为旧阶段开关,仅存档)。
|
||||
|
||||
## 主线路线(里程碑 × 迭代序列)
|
||||
@@ -83,7 +83,7 @@
|
||||
| 迭代 24 | **①敌人表内容修批(三关)(2026-10-13 用户令编入;**本迭代位预留后续追加卡**——用户将把其他需求陆续编入本迭代)**:需求卡片=`design/research/需求卡片-敌人表内容修批-2026-10-13.md`(**v1.1**——grilling 复核九问 Q1-Q9 已全裁、零待裁点、开工门=U0)。三件事合一:**N1** 第一关 (1,2) 降档(`enemy.tres:48` 改两值:`hp` 50→22、`armor_class` 3→2;**敌种 `bugbear` 不动**——`enemy.tres:594-600` 注释载明该行 50 血系 2026-09-24 用户裁决的设计而非填错,且 `hobgoblin` 无立绘,故「改敌种」案已否决;本批定性=阶名化解方案实机未达预期按 2026-10-13 体验反馈重裁)· **N2** 第二/三关普通敌技能投放(`skills.tres` 12→14 行:新增 `venom_spit` 毒吐 damage 1.6/CD2 挂 (2,5)/(2,6)/(2,7) 巨蜘蛛族、`shield_bash` 盾击 damage 1.7/CD3 挂 (3,0)/(3,5)/(3,7) 灰矮人族;**首遇教学位 (2,4) 池不动**,venom_spit 自 (2,5) 起投;两新行均不带 `rider_mult`——低 atk 下恒被 `damage_floor` 兜成 1 与 0.75 档等效)· **N3** 敌方 `attack_type` 加列并全填 `normal`(挂**敌种行**、20 行同值,不做差异化;`enemy_table.gd` 加枚举校验 + `unit_container.gd:119` 加单位快照 + `battle_orchestrator.gd:1406` 第 9 参由 `""` 改传值;全局平移=穿重甲受伤 −1 / 魔法护甲 +1 / 轻甲 0,使锻造甲路线首次具备战斗意义)。**契约要点**:池与敌种键属**契约级**,改必同步 `smoke_all.gd:3211` `expect_pools`(N1 因键值不变零改动、N2 同步 6 键);节点图拓扑零触碰(A1 关卡节点图重构的地盘);(1,1) 地精一伙不在本批范围(「第二个节点」字面偏差已登记 06)。**收口去向**:06「第一关遭遇表数值异常」「第二关技能池与投放」与锻造工坊条迁移面⑥ 三条一并销号;08「二·内容量」敌种池行注摘除 | ✅ 已入库(2026-10-13 单会话交付,出口闸全绿:冒烟 949/0+run_all 25 套〔485 批基线漂移 24→25 在案〕+探针 click/full+render_gate golden 0.00%+doc 三闸/熵增对基线零新增+MC 配对三组读数;实现报告=design/qa/iter24-实现报告-2026-10-13.md;残留人闸=实机目检三观测 07 ㉓) |
|
||||
| 迭代 25 | **①UI 全局主题批(引擎原生控件接管皮肤)(2026-10-13 用户令编入;UI 美化三层诊断 · 第一层第一条)**:**✅ 已全批入库(2026-10-13 /goal+iter U0 开工单会话交付,worktree g-plan2-iter25-theme 分支 iter25-theme-20261013)**——**T0 主题资源**:新建 `game/assets/theme/main_theme.tres` 挂 `project.godot` `gui/theme/custom`(15 类型全覆盖:V/HScrollBar·ScrollContainer·H/VSlider·TooltipPanel/Label·LineEdit·SpinBox·H/VSeparator + 预盖 CheckBox/CheckButton/OptionButton/PopupMenu 弹层;`default_font` 显式指向现役同字体文件=V6 中文字形防御;位图由 `tools/gen_theme_icons.py` 一次性生成落 `game/assets/art/ui/gen/`,色值溯源表落 `game/assets/theme/README.md`)· **T1 换代退役**:`ui_kit.gd` 的 `tooltip_theme()`/`_tip_theme` 与 `styled_slider()` 样式段、`ui_assembler.gd` 挂载行同批删除(禁新旧并存),settings_overlay 几何内联+debug_overlay `_slider_row` 双轨消隐· **T2 断言与文档同步闸**:冒烟新增 V1-V6 主题词条断言 38 条。**顺手销号**=06 第三层「UI 元素细节修」之①(音量滑轨两段对比度重配=已填充段 BG_ROOT #3A2E22 对暖石 #B8A582 实测 5.49:1)。**契约遵守**:🔴 Button 类型词条零接触(冒烟断言在闸)· 🔴 focus 族词条零定义(全主题扫描断言)· 🔴 零新增美术素材(位图=脚本生成纯色/几何)· 🔴 全局纹理过滤未动。**引擎事实订正(呈报追认)**:Godot 4.7.2 源码+默认主题链双查实证——①CheckButton 图标词条名与 CheckBox 同套 `checked`/`unchecked`(卡片 v1.2 注③「CheckButton 用 on/off」不成立,按引擎事实落位)②Slider 无 `grabber_pressed` 图标槽(冻结表「柄·按」值 GOLD_DEEP 留档未落位)③ScrollBar 柄是 StyleBox 非 Icon(无需位图)④4.7 导入参数已无逐贴图 filter 标志(位图原生尺寸消费无滤波伪影)。**闸**:冒烟 987/0(基线 949+本批 38 断言)+run_all 25 套+probe click/full+render_gate golden 0.00%+doc 三闸/熵增对基线零新增;MC 零跑(零数值零行为=纯呈现)。**收口去向**:06「UI 全局主题资源缺失」条移除+「UI 元素细节修」①销号;08 升 v1.3(三·界面主题行→在役、五·表现细节修行注①销号);07 ㉔ 全屏巡检登记;实现报告=design/qa/iter25-实现报告-2026-10-13.md。**待用户**:实机目检全屏巡检+专项观察点二(07 ㉔,登记不阻塞)+代拍板追认单(位图不入 git 政策口径/CheckButton 词条名订正等)+GDD 反哺点(组件规格是否立条款入 art-bible §7 等)。↓ 原任务登记:三件事合一——**T0** 新建 `game/assets/theme/main_theme.tres` 并挂 `project.godot` 的 `gui/theme/custom`,覆盖滚动条 / 滑轨 / 悬停气泡 / 输入件 / 分隔线等引擎原生控件,并预盖 CheckBox / CheckButton / OptionButton 及其弹层 PopupMenu(须在新主题内显式设 `default_font`=现役同一字体文件;新增小位图落 `game/assets/art/ui/gen/`,色值溯源表落 `game/assets/theme/README.md`)· **T1** 退役 `ui_kit.gd` 的 `tooltip_theme()` 与 `styled_slider()` 两处局部做法、消 `debug_overlay._slider_row` 双轨(🔴 旧实现同批删除)· **T2** 断言与文档同步闸。契约要点:🔴 Button 类型词条零接触 · 🔴 focus 族词条零定义 · 🔴 不新增美术素材、不改美术圣经 §7 · 🔴 全局纹理过滤不动 | ✅ 已入库(出口闸全绿+实机目检归用户 07 ㉔ 在册) | T0-T2≈0.5–1d(实际单会话) |
|
||||
| 迭代 26 | **①UI 交互与观感批(2026-10-14 用户令编入;UI 美化三层诊断 · 第一层第二/三条+第三层四件;本迭代位预留后续追加卡,同迭代 24 先例)**:需求卡片=`design/research/需求卡片-UI交互与观感批-2026-10-13.md`(**v1.2**——grilling 两轮八裁全落、零待裁点、卡片成立)。六项:**T1 按钮五态矩阵**(悬停=乙案 modulate 提亮〔与 primary_button 现行 `CANDLE.lightened(0.06)` 同纪律〕/禁用=本族底+α0.45 幽灵化/焦点=INK 2px 内缩 1px/危险钮补本族 pressed;走逐实例 override,迭代 25 两条主题红线断言维持不换代)· **T2 全局纹理过滤**(`project.godot` `default_texture_filter=0`+vignette/gradient_base/beams 显式 LINEAR 白名单+翻转面全枚举)· **T3 <4.5:1 换墨**(站桩顺位/护甲徽标换同族亮档+RAP 行 STONE_DEEP,机检断言锚定)· **T4 光柱连续 alpha 渐变**(0→0.05→0 横向+纵向衰减)· **T5 元素细节余②③**(BCard 图标槽明度差降档/商店卡片区垂直居中/营地四栏等高)· **T5b 诊断转储钮移调试浮窗**(`dump_diagnosis` 功能保留)。🔴 契约 5 条(主题层零新增词条/零新美术素材/棋盘零触碰/对比度 ≥4.5:1/旧实现同批清理);验证闸 V1-V7;代拍板白名单八项;反哺点四条;**渲染闸 golden 面处置**=T6 第 4 步(徽标换墨落 board golden 裁剪区:闸红→核热区限预期面→显式重制基线+呈报→复闸,超预期=L3)。**范围订正**(grilling 实查,iter25 滑轨条同款先例):②垫块仅三选一 BCard(商店卡实为纯文字行卡)/③仅商店+营地(三选一已居中)/危险钮「无按下态」订正为「在但皮肤错配」。估时 T0-T6≈2–2.5d | **✅ 已全批入库(2026-10-14 /goal+iter U0 开工单会话交付,worktree g-plan2-iter26-ui 分支 iter26-ui-20261014 七提交)**——T0 基线+枚举(含卡片 §2.2 枚举漏项勘误)/T1 按钮五态(悬停 modulate 提亮/禁用 α0.45 幽灵化/焦点 INK 2px 内缩 1px/危险钮本族按压态)/T2 全局 Nearest+平滑渐变件 LINEAR 白名单/T3 三处换墨(GOLD_BRIGHT/HERO_BLUE_BRIGHT/STONE_DEEP,6.47/5.88/5.98:1)/T4 光柱连续 alpha/T5 图标槽柔和档+商店居中+营地四栏等高/T5b 诊断钮迁调试浮窗;冒烟 987→1055/0(+68 断言)+run_all 25 套+probe click/full+render_gate golden 0.00%(登记即结未重制)+doc 三闸/熵增对基线零新增;MC 零跑(零数值零行为=纯呈现);实现报告=design/qa/iter26-实现报告-2026-10-14.md;残留人闸=实机目检五项(07 ㉕);待用户=代拍板追认单十三项+GDD 反哺点四条 | T0-T6≈2–2.5d(实际单会话) |
|
||||
| 迭代 27 | **①代码架构技术债修复批(2026-10-14 用户令编入;来源=[代码架构与实现质量审计报告-2026-10-14](design/research/代码架构与实现质量审计报告-2026-10-14.md),双席审计基线 97de02c,已逐条复核)**:需求卡片=`design/research/需求卡片-代码架构技术债修复批-2026-10-14.md`(**v1.2——三点全裁零待裁〔2026-10-14 用户三裁全按推荐案:①第三个 autoload/②单类持四账/③审计五段〕,卡片成立**)。五波:· **波一 场景拆分+局生命周期物化(≈4-5d)**〔P0-1/P0-2:屏容器 .tscn 切分=开始菜单根场景+营地场景+冒险场景〔内含 level_map/battle 两容器〕,视图代码原样搬、**40+ views 不转 .tscn**;SaveManager/MetaProgression 升格跨场景持有者;「一局」物化为可整体 `queue_free()` 的节点,`main.gd:647-657`/`:555-559` 手工清单消亡;13 个 smoke 探针挂载假设同批迁移〕· **波二 `_settle` 拆段(≈1.5d)**〔P1-1:五段 Segment 类 grant/aura/combat/decay/verdict,24 处 kind 分派随段归位,姊妹病灶 `damage_controller.gd:272` 148 行同批拆〕· **波三 账本收口(≈1.5d)**〔P1-4 共享四账 Ledger 类化+P1-2 刷新双账删 main 副本+P1-3 summary 增 `gp_final` 键、删 `gp_shadow_ledger.gd`〕· **波四 组合根可测化抽取+模态协议内聚(≈1.5-2d)**〔P1-5/P2-7;**须在波一落地后重估抽取面再动**〕· **波五 类型闸收尾+卫生件包(≈3d)**〔P1-6 拉闸+存量 73 处收口,**须在其他重构全部落地后**;P2 七组顺手带〕。🔴 契约 6 条(**零行为变更·重构前后同种子完整局输出逐位一致**/只拆不重写/views 不转 .tscn/探针契约零破坏/信号纪律不变/执行顺序锁+渲染零漂移);**核心验收=逐位一致对拍**(RngService 单盐流在役);验证闸 V1-V9;代拍板白名单九项;反哺点两条(architecture+ADR 系列/code-conventions)。 | **🔄 U0 已开工**(2026-10-14 用户令编入+同日 /goal+iter 27 发令,单会话交付进行中;卡片 v1.2 三点已裁;本迭代位预留后续追加卡,同迭代 24/26 先例) | T0-T7≈12-14d |
|
||||
| 迭代 27 | **①代码架构技术债修复批(2026-10-14 用户令编入;来源=[代码架构与实现质量审计报告-2026-10-14](design/research/代码架构与实现质量审计报告-2026-10-14.md),双席审计基线 97de02c,已逐条复核)**:需求卡片=`design/research/需求卡片-代码架构技术债修复批-2026-10-14.md`(**v1.2——三点全裁零待裁〔2026-10-14 用户三裁全按推荐案:①第三个 autoload/②单类持四账/③审计五段〕,卡片成立**)。五波:· **波一 场景拆分+局生命周期物化(≈4-5d)**〔P0-1/P0-2:屏容器 .tscn 切分=开始菜单根场景+营地场景+冒险场景〔内含 level_map/battle 两容器〕,视图代码原样搬、**40+ views 不转 .tscn**;SaveManager/MetaProgression 升格跨场景持有者;「一局」物化为可整体 `queue_free()` 的节点,`main.gd:647-657`/`:555-559` 手工清单消亡;13 个 smoke 探针挂载假设同批迁移〕· **波二 `_settle` 拆段(≈1.5d)**〔P1-1:五段 Segment 类 grant/aura/combat/decay/verdict,24 处 kind 分派随段归位,姊妹病灶 `damage_controller.gd:272` 148 行同批拆〕· **波三 账本收口(≈1.5d)**〔P1-4 共享四账 Ledger 类化+P1-2 刷新双账删 main 副本+P1-3 summary 增 `gp_final` 键、删 `gp_shadow_ledger.gd`〕· **波四 组合根可测化抽取+模态协议内聚(≈1.5-2d)**〔P1-5/P2-7;**须在波一落地后重估抽取面再动**〕· **波五 类型闸收尾+卫生件包(≈3d)**〔P1-6 拉闸+存量 73 处收口,**须在其他重构全部落地后**;P2 七组顺手带〕。🔴 契约 6 条(**零行为变更·重构前后同种子完整局输出逐位一致**/只拆不重写/views 不转 .tscn/探针契约零破坏/信号纪律不变/执行顺序锁+渲染零漂移);**核心验收=逐位一致对拍**(RngService 单盐流在役);验证闸 V1-V9;代拍板白名单九项;反哺点两条(architecture+ADR 系列/code-conventions)。 | **✅ 已全批入库(2026-10-14 /goal+iter U0 开工单会话交付,worktree g-plan2-iter27-techdebt 分支 iter27-techdebt-20261014 七提交)**——波一 三屏场景化+run_scope 会话物化+双 autoload(7a0d57d)/波二 _settle 五段 Segment+英雄攻击拆步(26301ba)/波三 RunLedger 单类四账+刷新双账删副本+gp_final 删影子账(6fd7d78)/波四 ModalFlow+互斥域 tags+双 context(8b9e556)/波五a 类型闸 368 参数化+审计器+warning 配置(b605022)/波五b 卫生件 13 死代码+FeatsEngine 退役+Callable 换装+状态机 enum 化+ConfigDB 归根+resolver 解耦(T6 笔)/T7 文档同步(本笔)。**闸**:逐位一致对拍三变体五跑全同(V1 核心验收)+冒烟 1055→1081/0(+V2 屏壳 11+V3 两连局 11+V4 段类 16+V6 模态 19+V5 快照 3+V7 2 断言)+run_all 25→27 套+probe click+render golden 0.00%+static_scan S1/S2/S4/S9 全绿(历史 cd 静默空转顺修);MC 对拍=parity_anchor 三变体×40 局×RUNSUM+JSONL 双面(工具入库 tools/parity_anchor.py);实现报告=design/qa/iter27-实现报告-2026-10-14.md(代拍板追认单十五项+GDD 反哺点两条);残留人闸=实机目检五件(07 ㉖);审计报告本体按退役规则 git rm | T0-T7≈12-14d(实际单会话) |
|
||||
| 迭代 28+ | **M4 数值批(**原 22+;迭代 21 已编入天赋树实装批、迭代 22 已编入秘宝实装批(均 2026-10-11 用户令)、迭代 23 已编入锻造工坊实装批(2026-10-12 用户令)**;迭代 24 已由用户令编入敌人表内容修批、迭代 25 已由用户令编入 UI 全局主题批(2026-10-13)、迭代 26 已由用户令编入 UI 交互与观感批(2026-10-14)、**迭代 27 已由用户令编入代码架构技术债修复批(2026-10-14)**,本批顺延 28+**——**Alpha 收官位·未排期**〔2026-10-09 语义换代:M4=Beta 阶段、非 Alpha 收官位,M3 未由用户明令关闭前不排期维持〕——2026-10-05 用户令编入迭代 17 卡②;2026-10-06 用户令移出独立成批并定序「Alpha 阶段最后——内容补全先行、统一数值调整殿后」〔当日曾被编入迭代 18 为收官卡,2026-10-07 用户令撤回〕;**2026-10-07 用户令二次后移:后续新迭代(迭代 20 起)一律不先做 M4,除非用户明确要求启动 M4 批次**)**:四件数值欠账合一批——①削弱档位终值(weaken 现值 −65/duration 2/refresh 考证在册;叠层改续时语义已定案,差 duration 终值+当量锚复算)②调参批数值点评(06 条目现行登记五条——任务口径「八条」与条目五条不符,需求卡片 §2.2 已呈报差异以条目为准)③迭代 10 奖励重构联动欠账①②(钥石产出重标 boss_keystone 首杀 3/3/3·复杀 2/2/3 provisional + 通关率带重扫〔通关回血 20%+AP 件首轮 +1〕)④元进度定价剩余面(forge base 20/比 150 考证在册——06 条目文本「base 10」滞后于 2026-09-22 对齿批已呈报;Boss 两档终值)。读数义务随批=迭代 14 两件后置复算(T6 MC 四带复算+T7 技能池节奏重测,均挂 07);顺路修复 damage_probe A1 改前既有红灯(判式换代批出口报告 §四.7 在册)。**硬约束:一切 MC/verifier 跑批发起前须用户批准;调参联动禁独立调参网络(β 带 [1.2,2.5] 逐 u 检算)**。需求卡片=`design/research/需求卡片-M4数值批-2026-10-05.md`(**v1.2 2026-10-06 案C 增补+联审修订**:v1.1 三事实与第五推算件照旧;联审=P3 转正顺延至重扫读数后/检算工具 WEAKEN_PCT 入同步面/F11 两句死文本全刷/T3·T5 四带复算并账一次跑批双认账/R5 改前锚=本批新立案C 锚/估时段一勘误 4.25d;案C 增补内容照旧=§2.6 三事实〔行为换代/锚全作废/难度预判〕+T0 推算稿第五件=对拍锚按新序重推导+T6 四带复算按案C 新行为首采;T0-T8≈6.25d,天然切分点 T4 末;🔴 契约 5 条含跑批批准制;**✅ 裁点全裁(2026-10-06 用户令:P1甲=维持 2 场·magnitude [60,85] 带内当量锚复算、具体值随出口 provisional 追认/P2甲 不对称有意/P3甲 3-3-3·2-2-3 维持、转正顺延至重扫读数到账且带内(Q4 二裁)/P4甲 不立直购价);开工=U0**) | 迭代 18 全部内容卡(③④⑤⑦)出口+全部内容批行为变更落定+**用户发令(未排期)**——重锚窗口须收尽全部内容批行为变更 | T0-T8≈6.25d(超软盒预挂,段一 T0-T4≈4.25d〔v1.2 勘误,原 4.5 系加总错误〕/段二 T5-T8≈2.0d) |
|
||||
|
||||
## 执行纪律(2026-09-27 用户立规)
|
||||
|
||||
Reference in new issue
Block a user