From 53f5d9cd696b7a862449f1ed8ce9899a7ffb27a8 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Sat, 24 Oct 2026 23:58:03 +0800 Subject: [PATCH] =?UTF-8?q?docs(=E6=89=B9=E5=90=8E=E6=94=B6=E5=B0=BE):=20?= =?UTF-8?q?=E8=BF=AD=E4=BB=A3=2034=20=E7=BB=93=E9=A1=B9=E2=80=94=E2=80=94?= =?UTF-8?q?=E5=8F=8D=E5=93=BA=E7=82=B9=E5=8D=81=E6=9D=A1=E8=90=BD=E6=96=87?= =?UTF-8?q?=EF=BC=8B=E4=BB=A3=E6=8B=8D=E6=9D=BF=E5=8D=81=E4=B8=89=E9=A1=B9?= =?UTF-8?q?=E8=BF=BD=E8=AE=A4=EF=BC=8B=E4=B8=AD=E9=97=B4=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E4=B9=9D=E4=BB=BD=E9=80=80=E5=BD=B9=EF=BC=8B=E8=B4=A6=E9=9D=A2?= =?UTF-8?q?=E6=8D=A2=E4=BB=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 落文(反哺点 ①②③⑤⑥⑦⑧⑨⑭⑮,经用户逐条裁决): - 敌人系统.md:寻址词族「同坐标/坐标行集」改「同带键/带键行集」五处,大地精行示例改寻址键 (1, battle, 3) - 关卡节点地图.md v2.1→v2.2:Boss 描边改紫赤+深墨环(依视觉定稿 level-map);补实现语义三句(层距=BFS 层差/Boss 与候选节点双豁免恒显类型/可见性只算当前圈不累积记忆);递出物改关卡序号+节点深度;info_visible_layers 已落数据表现行值 2 - 关卡节点图生成.md v1.1→v1.2:产出约束五条→六条,新增「多终点深度互异」;岔路取舍补候选集豁免类型可见性已兑现;调参表补图包络行(≤屏预算,超预算只限参数档) - level-map.md:信息层级第一层补类型可见性指针;画布公式记数订正(宽 70+层深×122+44.5、高 52+槽位×58+25+24,下限 620×256)——定稿语义不动 - 术语表.md:新增「关卡与地图」节,收「信息迷雾」(与视野迷雾区分,标识符禁 fog_ 前缀) - test-conventions.md §9.4:补「判据绑可观测提交面」一条,来源=迭代 34 探针首版假绿的教训(吸收原卡片 T2 描述项) ⑬ 超预算图策略无设计落点 → 待办清单新登记条目(设计面=文档轨,状态=待文档设计) ⑯ 卡片 T2 接口描述订正 → 判由 ⑭ 吸收,卡片随批退役不改 代拍板:迭代 34 两份代拍板单十三项(卡③ 六项+卡④ 七项,含卡④第 7 项白名单外甲案返工)用户全部追认,异议窗口关闭。 退役(吸收即死):reports/ 下迭代 34 产出物七份(实现报告/代拍板/反哺点清单/验收审计四份)+两份需求卡片。引用面已改写,doc_link 死链检查绿。 账面:roadmap 迭代 34 行改「已完成(2026-10-22)」、卡片列与实现报告列填「已退役(git 历史可考)」;顶部当前位迭代位与下一步换代。待办清单删迭代 34 两卡行、关卡节点图重构条设计定稿版本升 v1.2/v2.2、新登超预算图条目。体验验证清单登记 ㉜ 迭代 34 实机目检四项(不阻塞)。 域判定:diff 全部落在 design/+reports/+两份根流程清单+roadmap.md,纯文档域,故取 --docs 回执。零游戏测试执行(测试两入口铁规),结论均为静态核对。 已知缺口(不在本批修):待办清单从未设迭代 34 反哺点专条,落文凭据无处登记;roadmap 迭代 35/36 行仍写「待开工」与实际不符(35 卡①已合回、卡②停机;36 三卡已合回并收尾),留待用户发令订正。 --- design/engineering/test-conventions.md | 1 + design/gdd/systems/冒险循环/关卡节点图生成.md | 10 +- design/gdd/systems/冒险循环/关卡节点地图.md | 10 +- design/gdd/systems/战斗循环/敌人系统.md | 10 +- design/gdd/ux/level-map.md | 4 +- design/gdd/术语表.md | 6 + reports/iter34-代拍板-2026-10-22.md | 33 -- reports/iter34-卡④-验收审计-2026-10-22.md | 164 --------- .../iter34-卡④-验收审计-复审-2026-10-22.md | 75 ----- reports/iter34-反哺点-2026-10-22.md | 104 ------ reports/iter34-实现报告-2026-10-22.md | 278 ---------------- reports/iter34-验收审计-2026-10-22.md | 100 ------ reports/iter34-验收审计-复审-2026-10-22.md | 98 ------ .../需求卡片-信息迷雾可见性批-2026-10-21.md | 246 -------------- .../需求卡片-敌人表深度带换代批-2026-10-21.md | 313 ------------------ roadmap.md | 6 +- 体验验证清单.md | 15 + 待办清单.md | 18 +- 18 files changed, 58 insertions(+), 1433 deletions(-) delete mode 100644 reports/iter34-代拍板-2026-10-22.md delete mode 100644 reports/iter34-卡④-验收审计-2026-10-22.md delete mode 100644 reports/iter34-卡④-验收审计-复审-2026-10-22.md delete mode 100644 reports/iter34-反哺点-2026-10-22.md delete mode 100644 reports/iter34-实现报告-2026-10-22.md delete mode 100644 reports/iter34-验收审计-2026-10-22.md delete mode 100644 reports/iter34-验收审计-复审-2026-10-22.md delete mode 100644 reports/需求卡片-信息迷雾可见性批-2026-10-21.md delete mode 100644 reports/需求卡片-敌人表深度带换代批-2026-10-21.md diff --git a/design/engineering/test-conventions.md b/design/engineering/test-conventions.md index 37533e29..684caa7b 100644 --- a/design/engineering/test-conventions.md +++ b/design/engineering/test-conventions.md @@ -122,6 +122,7 @@ - **修改既有行为**:只撤销该改动(回退该 hunk 或该处接线)→ 跑能覆盖它的最窄测试 → 对应断言必须变红 → 还原 → 复绿。 - **新增行为**:用 §6 的变异办法把新代码改坏成最小缺陷形态 → 对应断言必须变红。 - **撤销后仍然绿**:说明断言没钉在这个改动上,判缺漏;不得用「代码能跑通」代替。 +- **判据绑可观测提交面**:端到端断言的判据要绑「被测改动特有的可观测提交面」(信号发射、事件、入参、绘制记录),不绑多层防御之后的终态——否则单点变异可能被下游兜底吸收,终态不变而假绿。例:探针「雾不扩可点域」首版只看屏/选路态终态,命中面放宽的变异仍绿;改绑 `route_chosen` 发射面后变异即红。 - 每张任务卡至少一条撤销或变异记录;持久化、生命周期、存档、跨战共享这类接线逐行做。 ### 9.5 禁止削弱测试 diff --git a/design/gdd/systems/冒险循环/关卡节点图生成.md b/design/gdd/systems/冒险循环/关卡节点图生成.md index fc702680..69d888b8 100644 --- a/design/gdd/systems/冒险循环/关卡节点图生成.md +++ b/design/gdd/systems/冒险循环/关卡节点图生成.md @@ -1,7 +1,7 @@ # 关卡节点图生成 > 一句话:一关的节点图从哪来——生成器按参数长出一张合法图 -> 状态:现行为 v1.1 +> 状态:现行为 v1.2 ## 设计目的 @@ -38,7 +38,7 @@ ### 图的规格:什么算一张合法的图 -合法图是一张岔路发散式道路系统:主路+支路,宽度由分叉自然长出,多终点时提前承诺归属。产出约束五条,每张产出图都必须满足: +合法图是一张岔路发散式道路系统:主路+支路,宽度由分叉自然长出,多终点时提前承诺归属。产出约束六条,每张产出图都必须满足: | 约束 | 内容 | |---|---| @@ -47,6 +47,7 @@ | 层高=沿路步数 | 入口到终点的最长路径步数;第一关 ≥6,逐关递增且增幅变大 | | 出口归属锁定 | 多终点时由大岔口把图分成互不连达的分支区域,各区域只通向自己的终点;每个终点前一层节点的去路集合恰含一个终点——选路=提前承诺打谁 | | 战斗节点保底 | 奖励/恢复/商店占位后战斗节点量不被挤没(保底数进调参表) | +| 多终点深度互异 | 多终点(多 Boss 节点)必须落在互异的深度带;同一深度带出现两个终点即判产出无效——共带会让「走哪条路打谁」落空 | 结构铁律:连线只朝前进方向(无环);入口、终点都可多个(个数=参数档),每条路径恰好从一个入口出发、恰好到达一个终点。 @@ -80,7 +81,7 @@ | 约束 | 内容 | |---|---| | 商店位 | 每个终点前一位恰一家商店——每名玩家一局必经恰一家店 | -| 岔路取舍·下一跳 | 一个岔口分出的各条去路,下一节点类型互不相同——下一跳必在可见范围,是决策的可见锚 | +| 岔路取舍·下一跳 | 一个岔口分出的各条去路,下一节点类型互不相同——下一跳必在可见范围,是决策的可见锚(实现侧已兑现:候选集强制豁免类型可见性) | | 岔路取舍·支路构成 | 一个岔口分出的各条支路,整条支路的节点类型构成互不相同——每条支路至少有一个别的支路没有的类型(例:一路有恢复节点、一路有奖励节点) | 内容归各 owner:战斗节点打谁=敌人系统按深度带配池;奖励/恢复/商店的兑付语义=关卡节点地图与各 owner 文档。 @@ -113,12 +114,13 @@ | 配比 | 四类占比合计 1,战斗保底优先 | 攻击性/兑付/恢复的节奏配比 | provisional | | 战斗节点保底数 | ≥ 调参值 | 成长位不挤没战斗——战斗是本作核心量 | provisional | | 商店数 | =出口数 | 每局决战前恰一次补给,成长保底是结构事实 | 已锁 | +| 图包络 | ≤ 屏预算(1280×800 下约 10 层×8 槽) | 超预算只许限参数档,禁改画布冻结公式 | 已锁 | ## 验收标准 | 判据 | 内容 | |---|---| -| 产出合格 | 任意参数档产出的图必过产出约束五条+结构铁律;任意入口出发的任意路径都恰好到达一个终点 | +| 产出合格 | 任意参数档产出的图必过产出约束六条+结构铁律;任意入口出发的任意路径都恰好到达一个终点 | | 生长递增 | L1/L2/L3 读数:最长路径步数与节点总数均逐关递增;节点总数增幅 Δ(L2→L3)>Δ(L1→L2) | | 归属锁定 | 多出口图每个终点前一层节点的去路集合恰含一个终点;各分支区域互不连达 | | 必经恰一店 | 任意入口→终点路径经过且恰经过一家店 | diff --git a/design/gdd/systems/冒险循环/关卡节点地图.md b/design/gdd/systems/冒险循环/关卡节点地图.md index f716fc77..a845d6ea 100644 --- a/design/gdd/systems/冒险循环/关卡节点地图.md +++ b/design/gdd/systems/冒险循环/关卡节点地图.md @@ -1,7 +1,7 @@ # 关卡节点地图 > 一句话:单关内的节点图选路与推进 -> 状态:现行为 v2.1 +> 状态:现行为 v2.2 ## 设计目的 @@ -64,7 +64,7 @@ 每个节点在图上有**节点深度**(本文含义:从入口沿路走过来的步数),用来当战斗的定位地址——遭遇坐标=关卡序号+节点深度,敌人表按**深度带**(深度区间)配池,寻址语义见[敌人系统](../战斗循环/敌人系统.md)。"最深处是关底"的直感由深度承载:终点恒在各路径最深处。单链(每步只有一条连线)是合法退化形态,节点深度等于它前面走过的战斗场数;三关参数档都含岔口,第一关不再是单链。图的来源见[关卡节点图生成](关卡节点图生成.md)。 -呈现侧口径(2026-09-17 用户拍板):节点图的画面表达走**方块地牢观感**——节点画成地牢房间的方块、连线画成通道——但逻辑拓扑就是本文的节点图,不产生任何额外选路或探索语义。关卡画面本体即节点链进度的呈现载体(选路覆盖层的常驻形态,节点态直接读图:已过暗金 / 当前金 / 候选下一跳通道亮金 / Boss 封印黑描边(旗朱→封印紫→封印黑 #000000,2026-09-28 用户拍板现行)),不另设进度条组件;视觉规格归 [HUD 框架](../表现与支撑/HUD框架.md)。 +呈现侧口径(2026-09-17 用户拍板):节点图的画面表达走**方块地牢观感**——节点画成地牢房间的方块、连线画成通道——但逻辑拓扑就是本文的节点图,不产生任何额外选路或探索语义。关卡画面本体即节点链进度的呈现载体(选路覆盖层的常驻形态,节点态直接读图:已过暗金 / 当前金 / 候选下一跳通道亮金 / Boss 紫赤描边(紫赤+深墨环,视觉定稿见 [level-map](../../ux/level-map.md))),不另设进度条组件;视觉规格归 [HUD 框架](../表现与支撑/HUD框架.md)。 **商店覆盖层呈现**(呈现 spec:[design/gdd/ux/shop.md](../../ux/shop.md) v1.0,2026-09-30;**v1.5 注记**——pool 模式货架面=共享池三选一同构卡〔进店抽 3/买 1 全重抽/空架售罄态〕,与三选一奖励同一交互语言;legacy 固定三件面随对照模式保留。**v1.5-a 注记(2026-10-04 用户裁)**:~~库存余量就近~~ **库存余量不呈现**(货架卡不带「库存余 N/∞」字样——库存语义仍在共享池令牌库,仅呈现退役;独立刷新机制另见待办清单「商店独立刷新机制」条):兑付 = 打开商店覆盖层(模态)——货架卡陈列、GP 余额读数、购买/离开;离开后兑付确认回选路。本节锁编排面(何时开/何时关/回选路),呈现细节归 spec;定价数值归[难度曲线与Boss](难度曲线与Boss.md)(shop.tres)。 @@ -102,6 +102,8 @@ Boss 兑付(胜利或英雄死亡)触发关卡收束点,此后不再有选 终点恒为 Boss,**Boss 标记与终点身份不入雾**——「走哪条=打谁」是提前承诺,承诺必须有信息前提:雾遮的是途中有什么,不遮终局打谁。N 为本系统自有参数(见调参表)。 +实现语义三句:层距=从入口出发的 BFS 层差;Boss(含终点)与当前候选节点双豁免,恒显类型;可见性只算当前这一圈——已走过的节点回雾,不累积记忆。 + ### 节点兑付:把控制流移交给小循环 **人话阶段**:节点兑付就是"走到这个房间里,这个房间的事开始发生"。本文按节点类型触发兑付,然后把属于别家领域的事交还给别家——本文自始至终不生产任何数值。 @@ -143,7 +145,7 @@ Boss 兑付(胜利或英雄死亡)触发关卡收束点,此后不再有选 |---|---|---| | 上游 / 下游 | [冒险结构](冒险结构.md) | 接口契约四件套(开始关卡 / 战斗结果上报 / 治疗封顶回报 / 关卡结束)+ 收束点次序语义:向下接开始关卡,向上报战斗结果、恢复请求与关卡结束 | | 上游 | [奇物](奇物.md) | 节点奖励件的分类、凭证与持有语义(提升池构成与共享池库存归[冒险结构](冒险结构.md)) | -| 上游 | [敌人系统](../战斗循环/敌人系统.md) | 定位信息的消费方:本文递出关卡序号 + 节点编号,按编号生成单位归它 | +| 上游 | [敌人系统](../战斗循环/敌人系统.md) | 定位信息的消费方:本文递出关卡序号+节点深度,敌人侧按深度带配池生成单位 | | 上游 | [难度曲线与Boss](难度曲线与Boss.md) | 敌我数值曲线与遭遇投放节奏的调参所有权;本文零数值 | | 上游 | [数据配置](../表现与支撑/数据配置.md) | 商店表(商品行 / GP 掉落参数 / 价格参数)的承载与统一读取;商店覆盖层的商品与定价数据源 | | 下游 | [战斗结算](../战斗循环/战斗结算.md) | 两个调用入口的发起方:战斗发起组装(定位信息)、关卡收束(清库) | @@ -169,7 +171,7 @@ Boss 兑付(胜利或英雄死亡)触发关卡收束点,此后不再有选 ## 调参表 -本系统自有参数一项——**信息可见层数 N**(int ≥ 1,provisional,定值批落数据表):节点类型可见距离(层),范围外信息迷雾只见结构。图结构合法性是规则不是参数(规则语义见[关卡节点图生成](关卡节点图生成.md)的产出规格),由加载校验强制;图的来源与节点构成归[关卡节点图生成](关卡节点图生成.md),战斗数值归难度曲线与Boss。 +本系统自有参数一项——**信息可见层数 N**(int ≥ 1,provisional,已落数据表:`level.tres` 的 `info_visible_layers`,现行值 2):节点类型可见距离(层),范围外信息迷雾只见结构。图结构合法性是规则不是参数(规则语义见[关卡节点图生成](关卡节点图生成.md)的产出规格),由加载校验强制;图的来源与节点构成归[关卡节点图生成](关卡节点图生成.md),战斗数值归难度曲线与Boss。 ## 验收标准 diff --git a/design/gdd/systems/战斗循环/敌人系统.md b/design/gdd/systems/战斗循环/敌人系统.md index 231b4fdf..72f32035 100644 --- a/design/gdd/systems/战斗循环/敌人系统.md +++ b/design/gdd/systems/战斗循环/敌人系统.md @@ -64,21 +64,21 @@ ### 开战生成:主角数据行与一场 1–4 个敌人(行集可混编多种敌种) -战斗开始时,编排方给出遭遇坐标(关卡序号 + 深度带——节点深度所在的区间),本系统据此在敌人表里取出该坐标的整个行集(一行或多行),把本战实际数量的敌人逐行生成出来——每行各按自己的数量行值实例化(单行 1 到 3 个),行集实例总数(各行开战骰后数量求和)不超过 4。同坐标多行即混编遭遇:各敌种同场上阵,生成序 = 表文件行序(行序即契约——目标顺位、摇号子流派生、开战叙述取首行都按它,加载期校验兜底:同坐标多行必须文件内相邻)。单行行集 = 既有形态:一场 1 到 3 个同种同属性敌人,来自同一行表值。战斗中敌人只减不增,不做召唤、增援、分裂。主角同时以当前血量入参生成,血量越界(高于上限或不超过 0)整单拒绝、不留半实例。 +战斗开始时,编排方给出遭遇坐标(关卡序号 + 深度带——节点深度所在的区间),本系统据此在敌人表里取出该坐标的整个行集(一行或多行),把本战实际数量的敌人逐行生成出来——每行各按自己的数量行值实例化(单行 1 到 3 个),行集实例总数(各行开战骰后数量求和)不超过 4。同带键多行即混编遭遇:各敌种同场上阵,生成序 = 表文件行序(行序即契约——目标顺位、摇号子流派生、开战叙述取首行都按它,加载期校验兜底:同带键多行必须文件内相邻)。单行行集 = 既有形态:一场 1 到 3 个同种同属性敌人,来自同一行表值。战斗中敌人只减不增,不做召唤、增援、分裂。主角同时以当前血量入参生成,血量越界(高于上限或不超过 0)整单拒绝、不留半实例。 生成拿到的是当时的表值快照:开战那一刻把每行的数值和池模板各抄一份,之后改表不影响已生成的单位。池模板快照成每实例自己的实例池(各技能冷却清零),此后各自独立摇号、互不干涉。某行的数量或攻击基线若配成了区间,由战斗结算用封闭随机流在开战时**按行各掷定一次**(每行掷自己的区间;掷定次数随行数——单行行集的掷定次数与既有口径逐位一致,混编不新增随机源形态)后传入确定值——本系统自身始终零随机;掷定后整场持久,攻击基线不逐拍重掷(数字要可读)。 | 规则 | 含义 | |---|---| | 敌方效果对全体生效 | 范围效果作用于所有存活敌人——混编放开后(2026-10-07 行集多行批)场上可多种敌种共存,结算语义按存活单位逐一生效、不依赖"场上全同种"前提;"只打某一个"的单体寻址暂不开放(见 P1) | -| 行集构成纪律 | 敌人表按(关卡序号 × 深度带)存放;深度带=节点深度的区间——逐局生成使单点深度不再固定,配池按带不按点,难度坡随带递增。同一坐标行集允许多行、允许不同敌种混编;Boss 行按终点配置,多终点各配一行(走哪条路决定打谁)。纪律三条,违规加载期返回错误并止动:①行集内 enemy_id 唯一(同一敌种在同行集仍只许一行);②同坐标多行必须表文件内相邻,行序 = 声明序 = 生成序(行序即契约);③行集实例总数(各行骰后数量求和)≤ 4,单行数量域 [1,3] 不变(UNIT_COUNT_MAX 语义 = 单种数)。行数不设上限;同关随深度换敌种合法 | +| 行集构成纪律 | 敌人表按(关卡序号 × 深度带)存放;深度带=节点深度的区间——逐局生成使单点深度不再固定,配池按带不按点,难度坡随带递增。同一带键行集允许多行、允许不同敌种混编;Boss 行按终点配置,多终点各配一行(走哪条路决定打谁)。纪律三条,违规加载期返回错误并止动:①行集内 enemy_id 唯一(同一敌种在同行集仍只许一行);②同带键多行必须表文件内相邻,行序 = 声明序 = 生成序(行序即契约);③行集实例总数(各行骰后数量求和)≤ 4,单行数量域 [1,3] 不变(UNIT_COUNT_MAX 语义 = 单种数)。行数不设上限;同关随深度换敌种合法 | | 主角数据行 | 主角战斗数值单独放一张全局单行表:生命上限、基础攻击力、护甲等级三字段(见调参表) | | 基础攻击恒存在 | 基础攻击不许配 0(配置为 0 加载期拒绝)——零基线乘任何百分比增益恒为零,"胜利路径恒有"的保障从数据层杜绝死锁 | | 先手攻击不是敌方技能拍 | 每次结算战斗段主角先手攻击顺位最前的存活敌人,这是固定动作;奖励侧的道具与增益是基础攻击之外的规划面伤害,归[地图战斗资源](地图战斗资源.md) | 首发敌种三种——地精、熊地精、食人魔酋长(末者为首发关底 Boss);L2/L3 内容批扩至现行八种。名字是玩家可见专名,池权重与护甲等级行值一律读配置表,本表只存敌种语义模板: -> **hobgoblin 缺口登记(2026-10-13 迭代 24 反哺④)**:敌人表有 `hobgoblin` 数据行((1,3),即第一关第四节点的「大地精」行),**无立绘、不在本敌种表**——登记在案的已知缺口(敌种语义模板未成文故呈现面无定义可依),本批未动;补齐归敌种内容批(立绘+语义模板+敌种表行三件套)。 +> **hobgoblin 缺口登记(2026-10-13 迭代 24 反哺④)**:敌人表有 `hobgoblin` 数据行(寻址键 (1, battle, 3) 的「大地精」行),**无立绘、不在本敌种表**——登记在案的已知缺口(敌种语义模板未成文故呈现面无定义可依),本批未动;补齐归敌种内容批(立绘+语义模板+敌种表行三件套)。 | 敌种 | 技能池构成(权重读表) | 护甲类型 | 护甲等级 | 定位 | |---|---|---|---|---| @@ -262,7 +262,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错 各敌种行值、池权重与池 EV 读数(含闸长期速率实测)一律读配置表与调参日志,本文不登记具体数值;EV 重锚与权重投值归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)。 -结构冻结(非调参项,修订走本文流程):技能类型枚举封闭、每池恰一普攻、每池增益 ≤1、死亡即不动手(摇定后兑现前死亡作废不进账)、每结算每存活敌恰行动一次、行序、先作用后推进、固定顺位、**行集构成纪律(2026-10-07 行集多行批换代——原「每坐标恰一敌种」退役:行集内 enemy_id 唯一 + 同坐标多行文件内相邻且行序 = 声明序 = 生成序 + 行集实例总数 ≤ 4)**、零随机(本系统自身语义零随机不变——摇号与掷点随机一律在[战斗结算](战斗结算.md)结算换算层按封闭随机流掷定,可回放契约 = 同种子同输入逐位复现,单敌出招轨迹可独立复放)。联动纪律:技能倍率 × 攻击(伤害拍支配)、权重 × 冷却 × 保底(池节奏三联动)禁止独立调参,联调须重跑方向性预检并同步 registry(登记 [待办清单](../../../../待办清单.md))。 +结构冻结(非调参项,修订走本文流程):技能类型枚举封闭、每池恰一普攻、每池增益 ≤1、死亡即不动手(摇定后兑现前死亡作废不进账)、每结算每存活敌恰行动一次、行序、先作用后推进、固定顺位、**行集构成纪律(2026-10-07 行集多行批换代——原「每坐标恰一敌种」退役:行集内 enemy_id 唯一 + 同带键多行文件内相邻且行序 = 声明序 = 生成序 + 行集实例总数 ≤ 4)**、零随机(本系统自身语义零随机不变——摇号与掷点随机一律在[战斗结算](战斗结算.md)结算换算层按封闭随机流掷定,可回放契约 = 同种子同输入逐位复现,单敌出招轨迹可独立复放)。联动纪律:技能倍率 × 攻击(伤害拍支配)、权重 × 冷却 × 保底(池节奏三联动)禁止独立调参,联调须重跑方向性预检并同步 registry(登记 [待办清单](../../../../待办清单.md))。 ## 验收标准 @@ -275,7 +275,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错 - 警觉授予:踩 N 颗雷叠 N 层、逐层直授无上限;敌方全体共享同一状态值(side-wide)。 - 目标顺位:多敌时单体目标恒为生成序最前存活者,杀最前后顺延;杀至空返回空;单敌时顺位与范围效果重合。 - 快照抗改表:实例化后修改敌人表,已生成单位的数值投影与实例池逐字不变;新实例才用新表值。 -- 表校验:越域值、池权重 ≤ 0、空池、普攻配倍率/冷却、池增益 > 1、skill_id 悬空、行集构成违例(行集内同敌种第二行 / 同坐标多行不相邻)均在加载期返回错误并止动;域内合法极端(攻击基线 0)不拒;主角表恰一行、攻击配 0 拒绝。 +- 表校验:越域值、池权重 ≤ 0、空池、普攻配倍率/冷却、池增益 > 1、skill_id 悬空、行集构成违例(行集内同敌种第二行 / 同带键多行不相邻)均在加载期返回错误并止动;域内合法极端(攻击基线 0)不拒;主角表恰一行、攻击配 0 拒绝。 - 零随机回放:同一动作与受击序列驱动两个独立实例,存活投影、逐实例摇定轨迹、顺位返回序列逐项相同。 - 表实一致:三张配置表字段与 `data/schemas/enemy_table.gd`/`hero_table.gd`/`skill_table.gd` 逐字段一致。 diff --git a/design/gdd/ux/level-map.md b/design/gdd/ux/level-map.md index b83e6ed0..72dc4e66 100644 --- a/design/gdd/ux/level-map.md +++ b/design/gdd/ux/level-map.md @@ -51,7 +51,7 @@ 本屏必须传达的全部信息,按注视优先级分六层: -1. **节点图本体**(第一注视点):节点方块(五类型字面:战/赏/疗/王/商)、通道连线、当前位置、可选去路 +1. **节点图本体**(第一注视点):节点方块(五类型字面:战/赏/疗/王/商)、通道连线、当前位置、可选去路;类型可见性=邻近 N 层内显示类型,范围外只见结构(机制见[关卡节点地图](../systems/冒险循环/关卡节点地图.md)) 2. **候选选路口**:亮金候选通道 + 候选节点亮金描边——「下一步能去哪」的图上双冗余(2026-09-27 拍板:候选按钮退役,图上点击为唯一提交通道) 3. **常驻语境**(顶栏):关卡名(第 N 层·名称)、GP 常驻总量(2026-09-26 二轮拍板去向:GP = 关卡画面常驻总量,[battle.md](battle.md) OQ14 口径经 2026-09-27 GP 归属拍板对齐批维持) 4. **状态展示**(底栏,2026-09-27 拍板):生命(当前/上限)、属性(攻击 / 护甲 AC 有效值)、本关已选加成(统一冒险加算区增量)——选路规划原料常读 @@ -65,7 +65,7 @@ | 区 | 位置与尺寸 | 内容 | |---|---|---| | **顶栏语境** | 居中横排,图区上方,高约 32px | 左:关卡名(`level_row.display_name`,如「第二层 · 幽暗地域」);右:GP 常驻徽章(GP 图标+数字,直角细线数据框——GP 值域超点阵适用档,走 pattern 5 的 When-NOT-to-Use 路线);HP 归底部状态栏(2026-09-27 拍板完成) | -| **节点图区** | 居中 | 整幅节点图自绘:节点方块 + 通道折线 + 节点态着色 + Boss 紫赤描边。画布随图自适应(**冻结公式**:宽 = 70+层深×122+34、高 = 52+槽位×58+26+8,下限 620×240——routebug 83c11a1 根修件);通道折线**冻结 2/3/4px**(未点亮石灰 STONE/候选亮金 GOLD_LIT/悬停加粗);节点方块 52×36 内**节点图标 20px 烘焙 1:1**(♻ kenney 五键:战=弓/赏=桂冠/疗=篝火/王=王冠/商=钱袋,WARM 单色、当前金底转深墨——双色墨制)+ 编号 10px 右上角 | +| **节点图区** | 居中 | 整幅节点图自绘:节点方块 + 通道折线 + 节点态着色 + Boss 紫赤描边。画布随图自适应(**冻结公式**:宽 = 70+层深×122+44.5、高 = 52+槽位×58+25+24,下限 620×256——routebug 83c11a1 根修件);通道折线**冻结 2/3/4px**(未点亮石灰 STONE/候选亮金 GOLD_LIT/悬停加粗);节点方块 52×36 内**节点图标 20px 烘焙 1:1**(♻ kenney 五键:战=弓/赏=桂冠/疗=篝火/王=王冠/商=钱袋,WARM 单色、当前金底转深墨——双色墨制)+ 编号 10px 右上角 | | **底部状态栏** | 图区下方横排,高约 48px | 左-中:状态数据框组(直角细线,pattern 5 族)——生命(当前/上限 + 迷你血条)、属性(攻击 / 护甲 AC,有效值 + 加成角标)、本关加成(攻+X · 上限+Y · AC+Z,零加成隐藏);右端:放弃冒险按钮(危险红族文字,与状态数据框保持间距——破坏性确认异位,pattern 7) | ### Component Inventory diff --git a/design/gdd/术语表.md b/design/gdd/术语表.md index b4ea59a7..f6d4a876 100644 --- a/design/gdd/术语表.md +++ b/design/gdd/术语表.md @@ -18,6 +18,12 @@ | 装板(装板期) | 把地图战斗资源摇定的类型身份铺设到棋盘格子上的布置动作(阶段);由战斗结算的布置段执行,随机取数标签为 `variant_place` | | 摇号 / 摇定 | 按池配置用随机数决定结果(资源身份、遭遇抽取、货架抽签);随机服务实现见 `game/core/rng_service.gd`(流标签为代码事实) | +## 关卡与地图 + +| 术语 | 定义 | +|---|---| +| 信息迷雾 | 关卡节点图上按邻近层数隐藏节点类型的可见性机制——只隐藏类型,结构(节点、连线、入口、终点位置)恒可见;与「视野迷雾」(战斗棋盘按英雄曼哈顿半径遮挡格子)同词根易混,代码标识符一律不用 `fog_` 前缀。参数 N=信息可见层数(`level.tres` 的 `info_visible_layers`),机制见[关卡节点地图](systems/冒险循环/关卡节点地图.md) | + ## 系统资源与经济 | 术语 | 定义 | diff --git a/reports/iter34-代拍板-2026-10-22.md b/reports/iter34-代拍板-2026-10-22.md deleted file mode 100644 index 324eaffe..00000000 --- a/reports/iter34-代拍板-2026-10-22.md +++ /dev/null @@ -1,33 +0,0 @@ -# 迭代 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 清单自决的设计分歧。 - -## 卡④ 信息迷雾可见性批 - -> 白名单依据=`reports/需求卡片-信息迷雾可见性批-2026-10-21.md` §9(六条)。 - -| # | 白名单条目 | 实际做法 | 约束核验 | -|---|---|---|---| -| 1 | provisional N=2(§9-1) | `level.tres` 挂 `info_visible_layers = 2`;`validate` 只校验 int ≥ 1 | 定值仍在数据表,代码零硬编码;N=1/3 改表实测可见窗随动 | -| 2 | API/探针命名(§9-2) | `info_visible_layers`/`type_visible_ids`/`node_display`/`display_probe` | 均无 `fog_` 前缀,与战斗「视野迷雾」零撞词 | -| 3 | 雾下节点呈现落点(§9-3) | 图标/类型文字改读 `node_display` 输出;节点方块、编号、连线结构通道零改动 | 编号保留、类型文字不绘制;结构通道冒烟与渲染闸全绿 | -| 4 | 大图夹具规模(§9-4) | 12 个 BFS 层构造(跨层跳边压层后布局实得 11 层×6 槽)、含双 Boss、跨层跳边 | 满足 ≥10 层 × ≥5 槽;断言按布局实测 `maxl/maxslot` 推导 | -| 5 | 常数锚同源化方式(§9-5) | 探针直接引 `LevelMapScreen.LAYER_BASE_X/LAYER_STEP_X/NODE_HALF` 导出常量 | 与 `_fit_canvas` 公式逐项同源,无手抄数字副本 | -| 6 | 提交切分与分支命名(§9-6) | 分支 `iter34-fog`;三笔:实现与断言(`ed8e0f9f`)、⑱ 判据改绑(`4ef154b9`)、类型闸归零+探针补尾缀(`6f04f29b`) | 三笔均在 `game/` 内;报告随批落 `reports/` | -| 7 | 白名单外——审计缺漏 D1 的接线层验收手段(卡片 §9 未列,已呈报三案) | 呈报甲(补绘制输出观测面)/乙(改 §7.1 口径)/丙(单次快照降级)并推荐甲;用户回「继续未完成的任务」后按甲落地:`_draw_graph` 绘制点记录本帧绘制事实,`display_probe()` 改读该记录 | 改动集中在提交 `1970e0ef`,一笔可回退;未触碰冻结视觉件(零新画法/色值/线宽/缩放滚动),新增面为只读成员与记录赋值 | - diff --git a/reports/iter34-卡④-验收审计-2026-10-22.md b/reports/iter34-卡④-验收审计-2026-10-22.md deleted file mode 100644 index eda8085d..00000000 --- a/reports/iter34-卡④-验收审计-2026-10-22.md +++ /dev/null @@ -1,164 +0,0 @@ -# 迭代 34 卡④(信息迷雾可见性批)独立验收审计报告(2026-10-22) - -> 审计员:未参与本卡实现的独立子代理。审计期只读源码/测试/产出物,自跑命令取证;除本报告外未写任何文件。 -> 审计对象:`D:\code\g-plan2-iter34-fog`(分支 `iter34-fog`,任务指定被审 HEAD `477fd0f5`,审计起点 `43c0f3c1`)。 -> 审计期分支前进说明:审计过程中分支新增 `6757c21e`(docs-only,仅 `reports/iter34-反哺点-2026-10-22.md` 追加 ⑮ 体验验证清单登记,6 行)。本报告结论按任务指定 HEAD `477fd0f5` 的代码面给出;`6757c21e` 不触及代码与测试,不影响任何判定,仅在反哺点相符性一节并入核对。 - -## 1. 审计范围与基线 - -| 项 | 内容 | -|---|---| -| 被审 diff | `git diff 43c0f3c1..HEAD`:14 个文件(`game/` 11 件:核心 1/schema 1/数据 1/呈现 1/冒烟 2/单测 4(含 2 个 .uid)/manifest 1;`reports/` 3 件)。审计期 HEAD 前进后为 15 件(多 1 件 docs-only) | -| 工作树状态 | 审计开工与收尾 `git status --short` 均为空;4 次变异注入后均 `git checkout --` 还原并复核为空 | -| 环境 | Godot 4.7.2 console;python 前置 `PYTHONIOENCODING=utf-8`;长测前清理了残留 `ui_click_probe` Godot 进程(2 个),全程串行单实例 | -| 不采信项 | 实现报告 §5.7 的「已全绿」自述仅作对照,判定一律用下面自跑读数 | - -### 1.1 自跑命令与读数(原文) - -| # | 命令(工作目录) | 读数原文 | 退出码 | -|---|---|---|---| -| C1 | `Godot…console.exe --headless --path . --script res://tests/unit/core/level_map_type_vis_test.gd`(`game/`) | `[level_map_type_vis_test] all green (26 checks)` | 0 | -| C2 | 同上换 `res://tests/unit/presentation/level_map_info_fog_test.gd` | `[level_map_info_fog_test] all green (19 checks)` | 0 | -| C3 | 同上 `res://tests/run_all.gd` | `[run_all] all green (40 suites)` | 0 | -| C4 | `Godot…console.exe --headless --path . res://smoke/ui_input_probe.tscn`(`game/`) | `[ui_input_probe] PASS — …十八断言全绿`(见 §4 观察项 3) | 0 | -| C5 | `python tools/run_smoke.py`(工作树根) | `[run_smoke] 摘要: 冒烟完成:1211 项检查,0 项失败`+`[run_smoke] PASS(退出码 / 摘要失败数 / 脚本错误扫描 三闸全过)`;新增 5 条「可见性冒烟」断言逐条 `[PASS]`(含〔fv4〕〔fv3〕〔fv6〕〔fv1〕) | 0 | -| C6 | `bash game/tests/static_scan.sh` | `[audit_type_hints] PASS——产品码类型闸归零(R1/R2/R3)`;`[static_scan] S9 ok` … `结构审计 PASS` | 0 | -| C7 | `python tools/audit_type_hints.py` | `[audit_type_hints] PASS——产品码类型闸归零(R1/R2/R3)` | 0 | -| C8 | 读 `game/tests/.gates/receipt.json` | `commit: 4ef154b9…`;`09 静态扫描 exit: "1"`;`all_green: false`;`changed_vs_baseline: ["09 静态扫描:红项清单变化…"]` | — | - -要点:C1–C7 证明**当前代码面**的冒烟、单元、探针、静态扫描在我手上全绿;C8 证明**闸回执证据**停留在 `4ef154b9`,且该次 09 红、`all_green=false`,此后还有 2 个代码相关提交(`6f04f29b` 改 3 个 `game/` 文件、`477fd0f5`/`6757c21e` 仅文档)。这一差异见 §5.2 与 §6 缺漏 D2。 - -## 2. §7.1 对照表逐行结论(fv1–fv9) - -判定口径:①断言真实存在且尾缀可 grep;②真实入口符合卡片该行声明;③断言强度足以在改动撤销/单点变异时变红。行内「通过」均附自跑依据。 - -| fv | 断言存在(文件:行,实测 grep) | 真实入口核对 | 断言强度核对 | 结论 | -|---|---|---|---|---| -| **fv1 邻近 N 层见类型** | `level_map_type_vis_test.gd:121/122/123`(层距 2 可见、3/4 不可见)、`:142/143`(入口锚层 0)、`:166/167/168`(单链退化);`smoke_all.gd:4942-4943`(真图节点 7/8 入雾)。尾缀〔fv1〕共 8 处断言+3 处注释 | 核心 `type_visible_ids()` 直调(卡片该行声明即此)+冒烟真图 L2 入口停点 | 边界两侧都断言(N 内真、N+1 假),非恒真;M1 实测 4 条红(§3) | **通过** | -| **fv2 范围外只见结构** | `level_map_info_fog_test.gd:51/54/56`(显隐与无描边)、`:96/98/100`(label 三态);`ui_input_probe.gd:59-62`(⑱ 雾下节点双通道,尾缀在 :60)。尾缀〔fv2〕共 8 处 | 单元=`ScreenScript.node_display` 纯函数(卡片允许);探针=`ro.display_probe()`。**但 `display_probe()` 内部是逐节点重调 `node_display`(`level_map_screen.gd:536-547`),不是读取实际绘制输出**——卡片该行要求「真机 `display_probe()` 读绘制面(接线层验收——防『断言在、接线坏、不红』)」不成立 | 单元决策面断言有效(M2 红);⑱ 的「图标不出示」判据自指(fog_id 正是按 `draw_icon==false` 选出,再断言其 false,恒真;「文字不出示」判据有效)。**接线层(`_draw_graph` 是否消费决策面)零断言:我注入「两处 `if bool(disp[...])` 直接改 `if true`」=模拟接线坏,C2 仍 `19 checks` 全绿、C4 仍 PASS**(§3 W1) | **缺漏**(详见 §6 D1) | -| **fv3 Boss/终点不入雾+多终点标记** | `level_map_type_vis_test.gd:144/145`(远距 Boss 在集、同层距非 Boss 不在集);`level_map_info_fog_test.gd:65/67/70/73`(双 Boss 描边、Boss 三通道在、远 Boss 不入雾、豁免不扩散);`ui_input_probe.gd:63-64`;`smoke_all.gd:4939`(真图 L2 Boss=9 在集)。尾缀〔fv3〕共 9 处断言 | 核心可见集直调+`node_display` 直调+真机 `display_probe`(卡片该行声明即此)+冒烟真图 | 单 Boss 核心豁免与双 Boss 决策面均有断言;M3/M4 报告已证(我未复跑,M2 连带 `Boss 豁免不扩散〔fv3〕` 实测红,说明该条有敏感度)。观察项:双 Boss 夹具把 7/9 直接写进 `type_vis=[1,7,9]`,未从 `type_visible_ids()` 推导「均在集」,多终点核心成员性只有单 Boss 用例覆盖同一代码分支(非阻塞,见 §4 观察项 4) | **通过**(含 1 条观察项) | -| **fv4 下一跳恒可见** | `level_map_type_vis_test.gd:132/133`(跨层跳边候选层距 N+1 仍在集、同锚非候选不在集);`smoke_all.gd:4938`(真图候选 ⊆ 可见集);`ui_input_probe.gd:66-67`(真机候选 draw_icon)。尾缀〔fv4〕共 3 处 | 核心直调+冒烟真图+探针 | 跨层跳边是反例夹具,删候选豁免会红(报告 M5;未复跑);M2 不连带此条,逻辑独立 | **通过** | -| **fv5 节点内详情不显示** | `level_map_info_fog_test.gd:87/88`(携带 `enemy_id/reward_id` 与不带者逐键相等;label 不含内容值,实际打印「战斗 · 可选」)。尾缀〔fv5〕共 3 处 | `node_display` 纯函数(卡片该行声明即此) | 逐键相等+字符串不含,两条互补;M6 报告已证(未复跑)。`node_display` 正文只读 `type`,代码审读一致 | **通过** | -| **fv6 N 进数据表** | `level_map_type_vis_test.gd:96`(真表读数 2)、`:100/102/104`(N=1 合法、0/-1 判 domain 错)、`:178/180/186`(改表 N=1/3/10 可见窗随动);`smoke_all.gd:4940-4941`(真图读表=2)。尾缀〔fv6〕共 7 处断言 | `LevelTable.validate()`+`db.level.info_visible_layers` 读值(核心直调,卡片声明即此) | 不是「读一次字段」——改表值三档窗随动+越域双值判错,强度够;M7a/M7b 报告已证(未复跑) | **通过** | -| **fv7 单圈语义** | `level_map_type_vis_test.gd:155/156/157`(visited 不豁免:远/中距回雾、近端仍显)、`:207`(`start_level_external` resume_state 重建与直入逐位一致)。尾缀〔fv7〕共 6 处 | 核心直调+真实 resume 入口 | visited 显式注入后仍不可见=单圈成立;resume 断言两侧同函数、若两者同空会平凡相等,但同套件其余组已证函数非空输出,风险可接受 | **通过** | -| **fv8 画布自适应** | `level_map_info_fog_test.gd:169`(规模实测 maxl=10/maxslot=6)、`:175`(min.x 1334.5 ≥ 1334.5)、`:177`(min.y 449.0 ≥ 449.0)、`:185`(全节点方块在画布内)、`:192/195`(双 Boss 描边、远处战斗 32 入雾);`ui_input_probe.gd:146-149`(常数锚引屏内常量)+⑬ | `canvas_probe()`/`layout_probe()`+真机探针 ⑬。⑬ 的 BFS 独立推导、常数同源 | 公式两侧独立推导(布局实测反解 maxl/maxslot,非用 `_fit_canvas` 自己的层表);M9 实测 2 条红(§3)。观察项:`layout_probe` 的 `maxl` 由 `_content_size` 居中后的坐标反解,若宽度公式少项,反解仍正确——正是 M9 能红的原因,无缺陷 | **通过** | -| **fv9 显隐接线(雾不扩可点域)** | `ui_input_probe.gd:76-91`(真机 `push_input` 点击雾下非候选节点,`route_chosen` 零发射,尾缀 :89) | 真机 push_input+真实 `_candidate_at` 命中面;判据绑 `route_chosen` 信号面(可观测提交面),未绑兜底终态 | M10 实测红,原文 `提交=[3] visible=true 选路态=true`(§3);这是本卡最强的一条 | **通过** | - -**§7.1 汇总**:fv1、fv3、fv4、fv5、fv6、fv7、fv8、fv9 通过(fv3 含 1 条观察项);**fv2 判缺漏**——不是「断言不存在」,而是卡片该行声明的「读绘制面/接线层验收」用当前 `display_probe()` 实现不成立,且实测接线坏不红。 - -## 3. 变异复现记录(自跑) - -四张 T 卡各复现一条(T1→M1、T2→M2、T3→M9、T4→M10),全部「注入→最窄闸见红→`git checkout --` 还原→复跑绿」,另加一条审计自设的接线坏注入 W1。**无复现不一致**:四条红的位置与报告 §5.4 所写逐字一致。 - -| # | T 卡 | 注入内容(精确位置) | 红断言原文(自跑) | 还原后读数 | -|---|---|---|---|---| -| **M1** | T1 | `game/core/level_runner.gd:433`:`absi(...) <= n` → `< n` | `[FAIL] 层距 N 内可见:锚层 1 取节点 4(层距 2)〔fv1〕`;`[FAIL] 单圈只按锚层取窗:已过近端节点 4(层距 2)仍可见〔fv7〕`;`[FAIL] 单链退化形态:入口锚层 0,下标 2 可见〔fv1〕`;`[FAIL] N 读表:N=3 时节点 5(层距 3)入窗〔fv6〕`;`4/26 项失败`,退出码 1 | `git status --short` 空;C1 复跑 `all green (26 checks)` 退出码 0 | -| **M2** | T2 | `game/presentation/views/level_map_screen.gd` `node_display`:`"draw_icon": type_shown` → `true` | `[FAIL] 雾下节点:图标与类型文字均不绘制(显隐语义,非灰化)〔fv2〕`;`[FAIL] Boss 豁免不扩散:雾下非 Boss 仍隐类型〔fv3〕`;`[FAIL] 大图呈现:入口停点远处战斗节点(编号 32,层 6)类型入雾〔fv8〕`;`3/19 项失败`,退出码 1 | `git status --short` 空;C2 复跑 `all green (19 checks)` 退出码 0 | -| **M9** | T3 | `level_map_screen.gd:_fit_canvas` 宽公式去 `+ NODE_HALF.x`(`LAYER_BASE_X + maxl*LAYER_STEP_X + 8.0`) | `[FAIL] 大图拟合:画布 min.x 覆盖最深节点(1298.0 ≥ 1334.5)〔fv8〕`;`[FAIL] 大图布局:全节点方块落在拟合画布内(origin=(0.0,0.0) size=(1298.0,449.0))〔fv8〕`;`2/19 项失败`,退出码 1 | `git status --short` 空;C2 复跑 `all green (19 checks)` 退出码 0 | -| **M10** | T4 | `level_map_screen.gd:_candidate_at`:`for nid in _cand_ids` 改为遍历全节点 id(先构 `_all_ids`) | `[ui_input_probe] FAIL — case⑱ 雾下节点点击产生提交(提交=[3] visible=true 选路态=true——雾不扩大可点域)〔fv9〕`,退出码 1 | `git status --short` 空;C4 复跑 `PASS` 退出码 0 | -| **W1**(审计自设,报告未列) | T2 接线层 | `_draw_graph` 两处条件 `if bool(disp["draw_icon"]):`/`if bool(disp["draw_label"]):` 均改 `if true:`(模拟「决策面正确、接线坏」) | **不红**:C2 `all green (19 checks)` 退出码 0;C4 `PASS` 退出码 0 | `git status --short` 空;C2 复跑 `all green (19 checks)` 退出码 0 | - -W1 的结论:本卡唯一「防止接线坏」的声明(§7.1 fv2 真实入口格)在端到端两层闸上都不成立——这正是卡片要求「真机 `display_probe()` 读绘制面」的动机,而 `display_probe()` 只是决策面的第二次求值。 - -## 4. 测试削弱检查结论 - -| 检查面 | 结论 | -|---|---| -| 删除既有断言 | **无**。`git diff 43c0f3c1..HEAD -- game/smoke game/tests` 的全部删除行只有 3 行,均为 `ui_input_probe.gd` 的画布常数锚注释+`need_x2` 手抄公式行,属卡片 §7.1「旧断言预声明」第①类允许项(改为引 `LevelMapScreen.LAYER_BASE_X/LAYER_STEP_X/NODE_HALF`,判据与断言语义未变)。其余冒烟/探针文件只增不删 | -| 放宽阈值 | **无**。冒烟新增 5 条全为新判据;⑬ 容差 `-0.5` 未动;⑱ 无「非空即过」类宽松判据 | -| 缩小扫描范围 | **无**。新两套件扫描全节点;大图夹具 63 节点全量比对 | -| 真实入口换下层直调 | **fv2 一项成立**(§2、§6 D1):`display_probe` 是决策面重算,不是绘制面读取。其余各行入口与卡片声明一致 | -| 注释掉断言 | **无** | -| 越出卡片声明的削弱 | **无**(除 fv2 的入口口径问题外) | - -观察项(非削弱,但影响判据强度,建议回炉 T2 时一并处理): -1. ⑱ 的「雾下图标不出示」判据自指:fog_id 按 `not disp[vnid]["draw_icon"]` 选出,再断言 `not draw_icon`,该半句恒真;有效的是「文字通道不出示」半句与「雾面节点存在」的存在性(M2 时因选不到 fog 节点而走 `case⑱ 雾面节点选取失败` 分支变红)。建议改为选区与断言解耦(如按层距/候选集独立选雾节点)。 -2. fv3 双 Boss 夹具的 `type_vis` 是手写 `[1,7,9]`,只证「决策面对两个 Boss 都亮」,未从 `type_visible_ids()` 推导「两端点均在集」;核心多 Boss 成员性由单 Boss 用例覆盖同一分支,风险低。 -3. C4 的 PASS 文案仍列到 ⑰ 为止(「十八断言」按 18 个 case 数),未点名 ⑱;报告 §5.2 称「探针⑱ 5 项断言」,实现实为 4 个 `_pre_fail` 判据+1 个选区前置。均为措辞/计数瑕疵,不影响判据有效性。 - -## 5. 报告 / 代拍板 / 反哺点相符性 - -### 5.1 实现报告 §5.3 六条偏差逐条核对 - -| 偏差 | 核对结果 | -|---|---| -| 1 大图夹具 12 BFS 层→布局 11 层(实测 maxl=10/maxslot=6) | **如实**(C2 打印「实测最大层 10/最大槽 6」;夹具源码 `tiers := 12`+跨层跳边) | -| 2 ⑱ 零提交判据改绑 `route_chosen` | **如实**(M10 红在信号面;旧终态判据被屏态/运行器兜底吸收的解释与 M10 输出 `visible=true 选路态=true` 一致)。属卡片 §8 L1 写法自救,已申报 | -| 3 类型闸 4 处 R1(`6f04f29b` 归零) | **如实**(旧 `static_scan.log` 逐行列 4 处 R1;C6/C7 现为 PASS) | -| 4 常数锚行号 `:98-99` → `:142-145` | **如实**(现文件 `:146-149` 为注释+公式;卡片原行号已 T0 订正) | -| 5 画布下限 620×256 vs 冻结文档 620×240 | **如实**(`level_map_screen.gd:303`=`Vector2(620, 256)`;`design/gdd/ux/level-map.md:68` 写 620×240;反哺点 ⑧ 已登记) | -| 6 命中面 `_candidate_at` 零改动 | **如实**(diff 该函数零 hunk;M10 是我注入才改) | - -**未申报的偏差 1 条**:§5.2 fv2 行写「真机 `display_probe()` 读绘制面」,实际 `display_probe()` 只是 `node_display` 快照重算,`_draw_graph` 接线零断言(W1 证明)。报告 §5.3 未列此偏差。 - -**报告 §5.7 与回执不符 1 条**:报告表 09 行写「1 → 0」,读作最终已绿;但 `receipt.json` 的 `commit=4ef154b9`、`09 exit=1`、`all_green=false`,且该回执早于 `6f04f29b`(修 09 的提交)与分支尖。报告末句「最终合并回执见本批合并提交信息(起跑 commit=分支尖)」是未来义务,不是已落证据;而 §5.1 已把 T4 标「完成」。**「批末代码域闸全绿」目前只有窄验证(audit_type_hints PASS+两套件+探针),没有分支尖的 `run_all_gates.sh --code` 回执。** - -(补充事实:C8 的 `changed_vs_baseline` 是「09 红项清单变化」。存量基线 `baseline.json` 里 09 本就是 exit=1 的存量红;本批先新增 4 处 R1 被判「清单变化」,修复后应转绿。所以问题不在代码现状,而在回执证据未随修复重生成。) - -### 5.2 代拍板六条(卡④)白名单核对 - -| # | 白名单条目 | 核对结果 | -|---|---|---| -| 1 | provisional N=2 | **合规**:`level.tres` 挂 2;`validate` 只校验 int≥1;代码零硬编码 N(`level_runner.gd:429` 读 `db.level.info_visible_layers`);C1 证明改表值窗随动 | -| 2 | API/探针命名 | **合规**:`info_visible_layers`/`type_visible_ids`/`node_display`/`display_probe` 均无 `fog_` 前缀。`level_map_info_fog_test.gd` 及 `_test_fog_hides_type` 属卡片 T2 指定的测试文件名/测试内私有函数,不是跨层 API | -| 3 | 雾下呈现落点 | **合规**:编号、方块、连线绘制零改动(生产 diff 删除行只有图标/文字块重排与条件切换,色值/线宽/形制零变);C5 冒烟 1211 项、C6 渲染相关静态面全绿 | -| 4 | 大图夹具规模 | **合规**:12 BFS 层压成 11 层×6 槽、含双 Boss、含跨层跳边(1→3 层目标),满足 ≥10×≥5 | -| 5 | 常数锚同源化 | **合规**:探针直接引 `LevelMapScreen` 导出常量,无手抄副本 | -| 6 | 提交切分/分支名 | **合规**:`iter34-fog`,三笔均在 `game/`;报告/产出物在 `reports/` | - -白名单外自决:**未发现**(W1 揭示的是验收口径缺失,不是实现自决)。 - -### 5.3 反哺点 ⑥–⑮ 对卡片 §5 的覆盖 - -| 卡片 §5 同步面/呈报项 | 反哺点 | 结论 | -|---|---|---| -| 关卡节点地图(N 状态行+可见性语义) | ⑥+⑩ | 覆盖 | -| 关卡节点图生成(屏预算行+下一跳兑现标注) | ⑦ | 覆盖 | -| level-map(画布公式漂移+Information Hierarchy+**雾的正式视觉规格呈报项**) | ⑧(含呈报项,明确「禁本批落文」) | 覆盖 | -| 术语表(信息迷雾 vs 视野迷雾) | ⑨ | 覆盖 | -| 待办清单 | ④+⑪ | 覆盖 | -| roadmap | ⑤+⑫ | 覆盖 | -| **超预算图升级路径(呈报项)** | ⑬ | 覆盖 | -| 实机目检三项登记 | ⑮(审计期新增提交 `6757c21e`) | 覆盖 | -| 方法论反哺 | ⑭ | 额外,合理 | - -### 5.4 契约与代码纪律 - -| 检查 | 结论 | -|---|---| -| 契约 1/2(三层语义、Boss/终点/候选豁免) | 未破:结构通道全绘;类型由 `type_vis` 决定;Boss 在核心与决策面双豁免;候选追加进核心集 | -| 契约 3(N 只进数据表) | 未破:唯一字面量 2 是 `level_table.gd:8` 的 schema 默认值(卡片 T1 明确要求),运行期经 `db.level` 读 | -| 契约 4(显隐、零新画法) | 未破:无灰化/雾纹理/新色值/线宽变化 | -| 契约 5(单圈零记忆) | 未破:实现不读 `visited`;C1 单圈组绿 | -| 契约 6(不动冻结件/禁缩放滚动) | 未破:`_fit_canvas` 公式零改动;下限 620×256 是改前既有值(卡片 §5.3-5) | -| 契约 7(呈现只读) | 未破:呈现层不重算层距,只消费 `type_visible_ids()`;`node_display` 的 Boss 判定属卡片 T2 指定的决策面语义 | -| 契约 8 / §8 L3 | 未破:无生成器/行进/敌人表/校验放宽改动;`type_visible_ids` 无状态;候选未被雾遮 | -| core 零 UI 依赖 | 通过:`level_runner.gd` 仅注释提及 `LevelMapScreen`,无 UI 类型引用 | -| 数值零字面量 / RNG | 通过:N 读表;新代码无 `randomize()`、无自建 RNG | -| 行尾/类型闸 | 通过:核心 `.gd` 无 CRLF;`audit_type_hints` PASS(C7) | -| 头注/变更记录禁令 | 通过:新增文件头只述职责;无版本历史节;`git diff --check` 仅 3 个报告文件「EOF 空行」提示,非代码问题 | - -## 6. 总判定:**不通过** - -代码现状的自跑读数全部为绿(C1–C7),未发现测试削弱、契约破坏、越权自决或数值/RNG 违规。但按卡片 §7.1 与 T4/T5 的验收口径,有 **2 条缺漏**必须回炉后重审: - -### D1(回炉 T2)fv2「接线层验收」未成立,且卡片 T2 与 §7.1 口径冲突 - -- **缺什么**:证明 `_draw_graph` 真的消费 `node_display` 输出的断言。当前 `display_probe()`(`level_map_screen.gd:536-547`)逐节点重新调用 `node_display`,与绘制路径是两次独立求值;测试与探针都只读这个快照。 -- **在哪**:`level_map_info_fog_test.gd:187-195`(大图 `display_probe`)、`ui_input_probe.gd:46-68`(⑱ 前四段);证据=W1 注入(`_draw_graph` 两处条件改 `if true`)后 C2 `19 checks` 全绿、C4 PASS。 -- **口径冲突**:卡片 T2 把 `display_probe()` 定义为「id → `node_display` 快照」,而 §7.1 fv2 要求它「读绘制面(接线层验收)」。实现按 T2 落地,§7.1 判据不可能由该接口兑现。这属 spec-AC 不一致,需用户裁:要么 T2 改接口/补一层「绘制输出可观测」的探针(例如自绘记录器:给 canvas 包一层记录 draw_rect/draw_texture_rect/draw_string 的测试桩,或离屏渲染取雾节点区域像素),要么由用户修改 §7.1 fv2 的验收口径(实现批不得自决)。无论走哪条,当前状态下 fv2 的撤销证明只覆盖决策函数,不覆盖接线。 -- **附带**:⑱ 的雾下图标判据自指(§4 观察项 1),回炉时一并解除自指。 - -### D2(回炉 T4/T5)批末代码域闸无分支尖绿回执 - -- **缺什么**:与分支尖同 commit 的 `tools/run_all_gates.sh --code` 全绿回执。 -- **在哪**:`game/tests/.gates/receipt.json`——`commit=4ef154b9`、`09 静态扫描 exit="1"`、`all_green=false`;`6f04f29b`(修 09)与 `477fd0f5` 之后未重跑。实现报告 §5.1 却把 T4 标「完成」、§5.7 表写「09 1 → 0」。报告 §5.6 自己也写明「合并前回执须与分支尖同 commit」。 -- **处置**:在分支尖重跑 `tools/run_all_gates.sh --code` 落新回执(`commit` 字段=分支尖、`all_green: true`),再交复审;不得用窄验证替代。我的 C1–C7 已证明重跑应能绿,但回执是合并闸的强制证据,不能由审计代跑(会覆写既有闸产物)。 - -### 非阻塞观察项(不单独构成缺漏,建议随 D1/D2 一并处理) - -1. ⑱ 雾下图标判据自指(§4-1)。 -2. fv3 双 Boss 夹具手写 `type_vis`,多终点核心成员性无独立推导(§4-2)。 -3. 探针 PASS 文案未列 ⑱,报告「5 项断言」与 4 个判据不符(§4-3)。 - -**合并前置**:D1、D2 关闭并复审通过前,本卡不得合并(卡片 T5、§7.1 末段)。 diff --git a/reports/iter34-卡④-验收审计-复审-2026-10-22.md b/reports/iter34-卡④-验收审计-复审-2026-10-22.md deleted file mode 100644 index b73a4e28..00000000 --- a/reports/iter34-卡④-验收审计-复审-2026-10-22.md +++ /dev/null @@ -1,75 +0,0 @@ -# 迭代 34 卡④(信息迷雾可见性批)独立验收审计·第二轮复审报告(2026-10-22) - -> 审计员:第二轮独立复审子代理,未参与实现、未参与第一轮审计。职责=复核甲案是否真关掉 D1、且无新问题。 -> 全程只读源码/测试/产出物+自跑最窄命令取证;除本报告外未写任何文件(注入变异均在跑完后 `git checkout --` 还原)。 -> 被审对象:`D:\code\g-plan2-iter34-fog`,分支 `iter34-fog`,被审 HEAD `de9cc102`(工作树开工/收尾 `git status --short` 均空)。 -> 被审改动:甲案两笔——`1970e0ef`(代码:`level_map_screen.gd`+`ui_input_probe.gd` 两文件)、`de9cc102`(账面:仅 `reports/` 三件)。审计起点=第一轮报告 `reports/iter34-卡④-验收审计-2026-10-22.md`(D1/D2 两条缺漏)。 -> 口径:不采信实现报告 §5/§六 的「已全绿/已闭合」自述,凡结论必附自跑读数或文件:行。 - -## 1. 自跑命令与读数原文 - -| # | 命令(工作目录=该工作树 `game/`) | 读数原文 | 退出码 | -|---|---|---|---| -| R1 | `…console.exe --headless --path . --script res://tests/unit/core/level_map_type_vis_test.gd` | `[level_map_type_vis_test] all green (26 checks)` | 0 | -| R2 | `…--script res://tests/unit/presentation/level_map_info_fog_test.gd` | `[level_map_info_fog_test] all green (19 checks)` | 0 | -| R3 | `…console.exe --headless --path . res://smoke/ui_input_probe.tscn` | `[ui_input_probe] PASS — …⑰未开格类型微光…⑱信息迷雾绘制接线(display_probe 读实际绘制记录)增)` | 0 | -| R4 | `…--script res://tests/run_all.gd` | `[run_all] unit/contract suite entry — 40 suites`;`[run_all] all green (40 suites)` | 0 | -| R5 | `PYTHONIOENCODING=utf-8 python tools/run_smoke.py` | `[run_smoke] 摘要: 冒烟完成:1211 项检查,0 项失败`;`[run_smoke] PASS(退出码 / 摘要失败数 / 脚本错误扫描 三闸全过)`;可见性断言逐条 `[PASS]`(含〔fv6〕N 读表=2、〔fv1〕层距 3/4 节点 7/8 入雾) | 0 | - -> 说明:R4/R5 只读验证单元/冒烟计数(run_all.gd 只写 `.gates/run_all_NN.log`,run_smoke.py 不写 `.gates`),**均未触碰 `receipt.json`**;未跑 `run_all_gates.sh`。R3 的 PASS 文案已点名 ⑱(第一轮观察项 3 已修)。 - -## 2. 四项逐条结论 - -### 项 1:D1 是否真关——**通过** - -- `display_probe()`(`level_map_screen.gd:546-547`)现只 `return _drawn_disp`,**不再自行调用 `node_display`**(全仓 `_drawn_disp` 仅 4 处:声明 :51、逐帧 clear :444、绘制点赋值 :517、返回 :547——无第二求值面)。 -- `_draw_graph` 在**实际绘制点**写记录:`boss_border`(:488,在描边画完之后)、`draw_icon`(:495,在 `if bool(disp["draw_icon"]):` 块内)、`draw_label`+`label_text`(:512-513,在 `if bool(disp["draw_label"]):` 块内),末 `_drawn_disp[nid] = rec`(:517)。记录随每帧 clear 重建(:444),只反映实际发生的绘制。 - -**W1 复现(第一轮判「不红」的那一发)**——把 :494/:511 两处 `if bool(disp["draw_icon"]|["draw_label"]):` 均改 `if true:`(`git diff` 净 2 行、无其它改动): - -- 呈现单元套件红:`ERROR: [FAIL] 大图呈现:入口停点远处战斗节点(编号 32,层 6)类型入雾〔fv8〕`(`level_map_info_fog_test.gd:195`)+`[level_map_info_fog_test] 1/19 项失败`,退出码 **1**。 -- 输入探针红:`[ui_input_probe] FAIL — case⑱ 雾下节点类型仍出示(图标=true 文字=true——范围外只见结构)〔fv2〕`,退出码 **1**。 -- `git checkout -- game/presentation/views/level_map_screen.gd` → `git status --short` 空 → 复跑 R2 `all green (19 checks)` 退出码 0。 - -**第一轮 W1=两入口全绿;本次两入口全红**——D1 关掉。**且两红原文与实现报告 §5.4 M11 行逐字一致**(§5.2 fv2 行「M11 绘制处绕开决策面 → 单元与探针双红(实测)」相符)。 - -**第二发新变异(验记录面不是摆设)**——绘制处条件保持原样(雾下节点实际不画图标),仅在 `_drawn_disp[nid] = rec` 前插一行无条件 `rec["draw_icon"] = true`(记录谎称画了图标、实际没画): - -- 呈现单元红:同〔fv8〕:195 一条,退出码 1;探针红:`case⑱ 雾下节点类型仍出示(图标=true 文字=false——范围外只见结构)〔fv2〕`(文字通道未被污染故=false,证断言确实逐值读记录),退出码 1。 -- 还原后 R2 `all green (19 checks)`。→ 记录的值是承重的(非仅存在性检查),断言确实消费绘制记录内容。 - -### 项 2:⑱ 自指是否解除——**通过** - -`ui_input_probe.gd` case⑱(:44-73)现况: - -- 选区=`fog_id`:`vnid != cur_id and not cands.has(vnid) and not vis.has(vnid)`(:56)——只读核心面 `vis = runner.type_visible_ids()`(:47)、`cur_id`(:48)、`cands`(:43),**不读 `disp`**(源码注释 :57 亦写明「选区只按核心可见集判,不读绘制记录」)。 -- 断言=`if bool(disp[fog_id]["draw_icon"]) or bool(disp[fog_id]["draw_label"])`(:64)——读呈现绘制记录。 -- Boss 选区按 `type=="boss"` 读节点数据(:54)、候选选区按 `cands[0]`(核心),断言分别读 `disp[boss_id]["boss_border"]`(:68)与 `disp[cands[0]]["draw_icon"]`(:71)。 - -选区全部来自核心/节点数据面,断言全部来自呈现绘制记录面——**两个不同面**,非第一轮「按 `not disp[...]["draw_icon"]` 选、再断言其 `not draw_icon`」的恒真自指。W1 变异能红即实证该断言不再恒真。→ 自指解除。 - -### 项 3:有无新削弱或新越权——**通过** - -- **删断言/放宽阈值/缩小扫描面/真实入口降级**:`git diff 43c0f3c1..HEAD -- game/` 的删除非注释行仅两类——① `level_map_screen.gd` 原「无条件绘制图标/字形/类型文字」块(改为经 `node_display` 决策面消费+写记录,属卡片 T2 本体,非删断言);② `ui_input_probe.gd` 旧手抄公式 `need_x2 = 70.0 + maxl2*122.0 + 26.0 + 8.0` 与旧 PASS 文案行。**无一条断言被删**。旧 `26.0`→新 `LevelMapScreen.NODE_HALF.x`(36.5,:153-154),阈值抬高 10.5px=**变严**(第一轮 F11 记探针低报仍绿,本次同源化后更紧),容差 `-0.5` 未动(:156)。真实入口 fv2 由「决策面快照」升为「绘制记录」=变强不变弱。 -- **`_drawn_disp` 是否只读观测面**:全仓仅 `level_map_screen.gd` 内 4 处引用(见项 1),**无新 `draw_rect/draw_texture_rect/draw_string`**、无色值/线宽/缩放滚动改动、不写存档、不引入持久状态语义;`clear`+记录赋值=纯只读观测面(仿 `canvas_probe`/`layout_probe` 先例)。甲案两文件之外零触达 core/data/smoke_all。 -- **早期返回空记录会否致平凡通过**:`_draw_graph` 早返回(`_runner == null or not visible`,:442)时记录不清空不重建。已核**无平凡通过面**——① 呈现单元 :192 先断言 `disp.has(boss_ids[0]) and disp.has(boss_ids[1])`,空记录即判红(且 :195 对缺失键 `disp[32]` 取 null 会报错、同样不放过),当前 19 项全绿反证记录已填充;② 探针 :59 前置判据 `not disp.has(fog_id) or not disp.has(boss_id) or not disp.has(int(cands[0]))` → `_pre_fail`(甲案新增),空记录走「记录缺位」红分支。两入口都对空记录设了拦截。 -- **代拍板第 7 行相符性**:卡片 §9 六条白名单(:216-221)无一条覆盖「把 `display_probe` 从 `node_display` 快照改为绘制记录观测面」这一接线层验收手段,属白名单外;代拍板第 7 行(`iter34-代拍板-2026-10-22.md:32`)如实备案「呈报甲/乙/丙三案并推荐甲,按甲落地:`_draw_graph` 绘制点记录本帧事实、`display_probe()` 改读该记录」,约束核验「改动集中 `1970e0ef` 一笔可回退、未触冻结视觉件、新增面为只读成员与记录赋值」——与代码实际做法、与本复审实测逐项一致。非静默越权。 - -### 项 4:D2 与账面相符——**通过** - -- `receipt.json`:`commit = de9cc102`=HEAD(分支尖)✓;`all_green = true` ✓;`changed_vs_baseline = []` ✓;闸项 01/02/03/04/05/09/10 全 `exit 0 / green`(09 静态扫描由「基线红→现绿·改善」,见 `inherited_red`);11 对拍按档位规则 NEED-APPROVAL(数值零变更,不发起,合规)。 -- 计数由自跑独立佐证:02 单元 **40 套件**(R4 `all green (40 suites)`)、01 冒烟 **1211 项 0 失败**(R5 摘要原文)——与回执 01/02 的 `exit 0` 相互印证。 -- 实现报告:§5.1 提交列表含 `1970e0ef`(:159「审计 D1 回炉 T2」)✓;§5.2 fv2 行与 §5.4 M11 行的红断言原文与项 1 实测逐字对得上 ✓;反哺点 ⑯(:100-104)写清「卡片 T2 :139 接口描述=`id → node_display 快照`滞后,与 §7.1 fv2『读绘制面』矛盾,须由**写卡段订正**、实现期不改卡片」✓。 - -## 3. 第一轮两条缺漏的闭合判定 - -- **D1(fv2 接线层验收未成立/⑱ 自指)=已闭合**。`display_probe()` 改读 `_draw_graph` 实际绘制记录、不再二次求值;第一轮判「不红」的 W1 注入(两处绘制条件 `→ if true`)本次在**呈现单元〔fv8〕与输入探针〔fv2〕两入口同时判红**,红原文与 M11 记录一致;⑱ 选区改按核心可见集/候选集/当前位独立选点、断言读绘制记录,自指解除;新变异(污染记录值)两入口亦红,证明记录值承重。 -- **D2(缺分支尖代码域全绿回执)=已闭合**。回执 `commit=de9cc102`=HEAD、`all_green=true`、`changed_vs_baseline=[]`,01/02/09 全绿,计数经自跑(1211 项 / 40 套件)独立印证。 - -## 4. 总判定:**通过(可合并)** - -甲案真关掉了 D1(W1 变异从「不红」变「双入口红」,实证接线层断言生效、记录非摆设、自指解除),D2 有分支尖全绿回执且与自跑读数相符。改动为只读观测面、零新画法/色值/线宽/缩放滚动/存档、无测试削弱、无静默越权(白名单外手段已备案并可整笔回退)。第一轮三条非阻塞观察项中,⑱ 自指(观察项 1)与 PASS 文案/计数(观察项 3)已随甲案修除;观察项 2(fv3 双 Boss 夹具手写 `type_vis`)按卡片 T2 指定写法保留、核心多 Boss 成员性由 `level_map_type_vis_test`〔fv3〕覆盖,维持非阻塞。 - -**唯一遗留(账面措辞,非阻塞、不构成缺漏)**:实现报告 §六 D2 行与 §5.7 行文字仍引用旧复跑 commit `8b9c6989`(甲案代码前的那次分支尖),而当前权威回执为 `de9cc102`;权威闸证据(`receipt.json`)本身正确、与 HEAD 一致、`all_green=true`,仅账面引用未随甲案后重跑刷新。合并前若再跑一次回执则会自然对齐;不影响 D2 闭合判定。 - -结论:卡④ D1/D2 两条缺漏均已闭合,无新削弱、无新越权,**通过,可合回 master**。 diff --git a/reports/iter34-反哺点-2026-10-22.md b/reports/iter34-反哺点-2026-10-22.md deleted file mode 100644 index c20caf38..00000000 --- a/reports/iter34-反哺点-2026-10-22.md +++ /dev/null @@ -1,104 +0,0 @@ -# 迭代 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 步账面随批);实现批不写该文件,换代归批后收尾或用户发令。 - -## ⑥ 关卡节点地图.md:调参表 N 状态行与可见性语义注记 - -- 文件与位置:`design/gdd/systems/冒险循环/关卡节点地图.md` :172(调参表「信息迷雾可见层数」行)、:100(可见范围「邻近 N 层」节) -- 改成:调参表状态由「定值批落数据表」改为「已落数据表 provisional 2(`level.tres` `info_visible_layers`)」;:100 节补实现语义三句——层距=入口 BFS 层差、Boss/终点与当前候选双豁免、单圈零记忆(已过节点回雾)。 -- 依据:卡④ T1 已实现并在 `level_runner.type_visible_ids()` 钉死;`level_map_type_vis_test` 五组断言〔fv1〕〔fv3〕〔fv4〕〔fv7〕覆盖。 - -## ⑦ 关卡节点图生成.md:屏预算约束行与「下一跳必在可见范围」兑现标注 - -- 文件与位置:`design/gdd/systems/冒险循环/关卡节点图生成.md` :105–114(调参表)、:83(「下一跳必在可见范围」) -- 改成:调参表补一行「图包络 ≤ 屏预算(1280×800 下约 10 层×8 槽;超预算只许限参数档,禁改画布冻结公式)」;:83 该句标注「实现侧已兑现:候选集强制豁免类型可见性」。 -- 依据:卡④契约 6 与 G6 定值(参数限图);`type_visible_ids()` 候选豁免断言〔fv4〕。 - -## ⑧ level-map.md:画布公式漂移订正+类型可见性层级行 - -- 文件与位置:`design/gdd/ux/level-map.md` :68(节点图区「冻结公式」句) -- 改成:宽 70+层深×122+34 → 70+层深×122+44.5(`NODE_HALF.x`36.5+8);高 52+槽位×58+26+8 → 52+槽位×58+25+24(`NODE_HALF.y`25+标签行 24);下限 620×240 → 620×256(抬高容纳标签行)。Information Hierarchy 节补「类型可见性(邻近 N 层显隐)」层级行。 -- 依据:`level_map_screen.gd:289–304` 现行 `_fit_canvas` 公式与大图拟合断言〔fv8〕;下限定值 256 是当前代码与渲染闸全绿的实际约束。**注意**:本条只订正文档记数,不动冻结件本身(画布公式语义与像素档位不变),是否接受改写由用户裁。 -- **呈报项(禁本批落文)**:「雾的正式视觉规格」(雾纹理/灰化遮罩/明度层)属冻结件域,本卡只做显隐语义最小呈现,视觉规格待用户裁后另立。 - -## ⑨ 术语表.md:登记「信息迷雾」并区别于「视野迷雾」 - -- 文件与位置:`design/gdd/术语表.md` -- 改成:新增词条「信息迷雾」=关卡节点图上按邻近层数隐藏节点类型的信息可见性;与「视野迷雾」(战斗棋盘按英雄曼哈顿半径遮挡)并列,注明两系统同词根易混、代码标识符禁 `fog_` 前缀。 -- 依据:卡④契约与风险 3;实现侧 API 全用 `info_visible_layers`/`type_visible_ids`/`node_display`/`display_probe`。 - -## ⑩ 关卡节点地图.md:Boss 描边口径冲突择一 - -- 文件与位置:`design/gdd/systems/冒险循环/关卡节点地图.md` :67 -- 改成:Boss 描边口径「封印黑 #000000」与 `level-map.md`/现役代码「紫赤+深墨环」不一致,请文档批核对后择一(现役实现与视觉终稿样张 v1 为紫赤+深墨环)。 -- 依据:卡④ G8 定值(实现随现役代码+level-map.md);本批未动描边视觉。 - -## ⑪ 待办清单.md:卡④条目状态按停卡实况回写 - -- 文件与位置:`待办清单.md` 中卡④登记条目 -- 改成:**不得记为「已实现」**——实现与代码域全量闸已完成(回执 `commit=6f547c35`、`all_green=true`),但独立验收审计判不通过、缺漏 D1(fv2 接线层验收与卡片 T2 对 `display_probe` 的定义互相矛盾)待用户裁决,卡④ 停在审计门。状态写「实现完成·审计不通过待裁(迭代 34)」,缺口记:「`display_probe` 只做决策面二次求值,`_draw_graph` 接线零断言;审计注入接线坏不红」;并写明实现报告路径。裁决后按用户选择推进(改验收接口 → 回炉 T2;改卡片 §7.1 口径 → 改卡后重交审计)。 -- 依据:`reports/iter34-卡④-验收审计-2026-10-22.md` §6 D1;五段流水线状态机(`doc-conventions` §12);实现批不写该文件,回写归批后收尾或用户发令。 - -## ⑫ roadmap.md:迭代 34 行状态刷新(卡③已完成、卡④停审计门) - -- 文件与位置:`roadmap.md` 迭代 34 行与顶部「当前位」节 -- 改成:卡③(敌人表深度带换代批)记为已实现并已合回;卡④(信息迷雾可见性批)记为「实现完成·独立验收审计不通过待裁」,迭代 34 不得标记完成;「当前位」按此实况改写。 -- 依据:迭代实现批收尾义务;实现批不写该文件,换代归批后收尾或用户发令。 - -## ⑬ 呈报项:超预算图策略升级路径 - -- 位置:无文档落点(用户在会话中裁) -- 内容:若后续定值批需要大于「约 10 层×8 槽」的完整可见图,两条路都动冻结件——等比缩放(动「20px 烘焙 1:1」「2/3/4px 折线」)或滚动视口(新交互范式)。本卡按 G6 走参数限图,两案均需用户裁。 -- 依据:卡④风险 2 与 G6 淘汰案。 - -## ⑭ test-conventions.md:验收断言应绑可观测提交面(方法论反哺) - -- 文件与位置:`design/engineering/test-conventions.md` §9.4(撤销/变异证明) -- 改成:补一句判据——端到端断言的判据应绑「被测改动特有的可观测提交面」(信号发射、事件、入参),不绑多层防御下的终态;否则单点变异可能被下游兜底吸收、终态不变而假绿。示例:探针「雾不扩可点域」首版只看屏/选路态终态,命中面放宽的变异仍绿;改绑 `route_chosen` 发射面后变异即红。 -- 依据:卡④ T4 实测(`提交=[3] visible=true 选路态=true`;终态与未点击一致)。 - -## ⑮ 体验验证清单.md:登记卡④三条实机目检项 - -- 文件与位置:`体验验证清单.md` -- 改成:登记三条待真人目检项(只登记、不阻塞)——①雾下可读性观感(未知类型节点是否一眼可辨为「未知」而非空节点);②多终点图 Boss 标记观感(双 Boss 是否都带描边且可辨);③大图完整可见观感(11 层×6 槽图是否完整落在屏内、编号不重叠)。判据与观测点见 `reports/iter34-实现报告-2026-10-22.md` §5.5。 -- 依据:卡④ T5「实机目检总清单三条」+iter 技能第 5 步账面随批;实现批禁写该清单,登记归文档批或用户发令。 - -## ⑯ 需求卡片:T2 的 `display_probe` 接口描述与 §7.1 fv2 口径一致化 - -- 文件与位置:`reports/需求卡片-信息迷雾可见性批-2026-10-21.md` :139(T2 第三条) -- 改成:「新增 `func display_probe() -> Dictionary`(id → `node_display` 快照,只读断言面,仿 `canvas_probe` 先例)」→「(id → 本帧实际绘制事实:图标/文字/描边/文案,由 `_draw_graph` 在实际绘制点写入,只读断言面)」,与 §7.1 fv2 真实入口格「真机 `display_probe()` 读绘制面(接线层验收)」对齐。 -- 依据:迭代 34 卡④ 独立验收审计 D1(`reports/iter34-卡④-验收审计-2026-10-22.md` §6);实现按 §7.1 验收面(甲案)落地,卡片 T2 的接口描述是滞后一侧,须由写卡段订正——实现期不改卡片。 diff --git a/reports/iter34-实现报告-2026-10-22.md b/reports/iter34-实现报告-2026-10-22.md deleted file mode 100644 index 36811584..00000000 --- a/reports/iter34-实现报告-2026-10-22.md +++ /dev/null @@ -1,278 +0,0 @@ -# 迭代 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` | 单元 | level 1 合成单关夹具(`display_name:"夹具关"`);现役三关零误报由 fv6 兜住 | 回退 ④ 敌侧换代 → 红 | -| fv18 | 混编行序 | `smoke_all.gd:4815` | 集成 | 冒烟读 (2,battle,5) 行集 | 变异对调两行 → 红(实测) | -| fv19 | 混编骰和 ≤ 4 | `smoke_all.gd:4820` | 集成 | 同行集静态求和 | 改运行期守卫 `ROWSET_INSTANCE_MAX` → 同段守卫断言(「两行各定值 3(总 6>4)spawn 被拒」)红;静态求和本身放宽不会红 | -| 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 | V7 S 清单 17 行逐条换代(尾缀=清单件核;随带定点断言 = Boss 行集与毒吐投放面 + S15 叙述寻址) | `smoke_all.gd:4281`、:4291、:4807、:4865;`battle_narrator_test.gd:81`、:82 | 集成+单元 | 扫表定位+Boss 行集;`boss_name(runner, db)` 经 `resolve_enemy_rowset(..., "boss")` | 变异 `boss_name` 行类 "boss"→"battle" → `battle_narrator_test` fv24 红(实测);逐条勾销见 §2.2.1 | -| fv25 | hobgoblin 缺口登记随行 | `smoke_all.gd:2116` | 接口 | 表文件注释在位 | 同 fv12 | -| fv26 | V9 反哺点五落点(非行为改动) | `reports/iter34-反哺点-2026-10-22.md` ①–⑤ | 件核 | 反哺点文件与卡片 §6 同步面表逐条比对 | 删任一落点 → 件核红(文档产出物,无代码断言) | - -覆盖说明:`game/` 全域共 37 行带 fv 尾缀(36 条断言,另 `smoke_all.gd:969` 一行是注释),覆盖 fv1–fv26;fv14(值列零变更)与 fv26(反哺点落点)按卡片约定走件核,代码侧无断言;fv9 与 fv20、fv12 与 fv25 各自共用同一断言行,计数时不重复。 - -#### 2.2.1 V7:S 清单 17 行逐条勾销(卡片位置 → 现工作树位置) - -| S | 现工作树位置 | 换代内容 | 勾销凭据 | -|---|---|---|---| -| S1 | `smoke_all.gd:3168`/:3491/:4499 | 三参化(row_kind="battle")+带语义注释 | 三处均显式传 "battle",行集首行读数随带键 | -| S2 | `smoke_all.gd:4795`(断言 :4801〔fv22〕) | 首遇带数据驱动定位+恰一行/unit_count=2/无 unit_count_max | 〔fv22〕实测绿;变异加 unit_count_max → 红(§2.3 第 5 项) | -| S3 | `smoke_all.gd:4802`(断言 :4807〔fv24〕) | L2 Boss 行集改 `_boss_depth(2)`+"boss" | 〔fv24〕实测绿 | -| S4 | `smoke_all.gd:4810`(断言 :4815〔fv18〕、:4820〔fv19〕) | 键改 (2,battle,5),行序契约保持 | 〔fv18〕变异对调 → 红(§2.3 第 6 项) | -| S5 | `smoke_all.gd:4852`/:4860(断言 :4859〔fv23〕、:4865〔fv24〕) | 首遇带定位+Boss 三参化 | 两条断言实测绿 | -| S6 | `smoke_all.gd:974-984`/:4781-4789/:5256-5258 | en_keys 改 (L,row_kind,depth_band),Boss 节点查 boss 键域 | 三处键串 `"%d_%s_%d"`;L2/L3 跨表行完整断言绿 | -| S7 | `smoke_all.gd:2263`/:2279/:2301 | Boss AC 台阶保留;(1,2) 锚定改 bugbear 首遇带定位〔fv21〕;曲线改按 (1,battle) 带键相邻比 ≤ 2.5 | 三条断言实测绿;fv21 变异见 §2.3 第 8 项 | -| S8 | `smoke_all.gd:4262-4306` | 毒吐投放面改 `depth_band > 巨蜘蛛首遇带`+池键含 row_kind | 〔fv24〕:4281/:4291 实测绿;键串 `2_battle_5_giant_spider` 等 | -| S9 | `smoke_all.gd:3460-3474`(断言 :3473〔fv23〕) | (1,2) 改 bugbear 首遇带定位(固定 1 不加骰) | 〔fv23〕实测绿;数据侧变异下 fv23 红(§2.3 第 8 项) | -| S10a | `smoke_all.gd:2024`/:2674/:2699/:3078/:3143/:3230/:3284/:3324/:3354/:3566/:3633/:3651/:3668/:4139/:4359/:4606/:4970/:5040;`damage_probe.gd:95` | 各补 `"node_type": "boss"` | 上述直呼点均带 node_type;冒烟 1161 项 0 失败 | -| S10b | `smoke_all.gd:2674`/:2699 | 改 (2,9)+boss | 两处均为 `"node_depth": 9, "node_type": "boss"` | -| S11 | `tests/unit/core/config_db_resolver_test.gd`(fv1–fv5) | 换代为带寻址语义断言 | fv1–fv5 实测绿;floor 变异红(§2.3 第 1 项) | -| S12 | `tests/unit/data_config/config_db_test.gd`(fv6–fv10) | 夹具键改 row_kind/depth_band,签名三参化 | fv6–fv10 实测绿;枚举判据变异红(§2.3 第 2 项) | -| S13 | `tests/unit/core/config_db_cross_validator_test.gd`(fv15–fv17) | 夹具键改名+补两条负向用例 | fv15/fv16 变异红(§2.3 第 3、4 项) | -| S14 | `smoke/skill_rhythm_probe.gd:17`;`smoke/damage_probe.gd:269`/:422 | 三参化 | 三处显式传 row_kind | -| S15 | `game/presentation/battle_narrator.gd:76`;验收 `tests/unit/presentation/battle_narrator_test.gd:81`/:82〔fv24〕 | 三参化(row_kind="boss")+补真实入口单测 | 实测绿;变异 "boss"→"battle" → fv24 红(§2.3 第 9 项) | -| S16 | `smoke_all.gd:3491`(断言 :3496) | erow2 首行读数随带键(三参化) | 全深度×12 种子 60 场断言实测绿 | - -勾销口径:S11–S13 归单测面,S1–S10、S14–S16 归冒烟/探针面,S15 归消费面;17 行全部给出工作树位置与凭据,无一行停在旧坐标语义。 - -### 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)) | 冒烟全量 | 首次注入在加载期即被跨表校验拦下:`ERROR: [ConfigDB/level_node_dangling] level 1 battle 节点深度 3 高于 (level 1, battle) 顶带键 2——顶 clamp 消解`,随后〔fv6〕红(config_db_test 2/2 项止步);「同带相邻」判据未触发——该行紧接 bugbear 带 2 行之后、文件内相邻。二次注入改为与 band 2 行互换带键(表可加载),命中「hobgoblin 行在 (1,battle,3)」〔fv12〕〔fv25〕与 20 行键序〔fv11〕 | 还原带键,冒烟复跑全绿 | -| 8 | 数据侧:L1 bugbear 行 `depth_band` 2→1(V6① 撤销证明换代) | 冒烟全量 | 单跑数据变异时〔fv21〕仍绿(首遇带随之变 1、锚定行随迁——数据驱动的正证),连带〔fv11〕〔fv23〕与 spawn 扫描等共 6 项红;叠加「`_first_encounter_band` 写死返回 2」后〔fv21〕红(期望带 2 找不到 bugbear 行),共 9 项红 | 两处均 `git checkout --` 还原,冒烟 1161 项 0 失败 | -| 9 | `battle_narrator.boss_name` 行类 "boss"→"battle"(S15 撤销证明) | `battle_narrator_test.gd` | 「Boss 名取自 Boss 行集首行(期望「食人魔酋长」实际「大地精」)〔fv24〕」红,退出码 1 | 改回 "boss",13 项检查全绿 | - -拦截边界如实记录:第 7 项按卡片写法直接把 hobgoblin 放到带 2 时,首条红是跨表 `level_node_dangling`(战斗节点深度 3 落到不存在的顶带),不是同带相邻规则——该行紧接 bugbear 带 2 行之后、文件内相邻,隔断判据不触发;键位断言的敏感度改用「与带 2 行互换带键」的表内合法变异单独观测。第 8 项单跑数据变异时〔fv21〕仍绿,说明该断言跟的是数据而不是写死值;只有「数据已变、坐标仍写死」的组合才让〔fv21〕红,这是它能区分两种实现的边界。另:第 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`(由未参与实现的子代理执行;只读卡片、本报告、diff、测试与闸回执,自跑最窄命令复现,不采信「已全绿」)。 - -**第一轮结论:不通过**——缺漏 4 条+描述不符 4 条(逐行依据见该报告第一至四节)。处置如下: - -| 缺漏 | 处置 | 落点 | -|---|---|---| -| V7 无覆盖行、fv24 尾缀挂错需求点 | 补 V7 覆盖行+S 清单 17 行逐条勾销表 | 本报告 §2.2 fv24 行、§2.2.1 | -| V9/fv26 覆盖行缺失 | 补件核行(反哺点文件 ①–⑤) | 本报告 §2.2 fv26 行 | -| S15 `boss_name` 换代无断言 | 补真实入口单测(扫表取 Boss 带键 → 断言叙述名=boss 行集首行名),并做撤销证明 | `game/tests/unit/presentation/battle_narrator_test.gd:56-82`〔fv24〕;§2.3 第 9 项 | -| V6①/fv21 撤销证明按记录无法变红 | 改为数据侧变异:bugbear 带 2→1(fv21 仍绿=数据驱动正证)+叠加写死坐标(fv21 红) | §2.3 第 8 项 | - -描述不符 4 条已按审计建议改写:fv17 夹具措辞(level 1 合成单关,非现役三关,现役三关由 fv6 兜住)、fv19 撤销归属(运行期守卫断言,静态求和本身不红)、§2.3 第 7 项拦截首红(跨表 `level_node_dangling`)、断言计数(36 条断言+1 行注释)。 - -**第二轮复审结论:通过**(`reports/iter34-验收审计-复审-2026-10-22.md`,被审 HEAD `68009b4e`)——A–F 六项全通过:V7 覆盖行与 17 行勾销表齐备(抽 6 行实读属实)、fv26 件核行在位、S15 单测走真实入口且变异红、V6① 数据侧撤销证明复现一致、四条描述不符已按实改写、修补未引入未申报的测试削弱。卡③ 合并前置满足。 - -## 四、全量代码闸读数 - -`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` 等)在清场前即为绿,佐证为环境并发而非行为回归。 - -## 五、卡④ 信息迷雾可见性批 - -### 5.1 工作树与任务卡状态 - -工作树 `D:\code\g-plan2-iter34-fog`,分支 `iter34-fog`,起自卡③合并后的 master `43c0f3c1`。提交:`ed8e0f9f`(T1–T3 实现与单测/冒烟/探针)、`4ef154b9`(⑱ 零提交判据改绑信号面)、`6f04f29b`(类型闸归零+探针补雾下文字通道断言)、`1970e0ef`(审计 D1 回炉 T2:绘制记录观测面+⑱ 选区解耦)。 - -| T 卡 | 内容 | 状态 | -|---|---|---| -| T0 | 事实坐实与基线读数 | 完成(改前基线:冒烟 1206 项 0 失败/单元套件全绿/探针全绿) | -| T1 | N 落表+越域校验+`type_visible_ids()`+核心套件 | 完成(提交 `ed8e0f9f`) | -| T2 | `node_display` 决策面+`display_probe`+`_draw_graph` 接线+呈现套件 | 完成(提交 `ed8e0f9f`,类型闸修补 `6f04f29b`) | -| T3 | 探针常数锚同源化+大图夹具(11 层×6 槽) | 完成(提交 `ed8e0f9f`) | -| T4 | 冒烟断言+探针⑱+变异汇总+代码域全量闸 | 完成(见 §5.4、§5.7) | -| T5 | 三份产出物+独立验收审计+合并 | 审计两轮完成(首轮不通过→甲案回炉→复审通过),合并进行中 | - -### 5.2 实际改动—验收对照表 - -生产侧落点:`game/core/level_runner.gd`(`type_visible_ids()` :422–440、`_bfs_layers()` :443–462);`game/presentation/views/level_map_screen.gd`(`node_display()` :420–437、`_draw_graph` 消费 :478、`display_probe()` :536–547);`game/data/schemas/level_table.gd:8`(字段)、:23–24(越域校验);`game/data/tables/level.tres:7`(`info_visible_layers = 2`);`game/smoke/ui_input_probe.gd:142–145`(常数锚同源化)、:44–90(case⑱);`game/smoke/smoke_all.gd:4938–4943`(真图可见性断言组)。 - -| fv | 需求点(简) | 验收断言(文件:行) | 层级 | 真实入口 | 撤销/变异结果 | -|---|---|---|---|---|---| -| fv1 | 邻近 N 层见类型 | `level_map_type_vis_test.gd:121`、:122、:123(层距边界);:142、:143(入口锚层 0);:166、:167、:168(单链退化);`smoke_all.gd:4942`(真图) | 单元+集成 | `LevelRunner.type_visible_ids()` 直调;冒烟真图读面 | M1 `<=N`→`= 10`),规模不变、语义不变。 -2. **⑱ 零提交判据改绑信号面**:按卡片原写法(命中面放宽到全节点 → ⑱ 红)首轮实测仍绿——点击确实穿透并提交,但雾下非战斗节点让本屏保持激活、运行器候选校验又把非法编号拒掉,终态与未点击时相同。改绑 `route_chosen` 发射面后单点变异即红(`提交=[3]`)。属卡片 §8 L1「断言写法」自救范围;同时给⑱ 各断言补 fv2/fv3/fv4/fv9 尾缀。 -3. **类型闸新增红**:T4 首轮全量闸暴露新增 4 处 R1(`Dictionary` 未参数化 1 处、`Array` 未参数化 3 处),已参数化归零(`6f04f29b`);修复后 09 转绿(相对基线为改善)。 -4. **常数锚行号**:卡片写 `ui_input_probe.gd:98-99`,工作树实落点 :142–145(T0 复核行号),同源化方式=直接引 `LevelMapScreen` 导出常量,未新增副本。 -5. **画布下限漂移**:`_fit_canvas` 现行为 `max(Vector2(620, 256))`,`level-map.md:68` 冻结公式写「下限 620×240」——本卡不动冻结件,登记反哺点。 -6. **命中面零改动**:`_candidate_at`(:373–386)卡内要求零改动,实现保持候选集循环,fv9 的变异证明正落在此函数。 - -### 5.4 变异验证记录表(注入 → 最窄闸见红 → 还原) - -| # | 注入内容 | 最窄闸 | 红断言(原文摘要) | 还原确认 | -|---|---|---|---|---| -| M1 | `type_visible_ids` 层距判定 `<= n` 改 `< n` | `level_map_type_vis_test` | 层距 N 内可见:锚层 1 取节点 4(层距 2)〔fv1〕;单链退化形态:入口锚层 0,下标 2 可见〔fv1〕(连带 fv6/fv7 各 1 条) | `git checkout` 还原,26 项全绿 | -| M2 | `node_display` 的 `draw_icon` 强制 true | `level_map_info_fog_test` | 雾下节点:图标与类型文字均不绘制〔fv2〕;Boss 豁免不扩散〔fv3〕;大图远处节点入雾〔fv8〕 | 还原,19 项全绿 | -| M3 | 删 `type_visible_ids` 的 Boss 豁免分支 | `level_map_type_vis_test` | Boss 恒显:层距 6 的末位 Boss 仍在可见集〔fv3〕;单链编号空间=数组下标〔fv1〕 | 还原,26 项全绿 | -| M4 | 删 `node_display` 的 Boss 豁免(`type_shown` 只看可见集) | `level_map_info_fog_test` | Boss 豁免独立于可见集:不在 type_vis 的 Boss 仍出示类型〔fv3〕 | 还原,19 项全绿 | -| M5 | 删 `type_visible_ids` 候选豁免追加段 | `level_map_type_vis_test` | 候选恒显:跨层跳边候选(层距 N+1)仍在可见集〔fv4〕 | 还原,26 项全绿 | -| M6 | `label_text` 拼接 `node.get("enemy_id")` | `level_map_info_fog_test` | 决策面不消费内容键〔fv5〕;label_text 不含内容值(实际「战斗goblin_secret · 可选」)〔fv5〕 | 还原,19 项全绿 | -| M7a | 删 `LevelTable.validate` 越域判据(`if false`) | `level_map_type_vis_test` | N 越域 0/-1:validate 判 domain 错〔fv6〕 | 还原,26 项全绿 | -| M7b | `type_visible_ids` 的 N 硬编码 2(不读表) | `level_map_type_vis_test` | N 读表:N=1 时节点 4 出窗〔fv6〕;N=3 时节点 5 入窗〔fv6〕;N≥层高全可见〔fv6〕 | 还原,26 项全绿 | -| M8 | 可见集加 `visited_ids().has(nid)`(累积可见) | `level_map_type_vis_test` | 单圈回雾:已过远端节点 0(层距 5)不因 visited 豁免〔fv7〕;中距节点 2 不可见〔fv7〕 | 还原,26 项全绿 | -| M9 | `_fit_canvas` 宽公式去 `NODE_HALF.x` 项 | `level_map_info_fog_test` | 大图拟合:画布 min.x 覆盖最深节点(1298.0 ≥ 1334.5)〔fv8〕;全节点落在画布内〔fv8〕 | 还原,19 项全绿 | -| M10 | `_candidate_at` 命中面放宽到全节点 | `ui_input_probe`(⑱) | 雾下节点点击产生提交(提交=[3] visible=true 选路态=true)〔fv9〕 | `git checkout` 还原,探针 PASS | -| M11 | `_draw_graph` 图标/文字两处条件改 `if true`(绕开决策面=接线坏) | `level_map_info_fog_test`+`ui_input_probe`(⑱) | 大图呈现:入口停点远处战斗节点(编号 32,层 6)类型入雾〔fv8〕;case⑱ 雾下节点类型仍出示(图标=true 文字=true——范围外只见结构)〔fv2〕 | `git checkout` 还原,19 项全绿+探针 PASS | - -### 5.5 实机目检总清单(只登记,不阻塞合并) - -| # | 项目 | 观测点 | 状态 | -|---|---|---|---| -| 1 | 雾下可读性观感 | 未知类型房间是否一眼可辨为「未知」而非「漏画」;编号仍在、类型图标与文字不出现 | 待用户试玩 | -| 2 | 多终点 Boss 标记观感 | 双 Boss 图上两个终点的紫赤描边是否都清楚可辨 | 待用户试玩 | -| 3 | 大图完整可见观感 | 大图(11 层×6 槽)整幅在画布内、无节点被裁切或挤在一角 | 待用户试玩 | - -### 5.6 遗留读数义务 - -- 数值零变更(`info_visible_layers` 是呈现参数,不进战斗结算),本卡不发起模拟跑批(MC 档位规则)。 -- 合并后主区需 `--editor --quit` 重刷类名缓存,再跑一次代码域全量闸复跑,读数写入合并提交信息。 -- 合并前回执须与分支尖同 commit(回执 `commit` 字段)。 - -### 5.7 全量代码闸读数 - -T4 里程碑跑批 `tools/run_all_gates.sh --code`,起跑 commit `4ef154b9`: - -| 闸 | 退出码 | 对基线 | -|---|---|---| -| 01 冒烟全量 | 0 | 一致(1211 项检查 0 失败) | -| 02 单元套件 | 0 | 一致(40 套件,含本卡新增 2 套件) | -| 03 探针 --click | 0 | 一致 | -| 04 探针 --full | 0 | 一致 | -| 05 渲染闸 | 0 | 一致 | -| 09 静态扫描 | 1 → 0 | 新增 4 处 R1(容器未参数化)→ `6f04f29b` 修复后归零,由红转绿(改善) | -| 10 熵增闸 | 0 | 一致 | -| 11 回放确定性对拍 | NEED-APPROVAL | 本卡数值零变更,按档位规则不发起(需用户批准) | - -`6f04f29b` 修复后窄验证:`audit_type_hints` PASS;两套件 26+19 项全绿;`ui_input_probe` PASS。 - -D1 回炉后在分支尖复跑(`de9cc102`,含代码笔 `1970e0ef`):`all_green: true`、`changed_vs_baseline: []`、01 冒烟 1211 项 0 失败、02 单元 40 套件全绿、03/04 探针绿、05 渲染闸绿、09 静态扫描 0(对基线「改善」)、10 熵增闸 0、11 对拍按档位规则 NEED-APPROVAL。此前那一次复跑(`8b9c6989`,甲案代码之前)已被本次取代。 - -## 六、卡④ 独立验收审计 - -审计报告:`reports/iter34-卡④-验收审计-2026-10-22.md`(未参与实现的子代理执行;被审 HEAD `6757c21e`;自跑 40 套件、探针、冒烟 1211 项,另自设变异注入)。 - -**第一轮结论:不通过**——2 条缺漏,无测试削弱、无契约破坏、无越权自决、无数值/RNG 违规。M1/M2/M9/M10 四条变异由审计自跑,「红的位置与报告 §5.4 逐字一致,无复现不一致」。 - -| 缺漏 | 内容 | 本批处置 | -|---|---|---| -| D2 回炉 T4/T5 | 缺与分支尖同 commit 的 `--code` 全绿回执(旧回执停在 `4ef154b9`、09 红、`all_green=false`) | **已闭合**:在分支尖重跑全量代码域闸,回执 `commit=de9cc102`(甲案代码回炉之后重跑)、`all_green=true`、`changed_vs_baseline=[]`(见 §5.7) | -| D1 回炉 T2 | fv2「接线层验收」未成立:`display_probe()` 是逐节点重调 `node_display` 的快照,与 `_draw_graph` 的实际绘制是两次独立求值;审计注入「`_draw_graph` 两处条件改 `if true`」模拟接线坏,单元 19 项与探针仍全绿。审计判为**卡片 T2 对 `display_probe` 的定义与 §7.1 fv2「读绘制面」要求互相矛盾(spec-AC 不一致)** | **甲案回炉(提交 `1970e0ef`)**:呈报后用户指令「继续未完成的任务」,按呈报推荐案甲落地——`_draw_graph` 在描边/图标/文字三处实际绘制点写入本帧绘制事实(新只读成员 `_drawn_disp`),`display_probe()` 改读该记录、不再二次求值;探针⑱ 选区改按核心 `type_visible_ids()` 独立选雾节点,解除「按记录选、再断言记录」自指;单元大图组两处呈现断言随动读绘制记录。新增撤销证明 M11(绕开决策面直接画 → 单元〔fv8〕与探针〔fv2〕双红)。该项在 §9 白名单外,已在代拍板追认单第 7 行备案,可整笔回退。 | - -审计附三条非阻塞观察项,处置:第 1、3 条已随甲案修除,第 2 条按卡片 T2 指定写法保留(核心多 Boss 成员性由 `level_map_type_vis_test` 的〔fv3〕用例覆盖同一分支)—— - -1. 探针 ⑱ 的「雾下图标不出示」判据自指——`fog_id` 正是按 `not draw_icon` 选出再断言其 `not draw_icon`,该半句恒真;有效的是文字通道半句与存在性判定(M2 时因选不到雾节点走「选取失败」分支变红)。建议选区与断言解耦(按层距/候选集独立选雾节点)。 -2. fv3 双 Boss 夹具手写 `type_vis=[1,7,9]`,未从 `type_visible_ids()` 推导两端点均在集;核心多 Boss 成员性由单 Boss 用例覆盖同一分支,风险低。 -3. 探针 PASS 文案只列到 ⑰、未点名 ⑱,§5.2 原称「探针⑱ 5 项断言」实为 4 个 `_pre_fail` 判据+1 个选区前置。两处均已订正:⑱ 已列入 PASS 文案,计数改写为「4 判据+1 前置」。 - -### 6.1 第二轮复审结论(`reports/iter34-卡④-验收审计-复审-2026-10-22.md`) - -被审 HEAD `de9cc102`(=分支尖=回执 commit)。执行者仍是未参与实现的子代理,自跑呈现单元、核心单元、输入探针与冒烟读数,并自己复现第一轮判「不红」的那发注入。 - -| 项 | 结论 | 复审自跑证据 | -|---|---|---| -| 项 1 D1 是否真关 | **通过** | 注入 `_draw_graph` 图标/文字两处条件改 `if true` → 呈现单元〔fv8〕与探针〔fv2〕双红,探针红原文 `case⑱ 雾下节点类型仍出示(图标=true 文字=true——范围外只见结构)〔fv2〕`;另发「只污染记录值」的新变异同样双红,证记录承重 | -| 项 2 ⑱ 自指解除 | **通过** | 选区改按核心 `type_visible_ids()`/候选集/当前位独立选点,断言读绘制记录,两侧不同面 | -| 项 3 新削弱/新越权 | **通过** | 无删断言、无放宽阈值(探针常数锚 26→36.5 属变严,容差 -0.5 未动);新增面为只读观测,零新画法/色值/线宽/缩放滚动/存档;白名单外手段已在代拍板第 7 行备案、可一笔回退 | -| 项 4 D2 与账面相符 | **通过** | `receipt.json` `commit=de9cc102`、`all_green=true`、`changed_vs_baseline=[]`;自跑冒烟 1211 项 0 失败、单元 40 套件绿 | - -**闭合判定:D1 已闭合、D2 已闭合,总判定通过(可合并)。** 观察项 1 与 3 已随甲案修除;观察项 2 按卡片 T2 指定写法保留,核心多 Boss 成员性由 `level_map_type_vis_test`〔fv3〕覆盖,维持非阻塞。复审指出的一处账面措辞(§5.7 与 §六 仍引旧复跑 commit `8b9c6989`)已在本节随文订正。 - -**合并状态:两轮审计均通过,合回 master。** 卡③ 已在 `43c0f3c1` 合回。 - diff --git a/reports/iter34-验收审计-2026-10-22.md b/reports/iter34-验收审计-2026-10-22.md deleted file mode 100644 index 04f38ea5..00000000 --- a/reports/iter34-验收审计-2026-10-22.md +++ /dev/null @@ -1,100 +0,0 @@ -# 迭代 34 卡③ 独立验收审计(2026-10-22) - -被审对象:实现报告 `reports/iter34-实现报告-2026-10-22.md`、需求卡片 `reports/需求卡片-敌人表深度带换代批-2026-10-21.md`、工作树 `D:\code\g-plan2-iter34-enemy`(分支 `iter34-enemy-band`,HEAD `7bb41891`,基线 `603eba31`)。 - -审计方式:只读代码、测试、卡片与 diff。所有结论以审计人自己运行的输出为准,不采信报告「已全绿」的表述。审计期间为复现撤销证明注入的变异,均用单文件 `git checkout -- ` 还原并复跑确认,工作树结束时无改动。 - -## 审计结论 - -不通过:缺漏 4 条(V7 无覆盖行、fv24 尾缀挂错需求点;V9/fv26 覆盖行缺失;S15 `boss_name` 换代无断言;V6①/fv21 撤销证明按记录无法变红),另有描述不符 4 条;其余对照行通过。 - -## 一、对照表逐行核对 - -核对方法:按报告 §2.2 的 file:line 逐条读断言文本,grep 尾缀〔fv#〕确认可定位,再沿断言回溯到改动点入口(`resolve_enemy_rowset`/`EnemyTable.validate`/`cross_validate`/生产表读数),并在工作树实跑对应套件确认该断言在跑。 - -| fv | 需求点 | 测试存在(file:line) | 尾缀可 grep | 真实入口 | 结论 | -|---|---|---|---|---|---| -| fv1 | V1① 带命中偏难 | `config_db_resolver_test.gd:58`、`:61` | 是 | `resolve_enemy_rowset(1,4/5,"battle")` → `band_of` | 通过 | -| fv2 | V1② 行序保序 | `config_db_resolver_test.gd:67`、`:71` | 是 | 同上,断言行集顺序 | 通过 | -| fv3 | V1③ 顶带 clamp+告警去重 | `config_db_resolver_test.gd:78`、`:84`、`:87` | 是 | 同上,D=99 与重复请求 | 通过 | -| fv4 | V1④ row_kind 路由 | `config_db_resolver_test.gd:93` | 是 | 同 D 传 battle/boss | 通过 | -| fv5 | V1⑤ 越域与非法行类 | `config_db_resolver_test.gd:101`、`:104`、`:107` | 是 | `resolve_enemy_rowset(0,…)`/`(1,-1,…)`/`(1,0,"elite")` | 通过 | -| fv6 | V2① 生产表校验零错误 | `config_db_test.gd:14` | 是 | `ConfigDB.load_tables` → `EnemyTable.validate` | 通过 | -| fv7 | V2② 非法 row_kind 被拒 | `config_db_test.gd:256` | 是 | `validate()` 非法枚举夹具 | 通过 | -| fv8 | V2③ dup_key 新键拦截 | `config_db_test.gd:235` | 是 | `validate()` 同带同敌种二行夹具 | 通过 | -| fv9/fv20 | V2④、V5③ 同带隔断 | `config_db_test.gd:225`(一条断言两个尾缀) | 是 | `validate()` 隔断夹具 | 通过 | -| fv10 | V2⑤ 锚行与 Boss 行集 | `config_db_test.gd:265`、`:273` | 是 | `validate()` 缺锚/缺 Boss 夹具 | 通过 | -| fv11 | V3① 20 行计数与键序 | `smoke_all.gd:2106` | 是 | 加载 `enemy.tres` 全表逐行比对 | 通过 | -| fv12/fv25 | V3②、V8 hobgoblin 留任 | `smoke_all.gd:2114`、`:2116` | 是 | 同 fv11 读表面+表注释 | 通过 | -| fv13 | V3③ 三 Boss 行就位 | `smoke_all.gd:2132` | 是 | 同 fv11 读表面 | 通过 | -| fv14 | V3④ 值列零变更 | 无断言(件核):`git diff 603eba31..7bb41891 -- game/data/tables/enemy.tres` | 无(卡片约定件核) | diff 去键列后逐值列比对 | 通过(去键列后值列逐字节一致) | -| fv15 | V4① 同带双 boss 报错 | `config_db_cross_validator_test.gd:137` | 是 | `cross_validate()` 双 Boss 共带夹具 | 通过 | -| fv16 | V4② 顶 clamp 消解报错 | `config_db_cross_validator_test.gd:142` | 是 | `cross_validate()` Boss 深度 10>顶带 9 | 通过 | -| fv17 | V4③ 单终点零误报 | `config_db_cross_validator_test.gd:132` | 是 | `cross_validate()` 合成单关夹具 | 例外:夹具只有 level 1(`display_name:"夹具关"`),报告写「现役三关夹具」不实;现役三关零误报由 fv6 兜住 | -| fv18 | V5① 混编行序 | `smoke_all.gd:4815` | 是 | 读 (2,battle,5) 行集顺序 | 通过 | -| fv19 | V5② 骰和 ≤4 | `smoke_all.gd:4820` | 是 | 读同行集静态求和 | 例外:断言是静态求和,放宽它本身不会红;能变红的是同段未编号的运行期守卫断言 | -| fv21 | V6① 首遇带数据驱动 | `smoke_all.gd:2282`(定位助手 `:3516`) | 是 | `_first_encounter_band` 扫表+行集读数 | 通过(撤销证明不成立,见第四节第 4 条) | -| fv22 | V6② 巨蜘蛛首遇带固定 2 | `smoke_all.gd:4801` | 是 | 扫表定位+行集读数 | 通过 | -| fv23 | V6③ L1/L3 首遇带固定 1 | `smoke_all.gd:3473`、`:4859` | 是 | 同上 | 通过 | -| fv24 | 报告写作「Boss 行集与毒吐投放面」 | `smoke_all.gd:4281`、`:4291`、`:4807`、`:4865` | 是 | 扫表定位+Boss 行集 | 缺漏:卡片 V7 要求「S 清单 17 行逐条换代+清单件核」,这 4 条断言不是该需求点的验证;报告无 V7 行,也无 S1–S16 逐条勾销表 | -| fv25 | V8 缺口登记随行 | `smoke_all.gd:2116`(与 fv12 共用行) | 是 | 表文件注释在位 | 通过 | -| —(V9/fv26) | V9 反哺点五落点件核 | 报告 §2.2 无此行 | — | 应为 `reports/iter34-反哺点-2026-10-22.md` 五条落点件核 | 缺漏:反哺点文件已有 ①–⑤ 五节,但对照表没有 fv26 覆盖行 | - -需求点覆盖对照:V1①–⑤=fv1–fv5,V2①–⑤=fv6–fv10,V3①–④=fv11–fv14,V4①–③=fv15–fv17,V5①–③=fv18–fv20,V6①–③=fv21–fv23,V8=fv25;V7 与 V9 没有对应覆盖行(见上表两处缺漏)。 - -## 二、撤销证明抽查 - -抽查 6 项(报告 §2.3 七条中取 5 条复现,另核 1 条不可复现)。每条流程:改一个文件注入 → 跑报告指明的最窄命令 → 确认对应断言变红 → `git checkout -- <单文件>` 还原 → 复跑回绿。 - -| 变异 | 复现结果 | 红输出首行 | 还原结论 | -|---|---|---|---| -| 1. `EnemyTable.band_of` 判据 `>=` 改 `<=`(反向 floor) | 已复现 | `[FAIL] 带命中取偏难一侧:请求深度 4 命中带 5(逐字不回带 0)〔fv1〕`;连带〔fv1〕第二条与〔fv3〕两条 | `git checkout -- game/data/schemas/enemy_table.gd`;resolver 套件 14 项全绿 | -| 2. `validate` 的 row_kind 枚举判据前置 `if false and` | 已复现 | `[FAIL] 非法 row_kind 被拒(封闭枚举 {battle, boss})〔fv7〕`(1/29 项失败) | 同文件 checkout;config_db_test 29 项全绿 | -| 3. 删除跨表「Boss 同带」判据 | 已复现 | `[FAIL] 同关双终点共带报 rowset_rule〔fv15〕` | `git checkout -- game/core/config_db_cross_validator.gd`;跨表套件 7 项全绿 | -| 4. 顶带消解判据短路 `if false` | 已复现 | `[FAIL] Boss 节点越顶带报 level_node_dangling〔fv16〕` | 同文件 checkout;7 项全绿 | -| 5. hobgoblin 与带 2 行互换带键(报告第 7 项第二注入法) | 已复现 | 冒烟首红〔fv11〕「敌人表 20 行且键序=迁移表序…」,随后〔fv12〕〔fv25〕红 | `git checkout -- game/data/tables/enemy.tres`;冒烟 1161 项检查 0 失败 | -| 6. hobgoblin 直接改到带 2(报告第 7 项第一注入法) | 已复现,但拦截者与报告所写不同 | `ERROR: [ConfigDB/level_node_dangling] level 1 battle 节点深度 3 高于 (level 1, battle) 顶带键 2——顶 clamp 消解`;随后〔fv6〕红,套件 2/2 项失败即止 | 同文件 checkout;config_db_test 29 项全绿 | -| 7. V6①「撤销扫表定位、写回写死坐标」 | 未复现(按记录设计不成立) | — | 未注入:助手 `_first_encounter_band`(`smoke_all.gd:3516`)返回值与旧写死值同为 L1=2/L2=4/L3=0,写回后断言值不变、不会红;要让 fv21 变红只能改数据把首遇行移带 | - -实际运行命令(均在工作树,`PYTHONIOENCODING=utf-8`,Godot 4.7.2 console 版 headless,一次只跑一个进程): - -- `--script res://tests/unit/core/config_db_resolver_test.gd`(多轮,含注入与还原后复跑) -- `--script res://tests/unit/data_config/config_db_test.gd`(多轮) -- `--script res://tests/unit/core/config_db_cross_validator_test.gd`(多轮) -- `--script res://tests/run_all.gd`(全量单元 35 套件) -- `--script res://smoke/smoke_all.gd`(1161 项检查 0 失败,多轮) -- `git diff`、`git status`、`git checkout -- <单文件>` - -补充核验:把 `battle_narrator.gd:76` 的 `"boss"` 改为 `"battle"` 后,35 个单元套件与整轮冒烟仍全绿,说明该改动点没有被任何断言拦住(见第四节缺漏 3)。 - -## 三、测试削弱检查 - -检查范围:`git diff 603eba31..7bb41891 -- game/tests game/smoke`(删 173 行、增 418 行)。逐项核对删除、阈值、扫描面与入口层级: - -1. `config_db_resolver_test.gd` 删除 `_test_ceil_progress_key`(board_gen ceil 3 条断言):属卡片 §8.2 旧断言预声明 S11「换代为 V1 带寻址语义断言」;board_gen 的 ceil/越顶/去重仍由 `config_db_test.gd:30-82` 覆盖,未失效。 -2. gp 掉落断言由硬编码 `[2,4]` 改为读 `shop.tres` Boss 档区间+关级加值:报告 §2.4 第 2 条已申报;判据仍比对结算输出,强度不低于原式。 -3. `skill_unlock_test.gd` Boss 用例 `spawn(2,9)` 补显式 `"boss"`:报告 §2.4 第 3 条已申报。 -4. 冒烟多处补 `node_type:"boss"`/补行类参数:报告 §2.4 第 1 条已申报。 -5. 未发现「真实入口换低层直调」:fv1–fv5 仍走 `resolve_enemy_rowset`,fv6–fv10 走 `EnemyTable.validate`(经加载),fv15–fv17 走 `cross_validate`,冒烟断言走 `_db.enemy.rows` 与 `spawn`。 -6. 检查数量:冒烟 1156→1161,单元 35 套件不变;无净收缩。其余删除行均为按 S 清单把旧坐标断言改写为带键断言,语义保持。 -7. 未发现未申报的阈值放宽或扫描面缩小。 - -结论:未发现未申报的测试削弱。另有一处计数描述不符:报告称「35 条断言带 fv 尾缀」,实测带尾缀行 35 行,其中 `smoke_all.gd:969` 是注释,断言为 34 条。 - -## 四、缺漏与例外 - -缺漏: - -1. **V7 无覆盖行、fv24 尾缀挂错需求点**。位置:报告 §2.2 表(无 V7 行);卡片 §8.2 V7 要求「S 清单 17 行逐条换代+实现报告逐条勾销」。事实:fv24 的 4 条断言(`smoke_all.gd:4281`/`:4291`/`:4807`/`:4865`)验证的是 Boss 行集与毒吐投放面,不是 S 清单完整性;报告也没有 S1–S16 逐条勾销表。建议:补 V7 覆盖行与逐条勾销表,或经卡片所有者同意把 V7 的验收方式改写为实际断言。 -2. **V9/fv26 覆盖行缺失**。位置:报告 §2.2 表;卡片 §8.2 V9。事实:`reports/iter34-反哺点-2026-10-22.md` 已有 ①–⑤ 五节落点,实物在,但对照表没有 fv26 件核行,无法按表逐行核对。建议:补一行「V9|五条落点各一|件核:反哺点文件 ①–⑤|非行为改动|通过」。 -3. **S15 `boss_name` 换代无断言**。位置:`game/presentation/battle_narrator.gd:76`;卡片 §8.1 S15、§8.2 V7。事实:把该处 `"boss"` 改成 `"battle"` 后,35 个单元套件与整轮冒烟 1161 项全绿;`battle_narrator_test.gd` 从未调用 `boss_name`。建议:补一条走真实入口的单测(构造 Boss 节点,断言叙述名取 boss 行集名),或在报告 §2.4 如实声明该处无断言并说明理由。 -4. **V6①/fv21 撤销证明不成立**。位置:卡片 §8.2 V6① 撤销证明、报告 fv21 行。事实:按记录「撤销扫表定位、写回写死坐标」还原后,助手返回值与写死值相同(L1=2/L2=4/L3=0),断言不会红;该撤销证明无法区分「数据驱动」与「写死」。建议:改为数据侧变异(把首遇行移到别的带,断言应取键失配变红)或如实标注撤销边界。 - -例外(描述不符,不影响其余覆盖): - -5. **fv17 夹具描述**。位置:`config_db_cross_validator_test.gd:128-132`;报告 §2.2 fv17 行写「现役三关夹具」。事实:夹具是 level 1 合成单关(`display_name:"夹具关"`);现役三关零误报由 fv6(生产表加载零 error)覆盖。建议:改报告措辞,或补现役三关夹具。 -6. **fv19 撤销归属**。位置:`smoke_all.gd:4820`。事实:静态求和断言被放宽不会红;真正能红的是同段未编号的运行期守卫断言(「两行各定值 3(总 6>4)spawn 被拒」)。建议:报告撤销证明改写为「改 `ROWSET_INSTANCE_MAX` 守卫 → 守卫断言红」。 -7. **§2.3 第 7 项拦截边界描述有误**。位置:报告 §2.3 注①。事实:hobgoblin 直接改到带 2 时,首条红是跨表 `level_node_dangling`(战斗节点深度 3 无带可落),不是「同带相邻规则」;同带相邻未触发,是因为 hobgoblin 紧接在 bugbear 带 2 行之后、文件内相邻。建议:按实际首红改写。 -8. **断言计数**。位置:报告 §2.2 覆盖说明「共 35 条断言带 fv 尾缀」。事实:带尾缀行 35 行,其中 1 行为注释(`smoke_all.gd:969`),断言 34 条。建议:改为 34 条。 - -审计结束时工作树 `git status --short` 为空,HEAD 仍为 `7bb41891`;除本报告外未新增或修改任何文件。 diff --git a/reports/iter34-验收审计-复审-2026-10-22.md b/reports/iter34-验收审计-复审-2026-10-22.md deleted file mode 100644 index c7ef9716..00000000 --- a/reports/iter34-验收审计-复审-2026-10-22.md +++ /dev/null @@ -1,98 +0,0 @@ -# 迭代 34 卡③ 独立验收审计·第二轮复审(2026-10-22) - -- 被审 HEAD:`68009b4e`(`iter34-enemy-band`,基线 `603eba31`);第一轮被审 HEAD `7bb41891` -- 被审对象:实现报告 `reports/iter34-实现报告-2026-10-22.md`(§2.2/§2.2.1/§2.3/§3)、第一轮审计报告 `reports/iter34-验收审计-2026-10-22.md`、修补 diff `7bb41891..68009b4e`、卡片 `reports/需求卡片-敌人表深度带换代批-2026-10-21.md` -- 审计方式:只读代码、测试、卡片与 diff;所有结论以审计人自己运行的命令输出为准,不采信报告「实测/已全绿」表述。为复现撤销证明注入的变异一律单文件 `git checkout --` 还原并复跑确认;不跑全量闸(`tools/run_all_gates.sh` 留给实现会话在最终提交上跑)。审计结束时工作树 `git status --short` 为空(本报告除外)。 - -## 结论速览 - -**A–F 六项全部通过;总结论:通过。** 第一轮 4 条缺漏与 4 条描述不符全部真闭合,本次修补未引入测试削弱,无阻塞遗留例外。 - ---- - -## A. 缺漏 1(V7 覆盖行+17 行勾销表)——通过 - -依据: - -1. 报告 §2.2 已新增 fv24 覆盖行,需求点改写为「V7 S 清单 17 行逐条换代」,撤销列指向「逐条勾销见 §2.2.1」。 -2. 报告 §2.2.1 存在 17 行勾销表:S1–S9、**S10a/S10b 分列**、S11–S16,逐行给出「现工作树位置/换代内容/勾销凭据」,S11–S13 归单测面、S15 归消费面,口径与卡片 §8.1 一致。 -3. 按任务要求抽查 6 行(逐行实读代码确认位置与换代内容属实): - -| 抽查 | 报告所记位置 | 实读确认 | -|---|---|---| -| S1 | `smoke_all.gd:3168`/:3491/:4499 | 三处均为 `resolve_enemy_rowset(1, …, "battle")[0]` 三参化,且带「行集首行(…battle 键域)」注释,属实 | -| S6 | `smoke_all.gd:974-984`/:4781-4789/:5256-5258 | 三处 `en_keys["%d_%s_%d" % [level_index, row_kind, depth_band]]`/`"%d_boss_9"` 查 boss 键域,属实 | -| S8 | `smoke_all.gd:4262-4306` | `_first_encounter_band(2,"giant_spider")` 取首遇带、判据改 `depth_band > spider_lead_band`、`expect_pools` 键串含 row_kind(如 `2_battle_5_giant_spider`),属实 | -| S10a | `smoke_all.gd:2024`/:2674/:2699…;`damage_probe.gd:95` | 抽 3 行均为 `"node_type": "boss"` 直呼;另用脚本核了表中全部 18 个 `smoke_all.gd` 行号,每个都含 `node_type": "boss"`,属实 | -| S14 | `skill_rhythm_probe.gd:17`;`damage_probe.gd:269`/:422 | 三处均显式传 row_kind(`"battle"`/`t`/`kind`),属实 | -| S16 | `smoke_all.gd:3491`(断言 :3496) | `erow2 = _db.resolve_enemy_rowset(1, int(depth_v), "battle")[0]`,下行 `scan_bad == 0` 断言,属实 | - -另核 S2/S3/S4/S5/S7/S9 的行号指向(4795/4802/4810/4852/4860、2263/2279/2301、3460-3474),均与断言实际位置对得上,未发现空指或错指。 - -## B. 缺漏 2(V9/fv26 覆盖行)——通过 - -- 报告 §2.2 新增 fv26 行:「V9 反哺点五落点(非行为改动)|`reports/iter34-反哺点-2026-10-22.md` ①–⑤|件核」,与卡片 V9「§6 五条每条有落点」对应。 -- `reports/iter34-反哺点-2026-10-22.md` 实读确有 ①–⑤ 五节(① 敌人系统.md 记法与措辞、② 关卡节点地图.md :146、③ 关卡节点图生成.md 产出规格、④ 待办清单.md 状态回写、⑤ roadmap.md 迭代行),每节均写「文件与位置/改成/依据」。 - -## C. 缺漏 3(S15 `boss_name` 断言)——通过 - -- 用例位置:`game/tests/unit/presentation/battle_narrator_test.gd:59-82`,`_test_boss_name_uses_boss_rowset()` 由 `_init` 调用。 -- 真实入口成立:用例加载生产表后调 `NarratorScript.boss_name(runner, db)`(`battle_narrator.gd:72`),函数内走 `db.resolve_enemy_rowset(..., "boss")`(`:76`);生产调用点 `presentation/main.gd:1331` 同款。runner 替身只提供 `boss_name` 实际读取的 `level_row`/`current_node()` 两项,与 `core/level_runner.gd` 的同名面一致。 -- 期望值由数据读出:`boss_depth` 扫表取 L1 boss 行 `depth_band`,`boss_expect`/`battle_name` 分别由 boss/battle 行集首行 `display_name` 读出,无写死字面量;另有一条「boss 名 ≠ 同深度请求的战斗行集名」判别断言。 -- 自跑(命令与首行输出): - - `PYTHONIOENCODING=utf-8 "" --headless --path . --script res://tests/unit/presentation/battle_narrator_test.gd` - → `[battle_narrator_test] all green (13 checks)`,EXIT=0 - - 撤销注入:把 `battle_narrator.gd:76` 的 `"boss"` 改 `"battle"` 后重跑 - → `[FAIL] Boss 名取自 Boss 行集首行(期望「食人魔酋长」实际「大地精」)〔fv24〕`;`[battle_narrator_test] 1/13 项失败`,EXIT=1 - - `git checkout -- game/presentation/battle_narrator.gd` 后复跑 → `[battle_narrator_test] all green (13 checks)`,EXIT=0 -- 与报告 §2.3 第 9 项所记(红断言原文、13 项回绿)逐字相符。 - -## D. 缺漏 4(V6①/fv21 撤销证明)——通过(实测与报告一致) - -实测流程与结果: - -1. 数据侧变异:`game/data/tables/enemy.tres` 的 (level_index 1, row_kind battle, depth_band 2, bugbear) 行 `depth_band` 2→1,跑 `res://smoke/smoke_all.gd` - → `=== 冒烟完成:1161 项检查,6 项失败 ===`(EXIT=1)。〔fv21〕**不在**失败列表(首遇带随数据变为 1、锚定行随迁——数据驱动正证成立)。6 项红为:〔fv11〕20 行键序、〔fv23〕熊地精首遇带固定 1、全深度×12 种子 spawn 扫描、「二十行九种池模板」、「先手击杀→摇定技能作废」、「行集内每个战斗/Boss 节点…精确行集(缺失 1)」。报告所记「共 6 项红」属实。 -2. 叠加写死:在 `smoke/smoke_all.gd` 的 `_first_encounter_band` 首行插入 `return 2`,重跑冒烟 - → 首条红即 `[FAIL] 熊地精首遇带(1,battle,2)降档锚定(hp 22 · ac 2 · 池 attack6/charge2/heavy2 零改动——迭代 24 N1;首遇带数据驱动定位)〔fv21〕`;`=== 冒烟完成:1161 项检查,9 项失败 ===`(EXIT=1)。报告所记「共 9 项红」属实。 -3. `git checkout -- game/data/tables/enemy.tres game/smoke/smoke_all.gd` 还原,复跑 - → `=== 冒烟完成:1161 项检查,0 项失败 ===`(EXIT=0)。 - -结论:该撤销证明现在能真正区分「数据驱动定位」与「写死坐标」——单跑数据变异〔fv21〕绿、叠加写死才红,报告 §2.3 第 8 项的记述与实测逐项一致。 - -## E. 描述不符 4 条——通过(4/4 已按实改写) - -1. **fv17 夹具措辞**:`config_db_cross_validator_test.gd:95-116` 的 `_loaded()` 只构造 `level_index: 1`、`display_name: "夹具关"` 的合成单关夹具;fv17(:132)在该夹具上断言零误报。报告已改为「level 1 合成单关夹具;现役三关零误报由 fv6 兜住」,与实读一致。**通过**。 -2. **fv19 撤销归属**:`smoke_all.gd:4810-4820` 的静态求和(首遇混编数据 Σ=4,阈值 `<= 4`)放宽阈值不会红;真正能红的是同段运行期守卫(`:4891-4914` 注入 (1,battle,6) 两行各 3 只,`:4909` 断言 `not over_sys.spawn(...)`,由 `ROWSET_INSTANCE_MAX` 守卫兜住)。报告已改为「改运行期守卫 → 守卫断言红;静态求和本身放宽不会红」,归属正确。**通过**。 -3. **§2.3 第 7 项拦截首红**(可选复现已做):把 hobgoblin 行 `depth_band` 3→2 后跑 `res://tests/unit/data_config/config_db_test.gd`,首条错误为 - `ERROR: [ConfigDB/level_node_dangling] level 1 battle 节点深度 3 高于 (level 1, battle) 顶带键 2——顶 clamp 消解` - 随后 `[FAIL] 全部表加载 + 校验通过(含跨表护栏零 error 诊断)〔fv6〕`,EXIT=1;`git checkout --` 还原。与报告改写后的「跨表 level_node_dangling 首红、同带相邻未触发」一致。**通过**。 -4. **断言计数**:`grep -rn "〔fv[0-9]*〕" tests/ smoke/ --include=*.gd` 得 37 行;逐行核对,`smoke_all.gd:969` 为注释(`# 同带多行合法,带键聚合天然兼容〔fv24〕)`),其余 36 行均为断言行 → 「36 条断言+1 行注释」属实;fv14/fv26 按卡片约定走件核,代码侧无尾缀,覆盖说明自洽。**通过**。 - -## F. 测试削弱检查——通过 - -检查范围:`git diff 603eba31..68009b4e -- game/tests game/smoke`(8 个文件,+449/−166)与本次修补 `git diff 7bb41891..68009b4e`。 - -1. **本次修补未碰产品代码与既有断言**:`7bb41891..68009b4e` 仅 `battle_narrator_test.gd` 38 行新增(0 删除)+两份报告;新增用例为纯增量,无删断言、无阈值放宽、无扫描面缩小。 -2. **全量 diff 的删除行均属卡片 §8.2「旧断言预声明」允许的 S1–S16 改写**:删除面集中在 `config_db_resolver_test.gd`(S11 换代)、`config_db_test.gd`(S12 夹具键改名)、`config_db_cross_validator_test.gd`(S13)、`smoke_all.gd`(S1–S10)、两份探针(S14);`skill_unlock_test.gd` 的 `spawn(2,9)` 补显式 `"boss"`、冒烟 gp 掉落断言改读 `shop.tres` Boss 档区间+关级加值,均在报告 §2.4 第 1–3 条申报。 -3. **无阈值放宽 / 无扫描面缩小**:diff 中没有 seed/`range()` 扫描规模改动;第一关曲线阈值 `≤ 2.5`、混编 `≤ 4`、首遇 `unit_count=2`/固定 1 等判据原样保留;gp 掉落断言由硬编码 `[2,4]` 改为数据驱动 `Boss 档 [6,10] + 关级加值`(因 S10a 把该战改为 boss 语义,掉落档合法切换),判据仍比对结算输出,强度不降。 -4. **真实入口未换下层直调**:fv1–fv5 走 `resolve_enemy_rowset`,fv6–fv10 走加载后的 `EnemyTable.validate`,fv15–fv17 走 `cross_validate`,fv18–fv23 走冒烟表读取+`spawn`,S15 走 `boss_name` → `resolve_enemy_rowset(..., "boss")`。 -5. **数量面**:冒烟 1156→1161(本卡 +5),单元套件 35 个不变;`battle_narrator_test` 检查数 11→13(新增 2 条)。无净收缩。 - -结论:未发现未申报的测试削弱,本次修补为纯增量。 - ---- - -## 遗留例外/观察(不阻塞) - -1. 第一轮审计报告第三节所记 diff 行数「删 173 行、增 418 行」与实测 `git diff --numstat 603eba31..7bb41891 -- game/tests game/smoke`(+411/−166)不一致,属第一轮报告的计数笔误(不影响其结论,也不属实现报告内容);本轮结论以实测为准。 -2. 新单测在解析 L1 battle 行集时(同深度请求落在 Boss 深度 4)会触发一次 `resolve_depth_clamp` 警告——这是顶带 clamp 的预期语义,非失败;用例仍 13 项全绿。 - -## 运行命令清单(均为工作树 `game/` 下、Godot 4.7.2 console 版、`PYTHONIOENCODING=utf-8`、一次一个进程) - -- `--headless --path . --script res://tests/unit/presentation/battle_narrator_test.gd`(注入前后与还原后共 3 轮) -- `--headless --path . --script res://smoke/smoke_all.gd`(数据变异/叠加写死/还原后共 3 轮) -- `--headless --path . --script res://tests/unit/data_config/config_db_test.gd`(hobgoblin 错带复现 1 轮) -- `git diff 603eba31..68009b4e -- game/tests game/smoke`、`git diff --numstat`、`grep -rn "〔fv[0-9]*〕"`、`git checkout -- <单文件>`、`git status --short` - -审计结束时工作树除本报告外无改动,HEAD=`68009b4e`。 diff --git a/reports/需求卡片-信息迷雾可见性批-2026-10-21.md b/reports/需求卡片-信息迷雾可见性批-2026-10-21.md deleted file mode 100644 index 1d5788b5..00000000 --- a/reports/需求卡片-信息迷雾可见性批-2026-10-21.md +++ /dev/null @@ -1,246 +0,0 @@ -# 需求卡片:信息迷雾可见性批(关卡节点图重构卡④——选路信息可见性落地) - -- 版本:**v1.0**(2026-10-21 成文;grilling 复核结论见 §11) -- 来源:[待办清单](../待办清单.md)「关卡节点图重构——可选节点太少」(2026-10-13 登记,设计面=文档轨)(唯一事实源:① [关卡节点地图](../design/gdd/systems/冒险循环/关卡节点地图.md) v2.1「选路信息可见性:近处见类型,远处起雾」节+同文调参表「信息可见层数 N」;② [关卡节点图生成](../design/gdd/systems/冒险循环/关卡节点图生成.md) v1.1「下一跳必在可见范围,是决策的可见锚」承诺;呈现口径权威=[level-map](../design/gdd/ux/level-map.md) 头部机制权威行+节点态呈现口径〔视觉终稿冻结件〕) -- 归属:关卡节点图重构批**卡④**(可见性规则+呈现接线);卡①生成器/卡②行进换代/卡③敌人表不在本卡 -- 排期:未编入(2026-10-18 用户令:需求卡片不预占迭代号,批次归属按工作量另裁) -- 开工门:U0(用户 `/iter` 发令)+ grilling 复核门过+零待裁点(§11) - -## 0. 前置依赖与并行性 - -- 设计闭合凭据=关卡节点图生成.md v1.1+关卡节点地图.md v2.1(2026-10-21),06 条目状态「文档设计已闭合」——第〇步放行成立。 -- 本卡消费的节点图数据形态=现行 `level.tres` 模板池(type/node_depth/next 三键);卡①生成器落地图后数据形态不变(生成侧只换图的来源),本卡消费面零随动。 -- **06 状态回写呈报**:条目状态应推进为「已写卡(`reports/需求卡片-信息迷雾可见性批-2026-10-21.md`)」——本会话受「只许创建/修改本卡一个文件」约束未落,开工前须由用户补记或授权写卡方补记(登记不阻塞,防遗忘义务在此显式承载)。 -- 与在役结构的关系:`LevelRunner`(core)与 `LevelMapScreen`(presentation)均在役,本卡只扩只读出口与呈现决策面,不改 autoload 链、不改行进/兑付流程。 - -## 1. 目标与完成定义 - -**目标**:把关卡节点地图 v2.1「选路信息可见性」三层语义落成可见性规则+最小显隐呈现——图结构全图明牌(节点、连线、入口、终点位置永远可见)/节点类型仅在邻近 N 层内可见、范围外信息迷雾只见结构不见类型/节点内详情(打谁、给什么)图上从不显示;Boss 标记与终点身份不入雾。N 进数据表(provisional 挂值,数值定值归定值批)。呈现接线三件:迷雾下节点显隐语义、多终点 Boss 标记、画布自适应(图变大布局跟上)。 - -**相对现状,新增了什么**: -1. 可见性规则(现役图上类型全明牌、零过滤——见 F2):`LevelRunner` 只读出口 `type_visible_ids()`; -2. N 参数落数据表(现役无此字段——见 F6):`LevelTable.info_visible_layers`(int ≥ 1,provisional 2); -3. 迷雾呈现显隐接线(现役图标/类型文字无条件绘制——见 F2):`node_display` 决策面+`_draw_graph` 消费; -4. 多终点 Boss 标记接线(渲染循环已通用,雾豁免与夹具断言补齐——见 F7); -5. 画布自适应断言面(公式已通用,大图回归断言与探针常数锚同源补齐——见 F3)。 - -**完成定义**(全部满足才算本批完成): -1. 邻近 N 层内节点类型可见;层距 > N 的非豁免节点只见结构(方块态色/编号/连线)不见类型(图标+类型文字);N 读数据表、int ≥ 1; -2. Boss 标记与终点身份恒可见(多终点图每个终点均带标记且均不入雾);当前候选(下一跳)恒可见类型; -3. 节点内详情图上零显示(回归断言在案:决策面不消费内容字段); -4. 迷雾呈现=显隐语义,零新画法零灰化遮罩;冻结视觉件零改动; -5. 单圈语义:可见性纯函数于当前锚点,已过节点出圈回雾(零累积记忆); -6. 画布自适应对大图成立(包络覆盖最深节点、命中可达)+探针常数锚与屏内公式同源; -7. 断言批全绿+变异验证记录齐;三份 `reports/` 产出物写齐(T5);批末代码域闸全绿+改前改后读数对拍。 - -## 2. 现状事实(2026-10-21 worktree 实查;开工日 T0 复核行号) - -| # | 事实 | 出处 | -|---|---|---| -| F1 | 节点态四色+Boss 描边在 `_draw_graph`:已过=COL_ROOM_DONE(暗金 #68562C)/当前=COL_ROOM_CURRENT(金)/未达=COL_ROOM_FUTURE(暗);Boss=紫赤 2px 描边+外缘 1px 深墨环(灰度冗余通道);候选=亮金描边(悬停 4px/常态 2px) | `game/presentation/views/level_map_screen.gd:10-15`/`:450-464`(态色 `:450-454`、Boss `:457-461`、候选 `:462-464`) | -| F2 | 节点类型三通道全明牌、零可见性过滤:字形回退 NODE_LABELS(战/赏/疗/王/商)、类型文字 NODE_TYPE_NAMES、五键图标 TEX_NODE_ICONS;每个节点无条件绘制图标(或字形)+编号+类型文字标签(当前位转「当前位置」、候选加「· 可选」) | `level_map_screen.gd:17-20`/渲染点 `:467-475`(图标/字形)、`:477-479`(编号)、`:482-489`(类型文字) | -| F3 | 画布自适应已公式化通用:布局常数 NODE_HALF=36.5×25(52×36 的 1.4×)、LAYER_BASE_X=70/LAYER_STEP_X=122/SLOT_BASE_Y=52/SLOT_STEP_Y=58;`_fit_canvas` 包络=宽 70+最大层×122+NODE_HALF.x+8 × 高 52+最大槽×58+NODE_HALF.y+24,下限 620×256;`_layout` 与命中 `_candidate_at` 同源 | `level_map_screen.gd:25-29`/`:289-304`/`:492-501`/`:373-386` | -| F4 | 呈现只读出口在役:`nodes()`/`next_candidate_ids()`/`current_node_id()`/`node_id_of()`/`node_out_ids()`/`visited_ids()`;无可见性出口(本卡新增) | `game/core/level_runner.gd:327`/`:388`/`:396`/`:401`/`:405`/`:410` | -| F5 | 编号空间=图形态 node_depth/单链数组下标(`_node_id`);层=入口 BFS 深度(`_assign_layers` 分层=画布列同源),同层 slot 垂直排布 | `level_runner.gd:340-343`/`level_map_screen.gd:517-542` | -| F6 | 数据面无 N 字段:LevelTable 仅 `rows`;rest_heal_pct 越域校验先例([0,100] domain 错)可循;level.tres 三行各带 rest_heal_pct=30 | `game/data/schemas/level_table.gd:7`/`:35-37`/`game/data/tables/level.tres` | -| F7 | 图合法性现役「Boss 恰一」(boss_count != 1 → structural 错)——多终点图现役被加载拒;但渲染循环逐节点判 `type == "boss"` 已天然多 Boss 通用 | `game/data/schemas/level_table.gd:80-81`/`level_map_screen.gd:457-461` | -| F8 | 冻结件现状:level-map 视觉终稿已冻结(2026-09-28 样张 v1 机检 11/11);画布冻结公式「宽 = 70+层深×122+34、高 = 52+槽位×58+26+8」与代码现值漂移(代码宽尾 44.5=NODE_HALF.x+8、高尾 49=NODE_HALF.y+24;节点 1.4× 化+标签行 +24 后所致,注自述「层距/布局公式零改」) | `design/gdd/ux/level-map.md:3`/`:68`/`level_map_screen.gd:25`/`:301-303` | -| F9 | Boss 标记口径两文档不一致:关卡节点地图.md:67 写「Boss 封印黑描边(旗朱→封印紫→封印黑 #000000)」,level-map.md 写「紫赤描边+深墨环」;**代码实况=后者**(紫赤 BOSS_PURPLE 描边 2px+INK_ROUTE 深墨外环 1px) | `design/gdd/systems/冒险循环/关卡节点地图.md:67`/`design/gdd/ux/level-map.md:77`/`:113`/`:175`/`level_map_screen.gd:457-461`/`game/presentation/views/ui_kit.gd:19`(INK_ROUTE)、`:43`(BOSS_PURPLE) | -| F10 | 节点内详情现状已零显示:`_draw_graph` 只消费 type/节点 id/访问态三类信息,图上无敌人行集、奖励内容渲染——「图上从不显示」现状成立,缺回归断言 | `level_map_screen.gd:420-489` | -| F11 | 画布拟合探针常数锚手抄数字与屏内公式漂移:探针 `need_x2 = 70+maxl×122+26+8`,屏内公式尾为 NODE_HALF.x+8=44.5——探针断言被低报 10.5px 仍绿(自述「改常数须两侧同步」) | `game/smoke/ui_input_probe.gd:98-103`/`level_map_screen.gd:301` | - -## 3. 设计契约(红线,违反 = L3 停机呈报) - -🔴 **契约 1 · 可见性三层语义不破**:图结构(节点、连线、入口、终点位置、编号)全图明牌;节点类型=邻近 N 层内可见、范围外只见结构不见类型;节点内详情图上从不显示(关卡节点地图.md:97-101 三层表逐行兑现)。 - -🔴 **契约 2 · Boss/终点/候选三豁免**:Boss 标记与终点身份不入雾(豁免集=type=="boss",终点恒为 Boss);当前候选(下一跳)恒可见类型——兑现生成.md:83「下一跳必在可见范围,是决策的可见锚」承诺(直接兑现、不押注图形态)。 - -🔴 **契约 3 · N 只进数据表**:`info_visible_layers`(int ≥ 1)落 LevelTable,provisional 挂值 2;代码禁硬编码 N、禁绕表读值;数值定值权归定值批(调参表「provisional,定值批落数据表」)。 - -🔴 **契约 4 · 显隐语义、零新画法**:迷雾节点=类型图标+类型文字不绘制(显隐),结构通道(方块态色/编号/连线)照常;**禁灰化遮罩、禁雾纹理、禁任何新色值/线宽/形制**——雾的正式视觉规格属冻结件域,须用户裁(呈报项 §5),本卡只做可见性语义的最小呈现。 - -🔴 **契约 5 · 单圈语义**:可见性是当前锚点的纯函数(零累积记忆)——已过节点出圈回雾;锚层=当前节点层,入口停点(node_index=-1)锚层=0。 - -🔴 **契约 6 · 画布自适应不动冻结件**:公式族自适应保留(图变大布局跟上=包络随层深/槽宽增长);完整可见性由生成参数档背书(图包络 ≤ 屏预算,进反哺点移交卡①参数档);**禁缩放/滚动等动冻结视觉件手段**(若定值批需要超预算图,另行走呈报由用户裁)。 - -🔴 **契约 7 · 呈现只读不破**:可见性一律经 `LevelRunner.type_visible_ids()` 只读出口(纯函数、零状态、断点快照零新增字段);呈现层禁自算层距、禁触碰 runner 写面(level-map.md 架构注记)。 - -🔴 **契约 8 · 范围锁**:不动生成器/生成参数档/图合法性放宽(卡①域)、不改行进(卡②域)、不改敌人表(卡③域)、不改 N 数值(定值批)、不改冻结视觉件(用户域)。 - -## 4. 范围边界 - -**做**:可见性规则(层距 N+三豁免+单圈);N 落 LevelTable+level.tres;雾显隐呈现接线(`node_display` 决策面+`_draw_graph` 消费+探针);多终点 Boss 标记雾豁免接线+夹具断言;画布自适应大图断言+探针常数锚同源化;断言批(单测+冒烟+变异验证记录);反哺点清单。 - -**不做**(明示去向): -- 生成器、生成参数档、图合法性「Boss 恰一→多终点」放宽 → 卡①(生成域规则语义以生成产出规格为准);本卡呈现面按多 Boss 通用实现+合成夹具断言,卡①数据到位即接通; -- 行进换代(Peglin 式移动/选路方式) → 卡②; -- 敌人表 (level_index, node_depth) 行集随动 → 卡③; -- N 的数值定值 → 定值批(本卡只挂 provisional 2); -- **雾的正式视觉规格**(雾纹理/灰化遮罩/明度层) → 呈报项,用户裁冻结件后另立(level-map 视觉终稿已冻结,禁自行重开); -- level-map.md/GDD 正文改写(含 F8 公式漂移、F9 Boss 口径不一致的文档修正) → 文档批(走 §5 反哺点)。 - -## 5. 关联文档同步面 - -> **口径(2026-10-17 文档同步闸 v3)**:本批是代码实现批,禁写 `design/` 整目录与根规则文件,唯一可写目录 = `reports/`。下表「同步义务」一律执行为「列进 `reports/iter-反哺点-<完成日>.md`:哪个文件哪一节、改成什么、依据,用户会话裁决后归文档批落文」。禁写「随批」。 - -| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 | -|---|---|---| -| `design/gdd/systems/冒险循环/关卡节点地图.md` | :172 调参表 N「定值批落数据表」→ 本批已落表(provisional 2);:100「可见范围(邻近 N 层)」的实现语义锚定(层距口径=入口 BFS 层差、三豁免、单圈回雾)需入文固化 | 反哺点 · 列清单(调参表状态行改「已落表 provisional 2」+可见性节补实现语义注记) | -| `design/gdd/systems/冒险循环/关卡节点图生成.md` | 调参表(:105-114)补「图包络 ≤ 屏预算」约束行(契约 6 依据:完整可见 AC 冻结 ⇒ 参数档背书);:83「下一跳必在可见范围」标注实现侧已兑现 | 反哺点 · 列清单 | -| `design/gdd/ux/level-map.md` | :68 画布公式与代码现值漂移核对(34→44.5/26+8→25+24);Information Hierarchy 补「类型可见性(邻近 N 层显隐)」层级行;**雾的正式视觉规格待用户裁后另立(呈报项,禁本批落文)** | 反哺点 · 列清单+呈报项登记 | -| `design/gdd/术语表.md` | 新词入册:「信息迷雾」(关卡节点图类型可见性)区别于「视野迷雾」(战斗棋盘,HUD框架/art-bible §6.5)——两系统同词根易混 | 反哺点 · 列清单 | -| `design/gdd/systems/冒险循环/关卡节点地图.md` :67 | Boss 描边口径「封印黑 #000000」与 level-map.md/现役代码「紫赤+深墨环」不一致(F9)——文档批核对择一 | 反哺点 · 列清单 | -| `待办清单.md` | 06 条目状态 →「已写卡(卡片路径)」 | **写卡段义务**(非实现批)——本会话单文件约束未落,开工前补记(§0 呈报) | -| `roadmap.md` | 迭代行编入笔与批内状态刷新 | 反哺点 · 列清单 | -| `game/core/level_runner.gd`、`game/data/schemas/level_table.gd`、`game/data/tables/level.tres`、`game/presentation/views/level_map_screen.gd`、`game/smoke/ui_input_probe.gd`、`game/smoke/smoke_all.gd`、`game/tests/**` | 实施本体 | 实施本体(可写) | - -## 6. 任务卡 - -> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核本卡全部行号。 - -### 卡前·文件结构图 - -| 文件 | 职责 | 动作 | -|---|---|---| -| `game/data/schemas/level_table.gd` | N 字段承载+越域校验 | 改 | -| `game/data/tables/level.tres` | N provisional 挂值 | 改 | -| `game/core/level_runner.gd` | 可见性只读出口 `type_visible_ids()` | 改 | -| `game/presentation/views/level_map_screen.gd` | 雾显隐决策面 `node_display`+`_draw_graph` 消费+`display_probe` | 改 | -| `game/smoke/ui_input_probe.gd` | 拟合探针常数锚同源化(去手抄数字) | 改 | -| `game/smoke/smoke_all.gd` | 真图可见性冒烟断言 | 改 | -| `game/tests/unit/core/level_map_type_vis_test.gd` | 可见性规则单测 | 新建 | -| `game/tests/unit/presentation/level_map_info_fog_test.gd` | 显隐呈现+多 Boss+详情不显示单测 | 新建 | -| `game/tests/run_all.gd` | 两套件注册进 manifest | 改 | - -### T0 事实坐实与基线读数(≈0.5–1d) - -- [ ] 复核 §2 全部行号与读数,漂移即订正本卡(产出:本卡 §2 订正或维持记录)。 -- [ ] 跑 `godot --headless --path game --script res://tests/run_all.gd` 取改前基线读数(套件数/失败数)写进实现报告 T0 段。 -- [ ] 跑 `tools/run_all_gates.sh` 按改动域选档取改前闸读数写进实现报告 T0 段。 - -### T1 N 落表+核心可见性出口(≈1–1.5d) - -**接口声明**——产出:`LevelTable.info_visible_layers: int`(默认 2,validate 越域 domain 错);`LevelRunner.type_visible_ids() -> Array[int]`(语义见下)。取用:无(首卡)。 - -- [ ] `level_table.gd` 在 `rows` 声明(:7)后新增 `@export var info_visible_layers: int = 2`——核查:字段在案、类型 int。 -- [ ] `level_table.gd` `validate()`(:20 起)增越域检查:`info_visible_layers < 1` 时 append `{"category": "domain", "message": "info_visible_layers 越域 int≥1: %d"}`——核查:单测断言面可判红。 -- [ ] `level.tres` 资源顶层挂 `info_visible_layers = 2`——核查:`db.load_tables` 零错+读数 2。 -- [ ] `level_runner.gd` 新增只读出口 `func type_visible_ids() -> Array[int]`——语义钉死:返回集 = Boss/终点 id(type=="boss")∪ `next_candidate_ids()` ∪ {id : |层(id) − 锚层| ≤ `db.level.info_visible_layers`};锚层=当前节点层,无当前节点(入口停点)=0;层=入口 BFS 深度(与 `level_map_screen._assign_layers` 同源口径);纯函数零状态、断点快照零新增字段——核查:套件可调用且边界断言绿。 -- [ ] 新建 `game/tests/unit/core/level_map_type_vis_test.gd`(extends SceneTree+Kit.check 断言,仿 curio_refresh_paid_test 样式;断言 desc 尾缀挂 §7.1 对照表:①⑤→〔fv1〕、②→〔fv4〕、③→〔fv3〕、④⑦→〔fv7〕、⑥→〔fv6〕),七组断言:① 层距 N 内可见/N+1 不可见(白盒注入 level_row+停点态,仿 smoke_all ⑫ 白盒先例);② 候选恒显(夹具含跨层跳边候选——候选层距恰 N+1 仍显);③ Boss 恒显(远距 Boss);④ 单圈回雾(已过远节点回雾、visited 不豁免);⑤ 入口停点锚层 0+**单链退化形态**(L1 现役无 `next` 键图上层距判定同成立——出边按 `_out_ids` 数组顺序退化口径);⑥ N 读表(改 `db.level.info_visible_layers` 为 1/3 → 可见窗随动;N ≥ 全图层高 → 全部非豁免节点可见)+越域 validate 判 domain 红;⑦ 续玩重建同值(`start_level_external` resume_state 重建停点后 `type_visible_ids()` 与同停点直入路径逐位一致)——核查:套件退出码 0。 -- [ ] `run_all.gd` `_suites()` 增一行 `{"path": "res://tests/unit/core/level_map_type_vis_test.gd", "expect": 0}`——核查:run_all 套件计数与 manifest 条目数一致。 -- [ ] 变异验证:把层距判定 `<= N` 改成 `< N` 跑该套件见边界断言红 → `git checkout` 精确还原 → 记录进实现报告变异表(注入形态/闸/红输出/还原结论)。 - -### T2 雾显隐呈现接线(≈1–1.5d) - -**接口声明**——取用:T1 的 `type_visible_ids()`。产出:`LevelMapScreen.node_display(node, nid, type_vis, is_current, is_candidate) -> Dictionary`(static 纯函数)+`LevelMapScreen.display_probe() -> Dictionary`。 - -- [ ] `level_map_screen.gd` 新增 `static func node_display(node: Dictionary, nid: int, type_vis: Array, is_current: bool, is_candidate: bool) -> Dictionary`——返回 `{"draw_icon": bool, "draw_label": bool, "label_text": String, "boss_border": bool}`;语义钉死:`boss_border = (type == "boss")`;Boss 节点 icon/label 恒 true;非 Boss 节点 `draw_icon = draw_label = type_vis.has(nid)`;`label_text`=现役文案规则(当前位「当前位置」/候选「<类型名> · 可选」/余「<类型名>」)——核查:纯函数单测可直调。 -- [ ] `_draw_graph` 消费 `node_display`(每停点一次取用 `type_vis = _runner.type_visible_ids()`;图标/字形 `:467-475`、类型文字 `:482-489`、Boss 描边 `:457-461` 三处改读决策面输出);结构通道(方块态色/编号/连线)零改动——核查:现役图渲染冒烟不红。 -- [ ] `level_map_screen.gd` 新增 `func display_probe() -> Dictionary`(id → `node_display` 快照,只读断言面,仿 `canvas_probe` 先例)——核查:探针可调用。 -- [ ] 新建 `game/tests/unit/presentation/level_map_info_fog_test.gd`(断言 desc 尾缀挂 §7.1 对照表:①④→〔fv2〕、②→〔fv3〕、③→〔fv5〕、大图组→〔fv8〕),四组断言:① 显隐(雾下节点 draw_icon=false 且 draw_label=false,boss_border=false;可见节点全 true);② Boss 豁免+多 Boss 标记(双 Boss 夹具:两节点 boss_border=true 且均在 type_vis);③ 详情不显示(夹具节点额外携带内容键如 `enemy_id/reward_id`,断言 label_text 不含其值且决策面输出与不带内容键的同型节点逐键相等);④ label_text 文案三态(当前位置/· 可选/类型名)——核查:套件退出码 0。 -- [ ] `run_all.gd` 注册该套件(expect 0)——核查:manifest 计数一致。 -- [ ] 变异验证两发:① 雾下 `draw_icon` 强制 true → ①断言红;② label_text 拼接 `node.get("enemy_id")` → ③断言红;逐发「注入→最窄闸见红→checkout 还原→记录」。 - -### T3 画布自适应接线与断言(≈1d) - -**接口声明**——取用:无新接口(断言面;大图夹具自建 stub runner)。产出:无新接口(探针常数锚同源化)。 - -- [ ] `ui_input_probe.gd:98-99` 常数锚去手抄数字,改引 `level_map_screen.gd` 导出常量(`LAYER_BASE_X`/`LAYER_STEP_X`/`NODE_HALF`)——核查:探针绿且 `need_x = LAYER_BASE_X + maxl×LAYER_STEP_X + NODE_HALF.x + 8` 与屏内 `_fit_canvas` 公式逐项同源。 -- [ ] `level_map_info_fog_test.gd` 增大图夹具断言组:合成 11 层×6 槽含双 Boss 图(stub runner 供 `node_out_ids`/`node_id_of`),断言 `canvas_probe()["min_size"].x ≥ 70+最大层×122+NODE_HALF.x+8`、`min_size.y ≥ 52+最大槽×58+NODE_HALF.y+24`,且 `layout_probe` 全节点位置落在画布矩形内(routebug 83c11a1 同类回归)——核查:断言绿。 -- [ ] 变异验证:`_fit_canvas` 宽公式去 `NODE_HALF.x` 项 → 大图断言红 → `git checkout` 还原 → 记录。 - -### T4 冒烟补断言+变异汇总(≈1–1.5d) - -**接口声明**——取用:T1 `type_visible_ids()`、T2 `display_probe()`(真图消费面——补上探针的实机调用方)。产出:无新接口。 - -- [ ] `smoke_all.gd` `_smoke_level_graph` 段(:4552 起)末增真图可见性断言组(纯核心面,无需场景):L2 图入口停点 `type_visible_ids()` ⊇ `next_candidate_ids()`、boss id ∈ 集合、层距 > N 的非豁免 id ∉ 集合(N 取 `db.level.info_visible_layers`)——核查:冒烟绿。 -- [ ] `ui_input_probe.gd` 增 case⑱(图上可见性接线回归,挂在 ⑫ 图上命中之前的入口停点处):经 `ro.display_probe()` 断言真图雾下节点 draw_icon=false、Boss 节点 boss_border=true、候选节点 draw_icon=true;并以 push_input 点击一个雾下非候选节点,断言零提交(选路态不变——雾不扩大可点域,候选集即合法集纪律不破)——核查:探针绿。 -- [ ] T1–T3 变异验证记录表成文(每条新断言:注入实验/跑的闸/红输出/还原结论)进实现报告——核查:记录表覆盖全部新增断言、零「未证」条目。 -- [ ] 里程碑步出口跑一次代码域闸全套(冒烟+单元+探针+渲染/静态)+改前改后读数对拍——核查:全绿+对拍记录在案;**渲染闸含 shot_probe level 屏截图+shot_checker A-D 判据(屏级骨架/文字对比度/明度三档带),雾显隐后仍须全绿**;卡内修复只做出红最小单元的最窄确认。 - -### T5 产出物落位卡(≈0.5d,末卡——三份 `reports/` 文件写齐+独立验收审计通过才算收口) - -- [ ] `reports/iter-实现报告-<完成日>.md`:各卡状态+变异验证记录表+**实际改动—验收对照表**(§7.1 需求侧表的执行对账,另加「结果」格)+**实机目检总清单**(观测项三条:雾下可读性观感/多终点图 Boss 标记观感/大图完整可见观感——登记不阻塞,验收时间由用户自行安排)+遗留读数义务。 -- [ ] `reports/iter-代拍板追认单-<完成日>.md`:§9 白名单内代拍项留痕(provisional N=2、API 命名等)。 -- [ ] `reports/iter-反哺点-<完成日>.md`:§5 每条一落点(含呈报项「雾的正式视觉规格」+「超预算图策略」升级路径)。 -- [ ] 合并前置:独立验收审计(§7.1 末段声明)完成且报告 `reports/iter-验收审计-<完成日>.md` 逐行「通过」——未通过不得合并,缺漏项回炉对应 T 卡。 - -**估时合计 ≈4.5–6d**。切分预案:T1/T2 可切(核心出口先落、呈现接线后落);T3 独立可切;T4/T5 须连跑——建议单批跑完。 - -## 7. 验证闸(逐需求点验收清单) - -| # | 需求点 | 测什么(断言内容) | 落点 | 变异注入实验 | -|---|---|---|---|---| -| V1 | 邻近 N 层见类型 | 层距 ≤ N 的 id ∈ `type_visible_ids()`、层距 N+1 的非豁免 id ∉;入口停点锚层 0 | `level_map_type_vis_test` ①⑤ | 判定 `<=N` 改 ` 各新增断言 desc 统一尾缀〔fv#〕(本表「验收测试」列可 grep 定位);撤销/变异证明逐条对应 §7 变异注入实验栏与 T1–T4 变异步(每张任务卡至少一条,test-conventions §9.4)。 - -| 需求点 | 改动(文件:行/行为) | 验收测试(名称+文件:行+尾缀) | 层级 | 真实入口 | 撤销或变异证明 | -|---|---|---|---|---|---| -| fv1 邻近 N 层见类型 | `game/core/level_runner.gd` 新增 `type_visible_ids()`(层距判定) | type_vis ①层距边界+⑤入口锚/单链退化〔fv1〕 `tests/unit/core/level_map_type_vis_test.gd` | 单元 | `LevelRunner.type_visible_ids()` 直调 | 变异:`<=N` 改 `-验收审计-<完成日>.md`(逐行「通过/缺漏/例外及依据」)。**审计未通过不得合并**(T5 合并前置)。 - -## 8. 异常分级 - -- **L1(自救)**:断言写法、命名、探针字段名、测试夹具规模微调。 -- **L2(记录继续)**:雾下编号保留/标签行占位的绘制细节、label_text 措辞微调(4 字上限内)、单测夹具的图形态选择。 -- **L3(停机呈报)**:任何触碰冻结视觉件的诉求(雾画法/灰化遮罩/缩放/滚动/线宽/色值/形制);N < 1 或改调参表语义;候选被雾遮(决策锚破);把生成器/行进/敌人表改动混入本卡;`type_visible_ids` 需要持久化状态(违反纯函数口径);等比缩放/滚动被要求时须用户裁(契约 6)。 - -## 9. 代拍板白名单(超清单必呈报) - -1. provisional N=**2**(约束 int ≥ 1;依据:N≥1 是 GDD 硬下限,2=越过下一跳再看一层供岔路两跳规划,再多雾语义弱化;定值归定值批)。 -2. API/探针命名(`info_visible_layers`/`type_visible_ids`/`node_display`/`display_probe`)——约束:**禁 `fog_` 前缀**(与战斗棋盘「视野迷雾」撞词,code-conventions §2.2 跨层标识符语义单一)。 -3. 雾下节点编号保留、类型文字隐藏的具体落点写法(约束:结构通道零改动)。 -4. 大图断言夹具规模(约束:≥ 10 层 × ≥ 5 槽、含双 Boss、含跨层跳边)。 -5. `ui_input_probe` 常数锚同源化方式(内联引用 vs preload 常量——约束:两侧同源可核查、禁再手抄数字)。 -6. 提交切分与 worktree 分支命名。 - -## 10. 风险与异常处置(已知风险,不许绕过) - -⚠️ **风险 1 · level-map 视觉终稿已冻结(2026-09-28 样张 v1 闸形 A)**:雾的**画法**(视觉规格)动冻结件须用户裁。本卡只做可见性语义的最小呈现(沿用现役明暗/显隐语言,契约 4),「雾的正式视觉规格」(雾纹理/灰化遮罩/明度层)列进 §5 同步面+T5 呈报项,**禁自行重开冻结件**。若实现期发现显隐语义在实机上不可读,登记进实机目检清单呈报,禁临时加视觉件。 - -⚠️ **风险 2 · 图超屏预算**:完整可见 AC(level-map.md:197)冻结,若卡①生成图超出公式包络屏预算(1280×800 下约 10 层 × 8 槽),参数限图是不动冻结件的唯一兑现路径(契约 6);若定值批需要更大图,等比缩放/滚动视口两案均动冻结件 → 走呈报由用户裁(T5 反哺点登记升级路径)。 - -⚠️ **风险 3 · 术语撞词**:「信息迷雾」(本卡,关卡节点图类型可见性)vs「视野迷雾」(战斗棋盘,board_view/board_cell_unit 在役)——代码命名禁 `fog_` 前缀(代拍板 2),文档侧入术语表反哺点。 - -## 11. 待裁点 - -**零待裁点,开工门 = U0。** - -灰色地带均已在卡内定值并写明依据,经 grilling 设计树对抗复核后维持: - -| # | 灰色地带 | 定值 | 依据(可推导) | 淘汰案 | -|---|---|---|---|---| -| G1 | 「邻近 N 层」度量 | \|入口 BFS 层(node) − 层(锚)\| ≤ N | 调参表量纲「可见距离(层)」+地图以层列组织(LAYER_STEP_X=层间步距) | 跳数距离(量纲不符);node_depth 差(node_depth=寻址 id 非布局层,L2 图 node 7 深度 7/层 3) | -| G2 | 候选可见性 | 候选集强制豁免 | 生成.md:83「下一跳必在可见范围,是决策的可见锚」是语义承诺,直接兑现 | 依赖图形态保证(层跳边反例可破坏) | -| G3 | 已过节点回雾 | 单圈、零记忆 | GDD 三层表无「已见例外」+「单圈雾」口径明示可见性只依赖当前位置;已过节点不可再达(无回头路),回雾零决策损失 | 已见恒显(累积揭示,非单圈语义) | -| G4 | 显隐 or 灰化 | 显隐(类型图标+类型文字不绘制) | 用户范围注「沿用现役明暗/显隐语言」+「不见类型」语义=类型通道不出现;灰化仍泄类型形 | 灰化遮罩(属雾的正式视觉规格=冻结件域,呈报项) | -| G5 | N 落位与取值 | LevelTable 表级字段,provisional 2 | GDD「本系统自有参数一项」单参数+AdventureTable.clear_heal_pct 表级先例;2=越过下一跳一层前瞻 | 逐关行字段(无逐关设计需求);硬编码(违反改表即改玩法) | -| G6 | 超屏图策略 | 参数限图(生成参数档背书包络 ≤ 屏预算) | 完整可见 AC 冻结+「禁自行重开冻结件」⇒ 不动冻结件的唯一路径 | 等比缩放(动「20px 烘焙 1:1」「2/3/4px 折线」冻结值);滚动视口(新交互范式)——两案均须用户裁,列呈报升级路径 | -| G7 | 多终点/多入口校验放宽与层语义归属 | 归卡①(生成域规则语义);本卡层口径按现役唯一入口实现(level_table.gd structural 拦截第二无入边节点),多入口层语义随卡①产出规格定、经反哺点随动 | 关卡节点地图.md:14「图合法性规则语义以关卡节点图生成产出规格为准」;本卡呈现面已多 Boss 通用(F7);现役数据与校验均单入口 | 本卡顺带放宽校验或预设多入口层算法(越界卡①域,违反契约 8) | -| G8 | Boss 标记口径(F9 文档冲突) | 实现随现役代码+level-map.md(紫赤+深墨环) | 视觉终稿冻结在案(样张 v1)=实况权威;文档批核对走反哺点 | 按关卡节点地图.md:67「封印黑」改色(动冻结件且与样张冲突) | diff --git a/reports/需求卡片-敌人表深度带换代批-2026-10-21.md b/reports/需求卡片-敌人表深度带换代批-2026-10-21.md deleted file mode 100644 index 9d9c63ca..00000000 --- a/reports/需求卡片-敌人表深度带换代批-2026-10-21.md +++ /dev/null @@ -1,313 +0,0 @@ -# 需求卡片:敌人表深度带换代批(坐标寻址 → 深度带寻址)· 关卡节点图重构卡③ - -- 版本:**v1.0**(2026-10-21 成文;自审五查+grilling 复核结论见 §11) -- 来源:[待办清单](../待办清单.md)「关卡节点图重构——可选节点太少」(2026-10-13 登记,来源=playnote,设计面=文档轨,状态=文档设计已闭合)(唯一事实源:[关卡节点图生成](../design/gdd/systems/冒险循环/关卡节点图生成.md) v1.1+[关卡节点地图](../design/gdd/systems/冒险循环/关卡节点地图.md) v2.1,2026-10-21 双定稿闭合凭据) -- 归属:敌人系统数据面与遭遇寻址链(`game/data/schemas/enemy_table.gd`+`game/data/tables/enemy.tres`+`game/core/config_db_resolver.gd`);关卡节点图重构批卡③(卡①生成器/卡②地图行进/卡④迷雾同批) -- 排期:未编入(2026-10-18 用户令:需求卡片不预占迭代号,批次归属按工作量另裁) -- 开工门:U0(用户 `/iter` 发令)+ grilling 复核门过(零待裁点,见 §11) - -## 0. 前置依赖与并行性 - -- **设计闭合(第〇步)**:06 条目「关卡节点图重构——可选节点太少」状态=文档设计已闭合,凭据=关卡节点图生成.md v1.1+关卡节点地图.md v2.1(各带路径+版本号)→ 放行写卡。 -- 本卡**不依赖**卡①(生成器)/卡②(地图行进)的实现:迁移期带切法=旧 ceil 等价切法(§4 契约 2),对现行 `level.tres` 模板逐位零行为变化,可独立交付独立验收。 -- 本卡**向卡① 输出**推论条款 A(多终点深度互异,§4 契约 6)——「Boss 行按终点配置、多终点各配一行(走哪条路决定打谁)」在定位信息只有两样时的前提条件,归卡①产出规格兑现,落文走反哺点(§6 ③)。 -- 与卡② 的接口零改动:定位信息契约=(关卡序号 + 节点深度) 两样(关卡节点地图.md:119),本卡只换消费侧寻址,不动传递侧。 - -## 1. 目标与完成定义 - -**目标**:遭遇寻址从「(关卡序号 × 节点深度) 点坐标+向上取整兜底」换代为「(关卡序号 × 深度带) 带寻址」——深度带=节点深度的区间,配池按带不按点,难度坡随带递增;Boss 行按终点配置、多终点各配行集(走哪条路打谁)。敌人表 20 行数据随寻址同步换键,行集构成纪律与加载期校验清单随带寻址换代表述。 - -**相对现状,新增了什么**: -1. 表键换代:`(level_index, node_depth, enemy_id)` → `(level_index, row_kind, depth_band, enemy_id)`——`depth_band`(深度带键)替代 `node_depth`,新列 `row_kind ∈ {"battle","boss"}` 承载「Boss 行按终点配置」; -2. 带寻址单点:`EnemyTable.band_of`(带切法静态纯函数)+`ConfigDbResolver.resolve_enemy_rowset(L, D, row_kind)` 签名换代; -3. 多 Boss 各配行集的 schema 与校验(同关 Boss 带键互异、每关 Boss 行集 ≥1、跨表校验多终点带互异); -4. 首遇教学位的带下定位方式(首遇带=该敌种该关最低带;首遇行固定数量不加骰); -5. 冒烟断言面与单测面的坐标换代(§8 S 清单)。 - -**完成定义**(全部满足才算本批完成): -1. `enemy.tres` 20 行按 §4.2 迁移表完成键迁移,且逐行逐字段与迁移前对拍相等(数值零变更,数值只在 `data/tables`); -2. `EnemyTable.validate()` 对迁移后生产表零错误;加载期拒绝清单换代后旧类别不失守(§4 契约 7); -3. 带寻址单点成立:全仓遭遇行集解析只经 `resolve_enemy_rowset(L, D, row_kind)`,带切法只有 `EnemyTable.band_of` 一份实现; -4. 生产路径行为零变化:现行三关模板任意节点开战,生成行集与迁移前逐位一致(同种子同遭遇逐位复现由既有回放面承接); -5. 多 Boss 行集能力就位(schema+校验+跨表互异断言绿),且三关现有单终点 Boss 行迁移后仍各就其位; -6. 首遇教学位带下定位断言绿:L2 巨蜘蛛首遇带行集={giant_spider} 恰一行、`unit_count=2` 且无 `unit_count_max`(固定 2 只不加骰逐字保持); -7. §8 冒烟断言面随动清单逐条换代完毕、全绿;变异验证记录表进实现报告; -8. 批末重闸按改动域选档全绿+改前改后读数对拍;三份 `reports/` 产出物写齐(T4)。 - -## 2. 设计事实源 - -| # | 出处 | 取用条款 | -|---|---|---| -| D1 | `design/gdd/systems/冒险循环/关卡节点图生成.md` v1.1(2026-10-21,06 闭合凭据之一) | 依赖与输出表敌人系统行(:96):「战斗节点遭遇按深度带配池,遭遇坐标=关卡序号+深度带;多终点各配 Boss 行」;内容归 owner(:86)「战斗节点打谁=敌人系统按深度带配池」 | -| D2 | `design/gdd/systems/冒险循环/关卡节点地图.md` v2.1(2026-10-21,06 闭合凭据之一) | :65「遭遇坐标=关卡序号+节点深度,敌人表按**深度带**(深度区间)配池」+「终点恒在各路径最深处」;:119「定位信息只有两样:关卡序号 + 节点深度。战斗侧按深度带配池查表」 | -| D3 | `design/gdd/systems/战斗循环/敌人系统.md`(状态:已定稿) | 开战生成节(:67)「遭遇坐标(关卡序号 + 深度带——节点深度所在的区间)」;行集构成纪律行(:74)「敌人表按(关卡序号 × 深度带)存放;深度带=节点深度的区间——逐局生成使单点深度不再固定,配池按带不按点,难度坡随带递增……Boss 行按终点配置,多终点各配一行(走哪条路决定打谁)。纪律三条……」;调参表敌人表行(:229);hobgoblin 缺口登记(:81);验收标准(:269/:278) | - -闭合凭据一致性:D1/D2 与 06 条目状态内列的两份定稿逐字一致;D3 为敌人面语义源(开战生成+行集构成纪律),与 D1/D2 同向。 - -## 3. 现状事实(2026-10-21 worktree 实查;开工日 T0 复核行号) - -| # | 事实 | 出处 | -|---|---|---| -| F1 | 敌人表按 (level_index, node_depth, enemy_id) 逐坐标存放、行集可多行混编——schema 自述「逐 (level_index, node_depth, enemy_id) 行集的类型化读取」+「行序即契约:同坐标多行必须文件内相邻」 | `game/data/schemas/enemy_table.gd:2-3`;首行键实样 `game/data/tables/enemy.tres:7-10` | -| F2 | 按坐标取行集的代码=`ConfigDbResolver.resolve_enemy_rowset(L, D)`(ceil 语义:命中坐标返回全部行、按表文件行序;无精确键则向上取整保证偏难、越顶 clamp 取最大键+警告四元组去重);门面与消费面三处 | `game/core/config_db_resolver.gd:33-37`/:54-110(`_resolve_progress`)/:114-118(`_ceil_key`);门面 `game/core/config_db.gd:193-194`;消费面 `game/core/unit_container.gd:43`、`game/core/battle_orchestrator.gd:327`、`game/presentation/battle_narrator.gd:76-78` | -| F3 | 敌人表现状 20 行=L1 五坐标((1,0)goblin/(1,1)goblin/(1,2)bugbear/(1,3)hobgoblin/(1,4)ogre_chief Boss)+L2 八行七坐标((2,0)(2,1)bugbear/(2,4)giant_spider/(2,5)bugbear+giant_spider 混编双行/(2,6)(2,7)giant_spider/(2,9)drider Boss)+L3 七坐标((3,0)duergar/(3,1)(3,4)(3,6)hook_horror/(3,5)(3,7)duergar/(3,9)duergar_king Boss);Boss 行每关恰一行、坐标=各关最深节点 | `game/data/tables/enemy.tres:7-505`(行起点 :8/:29/:50/:73/:97/:124/:147/:171/:194/:217/:244/:271/:298/:328/:354/:377/:401/:427/:451/:478) | -| F4 | hobgoblin 缺口行:(1,3)「大地精」行在表在役(unit_count 2 / unit_count_max 3 / hp 14),缺口登记=「无立绘、不在本敌种表——补齐归敌种内容批(立绘+语义模板+敌种表行三件套)」 | `game/data/tables/enemy.tres:73-96`;`design/gdd/systems/战斗循环/敌人系统.md:81` | -| F5 | 首遇教学位读表与断言面:L2 巨蜘蛛 (2,4) 行 `unit_count=2` 且无 `unit_count_max`(不加骰由「行有 unit_count_max 才掷骰」机制承载);GDD 定位=「L2 首遇教学位(固定 2 只——首遇位不加骰)」;断言三处=L1 D2 熊地精固定 1、(2,4) 巨蜘蛛恰一行固定 2、(3,0) 灰矮人固定 1 | 行值 `enemy.tres:171-192`;GDD `敌人系统.md:88`;机制 `game/core/battle_orchestrator.gd:316-346`(有 unit_count_max 才入 encounter 流掷骰);断言 `game/smoke/smoke_all.gd:3406-3411`/:4692-4697/:4747-4752 | -| F6 | 混编行集与行序契约:(2,5) 双行(bugbear 重击手→giant_spider 巢群);同坐标多行必须文件内相邻(加载期 `rowset_rule` 拦截);生成序=表文件行序(逐行实例化);叙述取首行(boss_name 取 rowset[0]);行集实例总数 ≤4(`ROWSET_INSTANCE_MAX`,spawn 期守卫) | 行值 `enemy.tres:194-241`;校验 `enemy_table.gd:121-130`;生成 `game/core/unit_container.gd:85-120`;叙述 `battle_narrator.gd:68-79`;守卫 `enemy_table.gd:29`+`unit_container.gd:81-84` | -| F7 | 表校验加载期拒绝清单(`EnemyTable.validate()` 本表侧)=empty_table/dup_key(键含 enemy_id)/domain(L≥1、D≥0、unit_count、hp、atk、pool 非空、权重、armor_class)/cross_field(unit_count_max 区间、atk_min/max 成对+中点恒等)/enum(armor_type、attack_type)/rowset_rule(同坐标相邻)/anchor(每关 depth-0 锚行);跨表侧=④ 战斗/Boss 节点 (L,D) 在 board_gen 与 enemy 双表精确行(缺行加载致命)+⑤ 技能池悬空/池构成纪律 | `enemy_table.gd:32-135`;`game/core/config_db_cross_validator.gd:54-85`(④)/:86-90+:152-190(⑤) | -| F8 | 定位信息契约=(关卡序号 + 节点深度) 两样(图侧组装移交战斗结算);enc 已随行携带 `node_type`(battle/boss/…),现仅消费于变异池门控与叙述,未参与敌人行集寻址 | `design/gdd/systems/冒险循环/关卡节点地图.md:23/:111/:119`;`game/core/level_runner.gd:467-482`(begin_battle 组装) | -| F9 | 既有解析单点纪律在案:「进度键解析单点收口(全仓统走 resolve_enemy_rowset ceil 版……禁双算法并存〔状态记录 312〕)」 | `enemy_table.gd:138-140` | -| F10 | 改前读数基线=开工日 T0 采集(冒烟/单测通过数对拍面)——写卡会话不跑测(测试执行两入口铁规),本卡不预写数字 | — | - -## 4. 设计契约(红线,违反 = L3 停机呈报) - -🔴 **契约 1 · 寻址换代与表键**:遭遇寻址=(关卡序号, 节点深度) 入 → (关卡序号, row_kind, depth_band) 命中;敌人表键=`(level_index, row_kind, depth_band, enemy_id)`。`row_kind ∈ {"battle","boss"}`(对齐节点 type 词表),`depth_band`=深度带键(int ≥ 0,带=节点深度的区间)。行类列是「Boss 行按终点配置」的表侧表达:战斗节点与终点同深度时两行集不串位,同关多 Boss 各占自己的带键。 - -🔴 **契约 2 · 迁移期行为零变化**:迁移期带切法取**旧 ceil 等价切法**(带键=旧 node_depth 值、请求落带=旧 ceil 命中键、越顶 clamp 顶带+警告去重沿 R1)——生产路径(level_runner 组装的遭遇)迁移前后生成行集逐位一致。数值单一事实源:迁移后数值只进 `data/tables`,20 行数值字段逐字段零变更,禁任何字面量改写。 - -🔴 **契约 3 · 带切法单点**:带切法唯一实现=`EnemyTable.band_of(band_keys: Array, D: int) -> int`(静态纯函数,签名与算法见 §7 接口块);`ConfigDbResolver` 与 `ConfigDbCrossValidator` 共用它,禁双算法并存(F9 状态记录 312 同源口径)。带的区间划分(切法粗细)属实现细节,但两语义不可破:D<0 → fatal `request_oob`(沿用)、D 高于该 (L,row_kind) 顶带 → clamp 顶带+warning(类别沿用 `resolve_depth_clamp`、四元组去重沿用)。 - -🔴 **契约 4 · 行集构成纪律带键新表述**(三条纪律在带寻址下不破):① 行集内 enemy_id 唯一(同一敌种在同一 (L,row_kind,depth_band) 行集仍只许一行);② 同带键多行必须表文件内相邻,行序=声明序=生成序(行序即契约——resolver 返回序/生成序/叙述取首行全依赖文件行序);③ 行集实例总数(各行骰后数量求和)≤ 4,单行数量域 [1,3] 不变。违规加载期返回错误并止动。 - -🔴 **契约 5 · 多 Boss 各配行集**:Boss 行按终点配置、多终点各配一行集(行集可多行=Boss+护卫混编,既有 P4 乙口径不破;同行集双 Boss 敌种属合法混编形态,内容裁量归难度曲线);同关多 Boss 行集带键互异、禁两终点共带(共带=两终点命中同一 Boss 行集,「走哪条路决定打谁」落空)。Boss 行集每关 ≥1。表侧投影=每关 boss 行集 ≥1(加载期);图侧投影=同关多 boss 节点解析带键互异(跨表校验,T2)。 - -🔴 **契约 6 · 推论条款 A:多终点深度互异**:定位信息只有 (关卡序号 + 节点深度) 两样(D2:119)且「多终点各配一行(走哪条路决定打谁)」(D3:74)⇒ 终点身份只能由节点深度区分 ⇒ **多终点必须落在互异深度带**(同深度多终点在现行定位信息下不可区分,属设计不可能态)。推论依据=上述两条款的逻辑合取(无第三通道:扩定位信息=改 D2 契约,归卡②/文档批,不在本卡)。表侧投影=契约 5 带键互异校验;图侧兑现=卡①产出规格(落文走反哺点 §6 ③)。执行中发现同深度多终点图样 → L3 呈报。 - -🔴 **契约 7 · 加载期拒绝清单换代全兜底**:旧类别(empty_table/dup_key/domain/cross_field/enum/rowset_rule/anchor)一个不失守,键面随契约 1 换代;新增:row_kind 枚举封闭(非法值拒)、每关 Boss 行集 ≥1、(跨表侧)boss 节点带互异+节点深度禁顶 clamp 消解(D 高于该 (L,row_kind) 顶带键=加载致命,替代旧「精确行」严格性——带内命中是设计语义、顶 clamp 是调参事故,分界就在这条)。board_gen 半边精确行校验不动(§5)。 - -🔴 **契约 8 · 首遇教学位语义不破**:新敌种首遇带行固定数量不加骰(无 `unit_count_max`);L2 巨蜘蛛首遇带行 `unit_count=2` 逐字保持。首遇带定位方式=数据驱动:该 (L, battle, enemy_id) 的最低 `depth_band` 行集(不写死坐标数字)。 - -🔴 **契约 9 · hobgoblin 缺口行不静默处置**:数据去向=随迁带键、行值零变更、留任在役;缺口登记(无立绘/不在敌种表)随行携带,补齐三件套(立绘+语义模板+敌种表行)归敌种内容批。禁借迁移删行、改行或补立绘(内容面归敌种内容批,本卡只定数据去向)。 - -### 4.2 数据迁移规则(20 行去向,逐行可核) - -键迁移通则:`node_depth` 值照搬为 `depth_band` 值(迁移期带键=旧深度键,契约 2);`row_kind`="boss" 仅三行(旧坐标为 Boss 节点行者),其余 "battle";`enemy_id` 与全部数值/池字段逐字段零变更;文件内行序不变(行序即契约)。 - -| 旧键 (L, D, eid) | 新键 (L, row_kind, band, eid) | 备注 | -|---|---|---| -| (1,0,goblin) (1,1,goblin) (1,2,bugbear) | (1,battle,0/1/2,同 eid) | (1,2)=bugbear 首遇带行(固定 1 不加骰,F5) | -| (1,3,hobgoblin) | (1,battle,3,hobgoblin) | **hobgoblin 缺口行:留任随迁(契约 9)** | -| (1,4,ogre_chief) | (1,boss,4,ogre_chief) | L1 单终点 Boss 行 | -| (2,0,bugbear) (2,1,bugbear) | (2,battle,0/1,同 eid) | | -| (2,4,giant_spider) | (2,battle,4,giant_spider) | 巨蜘蛛首遇带行(固定 2 不加骰,契约 8) | -| (2,5,bugbear) (2,5,giant_spider) | (2,battle,5,同 eid) | 混编双行保持相邻、行序不变(契约 4②) | -| (2,6,giant_spider) (2,7,giant_spider) | (2,battle,6/7,同 eid) | | -| (2,9,drider) | (2,boss,9,drider) | L2 单终点 Boss 行(多终点时各配行集归后续内容投放) | -| (3,0,duergar) (3,1,hook_horror) | (3,battle,0/1,同 eid) | (3,0)=duergar 首遇带(固定 1);(3,1)=hook_horror 首遇带(固定 2) | -| (3,4,hook_horror) (3,5,duergar) (3,6,hook_horror) (3,7,duergar) | (3,battle,4/5/6/7,同 eid) | | -| (3,9,duergar_king) | (3,boss,9,duergar_king) | L3 单终点 Boss 行 | - -行数核对:battle 行 17+boss 行 3=20;迁移后 dup_key(新键)零命中、anchor(battle band 0)三关各一、boss 行集三关各一。 - -## 5. 范围边界 - -**做**:遭遇寻址换代(带切法单点+resolver 签名);敌人表 20 行键迁移(§4.2);表 schema 与加载期校验清单换代;行集构成纪律带键新表述;多 Boss 各配行集的 schema/校验能力(数据投放归后续内容面);首遇教学位带下定位;冒烟断言面与单测面随动(§8 S 清单);反哺点清单。 - -**不做**(明示去向): -- 生成器(节点图怎么长、多终点怎么切)→ **卡①**;推论条款 A 的产出规格落文 → 反哺点③,文档批落; -- 地图行进与定位信息传递((关卡序号+节点深度) 契约本体)→ **卡②**,本卡零改动; -- 迷雾与「走哪条=打谁」的呈现 → **卡④**; -- 敌种新内容:hobgoblin 补齐(立绘+语义模板+敌种表行)→ **敌种内容批**;本卡只定数据去向(契约 9),不补立绘不删行; -- `board_gen.tres`/`difficulty.tres` 的键带化(两表仍按 (level_index, node_depth) 点键+既有解析语义,`config_db_cross_validator.gd:54-85` 的 board_gen 半边精确行校验不动)——生成图深度扩面后两表的覆盖问题归卡①/后续表批登记,本卡不扩面; -- 行值投值与难度坡数值(池权重/hp/atk/AC)→ 难度曲线与Boss(数值单一事实源=`data/tables`,本卡零数值); -- 带切法未来粗化(带合并/区间调整)的具体切法——实现细节(契约 3 两语义不破即可),本卡迁移期钉旧 ceil 等价切法。 - -## 6. 关联文档同步面 - -> 本批是代码实现批,禁写 `design/` 整目录与根规则文件,唯一可写目录=`reports/`。下表「同步义务」一律执行为:逐条列进 `reports/iter-反哺点-<完成日>.md`(哪个文件哪一节、改成什么、依据),用户会话裁决后归文档批落文。 - -| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 | -|---|---|---| -| `design/gdd/systems/战斗循环/敌人系统.md` | :81 hobgoblin 缺口登记的坐标记法「(1,3),即第一关第四节点」→ 带键记法「(1, battle, 3)」(数据留任语义不变);:278 表校验行「行集内同敌种第二行 / 同坐标多行不相邻」→「同带键多行不相邻」措辞随键换代 | 反哺点 · 列清单(①记法与措辞换代,依据=本卡契约 1/4) | -| `design/gdd/systems/冒险循环/关卡节点地图.md` | :146「本文递出关卡序号 + 节点编号,按编号生成单位归它」与 :119「关卡序号 + 节点深度……按深度带配池」两处表述不一致 → 统一为「关卡序号+节点深度;敌人侧按深度带配池生成单位」 | 反哺点 · 列清单(②用词统一,依据=:65/:119 既有定稿句) | -| `design/gdd/systems/冒险循环/关卡节点图生成.md` | 产出规格缺「多终点深度互异」条款——本卡推论条款 A(契约 6)的图侧兑现处 | 反哺点 · 列清单(③产出规格补条款:多终点落在互异深度带;依据=D2:119+D3:74 合取) | -| `待办清单.md`(06 登记处) | 本卡登记条状态推进「已写卡(`reports/需求卡片-敌人表深度带换代批-2026-10-21.md`)」(req-card 06 状态回写义务);实现批完成后按退役规则处理 | 反哺点 · 列清单(④状态回写与迭代行编入、条目退役记载——本会话文件面限于本卡一个文件,回写由批次收口/用户发令执行,防四卡并行互踩) | -| `roadmap.md` | 迭代行编入笔与批内状态刷新 | 反哺点 · 列清单(⑤) | -| `game/data/schemas/enemy_table.gd`、`game/data/tables/enemy.tres`、`game/core/config_db_resolver.gd`、`game/core/config_db.gd`、`game/core/unit_container.gd`、`game/core/battle_orchestrator.gd`、`game/core/config_db_cross_validator.gd`、`game/presentation/battle_narrator.gd` | 寻址与表承载改造本体 | 实施本体(可写) | -| `game/smoke/*`、`game/tests/*` | 断言面随动(§8 S 清单) | 实施本体(可写) | - -## 7. 任务卡 - -> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核本卡全部行号。回归措辞模板沿用:里程碑步(T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套。 - -### 卡前 · 文件结构图 - -| 文件 | 职责 | -|---|---| -| `game/data/schemas/enemy_table.gd` | 敌人表 schema:键换代+加载期拒绝清单换代+带切法单点 `band_of` | -| `game/data/tables/enemy.tres` | 敌人表数据:20 行键迁移+表尾迁移登记注释 | -| `game/core/config_db_resolver.gd` | 带寻址解析(L 维沿旧 ceil/clamp、D 维走 `band_of`) | -| `game/core/config_db.gd` | 门面 `resolve_enemy_rowset` 签名随动 | -| `game/core/unit_container.gd` | `spawn` 增 `row_kind` 入参、内部寻址随动 | -| `game/core/battle_orchestrator.gd` | 遭遇骰与 spawn 调用面随动(enc.node_type → row_kind) | -| `game/core/config_db_cross_validator.gd` | ④ 敌侧半边带化+Boss 带互异+顶 clamp 禁消解;board_gen 半边不动 | -| `game/presentation/battle_narrator.gd` | `boss_name` 行集寻址随动 | -| `game/smoke/smoke_all.gd`、`game/smoke/skill_rhythm_probe.gd`、`game/smoke/damage_probe.gd` | 断言面与直呼寻址面随动(§8 S 清单) | -| `game/tests/unit/core/config_db_resolver_test.gd`、`game/tests/unit/data_config/config_db_test.gd`、`game/tests/unit/core/config_db_cross_validator_test.gd` | 带寻址语义单测、夹具键改名、Boss 互异负向用例 | - -### 接口块(全卡共用,后卡引用以此为准) - -- **`EnemyTable.band_of(band_keys: Array, D: int) -> int`**(静态纯函数,带切法单点):`band_keys`=该 (level_index, row_kind) 的 depth_band 键升序数组;返回首个 ≥ D 的键;D 高于全部键 → 返回 -1(resolver 侧 clamp 顶带+warning,校验侧判「顶 clamp 消解」违例);`band_keys` 空 → 返回 -1 且 resolver 侧返回空行集(交消费侧既有「行集解析为空」fatal 路径,`battle_orchestrator.gd:328-330`)。算法体仅此一处(禁第二实现)。 -- **`EnemyTable.ROW_KINDS := ["battle", "boss"]`**(封闭枚举常量)。 -- **`ConfigDbResolver.resolve_enemy_rowset(L: int, D: int, row_kind: String) -> Array[Dictionary]`**:L<1 或 D<0 → `_diag` fatal `request_oob`(沿用);`row_kind` 非法 → `_diag` fatal(类别 `request_oob`);L 维 ceil/clamp 语义沿 `_resolve_progress` 现状;D 维=`band_of` 命中该 (L,row_kind) 带键行集、按表文件行序返回;`band_of` 返回 -1 → 取该 (L,row_kind) 顶带键+warning `resolve_depth_clamp`(四元组去重沿用)。 -- **`ConfigDb.resolve_enemy_rowset(L: int, D: int, row_kind: String) -> Array[Dictionary]`**(门面透传)。 -- **`UnitContainer.spawn(level_index: int, node_depth: int, hero_hp: int, unit_count_overrides: Array = [], atk_override: int = -1, max_hp_override: int = -1, enemy_atk_overrides: Array = [], hero_attack_type: String = "", hero_armor_type: String = "", row_kind: String = "battle") -> bool`**(尾参新增,缺省 "battle")。 -- **`ConfigDbCrossValidator.cross_validate(loaded: Dictionary, push_diag: Callable) -> void`**(签名不变;④ 敌侧判据换代)。 - -### T0 事实坐实与迁移表核对(≈0.5–1d) - -- [ ] 复核 §3 全部 file:line 与 §4.2 迁移表 20 行(逐行对照 `enemy.tres` 实表:键、eid、数值),漂移即订正本卡——可核查结果:订正记录或「零漂移」声明进实现报告素材。 -- [ ] 改前读数基线采集(冒烟/单测通过数,两入口铁规下随 T1 迭代 loop 首跑取值)——可核查结果:基线读数记录在案。 -- [ ] 推论条款 A 与 §6 反哺点点①②③ 条目起草(一节一改一依据)——可核查结果:反哺点草稿段落在 T4 产物成文前就绪。 - -### T1 表 schema 换代+数据迁移+带寻址单点(≈1.5–2d) - -- [ ] 实装 `EnemyTable.ROW_KINDS := ["battle", "boss"]` 封闭枚举常量(落点 `enemy_table.gd`)。可核查结果:常量在位且被 validate 判据引用。 -- [ ] 实装 `EnemyTable.band_of`(签名与语义=接口块;落点 `enemy_table.gd`)。可核查结果:`band_of` 全仓唯一实现(全仓检索零第二份带切法)。 -- [ ] 实装 `validate()` 键换代(`enemy_table.gd:32-135`):dup_key 键串改 `"%d_%s_%d_%s" % [L, row_kind, depth_band, enemy_id]`;domain 增 `row_kind ∈ ROW_KINDS`、`depth_band ≥ 0`(原 D 域判据换代);rowset_rule 键改 `"%d_%s_%d" % [L, row_kind, depth_band]`(相邻语义不变);anchor 改「每关存在 row_kind="battle" 且 depth_band=0 行」+新增「每关存在 row_kind="boss" 行 ≥1」(错误类别沿 `anchor`);其余判据(unit_count/unit_count_max/hp/atk/pool/armor/attack_type/armor_class)零改动。可核查结果:`validate()` 对旧格式夹具报键类错误、对新格式合法夹具零错。 -- [ ] 实装 `enemy.tres` 20 行键迁移(严格按 §4.2 表:depth_band 值=旧 node_depth 值、三行 row_kind="boss"、其余 "battle"、数值/池字段零变更、行序不变)。可核查结果:迁移后 20 行新键与 §4.2 逐行对上,且 `git diff` 仅键列+新增 kind 列、值列零变更(件核=V3)。 -- [ ] 实装 `enemy.tres` 表尾迁移登记注释一段(日期+键换代说明+hobgoblin 留任口径)。可核查结果:注释在位且与 §4.2/契约 9 同口径。 -- [ ] 验收步骤:跑 `godot --headless --path game --script res://tests/unit/data_config/config_db_test.gd`(先按 V2 改造夹具)与冒烟表校验段,期望「EnemyTable validate 零错误」断言绿。 -- [ ] 实装 `ConfigDbResolver.resolve_enemy_rowset(L, D, row_kind)` 换代+`EnemyTable.band_of` 接线(`config_db_resolver.gd:33-37` 重写;`_resolve_progress` 保留给 board_gen 零改动);`config_db.gd:193-194` 门面签名随动。可核查结果:`resolve_enemy_rowset(1, 3, "battle")` 返回 hobgoblin 行集、`resolve_enemy_rowset(1, 4, "boss")` 返回 ogre_chief 行集(夹具面)。 -- [ ] 验收步骤:跑 `godot --headless --path game --script res://tests/unit/core/config_db_resolver_test.gd`(按 V1 换代后),期望带寻址语义五断言全绿(见 §8 V1)。 -- [ ] 变异验证(注入→最窄闸见红→`git checkout` 还原→记录):把 `band_of` 改成「返回首个 ≤ D 的键」(floor 反向)→ 期望 V1「带命中偏难」断言红;把 `validate` 的 row_kind 枚举判据注释掉 → 期望 V2「非法 row_kind 被拒」断言红。记录表进实现报告。 - -### T2 消费面与跨表校验随动(≈1–1.5d) - -- [ ] 实装 `unit_container.gd`:`spawn` 尾参增 `row_kind: String = "battle"`,内部改 `db.resolve_enemy_rowset(level_index, node_depth, row_kind)`(:43),行集为空的报错消息随键换代(:45)。可核查结果:既有 spawn 调用(缺省战斗)零改动可编译,传 "boss" 取 Boss 行集。 -- [ ] 实装 `battle_orchestrator.gd`:`begin_battle` 内取 `var rk := String(enc.get("node_type", "battle"))`(缺省 battle=§10 代拍板③),`erowset_pre`(:327)与 `_enemy_system.spawn`(:355)传 rk。可核查结果:enc 带 `node_type:"boss"` 时遭遇行集为 Boss 行集,缺省时为 battle 行集。 -- [ ] 实装 `battle_narrator.gd` `boss_name`(:76-78):寻址改 `db.resolve_enemy_rowset(int(runner.level_row.level_index), int(node.get("node_depth", -1)), "boss")`。可核查结果:Boss 节点叙述名取 Boss 行集首行 display_name。 -- [ ] 实装 `config_db_cross_validator.gd` ④ 敌侧半边换代(:63-65、:81-85):battle/boss 节点 (L,D) 判据改「(L,row_kind) 行集非空且 `EnemyTable.band_of(该类带键, D) != -1`(-1=顶 clamp 消解,报 `level_node_dangling`)」;新增「同关多 boss 节点解析带键互异(同带报错,类别 `rowset_rule`)」;board_gen 半边(:62、:82-83)零改动。可核查结果:负向夹具(顶 clamp/同带双 boss)各报一行错误。 -- [ ] 验收步骤:跑 `godot --headless --path game --script res://tests/unit/core/config_db_cross_validator_test.gd`(按 V4 改造后),期望既有三用例+新增两负向用例全绿。 -- [ ] 验收步骤:T 段出口跑一次全套闸(`tools/run_all_gates.sh` 按改动域选档,本批改动域=`game/` 代码与数据),期望代码域全绿、既有单测(settle_segments 等零改动面)零红。 -- [ ] 变异验证:删掉「boss 节点带互异」判据 → 期望 V4 同带双 boss 负向用例红;把 ④ 敌侧 `band_of != -1` 判据短路为恒真 → 期望顶 clamp 负向用例红。记录表进实现报告。 - -### T3 冒烟断言面随动+首遇带定位(≈1.5–2d) - -- [ ] 按 §8 S 清单逐条换代 `smoke_all.gd` 直呼面(S1/S3/S4/S5/S16:`resolve_enemy_rowset` 三参化)——可核查结果:清单条目逐条勾销、冒烟该段绿。 -- [ ] 换代首遇教学位断言(S2/S9+契约 8 定位方式):改为数据驱动定位(扫表取该敌种该关最低 depth_band),断言=「L2 巨蜘蛛首遇带行集 = {giant_spider} 恰一行且 unit_count=2 且无 unit_count_max」+「L1 bugbear 首遇带行 unit_count=1 无 unit_count_max」+「L3 duergar 首遇带行 unit_count=1 无 unit_count_max」——可核查结果:三断言绿且不含写死坐标数字。 -- [ ] 换代混编与行序断言(S4):带键 (2,battle,5) 行集=双行、行序 [bugbear, giant_spider]、Σ(unit_count_max 缺省=unit_count) ≤ 4——可核查结果:断言绿。 -- [ ] 换代跨表覆盖与曲线断言(S6/S7):en_keys 键改 (L,row_kind,depth_band) 聚合、Boss 节点查 boss 键;L1 总量曲线断言改按 (1,battle) depth_band 升序相邻带总量比 ≤ 2.5(现值 12/10/22/35/72 口径不变)——可核查结果:断言绿。 -- [ ] 换代毒吐投放面断言(S8):判据改「pool 含 venom_spit 的行 ⇒ enemy_id=="giant_spider" 且 depth_band > 巨蜘蛛首遇带」+「巨蜘蛛首遇带行 pool 恒 {attack:6, bite:2, charge:1}」(去 `>=5` 写死)——可核查结果:断言绿。 -- [ ] 换代 Boss 坐标直呼面补 node_type(S10a:`smoke_all.gd:2022/:3025/:3090/:3177/:3231/:3271/:3301/:3474/:4503/:4933`、`damage_probe.gd:95` 各补 `"node_type": "boss"`)——可核查结果:各段绿、Boss 行集解析正确。 -- [ ] 换代 kind/坐标不一致直呼面(S10b:`smoke_all.gd:2621/:2646` 的 (2,4)+`node_type:"boss"` 改 (2,9)+`node_type:"boss"`——其断言语义「Boss 图回落/确定性」不变,棋盘载体改真 Boss 坐标)——可核查结果:该段绿、消息文本更新为新坐标。 -- [ ] 换代探针直呼面(S14:`skill_rhythm_probe.gd:17`、`damage_probe.gd:269/:420` 三参化)——可核查结果:探针可跑通。 -- [ ] 验收步骤:T 段出口跑一次全套闸,期望冒烟全绿、探针段无红。 -- [ ] 变异验证:给巨蜘蛛首遇带行加 `unit_count_max: 3` → 期望首遇「不加骰」断言红;把混编两行文件内对调 → 期望行序断言红;把 hobgoblin 行迁到错误带键 (1,battle,2) → 期望 V3 键位断言红。记录表进实现报告。 - -### T4 产出物落位卡(≈0.5d,末卡——三份 `reports/` 文件写齐+独立验收审计通过才算收口) - -- [ ] 轻闸全绿后、合并前写齐三份:`reports/iter-实现报告-<完成日>.md`(各卡状态+变异验证记录表+实机目检总清单+遗留读数义务)/`reports/iter-代拍板追认单-<完成日>.md`(§10 白名单内代拍项留痕)/`reports/iter-反哺点-<完成日>.md`(§6 五条每条一落点:①敌人系统.md 记法/措辞、②关卡节点地图.md :146 用词、③关卡节点图生成.md 推论条款 A、④06 状态回写与条目记载、⑤roadmap 编入笔)。可核查结果:三文件在 `reports/` 且 §6 同步面每条有落点。 -- [ ] 合并前置:独立验收审计(§8.2 末段声明)完成且报告 `reports/iter-验收审计-<完成日>.md` 逐行「通过」——未通过不得合并,缺漏项回炉对应 T 卡。可核查结果:审计报告在 `reports/` 且逐行「通过」。 - -**估时合计 ≈5–6.5d**(T0 0.5–1+T1 1.5–2+T2 1–1.5+T3 1.5–2+T4 0.5)。切分预案:T1/T2 后可切(表与解析先落、消费面后落)——但 T1 出口到 T2 之间编译面是断的(签名换代),建议 T1+T2 一轮同落、T3 单独一轮;超软盒(>7d)预挂:T3 冒烟面清单若超一孔,先落 S1–S5+S9+S10a/S10b(寻址三参化/首遇带/Boss 直呼主链)保主链绿,S6–S8+S14–S16 次轮补,全清单绿才收口。 - -## 8. 验证闸(逐需求点验收清单) - -| # | 需求点 | 测什么(断言/行为) | 落点/判定手段 | -|---|---|---|---| -| V1 | 带寻址语义 | ①带命中:请求 D 落带 i → 返回该带行集(夹具键 [0,5]:请求 4 → 命中带 5,偏难不回 0);②行序保序(行集按表文件行序返回);③顶 clamp:D 高于顶带 → 顶带行集+warning `resolve_depth_clamp` 一次(重复请求去重);④row_kind 路由:同 D 传 "battle"/"boss" 命中不同键域;⑤D<0/L<1 → fatal `request_oob` | 单测 `config_db_resolver_test.gd`(换代既有 `_test_ceil_progress_key`/`_test_rowset_order_preserved` 为带语义四断言+新增路由断言) | -| V2 | 表 schema 与校验换代 | 迁移后生产表 `validate()` 零错误;非法 row_kind 被拒;dup_key 新键拦截(同 (L,kind,band,eid) 二行报 dup);rowset_rule 同带隔断报错;anchor(battle band 0+boss ≥1)缺任一报错 | 冒烟表校验段+单测夹具(`config_db_test.gd`) | -| V3 | 数据迁移零变更 | 键位与结构:20 行计数、键序=§4.2 表序、hobgoblin 行在 (1,battle,3)、三 boss 行 kind/band 就位;**数值零变更不钉字面量**(AGENTS.md 数值单一事实源红线)——由 T1 迁移步骤「git diff 仅键列+新增 kind 列、值列零变更」件核承载 | 冒烟结构断言(键/计数/行序)+git diff 件核(T0/T1 清单) | -| V4 | 多 Boss 各配行集 | 同关两 boss 节点解析带键互异(同带 → 报错);节点深度触发顶 clamp → 报错;单终点现状三关零误报 | 单测 `config_db_cross_validator_test.gd` 新增两负向+既有三用例回归 | -| V5 | 行集构成纪律带键新表述 | 混编 (2,battle,5) 双行行序 [bugbear→giant_spider];Σ(unit_count_max 缺省=unit_count) ≤ 4;同带隔断加载拒 | 冒烟 S4+`enemy_table` 校验(V2 面) | -| V6 | 首遇教学位带下定位 | 首遇带=数据驱动最低带;L2 巨蜘蛛首遇带行集恰一行、unit_count=2、无 unit_count_max;L1 bugbear/L3 duergar 首遇带固定数同款 | 冒烟 S2/S9 换代断言 | -| V7 | 冒烟断言面随动完整 | §8.1 S 清单全部条目(S1–S16,S10 分 a/b 共 17 行)逐条换代、无一条留旧坐标语义 | 冒烟全绿+清单件核(实现报告逐条勾销) | -| V8 | hobgoblin 缺口行去向 | (1,battle,3,hobgoblin) 在役(V3 结构断言面)、缺口登记随行(不删不补、不加立绘);数值相等归 V3 git diff 件核 | 冒烟结构断言+件核(敌种内容批接续登记在反哺点①) | -| V9 | 反哺点清单 | §6 五条每条有落点 | 件核对表(T4) | - -### 8.1 冒烟断言面随动清单(S 清单——按旧坐标写就、须换代的断言/直呼面,2026-10-21 实查) - -| # | 断言/直呼面 | 位置 | 换代内容 | -|---|---|---|---| -| S1 | `resolve_enemy_rowset` 行集首行读数(遭遇扫描/D1 D2 掷骰段) | `game/smoke/smoke_all.gd:3115`/:3429/:4396 | 三参化(row_kind="battle"),带语义注释 | -| S2 | 巨蜘蛛首遇行集 (2,4) 定点断言 | `smoke_all.gd:4692-4697` | 首遇带数据驱动定位+「恰一行、unit_count=2、无 unit_count_max」 | -| S3 | L2 Boss 行集 (2,9) 断言 | `smoke_all.gd:4698-4702` | 三参化(row_kind="boss") | -| S4 | 混编行集 (2,5) 行序/骰和/行值断言 | `smoke_all.gd:4706-4719` | 键改 (2,battle,5);行序契约断言保持 | -| S5 | L3 首遇 (3,0) 与 Boss (3,9) 断言 | `smoke_all.gd:4747-4759` | 首遇带定位+三参化(boss) | -| S6 | 跨表覆盖义务 en_keys 键聚合 | `smoke_all.gd:971-981`/:4677-4687/:5144-5147 | 键改 (L,row_kind,depth_band);Boss 节点查 boss 键域 | -| S7 | Boss AC 台阶+(1,2) 锚定+L1 总量曲线 | `smoke_all.gd:2206-2244` | node_depth→depth_band;(1,2) 锚定改 bugbear 首遇带定位;曲线断言改按 (1,battle) 带键相邻比 ≤ 2.5 | -| S8 | 毒吐投放面(venom_spit 专行检查+池权重图) | `smoke_all.gd:4178-4230` | 「`node_depth >= 5`」改「depth_band > 巨蜘蛛首遇带」;池键串改含 row_kind | -| S9 | D2 熊地精固定 1(首遇教学位) | `smoke_all.gd:3406-3411` | (1,2) 改 bugbear 首遇带定位(固定 1 不加骰) | -| S10a | Boss 坐标 `begin_battle` 直呼缺 node_type | `smoke_all.gd:2022`/:3025/:3090/:3177/:3231/:3271/:3301/:3474/:4503/:4933;`smoke/damage_probe.gd:95` | 各补 `"node_type": "boss"` | -| S10b | kind/坐标不一致直呼((2,4)+boss) | `smoke_all.gd:2621`/:2646 | 改 (2,9)+boss(断言语义不变,载体改真 Boss 坐标) | -| S11 | resolver 单测(ceil 语义/行序保序) | `game/tests/unit/core/config_db_resolver_test.gd:51-70` | 换代为 V1 带寻址语义断言 | -| S12 | `resolve_enemy_rowset` 同通道单测+夹具键 | `game/tests/unit/data_config/config_db_test.gd:38-40`/:62-69/:201 | 夹具键改 row_kind/depth_band;签名三参化 | -| S13 | 跨表校验单测夹具 | `game/tests/unit/core/config_db_cross_validator_test.gd:54`/:66/:79 | 夹具键改名+补 V4 两负向用例 | -| S14 | 探针直呼面 | `game/smoke/skill_rhythm_probe.gd:17`;`game/smoke/damage_probe.gd:269`/:420 | 三参化 | -| S15 | `boss_name` 叙述寻址 | `game/presentation/battle_narrator.gd:76-78` | 三参化(row_kind="boss") | -| S16 | 全深度×多种子 spawn 扫描(erow2 首行行值读数) | `smoke_all.gd:3413-3433` | 首行 unit_count 读数随带键(三参化) | - -清单口径:S11–S13 归单测面(T1/T2),S1–S10、S14–S16 归冒烟/探针面(T3);S15 归 T2(消费面)。无第 17 类遗漏面——`tools/` 下 node_depth 引用属关卡模板历史脚本(`t5_build_templates.py` 等),非敌人表键,不随动。 - -**测试方式两分法(2026-10-11 用户定)**:V1–V9 全部机检自动化(冒烟+单测);能力验证可经调试接口直改敌人表/遭遇坐标直呼开战(沿用现役 DebugOverlay/DS_DEBUG 门控)。**用户目检项**:仅「三关实机开战遭遇观感不回归」一条——观测项写进 `reports/iter-实现报告-<完成日>.md` 实机目检总清单,登记不阻塞(验收时间用户自行安排)。 - -**闸口径**:轻闸每任务卡出口自跑;批末重闸=`tools/run_all_gates.sh` 按改动域选档(本批只碰 `game/` 代码与数据表 → 代码域档)全绿才合并+改前改后读数对拍。回归措辞:里程碑步(T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套。 - -**变异验证伴生**(新增/改写验收函数逐条注入实验,记录表进实现报告):`band_of` 反向 floor(V1 红)/row_kind 枚举判据注释(V2 红)/boss 带互异判据删除(V4 红)/顶 clamp 判据短路(V4 红)/首遇行加 unit_count_max(V6 红)/混编行对调(V5 红)/hobgoblin 迁错带键(V3 红)。数值零变更不设数值字面量断言(数值单一事实源红线),改键误写由键位/行序/计数断言兜、值列漂移由 git diff 件核兜。变异不红则改判据或如实标注拦截边界。 - -### 8.2 改动—验收对照表(2026-10-21 验收闭合批新规,test-conventions §9.3) - -> 各断言 desc 统一尾缀〔fv#〕(本表「验收测试」列可 grep 定位);撤销/变异证明逐条对应 §8 变异验证伴生清单与 T1–T3 变异步(每张 T 卡至少一条,test-conventions §9.4)——T0 为事实坐实卡(无行为改动),其迁移表核对红证并入 V3 行(hobgoblin 迁错变异);T4 产出物以件核撤销证明承载。 - -| 需求点 | 改动(文件:行/行为) | 验收测试(名称+文件:行+尾缀) | 层级 | 真实入口 | 撤销或变异证明 | -|---|---|---|---|---|---| -| V1① 带命中偏难 | `game/core/config_db_resolver.gd:33-37` D 维改走带寻址+`game/data/schemas/enemy_table.gd` 新增 `band_of` 纯函数(接口块签名) | 带命中偏难(夹具键 [0,5]:请求 4 命中带 5、偏难不回 0)〔fv1〕 `game/tests/unit/core/config_db_resolver_test.gd`(S11 换代) | 单元 | `EnemyTable.band_of()`/`ConfigDbResolver.resolve_enemy_rowset()` 直调 | 变异:`band_of` 改「返回首个 ≤ D 的键」(T1 变异步)→ 本断言红 | -| V1② 行序保序 | `config_db_resolver.gd` 带命中行集按表文件行序返回(行序即契约) | 行序保序〔fv2〕 `config_db_resolver_test.gd`(S11 换代 `_test_rowset_order_preserved`) | 单元 | `resolve_enemy_rowset()` 直调 | 变异:混编两行文件内对调(T3 变异步)→ 行序断言红 | -| V1③ 顶 clamp+warning 去重 | `config_db_resolver.gd` `band_of` 返回 -1 → 顶带键行集+warning `resolve_depth_clamp`(四元组去重沿用) | 顶 clamp+warning 一次去重〔fv3〕 `config_db_resolver_test.gd` | 单元 | `resolve_enemy_rowset()` 直调(D 高于顶带、重复请求两次) | 撤销证明:回退 D 维 clamp 接线 hunk → 本断言红(§9.4 既有行为换代) | -| V1④ row_kind 路由 | `resolve_enemy_rowset(L, D, row_kind)` 三参签名(`config_db_resolver.gd:33-37`+`config_db.gd:193-194` 门面随动) | row_kind 路由:同 D 传 battle/boss 命中不同键域〔fv4〕 `config_db_resolver_test.gd` | 单元 | 同 D 分别传 "battle"/"boss" 直调 | 撤销证明:撤销第三参接线 hunk → 同 D 双 kind 不再分域、断言红 | -| V1⑤ request_oob | `config_db_resolver.gd` L<1 或 D<0 → `_diag` fatal `request_oob`(沿用) | D<0/L<1 fatal `request_oob`〔fv5〕 `config_db_resolver_test.gd` | 单元 | `resolve_enemy_rowset(0, …)`/`(L, -1, …)` 直调 | 撤销证明:回退 OOB 判据 hunk → 断言红 | -| V2① 生产表 validate 零错误 | `enemy_table.gd:32-135` validate 键换代+`game/data/tables/enemy.tres` 20 行键迁移 | 迁移后生产表 validate 零错误〔fv6〕 冒烟表校验段 `game/smoke/smoke_all.gd`+`config_db_test.gd` | 接口 | `EnemyTable.validate()` 对 `enemy.tres` | 撤销证明:回退键换代/迁移 hunk → validate 键类错误红 | -| V2② 非法 row_kind 被拒 | `enemy_table.gd` domain 判据增 `row_kind ∈ ROW_KINDS`(`ROW_KINDS := ["battle","boss"]`) | 非法 row_kind 被拒〔fv7〕 `game/tests/unit/data_config/config_db_test.gd`(S12 夹具) | 接口 | `validate()` 非法枚举夹具 | 变异:`validate` 的 row_kind 枚举判据注释掉(T1 变异步)→ 本断言红 | -| V2③ dup_key 新键拦截 | `enemy_table.gd` dup_key 键串改 `"%d_%s_%d_%s"`(L,row_kind,depth_band,enemy_id) | dup_key 新键拦截(同键二行报 dup)〔fv8〕 `config_db_test.gd` | 接口 | `validate()` 同键二行夹具 | 撤销证明:回退 dup_key 键串 hunk → 同键二行漏拦、断言红 | -| V2④ rowset_rule 同带隔断 | `enemy_table.gd:121-130` rowset_rule 键改 `"%d_%s_%d"`(同带相邻语义不变) | rowset_rule 同带隔断报错〔fv9〕 `config_db_test.gd` | 接口 | `validate()` 隔断夹具 | 撤销证明:回退 rowset_rule 键串 hunk → 隔断漏拦、断言红 | -| V2⑤ anchor 缺任一报错 | `enemy_table.gd` anchor 改「每关 battle band 0」+新增「每关 boss 行集 ≥1」(类别沿 `anchor`) | anchor(battle band 0+boss ≥1)缺任一报错〔fv10〕 `config_db_test.gd` | 接口 | `validate()` 缺锚/缺 boss 夹具 | 撤销证明:回退 anchor 判据 hunk → 缺任一漏报、断言红 | -| V3① 20 行计数与键序 | `enemy.tres` 20 行键迁移(T0 逐行复核 §4.2 迁移表+T1 迁移步,文件行序不变) | 20 行计数+键序=§4.2 表序〔fv11〕 冒烟结构断言 `smoke_all.gd` | 接口 | 加载 `enemy.tres` 全表(冒烟表校验段) | 撤销证明:回退 `enemy.tres` 迁移 hunk(T0 核对面+T1 迁移面)→ 计数/键序断言红 | -| V3② hobgoblin 键位 | (1,3,hobgoblin) → (1,battle,3,hobgoblin) 留任随迁(契约 9) | hobgoblin 行在 (1,battle,3)〔fv12〕 冒烟结构断言 `smoke_all.gd` | 接口 | 同 fv11 读表面 | 变异:hobgoblin 迁错带键 (1,battle,2)(T3 变异步)→ 键位断言红(红证覆盖 T0 §4.2 迁移表核对面) | -| V3③ 三 boss 行 kind/band 就位 | 三行 `row_kind="boss"` 就位((1,boss,4)ogre_chief/(2,boss,9)drider/(3,boss,9)duergar_king,§4.2 表) | 三 boss 行 kind/band 就位〔fv13〕 冒烟结构断言 `smoke_all.gd` | 接口 | 同 fv11 读表面 | 撤销证明:回退任一 boss 行 kind 列 hunk → 断言红 | -| V3④ 值列零变更件核 | `enemy.tres` 仅键列+新增 kind 列(T1 迁移步:值列零变更、禁字面量改写) | 值列零变更〔fv14〕 git diff 件核(T1 迁移步清单) | 件核 | `git diff game/data/tables/enemy.tres` 件核 | 撤销证明:改任一值列字面量(T1 件核步)→ git diff 件核红 | -| V4① 同带双 boss 报错 | `config_db_cross_validator.gd:63-65/:81-85` ④ 敌侧带化+「同关多 boss 节点解析带键互异」判据(类别 `rowset_rule`) | 同带双 boss 负向报错〔fv15〕 `game/tests/unit/core/config_db_cross_validator_test.gd`(S13 新增负向) | 单元 | `ConfigDbCrossValidator.cross_validate()` 同带双 boss 夹具 | 变异:删「boss 节点带互异」判据(T2 变异步)→ 本用例红 | -| V4② 顶 clamp 消解报错 | ④ 敌侧 `band_of != -1` 判据(-1=顶 clamp 消解,报 `level_node_dangling`) | 顶 clamp 负向报错〔fv16〕 `config_db_cross_validator_test.gd` | 单元 | `cross_validate()` 节点深度高于顶带夹具 | 变异:④ 敌侧判据短路为恒真(T2 变异步)→ 本用例红 | -| V4③ 单终点三关零误报 | ④ 敌侧半边换代、board_gen 半边零改动(:62/:82-83) | 既有三用例回归零误报〔fv17〕 `config_db_cross_validator_test.gd` 既有三用例(S13 夹具键改名) | 单元 | `cross_validate()` 现役三关夹具 | 撤销证明:回退 ④ 敌侧换代 hunk → 改名后既有三用例红 | -| V5① 混编行序 | (2,5) 双行迁 (2,battle,5)、行序 [bugbear→giant_spider] 与文件相邻不变(`enemy.tres`) | 混编 (2,battle,5) 双行行序〔fv18〕 冒烟 S4 `smoke_all.gd:4706-4719` 换代 | 集成 | 冒烟 S4 段读 (2,battle,5) 行集 | 变异:混编两行文件内对调(T3 变异步)→ 行序断言红 | -| V5② 骰和 ≤ 4 | 行集实例总数纪律带键化(`enemy_table.gd:29` `ROWSET_INSTANCE_MAX`+`unit_container.gd:81-84` 守卫) | Σ(unit_count_max 缺省=unit_count) ≤ 4〔fv19〕 冒烟 S4 | 集成 | 同 fv18 读行集面 | 撤销证明:放宽 ≤4 判据/守卫 hunk → 断言红 | -| V5③ 同带隔断加载拒 | 同 fv9 面(`enemy_table.gd:121-130` rowset_rule 带键化) | 同带隔断加载拒〔fv20〕 `config_db_test.gd`(V2④ 面合用) | 接口 | `validate()` 隔断夹具 | 撤销证明:同 fv9(回退 rowset_rule 键串 hunk → 断言红) | -| V6① 首遇带数据驱动定位 | T3 首遇断言定位换代为扫表取该 (L,battle,eid) 最低 depth_band(禁写死坐标,契约 8) | 首遇带=数据驱动最低带〔fv21〕 冒烟 S2/S9 `smoke_all.gd:4692-4697`/`:3406-3411` 换代 | 集成 | 冒烟 S2/S9 段扫 `enemy.tres` | 撤销证明:撤销扫表定位 hunk(写回写死坐标)→ 三断言取键失配红;件核零写死坐标(契约 8) | -| V6② L2 巨蜘蛛首遇带 | S2 换代:首遇带行集恰一行、`unit_count=2`、无 `unit_count_max`(S2 :4692-4697) | 巨蜘蛛首遇带恰一行固定 2 不加骰〔fv22〕 冒烟 S2 `smoke_all.gd:4692-4697` 换代 | 集成 | 同 fv21 扫表定位面 | 变异:巨蜘蛛首遇行加 `unit_count_max: 3`(T3 变异步)→「不加骰」断言红 | -| V6③ L1/L3 首遇带固定数 | S9/S5 换代:L1 bugbear 首遇带固定 1、L3 duergar 首遇带固定 1、均无 `unit_count_max` | bugbear/duergar 首遇带固定 1 不加骰〔fv23〕 冒烟 S9 `smoke_all.gd:3406-3411`+S5 `:4747-4759` 换代 | 集成 | 同 fv21 扫表定位面 | 变异:首遇行加 `unit_count_max`(T3 变异步同法注入 L1/L3 首遇行)→ 断言红 | -| V7 S 清单随动完整 | §8.1 S1–S16(17 行)逐条换代(`smoke_all.gd`/`skill_rhythm_probe.gd`/`damage_probe.gd`/单测三件) | S 清单 17 行无一留旧坐标语义〔fv24〕 清单件核(实现报告逐条勾销)+冒烟/探针全绿 | 单元+集成+探针 | 冒烟/探针/`tests/run_all` 全套入口 | 分证变异挂 fv1/fv2/fv7/fv18/fv22(T1–T3 变异步);整面撤销证明:任一 S 条留旧语义(撤销该 hunk)→ 对应断言红 | -| V8 hobgoblin 缺口行去向 | `enemy.tres` (1,battle,3,hobgoblin) 留任随迁、行值零变更、缺口登记随行(契约 9:不删行不补立绘) | hobgoblin 在役+缺口登记随行〔fv25〕 冒烟结构断言(V3 面)+git diff 件核 | 接口 | 同 fv11 读表面+`git diff` 件核 | 变异:hobgoblin 迁错带键(T3 变异步,同 fv12)→ 键位断言红;删/补件由 git diff 件核兜 | -| V9 反哺点清单(**非行为改动**——纯文档产出物,无游戏行为,§9.1) | T4 `reports/iter-反哺点-<完成日>.md` §6 五条各一落点(①敌人系统.md 记法措辞/②关卡节点地图.md :146/③关卡节点图生成.md 推论条款 A/④06 状态回写/⑤roadmap 编入笔) | §6 五条每条有落点〔fv26〕 件核对表(T4 出口) | 非行为改动 | 反哺点清单对 §6 同步面表件核 | 撤销证明:删一落点(如⑤)→ T4 出口件核红 | - -**旧断言预声明(test-conventions §9.5)**——允许改写的旧断言清单及理由:§8.1 S1–S16(17 行)全部条目(理由:遭遇寻址由(关卡序号×节点深度)坐标换代为(关卡序号×row_kind×深度带)带键,断言取键与定位方式随动;标注「断言语义保持」者只换键/定位、判据不动)。除此之外的断言删除/放宽/换下层直调=未声明削弱,停卡呈报、独立审计判红。 - -**独立验收审计(test-conventions §9.7,2026-10-21 起)**:合并前由未参与实现的迭代 loop 内子代理(或用户点名会话)审计——只读本卡、实现报告实际对照表、diff 与测试文件,自跑最窄测试抽查,不采信「已全绿」;审计报告落 `reports/iter-验收审计-<完成日>.md`(逐行「通过/缺漏/例外及依据」)。**审计未通过不得合并**(T4 合并前置)。 - -## 9. 异常分级 - -- **L1(自救)**:断言措辞、命名、注释、文件落点;冒烟消息文本随坐标记法更新。 -- **L2(记录继续)**:带切法实现形态(ceil 式键表扫描 vs 显式区间表——接口块语义内);校验错误类别命名细节(沿既有词表增补);冒烟断言的扫描式/resolve 式写法选择(§10 ⑤)。 -- **L3(停机呈报)**:迁移后行值与 §4.2 表对不上(数据漂移);任何触碰定位信息契约(两样)的诉求;带切法出现第二实现;任何删/增敌人内容的诉求(hobgoblin 补齐或删行);执行中发现同深度多终点图样(推论条款 A 被打破);`validate()` 旧类别出现失守缺口且无法在键换代内兜住。 - -## 10. 代拍板白名单(超清单必呈报) - -1. 带切法实现形态与带键编号规则——约束:迁移期与旧 ceil 逐位等价(契约 2)、单点收口(契约 3)、D<0 fatal 与顶 clamp+warning 去重两语义不破。 -2. schema 新字段/常量命名(`row_kind`/`depth_band`/`ROW_KINDS`)与枚举值字符串("battle"/"boss" 对齐节点 type 词表)。 -3. `resolve_enemy_rowset` 第三参命名 `row_kind`;`enc.node_type` 缺省映射 "battle"(level_runner 生产路径恒传值,缺省只服务测试直呼面)。 -4. 校验错误类别命名(沿 `dup_key`/`domain`/`rowset_rule`/`anchor` 词表;确需新类别时命名并留痕)。 -5. 冒烟断言的定位写法(表扫描式 vs resolve 式)与断言名措辞——约束:首遇定位禁写死坐标数字(契约 8)。 -6. 提交切分与 worktree 分支命名。 - -## 11. 待裁点 - -**零待裁点,开工门=U0。** - -两处灰色地带已按设计事实推导定值(用户可否决,随 T4 反哺点清单呈报可见): -- **推论条款 A(多终点深度互异,契约 6)**:备选「扩定位信息带终点标识」——淘汰依据=D2:119「定位信息只有两样」是既有定稿契约,扩它归卡②/文档批;「多终点共带共享 Boss」——淘汰依据=D3:74「多终点各配一行(走哪条路决定打谁)」明文;定值=多终点落互异深度带,表侧投影为 Boss 带键互异校验。 -- **hobgoblin 缺口行去向(契约 9)**:备选「迁移时退役隔离」——淘汰依据=用户范围句「本卡只定数据去向不补立绘」+迁移零行为变更原则(删内容属敌种内容批职权);定值=随迁留任、缺口登记随行、补齐归敌种内容批。 - ---- - -**自审五查记录(2026-10-21)**:①规格覆盖——§1 六项新增/八项完成定义逐条挂 T 卡(寻址=T1/T2、数据迁移=T1、校验=T1/T2、多 Boss=T2、首遇=T3、冒烟随动=T3、反哺点=T4),无漏项;②步骤扫描——全部步骤一步一动作一可核查结果,函数体仅 `band_of` 一处给语义、其余签名+断言;③类型一致性——接口块五签名与 T 卡引用逐字一致(`resolve_enemy_rowset(L, D, row_kind)`/`spawn` 尾参 `row_kind`/`band_of(band_keys, D)`/`ROW_KINDS`);④审查焦点——补挂三类失败模式:顶 clamp 静默消解(V4)、同带双终点(V4)、首遇行误加骰(V6),各带变异注入;⑤篇幅比例——规格≈1 屏、任务卡步骤≈实现面 1:1,无抄写体。 - -**grilling 复核记录(2026-10-21,设计树对抗复核,不采访用户——可推导定值写依据、真归用户列 §11)**:走查五支——带定义/切法(覆盖域与顶 clamp 归 §4 契约 3+契约 7,无缺口)、行类维度(battle/boss 同深度串位反证成立,row_kind 必要性已写进契约 1;node_type 非法值 fatal 已钉)、多 Boss 寻址(共带后果原文写错——「混编双 Boss」改为「两终点命中同一 Boss 行集」,契约 5 已订正;表侧/图侧投影分工已写清)、首遇定位(关卡节点地图:120「教学位同样掷骰、无结构豁免」与敌人系统「首遇不加骰」并存无冲突——前者是图侧不豁免、后者是行值无区间,契约 8 表述核对一致)、数据迁移对拍(原 V3 数值逐字段断言与 AGENTS.md:72 数值单一事实源红线冲突——改为键位/行序/计数结构断言+git diff 值列件核,变异面改钉 hobgoblin 错带)。AGENTS.md 硬红线逐条过:数值单点(本卡零数值)、测试两入口(T 卡只写断言不跑测)、实现批禁写 design/(§6 义务全走反哺点、零旧口径义务措辞)。结论:零待裁点,两处灰色推导已定值并留 §11 供用户否决。 diff --git a/roadmap.md b/roadmap.md index f9a71058..0a4b00a2 100644 --- a/roadmap.md +++ b/roadmap.md @@ -5,8 +5,8 @@ ## 当前位(只回答「现在该做什么」;三行内随批次换代,禁止在此扩写成状态快照) - **阶段**:M3——Alpha 版本的完整实现(2026-10-09 立规:未明令宣布完成前停留 M3,迭代只排 M3 需求,M4 不排期;根目录 stage.txt 为旧阶段开关仅存档)。 -- **迭代位**:迭代 1–33 全部已完成或已终止——迭代 33 三卡合回并于 2026-10-22 总收口+反哺落文,迭代 34 两卡已合回、批后收尾未做;迭代 35 已编排(待开工,卡片在 reports/);迭代 36 起未编排——编入哪一迭代由用户经迭代编排段发令。 -- **下一步**:迭代 34 批后收尾(收口登记与遗留读数义务清册,由用户发令)→ `/iter 35` 发令开工(实现段,段间不自动流转)。待编池:营地交互重做卡⑤(排卡④之后)、卡④(已退回美术设计段,美术设计闭合后重立卡)、冒险前资源配比预设(冻结备选)、迭代 30 原卡②③(2026-10-17 已剔出迭代 30 规划、退回待设计,待美术/设计定稿后重新立卡)、玩家面残留禁字清扫(待写卡)、结算明细日志行序重锚(2026-10-21 授权发起、时点另定)。 +- **迭代位**:迭代 1–34 全部已完成——迭代 34 两卡于 2026-10-22 合回、2026-10-24 完成批后收尾;迭代 35 卡① 已合回、卡② 停机待覆盖批;迭代 36 三卡已合回;迭代 37 起未编排——编入哪一迭代由用户经迭代编排段发令。 +- **下一步**:迭代 35「生成图深度扩面覆盖批」立卡后重编卡②;迭代 36 补记迭代总表行(现仍写「待开工」,与实际不符);迭代 37 编排由用户发令(迭代编排段入口)。待编池:营地交互重做卡⑤(排卡④之后)、卡④(已退回美术设计段,美术设计闭合后重立卡)、冒险前资源配比预设(冻结备选)、迭代 30 原卡②③(2026-10-17 已剔出迭代 30 规划、退回待设计,待美术/设计定稿后重新立卡)、玩家面残留禁字清扫(待写卡)、结算明细日志行序重锚(2026-10-21 授权发起、时点另定)。 ## 里程碑时间线 @@ -67,7 +67,7 @@ | 迭代 31 | 已完成(2026-10-19) | 已退役(git 历史可考) | 2026-10-18 | ≈7.5 个工作日 | 已退役(git 历史可考) | | 迭代 32 | 已完成(2026-10-21) | 已退役(git 历史可考) | 2026-10-20 | ≈8.75 个工作日 | 已退役(git 历史可考) | | 迭代 33 | 已完成(2026-10-22) | 已退役(git 历史可考) | 2026-10-21 | ≈13.25 个工作日〔用户特批 2026-10-21 超 10 个工作日〕 | 已退役(git 历史可考) | -| 迭代 34 | 待开工 | reports/需求卡片-敌人表深度带换代批-2026-10-21.md
reports/需求卡片-信息迷雾可见性批-2026-10-21.md | 2026-10-21 | ≈11 个工作日〔用户特批 2026-10-21 超 10 个工作日〕 | — | +| 迭代 34 | 已完成(2026-10-22) | 已退役(git 历史可考) | 2026-10-21 | ≈11 个工作日〔用户特批 2026-10-21 超 10 个工作日〕 | 已退役(git 历史可考) | | 迭代 35 | 待开工 | reports/需求卡片-节点图生成器核心批-2026-10-21.md
reports/需求卡片-节点图消费侧换代批-2026-10-21.md | 2026-10-21 | ≈15.25 个工作日〔用户特批 2026-10-21 超 10 个工作日〕 | — | | 迭代 36 | 待开工 | reports/需求卡片-开场后缀营地灰字迷雾测点批-2026-10-24.md
reports/需求卡片-文案与禁字清扫批-2026-10-24.md
reports/需求卡片-状态面板瘦身批-2026-10-23.md | 2026-10-24 | ≈5.25 个工作日 | — | diff --git a/体验验证清单.md b/体验验证清单.md index a16579e2..b7fb7304 100644 --- a/体验验证清单.md +++ b/体验验证清单.md @@ -348,3 +348,18 @@ | 5 | 空槽新档链 | 空槽点「新档」→进入营地,槽卡就地翻为有档形态(进档+删档钮) | - **红灯信号**:主菜单出现旧六钮任何一枚;选档层摘要读出别槽值;删档一击直删;旧档迁移后槽 1 白板(迁移没跑)。 - **结论回流**:观感问题归迭代 34 卡④(营地场景图重立卡顺带复核入口观感);数据层缺陷归待办清单营地交互重做条。 + +--- + +## ㉜ 迭代 34——遭遇行集换代与信息迷雾实机目检(2026-10-24 随反哺写入登记) + +> 卡③ 把遭遇寻址换成(关卡序号, 行类, 深度带)三参,卡④ 给关卡节点图加信息迷雾(邻近 N 层内显示类型)。机检已覆盖行集解析、校验负向判据与可见性/绘制记录断言,遭遇观感与雾下图面仍要人眼看。登记不阻塞(2026-10-12 真人检测立规);总收口时点=迭代 34 实现报告(已退役,git 可考)。 + +| # | 目检项 | 判据 | +|---|---|---| +| 1 | 三关实机开战遭遇观感不回归(卡③) | 第一关地精/熊地精、第二关巨蜘蛛与重击手混编、三关 Boss 战的敌人数量与外观与改动前一致 | +| 2 | 雾下可读性观感(卡④) | 未知类型房间一眼可辨为「未知」而非「漏画」——编号仍在,类型图标与文字不出现 | +| 3 | 多终点 Boss 标记观感(卡④) | 双 Boss 图上两个终点的紫赤描边都清楚可辨 | +| 4 | 大图完整可见观感(卡④) | 大图(11 层×6 槽)整幅落在画布内,无节点被裁切或挤在一角 | +- **红灯信号**:改动前后遭遇敌人数量/外观不一致;雾下房间读作漏画或类型文字漏出;双 Boss 只有一侧带描边;大图有节点出界。 +- **结论回流**:实现缺陷归待办清单登记新条目;观感问题归关卡节点图呈现面后续批。 diff --git a/待办清单.md b/待办清单.md index f486eda2..eada6821 100644 --- a/待办清单.md +++ b/待办清单.md @@ -2,6 +2,18 @@ 本清单是流水线的唯一登记处:要做的事先在此登记一条,随流水线段推进改状态,做完整条删除;各系统文档的「待办」节只留一行指路存根,不再自建条目。条目格式(标题=登记元数据,正文=现状/缺口/归属/状态四属性)与状态机以 [doc-conventions §12.1](design/engineering/doc-conventions.md) 为权威。 +#### 超预算图策略升级路径——等比缩放与滚动视口两案待裁(2026-10-24 登记,来源=批次移交,设计面=文档轨) + +**现状**:迭代 34 卡④(信息迷雾可见性批,已合回 master,提交 16a7ec80)按「参数限图」交付,图包络约 10 层×8 槽即当前冻结画布的屏预算上限。若后续定值批需要更大的完整可见图,两条升级路径都要动冻结件,均未设计:①等比缩放——动「节点图标 20px 烘焙 1:1」与「通道折线冻结 2/3/4px」两条冻结值;②滚动视口——新增视口交互范式。 +- 相关文档 design/gdd/systems/冒险循环/关卡节点图生成.md v1.2(调参表「图包络」行) +- 相关文档 design/gdd/ux/level-map.md(画布冻结公式) + +**缺口**:两案需用户裁决后再走设计讨论;未裁前禁改画布冻结件。 + +**归属**:[关卡节点图生成](design/gdd/systems/冒险循环/关卡节点图生成.md)(图包络约束)+ [level-map](design/gdd/ux/level-map.md)(画布与交互呈现) + +**状态**:待文档设计 + #### game 代码结构审查批——行为缺陷定点修+结构重构候选(2026-10-24 登记,来源=审计发现,设计面=工程直入) **现状**:审计报告=reports/审计-game代码结构审查-2026-10-24.md(2026-10-24,全目录只读审查,零测试执行、结论全部静态阅读)。缺陷证据(报告 §二 Critical 行为缺陷段+定点清单,含行号)九件:①core/damage_controller.gd:215 用 `==` 比较单位字典(Godot 4 语义=逐键内容比较)——内容全同双敌其一死亡误作废对方单据,应 `is_same()`;②presentation/views/standee_body.gd:172/188 蓄力意图档常量错配(GOLD_INK vs GOLD_DEEP)死代码,三档运动签名设计失效且无测试覆盖;③presentation/views/battle_end_overlay.gd:281-287 庆祝 tween set_loops 无限叠加泄漏(close 只隐藏不 kill);④批量模拟×两层调试并发互斥缺口(presentation/views/debug_overlay.gd:84+presentation/main.gd:712-715/1489+presentation/tune_sim_controller.gd:46-58——用户两击可并触发,演出扭曲+测量作废);⑤presentation/modal_stack.gd:23-29 未登记层/重复开层静默降级(违 fail-fast,当前调用面无违规者属埋雷);⑥core/minesweeper_rules.gd:8-9 两条核心信号零契约成文(违 code-conventions §2.1)+全库信号注释载体普遍 `#` 非 `##`;⑦明细行类型封闭枚举漂移(core 实发 13 类 vs battle_orchestrator.gd 头注 9 类);⑧core/level_runner.gd:895/779 玩法数值字面量(relic 基价 15.0、散折 0.8,自注 provisional);⑨presentation/views/battle_stage_view.gd:332-338 以 display_name 子串匹配解析受击目标(同名敌错位,应携带 enemy_id)。另有定点小件与结构重构候选(报告 §三):main.gd 1508 行可判离块 ~440 行/board_view.gd 1219 行瓦片算法+英雄精灵可拆/adventure_runner 令牌池子系统 ~500 行可拆 CurioDeck/level_runner 商店子系统 ~260 行可拆/断点 schema 三处重复登记可单点化——重构候选非缺陷,是否立项由写卡段呈报用户裁决。 @@ -157,12 +169,10 @@ **现状**:来源=playnote 用户试玩记录「关卡节点图展示得有问题,希望可以优化一下。可以参考哥布林弹珠的那种方式去移动」。2026-10-13 用户明确定性:**这是当前关卡节点图的重构,不是呈现优化**——理由是**现在的可选节点太少**(用户原话),所以不是换一种画法或移动方式就能解决的事。 关联文档清单: -- 设计定稿 design/gdd/systems/冒险循环/关卡节点图生成.md v1.1(2026-10-21) -- 设计定稿 design/gdd/systems/冒险循环/关卡节点地图.md v2.1(2026-10-21) +- 设计定稿 design/gdd/systems/冒险循环/关卡节点图生成.md v1.2(2026-10-24) +- 设计定稿 design/gdd/systems/冒险循环/关卡节点地图.md v2.2(2026-10-24) - 需求卡片 reports/需求卡片-节点图生成器核心批-2026-10-21.md(2026-10-21) - 需求卡片 reports/需求卡片-节点图消费侧换代批-2026-10-21.md(2026-10-21) -- 需求卡片 reports/需求卡片-敌人表深度带换代批-2026-10-21.md(2026-10-21) -- 需求卡片 reports/需求卡片-信息迷雾可见性批-2026-10-21.md(2026-10-21) **现行实态**(`level.tres` 实查,三关各 5 张模板):**第一关五张模板全是单链排列变体**——7 个节点=战斗 ×4 + 奖励 + 休整 + Boss,战斗深度序单调保难度坡,**变化面只有奖励与休整两位的先后次序**,全链零分叉,玩家在选路上**没有任何选择**;第二/三关是网状图(10 节点,带 `next` 分支,最大层宽 4–5),有分叉,但用户仍判选择量不足。参考方向=Peglin(哥布林弹珠)的节点图移动与选路方式。