diff --git a/reports/iter34-代拍板-2026-10-22.md b/reports/iter34-代拍板-2026-10-22.md new file mode 100644 index 00000000..2ecf5818 --- /dev/null +++ b/reports/iter34-代拍板-2026-10-22.md @@ -0,0 +1,18 @@ +# 迭代 34 代拍板追认单(2026-10-22) + +> 本单只登记实现期在卡片 §10 白名单内所做的代拍项,属备案确认,不是事后授权。白名单依据=`reports/需求卡片-敌人表深度带换代批-2026-10-21.md` §10。 + +## 卡③ 敌人表深度带换代批 + +| # | 白名单条目 | 实际做法 | 约束核验 | +|---|---|---|---| +| 1 | 带切法实现形态与带键编号(§10-1) | 新增 `EnemyTable.band_of(band_keys, D)` 纯静态函数:对升序带键取首个 ≥ D 的键,全部小于 D 时返回 -1;resolver 侧 -1 → 取顶带+`resolve_depth_clamp` 告警(四元组去重沿用) | 迁移期带键=旧 `node_depth` 数值,请求逐位等价;单点收口(resolver 与跨表校验都调这一个函数);D<0 仍走 `request_oob` 致命通道 | +| 2 | 新字段/常量命名与枚举值(§10-2) | 表列名 `row_kind`/`depth_band`;常量 `EnemyTable.ROW_KINDS := ["battle", "boss"]`;枚举字符串与关卡节点 `type` 词表同字 | 与节点 type 词表一致;非法值由 `validate` 的 `domain` 类别拒绝 | +| 3 | `resolve_enemy_rowset` 第三参命名与缺省映射(§10-3) | 第三参命名 `row_kind`;`BattleOrchestrator` 由 `enc.node_type` 取值、缺省 `"battle"` | 生产路径 `level_runner` 恒传 `node_type`;缺省值只服务冒烟/单测直呼面 | +| 4 | 校验错误类别命名(§10-4) | 全部沿用既有类别:`domain`/`dup_key`/`rowset_rule`/`anchor`/`level_node_dangling` | 未新增类别;Boss 同带与顶带消解分别复用 `rowset_rule` 与 `level_node_dangling` | +| 5 | 冒烟断言的定位写法与措辞(§10-5) | 首遇位一律改为扫表定位:`_first_encounter_band(L, enemy_id)` 取该 (关卡, battle, 敌种) 的最低带;断言名带 fv 尾缀 | 首遇定位零写死坐标;写死坐标的旧断言全部移除 | +| 6 | 提交切分与分支命名(§10-6) | 分支 `iter34-enemy-band`;卡③分两笔:核心与数据面一笔、断言面一笔 | 两笔都在 `game/` 内,批次合并时按 diff 推代码域 | + +## 白名单外未代拍事项 + +无。实现期未遇到需要超出 §10 清单自决的设计分歧。 diff --git a/reports/iter34-反哺点-2026-10-22.md b/reports/iter34-反哺点-2026-10-22.md new file mode 100644 index 00000000..41ffda99 --- /dev/null +++ b/reports/iter34-反哺点-2026-10-22.md @@ -0,0 +1,37 @@ +# 迭代 34 反哺点清单(2026-10-22) + +> 本批是代码实现批,`design/` 整目录与根规则文件只读。以下五条是实现完成后需要对设计文档与流程清单做的改写,逐条写清「哪个文件哪一节、改成什么、依据」。用户裁决后由文档批落文。 + +## ① 敌人系统.md:坐标记法与表校验措辞换代 + +- 文件与位置:`design/gdd/systems/战斗循环/敌人系统.md` :81(hobgoblin 缺口登记) +- 改成:坐标记法由「(1,3),即第一关第四节点」改为「(1, battle, 3)」。数据行位置未变(仍在第一关带 3),只换记法。 +- 依据:本卡契约 1(寻址键由 (关卡, 节点深度) 换成 (关卡, 行类, 深度带));冒烟 `smoke_all.gd` 的 hobgoblin 键位断言〔fv12〕按新记法钉死。 + +- 文件与位置:同文件 :278(表校验项清单中的行集构成违例一句) +- 改成:「行集内同敌种第二行 / 同坐标多行不相邻」→「同带键多行不相邻」;同时把「同坐标」类表述统一为「同带键」。 +- 依据:本卡契约 4(行集构成纪律由坐标相邻改为带键相邻);`enemy_table.gd` 的 `rowset_rule` 校验键串已换为 `"%d_%s_%d"`。 + +## ② 关卡节点地图.md:两处定位信息表述统一 + +- 文件与位置:`design/gdd/systems/冒险循环/关卡节点地图.md` :146 +- 改成:本句「本文递出关卡序号 + 节点编号,按编号生成单位归它」统一为「本文递出关卡序号+节点深度;敌人侧按深度带配池生成单位」。 +- 依据:同文件 :119 既有定稿句「关卡序号 + 节点深度……按深度带配池」,两处表述当前不一致;本批实现侧 `level_runner` 递出 `node_depth`、敌人侧 `band_of` 落带,以此为准。 + +## ③ 关卡节点图生成.md:产出规格补「多终点深度互异」条款 + +- 文件与位置:`design/gdd/systems/冒险循环/关卡节点图生成.md` :41–:48(产出约束五条) +- 改成:在产出约束中补一条——多终点(多 Boss 节点)必须落在互异的深度带;同一深度带出现两个终点即判产出无效(理由:共带会让「走哪条路打谁」落空)。 +- 依据:本卡契约 6 的图侧兑现处;实现侧 `config_db_cross_validator.gd` 已新增「同日图多 Boss 同带」报错(类别 `rowset_rule`,断言〔fv15〕),顶带消解另报 `level_node_dangling`〔fv16〕。 + +## ④ 待办清单.md:条目状态回写与退役记载 + +- 文件与位置:`待办清单.md` 中本卡登记条目 +- 改成:状态推进为「已实现(迭代 34)」并写明实现报告路径;按中间文档退役规则登记本卡与迭代产出物的退役去向。 +- 依据:五段流水线状态机(`doc-conventions` §12);实现批不写该文件,回写归批后收尾或用户发令。 + +## ⑤ roadmap.md:迭代 34 行批内状态刷新 + +- 文件与位置:`roadmap.md` 迭代 34 行(两卡并列,本卡为卡③)与顶部「当前位」节 +- 改成:卡③状态记为已实现;卡④(信息迷雾可见性)仍在同一迭代内推进;「当前位」按实际进度改写。 +- 依据:迭代实现批的收尾义务(`iter` 技能第 5 步账面随批);实现批不写该文件,换代归批后收尾或用户发令。 diff --git a/reports/iter34-实现报告-2026-10-22.md b/reports/iter34-实现报告-2026-10-22.md new file mode 100644 index 00000000..1bb1008f --- /dev/null +++ b/reports/iter34-实现报告-2026-10-22.md @@ -0,0 +1,117 @@ +# 迭代 34 实现报告(2026-10-22) + +> 依据:`roadmap.md` 迭代 34 行与两份需求卡片。本批为代码实现批,产出物只写 `reports/`。 +> 卡③「敌人表深度带换代批」已完成;卡④「信息迷雾可见性批」另行施工(见第五节)。 + +## 一、批次概况 + +| 项 | 内容 | +|---|---| +| 工作树 | `D:\code\g-plan2-iter34-enemy`,分支 `iter34-enemy-band` | +| 开工基线(主区 master,603eba31) | 冒烟 1156 项检查 0 失败;单元 35 套件全绿;探针 `--click` 全绿 | +| 卡③收口读数 | 冒烟 1161 项检查 0 失败;单元 35 套件全绿;探针 `--click` 与 `--full` 全绿;静态扫描归零 | +| 合并前全量代码闸 | 见第四节 | + +## 二、卡③ 敌人表深度带换代批 + +### 2.1 任务卡状态 + +| T 卡 | 内容 | 状态 | +|---|---|---| +| T0 | 事实坐实与迁移表核对(§4.2 逐行) | 完成(迁移后 20 行键序与表序逐行一致〔fv11〕) | +| T1 | 带切法单点、resolver 三参签名、表键迁移、schema 校验换代 | 完成(提交 07f3eb55) | +| T2 | 跨表校验 ④ 敌侧带化、Boss 同带与顶带消解两条负向判据、消费面(叙述/结算)随动 | 完成(提交 07f3eb55) | +| T3 | 冒烟与单测断言面按 §8.1 S 清单换代、七项变异验证 | 完成(提交 61537da8、2 笔修补) | +| T4 | 三份产出物、独立验收审计、合并 | 进行中(本报告+审计+合并) | + +### 2.2 实际改动—验收对照表 + +生产侧关键落点:`game/data/schemas/enemy_table.gd`(`band_of` :157、`ROW_KINDS` :12、`row_kind` 枚举判据 :57–:58、锚行与 Boss 行集 :149);`game/core/config_db_resolver.gd`(三参签名 :33、带寻址与两档告警 :44–:80);`game/core/config_db.gd`(门面 :193);`game/core/config_db_cross_validator.gd`(④ 敌侧带化 :94–:106);`game/core/unit_container.gd`(行类参数 :38、解析 :43);`game/core/battle_orchestrator.gd`(行类取值 :328、透传 :359);`game/presentation/battle_narrator.gd:76`;`game/data/tables/enemy.tres`(20 行键迁移)。 + +| fv | 需求点(简) | 验收断言(文件:行) | 层级 | 真实入口 | 撤销/变异结果 | +|---|---|---|---|---|---| +| fv1 | 带命中偏难一侧 | `config_db_resolver_test.gd:58`、:61 | 单元 | `resolve_enemy_rowset` 直调 | 变异 `band_of` 改 floor → 红(实测两断言均红) | +| fv2 | 行集按表文件行序返回 | `config_db_resolver_test.gd:67`、:71 | 单元 | 同上 | 变异混编两行对调 → 红 | +| fv3 | 越顶带取顶带+告警去重 | `config_db_resolver_test.gd:78`、:84、:87 | 单元 | 同上(D 高于顶带、重复请求两次) | 变异 floor → 红(实测) | +| fv4 | row_kind 路由 | `config_db_resolver_test.gd:93` | 单元 | 同 D 分别传 battle/boss | 撤销第三参 → 双 kind 不再分域 | +| fv5 | 越域与非法行类致命 | `config_db_resolver_test.gd:101`、:104、:107 | 单元 | `resolve_enemy_rowset(0,…)`/`(L,-1,…)`/`(1,0,"elite")` | 撤销判据 → 不报致命 | +| fv6 | 生产表加载校验零错误 | `config_db_test.gd:14` | 接口 | `ConfigDB.load_tables` | 回退键迁移 → 校验红 | +| fv7 | 非法 row_kind 被拒 | `config_db_test.gd:256` | 接口 | `EnemyTable.validate` 非法枚举夹具 | 变异注释枚举判据 → 红(实测) | +| fv8 | dup_key 新键拦截 | `config_db_test.gd:235` | 接口 | 同带键同敌种二行夹具 | 回退键串 → 漏拦 | +| fv9/fv20 | 同带隔断报 rowset_rule | `config_db_test.gd:225` | 接口 | 隔断夹具 | 回退 rowset_rule 键串 → 漏拦 | +| fv10 | 锚行与 Boss 行集缺失报 anchor | `config_db_test.gd:265`、:273 | 接口 | 缺锚/缺 Boss 夹具 | 回退 anchor 判据 → 漏报 | +| fv11 | 20 行计数与键序 | `smoke_all.gd:2106` | 接口 | 加载全表逐行比对 | 变异对调/迁错带 → 红(实测) | +| fv12/fv25 | hobgoblin 在 (1,battle,3) 留任 | `smoke_all.gd:2114`、:2116 | 接口 | 同上读表面+表注释件核 | 变异迁错带 → 红(实测) | +| fv13 | 三 Boss 行类与带键就位 | `smoke_all.gd:2132` | 接口 | 同上读表面 | 回退任一行类 → 红 | +| fv14 | 值列零变更 | git diff 件核 | 件核 | `git diff` 逐值列比对 | 改任一值列 → 件核红 | +| fv15 | 同关双终点共带报错 | `config_db_cross_validator_test.gd:137` | 单元 | `cross_validate()` 双 Boss 同带夹具 | 变异删判据 → 红(实测) | +| fv16 | 顶带消解报错 | `config_db_cross_validator_test.gd:142` | 单元 | 节点深度高于顶带夹具 | 变异判据短路 `if false` → 红(实测) | +| fv17 | 单终点图零误报 | `config_db_cross_validator_test.gd:132` | 单元 | 现役三关夹具 | 回退 ④ 敌侧换代 → 红 | +| fv18 | 混编行序 | `smoke_all.gd:4815` | 集成 | 冒烟读 (2,battle,5) 行集 | 变异对调两行 → 红(实测) | +| fv19 | 混编骰和 ≤ 4 | `smoke_all.gd:4820` | 集成 | 同行集静态求和 | 放宽判据 → 红 | +| fv21 | 首遇带数据驱动定位 | `smoke_all.gd:2282` | 集成 | 扫表取最低带 | 撤销扫表定位 → 取键失配 | +| fv22 | 巨蜘蛛首遇带固定 2 不加骰 | `smoke_all.gd:4801` | 集成 | 扫表定位+行集读数 | 变异加 `unit_count_max: 3` → 红(实测) | +| fv23 | bugbear/duergar 首遇带固定 1 | `smoke_all.gd:3473`、:4859 | 集成 | 扫表定位+行集读数 | 变异加 `unit_count_max` → 红 | +| fv24 | Boss 行集与毒吐投放面 | `smoke_all.gd:4281`、:4291、:4807、:4865 | 集成 | 扫表定位+Boss 行集 | 回退投放面判据 → 红 | +| fv25 | hobgoblin 缺口登记随行 | `smoke_all.gd:2116` | 接口 | 表文件注释在位 | 同 fv12 | + +覆盖说明:`game/` 全域共 35 条断言带 fv 尾缀,覆盖 fv1–fv25(fv14 按卡片约定走 git diff 件核,代码侧无断言);fv9 与 fv20、fv12 与 fv25 各自共用同一断言行,计数时不重复。 + +### 2.3 变异验证记录表(注入 → 最窄闸见红 → 还原) + +| # | 注入内容 | 最窄闸 | 红断言(原文摘要) | 还原确认 | +|---|---|---|---|---| +| 1 | `EnemyTable.band_of` 的 `>=` 改为 `<=`(反向 floor) | `config_db_resolver_test.gd` | 带命中取偏难一侧:请求深度 4 命中带 5〔fv1〕;精确落带〔fv1〕;越顶带 clamp〔fv3〕×2 | 改回 `>=`,复跑全绿 | +| 2 | 注释掉 `validate` 的 `row_kind ∈ ROW_KINDS` 判据 | `config_db_test.gd` | 非法 row_kind 被拒(封闭枚举)〔fv7〕 | 恢复判据,复跑全绿 | +| 3 | 删除跨表校验「Boss 同带」判据 | `config_db_cross_validator_test.gd` | 同关双终点共带报 rowset_rule〔fv15〕 | 恢复判据,复跑全绿 | +| 4 | 顶带消解判据短路为 `if false` | `config_db_cross_validator_test.gd` | Boss 节点越顶带报 level_node_dangling〔fv16〕 | 恢复判据,复跑全绿 | +| 5 | 巨蜘蛛首遇行(2,battle,4)加 `unit_count_max: 3` | 冒烟全量 | 巨蜘蛛首遇带行集 = {giant_spider} 恰一行且 unit_count=2 无 unit_count_max〔fv22〕 | 删该字段,冒烟复跑全绿 | +| 6 | 混编两行(2,battle,5)文件内对调 | 冒烟全量 | 混编行序 [bugbear→giant_spider]〔fv18〕;20 行键序〔fv11〕;行值复制面 | 还原行序,冒烟复跑全绿 | +| 7 | hobgoblin 迁错带键(迁到 (1,battle,2)) | 冒烟全量 | 首次注入直接被加载期同带相邻规则拦下(表校验先红,键位断言未及运行);二次注入改为与 band 2 行互换带键(表可加载),命中「hobgoblin 行在 (1,battle,3)」〔fv12〕〔fv25〕与 20 行键序〔fv11〕 | 还原带键,冒烟复跑全绿 | + +拦截边界如实记录:第 7 项按卡片写法直接把 hobgoblin 放到带 2 时,报表在加载期校验即被拦下(同带键行被隔断),键位断言的敏感度无法单独观测;改用「与带 2 行互换带键」的表内合法变异后键位断言变红,证明该断言能拦住「行在错带」这一类改动。另:第 1 项连带 fv3 变红,属同一算法单点的预期耦合,不另计。 + +### 2.4 卡片与实际改动面的偏差(逐条说明) + +1. **S10a 补位**:卡片 S10a 列了 11 个补 `node_type: "boss"` 的位置,实际还需在 `smoke_all.gd` 的 CLEAR_SMOKE_DEPTH 段与 `(2,9)` 段若干直呼点补同一字段,并把 `spawn(1,4)`、深度循环 `spawn` 补行类参数。理由:这些点同样按 Boss 语义取行集,漏补会让它们落回 battle 键域、读到错的敌人行。语义未变,只是行类改为显式传。 +2. **gp 掉落断言改数据驱动**:原断言把「破财压制」战斗的 `gp_dropped` 与普通档掷定区间硬编码比对;该战斗在 S10a 中被标为 Boss 语义后,掉落档合法切换到 Boss 档,硬编码区间不再成立。改为从 `shop.tres` 读 Boss 档区间与关级加值再比对(`shop_gp_drop_row`/`shop_level_gp_bonus`),断言强度不变且不再写死数值。 +3. **单测补行类参数**:`skill_unlock_test.gd` 的 Boss 用例原先直呼 `spawn(2,9)` 取默认 battle 行类,会落错带;改为显式传 `"boss"`,普通行零扰动用例保持 `"battle"`。 +4. **静态扫描两处归零**:新 resolver 的行集容器改为显式类型(原为无类型 `Array`);表注释里的退役词改为白话。两处都不改游戏行为。 + +### 2.5 实机目检总清单(只登记,不阻塞合并) + +| # | 项目 | 观测点 | 状态 | +|---|---|---|---| +| 1 | 三关实机开战遭遇观感不回归 | 第一关地精/熊地精、第二关巨蜘蛛与重击手混编、三关 Boss 战的敌人数量与外观与改动前一致 | 待用户试玩 | + +### 2.6 遗留读数义务 + +- 数值零变更,本卡不发起模拟跑批(MC 档位规则)。 +- 合并后主区需 `--editor --quit` 重刷类名缓存,再跑一次全量代码闸复跑,读数写入合并提交信息。 + +## 三、卡③ 独立验收审计 + +审计报告:`reports/iter34-验收审计-2026-10-22.md`(由未参与实现的子代理执行,逐行结论见该文件)。 + +## 四、全量代码闸读数 + +`tools/run_all_gates.sh --code`,起跑 commit `8b18e057`(2026-10-22 04:42),回执 `game/tests/.gates/receipt.json`: + +| 闸 | 退出码 | 指纹 | 对基线 | +|---|---|---|---| +| 01 冒烟全量 | 0 | green | 一致 | +| 02 单元套件 | 0 | green | 一致(35 套件) | +| 03 探针 --click | 0 | green | 一致 | +| 04 探针 --full | 0 | green | 一致 | +| 05 渲染闸 | 0 | green | 一致(shot_probe 七屏+golden 逐像素) | +| 09 静态扫描 | 0 | green | 改善(基线红 → 现绿,本卡改动面归零) | +| 10 熵增闸 | 0 | green | 一致 | +| 11 回放确定性对拍 | NEED-APPROVAL | skip | 本卡数值零变更,按档位规则不发起(需用户批准) | + +`all_green: true`,`changed_vs_baseline: []`。改前基线(T0,主区 master `603eba31`):冒烟 1156 项检查 0 失败/单元 35 套件 0 失败/探针全绿。 + +> 环境注记:本轮曾出现一次阶段性假红(02/03/04/05 同时红)——前一次被中断的闸进程未死透,与新闸并行写了同一批 `game/tests/.gates/*.log`(日志内出现同一探针同时 PASS 与 FAIL 的交错字节),另有并行会话在同机跑另一 worktree 的闸。清场后端到端重跑得本次读数;单件直跑(`ui_struct_probe` 等)在清场前即为绿,佐证为环境并发而非行为回归。 + +## 五、卡④ 信息迷雾可见性批 + +另行施工,完成后在本文追加对应章节。