From 7c8c1ec564591906e6fa71b960019cc27f4889c1 Mon Sep 17 00:00:00 2001 From: Joywayer Date: Mon, 3 Aug 2026 12:30:58 +0800 Subject: [PATCH] =?UTF-8?q?docs(plan):=20=E8=AE=A2=E6=AD=A3=20Task=206=20?= =?UTF-8?q?=E4=B8=A4=E5=A4=84=E8=AF=84=E5=AE=A1=E6=8C=87=E5=87=BA=E7=9A=84?= =?UTF-8?q?=E5=BD=92=E5=9B=A0=E8=A1=A8=E8=BF=B0=EF=BC=88=E4=B8=8D=E6=94=B9?= =?UTF-8?q?=E4=BB=A3=E7=A0=81/=E6=95=B0=E5=80=BC=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Step 6 归因写反:脚本手工内联复现两种顺序,从未调用 ProfileManager.apply_run(), 故对调 apply_run() 内部顺序不影响其结果;真正的 apply_run() 顺序回归哨兵是 Step 5b (评审对调 profile_manager.gd:68-69 顺序后,Step 5b 未改一字即 FAILS=1)。 「22」出处指代错误:task-6-brief.md 全文无此数字,实际出自 docs_dev/specs/2026-07-31-shelf-c-attribute-shop-design.md:133 设计表,数值本身无误。 Co-Authored-By: Claude Opus 5 --- docs_dev/plans/2026-07-31-shelf-c-attribute-shop.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs_dev/plans/2026-07-31-shelf-c-attribute-shop.md b/docs_dev/plans/2026-07-31-shelf-c-attribute-shop.md index 1395025..123624c 100644 --- a/docs_dev/plans/2026-07-31-shelf-c-attribute-shop.md +++ b/docs_dev/plans/2026-07-31-shelf-c-attribute-shop.md @@ -869,7 +869,7 @@ Expected: `FAILS=0`,`帧距=3`(`wand_basic`),`原因=已达上限`。 > ⚠️ 脚本里的 `0.5` 是 `wand_basic` 的基准间隔。**若开局装备的不是 `wand_basic`,此常数与期望帧距都要改** —— 用 `_equipped_core.cast_interval` 读实际值更稳。断言的实质是「帧距 > 1(未饱和)」,不是「恰好等于 3」。实测确认开局装备确为 `wand_basic`(`combat_manager.gd:54` `_equipped_core = WandPreset.make_core_by_id("wand_basic")`),故 `0.5` 常数有效。 -**实际输出**:`FAILS=0 买了22次 mod=0.0985 原因=已达上限 帧距=3(应>1,证明未饱和)`。**校准**:到 `soft` 门槛实测需 **22 次购买**(`cast_delay_mod` 每次 `pct` 复利 `step=0.10`,`combine=inverse`,`merged=1-(1-0.10)^n`,`base×(1-merged)`≤`soft`(0.1) 在 `n=22` 时首次成立)——简报未写具体次数,此处补全为确定值,供日后回归对照。 +**实际输出**:`FAILS=0 买了22次 mod=0.0985 原因=已达上限 帧距=3(应>1,证明未饱和)`。**校准**:到 `soft` 门槛实测需 **22 次购买**(`cast_delay_mod` 每次 `pct` 复利 `step=0.10`,`combine=inverse`,`merged=1-(1-0.10)^n`,`base×(1-merged)`≤`soft`(0.1) 在 `n=22` 时首次成立)——`task-6-brief.md` 未写具体次数;「22」这一数字的出处是 `docs_dev/specs/2026-07-31-shelf-c-attribute-shop-design.md:133` 的设计表,本步运行时实测与之吻合(`1×0.9²²≈0.0985≤0.1` 首次在 `n=22` 成立),此处补全为确定值,供日后回归对照。 - [x] **Step 4: `cpu_limit` 的 `add_int` 硬约束(验收 11)** @@ -944,6 +944,8 @@ ShopManager.reset() ``` **实际输出**:`DISK_ROUNDTRIP FAILS=0 cleared_hp_max=100.00 cleared_cpu=5 loaded_keys=["attr_purchases", "player_stats", "saved_at", "schema_version", "shop_seed", "wand", "wave_num"] attr_purchases={ "cpu_limit": 2.0, "hp_max": 3.0 } hp=130.0000(应130.0000) hp_max=133.1000(应133.1000) cpu=7(应7)`。`attr_purchases` 经 JSON 序列化后数值型变为 `float`(`2.0`/`3.0`),`get_attr_purchases_save()` 内部按 `int(d[k])` 转换,往返后与购买前逐位相等。 > **踩坑记录**:第一轮跑此脚本时得到 `FAILS=1`(`cpu=7` 应 `2`),排查后发现是脚本本身的问题——上一段测试脚本的清理代码里手误调了 `PlayerStats.reset_for_run()`(会连带清掉法杖的 `"core"` 加成来源且不会自动重建),污染了本段测试开始前的基线,与被测代码无关。教训:`reset_for_run()` 只应由 `combat_manager` 在真正开局/重开时调用,且必须伴随法杖重新装备(`_rebuild_wand()` 会重建 `"core"` 加成);手工验收脚本里绝不能单独调它做"清空状态",否则会污染同会话后续脚本的基线。 +> +> **附带作用(评审发现)**:本步直接调用真实 `ProfileManager.apply_run()`(而非手工内联复现顺序),故它同时是**该函数顺序回归的哨兵**——对调 `profile_manager.gd:68-69` 的两行顺序会使本步 `FAILS=1`(评审实测 `hp=100.0000` 应 `130.0000`,脚本本身未改一字)。Step 6 验证的是机制本身(见下),本步(Step 5b)才是覆盖 `apply_run()` 实现的回归哨兵。 - [x] **Step 6: 回读顺序不吞血(Task 3 的核心风险)** @@ -976,7 +978,7 @@ _mcp_print("CORRECT ORDER FAILS=%d final hp=%.2f hp_max=%.2f(应 130/133.1)" - 错误顺序:`WRONG after load_save_data only: hp=130.00 hp_max=110.00` → `WRONG ORDER final: hp=100.00 hp_max=133.10`(吞 30 血,复现 Task 3 报告的原始发现)。 - 正确顺序:`CORRECT ORDER FAILS=0 final hp=130.00 hp_max=133.10`(未被钳,与 `hp_before`=130 完全一致)。 -这独立复核了 Task 3 的核心风险与其修复,且证明了断言本身非空——删掉 `apply_run` 里的顺序修复会让这条断言真正变红。 +本步独立复核 Task 3 的核心风险机制(`_modifiers` 非空时 `remove_modifiers_from` 才真正触发 `_recompute_attrs`,从而在「先 load 后 apply」下产生错误的中间钳位)。**注意本步是手工内联两种顺序、独立于 `apply_run()` 实现**(脚本全程未调用 `ProfileManager.apply_run()`),故它验证的是机制本身而非 `apply_run()`——对调 `apply_run()` 内部两行顺序**不会**影响本步的红/绿结果(评审已实测确认);`apply_run()` 的顺序回归哨兵是 **Step 5b**(见下)。 - [x] **Step 7: `shop` 段缺失即不上架(验收 16)**