diff --git a/reports/需求卡片-冒险域拆件与账本实体化批-2026-10-26.md b/reports/需求卡片-冒险域拆件与账本实体化批-2026-10-26.md new file mode 100644 index 00000000..f08d5733 --- /dev/null +++ b/reports/需求卡片-冒险域拆件与账本实体化批-2026-10-26.md @@ -0,0 +1,332 @@ +# 需求卡片:冒险域拆件与账本实体化批(AdventureRunner 真拆分·主卡) + +- 版本:**v1.2**(v1.0→grilling 一轮「回炉」13 阻断全折入→v1.1→二轮「通过附残留 8 条」全折入→v1.2 定稿,复核记录见 §12) +- 来源:[待办清单](../待办清单.md)「AdventureRunner 职责真拆分」条目(2026-10-25 登记,P0,状态=文档设计已闭合+待写卡)(唯一事实源:[architecture](../design/engineering/architecture/architecture.md) v1.16 核心层 HeroLedger/CurioStop 新件行+「冒险域拆分定稿」节) +- 归属:`game/core/` 新二件+adventure_runner/level_runner/curio_deck/shop_session/run_ledger/battle_orchestrator 改造+呈现接线面+测量面改址 +- 排期:未编入(迭代批卡片;估时 ≈5–5.5 个工作日;姊妹副卡另 ≈1.5–2) +- 开工门:U0+复核门过(§12);零待裁点 +- 姊妹卡:`reports/需求卡片-同调配装充能域封装批-2026-10-26.md`(副卡,依赖本卡——本卡完成后方可开工) + +## 0. 前置依赖与并行性 + +- **第〇步核对(2026-10-26 写卡会话)**:来源条目=设计线条目,闭合凭据=architecture v1.16(「冒险域拆分定稿」节),放行。 +- **卡间依赖**:本卡为姊妹副卡(充能域封装)的前置——本卡末态 RunLedger 为「仅剩同调充能账+其战斗原语」的瘦身壳,副卡将其整体退役。本卡禁越界做充能单源化(§5)。 +- **并行冲突注记(呈编排段裁先后)**:①「通关口径换代批」(已写卡在册)C 注释面含 core 六件 29 处「通关」注释——与本卡同触 adventure_runner/level_runner;两批无论先后,后做者行号基线漂移(各自 T0 事实坐实吸收);同迭代排波须错文件或串行。②「调试入口写死行删除批」(已写卡在册)触 main.gd:199 与三探针断言——本卡触 main 系装配面与探针连接面,不同行域,排波无冲突但建议串行波。③与「结构小件定点修批」「levelmap装配越界与BFS缓存批」(已写卡在册)零文件交叠。 + +## 1. 目标与完成定义 + +**目标**:adventure_runner 从 989 行/42 类变量/23 公开方法的上帝对象转为**薄应用层**(DDD 应用层形态:状态机+关序推进+结算受理+建件接线+断点拼盘落盘口+效果引擎冒险桶持有,零领域决策);新件 HeroLedger(主角实体账)与 CurioStop(三选一停点件)落码;RunLedger 三账迁移瘦身;CurioDeck 纯池化;六转发信号族删除(呈现直连);关卡对象构造注入;断点片段化+获得日记键;25 条转发属性撤除+消费方改址。**游戏行为零变化**(契约 1)。 + +**改动单元清单**(与文件结构图同源): + +| # | 单元 | 内容 | +|---|---|---| +| u1 | HeroLedger 建件+账本迁移 | 数值面(生命/钱包/锻造快照/类型轴/特性集/钥石/真视记录)迁入;获得日记三层结构;gp 单写原语;公式单点 | +| u2 | CurioStop 建件 | 停点三态/刷新三源账/兑付方法族/凭证出箱;三选一信号面自带 | +| u3 | CurioDeck 纯池化 | bind_handlers 反向回调退役;商店消费经 Callable 链至 CurioStop 兑付单点 | +| u4 | 应用层收薄 | adventure_runner 留状态机/关序/结算受理/建件接线/桶字典持有/断点拼盘口;件出口 hero()/stop() | +| u5 | level_runner 构造注入 | 后置 setter 群与商店重绑机制删除;8 条白盒转发属性撤除;断点关卡域片段方法 | +| u6 | 信号直连 | 六转发信号族删除;呈现/模拟器在 level_started 重取点重订阅;恰好一次断言 | +| u7 | 断点片段化+日记键 | 各件自交片段;应用层唯一落盘口;既有 27 键逐键冻结;获得日记键扩列(唯一声明的写入面扩展) | +| u8 | 转发属性撤除+改址 | adventure 4 条/level 8 条/board_view 13 条撤除;A 类属性直读 49 处+B 类内部直写约 78 处(68 处迁移态+10 处 run_ledger 账本断言族)+ui_input_probe 5 处+C 类方法面约 25 文件改指件 | +| u9 | RunLedger 瘦身 | bonus 账/vision 账/adventure_counters 桶全部退役迁出(桶归宿主+encounter `"adv_bucket"` 键);attune_charges 账保留(副卡退役) | + +**完成定义**: +1. u1–u9 落地;全套闸按本批改动域选档全绿;S13 计数读数改善(adventure_runner 类变量 42→约 20、level_runner 38→约 30、board_view 45→32——读数记录进实现报告,基线禁改)。 +2. 同种子改前改后:断点快照 27 键逐键逐位一致(含日记键前形态);冒烟/系统/单测/探针全绿。 +3. 撤销证明逐 wr 行落地;三份产出物写齐(T6);独立验收审计过。 + +## 2. 设计事实源 + +| # | 出处 | 取用条款 | +|---|---|---| +| D1 | [architecture](../design/engineering/architecture/architecture.md) **v1.16** | 核心层 HeroLedger 行、CurioStop 行;「冒险域拆分定稿」节全文(应用层形态/纯池化/RunLedger 退役与瘦身边界/构造注入/断点片段化/信号直连/调用直连/验收红线) | +| D2 | 待办清单条目实况「验收面预案要点」 | 真实入口断言/撤销证明/27 键冻结/RNG 零漂移/基线禁改/MC 发起权归用户 | +| D3 | [存档序列化](../design/gdd/systems/表现与支撑/存档序列化.md) 断点域节 | 27 键登记与豁免条款(本卡不改其正文——同步义务见 §6) | + +## 3. 现状事实(2026-10-26 写卡会话实查于 master daa8860b;开工日 T0 复核行号) + +| # | 事实 | 出处 | +|---|---|---| +| G1 | adventure_runner 989 行/42 类变量/23 公开方法/65 函数;七件变化原因混装(生命周期状态机/英雄账本/三选一停点/刷新双源/断点 schema/信号转发/商店装配) | `game/core/adventure_runner.gd` 全读;条目实况 | +| G2 | 转发属性 25 条:adv `:60-77` 4 条(_curio_taken/_curio_deck/_feat_ticket_pity/_feat_ticket_sold 直指 CurioDeck 件内);level `:50-66` 8 条(直指 ShopSession 件内);board `:82-122` 13 条(直指 TilePalette/HeroSprite 件内)。生产消费零;属性直读消费=5 单测 **49 处**+ui_input_probe **5 处** | grep 全库实测+复核订正 | +| G2b | **内部状态直写面(本批迁移态的测试直改,grilling 一轮补查)**:`_curio_pending/_curio_result/_node_curio_pending/_attune_refresh_x/_attune_refresh_y/_refresh_stock/_feats/ledger["hero_hp"]` 等直写约 **68 处/11 文件**——adventure_feats_test 15、feat_vouchers_test 14、curio_refresh_paid_test 10、meta_progression_forge_test 9(:293-303 直写停点态、:368 直读 ledger)、pool_case_d 5、cross_system_flow_test(集成)4、save_manager_domain_test 3、level_shop_economy 3、breakpoint_resume 3、treasure_effects 1。全部属 u1/u2 迁入件的承载态,随 T5 三类改址 | grilling 一轮实测 | +| G3 | 商店重绑 `_bind_shop` 全 6 调用(`_init:84`/`start_level:165`〔单关模式账本重建重绑——G3 原漏计〕/`start_level_external:205`/`set_run_ledger:688`/`set_attunement:646`/`set_tree_rules:670`);后置 setter 群:set_run_ledger/set_attunement/set_feats/set_tree_rules/set_hero_axes/set_shop_pool/set_voucher_grants/set_treasure_unlocked | `game/core/level_runner.gd:50-66/80-84/151-165/194-205/644-709/757-768`;grilling 复核订正 | +| G4 | 断点:`BREAKPOINT_FIELDS` 27 键 `:864-892`;`_snapshot_breakpoint` 5 调用点(`:483/:611/:665/:806/:855`);`_bp_parts` 对关卡对象五连挖(`:907-946`:node_id/shop_shelf/shop_visit_buys/visited_ids/aux_items);`_resume_*` 回填族 `:188-279` | `game/core/adventure_runner.gd` | +| G5 | 六转发信号 `:14-19`+`_forward_*` 六方法(`:849-855/:976-989`);`_bind_level_runner` 每关 6 连接 `:724-729`;`_forward_choices_presented` 转发兼快照双职 `:853-855` | `game/core/adventure_runner.gd`;呈现订阅面=`main_adventure_flow.gd:10-15` 全六+`sim/level_autoplay.gd:143-145` 三 | +| G6 | 加算区三写通道:三选一属性件 `adventure_runner.gd:425`(run_ledger.bonus[sink]);商店属性商品 `shop_session.gd:87-88`(bonus[attr]+=flat);战末导出 `battle_orchestrator.gd:1125-1127`(bonus_add_axis——按轴合计,无明细来源)。RunLedger 类壳触点:battle `:381` 类型检查、`:239/:757/:761-762/:1125-1127` 四族原语、`shop_session.gd:322-323` 硬转型;全仓 **18 文件**引用 RunLedger。**bonus 生产消费面 5 文件 8 处**(grilling 一轮补查):main_adventure_flow:37-38、level_map_screen:334/335/343、hud_presenter:20/313、ui_click_probe:689、level_autoplay:262 | 实读+grilling 复核核验 | +| G7 | `effective_max_hp` 双写逐字一致靠注释维持(adv `:305-307`/level `:106-108`);`apply_rest` 委托 `:322-323`;回血公式 `LevelRunner.rest_heal` 静态 `:588-589` | 实读 | +| G8 | encounter 注入:level `:519` `"ledger": run_ledger` 单键;begin_battle enc 装配 `:514-526` | `game/core/level_runner.gd` | +| G9 | CurioDeck `bind_handlers` `:25-27`(adv `_init` 注入 `:85`);`consume_pool_purchase` 经回调反调宿主 `:107-113` | `game/core/curio_deck.gd` | +| G10 | 呈现方法面消费:curio_interact_controller 16 处 `adventure.pick_curio/apply_node_curio/skip_empty_curio/refresh_*` 等;方法面总量≈25 文件(呈现 5+autoplay+约 20 测试) | grep 实测 | +| G11 | 停点零自动推进守卫:`continue_to_next_level` `:327-333`(无待确认/停点未兑付双拒);关卡对象每关新建 `:698`;信号顺序契约(level_started→重取→入口候选呈现)`:_inject_level_params:752`+`_present_level_entry:756-761` | `game/core/adventure_runner.gd`;`game/core/level_runner.gd:226-241` | +| G12 | 特性集活引用语义:`set_feats` 不复制(level `:655-657` 注释——关内兑付 relic 须当关生效) | `game/core/level_runner.gd` | + +## 4. 设计契约(红线,违反 = L3 停机呈报) + +🔴 **契约 1 · 行为零变化**:RNG 流名 reward_pick 与消费序零漂移;信号顺序契约冻结(关卡开始→重取→入口候选呈现);同种子逐位一致;玩家可见呈现零变化。MC 与基线数据逐项比对**是否发起由用户裁**(触及存档/RNG 面)。 + +🔴 **契约 2 · 断点冻结与唯一扩展**:既有 27 键键名/键序/缺省回退策略逐键冻结;唯一声明的扩展=新增获得日记键(扩列不升版;旧档缺日记→汇总键直载并跳过比对;日记在档→由日记推导汇总、与留存汇总不符即报错中止)。 + +🔴 **契约 3 · 机检纪律**:`tools/gdstyle_baseline.txt` 禁改禁 refresh,类变量计数下降属改善自然绿;**禁为迎合机检消息文本保留或新增无效成员/别名(§13)**;机检键与卡片契约互斥时停卡呈报。 + +🔴 **契约 4 · 新件红线**:Core 零 UI(headless 可跑完整冒险);全类型标注(S9);core↔core 接线只许方法 Callable 禁 lambda(S6);随机只经注入 RngServiceCore 的 reward_pick 封闭流;数值零字面量只读 db;文件头注=模块介绍(禁变更叙事/文档反链)。 + +🔴 **契约 5 · 调用直连不留壳**:不留任何纯转传委托方法(Middle Man 裁定,2026-10-26);呈现控制器经**取值回调**持件——回调只许捕获长活根对象(root),**禁件方法 Callable**(防悬挂);件出口=adventure 对象上 `hero()`/`stop()` 两个取件方法(组件出口非委托壳)。 + +🔴 **契约 6 · 注入纪律**:构造注入一次给齐(关卡对象后置 setter 群与商店重绑机制删除,`_bind_shop` 全仓仅构造一处——含单关模式重开:HeroLedger 实例不重建、走 `reset_for_single_level()` 值重置,shop 绑 hero 对象引用不换代,G3 第 6 处重绑因此消失);注入**活引用禁快照**(特性集/装配集语义——G12)。 + +🔴 **契约 7 · 重连恰好一次**:呈现/模拟器重订阅用 `is_connected` 守卫+未连即 `push_error`(release 模板剥 assert,禁裸 assert);「关卡开始信号前零发射」契约写入 level_runner 头注并配断言。 + +🔴 **契约 8 · RunLedger 瘦身不退役(本卡)**:瘦壳余面**只有** attune_charges 账+`attune_charge_has/set/consume` 三原语——bonus 账、vision_counter 账、adventure_counters 桶字典**全部退役迁出**(桶归宿主字典+encounter `"adv_bucket"` 键,battle :382 挂链改指);encounter `"ledger"` 键保留传瘦壳;整类文件删除归副卡。 + +🔴 **契约 9 · 测试改址非削弱**:A 类 49 处+B 类约 78 处与方法面改址=访问路径改写,断言语义与判据逐条保持;实现期不得借改址删断言/放宽判据(削弱申报=零)。 + +## 5. 范围边界 + +**做**:u1–u9;§8 全部验收;撤销证明;产出物。 + +**不做**(去向明示): +- **充能域封装**(AttuneLoadout 建件/物化行单源化/战斗使用管线改写/旧档同调行迁移/RunLedger 整类退役)→ 姊妹副卡 `reports/需求卡片-同调配装充能域封装批-2026-10-26.md`; +- **level_runner 商店方法委托层拆除**(buy_product 等同签名委托)→ 在册条目「level_runner 商店委托层拆除」(待写卡); +- 关卡主题数据缝扩展、获取即入账(用户裁维持现状)→ 不立项; +- design/ 与根规则文件任何编辑 → 反哺点清单(§6); +- MC/对拍锚重跑 → 用户发起。 + +## 6. 关联文档同步面 + +| 文档 | 关联点 | 同步义务 | +|---|---|---| +| `design/engineering/architecture/architecture.md` | 模块归属表 HeroLedger/CurioStop 行「设计定稿——实现批建件」标注换代为现状;CurioDeck 行删 bind_handlers 句;level_runner 行补构造注入句;「冒险域拆分定稿」节转现状登记(RunLedger 行注记瘦身半程) | 反哺点 · 列清单 | +| `design/gdd/systems/表现与支撑/存档序列化.md` | :59 断点域段机制句(写侧 _bp_parts 拼装/读侧 _bp_read 派生)改写为「各件自交片段+冒险应用层唯一拼盘落盘口+获得日记键扩列」 | 反哺点 · 列清单 | +| `design/gdd/systems/冒险循环/冒险结构.md` | 断点域字段口径 owner——新增获得日记键的字段口径登记(键名/缺省策略/旧档回退) | 反哺点 · 列清单 | +| `game/tests/验证集清单.md` | A 类 49 处+B 类约 78 处+方法面改址的清单同步(机器提取重生成) | 批内机械同步(game 内 .md,非禁写面) | +| `待办清单.md` | 来源条目状态推进(实现批收尾由 batch-closure 承接) | 反哺点 · 列清单 | + +## 7. 任务卡 + +### 卡前 · 文件结构图 + +| 文件 | 职责 | 行为改动 | +|---|---|---| +| `game/core/hero_ledger.gd`(**新增**) | 主角实体账:数值面+获得日记三层+gp 单写原语+公式单点+断点片段 | 新件(承载迁移态,行为不变)→ wr1/wr6 | +| `game/core/curio_stop.gd`(**新增**) | 三选一停点件:停点三态/刷新三源账/兑付族/凭证出箱/信号面/断点片段 | 新件(承载迁移态)→ wr2/wr3/wr6 | +| `game/core/adventure_runner.gd`(修改) | 薄应用层:删数值面/停点族/六转发信号族;建件接线;断点拼盘口;件出口 hero()/stop() | 结构改动,行为不变 → wr4/wr6 | +| `game/core/level_runner.gd`(修改) | 构造注入收参;8 白盒属性删;重绑机制删;战斗→关卡信号族保留;断点关卡域片段方法 | 结构改动 → wr5/wr6 | +| `game/core/curio_deck.gd`(修改) | 纯池化:bind_handlers 删;consume_pool_purchase 改经注入 Callable | 结构改动 → wr3 | +| `game/core/shop_session.gd`(修改) | 账本引用换代(run_ledger→hero);商店属性加算改经 hero 单写原语 | 结构改动,写通道语义不变 → wr1 | +| `game/core/run_ledger.gd`(修改) | 瘦身:bonus 账/vision 账/adventure_counters 桶全部退役迁出(桶归宿主字典+encounter `"adv_bucket"` 键);attune_charges 账+其三原语保留 | 结构改动 → wr1 | +| `game/core/battle_orchestrator.gd`(修改) | encounter 注入面:+`"hero"` 键;bonus_add_axis/vision_count_add 调用改指 hero;attune_charge_* 仍走 ledger 瘦壳 | 结构改动 → wr1 | +| `game/presentation/main_adventure_flow.gd`(修改) | 信号重连(level_started 重取点 is_connected 守卫);控制器件注入换代;bonus 读面改指 hero(:37-38) | 结构改动 → wr4/wr1 | +| `game/presentation/views/level_map_screen.gd`(修改) | bonus 读面改指 hero(:334/335/343) | 结构改动 → wr1 | +| `game/presentation/hud_presenter.gd`(修改) | bonus 读面改指 hero(:20/313) | 结构改动 → wr1 | +| `game/presentation/curio_interact_controller.gd`(修改) | 16 处调用改指 `stop()`(取值回调经 root) | 结构改动 → wr2 | +| `game/presentation/main.gd`(修改) | 装配面:冒险对象创建传参(存档承载构造注入)与件出口接线 | 结构改动(非行为) | +| `game/presentation/views/board_view.gd`(修改) | 13 条件成员同名转发属性删除 | 非行为改动(生产零消费) | +| `probe/ui_click_probe.gd`(修改) | bonus 读面改指 hero(:689) | 测量面改址 → wr1 | +| `probe/ui_input_probe.gd`(修改) | 5 处改指件(`_palette`/`_hero_sprite`) | 测量面改址 → wr7 | +| `game/tests/unit/core/` 5 文件(修改) | 49 处属性直读改指件(A 类) | 测量面改址 → wr7 | +| `game/tests/` 直写面 11 文件(修改) | 约 68 处内部状态直写改件公开构造面(B 类,G2b 清单) | 测量面改址 → wr7/wr2 | +| `sim/level_autoplay.gd`(修改) | 3 处转发信号订阅改关卡对象(level_started 重连);bonus 读面改指(:262) | 测量面改址 → wr4/wr1 | +| 其余方法面调用文件(约 20 测试文件,修改) | `adventure.pick_curio` 族改指 `adventure.stop().pick_curio`(C 类) | 测量面改址 → wr2 | + +(新增二件与新增函数的复用/唯一性核查见「落位与可复用性预检」节;新增数据件=获得日记键〔断点扩列〕。) + +### 接口块 + +**HeroLedger(`game/core/hero_ledger.gd`)** + +```gdscript +class_name HeroLedger extends RefCounted +func _init(db_ref: ConfigDb, base_override_ref: Dictionary) -> void # 锻造强化快照构造注入(原 _base_override 迁入) +func set_debug_override(atk_pct: int, hp_pct: int) -> void # 调试百分比通道(adventure.set_hero_override 转发件内) +# ---- 数值面(自 adventure_runner 迁入,语义逐字不变)---- +var hero_hp: int # 生命账(原 ledger["hero_hp"] 单值化——共享字典退役) +var gp: int # GP 钱包(原 ledger["gp"]——LevelRunner.gp 属性与 ShopSession 钱包读写全改指此单点) +func gain_gp(amount: int) -> void # gp 单写原语(clamp ≥0) +func spend_gp(amount: int) -> bool # gp 单写原语(不足 false 零副作用) +func clear_wallet() -> void # 收束清零 +func reset_for_single_level() -> void # 单关模式重开重置(值重置非实例重建——shop 绑 hero 对象引用不换代,重绑因此消失;语义=现 start_level :151-164 重置面) +func effective_max_hp() -> int # 公式单点(与现 :305-307 逐字同式:表值+base_override+汇总,后乘本件 pct) +func effective_atk() -> int # 公式单点(与现 level :101-103 同式,迁入) +func effective_ac() -> int # 同上(level :114-115) +static func rest_heal(pct: int, hp: int, max_hp: int) -> int # 回血公式单点(自 LevelRunner.rest_heal 迁入) +# ---- 获得日记三层 ---- +func record_gain(source_class: String, kind: String, detail: Dictionary) -> int # 获得记录列表追加,返回记录 id +func gain_bonus(axis: String, value: int, source_class: String, kind: String) -> void # 明细+汇总同步维护(三通道统一入口;战末通道 source_class="battle_export"、kind=轴名——battle :1125-1127 按轴逐条调) +func bonus_total(axis: String) -> int # 汇总读面 +func record_purchase(product_id: String) -> void # 购买条目(定价读数走 purchase_tier) +func purchase_tier(product_id: String) -> int +func record_keystone_drop(drop: Dictionary) -> void # 本局增量(keystone 更名 keystone_gained 语义)+逐杀明细 +func keystone_gained() -> int +func record_vision_use() -> void; func vision_used() -> int +var feats: Array[String] # 特性持有集(活引用注入——G12 语义) +func feats_held() -> Array +# ---- 断点片段 ---- +func breakpoint_fragment() -> Dictionary # hero_hp/bonus(汇总快照)/获得日记键/purchased/keystone 相关/relics/vision_counter_used +func restore_fragment(frag: Dictionary, params: Dictionary) -> void # 日记缺键→汇总直载跳过比对;在档→推导比对不符 push_error+拒载 +``` + +**CurioStop(`game/core/curio_stop.gd`)** + +```gdscript +class_name CurioStop extends RefCounted # 生命周期=每冒险一次(AdventureRunner 冒险开始建;关卡换实例不换件) +signal curio_choice_presented(payload: Dictionary) # 自 adventure_runner 迁入,载荷逐字不变 +signal curio_resolved(result: Dictionary) +func _init(db_ref: ConfigDb, deck_ref: CurioDeck, hero_ref: HeroLedger, snapshot_call: Callable) -> void +func rebind_level_runner(runner: LevelRunner) -> void # 每关注入时点=AdventureRunner._start_current_level 建件接线处:存当前关卡对象的 grant_curio_gp 方法 Callable(GP 件入账维持现路径与 wallet_changed 发射序——第二关起绑新 runner,防调死对象) +# ---- 五组入口 ---- +func open_level_clear(payload_base: Dictionary) -> void # 收编 _on_level_finished 停点段:抽签(level_clear)/置在途态/发信号/触发落盘回调 +func present_node_curio(candidates: Array) -> void +func pick_curio(kind: String, tier: String = "", feat_id: String = "") -> bool +func apply_node_curio(kind: String, tier: String = "", feat_id: String = "") -> bool +func skip_empty_curio() -> bool +func refresh_curio() -> bool; func refresh_curio_paid() -> bool +func curio_refresh_gp_cost() -> int; func attune_refresh_left() -> int; func refresh_stock() -> int +func curio_stop_pending() -> bool # 名继承现役 :584 谓词 +func stop_resolved() -> bool # 放行谓词(已兑付待推进且无在途停点) +func node_curio_pending_state() -> Dictionary +func voucher_outbox() -> Dictionary # 凭证出箱 {rap:int, time_sand:int}——战首取走清零 +func draw_candidates(channel: String) -> Array # 经 deck(reward_pick 流不变) +# ---- 断点片段 ---- +func breakpoint_fragment() -> Dictionary # bonus_pending/bonus_result/feat_ticket_*/refresh_stock/attune_refresh_y(读侧 params 回退经参传入) +func restore_fragment(frag: Dictionary, params: Dictionary) -> void +``` + +**adventure_runner 应用层(保留/新增面)** + +```gdscript +func _init(db_ref: ConfigDb, rng_ref: RngServiceCore, save_manager_ref = null) -> void # 存档承载改构造注入(缺省 null=断点静默,原语义) +func hero() -> HeroLedger # 件出口(组件交出,非委托壳) +func stop() -> CurioStop +# 保留:start_adventure/resume_adventure/continue_to_next_level/abandon/state/summary/runner()/set_hero_override +# 删除:数值面方法族/停点族方法/六转发信号与 _forward_*/_bp_parts 五连挖(改收片段) +# BREAKPOINT_FIELDS 常量保留本件=键序契约(拼盘口按此断言完整性) +``` + +**level_runner 构造注入** + +```gdscript +func _init(db_ref: ConfigDb, rng_ref: RngServiceCore, ctx: Dictionary) -> void +# ctx 键(一次给齐,后置 setter 群删除——grilling 一轮补全 12 键): +# hero:HeroLedger/ledger:RunLedger(瘦壳——本卡仅传,副卡删)/ +# attunement:Array/tree_rules:Array/shop_mode:String/treasure_unlocked:Dictionary/ +# hero_attack_type:String/hero_armor_type:String/voucher_rap:int/voucher_time_sand:int/ +# pool_wiring:Dictionary(池模式装配 4 参收编:{deck:Array, consume:Callable, ticket:Callable, cap:Callable}——缺省空字典=legacy 零注入) +# start_level(单关测试模式)件内自建私有 HeroLedger(_init 即建、空 override 注入——shop 绑定因此仍仅构造一次;start_level 收 base_override_in 经 hero 重注+reset_for_single_level() 值重置,实例不重建) +# 新增:func hero() -> HeroLedger # 只读出口(bonus 生产读面 5 文件经现 run_ledger 访问链改此承接) +# start_level_external 收参收窄为 (level_index:int, defer_entry:bool, resume_state:Dictionary) +# 新增:func breakpoint_fragment() -> Dictionary # 关卡域五键(node_id/visited_ids/aux_items/shop_shelf/shop_visit_buys) +# func restore_fragment(resume_state: Dictionary) -> void # 断点重建参数面收口(原 _resume_bp 直读面收编) +# 删除:_shop_pool_mode/_pool_deck/_pool_consume/_pool_ticket/_shop_shelf/_shop_visit_buys/_shop_paid_refreshes/_shop_purchased 八条白盒属性(内部访问改直指 _shop) +``` + +**T 卡间接口**:T1 产出 HeroLedger 全 API(T2/T3/T4 取用);T2 产出 CurioStop API 与 stop_resolved/voucher_outbox(T3 关序受理取用);T3 产出重连点与 ctx 签名(T4/T5 取用);T4 产出片段三接口(wr6 取用);各卡验收断言随卡落地。 + +### 落位与可复用性预检 + +| 新增件 | 复用面(为何不能复用既有) | 唯一面 | 分层与交互 | +|---|---|---|---| +| hero_ledger.gd | 既有 run_ledger.gd 职责=跨层共享账壳(本批瘦身退役中),非主角数值实体——主语不同不可复用;grep `hero_ledger`/`HeroLedger` 零命中 | 主角数值与获得记录唯一所有者;gp/生命/加算单写原语唯一落点(三写通道收口于此) | Core 纯逻辑;由 adventure_runner 建、注入 curio_stop/level_runner/shop_session/battle encounter;零 UI、随机零消费 | +| curio_stop.gd | 停点编排现散在 adventure_runner(本批迁出);grep 零同名类;名源=现役 `curio_stop_pending()` 谓词(:584)——件名继承在库概念 | 停点三态/刷新三源/兑付族唯一所有者 | Core 纯逻辑;随机只经注入 deck 的 reward_pick;兑付落账经注入 hero;落盘经注入方法 Callable(S6 合规) | +| 获得日记键(数据件) | 断点键族现无日记类键(BREAKPOINT_FIELDS 实查 27 键无之) | 获得记录持久化唯一载体;与汇总键并存但日记为正主(比对规则见契约 2) | 断点域扩列,owner 口径归冒险结构.md(反哺点) | +| ctx 注入字典 | 后置 setter 群(本批退役)的替代收口;CurioFlowContext 先例(curio_interact_controller.gd:31)同法 | 关卡依赖装配唯一入口 | 组合根→adventure→level 构造链 | + +### T0 事实坐实+改前基线采集(≈0.35d) + +- [ ] 复核 G1–G12 行号(吸收并行批漂移);记录改前读数:S13 三件计数(42/38/45)、`gdstyle_baseline.txt` 键数、五单测属性直读 49 处+直写面 68 处逐条清单(G2/G2b)。可核查结果:改前读数表进实现报告素材。 +- [ ] **改前断点基线采集(bp1 载体)**:新增临时对拍脚本 `game/tests/bp_baseline_dump.gd`(`--script` 直跑:固定种子集驱动 autoplay 冒险至各停点〔选路/三选一/兑付后/入口〕,逐停点 dump 断点 Dictionary 全键值)→ JSON 落 `reports/` 实现报告素材目录;批末随中间产物退役。改后复跑同脚本对比:**比对集=原 27 键**(新日记键不在改前档,排除出比对集单列核对)。可核查结果:基线 JSON 与复跑对比表在案。 + +### T1 HeroLedger 建件+账本迁移(≈1.0d) + +- [ ] 实装 hero_ledger.gd(接口块全签名;数值面自 adventure_runner :28-77 迁入、公式自两处 :305-307/level:101-115 迁入单点;获得日记三层与三通道入口)。可核查结果:件可 `new()` 直构单测。 +- [ ] 接线换代:adventure_runner 建件;shop_session 账本引用换 hero(:322-323 硬转型退役,属性商品走 `hero.gain_bonus`〔wr1-s 断言:购买后 bonus_total 与旧径同值〕);battle encounter +`"hero"` 键、bonus_add_axis/vision_count_add 改指 hero(:1125-1127/:761-762);**bonus 生产读面 5 文件 8 处改指 `hero().bonus_total()`**(main_adventure_flow:37-38/level_map_screen:334-343/hud_presenter:20/313/ui_click_probe:689/level_autoplay:262——现经 `runner.run_ledger` 访问链,LevelRunner 侧补 `func hero() -> HeroLedger` 只读出口承接);RunLedger 删 bonus/vision 账。 +- [ ] **冒险桶迁移**:adventure_runner 持 `adventure_counters` 字典(开局清/收束清/`_resume_counters` :256-258 回填改直写本字典);battle encounter 增 `"adv_bucket"` 键、:382 挂链 `counters_ctx.adventure_bucket` 改指该键(效果引擎就地直写路径不变——引用束同字典;battle 直构无注入路径以自有空字典兜底,承现 :381 `RunLedger.new()` 兜底语义)。 +- [ ] 验收步骤:〔hr1〕单测——effective_max_hp/rest_heal 与改前逐值一致(真实入口:start_adventure→恢复点节点 rest 真链,封顶口径断言继承现役);〔hr2〕三通道日记断言——三选一件/商店商品/战末导出各走真链后 `bonus_total` 与改前读数相等、日记条目来源指回正确。撤销证明见 wr1。 + +### T2 CurioStop 建件+CurioDeck 纯池化(≈1.0d) + +- [ ] 实装 curio_stop.gd(停点三态/刷新三源/兑付族/凭证出箱/信号面——全部自 adventure_runner :353-666 迁入,语义逐字);adventure_runner 停点段改调 `stop.open_level_clear`(关序受理读 `stop_resolved`/`voucher_outbox`)。 +- [ ] CurioDeck 纯池化:bind_handlers 删(:25-27/:85);商店消费链 ShopSession→(注入 Callable)→`curio_stop` 兑付单点(现 `_apply_curio_pick` 同口语义)。 +- [ ] 验收步骤:〔cs1〕三选一真链断言(继承条目预案:start_adventure→关卡完成→pick→断言加算区/池余量/停点态清零);〔cs2〕商店 pool 购买真链断言(buy_pool_item→兑付→摘牌/加算);〔cs3〕凭证拿到即开断言(现役断言继承改址)。撤销证明见 wr2/wr3。 + +### T3 应用层收薄+构造注入+信号直连(≈1.0d) + +- [ ] adventure_runner 收薄:删数值面/停点族残留/六转发信号族与 `_forward_*`;`_bind_level_runner` 六连接删;`_forward_choices_presented` 的快照触发改核心侧自有受理(choices_presented 订阅归应用层,落盘口直调)。 +- [ ] level_runner 构造注入:ctx 收参、setter 群删、`_bind_shop` 收敛为构造一次;八白盒属性删(内部改直指 `_shop`);头注补「关卡开始信号前零发射」契约。 +- [ ] 呈现/模拟器直连:main_adventure_flow 在 level_started 重取点 `is_connected` 守卫重连六信号(守卫未连即 push_error);curio_interact_controller 16 处改 `stop()`(取值回调经 root,禁件方法 Callable——契约 5);autoplay 3 处同法改(autoplay 增订 level_started:在该回调重取 runner 并重连——现经冒险转发的 node_entered 内重取机制随转发族消亡,重取点前移)。 +- [ ] 验收步骤:〔sc1〕恰好一次断言(重连后同信号处理器仅一次——探针真链驱动两关全流程);〔sc2〕信号顺序契约断言(关卡开始→重取→入口候选——现役探针断言继承);〔sc3〕源码断言——`_bind_shop` 全仓仅构造一处、`_forward_` 族零命中(static_scan/冒烟源码断言形态)。撤销证明见 wr4/wr5。 + +### T4 断点片段化+日记键(≈0.75d) + +- [ ] 三件片段接口落地(接口块签名);adventure_runner 拼盘口(BREAKPOINT_FIELDS 键序断言完整性→收片段→拼→落盘);level_runner 五键片段替代五连挖;`_resume_*` 族改分发片段。 +- [ ] 日记键写入与旧档回退(契约 2 规则)。 +- [ ] 验收步骤:〔bp1〕同种子改前改后断点逐位一致——**比对集=原 27 键**(日记新键排除出比对集、单列核对在档性)——T0 基线脚本改后复跑逐键相等(集成测试载体);〔bp2〕日记在档推导比对断言+旧档(无日记键构造档)回退直载断言;〔bp3〕续玩真链(ui_click_probe wc2 继承+wr 载荷断言)。撤销证明见 wr6。 + +### T5 转发属性撤除+测量面三类改址(≈1.0d,grilling 一轮扩容) + +- [ ] **A 类·转发属性直读改指件(49 处/5 文件)**:`a._curio_deck`→`a._curio.deck` 等 4 属性直读改指件成员(G2 清单逐条)。 +- [ ] **B 类·内部状态直写改件面(约 78 处/12 文件,G2b 清单+账本断言族)**:停点态/账本态直写改走件公开构造面——`a._curio_pending={...}`→经 `stop()` 测试构造面(件补测试用写入口:`_test_set_pending` 形态或公开装配参数,语义=原直写);`adr.ledger["hero_hp"]` 直读→`hero().hero_hp`;**run_ledger 账本断言族改指**(约 10 处/3 文件:adventure_feats :351/362、feat_vouchers :30/110-111/117/141、level_shop_economy :1037/1322/1325 的 bonus/adventure_counters 读断言→`hero().bonus_total()`/宿主桶读面)。 +- [ ] **C 类·方法面调用改指件(约 25 文件)**:`adventure.pick_curio` 族→`adventure.stop().pick_curio`;公式调用→`hero()`。 +- [ ] 撤 25 条转发属性(adv 4/level 8/board 13——board 13 条删除即净);ui_input_probe 5 处改指件;验证集清单重生成同步(§6)。 +- [ ] 验收步骤:全套闸按域选档跑一次全绿(改址后现役断言语义不变=绿);S13 计数读数记录(读数留档)。撤销证明见 wr7。 + +### T6 撤销证明+产出物落位卡(≈0.25d,末卡) + +- [ ] 逐 wr 行撤销证明(§8.1 末列——回退对应 hunk→最窄闸红→还原复绿,记录进实现报告)。 +- [ ] 写齐三份产出物(实现报告〔S13 读数对照+实机目检总清单+并行批交叠注记〕/代拍板追认单/反哺点清单〔§6 逐条落点〕)。 +- [ ] 合并前置:独立验收审计(§8.3)逐行「通过」。 + +**估时合计 ≈5.35d**(区间 5–5.5;T0 扩基线采集、T5 扩三类改址系 grilling 一轮订正——单卡破 5d 无碍:工作量限制属迭代层非卡片层,2026-10-25 两层口径)。 + +## 8. 验证闸 + +### 8.1 改动—验收对照表 + +| 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 撤销证明 | +|---|---|---|---|---|---| +| wr1 账本实体化(数值面/公式单点/三通道日记) | hero_ledger 新件+shop/battle/adv 接线换代 | 〔hr1〕公式逐值断言+〔hr2〕三通道日记断言+〔hr1-s〕商店加算同值断言〔拆件批 V1〕 | 单元+接口 | start_adventure→恢复点真链;商店/三选一/战末真链 | 回退 hero 接线 hunk→hr2 红(日记断言失源) | +| wr2 停点件迁移 | curio_stop 新件+关序受理改调 | 〔cs1〕三选一真链断言〔拆件批 V2〕 | 接口+集成 | start_adventure→关卡完成→pick 真链 | 回退停点段 hunk→cs1 红 | +| wr3 牌库纯池化 | curio_deck bind_handlers 删+商店链改接 | 〔cs2〕pool 购买真链断言〔拆件批 V3〕 | 集成 | buy_pool_item 真链(关内商店节点) | 回退商店链 hunk→cs2 红 | +| wr4 信号直连+恰好一次 | 六转发族删+重连点 | 〔sc1〕恰好一次+〔sc2〕顺序契约断言〔拆件批 V4〕 | 探针+系统 | 两关全流程真实驱动(探针) | 回退重连 hunk→sc1 红(双连或零连) | +| wr5 构造注入+重绑退役 | level_runner ctx 收参 | 〔sc3〕源码断言(_bind_shop 单点/_forward_ 零命中)+特性活引用现役断言〔拆件批 V5〕 | 冒烟源码断言+单元 | 现役冒烟段+关内 relic 兑付当关生效现役断言 | 回退 ctx hunk→sc3 源码断言红 | +| wr6 断点片段化+日记键 | 三件片段+拼盘口+日记键 | 〔bp1〕同种子 27 键逐位一致+〔bp2〕日记比对/旧档回退+〔bp3〕续玩真链〔拆件批 V6〕 | 集成+探针 | 同种子双跑+ui_click_probe 续玩 | 回退片段 hunk→bp1/bp2 红 | +| wr7 转发属性撤除+改址 | 25 条删+A 类 49 处+B 类约 78 处+C 类方法面改指件 | 改址后现役断言全绿+S13 计数读数记录+〔pr1〕ui_input_probe 直跑绿〔拆件批 V7〕 | 单元+探针 | 五单测套+ui_input_probe | 回退改址 hunk→对应套件红(路径不存在) | +| wr8 产出物 | T6 三份 | 件核〔wr8〕 | — | — | 缺项红 | + +### 8.2 测试削弱申报 + +零(改址=访问路径改写,断言语义与判据逐条保持——契约 9;无任何断言删除/阈值放宽/扫描面缩小)。 + +### 8.3 独立验收审计 + +入口=未参与实现的会话或子代理;报告落 `reports/iter-验收审计-<日期>.md`;抽查重点=27 键逐键比对执行记录、恰好一次断言、改址断言语义等价抽检(5 文件各 ≥3 处)、S13 基线未改(git diff 查 `tools/gdstyle_baseline.txt` 零变化)、撤销证明复现。未过不得合并。 + +## 9. 异常分级 + +- **L1(自救)**:行号漂移(T0 基线对照自核);测试改址的等价写法微调。 +- **L2(记录继续)**:非断言面注释措辞;呈现装配面等价调整(不动信号契约)。 +- **L3(停机呈报)**:机检键与契约互斥(契约 3);断点键序/逐位一致断言红且非测试问题;信号顺序断言红;发现第七件变化原因需扩拆件范围;RunLedger 瘦身后仍有非副卡范围的依赖残留。 + +## 10. 代拍板白名单(超清单必呈报) + +1. 提交切分与 worktree 分支命名。 +2. 测试改址的等价访问写法(语义不变前提下)。 +3. 迁入代码的注释随迁措辞(语义不变前提下)。 +4. 单关测试模式自建私有 HeroLedger 的内部组织。 + +## 11. 待裁点 + +**零待裁点,开工门=U0。**(全部设计裁点已在设计段闭合,凭据 architecture v1.16;本卡无新增裁量面。) + +## 12. 自审六查与复核记录 + +**自审六查(2026-10-26 写卡会话)**:①规格覆盖——u1→T1/wr1、u2→T2/wr2、u3→T2/wr3、u4/u6→T3/wr4、u5→T3/wr5、u7→T4/wr6、u8→T5/wr7、产出物→T6/wr8,完成定义三条各有落点;②步骤扫描——每步一动作一可核查结果,无「TBD/酌情」行;③类型一致性——接口块签名与 T 卡引用逐字一致(hero()/stop()/curio_stop_pending 名源);④审查焦点——断点逐位一致(bp1)与信号恰好一次(sc1)为最可能坑点,已挂 T4/T3;文件结构图行为改动行全部指到 wr 行;⑤篇幅比例——接口块为签名非实现体,无函数体抄写;⑥落位预检——新增二件+日记键+ctx 四件各有不能复用理由与唯一落点,与结构图「新增」标记对上。 + +**grilling 一轮复核记录(2026-10-26,独立子代理对抗复核,判「回炉」——13 阻断+7 建议,v1.1 全数折入)**:①改址面系统性漏列(测试直写约 68 处/11 文件+生产 bonus 消费 5 文件 8 处)→ G2b 新增+G6 订正+T5 三类改址重列+结构图补五行;②HeroLedger 接口不完整(gp 读面/pct 与 base_override 注入/战末日记形态)→ 接口块补 `var gp`/`set_debug_override`/构造参 base_override/战末通道 source_class="battle_export" 定死;③契约互斥(sc3 单关模式重绑)→ 契约 6 裁「实例不重建、值重置、shop 绑对象不换代」;④set_shop_pool 四参无落点 → ctx 补 pool_wiring 键;⑤adventure_counters 桶迁移漏步 → T1 增桶迁移步骤+契约 8/u9 与副卡 K5 口径对齐(瘦壳余面=attune 仅存);⑥gp_grant_call 跨关调死对象 → CurioStop 生命周期定每冒险一次+`rebind_level_runner` 每关注入时点写死;⑦bp1 基线采集不可执行 → T0 补采集步骤(载体/落盘/28 键对 27 键排除法);⑧数字订正(49 处/5 处探针/_bind_shop 6 处/:50-66);⑨autoplay 重取机制 → T3 补 level_started 重连;⑩wallet_mutated 无消费方信号删除(§13 同款);估时 4.75→5.25。复核确认属实的关键事实(989 行、转发属性与信号行号、_bind_shop 六处、attune_charge_has 零调用、system_test/smoke 无方法面调用、通关批交叠面)已随订正吸收。 + +**二轮闭合复检(2026-10-26,同一独立子代理)**:判「通过(附残留 8 条,无新阻断)」——13 阻断逐条核闭合(含三处点名矛盾检查:桶迁移与契约 8 一致、rebind 时点先于该关全部信号发射无冲突、副卡键值校验与零行为变化自洽)。残留 8 条已折入 v1.2:R1 数字统一(u8/契约 9/wr7/§6 四处 47→49+B 类 68→78);R2 B 类补 run_ledger 账本断言族(约 10 处/3 文件改指);R3 bonus 读面经 LevelRunner `hero()` 只读出口承接写明;R4 单关模式 `_init` 即建私有 hero(空 override)+start_level 经 reset 重注——绑定仍仅构造一次;R5 结构图 run_ledger 行同步桶退役+battle 直构空字典兜底;R6/R7/R8 归副卡折入。估时分项和 5.35d 对齐。 + +## 13. 禁为机检文本保留无效成员(重构类必填条款) + +禁止为迎合机检消息文本(含计数)而保留或新增无效成员/别名;本批撤除的 25 条转发属性即该债务的清偿——不得以「基线计数」「探针便利」等理由保留任何一条或新增同种转发;机检键与卡片契约互斥时实现段一律停卡呈报,不得自造第三条路(code-conventions §1.1 同款)。 diff --git a/reports/需求卡片-同调配装充能域封装批-2026-10-26.md b/reports/需求卡片-同调配装充能域封装批-2026-10-26.md new file mode 100644 index 00000000..c3175232 --- /dev/null +++ b/reports/需求卡片-同调配装充能域封装批-2026-10-26.md @@ -0,0 +1,207 @@ +# 需求卡片:同调配装充能域封装批(AdventureRunner 真拆分·副卡) + +- 版本:**v1.2**(v1.0→grilling 一轮「回炉」5 阻断全折入→v1.1→二轮「通过附残留」R6/R7/R8 折入→v1.2 定稿,复核记录见 §12) +- 来源:[待办清单](../待办清单.md)「AdventureRunner 职责真拆分」条目(2026-10-25 登记,P0,状态=文档设计已闭合+待写卡)(唯一事实源:[architecture](../design/engineering/architecture/architecture.md) v1.16 AttuneLoadout 新件行+「冒险域拆分定稿」节充能单源化句) +- 归属:`game/core/` 新一件(attune_loadout)+run_ledger 整类退役+battle_orchestrator 使用/重置路径+断点旧档迁移 +- 排期:未编入(迭代批卡片;估时 ≈1.5–2 个工作日) +- 开工门:U0+复核门过(§12);零待裁点 +- **前置卡**:`reports/需求卡片-冒险域拆件与账本实体化批-2026-10-26.md`(主卡)完成合回后方可开工——本卡消费其 RunLedger 瘦身壳与 encounter 多路注入面 + +## 0. 前置依赖与并行性 + +- **第〇步核对(2026-10-26 写卡会话)**:来源条目=设计线条目(同主卡),闭合凭据=architecture v1.16,放行。 +- **前置卡接口取用**:主卡 T1 产出的 HeroLedger 与 encounter `"hero"` 键、T3 产出的 ctx 注入面与「关卡开始信号前零发射」头注契约、T4 产出的片段三接口形态——本卡在同形接口上扩展充能域。 +- 并行冲突:与主卡串行(硬前置);与「通关口径换代批」(在册 v1.1)真实交叠=**adventure_runner+level_runner 两文件**(该批 C 注释面 adventure_runner 14 处/level_runner 3 处——本卡改其建件接线与 ctx;该批六件清单无 battle_orchestrator)——先后做者 T0 行号复核吸收;其余在册卡零交叠。 + +## 1. 目标与完成定义 + +**目标**:同调主动件充能从「字典轨+物化行轨双存、三处差额对账」改为**单源化**——物化行为唯一事实源,新建装备件 AttuneLoadout 拥有同调行并改「事后对账」为「写时种行/补行」;战斗使用与重置路径改指件;旧档读侧以行集为源;RunLedger 整类退役。**游戏行为零变化**(使用管线句柄语义逐位不变)。 + +**改动单元清单**: + +| # | 单元 | 内容 | +|---|---|---| +| k1 | AttuneLoadout 建件 | 装备中的秘宝件对象集(每件内含充能单位/重置周期);种行/补行写时同步 | +| k2 | 双轨退役 | RunLedger.attune_charges 字典轨删除;三差额对账函数退役(adv `_seed_attune_charges` :521-526/level `sync_attune_inventory` :705-715/battle `_reseed_attune_charges` :228-246 改归件方法) | +| k3 | 战斗路径改指 | battle 使用/重置走 loadout 原语(使用管线 validate/相位/fx/overlay/consume 逐位不变) | +| k4 | 断点与旧档迁移 | attunement_charges 键写读归件(键名策略不变);**同调行始终留在 treasure_inventory**(不剥离——使用管线与 C 区投影载体不动);旧档读侧以行集为源 | +| k5 | RunLedger 整类退役 | 全仓零引用+文件删除;encounter `"ledger"` 键移除 | + +**完成定义**: +1. k1–k5 落地;全套闸按本批改动域选档全绿;`grep -rn "RunLedger\|run_ledger" game/` 零命中(含注释面随批清与测试直构改指后;.uid 随删)。 +2. 同种子改前改后:充能使用全程逐位一致(使用次数/剩余/C 区投影);旧档续玩迁移正确。 +3. 撤销证明逐 wr 行;三份产出物;独立验收审计过。 + +## 2. 设计事实源 + +| # | 出处 | 取用条款 | +|---|---|---| +| D1 | [architecture](../design/engineering/architecture/architecture.md) **v1.16** | AttuneLoadout 行(物化行为唯一事实源/种行补行写时同步/旧档迁移归件/attunement_charges 键不变);「冒险域拆分定稿」节充能单源化句与 RunLedger 退役句 | +| D2 | 待办清单条目实况 2026-10-26 闭合注记 | 「充能改单源化:物化行为唯一事实源」(审查高危一修正的落定形态) | +| D3 | 主卡契约 1/2/3/4 | 行为零变化/断点冻结/机检纪律/新件红线(同款适用) | + +## 3. 现状事实(2026-10-26 写卡会话实查;行号以主卡合回后 T0 复核为准) + +| # | 事实 | 出处 | +|---|---|---| +| K1 | 双轨并存:字典轨=RunLedger.attune_charges(item_id→剩余次数);物化轨=treasure_inventory 内 source_class="attunement" 行(每格充能一行,used 标记消耗);两轨靠三处差额对账维持(种子满额→数未用行→差额补行防双份) | `game/core/run_ledger.gd:9`;`adventure_runner.gd:521-526`;`level_runner.gd:705-715`;`battle_orchestrator.gd:228-246` | +| K2 | 战斗使用管线(句柄驱动,全链骑在物化行上):validate_use(:703-717 目标窗口/板界/预读判定)→相位守卫→treasure_used fx 发射(:718-724,掘进蓄能 counter_spend 订阅依赖)→overlay 应用→consume 句柄(:754 消耗标 used)→attune_charge_consume 扣字典(:757 同点双写;行号以 T0 复核为准) | `game/core/battle_orchestrator.gd:703-763` | +| K3 | 重置周期三态:表列 charge_reset ∈ {adventure, battle, level};「已耗 handle 作废+差额补新=回满」语义(:225-227 注释);charges_per_adventure=0=自动兑付件不入使用面(:238) | `battle_orchestrator.gd:225-246`;`data/schemas/treasure_item_table.gd:39/153-154` | +| K4 | 断点:attunement_charges 键(keep_on_null 策略)载字典轨;aux_items 键载库存全量快照(含同调行——两键各存半边) | `adventure_runner.gd:873/927`(主卡合回后为片段面) | +| K5 | RunLedger 瘦身后余面(主卡末态):attune_charges 账+attune_charge_has/set/consume 三原语;battle :381 类型检查、:239/:757 调用点;encounter `"ledger"` 键 | 主卡 u9;`battle_orchestrator.gd:381` | +| K6 | C 区秘宝槽投影=treasure_inventory.query_inventory(含同调行,usable 预判) | `game/core/treasure_items.gd:42-48` | + +## 4. 设计契约(红线,违反 = L3 停机呈报) + +🔴 **契约 1 · 使用管线句柄语义逐位不变**:validate_use 判据/相位守卫/treasure_used fx 发射时点与载荷/overlay 应用序/consume 的 used 不可逆/重置「已耗作废+差额补新」——全部逐位保留;本卡只改「行归谁种、账归谁记」,不改任何一步的判定与顺序。 + +🔴 **契约 2 · 物化行为唯一事实源**:物化行保留(禁删行——审查 H1 裁定);删除的是字典轨与事后差额对账;剩余次数=由行的未用数派生(**唯一读法,无影子账**——al2 单源对拍兜底:行派生值=T0 基线字典轨值)。 + +🔴 **契约 3 · 断点与旧档**:attunement_charges 键名与 keep_on_null 策略不变(写读方换件);**同调行始终留在 treasure_inventory**(aux_items 键值形态逐位不变——逐位一致断言因此成立);旧档读侧以 aux_items 行集为唯一事实源恢复使用面,attunement_charges 键读值仅作一致性校验读数(不符不 fatal、记日志——键值本就派生自行);旧档缺 attunement_charges 键行为不变。 + +🔴 **契约 4 · 行为零变化与机检纪律**:同种子逐位一致;RNG 零漂移(充能域零随机——实查无 RNG 消费,保持);gdstyle 基线禁改;禁为机检文本保留无效成员(同主卡 §13)。 + +🔴 **契约 5 · 新件红线**:同主卡契约 4(Core 零 UI/S9/S6/数值零字面量/头注规范)。 + +## 5. 范围边界 + +**做**:k1–k5;§8 验收;撤销证明;产出物。 + +**不做**: +- 同调位槽位判定(attunement.gd 谓词面)——零触碰; +- 秘宝道具(非同调)库存语义、C 区投影形状——零触碰(投影数据源不变,行集不变); +- level_runner 商店委托层、关卡主题——在册条目/不立项(同主卡 §5); +- design/ 与根规则文件 → 反哺点清单。 + +## 6. 关联文档同步面 + +| 文档 | 关联点 | 同步义务 | +|---|---|---| +| `design/engineering/architecture/architecture.md` | AttuneLoadout 行标注转现状;RunLedger 相关行/句整段退役注记(「战斗域装配现状」节 RunLedger 条改写);模块表 level_runner/battle 行消费依赖列 ledger 引用句删除 | 反哺点 · 列清单 | +| `design/gdd/systems/跨局循环/秘宝.md` | 若有充能账机制句(T0 核)——双轨描述改单源化 | 反哺点 · 列清单 | +| `game/tests/验证集清单.md` | 充能断言改址同步 | 批内机械同步 | +| `待办清单.md` | 条目状态推进(batch-closure 承接) | 反哺点 · 列清单 | + +## 7. 任务卡 + +### 卡前 · 文件结构图 + +| 文件 | 职责 | 行为改动 | +|---|---|---| +| `game/core/attune_loadout.gd`(**新增**) | 同调配装件:装备件对象集+充能单位+种行/补行写时同步+断点片段 | 新件(承载迁移态)→ wr1/wr3 | +| `game/core/run_ledger.gd`(**删除**,含 .uid) | 整类退役(瘦壳余面归 loadout/battle 直改后无引用) | 结构改动 → wr4 | +| `game/core/battle_orchestrator.gd`(修改) | 充能原语调用改指 loadout(经 encounter `"loadout"` 键);重置改调件方法;`"ledger"` 键移除;:381 类型检查删 | 结构改动,管线语义不变 → wr1 | +| `game/core/adventure_runner.gd`(修改) | 建件接线(装配集注入 loadout);`_seed_attune_charges` 段退役(改调件种子方法);断点片段装配(attunement_charges 键改收件片段) | 结构改动 → wr3 | +| `game/core/level_runner.gd`(修改) | `sync_attune_inventory` 退役(改调件同步);ctx 增 loadout 键、删 ledger 键 | 结构改动 | +| `game/core/treasure_items.gd`(零改动) | 物化行载体不动(投放/查询接口由件调用) | 非行为改动(零触碰——同调行始终在此) | +| `game/tests/unit/core/feat_vouchers_test.gd`(修改) | `run_ledger.attune_charges` 直写 8 处(:73-75 等)改指件测试构造面 | 测量面改址 → wr1/wr4 | +| `game/tests/unit/core/treasure_effects_test.gd`(修改) | :275 RunLedger 直构改指 | 测量面改址 → wr2 | +| `game/tests/unit/battle/round_flow_skill_pool_test.gd`(修改) | :969/994 直构与 encounter 注入改指 | 测量面改址 → wr2 | +| `game/tests/unit/core/meta_progression_forge_test.gd`(修改) | :290-291 直构改指 | 测量面改址 → wr2 | +| `game/core/effect_engine.gd`/`effect_context.gd`(修改) | 注释中 RunLedger 表述随批清(零行为) | 非行为改动 | + +### 接口块 + +**AttuneLoadout(`game/core/attune_loadout.gd`)** + +```gdscript +class_name AttuneLoadout extends RefCounted +func _init(db_ref: ConfigDb, attunement_ids: Array) -> void # 装配集注入(活引用语义同主卡契约 6) +# ---- 种行/补行(写时同步,替代三处事后差额对账)---- +func seed_for_adventure(inventory: TreasureItems) -> void # 冒险开始:全部 active_charged 件种行(**不筛周期**——承现 _seed_attune_charges 全量种账+sync 全量投行语义;battle/level 周期件开局即有行,C 区投影行数不变) +func reset_cycle(cycle: String, inventory: TreasureItems) -> void # battle/level 周期回满(**按周期筛**;已耗行作废、差额补新——语义逐字承 :228-246) +# ---- 使用面(战斗路径改指)---- +func consume_charge(item_id: String, inventory: TreasureItems) -> bool # 承 attune_charge_consume(一行标 used) +# ---- 读面 ---- +func charges_left(item_id: String, inventory: TreasureItems) -> int # 剩余(未用行派生——唯一读法,无影子账) +func item_ids() -> Array +# ---- 断点片段 ---- +func breakpoint_fragment(inventory: TreasureItems) -> Dictionary # attunement_charges 键(值形状=现字典轨 {item_id:剩余}——由行派生,键名/策略不变) +func restore_fragment(frag: Dictionary, inventory: TreasureItems) -> void # 旧档:以行集为源恢复使用面;frag 键值仅校验读数(不符记日志不 fatal);缺键保持种子态(原语义) +``` + +**battle_orchestrator 改指**:`begin_battle` encounter 删 `"ledger"` 键——桶挂链走主卡已建的 `"adv_bucket"` 键(:382 改指已完成于主卡 T1,本卡零动作)、`"hero"` 键沿用;encounter 增 `"loadout": AttuneLoadout` 键;`_reseed_attune_charges(reset)` 改调 `loadout.reset_cycle(reset, treasure_inventory)`(:228-246 语义逐字承);使用点 `:757` 改 `loadout.consume_charge(...)`;`:239` 充能设定改种行路径;`:381` ledger 类型检查与 `RunLedger.new()` 兜底删除。 + +**测试直构面改址(grilling 一轮补查)**:treasure_effects_test:275、round_flow_skill_pool_test:969/994(`load("res://core/run_ledger.gd").new()` 直构+encounter "ledger" 注入)→ 改直构 HeroLedger+"hero"/"adv_bucket" 键注入;meta_progression_forge_test:290-291 同款;effect_engine.gd:94/effect_context.gd:3 注释中 RunLedger 表述随批清(注释面,非行为)。 + +**主卡接口取用**:HeroLedger(无充能交互)、ctx 注入面(本卡扩两键)、片段三接口形态(本卡同形扩展)。 + +### 落位与可复用性预检 + +| 新增件 | 复用面 | 唯一面 | 分层与交互 | +|---|---|---|---| +| attune_loadout.gd | 既有 attunement.gd=槽位判定谓词(职责不同不可复用);treasure_items.gd=库存载体(行归它管、不归件管——件持投放与判定,行数据仍单点在库存);grep `attune_loadout/AttuneLoadout` 零命中 | 同调行投放/充能判定/周期回满唯一所有者;与 attunement.gd 词形区分明确 | Core 纯逻辑;由 adventure_runner 建件注入 encounter 与 level ctx;零随机(K4 承)、零 UI | + +### T0 事实坐实(≈0.15d) + +- [ ] 复核 K1–K6 行号(主卡合回后坐标);记录改前读数:同种子三关冒险的充能使用全程记录(种子/使用次数/各停点剩余/C 区投影行数)——wr1 对拍基线。可核查结果:基线表进实现报告素材。 + +### T1 AttuneLoadout 建件+双轨退役(≈0.6d) + +- [ ] 实装 attune_loadout.gd(接口块全签名;种行/补行/使用面——语义逐字承三处对账函数与原语)。 +- [ ] 三处对账退役:adv `_seed_attune_charges` 改调 `seed_for_adventure`;level `sync_attune_inventory` 改调件同步(或并入 reset_cycle 调用点);battle `_reseed_attune_charges` 改调 `reset_cycle`;RunLedger attune 三原语调用清零。 +- [ ] 验收步骤:〔al1〕单测——三周期回满语义(adventure 全量种行+battle/level 按周期回满各态:已耗行作废、差额补新、charges=0 件不入使用面——判据值承现役断言)+**开局投影行数断言**(seed 后 C 区行集与改前同构——周期件开局即有行);〔al2〕**单源对拍断言**——`charges_left`(行派生)=T0 基线字典轨终值(改前采集),逐件逐停点相等。撤销证明见 wr1。 + +### T2 战斗路径改指+RunLedger 退役(≈0.5d) + +- [ ] encounter 键换代(+loadout/−ledger);battle 三点改指(:239/:757/:381 承址);使用管线其余步骤零触碰(契约 1)。 +- [ ] RunLedger 文件删除(全仓 grep 零引用为前置;.uid 同删)。 +- [ ] 验收步骤:〔al3〕使用真链断言——真实冒险驱动同调件使用,**六步各一条**(validate 拒绝/validate 受理/**相位守卫拒绝(非 Active 拒用)**/fx 发射/overlay 应用/used 不可逆),现役断言继承改指;〔al4〕源码断言 `RunLedger|run_ledger` 全仓零命中〔配装批 V4〕。撤销证明见 wr2。 + +### T3 断点片段+旧档迁移(≈0.4d) + +- [ ] attunement_charges 键写读归件(值由行派生——键值形态不变);旧档读侧以行集为源(键值仅校验读数——契约 3)。 +- [ ] 验收步骤:〔al5〕同种子改前改后断点逐位一致(27 键全量——同调行留库存故 aux_items 值不变;承主卡 bp1 载体复跑);〔al6〕旧档读侧断言——构造含同调行的旧断点档,续玩后使用面充能=行集派生值、行集与改前一致(键值校验读数落日志)。撤销证明见 wr3。 + +### T4 撤销证明+产出物落位卡(≈0.15d,末卡) + +- [ ] 逐 wr 行撤销证明;三份产出物(实现报告〔对拍基线表+读数〕/代拍板追认单/反哺点清单)。 +- [ ] 合并前置:独立验收审计(§8.3)逐行「通过」。 + +**估时合计 ≈1.8d**(区间 1.5–2)。 + +## 8. 验证闸 + +### 8.1 改动—验收对照表 + +| 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 撤销证明 | +|---|---|---|---|---|---| +| wr1 充能单源化(种行/补行/使用面) | attune_loadout 新件+三对账退役 | 〔al1〕周期回满单测+〔al2〕单源对拍断言(行派生=基线字典轨值)〔配装批 V1〕 | 单元 | 件直构单测+冒险真链驱动 | 回退种行 hunk→al1 红 | +| wr2 战斗路径改指+RunLedger 退役 | battle 三点改指+文件删除 | 〔al3〕使用真链断言+〔al4〕零引用源码断言〔配装批 V2〕 | 接口+集成+冒烟源码断言 | 真实冒险驱动同调件使用 | 回退 encounter 键 hunk→al3 红;al4 随文件复现红 | +| wr3 断点片段+旧档读侧 | attunement_charges 键归件+行集为源读侧 | 〔al5〕27 键逐位一致+〔al6〕旧档行集为源断言〔配装批 V3〕 | 集成 | 同种子双跑+构造旧档续玩 | 回退片段 hunk→al5 红 | +| wr4 产出物 | T4 三份 | 件核〔wr4〕 | — | — | 缺项红 | + +### 8.2 测试削弱申报 + +零(改址与退役文件的断言迁移,语义逐条保持;RunLedger 相关既有断言随 al1/al3 承接改写路径,判据值不变)。 + +### 8.3 独立验收审计 + +入口=未参与实现的会话或子代理;报告落 `reports/iter-验收审计-<日期>.md`;抽查重点=使用管线六步逐位核(validate/fx/overlay/consume 时点)、旧档迁移映射逐行、RunLedger 零引用复核、对拍基线表在案。未过不得合并。 + +## 9. 异常分级 + +- **L1(自救)**:行号漂移;迁移映射的等价写法。 +- **L2(记录继续)**:注释措辞。 +- **L3(停机呈报)**:使用管线任一步判定/顺序变化(契约 1 破);断点逐位一致红;发现非充能域的 RunLedger 残留依赖(越主卡范围)。 + +## 10. 代拍板白名单(超清单必呈报) + +1. 提交切分与 worktree 分支命名。 +2. 种行/补行的内部组织(语义不变前提下)。 + +## 11. 待裁点 + +**零待裁点,开工门=U0。**(设计裁点已闭合于 architecture v1.16;本卡无新增裁量面。) + +## 12. 自审六查与复核记录 + +**自审六查(2026-10-26 写卡会话)**:①规格覆盖——k1→T1/wr1、k2→T1/wr1、k3→T2/wr2、k4→T3/wr3、k5→T2/wr2、产出物→T4/wr4;②步骤扫描——无「TBD/酌情」行;③类型一致性——接口块与 T 卡引用逐字一致,主卡取用面(ctx/片段形态)与主卡接口块对齐;④审查焦点——使用管线逐位不变(契约 1+al3 六步含相位钉)与旧档读侧(al6)为最可能坑点;treasure_items 零触碰行已在结构图标「非行为改动」;⑤篇幅比例——签名与断言,无实现体;⑥落位预检——新增一件有不能复用理由(attunement 槽位谓词职责不同、treasure_items 是载体非所有者),唯一落点已答。 + +**grilling 一轮复核记录(2026-10-26,独立子代理对抗复核,判「回炉」——阻断 5 条(编号9–13)+关联建议,v1.1 全数折入)**:⑨aux_items「剥离迁移」与逐位一致/禁删行三方互斥 → 口径裁死「同调行始终留库存」,迁移重定义为键写读归件+旧档读侧行集为源(键值仅校验读数),契约 3/k4/接口块/al5/al6 同步改写;⑩seed 筛周期与现状矛盾(battle/level 周期件开局即有行)→ seed_for_adventure 改全量种行不筛周期+开局投影行数断言;⑪RunLedger 退役后桶链无源 → encounter "adv_bucket" 键沿用主卡(:382 已改指)写明零动作;⑫grep 零命中不可达+「零交叠」不实 → 结构图补 treasure_effects/round_flow_skill_pool/meta_progression_forge 三测试与 effect_engine/effect_context 注释清,并行注记补通关批交叠;⑬charge_available 承接零调用点原语+两读法未定义 → 删该接口、al2 改「行派生值=T0 基线字典轨值」单源对拍断言。建议级折入:al3 补相位守卫钉、K2 行号小漂注(consume :754/attune :757)。 + +**二轮闭合复检(2026-10-26,同一独立子代理)**:判「通过(附残留,无新阻断)」——5 阻断全核闭合、「键值仅校验读数与零行为变化」边界判自洽。残留 R6/R7/R8 已折入 v1.2:R6 契约 2 旧句(两读法兜底)删、wr1 列改单源对拍、§1 目标句旧措辞(同调行迁移)改「旧档读侧以行集为源」;R7 结构图补 feat_vouchers_test 充能直写 8 处改指行;R8 并行注记事实订正(通关批 C 面六件无 battle_orchestrator,真实交叠=adventure_runner+level_runner)。 + +## 13. 禁为机检文本保留无效成员(重构类必填条款) + +同主卡:禁止为迎合机检消息文本保留或新增无效成员/别名;RunLedger 的删除不得以任何「基线便利」理由拖延或保留空壳;机检键与契约互斥时停卡呈报(code-conventions §1.1 同款)。 diff --git a/待办清单.md b/待办清单.md index 16c6db1a..8bf9d401 100644 --- a/待办清单.md +++ b/待办清单.md @@ -27,9 +27,13 @@ - 相关文档:design/engineering/architecture/architecture.md(模块归属表须随拆分登记新件)· design/gdd/systems/表现与支撑/存档序列化.md(断点域契约,27 键冻结面)· 迭代 37 卡④ 契约 1 冻结公开面(commit e5ee4d04),正是本条无法在批内完成的原因(需求卡片已退役,口径见 git 历史) - **2026-10-26 文档设计已闭合**:设计讨论全套裁定(应用层薄编排/停点件 CurioStop/角色实体账 HeroLedger 三层获得结构/同调配装件 AttuneLoadout 充能单源化/断点片段化+获得日记键扩列/信号直连/构造注入/调用方直连不留壳)经 godot-master 技能库独立子代理审查修正后定稿——三高危修正(充能改单源化:物化行为唯一事实源;日记比对旧档豁免:缺日记回退汇总键直载;ShopSession 补入改造面:商店加算写通道经实体账单写原语)均已并入。定稿登记=design/engineering/architecture/architecture.md v1.16(核心层三新件行+「冒险域拆分定稿」节);钥石入账维持收束入账(获取即入账曾议、用户裁维持现状——中途入账有断点写盘非原子致账目撕裂的风险);获得明细随档保存(日记为正主、汇总键留作旧档兼容载入与一致性校验) +关联卡片(2026-10-26 双卡切分,副卡硬前置主卡): +- 需求卡片 reports/需求卡片-冒险域拆件与账本实体化批-2026-10-26.md(v1.2 定稿,grilling 两轮——一轮回炉 13 阻断全折入+二轮通过附残留 8 条已折入,零待裁点;估时 ≈5.35d) +- 需求卡片 reports/需求卡片-同调配装充能域封装批-2026-10-26.md(v1.2 定稿,同两轮闭合;估时 ≈1.8d) + **改动面**:游戏代码 -**状态**:文档设计已闭合+待写卡 +**状态**:文档设计已闭合+已写卡 #### level_runner 商店委托层拆除——迭代 37 冻结契约期过渡件(2026-10-26 登记,来源=批次移交)