docs(批后收尾): 迭代 35 结项——反哺点十七条落文+代拍板两单整单追认+中间文档十二份退役+账面换代

反哺点落文(用户 2026-10-25 逐条裁「全部照此落文」):卡①① 多终点深度互异改「互异节点深度」并补深度算法(最长路径、多入口取最长、不取最短的理由);卡①⑦ 增「支路互异上限=出口数 3」摆放约束;卡①②/卡②① 地图深度定义改最长路径、三处「节点编号」换「节点深度」;卡①③/卡②② 冒险结构覆盖义务换代为敌侧带命中+板侧解析命中+深度域 L1 0–6/L2 0–9/L3 0–13,删「旧模板池随实现批清数据」;卡①④/卡②④ level-map 登记生成图随动——入口停点候选数=入口个数、节点数字=图内句柄 id、L3 深度域超出冻结画布约 10 层屏预算(等比缩放/滚动视口两案未裁,只登记缺口);卡②③ 核对无用语漂移。版本:生成 v1.3、地图 v2.3、level-map Last Updated 2026-10-25。

代拍板:卡① 六条+白名单外两件、卡② 六条+超清单五件,按用户令整单追认(推翻项零)。

中间文档退役十二份(吸收即死):两张需求卡片、两卡实现报告/代拍板/反哺点/验收审计共八份、两份停机呈报;引用面已改写(待办证据指路改 git 提交 5499eb9c)。目检四条迁体验验证清单 ㉝。

账面换代:roadmap 迭代 35 行改「已完成(2026-10-25)」、卡片与实现报告列填退役保留字,顶部当前位三行换代;待办清单 06「关卡节点图重构」条目整条删除(完成即删),新增三条代码件待办(验证集清单重生成、测试宿主改名、level.tres 表尾叙事订正),图包络条目同步 v1.3 引用与实测越界事实。

本批为文档批:零 game/ 改动、零测试执行、零 MC。
This commit is contained in:
DKChan committed 2026-10-25 01:28:36 +08:00
1 parent 546e511385
commit 6c761e1369
18 files changed
+62 -1264

No files matched your search

@@ -1,7 +1,7 @@
# 关卡节点图生成
> 一句话:一关的节点图从哪来——生成器按参数长出一张合法图
> 状态:现行为 v1.2
> 状态:现行为 v1.3
## 设计目的
@@ -47,7 +47,9 @@
| 层高=沿路步数 | 入口到终点的最长路径步数;第一关 ≥6,逐关递增且增幅变大 |
| 出口归属锁定 | 多终点时由大岔口把图分成互不连达的分支区域,各区域只通向自己的终点;每个终点前一层节点的去路集合恰含一个终点——选路=提前承诺打谁 |
| 战斗节点保底 | 奖励/恢复/商店占位后战斗节点量不被挤没(保底数进调参表) |
| 多终点深度互异 | 多终点(多 Boss 节点)必须落在互异的深度带;同一深度带出现两个终点即判产出无效——共带会让「走哪条路打谁」落空 |
| 多终点深度互异 | 多终点(多 Boss 节点)必须落在互异的节点深度;同一节点深度出现两个终点即判产出无效——共深会让「走哪条路打谁」落空 |
节点深度的算法:自入口沿路走到该节点的最长路径步数;多入口时取距任一入口的最长路径。不用最短路径——合流节点或多入口图上取最短,会让某些出边指向深度不增甚至更浅的节点,破坏「连线只朝前进方向」的无环判据。
结构铁律:连线只朝前进方向(无环);入口、终点都可多个(个数=参数档),每条路径恰好从一个入口出发、恰好到达一个终点。
@@ -76,13 +78,14 @@
配比是生成旋钮:战斗/奖励/恢复/商店各占多少由参数档定,生成器掷出分布落在图上成为节点类型;配比只管非终点节点,终点恒为 Boss、不进配比。节点类型在可见范围内对玩家公开(可见性规则归关卡节点地图)——看得见的类型才谈得上提前规划。
摆放约束(三条):
摆放约束(四条):
| 约束 | 内容 |
|---|---|
| 商店位 | 每个终点前一位恰一家商店——每名玩家一局必经恰一家店 |
| 岔路取舍·下一跳 | 一个岔口分出的各条去路,下一节点类型互不相同——下一跳必在可见范围,是决策的可见锚(实现侧已兑现:候选集强制豁免类型可见性) |
| 岔路取舍·支路构成 | 一个岔口分出的各条支路,整条支路的节点类型构成互不相同——每条支路至少有一个别的支路没有的类型(例:一路有恢复节点、一路有奖励节点) |
| 支路互异上限=出口数 3 | 商店与 Boss 每条支路必有,可供支路互斥的类型只剩战斗/奖励/恢复三类——一条链上的岔口最多切出 3 条互异支路,故出口个数取值域为 1–3(见生成参数旋钮表) |
内容归各 owner:战斗节点打谁=敌人系统按深度带配池;奖励/恢复/商店的兑付语义=关卡节点地图与各 owner 文档。
@@ -1,7 +1,7 @@
# 关卡节点地图
> 一句话:单关内的节点图选路与推进
> 状态:现行为 v2.2
> 状态:现行为 v2.3
## 设计目的
@@ -54,7 +54,7 @@
| 节点类型 | 机制承诺 |
|---|---|
| 战斗 | 携带节点编号;行进至此开战(兑付见下节);胜利后回到选路 |
| 战斗 | 携带节点深度;行进至此开战(兑付见下节);胜利后回到选路 |
| Boss | 恒为图终点;行进至此开 Boss 战;胜利即关卡收束点 |
| 奖励 | 行进至此触发节点奖励(兑付见下节);反馈呈现后回到选路 |
| 恢复 | 行进至此向冒险结构发治疗封顶回报;反馈呈现后回到选路 |
@@ -62,7 +62,7 @@
商店房的编排规则:**每个终点前一位恰一家店**——哈迪斯式的"决战前最后一个补给点":买到的属性还有整段战斗可消费,错过的成长也没有第二家店可补。终点前一位同时是**必经位**:每名玩家一局恰好必经一家店,成长保底是图结构事实而非玩家自觉。这条位置约束不由加载校验承载,由冒烟断言把关(摆放规则语义见[关卡节点图生成](关卡节点图生成.md)配比节)。
每个节点在图上有**节点深度**(本文含义:从入口沿路走过来的步数),用来当战斗的定位地址——遭遇坐标=关卡序号+节点深度,敌人表按**深度带**(深度区间)配池,寻址语义见[敌人系统](../战斗循环/敌人系统.md)。"最深处是关底"的直感由深度承载:终点恒在各路径最深处。单链(每步只有一条连线)是合法退化形态,节点深度等于它前面走过的战斗场数;三关参数档都含岔口,第一关不再是单链。图的来源见[关卡节点图生成](关卡节点图生成.md)。
每个节点在图上有**节点深度**(本文含义:自入口沿路走到该节点的最长路径步数;多入口时取距任一入口的最长路径),用来当战斗的定位地址——遭遇坐标=关卡序号+节点深度,敌人表按**深度带**(深度区间)配池,寻址语义见[敌人系统](../战斗循环/敌人系统.md)。不用最短路径:合流节点或多入口图上取最短,会让某些出边指向深度不增甚至更浅的节点,破坏「连线只朝前进方向」的无环判据。"最深处是关底"的直感由深度承载:终点恒在各路径最深处。单链(每步只有一条连线)是合法退化形态,节点深度等于它前面走过的战斗场数;三关参数档都含岔口,第一关不再是单链。图的来源见[关卡节点图生成](关卡节点图生成.md)。
呈现侧口径(2026-09-17 用户拍板):节点图的画面表达走**方块地牢观感**——节点画成地牢房间的方块、连线画成通道——但逻辑拓扑就是本文的节点图,不产生任何额外选路或探索语义。关卡画面本体即节点链进度的呈现载体(选路覆盖层的常驻形态,节点态直接读图:已过暗金 / 当前金 / 候选下一跳通道亮金 / Boss 紫赤描边(紫赤+深墨环,视觉定稿见 [level-map](../../ux/level-map.md))),不另设进度条组件;视觉规格归 [HUD 框架](../表现与支撑/HUD框架.md)。
@@ -155,7 +155,7 @@ Boss 兑付(胜利或英雄死亡)触发关卡收束点,此后不再有选
1. 从冒险结构接收开始关卡(关卡序号、当前生命、生效上限),加载本关节点图并呈现选路停点(关卡画面),玩家在图上选出第一跳,行进自所选节点开始(入口节点不自动进入)。
2. 每节点兑付完成并确认后返回关卡画面,玩家再选路前进;岔路选一条、单链点继续;零自动推进。
3. 战斗 / Boss 节点:组装关卡序号 + 节点编号,移交战斗结算开战;战斗结束向冒险结构上报战斗结果。
3. 战斗 / Boss 节点:组装关卡序号 + 节点深度,移交战斗结算开战;战斗结束向冒险结构上报战斗结果。
4. 奖励节点:触发节点奖励兑付 = 提升三选一(与通关三选一共享令牌库);恢复节点:向冒险结构发治疗封顶回报;商店节点:打开商店覆盖层,购买即时生效,离开后兑付确认。
5. Boss 战胜利或任意战斗倒下 = 关卡收束点:先调战斗结算的关卡收束清库,再宣布关卡结束。
6. 单链是合法退化形态;三关参数档都含岔口,第一关即有选择(图的来源见[关卡节点图生成](关卡节点图生成.md))。
@@ -177,7 +177,7 @@ Boss 兑付(胜利或英雄死亡)触发关卡收束点,此后不再有选
- 图合法:行集通过加载校验——每条路径恰好从一个入口出发、恰好到达一个终点,终点恒为 Boss(可多个)、连线无环、任意入口出发的任意路径都到达某一个终点;违规配置加载期致命(规则语义见[关卡节点图生成](关卡节点图生成.md)产出规格)。
- 行进自主:从入口到 Boss 的每一次前进都由玩家选路发起(含关卡开始后的第一跳——关卡开始停在图上,入口节点不自动进入);不存在任何自动推进路径;倒下时行进终止。
- 兑付移交:每场开战调用携带(关卡序号 + 节点编号),与节点图上该节点位置一致;每场战斗结束恰一次战斗结果上报。
- 兑付移交:每场开战调用携带(关卡序号 + 节点深度),与节点图上该节点位置一致;每场战斗结束恰一次战斗结果上报。
- 兑付后确认:战斗节点的继续确认挂战斗总结结算(settlement-summary.md),奖励/恢复挂兑付反馈覆盖层;到达与兑付之间无确认步。
- 恢复兑付:治疗封顶回报载荷 = 该关恢复比例(读关卡配置行);满血回复 0 是合法状态(执行语义归冒险结构)。
- 奖励兑付:奖励节点兑付恰触发一次;池空直通空态合法,现行 = 提升三选一(与通关三选一共享令牌库)取一件按件类兑付(spec:node-reward.md v2.x;兑付路由归[冒险结构](冒险结构.md)提升池节)。
@@ -261,7 +261,7 @@ GP(显示名「GP」)是冒险内的一次性属性提升货币:战斗胜
| 参数 | 域 | 现行值 | 说明 |
|---|---|---|---|
| 关卡行集(关数与图的参数档) | 关卡表逐关行 | 三关现行(图由生成器按参数档产出,见[关卡节点图生成](关卡节点图生成.md);旧模板池随实现批清数据) | 加关 = 内容批(参数档 + 敌我数值 + 新元素同批);确定性 = 固定种子+固定参数档(首局教学与存档复现的固定图由此承载,无兜底模板) |
| 关卡行集(关数与图的参数档) | 关卡表逐关行 | 三关现行(图由生成器按参数档产出,见[关卡节点图生成](关卡节点图生成.md)) | 加关 = 内容批(参数档 + 敌我数值 + 新元素同批);确定性 = 固定种子+固定参数档(首局教学与存档复现的固定图由此承载,无兜底模板) |
| 恢复比例 | int [0,100],逐关行 | 见 level.tres rest_heal_pct(provisional) | 恢复点回复生效上限的百分比;随上限加成同步放大;100 = 恢复点变全满泉,0 = 死节点 |
| 上限提升 | int [0,999],冒险表逐件列 | adventure_table bonus_attack_flat / bonus_max_hp_flat / bonus_armor_flat(provisional) | 三选一属性件各自兑付值;值锚与上调约束归难度曲线与Boss |
| 三选一件值(其余) | int [0,999],冒险表 kind×tier 列族 | adventure_table curio_value_*(GP 袋 / AP 件 / 恢复 / 刷新,provisional) | 令牌件值读表;道具件授予件数随秘宝件出池退役 |
@@ -290,7 +290,7 @@ GP(显示名「GP」)是冒险内的一次性属性提升货币:战斗胜
- 同调位约束:道具终态持有恒 ≤ 同调位(谓词表实时求值);超位时停点渠道触发替换交互(丢旧收新 / 放弃新件两路),战斗内渠道沉没不入;奖励节点渠道同受约束。(现行零道具件投放——约束保留作契约,见「秘宝件受同调位约束」节注。)
- 钥石逐杀:Boss 击杀后钥石累计增量 = boss_keystone 行值(首杀/复杀两档);大奖励面钥石入账零残留。
- 收束次序:通关宣布到达时库存已被关卡节点地图先行清空;重复的关卡结束宣布被拒绝,状态与摘要零变化。
- 覆盖义务:冒烟断言——行集内每个战斗与关底节点(关、深)在敌人与棋盘生成的数值表中有精确行;序列关数 = 行集关数。
- 覆盖义务:冒烟断言——行集内每个战斗与关底节点(关、深)都必须在敌人与棋盘生成的数值表里命中:敌侧按深度带命中(落带不早于请求深度,禁以顶带 clamp 消解),板侧按解析命中;生成图深度域 L1 0–6/L2 0–9/L3 0–13(参数档 `layers` 实测,provisional);序列关数 = 行集关数。
- 生效前提未兑现(第二关行缺行):以单关冒险运行(合法态),越界关断言显式跳过而非失败。
- 放弃:战斗中的放弃请求被拒绝;非战斗期放弃按失败同型结算,已获大奖励不追回;放弃入口仅在选路停点呈现且只在冒险模式开放。
- 种子域:冒险内零随机流自开,一切随机派生自主种子(含 GP 掉落掷定的 gp_drop 封闭流);同种子同操作序列两局逐位可复现。
+5 -4
View File
@@ -2,12 +2,13 @@
> **Status**: 定稿版——三项设计提案已拍板完成(2026-09-27:底栏状态展示 / 图上点击选路·候选按钮退役 / 放弃二次确认);**形态已升格独立屏(2026-09-28 用户裁决:独立存在为最终形态)**;**视觉终稿已冻结(2026-09-28 关卡画面样张 v1 机检 11/11 全绿,闸形 A——冻结值见 Layout/组件清单与样张机检报告,迭代 4)**
> **Author**: user + ZCode(关卡画面 UX 批)
> **Last Updated**: 2026-10-15(简明技术中文用语规范批:词面修正 6 处)
> **Last Updated**: 2026-10-25(迭代 35 生成图换代:呈现面随动登记)
> **Platform Target**: PC (Steam)——Keyboard/Mouse 主,全部操作纯鼠标可完成(同 [battle.md](battle.md))
> **Template**: UX Spec
> **覆盖范围**: 独立屏形态(关卡停点全景)· 入口停点 · 岔路停点 · 单链停点 · 放弃冒险入口
> **不覆盖**: 节点覆盖层(NodeOverlay——奖励/恢复兑付反馈,spec:[node-reward.md](node-reward.md))、商店覆盖层(spec:[shop.md](shop.md))、关卡结算屏([level-clear.md](level-clear.md))、战斗屏([battle.md](battle.md))
> **机制权威**: [关卡节点地图](../systems/冒险循环/关卡节点地图.md)(选路、兑付、停点语义);图的来源 = [关卡节点图生成](../systems/冒险循环/关卡节点图生成.md)(参数化长图——只换图的来源与形态,不换本屏的呈现语义;多终点时各终点均带 Boss 标记,标记语义不变、数量随图;图形态随参数变化,布局自适应,形态不进呈现代码);**系统契约**: [HUD框架](../systems/表现与支撑/HUD框架.md)(订阅纪律、模态层级、可访问性基线)
> **生成图随动登记(2026-10-25)**:入口停点候选数=入口个数(1 或多,多入口并列呈现,首跳即选从哪个入口进场);节点数字=图内句柄 id(非节点深度、非数组序);生成图深度域 L3 上探至 0–13,超出画布冻结公式约 10 层的屏预算——等比缩放与滚动视口两案均未设计,归呈现批(见待办清单「超预算图策略升级路径」条),本 spec 冻结值暂不变。
---
@@ -65,7 +66,7 @@
| 区 | 位置与尺寸 | 内容 |
|---|---|---|
| **顶栏语境** | 居中横排,图区上方,高约 32px | 左:关卡名(`level_row.display_name`,如「第二层 · 幽暗地域」);右:GP 常驻徽章(GP 图标+数字,直角细线数据框——GP 值域超点阵适用档,走 pattern 5 的 When-NOT-to-Use 路线);HP 归底部状态栏(2026-09-27 拍板完成) |
| **节点图区** | 居中 | 整幅节点图自绘:节点方块 + 通道折线 + 节点态着色 + 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 右上角 |
| **节点图区** | 居中 | 整幅节点图自绘:节点方块 + 通道折线 + 节点态着色 + 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 单色、当前金底转深墨——双色墨制)+ 编号(图内句柄 id)10px 右上角 |
| **底部状态栏** | 图区下方横排,高约 48px | 左-中:状态数据框组(直角细线,pattern 5 族)——生命(当前/上限 + 迷你血条)、属性(攻击 / 护甲 AC,有效值 + 加成角标)、本关加成(攻+X · 上限+Y · AC+Z,零加成隐藏);右端:放弃冒险按钮(危险红族文字,与状态数据框保持间距——破坏性确认异位,pattern 7) |
### Component Inventory
@@ -74,7 +75,7 @@
|---|---|---|---|---|
| 关卡名标签 | 文本 | `level_row.display_name`(关卡表行读数) | 只读 | 新建(现行标题位升级) |
| GP 常驻徽章 | 直角细线数据框 | GP 图标 + 数字(`runner.gp`,冒险钱包读数;刷新经 `wallet_changed` 信号投影〔gain/buy/clear 三事件〕或写路径回执后重查) | 只读 | 新建(GP 去向拍板落地面) |
| 节点图画布 | 自绘 Control | 节点图标(五键 20px 烘焙,双色墨制)+ 编号、通道折线、节点态着色、Boss 紫赤描边+深墨环(BOSS_PURPLE——2026-09-26 封印紫批语义:紫赤本色) | 悬停预承诺 / 点击提交选路(唯一通道) | ✅ level_map_screen.gd `_draw_graph`(视觉终稿已落码——迭代 4 T2/T3) |
| 节点图画布 | 自绘 Control | 节点图标(五键 20px 烘焙,双色墨制)+ 编号(图内句柄 id)、通道折线、节点态着色、Boss 紫赤描边+深墨环(BOSS_PURPLE——2026-09-26 封印紫批语义:紫赤本色) | 悬停预承诺 / 点击提交选路(唯一通道) | ✅ level_map_screen.gd `_draw_graph`(视觉终稿已落码——迭代 4 T2/T3) |
| 状态数据框组 | 直角细线数据框 ×3 | 生命(当前/上限 + 迷你血条)、属性(攻击 / 护甲 AC 有效值 + 加成角标)、本关加成(加算区增量列表,零加成隐藏) | 只读 | 新建(2026-09-27 拍板:底栏状态展示) |
| 放弃冒险按钮 | 按钮(危险红族) | 「放弃冒险(同失败结算——已获大奖励保留)」;二次确认态已拍板(见布局决策 3) | 点击(首击转确认态、二击提交) | ✅ level_map_screen.gd(可见性归组合根,仅冒险模式开) |
| 标题行 | 文本 | 停点语境提示(见布局决策 1 三停点标题) | 只读 | ✅ level_map_screen.gd `_title`(措辞已按布局决策 1 改稿) |
@@ -83,7 +84,7 @@
| 停点 | 候选数 | 标题 |
|---|---|---|
| 入口停点 | 1(入口节点) | 「出发——选择首个节点」 |
| 入口停点 | 入口个数(1 或多) | 「出发——选择首个节点」 |
| 单链停点 | 1 | 「继续前进」 |
| 岔路停点 | ≥2 | 「选择下一节点」 |
@@ -1,57 +0,0 @@
# 迭代 35 卡② 停机呈报(实现段零裁断——退回上游)
- 日期:2026-10-24
- 触发:`/iter 35` 第 4 步逐卡推进——卡① 已开工并实现,卡② 开 T1 前核 §0 前置,命中卡片自述硬交付序列
- 批性质:代码实现批;本呈报只移交缺陷,不改卡片、不改 `design/`、不改待办清单
- 本卡改动:**零**(未动 `level_table.gd`/`level.tres`/`level_runner.gd` 任何消费侧文件)
## 一、现状差在哪
卡② `reports/需求卡片-节点图消费侧换代批-2026-10-21.md` §0「硬交付序列」明文:
> 敌人深度带数据对生成图深度域的覆盖……归口=卡③ §5 已登记的「生成图深度扩面覆盖问题」,**尚未立卡(2026-10-24 实况登记)**……未覆盖时覆盖断言(§8.1 S5)红、遭遇解析顶 clamp 消解,**本卡不得单独合入**。
待办清单 `待办清单.md:143` 同口径登记:覆盖批的立卡要件(敌侧每 (关, row_kind) 顶带键 ≥ 该关最大生成深度+Boss 带键可互异+板侧 `board_gen` 键域覆盖全域)尚未成为任何一张卡片,roadmap 也没有该批的迭代行。
卡① 已落地的参数档深度域(`game/data/tables/level_gen_params.tres`)= L1 0–6/L2 0–9/L3 0–13;敌侧带顶仍是 L1=3/L2=L3=7、Boss 各关单带 4/9/9,板侧 `board_gen` 精确行同域缺口未变。
## 二、建议做什么
卡② 停工退回上游,按既定归口先走「生成图深度扩面覆盖批」的登记→写卡→编排三段,该批落地后再重编卡②。
预期效果:卡② 的 S5 覆盖断言(V11)有绿灯前提,切源后起关不再触发 `EnemyTable.band_of` 返 -1 的加载致命(`game/data/schemas/enemy_table.gd:157-161`、`game/core/config_db_cross_validator.gd:94-106`)。
会动到的面:`game/data/tables/enemy.tres` 深度带键域与 Boss 行集、`game/data/tables/board_gen.tres` 的 `node_depth` 键域——全是数值表改动,需用户发起(AGENTS.md 数值单点+MC 审批红线),不属本实现批职权。
本迭代已交付面:卡① 生成器本体+参数档数据表+产出侧自证+断言批(见 `reports/iter35-卡①-实现报告-2026-10-24.md`)。
## 三、为什么选这个做法
备选与淘汰依据:
1. **本批顺带补敌/板覆盖数据**——淘汰:卡② §5「不做」与卡① §5「不做」都明写覆盖归卡③/后续表批;实现段自扩数值域=越范围,且数值改动需用户发令。
2. **卡② 只交 T1(加载校验换代)不合切源**——淘汰:T1 退役旧判据与模板池校验分支后,`level.tres` 仍携 15 张模板,中间态必红(卡② §7 估时注记「T2+T3 须同轮落地,拆开中间态冒烟必红」),交出去的是一半不能验收的卡。
3. **等覆盖批、卡② 整卡停工**(本呈报建议案)——代价=迭代 35 只交卡①,与 2026-10-24 上午停机呈报的「读法乙」一致,用户当时已裁「整体停工」并按此重锚两卡。
## 四、做完怎么验证
覆盖批的验收面已由卡② 预写死:S5/V11 断言=生成图逐 battle/boss 节点 `band_of` 非 -1(禁顶 clamp)+多终点 Boss 解析带键两两互异+板侧解析命中非空,扫描面=三关参数档×种子(卡② §8 V11)。该批落地后卡② 重编,这些断言即其开工门。
把握不足处:L2/L3 多终点 Boss 带键「可互异」需要敌表 Boss 行集从单带扩成按终点深度分带——具体带切法属卡③ 契约 5 的续域,覆盖批写卡时须一并裁。
## 五、待办清单状态回退与缺口补记拟稿(落笔归上游段/用户)
`待办清单.md:149` 现状态行:`文档设计已闭合+已写卡+已编迭代 34+已编迭代 35`
拟改为:
```
**状态**:文档设计已闭合+已写卡+已编迭代 34+已编迭代 35;迭代 35 卡① 已实现待合回(2026-10-24);卡② 停工退回——覆盖批未立卡,其 §0 硬交付序列未满足,须「生成图深度扩面覆盖批」落地后重编
```
缺口补记(拟入 06 条目,替换现第 143 行缺口段的「迭代 35 停机退回」表述):
```
**缺口状态更新(2026-10-24 迭代 35 实现批)**:卡② §0 硬交付序列仍未满足——覆盖批未立卡,卡② 停工退回上游;卡① 不触覆盖域,已在本迭代实现(生成器产出深度域 L1 0–6/L2 0–9/L3 0–13 实测坐实)。
立卡要件不变:敌侧每 (关, row_kind) 顶带键 ≥ 该关最大生成深度+Boss 带键可互异;板侧 board_gen 键域覆盖生成深度全域;数值 provisional。
```
@@ -1,24 +0,0 @@
# 迭代 35 卡① 代拍板追认单(节点图生成器核心批)
- 日期:2026-10-24
- 依据:`reports/需求卡片-节点图生成器核心批-2026-10-21.md` §10 代拍板白名单六条——授权发生在卡片审问阶段,本批只执行预授权并留痕
- 待用户动作:追认或推翻。推翻任一条即回写对应实现面(不改设计文档)
| # | 卡片白名单条目 | 本批拍定值 | 落点 |
|---|---|---|---|
| ① | RNG 纯流面机制细节 | `pure_stream(seed_val: int, scope: int) -> RandomNumberGenerator`;派生式复用 `_mix64(SINGLE_SALT ^ (\|seed_val\| + scope × GOLDEN_RATIO))`;scope 分域取**单流多次取数**(`SCOPE_STRUCTURE = 0` 一个域,内部按取数序推进 RNG 状态);不推 `_counter`、不落事件日志、不读 `_master_seed`;负种子按 `absi` 归一、`INT64_MIN` 断言拒 | `game/core/rng_service.gd` pure_stream;断言〔fv3〕〔fv10〕 |
| ② | 「支路」度量口径 | 支路互斥段 = 自出边起的可达集,减去同岔口其余出边可达集的并集(即「至再汇合/终点止」的独占段);类型构成按该独占段的**多重集**(类型名排序数组)比较;「每支路至少一个别的支路没有的类型」判据 = 该独占段内存在一个类型不出现在任何其他支路的独占段 | `node_map_generator.gd` `_check_fork_rules`;断言〔fv5〕 |
| ③ | 生成器内持有结构与句柄赋值序 | 图持有 = `_pool`(Array[Dictionary])+`_by_id`;节点字段恰 `id/type/depth/next`;id 赋值序 = 入口 → 主链段自浅到深 → 各区域自终点倒序回填 → 侧链岔口;`generate` 返回 `{nodes, entries, terminals}` | 同上 `_build`/`_mk`;读面对齐 §7 接口块 |
| ④ | 参数档 .tres 行键形态与 provisional 微调 | `rows: Array[Dictionary]`,键 = `level_index`,字段键集 = `ROW_KEYS` 十二键闭集(含 `fork_ways_min/max`);三行取卡片 §8.1 表原值(layers 6/9/13、branch_density .30/.50/.70、配比三档、entry 1/2/2、exit 1/2/3、battle_floor 4/6/8),未做域内微调 | `game/data/schemas/level_gen_params.gd`、`game/data/tables/level_gen_params.tres`;断言〔fv2〕 |
| ⑤ | 长图算法具体步骤(HOW) | 单出口图(L1)= 入口→定长链→商店→Boss,链上挂侧链岔口;多出口图(L2/L3)= 入口→主链段→**归属大岔口**(主链段末节点切 e 条区域)→各区域单调链(区域内禁再扩岔);岔口侧链与主去路同深度、汇入主去路的后继(保「深度=最长路径步数」不变量);相邻两层禁同时扩岔(否则上层支路独占段吞掉下层侧链,破契约 5③);分支密度实际生效数 = min(round(bd×层高), 可用锚点数)——种子 42 实测侧支节点数 L1=4/L2=4/L3=3(总节点 11/19/29 减无岔口基线 7/15/26),provisional 期的实现自由面,定值批若要「十几次决策点」须放宽锚点几何) | `node_map_generator.gd` `_build`/`_add_forks` |
| ⑥ | 提交切分与分支命名 | 分支 `iter35`(单工作区 `../g-plan2-iter35`);提交三笔=卡① 实现(含断言与 manifest)/fv4 判据三分码修订/致命面体例修正+断言判别力补强 | git log(63a6ea80、a039306f、16c776e9) |
## 白名单外、本批自认为需要呈报的两件
1. **致命面形态修正**:卡片 §7 写「push_error+assert/既有 fatal 路径」。实测 assert 在 headless `--script` 下只中断当前调用链、`OS.crash` 会阻塞跑批且无法被断言消费——故按仓库既有体例(`config_db.gd:78-88` Core 置 `_fatal_flag`+push_error,退出决策归组合根 `main.gd:396 _fatal_screen`)实现:`generate` 不合格时置致命封印+断言+**零交付**(不返回任何图),消费侧(卡② 起关路径)按 `is_fatal()` 停机。契约 4 语义(无兜底图、无软回退、不合格不进玩法)不变,只是停机点从生成器内移到组合根。
2. **调试面曾加一件方法 `generate_for_debug(params, seed)`**——独立验收审计判定其零调用方=死代码,**本批已删除**(断言读产出规格违例改走公有 `validate_output(graph, params)` 直调,能力验证面仍由卡片 §8 两分法的现役 DebugOverlay/DS_DEBUG 承载)。此条不再请求追认,仅作处置留痕。
## 遗留读数义务(实现报告同步在册)
- 用户目检两条未做(登记不阻塞):三关生成图选路观感、生成规模随关卡变大可感知——呈现依赖卡②/卡④ 落地。
- MC/对拍零跑:本批无数值改动、未涉核心结算,按红线不发起跑批。
@@ -1,22 +0,0 @@
# 迭代 35 卡① 反哺点清单(节点图生成器核心批)
- 日期:2026-10-24
- 出处:`reports/需求卡片-节点图生成器核心批-2026-10-21.md` §6 关联文档同步面六条 + 实现中新发现一条设计面事实
- 状态:待用户在会话里逐条裁决;裁决后由文档批写进 `design/`,本文件随之退役(doc-conventions §11 吸收即死)
- 依据代号沿卡片 §2:D1=关卡节点图生成.md v1.1,D2=关卡节点地图.md v2.1,D3=冒险结构.md
| # | 文件与节 | 改成什么 | 依据 |
|---|---|---|---|
| ① | `design/gdd/systems/冒险循环/关卡节点图生成.md` 产出约束节(D1 :41-49 五条之后) | 增一条产出约束「多终点落在互异节点深度」;并在层高条目处成文「节点深度=自入口最长路径步数(多入口取距任一入口的最长路径)」 | 卡① 契约 2;D2 :119「定位信息只有两样(关卡序号+节点深度)」+D1 :96「多终点各配 Boss 行、走哪条路决定打谁」合取——同深度多终点在只有两样定位信息下不可区分;卡③ 契约 6 推论条款 A 的图侧兑现(卡③ §6 反哺点③ 派发) |
| ② | `design/gdd/systems/冒险循环/关卡节点地图.md` :65 | 「节点深度=从入口沿路走过来的步数」补注为「自入口最长路径步数」,并说明合流图上为何不能用最短路径 | 卡① §11 推导:最短路径赋值下合流/多入口节点可出现「出边目标深度 ≤ 源」,使无环判据(D1 :51 连线只朝前进方向)失效;实现侧断言 `node_map_generator_test`〔fv1〕已按最长路径口径写死 |
| ③ | `design/gdd/systems/冒险循环/冒险结构.md` :293 覆盖义务行 | 登记生成图实际深度域供覆盖核对:**L1 深度 0–6/L2 0–9/L3 0–13**(三档参数档 `layers` = 6/9/13 实测,2026-10-24 卡① 落地读数);覆盖义务措辞换代(精确行→敌侧带命中+板侧解析命中)仍归卡③ 反哺线,本条只补深度域数值 | D3 :293 覆盖义务+卡① §0 交付序列;`game/data/tables/level_gen_params.tres` 现值 |
| ④ | `design/gdd/ux/level-map.md` | 登记呈现面随动需求:多入口首跳候选、多终点标记、含岔口图与深度域 0–13 的画布自适应;本批未改任何呈现代码 | 卡① §6 表行(06 条目连带面②);落地归卡④/level-map 文档批 |
| ⑤ | `待办清单.md` 06「关卡节点图重构——可选节点太少」条目 | 状态推进为「卡① 已实现待合回;卡② 停工退回(覆盖批未立卡)」,并把第 143 行缺口段更新为「已实现卡① 深度域实测」版本——拟稿见 `reports/iter35-卡2-停机呈报-2026-10-24.md` 第五节 | 实现批对流程清单零改动(AGENTS.md 两类批红线),条目状态只由流水线各段推进 |
| ⑥ | `roadmap.md` 迭代 35 行 | 卡片列与状态换代:卡① 标实现批已交付(合回后改「已完成」)、卡② 标停工退回上游;顶部「当前位」三行随之更新 | 卡① §6 表行;roadmap 属文档批职权,本批只列点不落笔 |
| ⑦ | `design/gdd/systems/冒险循环/关卡节点图生成.md` 配比与摆放约束节(D1 :74-88) | 成文一条结构上限:出口个数 3 不只是调参表的取值域,而是摆放约束③「每支路至少一个别的支路没有的类型」的天花板——五类节点里商店与 Boss 每条支路必有,可供支路互斥的唯一类型只剩 battle/reward/rest 三类,故一条链上的岔口最多切出 3 条互异支路 | 实现实证:卡① 三档构型中,多终点图必须给每个归属区域指定互斥签名类型才能过支路互异断言(`node_map_generator.gd` REGION_SIGNATURES 三元素);D1 :107 出口 1–3 已锁范围与该推论一致,但文档未写理由 |
## 与实现差异/缺口逐条自证
- ①②:文档只写「步数」未写「最长」,实现取最长路径赋值——差异已按契约 2 落码并写断言,属文档缺位。
- ⑦:文档「岔路取舍·支路构成」条目在三终点情形下隐含唯一可行解(每区域独占一类),实现按此构型;文档若不加此句,后续调参批可能误配四出口。
- 本批未触碰 GDD 任何条款文本,也未新增/修改 `design/` 与两份根流程清单。
@@ -1,99 +0,0 @@
# 迭代 35 卡① 实现报告(节点图生成器核心批·参数化长图生成器)
- 日期:2026-10-24
- 卡片:`reports/需求卡片-节点图生成器核心批-2026-10-21.md` v1.1
- 工作区:独立 worktree `D:/code/g-plan2-iter35`(分支 `iter35`,整迭代单工作区)
- 批性质:代码实现批——本批未写、未改、未新增 `design/` 与根规则文件;文档面义务全落本目录(见反哺点清单)
- 提交序列:卡① 实现(生成器+参数档+断言+manifest)→ fv4 判据三分码 → 致命面体例修正+判别力补强 → 合流图夹具按契约 2 重写 → 战斗保底判据专测夹具
## 一、任务卡状态
| T 卡 | 状态 | 交付面 |
|---|---|---|
| T0 事实坐实与跨卡接口对齐 | 完成(卡② 侧对齐随停工移交) | §3 F1–F8 行号与 §2 取用条款抽查:六处关键锚点实查命中(`level_runner.gd:513-525` enc 组装、`enemy_table.gd:157-161` band_of、`config_db_cross_validator.gd:100-106` 迭代 34 检查、`node_map_templates_test.gd:32-104` 宿主、`rng_service.gd:34/:86` 双面、`run_all.gd` manifest 体例)——零漂移;接口定稿见 §三 注 1;RNG 纯流面与支路口径定稿见 `reports/iter35-卡①-代拍板-2026-10-24.md` ①② |
| T1 参数档数据表 | 完成 | `game/data/schemas/level_gen_params.gd`(LevelGenParams,ROW_KEYS 十二键闭集+validate 域校验+row_by_level_index)、`game/data/tables/level_gen_params.tres`(三行 provisional,照卡片 §8.1 逐行填)、`game/core/config_db.gd`(注册+成员+装载+访问器 `level_gen_params_row()`)、manifest 登记一行 |
| T2 生成器核心 | 完成 | `game/core/rng_service.gd` 新增 `pure_stream(seed_val, scope)`(纯派生、不推 `_counter`、不落事件日志);`game/core/node_map_generator.gd`=`generate(params, seed)` 产图+`validate_output(graph, params)` 产出自证+`check_params` 可行性判定+`is_fatal()` 致命封印读面 |
| T3 验收断言批总装 | 完成 | 三宿主共 72 条断言:`level_gen_params_test.gd`〔fv2〕17 条、`node_map_generator_test.gd`〔fv1/fv3/fv5/fv6/fv7/fv9/fv10〕39 条、`node_map_growth_test.gd`〔fv4/fv8〕16 条;manifest 三行全登记(闸 02 实跑 58 套件全绿,本批 +3) |
| T4 产出物落位 | 完成(实现报告=本文件;代拍板单、反哺点清单、卡② 停工呈报同批) | `reports/iter35-卡①-实现报告-2026-10-24.md`、`reports/iter35-卡①-代拍板-2026-10-24.md`、`reports/iter35-卡①-反哺点-2026-10-24.md`、`reports/iter35-卡2-停机呈报-2026-10-24.md` |
## 二、完成定义逐条对账(卡片 §1)
| # | 完成定义 | 现实读数 |
|---|---|---|
| 1 | 产出图必过五条+铁律+摆放三条 | `generate` 产前强制 `validate_output`;三档 × 20 种子(42–61)扫描自证零错误〔fv1〕 |
| 2 | 参数档落地 ConfigDB 单点读、生成器不认关卡号 | 三行 .tres 加载零诊断;`generate(params, seed)` 无形参 level_index;件核=全仓 `generate` 调用点零传关卡号 |
| 3 | 确定性(同种子同图、counter 无关、随机只经 RngService) | 同 (seed,params) 两次逐位同图〔fv3〕;两台服务处不同号位(1 vs 999999+7 次取号)产图逐位相同〔fv3〕;`counter()` 前后不变〔fv10〕;生成器内零 `randomize()`/零自建 RNG/零 `open_stream` |
| 4 | 生长递增 | 同种子 42 读数:层高 6/9/13,节点总数 11/19/29,Δ(L1→L2)=8 < Δ(L2→L3)=10〔fv8〕 |
| 5 | 专项兑现 | L1 出口恒 1、大岔口自 L2 起、下一跳互异、支路构成互异各有独有类型、每路径恰一店、多终点深度互异、战斗保底 ≥ 4/6/8——逐项断言〔fv5/fv6/fv7/fv9〕 |
| 6 | 参数无解 fail-fast | `check_params` 拦两类无解夹具(层深 6 放三出口、保底超可放数)〔fv4〕;真实停机通道=致命封印置位→组合根停机(子进程退出码恰 1)〔fv4〕 |
| 7 | 验收断言批全绿+变异记录表 | 三套件独立跑全绿(17+42+16 checks,退出码 0);变异记录表见 §四 |
| 8 | 批末重闸全绿+产出物写齐 | 〔闸读数见 §五〕;三份 `reports/` 产出物+停工呈报在位 |
## 三、实际改动—验收对照表(卡片 §8.2 的行号落地)
> 断言宿主行号取实现当日实测;〔fv#〕尾缀可 grep。
| 尾缀 | 需求点 | 改动落点 | 验收测试(文件:行) | 真实入口 | 撤销/变异证明 |
|---|---|---|---|---|---|
| fv1 | 产出合格+产出自证 | `game/core/node_map_generator.gd` `validate_output()`、`_build()` | `node_map_generator_test.gd:88-89`、`:328-377`(正负向夹具) | `generate(params, seed)` 产前强制+`validate_output(graph, params)` 直调 | m4 首写深度→`:361` 红;m5 注掉终点恒 Boss→`:350` 红;夹具级:dup/dangling/enum/回边/合流各命中对应类别 |
| fv2 | 参数档 schema+.tres+ConfigDB | `level_gen_params.gd`、`level_gen_params.tres`、`config_db.gd:22/:43/:146/:253` | `level_gen_params_test.gd:16,47,50,55,59`+域负向 `:66-101` | `LevelGenParams.validate()`/`ConfigDB.level_gen_params_row()` | m1 L1 出口改 2→`:16` 红;m2 配比合计 0.5→`:16` 红 |
| fv3 | 可复现(纯函数+counter 无关) | `node_map_generator.gd` `generate/_setup_and_build`、`rng_service.gd` `pure_stream` | `node_map_generator_test.gd:99,109,119` | `generate(params, seed)` 同种子两次直调+跨号位双实例对拍 | m3 取数改 `open_stream("node_map")`→`:109` 红 |
| fv4 | 执行边界(无兜底图/fail-fast) | `node_map_generator.gd` `check_params()`+`_fatal()`+`is_fatal()` | `node_map_growth_test.gd:64,70,74,91` | 无解参数档调 `generate`;子进程 `-- fatal-fixture` 真实停机通道 | m11 致命短路改 `pass`→`:91` 红(停机码不再是 1) |
| fv5 | 岔路取舍两条 | `node_map_generator.gd` `_check_fork_rules()`、`_add_forks()` 双禁相邻扩岔 | `node_map_generator_test.gd:163-164`、`:412` | 产图岔口扫描+同类型下一跳夹具 | m8 侧支类型写死 battle→套件经致命通道转红(`:412` 夹具级判据直证下一跳互异) |
| fv6 | 恰一店+归属锁定+多终点深度互异 | `node_map_generator.gd` 区域链/商店位构造、`_check_fork_rules` 独占段 | `node_map_generator_test.gd:228-230`、`:387,397,404` | `validate_output` 前驱/店数/DFS 路径+depth 比对;DFS 全路径枚举 | m6 商店位改 rest、m7 双终点同 depth→套件经致命通道转红;夹具级 `:387/:404` 直证两类判据 |
| fv7 | 战斗保底 | `node_map_generator.gd` `_assign_types` 保底优先守卫、`validate_output` 保底判据 | `node_map_generator_test.gd:257`、`:343-346` | 产图战斗计数+合法形状低保底夹具 | m9b 注掉保底判据→`:343` 红;m9 砍穿保底→`:257` 所在套件转红(中止于空图读面) |
| fv8 | 生长递增 | `level_gen_params.tres` 三档 provisional 值 | `node_map_growth_test.gd:57-58` | 三档 `generate` 读数对拍(同种子 42) | m10(L3 分支密度归零)NOT-RED——如实标注拦截边界,见 §四 注 |
| fv9 | 含岔口与出口结构 | `node_map_generator.gd` `_add_forks` 起始 wanted、大岔口构造 | `node_map_generator_test.gd:285-287` | 三档 × 种子扫描结构计数 | m12 强制零岔口→`:285` 红 |
| fv10 | RNG 单点(纯流面) | `rng_service.gd` `pure_stream()` | `node_map_generator_test.gd:313-318` | `pure_stream` 直调+`counter()` 前后读数 | 与 m3 同发注入(counter 不变断言红)+静态扫描 09 零 `randomize()` |
| fv11 | 反哺点清单 | 无代码改动(非行为改动) | 件核:`reports/iter35-卡①-反哺点-2026-10-24.md` 七条落点 | T4 产出物件核 | 缺任一落点→件核不收口 |
注 1(接口定稿对卡② 的裁剪):`generate(params, seed)` **不收 level_index**(契约 6),返回 `{nodes:[{id,type,depth,next}], entries:[int], terminals:[int]}`;参数档字段名 = `layers/branch_density/battle_ratio/reward_ratio/rest_ratio/shop_ratio/entry_count/exit_count/battle_floor/fork_ways_min/fork_ways_max`;两条硬语义(同种子同图、纯函数复现)由〔fv3〕〔fv10〕锁住。卡② 重编时 T0 按本表对齐接线。
## 四、变异验证记录表(注入→最窄套件见红→`git checkout` 还原)
| # | 注入 | 期望红点 | 实测 |
|---|---|---|---|
| m1 | `level_gen_params.tres` L1 `exit_count` 1→2 | fv2 值域 | RED-OK:`生产 level_gen_params.tres 随全表加载 + validate 零违例〔fv2〕` 红 |
| m2 | L3 `battle_ratio` .55→.05(合计 ≠1) | fv2 合计 1 | RED-OK:同上断言红 |
| m3 | 生成器取数 `pure_stream` → `open_stream("node_map")` | fv3 counter 无关 | RED-OK:`counter 无关(不同号位态同种子同图)〔fv3〕` 红 |
| m4 | 最长路径计算 `maxi(...)` → 首写 only | fv1 深度语义 | RED-OK:`合法合流图(第二入口直插主链,深度取最长路 3)自证零错误〔fv1〕` 红 |
| m5 | `validate_output` 注掉「终点(无出边)非 Boss」判据 | fv1 | RED-OK:`非 Boss 终点夹具命中「终点(无出边)非 Boss」判据〔fv1〕` 红 |
| m6 | 区域商店位 `_mk("shop",…)` → `_mk("rest",…)` | fv6 | 拦截发生(进程红),红点落在空图致命通道(套件在〔fv3〕后中止);判据本体由 `:404` 夹具级断言直证 |
| m7 | 终点深度 `L - r` → `L - (r/2)`(两终点同深) | fv6 | 同 m6:进程红;判据本体由 `:387` 夹具级断言直证 |
| m8 | 岔口侧支类型修型写死 `battle` | fv5 | 同 m6:进程红;判据本体由 `:412` 夹具级断言直证 |
| m9 | 配比填余守卫 `if chain_battles - 1 < floor_n:` → `if False:` | fv7 | 拦截发生(进程红,中止于空图读面)——红点未落在〔fv7〕尾缀,改以 m9b 作判据级证明 |
| m9b | `validate_output` 注掉「低于保底」判据 | fv7 | RED-OK:`战斗节点低于 battle_floor 的合法形状夹具命中「低于保底」判据〔fv7〕` 红 |
| m10 | L3 `branch_density` 0.7→0.0 求增幅倒挂 | fv8 | **NOT-RED**(实测 L3 仍 27 节点、Δ 未倒挂)——本几何族下「只调分支密度」不足以破坏增幅递增,如实标注为拦截边界;层高/节点数的单调性由参数档 schema 域校验(层深递增且增幅变大)与〔fv8〕三档读数共同承载 |
| m11 | `generate` 无解路径 `_fatal(...)` → `pass` | fv4 | RED-OK:`无解参数档置致命封印并由组合根停机(退出码恰 1)〔fv4〕` 红 |
| m12 | 岔口数 `wanted` 写死 0 | fv9 | RED-OK:`三关参数档生成图各含 ≥1 岔口节点(第一关即含)〔fv9〕` 红 |
跑批前后各一遍三套件:BASE/FINAL 均 exit=0 all green(17/42/16 checks)。
## 五、批末重闸读数
- 首轮 `tools/run_all_gates.sh --code`(回执 commit `ba660446`):**09 静态扫描 基线绿 → 现红**——新增两类本批违例:S5 core 裸引用 autoload 点标识符 1 处(注释形态)、类型闸 R1 无类型容器 17 处(全在本批新文件)。
- 修复=`c0059bc5`(容器声明补参数化或改推断形;注释去 autoload 点引用形态),单件复跑 `bash game/tests/static_scan.sh` → S1–S12 全 ok、`tools/audit_type_hints.py` → PASS 归零。
- 二轮全量代码域闸(回执 commit `c0059bc5`):**「验收通过——闸况与基线一致,无新增红」**,退出码 0;未跑面=11 回放确定性对拍(本批 diff 触及 RNG/数据表面,对拍须用户批准发起,列存量红·对基线零新增)。00 冒烟/01 系统测试/02 单元与集成(58 套件,含本批新登记三件)/03 探针 --click/04 探针 --full/05 渲染闸/10 熵增闸均与基线一致。
- 死代码清理(审计缺漏⑤)后的三套件与静态扫描复跑读数见 §六末。
- **三轮全量代码域闸=本批最终回执**(清理与报告收口笔之后跑,回执 commit `90fd434a` 与分支尖对齐):结论「验收通过——闸况与基线一致,无新增红」,退出码 0;未跑面仍为 11 回放确定性对拍(本批 diff 触及 RNG/数据表形态,对拍须用户批准后设 `PARITY_APPROVED=1` 重跑才实跑)。
## 六、独立验收审计结论
审计件:`reports/iter35-卡①-验收审计-2026-10-24.md`(未参与实现的 loop 内子代理,只读卡+对照表+diff+测试,自跑窄测复现撤销证明,不采信本报告自述)。
- **结论=有条件通过**,无必须退回的不通过项:对照表 fv1–fv11 逐行核过,断言真实存在且尾缀可 grep;真实入口未绕过改动点(`generate(params, seed)` 不收关卡号、`validate_output` 在产图主路径被产前强制调用、`pure_stream` 为生成器唯一取数源,生成器内零 `randomize()`/零自建 RNG/零 `open_stream`);diff 零删除、未触 `design/` 与根规则文件;`level_gen_params.tres` 与卡片 §8.1 逐格对上;manifest 三行 `expect: 0` 齐;本报告对 m6–m10 的 NOT-RED 与红点漂移属**如实呈报**(未写成已拦截)。
- 审计独立复现的撤销证明两条:m11(`_fatal(...)` → `pass`)→ 唯一红 `node_map_growth_test.gd:91`〔fv4〕(子进程停机码 1→2),还原后 16 checks 全绿;m4(最长路计算改首写)→ 唯一红 `node_map_generator_test.gd:361`〔fv1〕合法合流图自证,还原后 39 checks 全绿。
- 缺漏五项处置:①断言计数(报告原写 42/合计 70,实测 39/72)→ 已改 §一 T3;②fv2 行 ConfigDB 行号漂移(:42/:250 → 实测 :43/:253)→ 已改 §三;③§五闸读数、§六审计结论原为「待补」→ 本节与上节补齐;④`:404`/`:412` 两条夹具断言按错误**类别**判定,存在同类掩蔽源(同类别的另一判据可顶掉专指性)→ 记为已知拦截边界,判据专指性由 m5/m9b 两条「注掉判据即红」的注入补足(已 RED-OK);⑤`generate_for_debug` 零调用方=本批引入的死代码 → 已删除(生产路径只留 `generate`;断言读产出规格违例改走 `validate_output` 公有面直调),代拍板单第 2 条随之撤销。
- 清理后复跑读数(死代码删除同批):`level_gen_params_test` all green (17 checks)、`node_map_generator_test` all green (39 checks)、`node_map_growth_test` all green (16 checks),退出码均 0;`bash game/tests/static_scan.sh` → S1/S2/S3/S4/S5/S9/S10/S11/S12 全 ok。
## 七、实机目检总清单(登记不阻塞)
1. 三关生成图选路观感:多入口首跳、大岔口取舍、多终点走向可见、第一关即有选择——**依赖卡②/卡④ 落地后才能实机看到**(本批只产图不接运行时)。
2. 生成图规模随关卡推进变大(11/19/29 节点、层高 6/9/13)可感知——同上。
## 八、遗留读数义务与停机面
- 参数档数值全 provisional;定值批须重跑〔fv8〕与 MC 对拍(本批零数值改动未跑 MC)。
- 分支密度实际生效数受构型锚点几何限制:种子 42 实测侧支节点数 L1=4/L2=4/L3=3(总节点 11/19/29 减无岔口基线 7/15/26 之差),与 D1 调参表「一局十几次决策点」的意图有距离——已记入代拍板 ⑤ 与反哺点,定值批若要提密度须放宽锚点几何(属实现自由面,不改产出规格)。
- 卡② 停工:其 §0 硬交付序列的「生成图深度扩面覆盖批」未立卡,本批未切运行时图源——详见 `reports/iter35-卡2-停机呈报-2026-10-24.md`。迭代 35 因此未做「一次合并」,合回与否待用户裁拆批。
- 生成图深度域实测 L1 0–6/L2 0–9/L3 0–13 已写进反哺点③,供覆盖批立卡时当量程依据。
@@ -1,130 +0,0 @@
# 迭代 35 卡① 验收审计报告(节点图生成器核心批·合并前独立审计)
- 日期:2026-10-24
- 审计方:独立会话(未参与本批实现)
- 被审工作区:`D:/code/g-plan2-iter35`(分支 `iter35`,HEAD = `6074b3c3`,审读开始前 `git status --short` 为空)
- 基线:`2931b1f2`(开工时 master)
- 依据合同:`reports/需求卡片-节点图生成器核心批-2026-10-21.md` v1.1(§1 完成定义/§4 契约 1–7/§7 任务卡 T0–T4/§8.1 参数档取值表/§8.2 改动—验收对照表/§10 代拍板白名单)
## 一、审计范围与读数依据
### 1.1 实际读过的文件
| 类别 | 文件 |
|---|---|
| 输入合同 | `reports/需求卡片-节点图生成器核心批-2026-10-21.md`(全文 269 行) |
| 被审产出物 | `reports/iter35-卡①-实现报告-2026-10-24.md`、`reports/iter35-卡①-代拍板-2026-10-24.md`、`reports/iter35-卡①-反哺点-2026-10-24.md` |
| 实现本体 | `game/core/node_map_generator.gd`(547 行全文)、`game/core/rng_service.gd`(151 行全文)、`game/core/config_db.gd`(本批 diff 段)、`game/data/schemas/level_gen_params.gd`(81 行全文)、`game/data/tables/level_gen_params.tres`(49 行全文) |
| 断言面 | `game/tests/unit/core/node_map_generator_test.gd`(445 行全文)、`game/tests/unit/core/node_map_growth_test.gd`(115 行全文)、`game/tests/unit/data_config/level_gen_params_test.gd`(106 行全文)、`game/tests/run_all.gd`(diff 段)、`game/tests/unit/test_kit.gd`(协议语义:check/finish/退出码) |
| 闸回执 | `game/tests/.gates/receipt.json`(实现会话批末代码域闸产物,本审计未重跑全量闸) |
| 规则源 | 根 `agents.md`(红线)、`tools/run_all_gates.sh`(09 静态扫描=`game/tests/static_scan.sh`) |
### 1.2 实际跑过的命令与读数
| # | 命令(均在 `D:/code/g-plan2-iter35` 内执行) | 读数 |
|---|---|---|
| R1 | `git log --oneline -5` / `git status --short` / `git branch --show-current` | HEAD `6074b3c3`、分支 `iter35`、工作区干净 |
| R2 | `git diff --stat 2931b1f2..HEAD -- .` 与 `git diff --name-only 2931b1f2..HEAD -- . ':!game'` | `game/` 内 14 个文件、共 1562 行插入;`game/` 之外只有 `reports/` 四份产出物。**零文件触及 `design/`、`AGENTS.md`、`roadmap.md`、`待办清单.md`、`体验验证清单.md`**(`grep -Ei "design/\|AGENTS\|roadmap\|待办\|体验"` 命中 NONE) |
| R3 | `git diff --numstat 2931b1f2..HEAD -- game/` | 14 行删除列全为 `0`——本批对既有代码与既有断言**零删除、零改写** |
| R4 | 套件基线跑(逐条串行,每次先 `taskkill //IM Godot_v4.7.2-stable_win64.exe //F`):`--script res://tests/unit/data_config/level_gen_params_test.gd` | 退出码 0,`all green (17 checks)` |
| R5 | `--script res://tests/unit/core/node_map_generator_test.gd` | 退出码 0,`all green (39 checks)` |
| R6 | `--script res://tests/unit/core/node_map_growth_test.gd` | 退出码 0,`all green (16 checks)`,`[fv4] 无解子进程退出码 = 1` |
| R7 | m11 注入复现(见 §二) | 退出码 1,唯一红点 = `〔fv4〕` 组合根停机码断言 |
| R8 | m11 还原复跑 | 退出码 0,`all green (16 checks)` |
| R9 | m4 注入复现(见 §二) | 退出码 1,`[node_map_generator_test] 1/39 项失败`,唯一红点 = `〔fv1〕` 合法合流图断言 |
| R10 | m4 还原复跑 | 退出码 0,`all green (39 checks)`,工作区回到干净 |
| R11 | 件核 grep:`grep -n "randomize(\|RandomNumberGenerator.new(\|open_stream(\|FileAccess" game/core/node_map_generator.gd` | **零命中**(连注释都没有取数面引用);`grep -n level_index` 只命中第 33 行注释「不收 level_index」 |
| R12 | 件核 grep:全仓 `\.generate(` 非测试调用点 | 只命中 `board_generator.generate(...)`(另一类);`NodeMapGenerator` 的引用面 = 自身+`run_all.gd` manifest+两套新测试,**零生产消费方**(本批不接运行时,与卡片 §5 一致) |
### 1.3 批末代码域闸回执读数(未重跑,只核读)
`game/tests/.gates/receipt.json`:`commit = c0059bc5`、`domain = code`、`all_green = true`、`changed_vs_baseline = []`、`inherited_red = []`;闸 00/01/02/03/04/05/09/10 全 exit 0,闸 11(回放确定性对拍)= `NEED-APPROVAL` 未跑,计入 `not_run`——与「档位须用户发起」红线一致,不算新增红。**注意:实现报告 §五「批末重闸读数」仍是「待补」占位,回执读数没有回填进报告(见 §四 缺漏 3)。**
## 二、A 表:改动—验收对照表逐行核对(实现报告 §三 fv1–fv11)
每行三问:① 断言在测试文件里真实存在(file:line 已 grep);② 「真实入口」列确实走到被改代码;③ 「撤销或变异证明」在报告 §四 有对应注入记录。
| 尾缀 | ① 断言真实存在 | ② 真实入口核实 | ③ 变异记录对应 | 判定 |
|---|---|---|---|---|
| **fv1** 产出合格+产出自证 | 存在:`node_map_generator_test.gd:88,89`(三档×20 种子自证+入口/终点计数)、`:328,332,336,350,361,370,377`(违规夹具与合流夹具) | `generate()` 在 `node_map_generator.gd:47` 无条件调用 `validate_output(built, params)`,不过即 `_fatal` 且零交付(`:48-52`)——**产前强制成立,不是只在测试里直调**;`:82-83` 走 `_graph()`(真 `generate`)产图后再直调一次自证做二次核对 | m4(首写深度)→ 报告记 `:361` 红、m5(注掉终点恒 Boss 判据)→ 记 `:350` 红;**m4 本审计已实跑复现,红点逐字命中 `:361`** | **通过** |
| **fv2** 参数档 schema+.tres+ConfigDB | 存在 17 条:`level_gen_params_test.gd:16,47,50,52,55,62,72,75,78,81,85,88,92,97,100,102,105` | `:16` 走 `db.load_tables("res://data/tables", true)`=生产装载真入口;访问器 `config_db.gd:253 level_gen_params_row()` 实存并被 `:47/50/52` 与测试侧 `_params()`(`node_map_generator_test.gd:38`)消费;schema 直调 `validate()` 是卡片 §8.2 自身指定的入口(数据层无更上层入口),非降级 | m1/m2 → 报告记 `:16` 红 | **通过**(报告 §三 行的落点行号 `config_db.gd:42/:250` 与 HEAD 实值 `:43/:253` 漂移,`/22/146` 正确——见 §四 缺漏 2) |
| **fv3** 可复现(纯函数+counter 无关) | 存在:`:99`(同种子两次逐位同图)、`:109`(跨号位双实例对拍)、`:119`(异种子异图,10 种子去重 ≥8) | 三条全部经 `_graph()`→`NodeMapGenerator.generate(params, seed)`;`:101-111` 用两台服务处不同号位(`new_adventure(1)` vs `new_adventure(999999)`+7 次 `open_stream`)各建新生成器对拍——counter 无关确实从生产产图面进入 | m3(取数改 `open_stream("node_map")`)→ 报告记 `:109` 红 | **通过** |
| **fv4** 执行边界(无兜底图/fail-fast) | 存在:`node_map_growth_test.gd:64,70,74,82,91` | 静态面 `:64/70/74` 直调 `NodeMapGenerator.check_params()`;`:79-91` 用 `OS.execute` 起真实子进程跑 `-- fatal-fixture`,夹具 `_trigger_fatal` 经 `gen.generate(unsolvable, 42)` 真入口产图,再由 `is_fatal()` 决定停机码——审计实跑读数 `[fv4] 无解子进程退出码 = 1`,通道真实 | m11(`_fatal(...)`→`pass`)→ 报告记 `:91` 红;**本审计已实跑复现** | **通过** |
| **fv5** 岔路取舍两条 | 存在:`:163`(下一跳类型互异)、`:164`(支路构成互异+各有独有类型)、`:412`(同类型下一跳夹具)、`:162`(每档每种子的岔口存在性静默条) | `:127-161` 对 `generate` 产图逐岔口独立重算(不复用 `validate_output` 的实现),夹具面 `:412` 直调 `validate_output`;测试侧 `_branch_types()`(`:168-194`)与实现 `_check_fork_rules` 的独占段口径一致(代拍板 ②) | m8(侧支类型写死 battle)→ 报告如实记「进程红、红点落空图致命通道,判据本体由 `:412` 夹具级直证」 | **通过**(判别力短板见 §四 缺漏 4) |
| **fv6** 恰一店+归属锁定+多终点深度互异 | 存在:`:228`(DFS 全路径枚举恰一店)、`:229`(每终点前一位恰一店+店数=终点数)、`:230`(多终点异深)、夹具 `:387,397,404` | 三条主断言走 `generate` 产图+测试自身 `_all_paths()` 枚举(独立实现,非套用被测函数);`:213-221` 另在测试侧重算店数与前驱类型 | m6(商店位改 rest)、m7(两终点同深)→ 报告如实记「进程红,红点落空图致命通道」,未写成 fv6 尾缀专红 | **通过**(判别力短板见 §四 缺漏 4) |
| **fv7** 战斗保底 | 存在:`node_map_generator_test.gd:257`(三档×10 种子计数)、`:343`(低保底合法形状夹具必拒)、`:345`(保底 1 下不误伤) | `:255` 经 `_graph()` 真入口产图计数;`:343/345` 是 `ba660446` 专门为「让判据可被变异拦下」补的正反夹具,一拒一不误伤,判据按消息文本「低于保底」专断 | m9(砍穿保底)报告如实记「红点未落〔fv7〕尾缀、中止于空图读面」,并以 **m9b**(注掉判据)作判据级 RED-OK 记 `:343` 红 | **通过** |
| **fv8** 生长递增 | 存在:`node_map_growth_test.gd:57`(步数逐关变大)、`:58`(节点总数递增且增幅变大)+`:43-52` 五种子静默逐档读数 | `_reading()`(`:31`)经 `gen.generate(db.level_gen_params_row(L), 42)` 真入口,参数档从生产表读回,非硬编码 | **m10 = NOT-RED**,报告在 §三 与 §四 两处均明写「NOT-RED/如实标注拦截边界」,未冒充已拦截 | **通过**(拦截边界已如实呈报,见 §四 缺漏 5) |
| **fv9** 含岔口与出口结构 | 存在:`node_map_generator_test.gd:285`(三档各含 ≥1 岔口)、`:286`(L1 终点恰 1)、`:287`(L2/L3 含分区域大岔口) | 全走 `generate` 产图结构扫描+测试自身 BFS `_terminals_reachable()` | m12(`wanted` 写死 0)→ 记 `:285` 红 | **通过** |
| **fv10** RNG 单点(纯流面) | 存在:`node_map_generator_test.gd:313`(产图前后 counter 同值)、`:316`(同 (seed,scope) 同流)、`:317`(不推计数器且产图非空) | `:308-318` 真实例化 `RngServiceCore` 注入生成器、走 `generate` 产图后读 `counter()`;`pure_stream` 直调亦存在。静态面:R11 grep 在 `node_map_generator.gd` 内零命中 `randomize(`/`RandomNumberGenerator.new(`/`open_stream(`,生成器唯一取数点为 `:66 _rng_service.pure_stream(seed_val, SCOPE_STRUCTURE)`;闸 09 静态扫描回执 exit 0 | 与 m3 同发注入(报告记 `:109` 红) | **通过** |
| **fv11** 反哺点清单(非行为改动) | 件核对象存在:`reports/iter35-卡①-反哺点-2026-10-24.md` 七条表行 | 卡片 §6 六条逐格对上:①生成规格(多终点异深+最长路径赋值)②地图 :65 消歧③冒险结构 :293 深度域登记④level-map 呈现随动⑤待办清单 06 状态⑥roadmap 编入笔;另加实现新发现⑦(出口数 3 是支路互异天花板)。每条有「文件与节/改成什么/依据」三列 | 纯文档产出物,无代码变异,报告与卡片均标「非行为改动」 | **通过** |
**契约逐条复核(与 A 表交叉)**:契约 1(纯函数+counter 无关+纯流面)=fv3/fv10 过;契约 2(id/depth 拆两轴+最长路径赋值+多终点异深)=节点字段恰 `id/type/depth/next`(`_mk:414`)、`validate_output:174-179` 逐节点比对最长路值、`:219-224` 异深判据,过;**契约 6(`generate` 不收 level_index)**=签名 `generate(params: Dictionary, seed_val: int)`(`:34`),全仓调用点零传关卡号(R12),过;契约 4(无兜底图)=生成器内零模板/零上一张/零空图回退分支,三处 `return {}` 全在 `_fatal` 之后(`:41/45/52`,注释明写「致命中止后不可达;本行即无残图交付的显式证明」),过。
## 三、B 段:撤销证明复现记录(2 条,真跑)
前置:`git status --short` 空;`node_map_generator.gd` 为 UTF-8、547 行全 CRLF(注入后仍 547 CRLF,行尾未被工具改写)。
### B1 · m11 无解路径致命短路
- 锚点注入(`game/core/node_map_generator.gd:40`,唯一命中,1 行改):
- 原文:`_fatal("参数无解致命中止(契约 4——无兜底图、禁软回退)")`
- 注入:`pass # m11 mutation injection`
- 跑:`--script res://tests/unit/core/node_map_growth_test.gd` → **退出码 1**
- 红点读数(逐字):
- `[fv4] 无解子进程退出码 = 2`(原为 1)
- `ERROR: [FAIL] 无解参数档置致命封印并由组合根停机(退出码恰 1,无残图交付)〔fv4〕`
- 同批其余三条〔fv4〕(`:64/70/74`)仍 PASS——红点精确落在子进程停机通道那条,未泛化。
- 还原:`git checkout -- game/core/node_map_generator.gd`(HEAD 已含实现,安全)→ `git status --short` 空
- 还原复跑:**退出码 0,`all green (16 checks)`**
- 结论:**与报告 §四 m11 记录逐字一致,RED-OK 复现成立。**
### B2 · m4 最长路径计算改首写
- 锚点注入(`node_map_generator.gd:440`,唯一命中,1 行改):
- 原文:`out[nid] = maxi(int(out.get(nid, 0)), int(out[id]) + 1)`
- 注入:`if not out.has(nid): out[nid] = int(out[id]) + 1 # m4 mutation injection`
- 跑:`--script res://tests/unit/core/node_map_generator_test.gd` → **退出码 1**
- 红点读数(逐字):`ERROR: [node_map_generator_test] 1/39 项失败`,唯一 FAIL 行 =
- `ERROR: [FAIL] 合法合流图(第二入口直插主链,深度取最长路 3)自证零错误〔fv1〕`
- 首写口径使合流节点取到短路值(3→1),与 `:174-179` 最长路比对不符 → 自证报错,正是报告 §四 m4 声明的红点位置。
- 关键旁证:三档×20 种子主自证〔fv1〕`:88` 仍 PASS(生成器构型无合流,取长/取首等价)——说明这条断言拦的正是「合流图深度语义」,不是泛泛报错。
- 还原:`git checkout -- game/core/node_map_generator.gd` → 工作区干净
- 还原复跑:**退出码 0,`all green (39 checks)`**
- 结论:**与报告 §四 m4 记录逐字一致,RED-OK 复现成立。**
## 四、C 段:测试削弱检查(逐条给依据)
| 检查项 | 结论 | 依据 |
|---|---|---|
| 旧断言删改 | **零削弱** | `git diff --numstat` 14 个文件删除列全为 0;`run_all.gd`+3 行、`config_db.gd`+8 行、`rng_service.gd`+14 行(`pure_stream` 纯新增,`open_stream/derive_at` 未触);三套测试全为新建文件——与卡片 §8.2「零旧断言改写」预声明一致 |
| manifest 登记(未登记=闸 02 不执行) | **齐且口径正确** | `run_all.gd` 三行新增均为 `"expect": 0`,路径与盘上文件一一对应:`tests/unit/data_config/level_gen_params_test.gd`、`tests/unit/core/node_map_generator_test.gd`、`tests/unit/core/node_map_growth_test.gd`;三套件单跑退出码实测均 0(R4/R5/R6),与 expect 0 自洽 |
| 参数档数值 vs 卡片 §8.1 | **逐格对上,无放宽** | `level_gen_params.tres`:layers 6/9/13 ✓、branch_density 0.3/0.5/0.7 ✓、配比 .50/.20/.20/.10|.50/.20/.15/.15|.55/.15/.15/.15(各合计 1)✓、entry 1/2/2 ✓、exit 1/2/3 ✓、battle_floor 4/6/8 ✓、fork 2/3 三档 ✓;代拍板 ④ 自陈「取卡片原值、未做域内微调」与实物一致 |
| 扫描面种子数是否被缩小 | **未见对卡片的缩小;有一处对报告自述的漂移** | 卡片 §8 V1/T3 措辞=「三关参数档×固定种子」,未规定种子条数。实测主自证面 `node_map_generator_test.gd:81 range(42, 62)`=42–61 共 **20 种子 × 3 档**,与报告 §二#1「三档 × 20 种子(42–61)」一致;其余面:fv5/fv6/fv9 各 3 种子〔42,43,44〕、fv7 10 种子、fv8 5 种子、fv3 异图 10 种子——均落在卡片授权面内。**漂移在报告侧**:报告记该套件 42 条、实测 39 条(见缺漏 1) |
| 生成失败的回退分支(契约 4 禁) | **零回退分支** | 生成器不引用 ConfigDB/`level.tres`/模板池(R11/R12 grep 零命中),无「失败用模板/用上一张」路径;`_fatal` 后三个 `return {}` 是停机后的不可达行、并由 `is_fatal()` 要求消费侧拒收;本批**无任何生产调用方**取用产图(`NodeMapGenerator` 引用面=自身+manifest+两测试),故 `{}` 不存在被当合法图消费的现实通道 |
| `--script` 禁裸 autoload(F8/code-conventions:71) | 合规 | 生成器 `_init(rng_service = null)` 构造注入,未注入即 `push_error`+致命(`:42-45`);测试侧 `RngScript.new()` 显式实例化后注入 |
| NOT-RED 与「红点落别处」是否如实呈报 | **如实** | 报告 §四 m10 明写 `**NOT-RED**` 并在 §三 fv8 行再次标注;m6/m7/m8/m9 明写「拦截发生(进程红),红点落在空图致命通道/未落〔fv7〕尾缀」,并各自改以夹具级断言(`:404/:387/:412`)或 m9b 作判据级证明——四条**均未被写成 RED-OK/已拦截**,符合「无变异红记录只写已实现、拦截能力未证」红线 |
| 像素纪律/数值单点 | 合规 | 本批无像素结构件;玩法数值只落 `.tres`,生成器不硬编码旋钮值(全部读 `params`)。实现自由面常量(`MAX_WIDTH=4`、三岔概率 `0.35`、`_trunk_len` 取 `L/2`)属 HOW 面,卡片 §10 ⑤ 授权、报告 §八与代拍板 ⑤ 已登记其副作用(分支密度实际生效数受锚点几何限制) |
### 缺漏与待办(审计判定,非红线违例)
1. **实现报告断言计数不符**:报告 §一 T3 与 §二#7 记 `node_map_generator_test` 42 条、合计 17/42/16;HEAD 实测 **39 条、合计 17/39/16 = 72 条**(另 `63a6ea80` 提交信息记 68 条,说明该数在批内漂移后未回填)。合回前须把报告读数订正为实测值。
2. **实现报告 §三 fv2 行的落点行号漂移**:记 `config_db.gd:22/:42/:146/:250`,HEAD 实值 `:22/:43/:146/:253`。
3. **实现报告 §五(批末重闸读数)与 §六(审计结论)仍为「待补」占位**:完成定义 #8 要求重闸读数入报告;回执已在盘(`c0059bc5`/`domain=code`/`all_green=true`/闸 11 按红线未跑),须把这段读数抄进 §五,本报告可作 §六 依据。
4. **三条夹具级断言按错误类别判定、判别力弱于消息级**:`:404`(终点前驱非店)与 `:412`(岔口同类型下一跳)用 `_has_cat(..., "structural")`——若只注掉该条判据、同夹具另有其它 structural 违例,断言可能仍绿(`:404` 的夹具确实同时触发「店数≠终点数」「穿店数≠1」两类,存在掩蔽源);`:387`(多终点同深)经逐节点推演无同类掩蔽源,专指成立。对照:`:350`(终点非 Boss)与 `:343`(低于保底)已按消息文本专断,是应当效仿的体例。**不阻塞合回**——m5/m9b 已证这两条判据可被拦,m6/m7/m8 已从真实 `generate` 入口证得套件级拦截。
5. **m10 拦截边界真实存在**:「只调分支密度」不足以破坏节点总数增幅递增。报告已把单调性交给参数档域校验(层深递增且增幅变大,`level_gen_params.gd:64-71`+`:85` 断言)与 fv8 三档读数共同承载,属如实标注,不是漏判。
6. **新增旁路入口 `generate_for_debug`(`:58-61`)当前零调用方**:只构型、不自证、不致命。卡片 §8 两分法授权调试接口,但代拍板单把它列为「白名单外需呈报第 2 件」待用户追认;本批无运行时接线故不构成「不合格产出进玩法」通道。卡② 接线时须保持生产路径只走 `generate`。
7. **代拍板六条+白名单外两件待用户追认**(致命面形态从「生成器内停机」改为「置封印+组合根停机」,fv4 判据随之改为「停机码恰 1」)——语义等价、有断言兜住,但追认动作未完成。
## 五、结论
**有条件通过(可以合回,条件是下列三件在合回动作前后立即补齐,无需重跑实现)**:
1. 实现报告 §五 回填批末代码域闸读数(回执 `c0059bc5`:domain=code、all_green=true、闸 11 按红线未跑)、§六 挂本审计报告,并把断言计数由 42 订正为实测 39(合计 72)。
2. 实现报告 §三 fv2 行的 `config_db.gd` 行号按 HEAD 实值订正(`:43/:253`)。
3. 用户对 `reports/iter35-卡①-代拍板-2026-10-24.md` 六条+白名单外两件(致命面形态、`generate_for_debug`)作追认或推翻;推翻则回写实现面。
判定依据:卡片 §1 完成定义八项逐条有真实入口断言兜住(§二 A 表全通过);两条撤销证明(m11/m4)独立复现且红点逐字命中报告声明;本批零删改既有代码与既有断言、零 `design/` 与根规则文件触碰、参数档数值与卡片 §8.1 逐格一致、无回退分支、RNG 单点静态核零命中;NOT-RED 与红点漂移均如实呈报。
**不通过项清单**:无(不存在必须退回实现或上游的缺漏;上述三件为产出物回填与用户裁决动作,非事实性缺陷)。
**另须留意(非本批验收范围)**:卡② 因 §0 硬交付序列的「生成图深度扩面覆盖批」未立卡而停工(`reports/iter35-卡2-停机呈报-2026-10-24.md`),迭代 35 因此不是一次合并——卡① 可否单独合回属用户拆批裁决,本审计只判定卡① 代码面验收闭合。
@@ -1,29 +0,0 @@
# 迭代 35 卡② 代拍板追认单(节点图消费侧换代批)
- 日期:2026-10-24
- 依据:`reports/需求卡片-节点图消费侧换代批-2026-10-21.md` §10 代拍板白名单六条——授权发生在写卡段,本批只执行预授权并留痕
- 待用户动作:追认或推翻。推翻任一条即回写对应实现面(不改设计文档)
## 一、白名单内六条的执行值
| # | 卡片白名单条目 | 本批拍定值 | 落点 |
|---|---|---|---|
| ① | 图数据内部适配形态 | 生成图落到 `level_row` 的**行副本**上(`row.duplicate(true)` + `merged["nodes"] = graph["nodes"]`),表本体不被写脏;节点字段恰 `id/type/depth/next`,句柄即 `id`;读面 API 六签名逐字不变 | `game/core/level_runner.gd` `_assign_generated_graph`/`nodes()`;断言=`node_map_templates_test` 「起关生效图=生成器同档同种子直取逐位一致」 |
| ② | 校验实现形态与错误类别命名 | 无环判据取「出边目标 `depth` 严格大于源」写法(不做 DFS 判环);错误类别沿用 `structural`/`dangling_next`/`dup_key`/`enum`/`domain` 词表,零新增类别 | `game/data/schemas/level_table.gd` `validate_graph`;断言〔v1〕17 条 |
| ③ | 断点键换代细节 | 代差标记键命名 `graph_gen_v2`(值恒 1);退役键=`template_pick`;`node_id`/`visited_ids` 按图内句柄落档(与 `current_node_id()`/`visited_ids()` 同空间);旧断点拒绝后的盘面处置=**留档不清**(`resume_adventure` 返回 false + push_error,菜单侧「继续上局」自然失效由既有空断点态承载) | `game/core/adventure_runner.gd` `_snapshot_breakpoint`/`resume_adventure`;断言=`breakpoint_resume_test` P7 六条+`node_map_templates_test` ⑤ 拒绝条 |
| ④ | 冒烟断言定位写法与措辞 | 断言定位两分:**结构/覆盖/确定性类**直取生成器(参数档+种子 42/42–61 扫描),**行进/停点/兑付类**走 runner 与 AdventureRunner 真实入口(`start_level`/`start_level_external`/`pick_next_node`/`resume_adventure`);断言文本一律不写死节点编号形状 | `game/tests/integration/node_map_templates_test.gd`、`game/tests/unit/core/level_shop_economy_test.gd`〔v11〕、`game/tests/unit/core/adventure_feats_test.gd` |
| ⑤ | route 轴实现与 MC 字段值形态 | route 轴沿用「候选句柄升序= min/降序= max」的既有评分 tie-break(`_route_pick` 只换寻址空间,评分逻辑零动);MC 出数字段 `level_templates` → `level_maps`,值形态 `"%d#%d" % [关卡序号, 主种子]`(关卡×生成图标识) | `game/sim/level_autoplay.gd` `_route_pick`/`_on_adventure_node_entered`、`game/sim/adventure_monte_carlo.gd` 出数面 |
| ⑥ | 提交切分与分支命名 | 分支 `iter35b`(工作区 `../g-plan2-iter35b`);切分=覆盖数据批 → T1 校验换代 → T2 一口(④静态检查退役+随动)→ T2 二口+T3 断言面主体 → T3 收口(商店宿主)→ 变异验证与产出物 | git log(`9214ef8e`、`c0dd4420`、`98c61d50`、`9ee3bea1` 及后续收口笔) |
## 二、白名单外、本批自认需要呈报的五件
1. **「奖励节点三选一 ≥1 次」断言的替代形态**(`adventure_feats_test`)。旧判据「L1 链必经 1 个」的前提是单链模板形状,随模板池消亡;实测确定性选路评分在种子 42–47 × min/max 两轴共 12 次全程冒险里**一次都没有走进奖励支路**(生成图里奖励节点的句柄序恒在战斗支路之后,评分优先推进)。若保留「≥1 次」原句就是逼着改扫描口径凑数。本批拆成两条:① 图侧「三关生成图各含 ≥1 奖励节点」;② 行进侧走真实入口——打赢入口战、在岔口显式 `pick_next_node` 点奖励支路、断言三选一候选可取(3 件)且停点在途且兑付受理。语义从「形状必经」换成「接线可用+图上存在」,未放宽到恒真。
2. **三处 `_level_active_nodes` 副本曾是假绿**。`templates` 键清出后该 helper 落到 `row.get("nodes", [])` 返回空数组,凡以它为节点的扫描断言(覆盖义务、Boss 深度、逐节点行集)都变成「扫描面为空所以零违例」的空转绿。本批把三宿主 helper 换成参数档+种子 42 的生成图取数,并在覆盖断言里加「扫描节点数 > 0」的非空前置。这条是缺陷清偿,不是判据改动,但因为它把三条一直绿着的断言重新变成有效的(当场新增暴露一次 `boss_depth` 读到 -1 的真红),特此留痕。
3. **商店到达余额读数 2 → 3**(`adventure_feats_test` ⑦ GP 跨关延续)。旧断言 `shop_seq.size() == 2` 的依据是「L1 单链无店、L2/L3 各一店」;卡② 商店编排语义为「每终点前恰一店」⇒ 每关路径必穿一店 ⇒ 三关全程 = 3 次到达。本批按新语义把读数断言改成 3 并保留「首达余额 > 0」。若 S3 三性质扫描(`level_shop_economy_test`)与这条投影不一致,二者之一必红,属互相校验。
4. **`_boss_depth` helper 随删两处**(`round_flow_skill_pool_test`、`table_structure_guard_test`)。它们调用已退役的模板取数面、且在各自宿主内**零调用方**(〔fv13〕换代时留下的死件)。按契约 6「禁留死代码」删除;不涉及任何断言删除。
5. **两个呈现宿主的夹具拓扑重建**(`level_map_type_vis_test`、`level_map_info_fog_test`)。旧夹具用「6→3 回边」表达非法图,而新形状要求 `depth` 沿出边严格前进,回边无法自洽表达;本批把该夹具改为长跳前向边+侧链节点,保留全部阈值与可见集断言,负向回边判据改由 `level_table_validate_test`〔v1〕的夹具图承载。此条由并行子代理执行,**独立验收审计须复核其「断言条数与阈值零改动」的自述**(自述见实现报告随动段)。
## 三、遗留读数义务(与实现报告同册)
- 用户目检两条未做(登记不阻塞):三关实机选路观感不回归、首局种子 42 固定图的教学体验。
- MC/对拍零跑:本批无玩法数值改动,按红线不发起跑批;11 回放确定性对拍按前批裁决不补跑。
@@ -1,25 +0,0 @@
# 迭代 35 卡② 反哺点清单(节点图消费侧换代批)
- 日期:2026-10-24
- 依据:`reports/需求卡片-节点图消费侧换代批-2026-10-21.md` §6 关联文档同步面六条+实现批执行中新发现的落点
- 处置:本批为代码实现批,禁写 `design/` 与根流程清单,以下只列不改;每条由用户裁决后归文档批落文
## 一、卡片 §6 预列六条
| # | 文件与节位 | 现状陈述 → 应改成 | 依据 |
|---|---|---|---|
| ① | `design/gdd/systems/冒险循环/关卡节点地图.md` :57/:156/:178 | 「战斗|携带节点编号」「组装关卡序号 + 节点编号」「每场开战调用携带(关卡序号 + 节点编号)」三处 → 统一为「关卡序号+节点深度(自入口步数)」,与 :23/:65/:111/:119 同口径 | 卡② 契约 2(弃节点编号寻址)+ D1:65/:119 定稿句;实现落点 `game/core/level_runner.gd` enc 组装段(`node_depth` 取节点 `depth` 值) |
| ② | `design/gdd/systems/冒险循环/冒险结构.md` :293、:264 | :293 覆盖义务「每个战斗与关底节点(关,深)在敌人与棋盘生成的数值表中有精确行」→ 「敌侧按深度带命中(落带不早于请求深度,禁顶 clamp 消解)+板侧解析命中」;:264 关卡行集行的「旧模板池随实现批清数据」括注已成既成事实 → 注销括注、改述为参数档+生成器承载 | 卡③ 契约 1+卡② 完成定义 6;实现落点 `game/data/tables/level.tres`(templates 键已清出)、`game/tests/unit/core/level_shop_economy_test.gd` 覆盖断言〔v11〕 |
| ③ | `design/gdd/systems/冒险循环/关卡节点图生成.md` | 用语核对结论:消费侧注释只引用其「产出规格/执行边界」节号,未发现「岔口/终点/路径」用语漂移 → 记「无漂移」 | 实现在 `game/data/schemas/level_table.gd`、`game/core/level_runner.gd` 注释面自查(卡② T0 事实坐实项) |
| ④ | `design/gdd/ux/level-map.md` | 呈现面随动登记:句柄寻址后地图显示的节点数字=图内句柄 id(非深度、非数组序),多入口/多终点/含岔口三形态需补呈现条款 → 归卡④ 或文档批处理,本批未改呈现代码 | 卡② §6 表「呈现面随动义务」;实现落点 `game/core/level_runner.gd` `node_id_of`/`visited_ids` 语义换代 |
| ⑤ | `待办清单.md`(06) | 卡② 条目状态推进与退役记载:本批实现闭合后该条目按流水线规则由收口段处理,本会话未改该文件 | req-card 06 状态回写义务+迭代批禁改根流程清单红线 |
| ⑥ | `roadmap.md` | 迭代 35 行批内状态刷新(卡② 由「已编」推进到「实现批完成待收口」)——本会话未改该文件 | 同上(实现批禁写根规则文件) |
## 二、实现批新发现的四条(卡片未预列,一并呈报)
| # | 文件与节位 | 发现 | 建议处置 |
|---|---|---|---|
| ⑦ | `game/tests/验证集清单.md`(批 B 迁移账本的断言索引,11 行含 `first_script`/`template_pick` 措辞) | 该清单是批 B 迁入时的断言文本快照索引,只由 `tools/extract_checks.py` 手工重生成、不进任何闸;卡② 断言换代后其中 11 行文本与行号已过期 | 由用户裁决:跑一次 `tools/extract_checks.py` 重生成,或在清单头部登记「换代批后快照失效、按宿主现文为准」 |
| ⑧ | `game/tests/integration/node_map_templates_test.gd`(宿主文件名) | 该宿主现承载「生成图确定性断言套」,文件名里的 templates 是模板时代遗留名;卡片 S6 明令换代断言落「S1 同宿主」且 manifest 零新增登记,故本批保留原名 | 待用户裁决:改名(如 `node_map_determinism_test.gd`)须同批改 `run_all.gd` manifest 路径行,属独立小批 |
| ⑨ | `game/data/tables/level.tres` 表尾注释 | 卡片 T3 要求表尾写「15 张模板去向+参数档字段指引」,实现里带了一句「随迭代 35 卡② 清出」的迭代叙事,与 doc-conventions §5「禁写变更叙事」的口径有张力 | 待用户裁决:保留(卡片明令的去向注记)或删去迭代号只留图源换代事实句 |
| ⑩ | `design/gdd/systems/冒险循环/关卡节点地图.md`(或 06 体验验证清单)——教学担子交接 | 卡② 待裁点已定「模板 0 教学重放语义废除,教学位由首局固定种子 42 的生成图承载」;文档侧仍写着「模板 0=教学图」的表述在 ①②之外的段落里残留,且「首局图观感是否可当教学」属真人判断 | 建议随 ①② 一并清扫措辞,并把「首局教学图体验」列进 `体验验证清单.md`(卡片 §8.2 已把它列为用户目检项,登记不阻塞) |
@@ -1,172 +0,0 @@
# 迭代 35 卡② 实现报告(消费侧换代批·含生成图深度扩面覆盖数据同批落)
- 日期:2026-10-24 起批(进行中)
- 工作区:`D:/code/g-plan2-iter35b`(分支 `iter35b`,起点=master `99e1b20b`,已含卡① 合回 `6475ebff`)
- 卡片:`reports/需求卡片-节点图消费侧换代批-2026-10-21.md` v1.1
- 批性质:代码实现批——`design/` 与根规则文件只读;账面随动义务落 `reports/`(见 §五)
- 开工实况:卡② §0 的硬交付序列(生成图深度扩面的敌/板表覆盖)由用户 2026-10-24 裁决**与本卡同批落**(卡片原文允许「须先落或与本卡同批落」),故本报告 §一 先记覆盖数据批,后续各段记卡② 本体。
## 一、覆盖数据段(已完成·提交 `9214ef8e`+判据加固一笔)
**授权口径**:数值面改动本属独立批次;用户点名随本批同落,取值授权为「按现有曲线插值、全 provisional」。
| 面 | 改动 | 量程依据(卡① 实测) |
|---|---|---|
| 敌侧战斗带顶 | L1 3→6、L2 7→9、L3 7→13,各加一行;敌种复用在册 id(bugbear / giant_spider / duergar),零新内容 | 生成图实际战斗深度 L1≤4、L2≤4、L3≤9;顶带按立卡要件取该关最大生成深度 |
| Boss 按终点深度分带 | L1 加带 6、L2 加带 8、L3 加带 11/12/13(敌种复用 ogre_chief / drider / duergar_king) | 终点深度=layers−r:L1 6;L2 9/8;L3 13/12/11 |
| 板侧 `node_depth` 键域 | 补齐 L1 0–6/L2 0–9/L3 0–13(新增 12 行,其余字段按该关同档行复制) | 生成图每个深度都要出板(覆盖义务含全部节点类型) |
| 敌种与数值纪律 | AC 全部落在迭代 5 已裁带宽(杂鱼 0–5/Boss 8–12);模板时代带键 0–3/4/9 与 hobgoblin 留任位一律不动 | `table_structure_guard_test` 带域断言零改判 |
**验收断言**(宿主 `game/tests/unit/core/level_shop_economy_test.gd` 新增 `_smoke_generated_coverage`;扫描面=三关参数档 × 种子 42–61):
- 〔v11〕敌侧落带——生成图每个 battle/boss 节点深度经 `resolve_enemy_rowset` 解析出行的 `depth_band ≥ 请求深度`(等价 `EnemyTable.band_of` 非 -1)。
判据加固记录:初稿写作「行集非空」,被撤销证明证伪——越顶时 resolver clamp 到顶带照样返非空行,正是设计禁的「顶 clamp 消解」,故改为落带等式判据。
- 〔v11〕板侧精确命中——`resolve_board_gen(L, D)` 非空且返回行 `node_depth == D`。
- 〔v11〕多终点带键互异——同图各终点深度解析出的 `depth_band` 两两不等。
- 量程读数:L1 深度域 0–6、L2 0–9、L3 0–13;宿主全绿 152 checks(其中本段新起算 3 条)。
**变异验证**(逐条注入→最窄宿主见红→`git checkout` 还原;注入前实现已入库,防还原吞掉未提交码):
| 注入 | 期望红点 | 实测 |
|---|---|---|
| L2 Boss 带键 8 并入顶带 9(回单带) | 带互异 | RED-OK:`多终点 Boss 各终点解析带键两两互异〔v11〕` 红 |
| L3 战斗顶带 13 降到 8(深 9 战斗节点越顶) | 敌侧落带 | RED-OK:`敌侧解析落带 ≥ 请求深度〔v11〕` 红(连带 `(3,battle,8)` 精确键断言红) |
| 删除 board_gen `(3,13)` 精确行 | 板侧精确命中 | RED-OK:`每个节点深度在 board_gen 精确命中〔v11〕` 红 |
| L3 战斗顶带 13→12(首版注入) | 敌侧落带 | NOT-RED·已标注:13 号战斗顶带未被任何生成节点请求(该行为立卡要件保守上限的余量)——据此把判据从「非空」改为「落带 ≥ 深度」,并补上一条真红注入 |
**旧断言随动四条(声明于此,非静默改判)**:
| 断言 | 原口径 | 新口径 | 理由 |
|---|---|---|---|
| `table_structure_guard` 〔fv11〕 | 敌人表 20 行且键序=迁移表序 | 28 行且键序=覆盖表序 | 扩带必然改行数与键序;行序即契约的判据形态不变 |
| `table_structure_guard` 〔fv13〕 | 三关 Boss 各恰一行且 band=图 Boss 节点深度 | 三关 Boss 带键清单=覆盖表(L1 4/6、L2 8/9、L3 9/11/12/13) | 判据对象是单终点模板时代形状;生成图多终点必然多行,「互异」移交〔v11〕运行时把关 |
| `level_shop_economy` 混编段 | 注入段还原后表回 20 行 | 回 28 行 | 同一基线行数随覆盖批换代 |
| `level_shop_economy` 深度 8 段 | `(L,8)` 无板行/战斗行残留(商店房专属位清理确认) | `(L,8)` 板侧覆盖行在册;战斗侧仍禁 `(L,battle,8)` 精确键 | 生成图下深度 8 是正常可行深度;扫描面未缩,只按现行设计换板侧正负号 |
## 二、卡② 本体进度
| T 卡 | 状态 |
|---|---|
| T0 事实坐实与卡① 接口对齐 | 待做——接口四件已可由卡① 定稿直读(`generate(params, seed)` 不收 level_index、`{nodes,entries,terminals}`、节点 `id/type/depth/next`、参数档字段名),本段只需核 §3 行号漂移 |
| T1 加载校验换代(四检+良构) | 完成(提交 `c0dd4420`,明细见 §二·五)——`LevelTable.validate_graph(nodes)` 静态单点在位,表加载期图校验与旧六判据退役,新宿主〔v1〕17 条+manifest 登记,run_all 全绿 59 套件,四条变异注入均见目标尾缀红 |
| T2 消费侧切源与行进/定位/确定性换代 | 未开工——任务见分支待办 #3 |
| T3 模板清理与 S1–S8 断言换代 | 未开工(S5/V11 覆盖断言已由 §一 提前落位)——任务见分支待办 #4 |
| T4 产出物 | 本报告即起始件;代拍板单与反哺点清单随收口补 |
## 二·五 T1 加载校验换代(已完成·提交 `c0dd4420`)
**改动**:`LevelTable.validate_graph(nodes: Array) -> Array` 静态单点承载四检+良构基底(契约 1 原口径:①入口(无入边)≥1 且终点(无出边)≥1;②全员从某入口可达且可达某终点;③终点恒 Boss 且 Boss 无出边;④出边目标深度严格大于源=无环。良构=句柄唯一·出边全命中·type 五类枚举·battle/boss 带深度)。表加载期不再校验图:旧六判据(Boss 恰一/战斗≥2/单链末 Boss/前三位纯战斗/出度≤2/Boss 编号最大)+模板池校验分支+BFS 层宽≤5 一并删除,行级校验(level_index 唯一/display_name/rest_heal_pct/info_visible_layers)保留。商店位与入口终点个数按「勿扩勿缩」不入本检。
**新宿主**:`game/tests/unit/core/level_table_validate_test.gd`〔v1〕17 条断言(正例三形/负例八类/范围反证三条/②④ 关系实证三条)+ `run_all.gd` manifest 一行;闸 02 实跑 59 套件全绿。
**撤销(变异)证明**——逐条注入→本宿主见红→`git checkout` 还原,注入前实现已入库:
| 注入 | 目标尾缀 | 实测 |
|---|---|---|
| 注掉「终点恒为 Boss」判据 | 〔v1〕终点非 Boss 负例 | RED-OK:`负例:终点非 Boss 命中「终点恒为 Boss」〔v1〕` 红 |
| 注掉前进方向判据 | 〔v1〕回边/环两负例 | RED-OK:`回边(目标深度不严格大于源)…` 与 `环(2→1 回边)…` 双红 |
| 注掉句柄唯一登记 | 〔v1〕dup_key 负例 | RED-OK:`负例:句柄重复报 dup_key〔v1〕` 红 |
| 注掉入口收集分支(附带做) | 〔v1〕正例 | RED-OK:多入口/含岔口正例双红(入口集空→可达性全断) |
| 前两轮注错语法(`if false and if …`)致解析错 | — | 已作废重跑,未计入红证;教训=注入必须保持可编译,否则「红」是解析失败给的 |
**判据②与④在 DAG 上互斥(新发现,拟入反哺点)**:无环图每个源点都是入口、每条极长路都止于终点,故「孤儿/断头」构造不出独立负例;② 的真实定位是 ④ 失效时的纵深防御面。测试据此改为两独立链正证不误伤+自环先被 ④ 拦的实证。文档(关卡节点地图 v2.1 :51 走图三句/关卡节点图生成 v1.1 结构铁律)宜注明这一兜底定位,免得后续批误判 ② 有独立拦截能力。
**件核**:全仓 grep 六判据消息文本 → 零残留;唯一余留是 `game/data/tables/level.tres:22` 表尾模板生成史注释,随 T3 模板清出一并消失。
**本段旧断言随动(四条,声明)**:`level_shop_economy` ③ 段整段改走 `validate_graph`,其中「入口唯一违例」随设计换代翻为多入口合法正例、「孤儿」条改为非 Boss 终点;`level_map_type_vis` 夹具注释订正;`round_flow_skill_pool` 敌表池清单 20→28 行补覆盖批八行池克隆键;`board_gen_reward`「(2,3) ceil 上取」改判精确命中并以「临时摘该行」的夹具面保留 ceil 能力判据。(前两条属本卡 §9.5① S 随动族;后两条属 §一 覆盖批的键域随动,先前漏跑整套未暴露,本轮 run_all 抓出。)
## 二·七 T2 第一口(已完成·提交 `98c61d50`)
跨表校验 ④ 整体退役(详见提交信息),两条拦截语义由〔v11〕承接、覆盖不降级的依据=生成图深度域是模板深度域的超集;`save_manager` 首次冒险位注释随确定性承载换代改口径(键与行为零改动);run_all 59 套件全绿。
## 二·八 续做清单(冷启动可照此接上·T2 剩余+T3)
1. `game/core/level_runner.gd`:删 `_resolve_template_row`(:300-324 含 `active_template_name/index` 声明)→ 起关改调 `NodeMapGenerator.new(RngService).generate(ConfigDB.level_gen_params_row(L), seed)`;拿到图后、进节点前调 `LevelTable.validate_graph(nodes)`,违规 `push_error`+返回 false(走 `main.gd:396 _fatal_screen` 挂点);`start_level`/`start_level_external` 的 `template_pick` 尾参删除;`_entry_node`→`_entry_nodes`(多入口,入口停点候选=全部入口,单入口逐位不变);`_node_id`(:341-347)改返回 `id` 句柄、`_out_ids`/`_out_nodes`/`visited_ids`/`pick_next_node`/`_restore_to_stop` 同空间随动、单链隐式出边(:360-385 体内)退役;`begin_battle` enc(:513-525)`node_depth` 取节点 `depth` 值(键名不变)。
2. `game/core/adventure_runner.gd`:删 `_first_script`(:45/:102/:194)与 `template_pick` 计算传递(:850/:852-854/:863);断点快照删 `template_pick` 键(:1013)、`node_id`/`visited_ids`(:1000/:1017)句柄化;扩列**代差标记键**(缺省 0/写 1),`resume_adventure` 遇缺标记键旧断点=返回 false+`push_error`(禁静默按新句柄回放)。
3. `game/presentation/main.gd`:删 `first_script` 参数构造(:594-596);种子三分判定(:1476-1490 `_seed_value`)零改动。
4. 断言与驱动面换代(S1–S8,见卡② §8.1):`node_map_templates_test` 模板段①-⑥退役+⑦改写为「首局种子 42」,同宿主新增确定性四断言;`_level_active_nodes` 三副本(`level_shop_economy:970`/`adventure_feats:812`/`round_flow:357`)改经生成器取图;`level.tres` 三行 `templates` 键删除+表尾注释去向段;`sim/level_autoplay.gd`(:37/:63/:141/:200-202/:12/:377-379)与 `adventure_monte_carlo.gd:139` 换代(`level_templates`→`level_maps`);`probe/shot_probe.gd:12-13`、`ui_click_probe.gd:373` 假设性质化;`breakpoint_resume_test`/`pool_case_d_test`/`feat_vouchers_test`/`cross_system_flow_test:79`/`meta_progression_forge_test:316` 随动。
5. 件核:全仓零 `first_script`/`template_pick`/`active_template`/`node_depth 当身份` 引用;`level.tres` 无 `templates` 键。
6. 收口顺序:T2+T3 必须同轮(拆开中间态必红)→ `run_all_gates.sh --code` 全绿 → 独立验收审计 → 合回 → 反哺点/代拍板/待办清单状态随批。
7. 待用户项:覆盖批八行与棋盘 12 行数值为插值 provisional(真人试玩定味);数值面已动,11 回放确定性对拍与 `balance_verifier` 是否发起需重新裁定。
## 二·九 T2 第二口=消费侧切源主体(已完成·提交 `9ee3bea1`+`38492116`+`78924fdd`+`548cd2da`)
§二·八 清单 1–3 与 5 逐条落定:
- `level_runner.gd`:`_resolve_template_row` 与 `active_template_name/index` 删除,新增 `_assign_generated_graph(row, seed)`(`db.level_gen_params_row(L)` 取参数档 → `NodeMapGenerator.generate(params, seed)` → `LevelTable.validate_graph(graph.nodes)` 违规 `push_error`+返回 false,无任何兜底图);`start_level(level_index, seed, base_override)`/`start_level_external(..., defer_entry, resume_state)` 的 `template_pick` 尾参删除;`_entry_node`→`_entry_nodes() -> Array[Dictionary]`(全部无入边节点,多入口首跳即选路);`_node_id` 取 `id` 句柄,`_out_ids`/`_out_nodes`/`visited_ids`/`pick_next_node`/`_restore_to_stop`/`_bfs_layers` 同句柄空间随动,单链隐式出边(数组序兜底)整体退役;enc `node_depth` 取节点 `depth` 值、键名不变。
- `adventure_runner.gd`:`_first_script` 字段与参数读入、`template_pick` 计算与传递全删;断点快照 `template_pick` 键 → `graph_gen_v2: 1` 代差标记键;`resume_adventure` 首检该标记,缺键旧断点返回 false+`push_error`(禁按新句柄空间静默回放)。
- `main.gd` 删 `first_script` 参数构造(种子三分判定 `:1476-1486` 零改动,首局恒 42);`save_manager.gd` 首次冒险位注释随 T2 第一口已换代。
- 件核:全仓 `first_script`/`template_pick`/`active_template` 零引用;`level.tres` 三行无 `templates` 键;`sim/level_autoplay.gd` 的 `boss_depth` 读数键由 `node_depth` 改 `depth`(该处曾是模板时代键名残留,切源后读不到值=测量面静默漂移,随 S7 一并清)。
## 二·十 T3 断言面换代(S1–S8 全数落位)
| 清单项 | 宿主与落位 | 换代后断言面 | 变异拦截面 |
|---|---|---|---|
| S1 | `tests/integration/node_map_templates_test.gd` 整宿主重写 | ①-⑥ 模板段退役;⑦ 收束置位三条保留(措辞换「首局恒走固定种子 42」);宿主现名不变(manifest 零新增登记,改名归反哺点⑧) | M5/M7 |
| S2 | `_level_active_nodes` 三副本(`level_shop_economy`/`adventure_feats`/`round_flow_skill_pool`) | 一律改经 `NodeMapGenerator.generate(db.level_gen_params_row(L), 42)` 取图;消费点深度键 `node_depth`→`depth`;两宿主内零调用方的死件 `_boss_depth` 随删 | — |
| S3 | `level_shop_economy` 商店段 | 三条性质断言(终点前驱恰一店/商店总数=终点数/全路径恰穿一店)× L1–L3 参数档 × 种子 42+42–61 扫描;硬编码 8/9/穿节点 8/L1 行集退役;行进面「当前节点型别=shop 且出边恰一条指终点」 | M2/M3 |
| S4 | `level_shop_economy` 形状段 | 节点数/五型计数/岔口数/终点数改生成图读数性质(含「L1 终点恰一、L2/L3 含岔口」V4 投影),非空前置在位 | — |
| S5 | `level_shop_economy`〔v11〕+`adventure_feats`〔fv24〕 | 敌侧=解析落带 ≥ 请求深度(禁顶 clamp)、板侧=精确命中、多终点 Boss 带键两两互异;`adventure_feats` 原「行集内每节点在 board_gen+enemy 有精确行集」改走 `resolve_enemy_rowset`/`resolve_board_gen` 真实消费链+扫描非空前置 | 〔v11〕两条已按批内变异验证见红(前节记录) |
| S6 | `node_map_templates` 新确定性套 | 同档同种子两次产图逐位同图/换种子即变图/节点携唯一句柄+depth/起关生效图=生成器直取(单一图源)/起关产图零计数器消费/入口候选数=参数档 `entry_count`+第二入口句柄显式进入/种子 42 两开局同图/断点存→恢复→再产图同图/缺代差键旧断点拒绝/表无 `templates` 键 | M1/M5/M6/M7 |
| S7 | `sim/level_autoplay.gd`、`sim/adventure_monte_carlo.gd`、`probe/shot_probe.gd`、`probe/ui_click_probe.gd` | `template_pick` 尾参退役;MC `level_templates`→`level_maps`(值 `关卡#主种子`);route 轴沿句柄升/降序;探针「L2 商店为 Boss 前必经位」假设改性质措辞;`probe/board_shot_probe`、`probe/type_glow_shot_probe` 起关尾参残留清理 | — |
| S8 | `breakpoint_resume`(新增 P7 六断言)、`pool_case_d`、`feat_vouchers`、`cross_system_flow:79`、`meta_progression_forge:316/:323`、`curio_refresh_paid`、`save_manager_domain` | `first_script` 键清退;断点夹具 `template_pick`→`graph_gen_v2`;meta 参数面 extra 键样换 `treasure_unlocked`(「入口特有键随 extra 原样并入」判据不动);P7 钉「快照无已抽模板键+代差标记在档+停点句柄与已到序往返+续玩重生成同图+旧断点拒绝+同种子重开局同图」 | M6 |
补充两条断言(V2/V6 拦截面补位,提交 `38492116`):原「入口停点候选 ≥1」不足以拦「候选写死单入口」,改判「=参数档 `entry_count`」并加点第二入口;`adventure_feats` 新增 `_drive_to_pref` 真实选路驱动,据此落「进战载荷两样=关卡序号+节点深度,且命中节点句柄≠深度」〔v6〕与奖励支路经停三选一在途两条。
宿主读数:`node_map_templates` 21 checks、`adventure_feats` 138、`breakpoint_resume` 全绿、`pool_case_d`/`feat_vouchers`/`cross_system_flow`/`curio_refresh_paid` 21/`save_manager_domain` 101/`meta_progression_forge` 133/`round_flow_skill_pool` 127/`table_structure_guard` 67/`level_map_type_vis` 26/`level_map_info_fog` 19 全绿;`level_shop_economy` 见下节。
## 二·十一 T3 收口:`level_shop_economy` 宿主换代(147→176 checks)
换代后该宿主的图源单点 = `_generated_graph(level_index, seed)`(`db.level_gen_params_row(L)` × 种子),`_level_active_nodes` 走该单点取种子 42 的现行图;段内新增一批图读数辅助(`_entry_ids`/`_terminal_ids`/`_fork_ids`/`_type_tally`/`_path_shop_count`/`_all_entry_terminal_paths`/`_path_in_graph`/`_coverage_scan`/`_enemy_band_covers`/`_board_row_exact`),行进面与枚举面共用同一判据口径。
- S4 形状段:`L2 节点数 = 10`/`战斗节点数 = 5`/`普通战斗 6+Boss 恒一`/`恢复 1+奖励 1+商店 1`/`真实岔路 = 0`/`L1 行集零改动` 六类写死读数退役,改为「五型计数合计 = 节点数」「战斗节点数 ≥ 参数档 `battle_floor`」「Boss 节点数 = 参数档 `exit_count`」「岔口(出度 ≥2)≥1」「L1 终点恰一」「终点深度 = 参数档 `layers`」,每条都带扫描面非空前置(`L%d 现行起关图取数非空`)。
- S3 商店段:三条性质断言 × 三关参数档 × 种子 42+42–61 全扫描(违例计数落进断言消息,图数与路径数在案:60 图 / 1413 条入口→终点路径),另保留行进面两条(到店当前节点型别=shop 且出边恰一条指终点;min/max 两轴路径逐跳为图出边、末节点为 Boss、穿店恰一)。
- S5 覆盖段:`跨表行完整(7 节点)` 改 `_coverage_scan` 逐关读数——敌侧「落带 ≥ 请求深度」、板侧「精确命中且 `node_depth` 等值」,并逐关登记颗数非空;终点 Boss 行集断言按图终点深度解析(`L2 全部终点深度 … 的 Boss 行集`)。
- 收口一件:换代过程中宿主内一度写过 `MUTATION-A/B/C/D` 内联自改生成图的脚手架与两条配套 MUT 断言(把变异开关埋进测试面=测试自己造数据,属反模式),已由 `d48bf10f` 整体删除,V5 证据改由生产码注入取证(见下表 M2/M3)。
## 二·十二 变异验证记录表(卡② 补挂七条;T1 四条与〔v11〕两条见 §二·五/§一)
跑批脚本 `game/tests/.gates/mutate_iter35_card2.py`(注入→最窄宿主→还原→逐条自检,跑后 `git status` 核产品码四件零改动;脚本本身属临时件,收口前删除)。红行取被测宿主自身的 FAIL 文本,不取包装层退出码。
| # | 注入点 | 变异内容 | 最窄宿主 | 结果与红行 |
|---|---|---|---|---|
| M1 | `level_runner.gd` `_candidates = entries`(两处入口停点候选,改首条) | 多入口候选写死单入口 | `node_map_templates_test` | 红(命中):`入口停点候选数=参数档入口个数(L3 档 2——多入口首跳即选路,禁写死单入口)` |
| M2 | `node_map_generator.gd` 产图返回前把 shop 型别改 rest | 终点前驱改非店 | `level_shop_economy_test` | 红(命中):性质①「每终点直接前驱恰一家店」违例 |
| M3 | 同上,把首个 battle 型别改 shop | 某路径加第二家店 | `level_shop_economy_test` | 红:性质②「每图商店节点数=终点数」违例 60/60 图;性质③「每条入口→终点路径恰穿一家商店」违例 738/1413 条;行进面 `L2 min/max 路径穿商店恰 1 家` 同批转红 |
| M4 | `level_runner.gd` enc `"node_depth": int(node.get("depth", 0))` → 取 `id` | enc 定位信息取句柄 | `adventure_feats_test` | 红(命中):`进战载荷两样=关卡序号+节点深度(实测 depth=… 句柄=…)〔v6〕` |
| M5 | `node_map_generator.gd` `pure_stream(seed_val, SCOPE_STRUCTURE)` → `open_stream("node_map")` | 产图改依赖统一流计数器号位 | `node_map_templates_test` | 红(命中):`同参数档同种子两次产图逐位同图(D2 执行边界)` |
| M6 | `adventure_runner.gd` `if int(bp.get("graph_gen_v2", 0)) != 1:` → `if false:` | 旧断点缺代差标记键却放行回放 | `breakpoint_resume_test` | 红(命中,复跑取证到断言名):`P7 缺生成图代差标记键的旧断点显式拒绝(禁按新句柄空间静默回放)`(1/56 项失败) |
| M7 | `level.tres` 首行偷留 `"templates": [{"nodes": []}]` | 模板数据未清尽 | `node_map_templates_test` | 红(命中):`level 表三行均无 templates 键(模板数据已清出)` |
卡片 §8 变异清单九条的落位:V1 两条(T1 已录)、V11 两条(覆盖批已录)、V2/V5×2/V6/V7/V8/V9 共六条(本表 M1–M7,V5 拆两条)。
## 二·十三 实际对照表(卡片 §8.2 八行的落地坐标;审计第 1 件按此逐行核)
| 需求点 | 测试落点(文件:行/尾缀) | 真实入口 | 撤销或变异证明 |
|---|---|---|---|
| 加载校验四检+良构 | `game/tests/unit/core/level_table_validate_test.gd`(17 条,〔v1〕)+起关拒绝段 `game/core/level_runner.gd:308-312` | `LevelRunner.start_level_external`(违规图返回 false) | T1 四条注入见红(§二·五):终点恒 Boss 判据注释、无环判据短路等 |
| 行进语义(多入口/大岔口/多 Boss/单链) | `node_map_templates_test.gd:60-66`〔v2〕;`level_shop_economy_test.gd:1157-1216`(V3 段:多终点图、两路各收本路 Boss、区域隔离、收束恰一次);`level_shop_economy_test.gd:339`〔v4〕(L1 终点恰一)+`:632`(L3 入口数=`entry_count`、终点数=`exit_count`) | `LevelRunner.start_level_external`/`start_level`+`pick_next_node`/`sim/level_autoplay.run_level`(route=min/max 两轴全程驱动) | M1(候选写死单入口)→〔v2〕红 |
| 商店编排三条性质 | `level_shop_economy_test.gd:1129-1133`〔v5〕(扫描面非空+性质①②③,60 图/1413 路径读数)+`:1000-1010` 行进面 | 生成图逐节点解析+`runner` 行进到店 | M2(终点前驱非店)→性质①红;M3(加第二家店)→性质②③红 |
| 生成图覆盖+多终点 Boss 带互异 | `level_shop_economy_test.gd:259-306`〔v11〕+`adventure_feats_test.gd:111-131`〔fv24〕 | `ConfigDB.resolve_enemy_rowset`/`resolve_board_gen` 真实消费链 | 覆盖批两条注入已录(Boss 带并单带、删顶带);〔fv24〕判据与〔v11〕同源单点 |
| 定位信息两样(关卡序号+节点深度) | `adventure_feats_test.gd:159-166`〔v6〕(读 `BattleOrchestrator.encounter`) | 真实进战入口 `_drive_to_pref`→`pick_next_node`→`begin_battle` | M4(enc `node_depth` 取句柄)→〔v6〕红 |
| 确定性承载+旧断点代差 | `node_map_templates_test.gd:44-95`〔v7〕〔v8〕;`breakpoint_resume_test.gd:157-183`〔v7〕〔v8〕〔v9〕 | `NodeMapGenerator.generate`/`AdventureRunner.start_adventure`/`resume_adventure`(真实快照写手 `SaveManager`) | M5(产图改计数器流)→〔v7〕红;M6(缺代差键放行)→〔v8〕红 |
| 15 张模板清理 | `node_map_templates_test.gd:91-96`〔v9〕+件核 grep(全仓零 `templates`/`first_script`/`template_pick`/`active_template`) | `ConfigDB.level_row` 表读面 | M7(表内偷留 `templates` 键)→〔v9〕红 |
| 反哺点清单(非行为改动) | `reports/iter35-卡②-反哺点-2026-10-24.md` 十条落点 | T4 产出物件核 | 缺任一落点=V10 件核红(本文件 §三·一 目检两条同批登记) |
宿主读数(终版):`level_shop_economy_test` 181 条、`node_map_templates_test` 21 条、`adventure_feats_test` 138 条、`breakpoint_resume_test` 56 条、`level_table_validate_test` 17 条。
## 三·一 实机目检总清单(真人判断项,登记即完成义务,不作为合回前置)
| # | 观测项 | 真实入口 | 期望看到什么 | 本批机检已覆盖的部分 |
|---|---|---|---|---|
| 目检① | 三关选路观感不回归:多入口首跳、大岔口取舍、多终点走向可见 | 主菜单开局 → 关卡地图(`res://probe/ui_click_probe.tscn` 亦可走同路径) | 开局即出现两个可选入口(L2/L3);岔口处候选互异且分属不同支路;走 A 支只遇 A 支终点 Boss | 候选数=参数档 `entry_count`、第二入口句柄可进入、终点数=`exit_count`、岔口 ≥1、每终点前恰一店(`node_map_templates`/`level_shop_economy` 扫描面) |
| 目检② | 首局教学图体验(种子 42 固定图) | 新档开局(`is_first_adventure_done==false` → 恒种子 42) | 同一张图、节奏可教学:入口战→岔口→商店→Boss 的可读顺序,含至少一个奖励位与一个恢复位 | 种子 42 两开局逐位同图、开局图=参数档直取、三关图各含奖励/恢复节点、恢复公式两分支读数 |
登记口径:以上两项由用户自行安排试玩;本批不以任何目检为停工或合回理由(硬性红线「真人检测只登记不阻塞」)。
## 三·二 其余遗留读数义务
- 覆盖数据为 provisional 插值,未跑 MC/对拍——数值面既动,卡② 收口前须请用户裁定是否发起 11 回放确定性对拍与 `balance_verifier` 重跑(本批目前只跑到「覆盖断言绿」,未测难度观感)。
- 待办清单 06 条目「覆盖批未立卡」缺口段现况已过期(覆盖数据已随本批落地),状态回写归文档批。
@@ -1,117 +0,0 @@
# 迭代 35 卡② 独立验收审计(节点图消费侧换代批)
- 审计日期:2026-10-24(执行跨至 2026-10-25 完成)
- 审计对象:分支 `iter35b` 尖 `0c5cd428`,改动范围 `git diff master...HEAD`(merge-base `bb63c93c`,31 文件级)
- 审计身份:未参与实现的独立会话子代理(迭代 loop 内启动,依 test-conventions §9.7 授权跑测)
- 合同:`reports/需求卡片-节点图消费侧换代批-2026-10-21.md` v1.1;被审产出物=实现报告/代拍板单/反哺点清单三份
## 总结论:**通过**
逐条独立复核(不采信实现方「已全绿」)后,V1–V11、S1–S8、件核四项、批性质禁令、变异伴生九条拦截面全部成立;实现报告 §二·十三 实际对照表的每条测试落点均真实存在、真实入口非绕过改动点的下层直调;三条撤销证明(M1/M4/M6)由本审计亲手注入复现出红并还原自证 git status 干净。三处「必看」的旧断言改写均为等价或更强、且已在卡片 §8.2/§一随动表/代拍板单申报,无未申报削弱。**建议合回**。
残留项均为已在报告内申报的过程件与文档措辞张力(反哺点⑦/⑨),属文档批处理面,不构成实现批的验收缺漏。次要行号漂移(±1–5 行)不影响判据可定位性(以 尾缀 grep 为权威落点)。
## 一、环境与跑测方法
- 基线复核:本审计自跑 `PYTHONIOENCODING=utf-8 Godot_v4.7.2 --headless --path . --script res://tests/run_all.gd`,结果 `all green (60 suites)`;对 `FAIL|红色|断言失败` 的 7 处命中逐条判读,全为良性(通过态测试函数名含 "failure_restores"、故意的 corrupt-JSON 解析报错、"[PASS] …R3 fail-fast" 行),**零真实 FAIL**。
- 关键宿主自证读数:`level_table_validate_test` 17、`node_map_templates_test` 21、`adventure_feats_test` 138、`level_shop_economy_test` 181、`breakpoint_resume_test` PASS —— 与实现报告 §二·十三「终版读数」逐一对齐。
- 撤销证明:在指定文件注入变异→跑最窄宿主取宿主自身 FAIL 行→写回原文→`git status`/`git diff HEAD` 自证字节级还原(三次注入后树均干净)。
- 静态核:diff 路径、件核四项、旧断言删除—替换、非空前置、代拍板超清单五件,逐项 grep + 打开文件确认。
- 依赖说明:探针/冒烟包装闸(run_all_gates.sh 的 probe/smoke/balance 段)未由本审计重跑,依 `game/tests/.gates/receipt.json`(记录 commit=`0c5cd428`、域=code、全绿、11 回放确定性对拍 NEED-APPROVAL 经用户裁定零跑)作背景;代码域测试面已由 run_all.gd 独立复现。**MC/11 回放确定性对拍的零跑是红线内正确处置**(卡② 本体零玩法数值;覆盖批数值随卡② 同批、档位须用户发起),非本审计可越权补跑,亦不阻断代码侧验收结论。
## 二、逐需求点审计表(V1–V11)
| # | 审计项 | 判据出处(卡片) | 实际跑了什么/打开确认了什么 | 结果 |
|---|---|---|---|---|
| V1 | 加载校验四检+良构+起关拒绝 | §4 契约1;§8 V1;§8.2 行1 | 打开 `level_table.gd:50 validate_graph`=①入口终点≥1 ②全员可达双向BFS ③终点恒Boss/Boss无出边 ④出边目标depth严格>源;良构=句柄唯一·出边全命中·type五枚举·battle/boss带depth。`level_runner.gd:308` 起关调 `LevelTable.validate_graph` 违规 return false(真实入口 `start_level`/`start_level_external`)。跑 `level_table_validate_test`〔v1〕17 条全绿(正例三形/负例八类/范围反证三/②④互斥实证)。旧六判据文本全仓 grep 零残留(`编号最大`/`纯战斗`/`出度上限` 作判据 0 命中);`validate()` 已缩为行级,`level_shop_economy:427` 保留「行级校验零错误(图合法性移交 validate_graph)」 | 通过 |
| V2 | 多入口首跳(候选=全部入口) | §4 契约5;§8 V2 | 〔v2〕`node_map_templates:64` 「入口停点候选数=参数档入口个数(L3 档 2)」经 `start_level_external(...,defer_entry=true)`→`level_runner:214 _candidates=entries` 执行;第二入口 `:68` 走 `pick_next_node`。**亲手注入 M1**(两处 `_candidates=entries`→`[entries[0]]`)→该断言变红,还原绿 | 通过 |
| V3 | 大岔口分区域兑付+多Boss收束恰一次 | §4 契约5;§8 V3 | 打开 `level_shop_economy:1156 _smoke_multi_terminal_settlement`:真实入口 `sim/level_autoplay.run_level(min/max 两轴)`+`runner.start_level(2,42)`+`pick_next_node`;断言 L2≥2终点Boss、两路各收本路终点Boss互异、区域隔离(A路未到B终点)、`level_finished` count==1 且 result=victory 且 node_id∈Boss集。基线该宿主 181 全绿 | 通过 |
| V4 | 单链退化合法+三关含岔口+L1终点恰一 | §1完成定义;§8 V4 | 〔v4〕`level_shop:340`「L1 终点恰一个(大岔口自L2起)」`_terminal_ids==1 and boss==1`;`:633` L3 入口数=entry_count·终点数=exit_count≥2;含岔口 `:341/442`(出度≥2节点≥1);单链合法由 V1 `level_table_validate:56` 夹具承载。`adventure_feats:165`〔v4〕三关各含≥1奖励节点 | 通过 |
| V5 | 商店编排三性质 | §4 契约4;§8 V5 | 〔v5〕`level_shop:1129/1130/1131` 三性质(终点前驱恰一店/店数=终点数/全路径恰穿一店)×L1–L3×种子42–61 扫描;非空前置 `:1128 graph_total==3×range & term>=3 & path>=3`,逐图空即 `:1101 false`。DFS `_all_entry_terminal_paths:186` 走句柄序。加载校验内无商店位(`level_table_validate:97` 反证)。M2/M3 记录判据名=性质①/②③,与卡片「终点前驱非店」「路径加第二店」对应(底层断言已开文件确认为真判据) | 通过 |
| V6 | 定位信息两样(关卡序号+节点深度,弃编号寻址) | §4 契约2;§8 V6 | `level_runner:500` enc `"node_depth": int(node.get("depth",0))`=depth值非句柄、键名保留;`_node_id:333` 返回 `id` 句柄(双编号空间退役)。〔v6〕`adventure_feats:188` 走真实 `_drive_to_pref→pick_next_node→begin_battle→current_battle().encounter`,判据含 `enc.node_depth==node.depth` **且 `node.id != node.depth`**(防句柄冒充)。**亲手注入 M4**(enc 取 `id`)→该断言红(实测 depth=6 句柄=6),还原绿 | 通过 |
| V7 | 确定性承载(纯函数复现) | §4 契约3;§8 V7 | 〔v7〕`node_map_templates:43` 同档同种子两次 generate 逐位同图/`:45` 换种子即变/`:53` 起关生效图=生成器直取(单一图源)/`:80` 种子42两开局同图;`breakpoint:174/181` 续玩重生成同图+同种子重开局同图。M5 记录判据名「同参数档同种子两次产图逐位同图」对应卡片「生成器注计数器依赖」;底层 `pure_stream→open_stream` 注入确会破坏该断言(判据对象正确) | 通过 |
| V8 | 模板0语义废除+旧断点代差拒绝 | §4 契约3;§8 V8 | `adventure_runner:146` `if int(bp.get("graph_gen_v2",0))!=1: return false`;快照 `:1014 graph_gen_v2:1`。〔v8〕`node_map:88` 续玩受理(标记在档)+`:94` 缺标记键旧断点 `==false`;`breakpoint:161/171/179` P7 标记键+句柄往返+旧断点拒绝。`is_first_adventure_done` 两态(种子42/随机)由 `node_map:106-112` 收束置位承载。**亲手注入 M6**(`if false:`)→`breakpoint:179`〔v8〕「缺生成图代差标记键的旧断点显式拒绝」红,还原绿 | 通过 |
| V9 | 15 张模板清理 | §4 契约6;§8 V9;完成定义6 | 〔v9〕`node_map:101` 三行 level_row 均无 `templates` 键+`breakpoint:159` `not has("template_pick")`。件核四项见第四节。`_resolve_template_row`/`active_template_*` 代码零引用。`level.tres` 仅剩 3 行 `level_index/display_name/rest_heal_pct`。M7 记录判据名「level 表三行均无 templates 键」对应卡片「level.tres 偷留 templates 键」 | 通过 |
| V10 | 反哺点清单六条各有落点 | §6;§8 V10(非行为改动) | 打开 `reports/iter35-卡②-反哺点-2026-10-24.md`:卡片预列①-⑥逐条有文件+节位+改成什么+依据;另实现批新发现⑦-⑩四条一并呈报。V10 义务满足 | 通过 |
| V11 | 生成图覆盖+多终点Boss带互异(承跨表校验④语义) | §0硬交付;§4契约8;§8 V11 | 〔v11〕`level_shop:302-305` 敌侧落带≥请求深度(`_enemy_band_covers:223` 经 `resolve_enemy_rowset` 真实链,禁顶clamp)/板侧精确命中(`node_depth==D`)/多终点带键两两互异;非空前置 `:268/275/302`。〔fv24〕`adventure_feats:130` 同源消费链+`cov_scan>0`。§一 覆盖批两条注入记录(Boss带并单带→互异红;删顶带→落带红)判据名对应卡片伴生条。**跨表校验④整段已从 `config_db_cross_validator.gd` 删除**(`node_lists`/`level_node_dangling`/带clamp/带互异静态代码零残留),两拦截语义由〔v11〕升级到真实生成图,与 §8.2 预声明④一致 | 通过 |
## 三、S1–S8 断言随动核
| # | 核到之处 | 结果 |
|---|---|---|
| S1 | `node_map_templates_test` 整宿主重写,全文件无「模板 0/回滚档/池=5/node_map抽签」文本(grep 0);⑦收束置位改写为「首局恒走固定种子42」 | 通过 |
| S2 | `_level_active_nodes` 三副本(`level_shop:48`/`adventure_feats:895`/`round_flow:343`)均改 `NodeMapGenerator.generate(level_gen_params_row(L),42)`;死件 `_boss_depth` 全仓 .gd 零引用(仅 `验证集清单.md` 快照残留,见第五节) | 通过 |
| S3 | 商店三性质+行进面(到店节点型别=shop且出边恰指终点)换代完成,硬编码 8/9/穿节点8/L1行集退役 | 通过 |
| S4 | 形状写死断言(节点数=10/普通战斗6+Boss恒一/恢复1+奖励1+商店1)改为生成图读数性质(五型合计=节点数/≥battle_floor/Boss数=exit_count/岔口≥1/终点depth=layers),每条带非空前置 `L%d 现行起关图取数非空` | 通过 |
| S5 | 覆盖判据换真实消费链+落带非顶clamp+带互异(见 V11) | 通过 |
| S6 | 确定性四断言(同图/换种子变图/句柄+depth/单一图源/种子42两开局/断点重生成同图/缺templates)落 `node_map_templates` 同宿主,manifest 零新增 | 通过 |
| S7 | `level_autoplay:141/200-202` `level_maps`(值 `关卡#主种子`)替代 `level_templates`;MC 出数面 `adventure_monte_carlo:139` 随动;sim 内 `template_pick` 零残留;route 轴沿句柄升降序 | 通过 |
| S8 | `breakpoint_resume` P7 六条;`pool_case_d`/`feat_vouchers`/`cross_system_flow` first_script 键清退(.gd 零引用);`meta_progression_forge:323` extra 键样例换 `treasure_unlocked`,「入口特有键随 extra 原样并入」判据结构保持(仍验 wide_scout_band+shop_mode==pool) | 通过 |
## 四、件核四项(命令与命中数)
| 项 | 命令 | 命中 | 判读 |
|---|---|---|---|
| 全仓零 `first_script` | `grep -rn first_script game --include=*.gd` | **.gd 0** | 代码面零引用(通过)。`.md` 仅 `game/tests/验证集清单.md` 快照 8 处(不在本 diff、不进任何闸、已申报反哺点⑦待用户重生成/注记)——属过程文档快照,非代码死引用,见第五节例外说明 |
| 全仓零 `template_pick` | `grep -rn template_pick game --include=*.gd` | **.gd 1** | 唯一命中 `breakpoint_resume_test:159 not bp_j.has("template_pick")`=**反向断言**(断言退役键缺席),属例外。其余仅 `验证集清单.md` 快照 3 处 |
| 全仓零 `active_template` | `grep -rn active_template game --include=*.gd` | **.gd 0** | 代码面零引用(通过);快照 2 处同上 |
| `level.tres` 无 `templates` 键 | `grep -n templates game/data/tables/level.tres` | **0 数据键** | 仅 1 处表尾去向注释(第16行「旧15张模板池…清出」),三行均为行级字段无 templates/nodes(V9 达成) |
## 五、测试削弱核查(三处必看 + 全量删除扫描)
对 `git diff master...HEAD` 的**全部删除断言行**(约 60 条 Kit.check)逐条溯源其替换体,未发现「删断言/放宽阈值/缩扫描面/换下层直调/精确改恒真/空扫描判绿」的未申报削弱。三处重点:
1. **奖励三选一断言替代**(`adventure_feats`):旧「L1 链必经≥1 次」→新「图侧每关≥1奖励节点〔v4〕 + `_drive_to_pref("reward")` 真实岔口点选→`node_curio_candidates`+`present_node_curio`呈停+`apply_node_curio`受理」,另有 `:197` 兑付回执==经停逐笔。判据语义从「形状必经」变「接线可用+图上存在」,**已在代拍板①申报**(实测确定性评分 12 次全程恒不进奖励支路,含岔口设计下奖励位可选为既定),替代体仍走真实入口证机制可兑付,未放宽为恒真。判:申报过的合法替代,不红。
2. **`shop_seq.size()` 2→3**(`adventure_feats:325`):随契约4「每关路径恰穿一店⇒三关=3」的必然投影,**代拍板③申报**,与 V5 三性质扫描互为校验(不一致则二者之一必红),非任意放宽。判:不红。
3. **三处 `_level_active_nodes` 换代**:templates 键清出后旧实现落 `row.get("nodes",[])` 返空数组会致覆盖/Boss深度/逐节点扫描断言集体空转绿——本批三副本均改生成图取数,且所有消费断言带非空前置(`cov_scan>0`/`scanned>0`/`graph_total==3×range`/逐图空→显式 `false`)。**代拍板②申报为缺陷清偿**(当场重新暴露一次 `boss_depth` 读 -1 真红并清偿)。判:有效强化,不红。
**其余删除断言**全部落入卡片 §8.2「旧断言预声明」四类(S1–S8随动/V5商店换代/V8收束置位改写/④静态检查退役由S5承接),替换体经开文件确认为等价或更强(模板形状写死→生成图性质扫描、静态代理→真实消费链落带)。
## 六、变异伴生九条拦截面判定(§8.2)
| 卡片条 | 记录/复现 | 判据名是否对应 | 结果 |
|---|---|---|---|
| V1 终点恒Boss判据注释 | §二·五 记录 `终点非 Boss 负例〔v1〕` 红 | 对应(负例夹具命中「终点 1 非 Boss」) | 判定成立 |
| V1 无环判据短路 | §二·五 记录 回边/环两负例红 | 对应(「违反前进方向」) | 判定成立 |
| V11 Boss带并单带 | §一 记录 带互异红 | 对应〔v11〕两两互异 | 判定成立 |
| V11 删顶带 | §一 记录 落带≥深度红 | 对应〔v11〕band_of非-1 | 判定成立 |
| V2 候选写死单入口 | **本审计亲手注入 M1** | 红行原文见第七节 | **已复现** |
| V5 终点前驱非店 | §二·十二 M2 | 对应性质①(已确认 pred 型别判定为真判据) | 判定成立 |
| V5 路径加第二店 | §二·十二 M3 | 对应性质②③(已确认 shop 计数判定为真判据) | 判定成立 |
| V6 enc取句柄 | **本审计亲手注入 M4** | 红行原文见第七节 | **已复现** |
| V7 生成器注计数器依赖 | §二·十二 M5 | 对应〔v7〕同种子逐位同图 | 判定成立 |
| V8 旧断点放行回放 | **本审计亲手注入 M6** | 红行原文见第七节 | **已复现** |
| V9 表留 templates 键 | §二·十二 M7 | 对应〔v9〕三行无 templates(已确认 iter has("templates")) | 判定成立 |
结论:九条中三条由本审计独立注入复现出红,其余六条的实现方记录判据名与卡片要求逐条对应、且底层断言开文件确认为真实判据(非恒真/非空扫描),无「记录名与卡片错配」情形。
## 七、撤销证明复现记录(本审计亲手注入,附红行原文)
- **M1(V2)**:`level_runner.gd` 两处 `_candidates = entries` → `[entries[0]]`(`:214` defer入口 / `:243` 断点入口停点)。跑 `node_map_templates_test`。红行:
`ERROR: [FAIL] 入口停点候选数=参数档入口个数(L3 档 2——多入口首跳即选路,禁写死单入口)〔v2〕`
还原后 `git status` 干净。
- **M4(V6)**:`level_runner.gd:500` enc `"node_depth": int(node.get("depth",0))` → `int(node.get("id",0))`。跑 `adventure_feats_test`。红行:
`ERROR: [FAIL] 进战载荷两样=关卡序号+节点深度(实测 depth=6 句柄=6)〔v6〕`
还原后干净。
- **M6(V8)**:`adventure_runner.gd:146` `if int(bp.get("graph_gen_v2",0))!=1:` → `if false:`。跑 `breakpoint_resume_test`。红行:
`[breakpoint_resume_test] FAIL — P7 缺生成图代差标记键的旧断点显式拒绝(禁按新句柄空间静默回放)〔v8〕`
还原后干净。
三条注入均:注入前确认 `git status` 干净;取被测宿主自身 FAIL 行(非包装层退出码);写回原文后 `git diff HEAD` 为空、`git status` 干净。
## 八、代拍板超清单五件(白名单外)的独立判断
1. 奖励断言替代 → 见第五节①,申报充分、替代体仍证接线,通过。
2. `_level_active_nodes` 三处空转缺陷清偿 → 三副本确认换代、非空前置齐备,清偿真实(当场重暴露 boss_depth=-1 红),通过。
3. 商店到达余额 2→3 → 契约4 必然投影、与 V5 互校,通过。
4. `_boss_depth` 死件随删(两宿主零调用方)→ 全仓 .gd 零引用确认,涉删纯死代码不触断言,通过。
5. 两呈现宿主(`level_map_type_vis`/`level_map_info_fog`)夹具拓扑重建、自述「断言条数与阈值零改动」→ **本审计独立计数核**:19→19、26→26 无缩减;可见集阈值判据仍在(层距 N 可见/N+1·N+2 不可见、候选豁免、Boss 豁免不扩散、句柄32层6入雾),负向回边判据移交 `level_table_validate`〔v1〕,自述属实,通过。
## 九、批性质与残留申报项
- **批性质禁令**:`git diff master...HEAD --name-only` 仅 31 个 `game/` 文件 + 3 份 `reports/` 产出物;grep `design/|AGENTS.md|roadmap.md|待办清单|体验验证清单` = **零命中**。实现批未写 design/ 与根流程清单,合规。
- **申报的非阻塞残留**(属文档批/用户裁决面,不红):
- 反哺点⑦:`game/tests/验证集清单.md` 为批 B 断言文本快照索引,本批未重生成,仍含退役措辞与旧行号,不进任何闸;已诚实列清单待用户裁决重生成或注记。件核四项中的 `.md` 快照命中即源于此,代码面干净,不构成契约6「死代码死断言」违令。
- 反哺点⑨:`level.tres:16` 表尾去向注记含「随迭代 35 卡② 清出」的迭代叙事,与 doc-conventions §5「禁写变更叙事」有张力;但卡片 T3 明令表尾写「15 张模板去向」注记,属卡片授权范围,已申报待裁。
- 实机目检两条(三关选路观感、首局种子42教学图)已登记于实现报告 §三·一,依「真人检测只登记不阻塞」红线,不作合回前置。
- **次要观察**:报告 §二·十三 若干行号与实际有 ±1–5 行漂移(如 v9 标 :91-96 实为 :101、v4 标 :339 实为 :340),但每条 尾缀 均可 grep 定位、断言真实存在,不影响验收。
@@ -1,278 +0,0 @@
# 需求卡片:节点图消费侧换代批(模板池消费 → 生成图消费)· 关卡节点图重构卡②
- 版本:**v1.1**(2026-10-24 修订重锚——断言宿主随 game/smoke/ 退役〔16c6f136〕迁批 B 16 宿主、跨表校验④删除范围重划(迭代 34 检查语义承接进 S5)、run_all manifest 登记步补齐、§3 行号重锚;v1.0 2026-10-21 成文,自审五查+grilling 复核结论见文末)
- 来源:[待办清单](../待办清单.md)「关卡节点图重构——可选节点太少」(2026-10-13 登记,来源=playnote,设计面=文档轨,状态=文档设计已闭合)(唯一事实源:[关卡节点地图](../design/gdd/systems/冒险循环/关卡节点地图.md) v2.1+[关卡节点图生成](../design/gdd/systems/冒险循环/关卡节点图生成.md) v1.1+[冒险结构](../design/gdd/systems/冒险循环/冒险结构.md) 关卡行集与结构冻结行,2026-10-21 双定稿闭合凭据)
- 归属:关卡节点地图消费侧(加载校验/行进语义/商店编排冒烟/定位信息/确定性承载/旧模板清理);关卡节点图重构批卡②(卡①生成器/卡③敌人表深度带〔已落地·迭代 34〕/卡④迷雾可见性〔已落地·迭代 34〕同批)
- 排期:未编入(2026-10-18 用户令:需求卡片不预占迭代号,批次归属按工作量另裁)
- 开工门:U0(用户 `/iter` 发令)+ grilling 复核门过(零待裁点,见 §11)
## 0. 前置依赖与并行性
- **设计闭合(第〇步)**:06 条目「关卡节点图重构——可选节点太少」状态=文档设计已闭合,凭据=关卡节点图生成.md v1.1+关卡节点地图.md v2.1(各带路径+版本号)→ 放行写卡。
- **硬依赖卡①(生成器)**:运行时图来源换成生成器产图(§7 取用块),卡①接口定稿+实现落地后本卡才可合入运行时切源;T0 与卡①接口对齐(签名/图数据形状/参数档 schema/复现语义四件)。
- **硬交付序列(跨卡数据覆盖)**:敌人深度带数据对生成图深度域的覆盖(每 (关卡序号, row_kind) 顶带键 ≥ 该关生成图最大节点深度;且多终点 Boss 各终点深度的解析带键可互异——卡③ 契约 5「同关多 Boss 行集带键互异」的图侧投影)须先落或与本卡同批落——归口=卡③ §5 已登记的「生成图深度扩面覆盖问题(卡①/后续表批)」,**尚未立卡(2026-10-24 实况登记,见待办清单 06 条目缺口)**。数据实况(迭代 34 落地后实查):敌侧战斗带顶 L1=3/L2=L3=7(L1 深度 4-5、L2 深度 8、L3 深度 8/10-12 越顶)、Boss 各关单带 4/9/9(L1 终点深度 6 越顶、L2 双终点深 8/9 共带、L3 终点深至 13 越顶);板侧 board_gen `node_depth` 精确行同域缺口——切源即 `EnemyTable.band_of`(`enemy_table.gd:157`)越顶返 -1 加载致命。未覆盖时覆盖断言(§8.1 S5)红、遭遇解析顶 clamp 消解,本卡不得单独合入(依据:冒险结构.md:293 覆盖义务+卡③契约 7 顶 clamp 禁消解+闸全绿要求)。
- 与卡③接口零改动:定位信息契约=(关卡序号 + 节点深度) 两样(关卡节点地图.md:119;卡③ §0 同口径),本卡换传递侧值语义、不动消费侧寻址。
- 与卡④(迷雾可见性)并行无依赖;迷雾呈现面(近处见类型/远处起雾)归卡④,本卡只保证图结构只读读面在位。
## 1. 目标与完成定义
**目标**:节点图消费侧六件换代——① 加载校验换代(多入口/多终点、每路径恰从一入口到一终点、终点恒为 Boss、无环;规则语义以关卡节点图生成 v1.1 产出规格为准,校验动作在消费侧);② 行进语义换代(大岔口自 L2 起、多 Boss 兑付与关卡收束、单链退化形态仍合法但三关参数档都含岔口);③ 商店编排冒烟断言换代(每个终点前一位恰一家店、每局必经恰一家);④ 定位信息换代(关卡序号+节点深度,弃节点编号寻址语义);⑤ 确定性承载换代(固定种子+固定参数档承载首局教学图与存档复现,「模板 0=回滚档」语义废除);⑥ 旧 15 张模板 level.tres 数据清理(生成器产图经卡①接口取用)。
**相对现状,新增了什么**:
1. 图来源换代:`level.tres` 模板池(3 关 × 5 张)→ 卡①生成器按(参数档,种子)产图;加载校验的对象从静态模板变为运行时生成图;
2. 校验语义换代:唯一入口/唯一 Boss/编号最大/出度 ≤2/层宽 ≤5/单链前三纯战斗六项退役,换为多入口多终点合法+路径完整性+终点恒 Boss+无环四检;
3. 行进面:多入口首跳(入口停点候选=全部入口)、任一终点 Boss 胜利即关卡收束(多 Boss 泛化)、单链退化过校验;
4. 定位信息值语义:`node_depth` 从节点编号换为节点深度(自入口步数);图内行进/断点寻址改生成图节点句柄(`_node_id` 双编号空间退役);
5. 确定性承载:`first_script`/`template_pick`/`active_template_*`/模板 0 回滚档全退役;首局教学图=种子 42+参数档生成图;断点复现=主种子+参数档重生成同图;
6. 冒烟断言面从模板形状写死断言换为生成图性质断言(商店编排三条、含岔口、确定性三条)。
**完成定义**(全部满足才算本批完成):
1. 加载校验四检+良构基底在位:违规生成图起关致命(无软回退、无兜底图);旧六判据零残留;
2. 多入口首跳、多 Boss 兑付收束、单链退化合法三条行进语义各有验收断言绿;
3. 商店编排冒烟性质断言(终点前恰一店/商店数=终点数/全路径恰穿一店)在三关参数档×种子扫描面全绿;
4. 定位信息=(关卡序号, 节点深度):enc 键名不变、值语义换代,与卡③带寻址衔接正常;图内寻址=句柄(读面 API 签名不变);
5. 确定性承载换代落地:同 (种子, 参数档) 两次产图逐位同图;首局种子 42 教学图恒定;断点存→恢复→再产图同图;`template_pick` 断点键退役;
6. `level.tres` 三行 `templates` 键清出(15 张模板数据清空,行级字段保留);全仓零 `first_script`/`template_pick`/`active_template` 引用(件核);
7. §8 断言批全绿+变异验证记录表进实现报告;
8. 批末重闸按改动域选档全绿+改前改后读数对拍;三份 `reports/` 产出物写齐(T4)。
## 2. 设计事实源
| # | 出处 | 取用条款 |
|---|---|---|
| D1 | `design/gdd/systems/冒险循环/关卡节点地图.md` v2.1(2026-10-21,06 闭合凭据之一) | :51 结构铁律走图三句(连线只朝前进方向无环/每条路径恰从一入口出发恰到一终点/终点恒为 Boss 可多个)+「违反任何一条的行集是配置违约,加载期拦截」;:63 商店编排(每个终点前一位恰一家店、每名玩家一局必经恰一家店、**位置约束不由加载校验承载、由冒烟断言把关**);:65 节点深度=从入口沿路走过来的步数、遭遇坐标=关卡序号+节点深度、单链合法退化、三关参数档都含岔口;:71-91 行进纪律(兑付后确认、零自动推进、入口不自动进入);:119 定位信息只有两样(关卡序号 + 节点深度);:126-136 关卡收束点(先清库后宣布);:174-186 验收标准(图合法四语义/兑付移交/商店房编排/单链特例合法) |
| D2 | `design/gdd/systems/冒险循环/关卡节点图生成.md` v1.1(2026-10-21,06 闭合凭据之一——产出规格/执行边界,本卡校验规则语义来源) | :41-51 产出约束五条(道路系统=除岔口外每节点恰一条去路、岔口去路 2–3;宽度=分叉生长;层高=沿路步数;出口归属锁定;战斗节点保底)+结构铁律(无环、入口终点可多个〔个数=参数档〕、每路径恰一入口到一终点);:53-60 执行边界(不合格产出禁止进玩法、无兜底图、参数无解即致命中止、同种子+同参数档产出同一张图、随机只经 RngService 统一流);:62-72 五旋钮与三套参数档(生成器只吃参数档不认关卡号;第一关即含岔口;单链是分支密度取下限的合法退化形态、不作为三关参数档取值);:78-84 摆放约束(商店位=每个终点前一位恰一家商店);:101-115 调参表(层深 L1 ≥6 已锁、出口个数 L1 恒 1/L2/L3 1–3 已锁、商店数=出口数已锁、其余 provisional);:117-128 验收标准 |
| D3 | `design/gdd/systems/冒险循环/冒险结构.md`(状态:已定稿) | :264 关卡行集行(关卡表逐关行承载关数与图的参数档;「旧模板池随实现批清数据」——本卡即该清理义务;「确定性 = 固定种子+固定参数档(首局教学与存档复现的固定图由此承载,无兜底模板)」);:275 结构冻结(终点恒为 Boss、终点可多个各在路径最深处;收束点先清库后宣布的次序;一冒险一主种子);:293 覆盖义务(行集内每个战斗与关底节点(关,深)在敌人与棋盘生成的数值表中有行——措辞随深度带换代见 §6 反哺点②) |
闭合凭据一致性:D1/D2 与 06 条目状态内列的两份定稿逐字一致;D3 关卡行集行与结构冻结行同向,且明文把「旧模板池清理」预写为实现批义务。
## 3. 现状事实(2026-10-21 成文实查;行号与断言宿主 2026-10-24 v1.1 重锚——对齐 game/smoke/ 退役〔16c6f136,1065 条断言经批 B 迁入 16 宿主〕与迭代 34 落地后 master 现态;开工日 T0 复核行号)
| # | 事实 | 出处 |
|---|---|---|
| F1 | 图合法性校验唯一落点=`LevelTable.validate()`(表加载期、ConfigDB 收敛 fail-fast):单链校验体 `_validate_level_nodes`(Boss 计数恰一 :83-84、战斗 ≥2 :85-86、单链末 Boss :87-90、单链前三纯战斗 U2 规则 :94-98);图合法性核心 `_validate_graph`(悬空出边+前进方向「目标编号严格递增 ⇒ 无环」:126-132、**出度上限 2** :133-138、**入口唯一〔无入边恰一〕** :139-149、**Boss 唯一终点+无出边+编号最大** :150-157、双向可达〔无孤儿+全员达 Boss〕:159-182、BFS 层宽 ≤5 U2 规则 :183-201);id 解析双编号空间(图=node_depth/单链=数组下标):104-125 | `game/data/schemas/level_table.gd:21-58`/:61-99/:104-201 |
| F2 | 模板池加载路径:`level.tres` 三关各 5 张模板(15 张;L1 五张=单链排列变体、L2/L3 网状 10 节点);`LevelTable.validate` 池分支(池内全模板加载期校验);`LevelRunner._resolve_template_row`(template_pick ≥0 强制取模板/−1 经 `rng.open_stream("node_map")` 抽签;`active_template_name` 供 MC 分层出数、`active_template_index` 供断点备案);`start_level`/`start_level_external` 各带 `template_pick` 尾参;池解析在播种后(EC7) | 模板数据 `game/data/tables/level.tres:8-10`+表尾注释(t5/U2 生成史);校验分支 `level_table.gd:40-57`;解析 `game/core/level_runner.gd:300-324`(:304-305/:307/:317-318);尾参 :130/:186;播种序 :162 |
| F3 | 首局/回滚档(模板 0)读取处:`main.gd` `first_script = not save_manager.is_first_adventure_done()` 传入冒险参数面;种子三分判定(①显式合法整数②**首局固定 42**〔教学重放模板 0 即在此种子下标定〕③非首局 randi())单点=`_seed_value()`;`AdventureRunner._first_script`(true=全关零抽签取池内模板 0)→ `template_pick = 0 if _first_script else -1`;`SaveManager.is_first_adventure_done/mark_first_adventure_done`(存档布尔位,置位只在冒险收束挂点);断言段「模板 0 = 现行固定图(回滚档成员)」(池=5/强制 0 逐位相等/N=1 回滚档形态/first_script 分支/收束置位)——**宿主=批 B 裁决六整套迁集成** | `game/presentation/main.gd:594-596`/:1476-1490(_seed_value 三分判定);`game/core/adventure_runner.gd:45`/:102/:194/:850;`game/core/save_manager.gd:301-311`;`game/tests/integration/node_map_templates_test.gd:32-104`(:44 池=5/:45 模板 0 现行/:52-59 强制零抽签逐位相等/:76 N=1/:82 首次脚本/:96-101 布尔位与收束置位;manifest 已在册) |
| F4 | 商店「Boss 前一位必经」断言:`_smoke_shop_graph` 硬编码旧模板形状(商店房恰 1 且 node_depth=8〔next=[9]〕、Boss=9=全图最大编号、DFS 枚举全路径穿商店房 8、跨表 (·,9)/(·,8) 行覆盖+「L1 行集零改动(单链 Boss (1,4))」);路径枚举 `_all_entry_boss_paths`(DFS 迭代栈);行进断言「L2 行进到商店房(节点 8,next=[9]——Boss 前必经位)」;模板感知取节点表 `_level_active_nodes`(恒取模板 0)——**宿主=批 B 迁 G8 单元宿主** | `game/tests/unit/core/level_shop_economy_test.gd:679-715`(_smoke_shop_graph::696 商店恰 1 depth=8/:697 Boss=9 最大编号/:698-703 DFS 穿店/:704-714 跨表行覆盖与 L1 行集零改动)/:936(_all_entry_boss_paths)/:601(行进到商店房)/:970(_level_active_nodes) |
| F5 | Boss 编号最大语义:`_validate_graph` ⑤「Boss 恒唯一终点:无出边 + 编号最大」——`ids[i] != ids.max()` 报「终点编号最大」;连带 :83-84 Boss 计数恰一 | `game/data/schemas/level_table.gd:150-157`/:83-84 |
| F6 | 定位信息与寻址现状:`begin_battle` 组装 enc=`level_index` + `node_depth`(**值实为节点编号**)+ `node_type`;`_node_id` 双编号空间(图形态=node_depth 当节点身份/单链=数组下标,混用注记在案);`_entry_node` 取无入边**唯一**节点;`pick_next_node(node_id)` 按编号选路;断点 `node_id`/`visited_ids` 同编号空间;战斗侧按 (level_index, node_depth, row_kind) 三参解析敌行集(`resolve_enemy_rowset`——迭代 34 卡③ 落地形态) | 组装 `game/core/level_runner.gd:513-525`(:514/:524);`_node_id` :341-347;`_entry_node` :348-358;`pick_next_node` :619 起;断点 `game/core/adventure_runner.gd:1000`/:1017;消费 `game/core/battle_orchestrator.gd:329`(resolve_enemy_rowset 三参)/:357/:447/:1054;跨表覆盖校验 `game/core/config_db_cross_validator.gd:54-106`(模板池感知分支 :76-83;敌侧带寻址+顶 clamp 拦截 :90-102;**迭代 34 写入「同图多终点 Boss 解析带键互异」:103-106——T2 删除范围须按 v1.1 重划**) |
| F7 | 行进语义现状:defer_entry 入口停点(单候选=唯一入口)、`present_entry_choice`、兑付确认后 `_present_choices` 出边候选、零自动推进;`_on_battle_finished` 以「节点 type=="boss"」判关卡收束(Boss 胜=victory、任意败=defeat,多 Boss 场景本就泛化);单链隐式出边(无 next 键=数组序下一项)+`_graph_mode` 探测 | `level_runner.gd:184-233`(:219-223/:228-233)/:561-569/:556-562(:562 boss 判收束)/:360-385(单链隐式出边在 _out_ids/_out_nodes 体内)/:149-158、:202-205 |
| F8 | 断点与确定性承载现状:快照 28 键含 `template_pick`(=`active_template_index`)、`master_seed`、`rng_counter`、`node_id`、`visited_ids`;续玩 `resume_adventure` 回填 `rng.restore_adventure(master_seed, rng_counter)`+强制 `template_pick`(已抽模板续玩零重抽零 RNG 消耗);rng 快照契约=主种子+计数器 | `game/core/adventure_runner.gd:998-1023`(:1000/:1013/:1014/:1015/:1017)/:140-148/:852-854;`game/core/rng_service.gd:4`/:77-83(restore_adventure) |
| F9 | 模板/first_script 依赖面(game/smoke/ 退役后现役清单,2026-10-24 实查,共 12 文件):产品面 4 件——`adventure_runner.gd` 7 处(:45/:102/:194/:850/:852-854/:863/:1013)、`level_runner.gd` 17 处(尾参 :130/:186、解析体 :300-321、active_template_* :304-305)、`main.gd` 2 处(:594-596)、`game/sim/level_autoplay.gd` 7 处(尾参 :37/:63、`level_templates` :141/:200-202、route 轴注释「候选节点编号最小/最大」:12/:377-379);测量面 1 件——`game/sim/adventure_monte_carlo.gd`(`level_templates` 出数面 :139);测试面 7 件——`game/tests/integration/node_map_templates_test.gd`(S1 全段 :32-104)、`game/tests/integration/cross_system_flow_test.gd:79`(`{"first_script": true}` 驱动)、`game/tests/unit/core/meta_progression_forge_test.gd:316/:323-324`(参数面 extra 键样例)、`feat_vouchers_test.gd:25`、`pool_case_d_test.gd:37/:68/:113/:142/:160`(均传 `{"first_script": true}`)、`adventure_feats_test.gd`(模板感知取节点表 :812-816+en_keys 覆盖断言 :112-130)、`level_shop_economy_test.gd`(`_level_active_nodes` :970 及消费 3 处) | 各文件如列 |
| F10 | 形状写死的断言面(模板时代遗留,**宿主=批 B 迁入**):「L2/L3 节点数 = 10」`level_shop_economy_test.gd:102/:257`、「L1 行集零改动(单链 Boss (1,4))」:714、逐节点扫描断言 :105-110/:211-219/:260-274、参数面断言「入口特有键(first_script/shop_mode)随 extra 原样并入」`meta_progression_forge_test.gd:316/:323-324`;历史生成工具 `tools/t5_build_templates.py`/`t17_fanout2_rebuild.py`(一次性内容批工具留档,在盘) | `game/tests/unit/core/level_shop_economy_test.gd` 与 `meta_progression_forge_test.gd` 如列;`tools/t5_build_templates.py:8` 等 |
## 4. 设计契约(红线,违反 = L3 停机呈报)
🔴 **契约 1 · 加载校验换代与 fail-fast**:加载校验(生成图到手、进节点前执行)=四检+良构基底——① 多入口/多终点合法(入口〔无入边节点〕≥1、终点〔无出边节点〕≥1;入口/终点个数与参数档的一致性归卡①产出侧——D1:176 加载校验清单无此项,本卡不核个数);② 每条路径恰好从一个入口出发、恰好到达一个终点(全部节点从某入口可达+可达某终点,无孤儿无断头);③ 终点恒为 Boss(每个终点 type="boss" 且每个 boss 节点无出边);④ 无环(出边目标节点深度严格大于源——连线只朝前进方向);良构基底=节点句柄唯一、出边引用全部命中、type ∈ 五类枚举、battle/boss 节点带节点深度。违规=致命(push_error+起关拒绝,冒险启动失败走既有 fatal 路径),无软回退、无兜底图(D2 执行边界「无效图绝不上给玩家」)。
🔴 **契约 2 · 弃节点编号寻址**:定位信息=(关卡序号, 节点深度)——`node_depth` 键名保留、**值语义换代为自入口步数**(现值实为节点编号,F6);图内行进/断点/呈现读面的节点身份=生成图节点句柄(卡①产出的唯一 id),禁再以 `node_depth` 兼任节点身份(`_node_id` 双编号空间退役)。定位信息两样契约不破(D1:119;卡③ §0 同口径)。
🔴 **契约 3 · 确定性承载=固定种子+固定参数档**:图=(种子, 参数档) 的纯函数——同 (种子, 参数档) 两次产图逐位同图,复现不依赖统一流全局计数器位次(D3:264「首局教学与存档复现的固定图由此承载」+D2 执行边界「同种子+同参数档产出同一张图」合取);首局教学图=首局固定种子 42(main.gd 种子三分判定保持)+固定参数档生成图;存档复现=断点 `master_seed`+参数档重生成同图(断点零新增图身份键);「模板 0=回滚档」语义废除——模板池、`template_pick` 强制、`active_template_*`、`first_script` 参数键全退役(F3/F9 清单)。**旧断点代差显式处置**:断点快照扩列代差标记键(缺省 0/写 1,扩列不升版先例);续玩遇缺标记键的旧断点=`resume_adventure` 显式拒绝(返回 false+push_error,禁按句柄语义静默回放——旧 `node_id` 值与新句柄空间可碰撞错位),旧模板图已随模板池退役、无迁移动作可做(禁凭空捏图=无兜底图红线);处置留痕实现报告。
🔴 **契约 4 · 商店编排语义不破**:每个终点前一位恰一家店(终点直接前驱恰为一家 shop 节点)、商店总数=终点数、所有入口→终点路径穿过且恰穿过一家店(D2 调参表「商店数=出口数」已锁+D1:63)。位置约束**不由加载校验承载、由冒烟断言把关**(D1:63 明文),加载校验禁新增商店位检查。
🔴 **契约 5 · 行进纪律与收束次序不破**:兑付后确认+零自动推进不变;入口不自动进入(多入口时首跳=「从哪进场」的选择,入口停点候选=全部入口节点);任一终点 Boss 战胜利即关卡收束(多 Boss 泛化,走哪条路兑付哪个 Boss)、英雄死亡=失败;收束次序先调战斗结算清库、后宣布关卡结束(D3:275 结构冻结);单链退化形态合法(校验不设「必有岔口」),三关参数档都含岔口是参数/生成面事实(冒烟挂验)。
🔴 **契约 6 · 模板清理义务**:15 张模板数据与模板池代码路径(含冒烟/单测引用面,F9/F10)全部清退,禁留死代码死断言;参数档数据(五旋钮 schema 与初值)不归本卡——随卡①参数 schema 落位,消费侧只读不值(D2「生成器只吃参数档」+数值事实源=data/tables)。
🔴 **契约 7 · 接口纪律**:生成器产图取用卡①接口(§7 取用块;签名与图数据形状以卡①定稿为准,**两条硬语义不随签名浮动**:同 (种子, 参数档) ⇒ 同图;纯函数复现);与卡③的定位信息传递契约零改动(enc 键名 `level_index`/`node_depth`/`node_type` 保持);本卡不实现生成算法、不动敌人表深度带数据(卡③)、不做迷雾可见性(卡④)、不落参数档数值(定值批/难度曲线)。
🔴 **契约 8 · 多终点深度互异(跨卡推论条款 A,卡③契约 6 同源)**:定位信息只有两样且「多终点各配一行(走哪条路决定打谁)」⇒ 多终点必须落在互异深度(同深度多终点=设计不可能态);图侧兑现归卡①产出规格(卡③ §6 反哺点③已布),本卡不新增校验;执行中发现同深度多终点图样 → L3 呈报。
## 5. 范围边界
**做**:加载校验四检+良构(`level_table.gd` 换代);行进语义三件(多入口首跳/多 Boss 收束/单链退化合法);定位信息值语义换代+句柄寻址;确定性承载换代(first_script/template_pick 链路退役、断点键换代);旧 15 张模板 `level.tres` 数据清理+模板池代码路径清退;冒烟断言面换代(商店三条性质断言、含岔口、确定性三条);断言批与变异验证;反哺点清单。
**不做**(明示去向):
- 生成器算法本体(图怎么长、多终点怎么切、产出约束五条的产出侧自证与测试)→ **卡①**;本卡只取用其产图接口;
- 敌人表深度带数据、带切法、`resolve_enemy_rowset` 三参化 → **卡③**(已写卡);本卡只保证传递侧 (关卡序号, 节点深度) 值语义正确;
- 迷雾可见性(近处见类型/远处起雾、Boss 标记不入雾)→ **卡④**;
- 生成图深度扩面的敌/板表数据覆盖(深度带补行/带切法粗化、board_gen/difficulty 键带化)→ 卡③ §5 已登记归口(卡①/后续表批);本卡只把交付序列写死(§0),不扩数据;
- 参数档数值(层深/分支密度/配比/入口个数/出口个数的取值)→ 定值批落表(D2 调参表状态列),本卡零数值;
- 呈现层改版(level-map 屏面布局、节点编号显示、多终点标记画法)→ level-map/HUD 框架与卡④;本卡只保证 runner 只读读面签名不变;
- 历史生成工具 `tools/t5_build_templates.py`/`t17_fanout2_rebuild.py` → 一次性内容批留档不动(`level.tres` 表尾注释已载明)。
## 6. 关联文档同步面
> 本批是代码实现批,禁写 `design/` 整目录与根规则文件,唯一可写目录=`reports/`。下表「同步义务」一律执行为:逐条列进 `reports/iter<N>-反哺点-<完成日>.md`(哪个文件哪一节、改成什么、依据),用户会话裁决后归文档批落文。
| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 |
|---|---|---|
| `design/gdd/systems/冒险循环/关卡节点地图.md` | :57「战斗|携带节点编号」、:156「组装关卡序号 + 节点编号」、:178「每场开战调用携带(关卡序号 + 节点编号)」三处与 :23/:65/:111/:119「关卡序号 + 节点深度」不一致 → 统一为「关卡序号+节点深度(自入口步数)」(本卡契约 2 弃节点编号寻址的文档面) | 反哺点 · 列清单(①用词统一,依据=D1:65/:119 定稿句+用户卡②范围句) |
| `design/gdd/systems/冒险循环/冒险结构.md` | :293 覆盖义务「每个战斗与关底节点(关,深)在敌人与棋盘生成的数值表中有精确行」→ 深度带换代后措辞改「敌侧深度带命中+板侧解析命中」;:264 关卡行集行「旧模板池随实现批清数据」括注在本卡完成后成既成事实(括注注销) | 反哺点 · 列清单(②措辞换代+括注注销,依据=卡③契约 1/本卡完成定义 6) |
| `design/gdd/systems/冒险循环/关卡节点图生成.md` | 无改动(本卡消费其产出规格与执行边界)——但校验四检的实现措辞如与产出规格用语需对齐(「岔口」「终点」「路径」定义引用),T1 注释引用其节号 | 反哺点 · 列清单(③仅在实现注释发现用语漂移时列,无漂移则记「无」) |
| `design/gdd/ux/level-map.md` | 图结构(多入口/多终点/含岔口)呈现面随动义务(06 条目连带面②)——本卡不改呈现代码,读面 API 签名不变(句柄化后编号显示语义漂移:显示的是句柄) | 反哺点 · 列清单(④呈现面随动需求登记归卡④/level-map 文档批) |
| `待办清单.md`(06 登记处) | 本卡登记条状态推进「已写卡(`reports/需求卡片-节点图消费侧换代批-2026-10-21.md`)」(req-card 06 状态回写义务);实现批完成后按退役规则处理 | 反哺点 · 列清单(⑤状态回写与条目退役记载——本会话文件面限于本卡一个文件,回写由批次收口/用户发令执行,防四卡并行互踩) |
| `roadmap.md` | 迭代行编入笔与批内状态刷新 | 反哺点 · 列清单(⑥) |
| `game/data/schemas/level_table.gd`、`game/data/tables/level.tres`、`game/core/level_runner.gd`、`game/core/adventure_runner.gd`、`game/core/config_db_cross_validator.gd`、`game/presentation/main.gd`、`game/core/save_manager.gd` | 消费侧换代与模板清理本体 | 实施本体(可写) |
| `game/tests/integration/node_map_templates_test.gd`、`game/tests/unit/core/level_shop_economy_test.gd`、`game/tests/unit/core/meta_progression_forge_test.gd`、`game/tests/unit/core/adventure_feats_test.gd`、`game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd`、`game/tests/unit/core/config_db_cross_validator_test.gd`、`game/tests/unit/core/breakpoint_resume_test.gd`、`game/tests/unit/core/pool_case_d_test.gd`、`game/tests/unit/core/feat_vouchers_test.gd`、`game/tests/run_all.gd` | 断言面换代与 manifest 登记(§8 S 清单——game/smoke/ 已退役,批 B 后断言面全落 16 宿主) | 实施本体(可写) |
| `game/sim/level_autoplay.gd`、`game/sim/adventure_monte_carlo.gd`、`game/probe/shot_probe.gd`、`game/probe/ui_click_probe.gd` | 驱动/测量/探针面换代(S7) | 实施本体(可写) |
## 7. 任务卡
> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核本卡全部行号。回归措辞模板沿用:里程碑步(T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套。
### 卡前 · 文件结构图
| 文件 | 职责 |
|---|---|
| `game/data/schemas/level_table.gd` | 图合法性校验换代:四检+良构基底(`validate_graph` 静态入口);旧六判据与模板池校验分支退役;行级校验保留 |
| `game/data/tables/level.tres` | 15 张模板数据清理(三行 `templates` 键删除;行级字段保留;参数档字段随卡① schema 不归本卡) |
| `game/core/level_runner.gd` | 图来源换代(卡①产图替代 `_resolve_template_row`)+起关校验调用+多入口首跳+句柄寻址(`_node_id` 双空间退役)+enc `node_depth` 值语义换代 |
| `game/core/adventure_runner.gd` | `first_script`/`template_pick` 链路退役;断点键换代(`template_pick` 退役、`node_id`/`visited_ids` 句柄化) |
| `game/core/config_db_cross_validator.gd` | ④ 关卡节点半边整体退役(:54-106,随静态节点数据消亡——含迭代 34 多终点 Boss 带互异检查的静态形态,语义由 S5/V11 运行时断言承接;跨表校验单测 `_test_level_node_band_rules` 段同步退役) |
| `game/presentation/main.gd` | `first_script` 参数构造退役(种子三分判定保持不动) |
| `game/core/save_manager.gd` | `is_first_adventure_done` 注释语义换代(模板 0 教学重放 → 首局固定种子;键与行为不变) |
| `game/tests/integration/node_map_templates_test.gd`(改)、`game/tests/unit/core/level_shop_economy_test.gd`(改)、`game/tests/unit/core/meta_progression_forge_test.gd`(改)、`game/tests/unit/core/adventure_feats_test.gd`(改)、`game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd`(改)、`game/tests/unit/core/config_db_cross_validator_test.gd`(改)、`game/tests/run_all.gd`(改) | 断言面换代(S1–S8):模板段退役+商店断言换代+形状断言性质化+生成图取数面+④ 静态检查退役随动+新套件 manifest 登记 |
| `game/tests/unit/core/level_table_validate_test.gd`(新建) | 四检+良构单测(正向/负向夹具图) |
| `game/tests/unit/core/breakpoint_resume_test.gd`、`game/tests/unit/core/pool_case_d_test.gd`、`game/tests/unit/core/feat_vouchers_test.gd` | 断点键换代随动、`first_script` 键清退 |
### 接口块(全卡共用,后卡引用以此为准)
- **取用卡①产出:生成器产图接口**(期望签名,**以卡①定稿签名为准**):`generate(level_index: int, params: Dictionary, seed: int) -> Dictionary`。返回期望形状:`{"nodes": Array[Dictionary], "entries": Array[int], "terminals": Array[int]}`;节点期望字段:`{"id": int(图内唯一句柄), "type": String(battle/boss/reward/rest/shop), "depth": int(自入口步数), "next": Array[int](出边目标句柄)}`。**两条硬语义不随签名浮动**:① 同 (seed, params) ⇒ 逐位同图(D2 执行边界);② 纯函数复现——图=(seed, params) 的函数,复现不依赖统一流全局计数器位次(D3:264 存档复现承载合取)。生成器内部取数仍经 RngService(禁自建 RNG 红线不破)——纯函数复现与统一流的机制协调(derive_at 纯派生/号位内重放/RngService 纯流面)归卡①接口定稿,硬语义不变。图数据内部适配(若卡①定稿字段名为 `node_depth`/`depth` 或 id 载体不同)在 T0 对齐后按定稿接线,enc 键名不变。
- **取用卡①产出:参数档 schema**(期望五旋钮行字段:层深/分支密度/配比/入口个数/出口个数,落 `level.tres` 关卡行;字段名与初值以卡①定稿为准,数值归定值批)——消费侧只读该参数档传给 `generate`,不自定值。
- **产出(供战斗侧/卡③)**:`begin_battle` enc 保持 `level_index: int` + `node_depth: int`(**值=节点深度**)+ `node_type: String`;与卡③ `resolve_enemy_rowset(L, D, row_kind)` 衔接零改动。
- **产出(供呈现层)**:runner 只读读面签名不变——`nodes() -> Array`、`node_id_of(node) -> int`(句柄)、`node_out_ids(node) -> Array`、`current_node_id() -> int`、`next_candidate_ids() -> Array`、`visited_ids() -> Array`、`pick_next_node(node_id: int) -> bool`。
- **校验入口**:`LevelTable.validate_graph(nodes: Array) -> Array`(静态函数,返回错误字典列表——与现役 `validate()` 错误形态同构;落点 `level_table.gd`,校验体单一住所不拆)。
### T0 事实坐实与卡①接口对齐(≈0.5–1d)
- [ ] 复核 §3 全部 file:line 与 §2 取用条款行号,漂移即订正本卡——可核查结果:订正记录或「零漂移」声明进实现报告素材。
- [ ] 与卡①接口对齐四件:产图签名、图数据形状(id/type/depth/next 字段名)、参数档 schema 字段名、复现语义(纯函数复现两条硬语义确认)——可核查结果:对齐纪要(定稿签名对照本卡接口块,漂移处回写本卡接口块)。
- [ ] 生成图深度域实测:对 L1/L2/L3 参数档各以种子 42 生成,记录最大节点深度;对照敌/板表覆盖(敌侧顶带键、板侧键域)——可核查结果:覆盖实测表在案;缺覆盖(预期如此,§0 硬交付序列)则登记「数据覆盖批先行」开工前置,缺覆盖状态下不进 T2 切源合入。
- [ ] 改前读数基线采集(冒烟/单测通过数,两入口铁规下随 T1 迭代 loop 首跑取值)——可核查结果:基线读数记录在案。
- [ ] §6 反哺点①-⑥ 条目起草(一节一改一依据)——可核查结果:反哺点草稿段落在 T4 产物成文前就绪。
### T1 加载校验换代(≈1.5–2d)
- [ ] 实装 `LevelTable.validate_graph(nodes: Array) -> Array`(签名与判据=契约 1 四检+良构基底;落点 `level_table.gd`)。可核查结果:正向夹具图(多入口多终点/含岔口/单链)零错误;负向夹具图(非 Boss 终点/带出边的 Boss/环/孤儿节点/断头节点/悬空出边/句柄重复/缺 depth 的战斗节点)各报对应错误类别(沿 `structural`/`dangling_next`/`dup_key`/`enum`/`domain` 词表)。
- [ ] 退役旧判据六项(`level_table.gd:83-84` Boss 恰一、:85-86 战斗 ≥2、:87-90 单链末 Boss、:94-98 前三纯战斗、:133-138 出度 ≤2、:155-157 编号最大)与模板池校验分支(:40-57),行级校验(level_index 唯一/display_name/rest_heal_pct 域)保留。可核查结果:`validate()` 对生产表行级零错误;全仓检索六判据消息文本零残留。
- [ ] 实装无环判据=出边目标节点深度严格大于源(取代「目标编号严格递增」,:126-132 换代)。可核查结果:回边夹具(目标深度 ≤ 源)报「违反前进方向」错误。
- [ ] manifest 登记:`game/tests/run_all.gd` `_suites()` 追加 `{"path": "res://tests/unit/core/level_table_validate_test.gd", "expect": 0}`(对齐既有行体例;批 B 协议——禁「文件在 manifest 不在」空窗)。可核查结果:run_all 实跑套件数 +1 且新套件 PASS。
- [ ] 验收步骤:跑 `godot --headless --path game --script res://tests/unit/core/level_table_validate_test.gd`,期望四检正负向断言全绿。
- [ ] 变异验证(注入→最窄闸见红→`git checkout` 还原→记录):注释掉「终点恒为 Boss」判据 → 期望非 Boss 终点负向用例红;把无环判据改成恒真 → 期望回边负向用例红。记录表进实现报告。
### T2 消费侧切源与行进/定位/确定性换代(≈2–2.5d)
- [ ] 实装图来源换代:`level_runner.gd` `_resolve_template_row`(:300-324,含 :300-305 解析注释与 `active_template_name`/`active_template_index` 声明)删除,起关路径改调卡① `generate(level_index, params, seed)`(params 读关卡行参数档、seed 取本局种子口径——单关自播种/冒险主种子派生,以卡①定稿为准)。可核查结果:起关拿到生成图(夹具参数产图可走通进节点)。
- [ ] 实装起关校验接线:生成图到手、进节点前调用 `LevelTable.validate_graph`,违规 push_error+返回 false(起关拒绝,冒险启动失败走既有 fatal 路径——`main.gd:396` `_fatal_screen`,启动失败挂点 :597)。可核查结果:违规夹具图起关被拒(返回 false)。
- [ ] 实装多入口首跳:`_entry_node`(:348-358)换 `_entry_nodes` 返回全部无入边节点;`defer_entry`/`present_entry_choice` 入口停点候选=全部入口(单入口行为逐位不变)。可核查结果:双入口夹具图首跳候选数=2,pick 任一入口正确进入。
- [ ] 实装句柄寻址:`_node_id`(:341-347)改返回节点句柄(卡① id 字段);`_out_ids`/`_out_nodes`/`visited_ids`/`pick_next_node`/`_restore_to_stop` 同空间随动;单链隐式出边(:360-385 数组序,_out_ids/_out_nodes 体内)退役(生成图恒带显式出边,单链=出度 ≤1 的图)。可核查结果:单链夹具图(显式出边)行进走通;`pick_next_node` 候选外句柄拒绝。
- [ ] 实装定位信息值语义换代:`begin_battle` enc(:513-525)`node_depth` 取节点 `depth` 值(自入口步数);`level_finished` 载荷位置字段句柄化;enc 键名不变。可核查结果:载荷断言(level_index/depth 与图上节点一致)绿。
- [ ] 实装 `adventure_runner.gd` 模板链路删除:`_first_script` 字段与参数读入(:45/:102/:194)、`template_pick` 计算与传递(:850/:852-854/:863)整体删除。可核查结果:全仓检索 `_first_script`/`template_pick` 零引用(`level_autoplay`/单测面随动见 T3)。
- [ ] 实装断点键换代:`_snapshot_breakpoint` 的 `template_pick` 键(:1013)删除、扩列代差标记键(契约 3);`node_id`/`visited_ids`(:1000/:1017)句柄化落档与 `_restore_to_stop` 回读同空间;`resume_adventure` 遇缺标记键旧断点显式拒绝(返回 false+push_error)。可核查结果:断点写读往返无 `template_pick` 键、句柄往返一致;旧形态夹具断点被拒(`breakpoint_resume_test` 面)。
- [ ] 实装 `main.gd` `first_script` 参数构造删除(:594-596);种子三分判定(:1476-1490,`_seed_value` 单点)零改动。可核查结果:首局(`is_first_adventure_done==false`)种子=42、非首局随机两态行为不变。
- [ ] 实装 `save_manager.gd:301-305` 注释语义换代(「模板 0 教学重放」→「首局固定种子」;键与行为零改动)。可核查结果:注释与契约 3 同口径。
- [ ] 实装跨表校验 ④ 关卡节点半边退役+迭代 34 检查语义承接:`config_db_cross_validator.gd:54-106` ④ 整段(模板池感知 :76-83、node_lists 循环、敌侧带寻址/顶 clamp 拦截 :90-102、**迭代 34 写入的「同图多终点 Boss 解析带键互异」:103-106**)随静态节点数据消亡整体删除——该检查的对象=表内静态节点,切源后 `level.tres` 行不再携带节点数据,留置即死代码(契约 6 禁留);其两条拦截语义由 S5 运行时断言承接(顶 clamp 禁消解=`band_of` 非 -1;多终点 Boss 带键互异——对真实生成图逐终点解析比对,拦截面从静态代理升级到消费图本体);`config_db_cross_validator_test.gd` 的 `_test_level_node_band_rules` 段(:19 调用行)同步退役。可核查结果:全仓检索 `node_lists`/「模板池感知」/`level_node_dangling` 零残留;S5 承接断言在位(T3)。
- [ ] 验收步骤:T 段出口跑一次全套闸(`tools/run_all_gates.sh` 按改动域选档),期望除 §8 S 清单未换代条目外零红(S 清单随 T3 收口)。
- [ ] 变异验证:把多入口候选写死单入口 → 期望多入口首跳断言红;把 enc `node_depth` 值取句柄 → 期望定位信息载荷断言红;把断点 `template_pick` 键偷偷写回 → 期望断点键退役断言红。记录表进实现报告。
### T3 模板清理与冒烟断言换代(≈2–2.5d)
- [ ] 实装 `level.tres` 三行 `templates` 键删除(15 张模板数据清出;`level_index`/`display_name`/`rest_heal_pct` 保留)。可核查结果:`git diff` 仅删模板数据段+表尾注释一段(15 张模板去向+参数档字段指引——沿 `level.tres` 既有表尾注释体例);冒烟表校验段行级零错误。
- [ ] 换代模板断言段(S1):`_smoke_node_map_templates`(`game/tests/integration/node_map_templates_test.gd:32-104`)①-⑥ 退役(node_map 标签/池=5/模板 0=现行/强制 0/N=1 回滚档/first_script 分支),⑦ 收束置位断言保留改写(语义换「首局种子 42」注释);替代断言=确定性三条(S6,同宿主落位)。可核查结果:该宿主绿且消息文本无「模板 0/回滚档」字样。
- [ ] 换代生成图取数面(S2):`_level_active_nodes` 三宿主副本(`level_shop_economy_test.gd:970`、`adventure_feats_test.gd:812-816`、`round_flow_skill_pool_test.gd:357`)改经卡①接口取生成图(固定种子+关卡行参数档);消费点(level_shop :102/:105/:211-219/:260-274/:689/:698、adventure_feats :118-130、round_flow :319/:330)随动。可核查结果:三宿主绿、取数面零模板引用。
- [ ] 换代商店断言(S3,三条性质断言):① 每个终点的直接前驱恰为一家 shop 节点(终点入边恰一且 type=="shop");② 商店总数=终点数;③ 所有入口→终点路径穿过且恰穿过一家店(DFS 枚举换代 `_all_entry_boss_paths`(:936)消费句柄/深度,判定=路径上 shop 计数恰 1);断言面=L1/L2/L3 参数档 × 种子扫描(42 与 range(42, 62) 全种子);硬编码「node_depth 8/9/穿节点 8/L1 行集零改动」退役(:696/:697/:698-703/:714);:601 行进到商店房断言改性质(路径上恰一店)。可核查结果:三性质断言在扫描面全绿。
- [ ] 换代形状写死断言(S4)::102/:257「节点数 = 10」改生成图读数性质(节点数 ≥ 层高下限+随图);:714「L1 行集零改动(单链 Boss (1,4))」退役(单链模板消亡,单链合法性改由 V2 夹具承载);逐节点扫描断言(:105-110/:211-219/:260-274)敌侧键面随卡③ S 清单、本卡只换取数面。可核查结果:清单条目逐条勾销、断言面全绿。
- [ ] 换代覆盖义务断言(S5,承接跨表校验④退役后的两条语义):节点源换生成图后,敌侧覆盖判据=`EnemyTable.band_of`(`game/data/schemas/enemy_table.gd:157`)非 -1(禁顶 clamp——承 `config_db_cross_validator.gd:98-102` 静态拦截语义)+**多终点 Boss 解析带键互异**(承迭代 34 `:103-106` 检查语义——对生成图逐终点 depth→`band_of` 解析比对,共带即红);板侧=board_gen 解析命中非空;以 §0 硬交付序列(敌侧带数据覆盖+Boss 带键可互异)为绿灯前提。可核查结果:覆盖与带互异断言在扫描面全绿(数据批先行后)。
- [ ] 新增确定性断言(S6,落点 `game/tests/integration/node_map_templates_test.gd`——S1 同宿主,模板段退役后该宿主承载生成图确定性断言;manifest 已在册零新增登记):① 同 (种子, 参数档) 两次 `generate` 逐位同图;② 首局种子 42 两次开局(`is_first_adventure_done==false`)生成图逐位同图;③ 断点写→`restore_adventure`→再产图同图;④ `level.tres` 无 `templates` 键。可核查结果:四断言绿。
- [ ] 换代驱动/工具面(S7):`game/sim/level_autoplay.gd` `template_pick` 尾参退役(:37/:63)、MC 字段 `level_templates`(:141/:200-202)改生成图身份字段(`level_maps`,值=种子+参数档标识)、route min/max 轴(:12/:377-379)改句柄升/降序(确定性轴保持)、`game/sim/adventure_monte_carlo.gd:139` 出数面随动;探针注释与驱动假设(`game/probe/shot_probe.gd:12-13`、`game/probe/ui_click_probe.gd:373`「L2 商店为 Boss 前必经位」)性质化。可核查结果:autoplay/探针跑通、MC 出数字段名更新。
- [ ] 换代单测随动(S8):`breakpoint_resume_test.gd`(断点无 `template_pick` 键、`node_id`/`visited_ids` 句柄往返、复现同图);`pool_case_d_test.gd`/`feat_vouchers_test.gd` `first_script` 键清退(:37/:68/:113/:142/:160/:25)+`cross_system_flow_test.gd:79` 随动;`main.gd` 参数面断言(`meta_progression_forge_test.gd:316/:323-324` first_script extra 键样例换非 first_script 键,「入口特有键随 extra 原样并入」语义保持)。可核查结果:单测面全绿、全仓 `first_script`/`template_pick`/`active_template` 零引用(件核)。
- [ ] 验收步骤:T 段出口跑一次全套闸,期望冒烟+单测全绿、探针段无红。
- [ ] 变异验证:终点前驱改非店节点 → 期望商店断言①红;某路径加第二家店 → 期望③红;生成器夹具注一滴计数器依赖(同种子两次产图不同)→ 期望 S6① 红;`level.tres` 偷留一个 `templates` 键 → 期望 S6④ 红。记录表进实现报告。
### T4 产出物落位卡(≈0.5d,末卡——三份 `reports/` 文件写齐才算收口)
- [ ] 轻闸全绿后、合并前写齐三份:`reports/iter<N>-实现报告-<完成日>.md`(各卡状态+变异验证记录表+实机目检总清单+遗留读数义务)/`reports/iter<N>-代拍板追认单-<完成日>.md`(§10 白名单内代拍项留痕)/`reports/iter<N>-反哺点-<完成日>.md`(§6 六条每条一落点:①关卡节点地图.md 节点编号措辞、②冒险结构.md 覆盖义务措辞+括注注销、③关卡节点图生成.md 用语核对、④level-map.md 呈现面随动登记、⑤06 状态回写与条目记载、⑥roadmap 编入笔)。可核查结果:三文件在 `reports/` 且 §6 同步面每条有落点。
**估时合计 ≈6.5–8.5d**(T0 0.5–1+T1 1.5–2+T2 2–2.5+T3 2–2.5+T4 0.5)。切分预案:T1 可单独一轮(夹具驱动、不碰运行时);T2+T3 须同轮落地(切源与模板断言换代同拍,拆开中间态冒烟必红);超软盒(>9d)预挂:T3 冒烟面清单若超一孔,先落 S1–S6(模板退役/商店/确定性主链)保主链绿,S7/S8 的探针与单测随动次轮补,全清单绿才收口。
## 8. 验证闸(逐需求点验收清单)
| # | 需求点 | 测什么(断言/行为) | 落点/判定手段 |
|---|---|---|---|
| V1 | 加载校验四检+良构 | 正向:多入口多终点图/含岔口图/单链图过校验;负向:非 Boss 终点、带出边 Boss、环(回边)、孤儿节点、断头节点、悬空出边、句柄重复、战斗节点缺 depth——各报错误且起关拒绝 | 单测 `level_table_validate_test.gd`(新建)+起关拒绝冒烟 |
| V2 | 多入口首跳 | 双入口图入口停点候选=2(全部入口),pick 任一正确进入;单入口行为逐位不变 | 单测(runner 注入图/生成器夹具参数驱动,形态以卡①接口定稿为准) |
| V3 | 大岔口行进与多 Boss 兑付收束 | 多终点生成图(L2/L3 参数档出口 >1 时大岔口分区域)走不同区域各兑付各自 Boss(走哪条路决定打谁——A 区路径不误兑付 B 区 Boss);任一 Boss 胜=`level_finished` 恰一次(result=victory);倒下=defeat;收束次序先清库后宣布(既有断言保持) | 冒烟(生成图驱动全程) |
| V4 | 单链退化合法+三关含岔口+大岔口自 L2 起 | 单链夹具图过校验(不报「必有岔口」类错误);L1/L2/L3 参数档生成图各含 ≥1 个岔口节点(出度 ≥2);L1 生成图终点恰 1(大岔口自 L2 起的图侧投影) | 单测+冒烟(生成图扫描) |
| V5 | 商店编排三条 | 每终点直接前驱恰一店;商店总数=终点数;所有入口→终点路径恰穿一店(DFS);三关参数档×种子扫描(42+range(42,62))全绿 | 冒烟(S3 换代断言) |
| V6 | 定位信息两样 | begin_battle 载荷 (level_index, node_depth) 与图上节点 depth 一致、enc 键名零变化;与卡③三参解析衔接(敌侧行集命中) | 冒烟+单测载荷断言 |
| V7 | 确定性承载 | 同 (种子, 参数档) 两次产图逐位同图;首局种子 42 两次开局同图;断点存→恢复→再产图同图 | 冒烟(S6 ①②③) |
| V8 | 模板 0 语义废除+旧断点代差 | `level.tres` 无 `templates` 键;全仓零 `first_script`/`template_pick`/`active_template` 引用;`is_first_adventure_done` 种子选择两态行为不变(42/随机);缺代差标记键的旧断点被显式拒绝续玩(禁静默回放) | 冒烟(S6④+收束置位改写断言)+单测(旧断点拒绝——`breakpoint_resume_test`)+件核 |
| V9 | 15 张模板清理 | 三行 `templates` 键不在;模板池代码路径(`_resolve_template_row`/模板池校验分支/`_level_active_nodes` 模板读取)零残留;表尾去向注释在位 | 冒烟表断言+件核(git diff 仅删模板段) |
| V10 | 反哺点清单 | §6 六条每条有落点 | 件核对表(T4) |
| V11 | 生成图覆盖+多终点 Boss 带互异(消费侧绿灯断言,S5 承接跨表校验④语义) | 生成图每个 battle/boss 节点深度 `band_of` 非 -1(禁顶 clamp);多终点各深度解析带键两两互异(共带即红);板侧解析命中非空——以 §0 硬交付序列为绿灯前提 | S5 断言(三关参数档×种子扫描,宿主 `level_shop_economy_test.gd` 换代段) |
### 8.1 断言面随动清单(S 清单——模板时代遗留、须换代的断言/直呼面;宿主 2026-10-24 v1.1 重锚=批 B 迁入位)
| # | 断言/直呼面 | 位置 | 换代内容 |
|---|---|---|---|
| S1 | 模板池断言段 `_smoke_node_map_templates` | `game/tests/integration/node_map_templates_test.gd:32-104` | ①-⑥ 退役(node_map 标签/池=5/模板 0=现行/强制 0/N=1 回滚档/first_script 分支);⑦ 收束置位保留改写(语义换首局种子) |
| S2 | 模板感知取节点表 `_level_active_nodes` 三宿主副本及消费点 | `level_shop_economy_test.gd:970`(消费 :102/:105/:211-219/:260-274/:689/:698);`adventure_feats_test.gd:812-816`(消费 :118-130);`round_flow_skill_pool_test.gd:357`(消费 :319/:330) | 改经卡①接口取生成图(固定种子+参数档) |
| S3 | 商店图不变式 `_smoke_shop_graph`+行进到商店房断言 | `level_shop_economy_test.gd:679-715`/:601 | 换三条性质断言(终点前恰一店/商店数=终点数/全路径恰穿一店);硬编码 8/9/穿节点 8/L1 行集零改动退役 |
| S4 | 形状写死断言 | `level_shop_economy_test.gd:102`/:257(节点数=10)/:714(L1 行集零改动)/:105-110、:211-219、:260-274(逐节点扫描) | 节点数改生成图读数性质;L1 单链断言退役;扫描断言敌侧键面随卡③ S 清单、本卡换取数面 |
| S5 | 覆盖义务断言(en_keys 键聚合→生成图覆盖) | `level_shop_economy_test.gd:211-219/:267-274`(跨表行完整)/:704-714(商店房跨表行集)/`adventure_feats_test.gd:118-130` | 节点源换生成图;敌侧判据=`band_of` 非 -1(禁顶 clamp)+多终点 Boss 解析带键互异(承跨表校验④/迭代 34 检查语义);板侧=解析命中非空;以 §0 数据覆盖为绿灯前提 |
| S6 | 确定性断言(新增) | `integration/node_map_templates_test.gd` 换代段(S1 同宿主) | 同图三断言+`level.tres` 无 templates 键(V7/V8 承载) |
| S7 | 驱动/工具面 | `game/sim/level_autoplay.gd:37/:63/:141/:200-202/:12/:377-379`;`game/sim/adventure_monte_carlo.gd:139`;`game/probe/shot_probe.gd:12-13`;`game/probe/ui_click_probe.gd:373` | template_pick 尾参退役;MC 字段 `level_templates`→`level_maps`;route 轴句柄序;探针假设性质化 |
| S8 | 单测随动面 | `breakpoint_resume_test.gd`;`pool_case_d_test.gd:37/:68/:113/:142/:160`;`feat_vouchers_test.gd:25`;`cross_system_flow_test.gd:79`;`meta_progression_forge_test.gd:316/:323-324`(参数面 extra 键样例);`config_db_cross_validator_test.gd`(`_test_level_node_band_rules` 段,:19 调用行) | 断点键换代断言;first_script 键清退;extra 键样例换非 first_script 键(断言语义保持);④ 静态检查段随 T2 退役(语义由 S5 承接) |
清单口径:S1–S6 归 T3 断言面,S7 归 T3 驱动面,S8 归 T2/T3 单测面;「冒烟」措辞沿 v1.0 语义=断言面统称,批 B 后其载体已是 `game/tests/` 各宿主(非 `game/smoke/`——该目录已退役);`tools/` 下历史生成脚本不随动(§5 不做)。
### 8.2 改动—验收对照表
> 六格齐(test-conventions §9.3);层级列只填 §9.2 四层词(单元/接口/集成/探针),件核是证明方式不是层级;T0 为事实坐实卡(无行为改动),其红证并入 V1(加载判据事实面)与 V8(模板链路事实面);纯产出物行按 §9.1 标「非行为改动」。
| 需求点 | 改动 | 验收测试 | 层级 | 真实入口 | 撤销或变异证明 |
|---|---|---|---|---|---|
| 加载校验四检+良构 | `level_table.gd` 新增 `validate_graph`、旧六判据与模板池校验分支退役 | V1(`level_table_validate_test.gd` 正负向夹具+起关拒绝冒烟) | 接口+集成 | 起关真实入口 `LevelRunner.start_level_external`(违规图返回 false) | 变异:注释「终点恒为 Boss」判据→负向红;无环判据短路→回边红 |
| 行进语义(大岔口/多 Boss/单链) | `level_runner.gd` 多入口首跳+句柄寻址+单链显式出边;收束泛化保持 | V2(双入口候选断言)/V3(多终点全程驱动)/V4(单链夹具+含岔口+L1 终点恰 1) | 单元+集成 | 冒烟生成图全程驱动(`level_autoplay.run_level` 真实入口)+runner 夹具单测 | 变异:候选写死单入口→V2 红 |
| 商店编排冒烟换代 | `smoke_all.gd` `_smoke_shop_graph` 三条性质断言换代 | V5(终点前恰一店/商店数=终点数/全路径恰穿一店,种子扫描) | 集成 | 冒烟商店段(`python tools/run_smoke.py`) | 变异:终点前驱改非店→①红;路径加第二店→③红 |
| 生成图覆盖+Boss 带互异(S5 新判据,承跨表校验④语义) | S5 换代断言:`band_of` 非 -1+多终点带键互异+板侧命中(落 `level_shop_economy_test.gd` 换代段) | V11(S5 覆盖与带互异断言,种子扫描) | 集成 | 生成图逐节点/逐终点解析驱动(`resolve_enemy_rowset`/`band_of` 真实消费链) | 变异:enemy.tres boss 带并成单带→带互异断言红;删某 (关,row_kind) 顶带→覆盖断言红 |
| 定位信息两样 | `begin_battle` enc 值语义换代(node_depth=深度)+句柄寻址 | V6(载荷断言+卡③解析衔接) | 接口 | 战斗真实入口 `begin_battle`(冒烟驱动开战) | 变异:enc node_depth 取句柄→V6 红 |
| 确定性承载+旧断点代差 | `adventure_runner.gd`/`main.gd`/`save_manager.gd` 模板链路退役+断点键换代+代差标记键 | V7(S6 同图三断言)/V8(模板键零引用+旧断点拒绝) | 接口+集成 | 冒烟 S6+`breakpoint_resume_test.gd`+续玩真实入口 `resume_adventure` | 变异:生成器注计数器依赖→V7 红;旧断点放行回放→V8 红 |
| 15 张模板清理 | `level.tres` 三行 `templates` 键删除+模板池代码路径清退 | V9(表断言+件核) | 接口 | 冒烟表校验段+`git diff` 件核(仅删模板段) | 变异:留一个 `templates` 键→V9 红 |
| 反哺点清单(**非行为改动**——纯文档产出物,无游戏行为,§9.1) | §6 六条落 `reports/iter<N>-反哺点-<完成日>.md` | V10(件核对表) | 非行为改动 | T4 产出物件核 | 撤销证明:缺任一落点→V10 件核红 |
**旧断言预声明(test-conventions §9.5)**——允许改写的旧断言清单及理由:①§8.1 S1–S8 随动面全部条目(理由:图源换模板池→参数档生成、寻址换句柄与节点深度、断点键换代;其中标注「断言语义保持」者只换键样例/定位方式、判据不动);②V5 商店三条性质断言换代(理由:商店编排规则由「每关恰 1·Boss 前一位」换代为「每终点前一位恰一店」,旧断言判据对象已废);③V8 收束置位改写断言(理由:模板 0 回滚档语义废除,置位条件随种子承载换代);④**跨表校验④静态检查退役**(`config_db_cross_validator.gd:54-106` 含迭代 34「同图多终点 Boss 解析带键互异」:103-106 与顶 clamp 拦截 :90-102,及 `config_db_cross_validator_test.gd` `_test_level_node_band_rules` 段——理由:检查对象=表内静态节点,切源后随模板数据消亡,留置即死代码;两条拦截语义由 S5/V11 运行时断言承接,拦截面从静态代理升级到真实生成图,无削弱)。除此之外的断言删除/放宽/换下层直调=未声明削弱,停卡呈报、独立审计判红。
**独立验收审计**(test-conventions §9.7):合并前由未参与实现的会话或子代理执行——审计入口=只读需求卡片+本对照表+diff+测试文件+实现报告,自跑最窄测试抽查(不采信「已全绿」自述);审计报告文件=`reports/iter<N>-验收审计-<日期>.md`,逐行写「通过/缺漏/例外及依据」,未通过不得合并。测试执行两入口铁规不变(审计在迭代 loop 内启动的子代理算 loop;另开会话须用户点名)。
**测试方式两分法(2026-10-11 用户定)**:V1–V10 全部机检自动化(冒烟+单测);能力验证可经调试接口直改种子/参数档驱动生成图(沿用现役 DebugOverlay/DS_DEBUG 门控)。**用户目检项**:「三关实机选路观感不回归(多入口首跳/大岔口取舍/多终点走向可见)」+「首局教学图体验(42 种子固定图)」两条——观测项写进 `reports/iter<N>-实现报告-<完成日>.md` 实机目检总清单,登记不阻塞(验收时间用户自行安排)。
**闸口径**:轻闸每任务卡出口自跑;批末重闸=`tools/run_all_gates.sh` 按改动域选档(本批只碰 `game/` 代码与数据表 → 代码域档)全绿才合并+改前改后读数对拍。回归措辞:里程碑步(T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套。
**变异验证伴生**(新增/改写验收函数逐条注入实验,记录表进实现报告):终点恒 Boss 判据注释(V1 红)/无环判据短路(V1 红)/多入口候选写死单入口(V2 红)/终点前驱改非店(V5 红)/路径加第二店(V5 红)/enc node_depth 取句柄(V6 红)/生成器注计数器依赖(V7 红)/旧断点缺代差键却放行回放(V8 红)/level.tres 留 templates 键(V9 红)。变异不红则改判据或如实标注拦截边界。
## 9. 异常分级
- **L1(自救)**:断言措辞、命名、注释、消息文本;冒烟消息随语义换代更新。
- **L2(记录继续)**:图数据内部适配形态(句柄载体/生成图在 runner 内的持有结构);校验实现形态(深度单调判据的实现写法);冒烟断言定位写法(生成图直取 vs 经 runner 读面);测试驱动形态(注入图 vs 生成器夹具参数);route 轴/MC 字段命名细节(§10 ⑤)。
- **L3(停机呈报)**:卡①接口与两条硬语义(同图/纯函数复现)不兼容且超出适配面;执行中发现同深度多终点图样(推论条款 A 被破,契约 8);任何触碰定位信息两样契约、收束次序、商店编排语义的诉求;生成图深度域超出敌/板表覆盖且数据批无人接手(§0 硬交付序列失管);模板清理出现残留被外部引用且本卡兜不住;校验四检判据被要求放宽(违 D1:51「加载期拦截」)。
## 10. 代拍板白名单(超清单必呈报)
1. 图数据内部适配形态(节点句柄载体、生成图在 runner 内的持有结构、`generate` 返回值的内部解析)——约束:读面 API 签名不变、句柄唯一、禁 node_depth 兼身份(契约 2)。
2. 校验实现形态(无环判据的深度单调写法 vs DFS 判环——契约 1 语义内)与校验错误类别命名(沿 `structural`/`dangling_next`/`dup_key`/`enum`/`domain` 词表,确需新类别时命名留痕)。
3. 断点键换代细节(代差标记键命名、退役键清单的缺键容忍、句柄字段的断点序列化形态、旧断点拒绝后的盘面处置〔清/留〕)——约束:save 域扩列不升版先例、复现同图不破、旧断点禁静默回放(契约 3)。
4. 冒烟断言定位写法(生成图直取 vs 经 runner 读面)与断言名措辞——约束:禁写死节点编号形状(契约 4)。
5. `level_autoplay` route 轴实现(句柄升/降序的取数写法)与 MC 字段名 `level_maps` 的值形态(种子+参数档标识)。
6. 提交切分与 worktree 分支命名。
## 11. 待裁点
**零待裁点,开工门=U0。**
四处灰色地带已按设计事实推导定值(用户可否决,随 T4 反哺点清单呈报可见):
- **确定性复现机制(契约 3)**:备选「断点存生成图快照」——淘汰依据=D3:264「固定图由此(固定种子+固定参数档)承载」明文,存图快照不是「由种子+参数档承载」;备选「统一流号位重放」——淘汰依据=复现依赖全局计数器位次,与 D2 执行边界「同种子+同参数档产出同一张图」冲突(同参数档不同位次会漂);定值=生成图=(种子, 参数档) 纯函数,断点零新增图身份键,续玩以主种子+参数档重生成同图。依据=D3:264+D2:60 合取。
- **U2 两规则退役(单链前三纯战斗/层宽 ≤5)**:备选「保留作生成图加载校验」——淘汰依据=两规则的判据对象是旧模板形状(`level.tres` 表尾 U2 返工注记在案),D2 v1.1 产出规格无此约束(「宽度=分叉生长」新语义无层宽上限;「前三纯战斗」在含岔口图上不可定义);备选「移交卡①产出约束」——淘汰依据=产出规格五条已锁清单无此两条,扩产出规格归文档批非本卡;定值=随模板池退役,教学担子由首局种子 42 固定图+难度曲线数值责任承载(D1:120「教学位节点同样掷骰、没有结构豁免」)。依据=D2 产出规格+用户卡②范围句「规则语义以生成文档产出规格为准」。
- **多终点深度互异不入本卡校验(契约 8)**:备选「消费侧加载校验加第五检」——淘汰依据=用户范围句明列四检「勿扩勿缩」,且卡③ §0 已把图侧兑现归口卡①产出规格;定值=本卡不新增校验、只留 L3 呈报口(同卡③契约 6 口径)。依据=用户范围句+卡③契约 6。
- **旧断点代差处置(契约 3 代差句)**:备选「旧断点静默按新语义回放」——淘汰依据=旧 `node_id` 值与新句柄空间可碰撞错位(静默错节点=违反 fail-fast);备选「迁移旧断点」——淘汰依据=旧模板图已随模板池退役、旧 node_id 指向的图不复存在,无迁移动作可做(禁凭空捏图=无兜底图红线);定值=扩列代差标记键、缺键旧断点显式拒绝续玩(返回 false+push_error),盘面处置(清/留)落 §10 ③。依据=AGENTS.md fail-fast 红线+D2 无兜底图+迭代 21 T5 开发期破坏性先例。
---
**自审五查记录(2026-10-21)**:①规格覆盖——§1 六件目标/八项完成定义逐条挂 T 卡(校验=T1、行进/定位/确定性=T2、商店冒烟/模板清理=T3、反哺点=T4;确定性横跨 T2 链路退役+T3 断言补齐),无漏项;②步骤扫描——全部步骤一步一动作一可核查结果,实现体只给签名+判据名(`validate_graph` 判据清单、商店三性质断言、确定性三断言),无抄写体;③类型一致性——接口块签名与 T 卡引用逐字一致(`generate(level_index, params, seed)`/`validate_graph(nodes)`/enc 三键/runner 读面七个方法名);④审查焦点——补挂四类失败模式:违规图放行(V1 变异)、商店位漏店/双店(V5 变异)、复现漂移(V7 变异)、模板键残留(V9 变异);⑤篇幅比例——规格约 1 屏、任务卡步骤与实现面 1:1,函数体零展开。
**v1.1 修订自审(2026-10-24,宿主重锚批——六查复核)**:动笔面=§3 F1–F10 宿主与行号重锚(smoke_all 五处指认全迁批 B 宿主:S1→integration/node_map_templates_test、S3/S4/S5 主体→unit/core/level_shop_economy_test、extra 键样例→meta_progression_forge_test、驱动面→sim/probe 新路径)+§0 硬交付序列补 2026-10-24 数据实况与 Boss 带互异条款+T1/T2/T3 行号订正+T1 补 manifest 登记步(阻断 4 闭合)+**T2 跨表校验删除范围重划**(阻断 3 闭合:④ 整段 :54-106 随静态节点数据消亡退役,迭代 34 检查〔:103-106〕的拦截语义由 S5/V11 运行时断言承接——原 v1.0 写「只删死分支」时迭代 34 尚未在该段落码,照旧执行会连带静默删掉已交付断言;拦截面从静态代理升级到真实生成图,无削弱,入旧断言预声明④)+§8.1 S 清单宿主换代+§8/8.2 补 V11 行与变异证明+归据句卡③④ 状态换代。六查:①规格覆盖——设计面零变动(§1/§2/§4 契约未触;§4 契约 8「本卡不新增校验」不受影响——S5 是断言不是加载校验),V11 为既有 §0 交付序列的验收落位(v1.0 缺行,本轮补齐使验收闭合);②步骤扫描——manifest 步与 S5 语义承接步均一步一动作+可核查结果;③类型一致性——签名零变动(卡① 接口块期望签名沿 v1.0 原文,T0 对齐步不变);④改动覆盖——V11 新行带撤销/变异证明(boss 带并单带→红;删顶带→红);⑤篇幅比例——零函数体;⑥落位复用——断言宿主全复用批 B 16 宿主与既有 manifest 行体例,S6 落 S1 同宿主零新增登记。重锚依据=`reports/批B-断言迁移账本-2026-10-22.md`+2026-10-24 master 实查(16c6f136/迭代 34 落地后现态)。
**grilling 复核记录(2026-10-21,设计树对抗复核,不采访用户——可推导定值写依据、真归用户列 §11)**:按设计树走查八支——①校验语义边界(四检 vs 产出规格五条:五条是卡①产出侧自证〔D2:117 产出合格判据〕、四检是消费侧加载拦截〔D1:51/:176 明列清单〕,「个数=参数档」括注归产出侧、本卡不核个数——边界写进契约 1①);②节点深度歧义(合流/多入口下 depth 赋值一致性归卡①产出规格,消费侧以「出边目标深度严格大于源」兜前进方向);③多入口路径语义(「每条路径恰好从一个入口出发」=每个节点在某条入口→终点路径上〔无孤儿无断头〕+入口为无入边节点——形式化写进契约 1②);④确定性复现(三案淘汰两案、定值纯函数复现,§11 留否决口;RNG 机制协调归卡①接口定稿、硬语义不浮动);⑤U2 规则去留(判据对象消亡+产出规格无据 → 退役定值,§11 留否决口);⑥商店「前一位」形式化(D1:63「前一位恰一家店」+D1:182「恰穿一家」+D2「商店数=出口数」三者合取 ⇒ 终点入边恰一且前驱是店——契约 4 表述核对);⑦**旧断点代差(本轮新查出的真缺口)**——旧断点 node_id 与新句柄空间可碰撞静默错位,定值代差标记键+显式拒绝(§11 留否决口);⑧跨卡序列(生成图深度域 vs 敌侧带覆盖=真实缺口,卡③ §5 已登记归口——本卡把交付序列写死为 §0 硬前置而非待裁)。code-conventions 对照:§2.2「跨层标识符语义单一且成文」恰为契约 2 的规范依据(node_depth 双语义是现役违规态)、S9 类型闸与既有 `validate()` 同形、§4.11 新单测不经 autoload 无冲突。AGENTS.md 硬红线逐条过:数值单点(本卡零数值、参数档只读)、RNG 单点(生成器取数归卡①、本卡不自建 RNG)、测试两入口(T 卡只写断言不跑测)、实现批禁写 design/(§6 义务全走反哺点、零旧口径义务措辞)、fail-fast(违规图致命无软回退+旧断点显式拒绝)。结论:零待裁点,四处灰色推导已定值并留 §11 供用户否决。
@@ -1,268 +0,0 @@
# 需求卡片:节点图生成器核心批(参数化长图生成器)· 关卡节点图重构卡①
- 版本:**v1.1**(2026-10-24 修订重锚——§3 行号与断言宿主对齐 game/smoke/ 退役〔16c6f136〕后仓库现态+run_all manifest 登记步补齐;v1.0 2026-10-21 成文,自审五查+grilling 复核结论见文末 §11)
- 来源:[待办清单](../待办清单.md)「关卡节点图重构——可选节点太少」(2026-10-13 登记,来源=playnote,设计面=文档轨,状态=文档设计已闭合)(**唯一事实源**:[关卡节点图生成](../design/gdd/systems/冒险循环/关卡节点图生成.md) **v1.1**(2026-10-21 双定稿闭合凭据之一);协作凭据=[关卡节点地图](../design/gdd/systems/冒险循环/关卡节点地图.md) v2.1+[冒险结构](../design/gdd/systems/冒险循环/冒险结构.md) 关卡行集/结构冻结/覆盖义务行)
- 归属:关卡节点图**生成侧**(参数化长图生成器算法本体+五旋钮参数档数据表+产出约束自证+执行边界+确定性承载);关卡节点图重构批**卡①**(卡②消费侧换代/卡③敌人表深度带〔已落地·迭代 34〕/卡④迷雾可见性〔已落地·迭代 34〕同批)
- 排期:未编入(2026-10-18 用户令:需求卡片不预占迭代号,批次归属按工作量另裁)
- 开工门:U0(用户 `/iter` 发令)+ grilling 复核门过(零待裁点,见 §11)
## 0. 前置依赖与并行性
- **设计闭合(第〇步)**:06 条目「关卡节点图重构——可选节点太少」状态=文档设计已闭合,凭据=关卡节点图生成.md v1.1+关卡节点地图.md v2.1(各带路径+版本号)→ 放行写卡。
- **本卡是生成侧,被卡②硬依赖**:卡②(消费侧换代)运行时图来源换成生成器产图,其契约 7/接口块明文「签名与图数据形状**以卡①定稿为准**」;本卡 §7 接口块即该定稿,卡② T0 按本卡对齐(产图签名/图数据形状/参数档 schema 字段名/复现语义四件)。**并行无阻塞**:本卡不依赖卡②实现,自证产出合法图即可独立验收。
- **输出推论条款 A 给卡③**:卡③(敌人表深度带)契约 6 推论条款 A「多终点深度互异」的**图侧兑现归本卡产出规格**(卡③ §6 反哺点③明文派发);本卡把「多终点落在互异节点深度」定为产出约束(§4 契约 3/§8 V6)。
- **RNG/复现机制由本卡定稿**:卡② 契约 3 把「纯函数复现与统一流的机制协调(derive_at 纯派生/号位内重放/RngService 纯流面)归卡①接口定稿,硬语义不变」——本卡 §4 契约 1 定值为 RngService 纯流面(推导链见 §11)。
- **深度赋值语义由本卡定稿**:卡② 契约 1④/grilling 注记「合流/多入口下 depth 赋值一致性归卡①产出规格」——本卡定值为「自入口最长路径步数」(§4 契约 2,推导链见 §11)。
- **生成图深度扩面的敌/板表覆盖(遭遇坐标覆盖)不在本卡**:归卡③ §5 已登记的「生成图深度扩面覆盖问题(卡①/后续表批)」中的**后续表批**——本卡只产出深度值并登记交付序列依赖(§5 不做/§6 反哺点),敌/板表补行是数值/敌人表(卡③/后续表批),本卡零敌数值(用户范围句明示「敌人表深度带(卡③)」不做)。
## 1. 目标与完成定义
**目标**:把关卡节点图生成 v1.1 的「参数化长图生成器」落成一个**纯函数生成器**——吃「参数档+种子」产出一张合法节点图,交付给消费侧(卡②)。四件本体:① 五旋钮(层深/分支密度/配比/入口个数/出口个数)+ L1/L2/L3 参数档数据表(schema+.tres,provisional 值);② 产出约束五条+结构铁律(生成器产出自证);③ 摆放约束三条(商店位/岔路取舍·下一跳/岔路取舍·支路构成);④ 执行边界四条(不合格禁止进玩法/无兜底图/参数无解即 fail-fast/同种子+同参数档=同图、随机只经 RngService)。
**相对现状,新增了什么**(现状=固定模板池,见 §3):
1. 运行时参数化生成器:图从「固定 15 张模板池」换成「(参数档, 种子) 纯函数生成」——改形态=改参数不改代码;
2. 五旋钮参数档数据表(schema+.tres,L1/L2/L3 三档,provisional 值)+ ConfigDB 注册与单点读取;
3. 产出约束/结构铁律/摆放约束的**产出侧自证**(生成器交付前强制过一遍,不过即参数无解致命);
4. 确定性承载:同(种子, 参数档)⇒ 逐位同图,纯函数复现、复现不依赖统一流全局计数器号位(RngService 纯流面);
5. 多入口多终点/每路径恰一入一出/大岔口自 L2 起(L1 出口恒 1)/多终点深度互异 的图侧兑现。
**完成定义**(全部满足才算本批完成):
1. `generate(params, seed)` 产出图**必过**产出约束五条+结构铁律+摆放约束三条(生成器产出自证在位,自证失败=参数无解致命中止);
2. 参数档数据表(schema+.tres)落地 ConfigDB 单点读取,L1/L2/L3 五旋钮齐备(provisional 值,域校验通过);生成器只吃参数档、不认关卡号;
3. 确定性:同(种子, 参数档)两次产图逐位同图;复现不依赖统一流计数器号位(counter 无关);随机只经 RngService(纯流面),零 `randomize()`/零自建 RandomNumberGenerator;
4. 生长递增:L1/L2/L3 读数(最长路径步数、节点总数)逐关递增,且节点总数增幅 Δ(L2→L3)>Δ(L1→L2);
5. 专项兑现:L1 出口恒 1、大岔口(多终点归属锁定)自 L2 起;任意岔口各去路下一节点类型互不相同、各支路构成互不相同;每条入口→终点路径恰过一家店;多终点落在互异节点深度;战斗节点数 ≥ 保底数;
6. 参数无解(给不出合法图)=配置错误,致命中止(fail-fast),无兜底图、无软回退;
7. §8 验收断言批全绿+变异验证记录表进实现报告;
8. 批末重闸按改动域选档全绿+改前改后读数对拍;三份 `reports/` 产出物写齐(T4)。
## 2. 设计事实源
| # | 出处(**唯一事实源**) | 取用条款 |
|---|---|---|
| D1 | `design/gdd/systems/冒险循环/关卡节点图生成.md` **v1.1**(2026-10-21,06 闭合凭据之一——本卡 100% 以它为唯一设计依据) | :41-49 产出约束五条(道路系统=除岔口〔≥2 去路〕外每节点恰一条去路、岔口去路 2–3/宽度=分叉生长〔不摆平行层、同深度节点数由岔口自然长出 1→2→3→4〕/层高=沿路步数〔入口到终点最长路径步数、L1≥6、逐关递增且增幅变大〕/出口归属锁定〔大岔口分成互不连达区域、各区域只通向自己的终点、终点前一层去路集合恰含一个终点〕/战斗节点保底);:51 结构铁律(连线只朝前进方向无环/入口终点可多个〔个数=参数档〕/每条路径恰从一入口出发恰到一终点);:53-60 执行边界四条(不合格产出禁止进玩法/无兜底图〔软回退禁〕/参数无解即致命中止/同种子+同参数档产出同一张图、随机只经 RngService 统一流);:62-72 五旋钮与三套参数档(层深/分支密度/配比/入口个数/出口个数;**生成器只吃参数档、不认关卡号**;生长曲线层高宽度节点数路径长度逐关递增且增幅变大、决策点密度逐关递增、第一关即含岔口;单链是分支密度取下限合法退化形态、不作为三关取值;大岔口自第二关起、第一关出口恒 1);:74-88 配比与摆放约束三条(商店位=每终点前一位恰一店/岔路取舍·下一跳=一岔口各去路下一节点类型互不相同、下一跳必在可见范围/岔路取舍·支路构成=一岔口各支路节点类型构成互不相同、每支路至少一个别的支路没有的类型)+扩展节点类型位;:86 内容归 owner(战斗打谁=敌人系统深度带配池);:101-115 调参表(层深 L1≥6 已锁/L2>L1 增幅变大 provisional/岔口去路 2–3 已锁/分支密度 provisional〔一局十几次〕/入口 1 起 provisional/出口 L1 恒 1、L2/L3 1–3 已锁范围/配比 provisional/战斗保底数 provisional/商店数=出口数已锁);:117-128 验收标准(产出合格/生长递增〔L1/L2/L3 最长路径步数与节点总数递增、Δ(L2→L3)>Δ(L1→L2)〕/归属锁定/必经恰一店/岔路取舍/可复现/无软回退/战斗保底) |
| D2 | `design/gdd/systems/冒险循环/关卡节点地图.md` v2.1(2026-10-21,06 闭合凭据之一——走图视角语义参照,本卡不实现走图) | :51 结构铁律走图三句(无环/每路径恰一入一出/终点恒为 Boss 可多个)+「规则语义以关卡节点图生成的产出规格为准」;:57-61 五类节点(battle/boss/reward/rest/shop,Boss 恒为终点);:65 节点深度=自入口步数、遭遇坐标=关卡序号+节点深度、终点恒在各路径最深处、单链合法退化、三关参数档都含岔口;:63 商店编排(每终点前一位恰一店、每局必经恰一店、位置约束由冒烟断言把关非加载校验);:103 下一跳必在可见范围(可见性规则归卡④);:119 定位信息只有两样(关卡序号+节点深度) |
| D3 | `design/gdd/systems/冒险循环/冒险结构.md`(状态:已定稿) | :264 关卡行集行(关卡表逐关行承载关数与图的参数档;「旧模板池随实现批清数据」;「**确定性 = 固定种子+固定参数档(首局教学与存档复现的固定图由此承载,无兜底模板)**」);:275 结构冻结(终点恒为 Boss〔终点可多个、各在路径最深处〕、一冒险一主种子、收束点先清库后宣布);:293 覆盖义务(行集内每个战斗与关底节点〔关,深〕在敌人与棋盘生成的数值表中有行——**措辞随深度带换代**,敌/板表覆盖归卡③/后续表批) |
闭合凭据一致性:D1 与 06 条目状态内列的设计定稿逐字一致(`关卡节点图生成.md` v1.1);D2/D3 为协作语义参照,与 D1 同向(确定性、结构铁律、覆盖义务)。
## 3. 现状事实(2026-10-21 成文实查;行号 2026-10-24 v1.1 重锚——对齐 game/smoke/ 退役〔16c6f136〕与迭代 34 落地后 master 现态;开工日 T0 复核行号)
| # | 事实 | 出处 |
|---|---|---|
| F1 | **无运行时参数化生成器**;图来自固定模板池(15 张=3 关×5 张,L1 五张=单链排列变体 7 节点、L2/L3 网状 10 节点 node_depth 0–9);离线工具 `tools/t5_build_templates.py`/`t17_fanout2_rebuild.py` 一次性预生成入库(非运行时生成) | 模板数据 `game/data/tables/level.tres:8`(L1 五链)/:9(L2 五网)/:10(L3 五网);表尾生成史注释 `level.tres:13-19`(:19「生成器 = tools/t5_build_templates.py」);离线工具 `tools/t5_build_templates.py`/`tools/t17_fanout2_rebuild.py` 在盘 |
| F2 | 节点图数据结构=`level_row.nodes: Array[Dictionary]`,节点=`{node_depth, type, next?}`;图形态=任一节点带 `next`(`_graph_mode` 探测);节点 id 双编号空间(图=`node_depth` 当节点身份/单链=数组下标,注记「混用两空间会碰撞」);入口取「无入边**唯一**节点」 | 结构与探测 `game/core/level_runner.gd:67`/:149-158/:202-205;`_node_id` 双空间 `level_runner.gd:341-347`;`_entry_node` 唯一 `level_runner.gd:348-358`;出边 `_out_ids`/`_out_nodes` `level_runner.gd:360-385` |
| F3 | 现行图合法性校验约束与 D1 v1.1 冲突(旧模板形状约束):出度 ≤2(:133-138)、入口唯一〔无入边恰一〕(:139-149)、Boss 唯一终点+无出边+编号最大(:150-157)、Boss 计数恰一(:83-84)、单链末 Boss(:87-90)、单链前三纯战斗 U2(:94-98)、BFS 层宽 ≤5 U2(:183-201)——D1 v1.1 多入口多终点/岔口去路 2–3/大岔口自 L2 起 与之冲突;换代归卡②(消费侧加载校验),本卡产出侧按 D1 v1.1 | 校验体 `game/data/schemas/level_table.gd:83-84`/:87-90/:94-98/:133-138/:139-149/:150-157/:183-201 |
| F4 | 模板抽取经 `node_map` 流(`rng.open_stream("node_map")` 抽签)/`template_pick` 强制取模板;`begin_battle` 组装 enc=`level_index`+`node_depth`(值实为节点编号)+`node_type` | 抽取 `level_runner.gd:307-324`(:317-318 抽签、:314-315 强制);enc 组装 `level_runner.gd:513-525`(:514/:524) |
| F5 | RngService 统一随机流单点(禁 `randomize()`/自建 RNG):`open_stream(purpose)` 经全局计数器取号(计数器 +1)、`derive_at(scope)` 纯派生不推计数器、`PURPOSE_TAGS` 含 `node_map`;快照契约=主种子+计数器 | 类头纪律 `game/core/rng_service.gd:3`;`PURPOSE_TAGS` :9;`derive_at` :34-37;`set_master_seed` :52;`new_adventure` :67;`open_stream` :86-99;AGENTS.md:73「RNG 单点——禁 randomize()/自建 RandomNumberGenerator,随机只经 RngService 统一流」 |
| F6 | ConfigDB 数据表注册模式:`_tables` 映射表名→.tres、`var level: LevelTable`、`load_tables` 装载、访问器单点读取(`level_row(level_index)`);数值单一事实源=`data/tables/*.tres` 经 ConfigDB 单点读 | 注册映射 `game/core/config_db.gd:20`;成员 `config_db.gd:40`;装载 `config_db.gd:142`;访问器 `config_db.gd:245-246`;AGENTS.md:72 数值单一事实源 |
| F7 | 数据表 schema 范例(`rows: Array[Dictionary]`+`validate()` 域校验,空表=合法态):难度表 schema 同构可循 | `game/data/schemas/difficulty_table.gd:7`(rows)/:13-27(validate 域校验);同构参照 `game/data/schemas/level_table.gd:7/:21` |
| F8 | Core 层纪律:完整玩法须可 `--headless --script` 跑通、零 UI 依赖;`--script` 模式禁裸 autoload 标识符(ConfigDB/RngService 经节点路径注入) | AGENTS.md:75;`code-conventions.md:71`(`--script` 禁裸 autoload,经 `get_node("/root/…")`);`level_runner.gd:2-3`(Core 零 UI、headless 可跑) |
## 4. 设计契约(红线,违反 = L3 停机呈报)
🔴 **契约 1 · 生成器纯函数复现+RNG 单点(纯流面)**:`generate(params, seed)` 是 **(参数档, 种子) 的纯函数**——同(种子, 参数档)两次产图逐位同图,复现**不依赖**统一流全局计数器号位(D3:264「固定图由固定种子+固定参数档承载」+D1:60「同种子+同参数档产出同一张图」合取;断点续玩以「主种子+参数档」重生成同图、断点零新增图身份键——resume 在停点号位重生成,号位≠产图号位,故必须 counter 无关)。生成器取数**只经 RngService 纯流面**(新增 `pure_stream(seed_val, scope) -> RandomNumberGenerator` 或等价纯派生面:seed 键值、纯函数、**不推 `_counter`、不落事件日志**);**禁 `randomize()`/禁自建 RandomNumberGenerator/禁 `open_stream` 取数**(open_stream 推计数器=号位相关,破坏 counter 无关)。RNG 单点红线不破:随机仍出自 RngService(自建 RNG 才是红线违例,RngService 提供纯流面属服务内分工)。纯流面机制协调是本卡定稿(§11 推导),硬语义(纯函数/counter 无关/同图)不随机制实现浮动。
🔴 **契约 2 · 节点深度语义单一(id=句柄/depth=自入口步数)+多终点深度互异**:图数据节点字段拆两轴——`id: int`=图内唯一句柄(导航身份);`depth: int`=**自入口最长路径步数**(遭遇坐标取值,D2:65「节点深度=自入口步数」)。禁 `node_depth` 兼任身份与深度(code-conventions §2.2「位置/句柄/键三种不同、禁凭当前恰好相等传值」——现役 node_depth 双语义即违规态)。`depth` 赋值定值=**自入口最长路径步数**(多入口取「距任一入口最长路径」),此赋值使「出边目标 depth 严格大于源」成为有效无环判据(D1:51 无环+卡② 契约 1④)+与「层高=沿路最长步数」(D1:47)一致。**多终点深度互异**(推论条款 A,卡③ 契约 6 派发本卡兑现):多终点各落在互异 `depth`(同 depth 多终点在「定位信息只有两样〔关,深〕」下不可区分=设计不可能态,D2:119+D1:96「多终点各配 Boss 行」+「走哪条路决定打谁」合取);单终点(L1)不涉。
🔴 **契约 3 · 产出约束五条+结构铁律是产出规格唯一陈述处(产出自证)**:生成器交付前强制自证产出过 D1:41-51 全部——产出约束五条(道路系统〔除岔口外每节点恰一条去路、岔口去路 2–3〕/宽度=分叉生长〔不摆平行层、宽度源于岔口〕/层高=沿路步数〔L1≥6、逐关递增增幅变大〕/出口归属锁定〔大岔口分互不连达区域、各区域只通自己终点、终点前一层去路集合恰含一个终点〕/战斗节点保底)+结构铁律(无环〔连线只朝前进〕/入口终点可多个〔个数=参数档〕/每路径恰从一入口出发恰到一终点)。自证不过=**产出不合格**(执行边界①)。
🔴 **契约 4 · 执行边界四条(无兜底图、fail-fast)**:① 不合格产出禁止进玩法(自证不过的图绝不上给玩家);② 无兜底图(不设固定兜底图、软回退一律禁);③ 参数无解即配置错误、致命中止(fail-fast,push_error+assert/既有 fatal 路径,禁静默降级、禁空图/残图回退);④ 同种子+同参数档=同图(见契约 1)。禁任何「生成失败就用模板/用空图/用上一张」回退。
🔴 **契约 5 · 摆放约束三条**:① 商店位=每个终点前一位恰一家商店(每名玩家一局必经恰一家店)+商店总数=出口数(D1:115 已锁)+每条入口→终点路径恰过一家店;② 岔路取舍·下一跳=一个岔口分出的各去路,下一节点类型互不相同;③ 岔路取舍·支路构成=一个岔口分出的各支路,节点类型构成互不相同、每支路至少一个别的支路没有的类型。位置约束(①)由生成器产出侧兑现+冒烟/单测断言把关(D2:63「不由加载校验承载、由冒烟断言把关」——卡② 加载校验不查商店位,本卡产出侧必须产对)。
🔴 **契约 6 · 五旋钮+生成器只吃参数档不认关卡号**:生成器输入=参数档(五旋钮值)+种子,**不接收、不读取关卡序号**(D1:72「生成器只吃参数档、不认关卡号」);调用方(冒险结构/卡②)负责 level_index→参数档 解析后把参数档交给 `generate`。图=f(参数档, 种子),与第几关无关(同参数档+同种子⇒同图,即便来自不同关)。五旋钮=层深/分支密度/配比/入口个数/出口个数;配比四类占比合计 1、战斗保底优先;商店数=出口数(结构事实,非配比自由项)。
🔴 **契约 7 · 接口纪律与边界**:生成器产出图给卡②(§7 接口块,签名与图数据形状本卡定稿、两条硬语义〔同图/纯函数复现〕不随签名浮动);`depth` 喂遭遇坐标 (关,深) 交卡③ 带寻址(enc 键名 `level_index`/`node_depth`/`node_type` 保持,`node_depth` 值=`depth`);图结构只读读面供卡④ 可见性(可见性规则归卡④,本卡只保证类型数据在节点上)。本卡不实现生成算法之外的:走图/行进/兑付(卡②)、敌人表深度带与敌数值(卡③)、迷雾可见性(卡④)、参数档数值定值(定值批,数值全 provisional)。
## 5. 范围边界
**做**:参数化长图生成器本体(`generate(params, seed)` 产合法图);五旋钮参数档数据表(schema+.tres,L1/L2/L3,provisional 值)+ ConfigDB 注册单点读;产出约束五条+结构铁律+摆放约束三条的产出侧自证;执行边界四条(含 RNG 纯流面确定性承载、参数无解 fail-fast);验收断言批(产出合格/可复现/岔路取舍/必经恰一店/归属锁定/多终点深度互异/战斗保底/生长递增/L1 出口恒 1·大岔口 L2 起/参数无解)+变异验证设计。
**不做**(明示去向):
- 消费侧行进(加载校验换代、行进语义、句柄寻址、模板清理、确定性承载链路退役)→ **卡②**(已写卡);本卡只交付产图接口;
- 敌人表深度带(带切法、`resolve_enemy_rowset`、敌数值、多 Boss 行集)→ **卡③**(已写卡);本卡只产出 `depth` 值与多终点深度互异;
- 迷雾可见性(近处见类型/远处起雾、可见层数 N、Boss 标记不入雾)→ **卡④**(已写卡);本卡只保证节点 `type` 数据在节点上;
- **参数档数值定值**(层深/分支密度/配比/入口/出口/战斗保底的最终取值)→ 定值批落表(D1 调参表状态列),本卡 .tres 值全 **provisional**;
- **生成图深度扩面的敌/板表覆盖**(遭遇坐标覆盖义务:生成深度域须被敌侧深度带、板侧键域覆盖)→ 卡③/后续表批(§0);本卡只产出深度、登记交付序列依赖,零敌数值零板数值;
- 生成算法的具体长图步骤(怎么从旋钮长出一张合法图)→ 代码实现自由(D1:28「生成算法本身归代码——图怎么长出来是实现的事」);本卡只定产出规格与执行边界(WHAT,不写 HOW);
- 旧 15 张模板 `level.tres` 清理与模板池代码路径退役 → **卡②**(契约 6 模板清理义务);本卡不删模板数据;
- 呈现层(level-map 画布自适应、多终点标记画法)→ level-map/HUD 框架与卡④。
## 6. 关联文档同步面
> 本批是代码实现批,禁写 `design/` 整目录与根规则文件,唯一可写目录=`reports/`。下表「同步义务」一律执行为:逐条列进 `reports/iter<N>-反哺点-<完成日>.md`(哪个文件哪一节、改成什么、依据),用户会话裁决后归文档批落文。同步义务一律走反哺点清单,禁用旧口径的「随文档批一并落」式措辞(2026-10-17 起作废)。
| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 |
|---|---|---|
| `design/gdd/systems/冒险循环/关卡节点图生成.md` | 产出规格「多终点深度互异」条款缺位——本卡契约 2 兑现推论条款 A(卡③ 契约 6 图侧);「深度=自入口最长路径步数」赋值语义宜在图规格节成文(消 node_depth 双语义歧义) | 反哺点 · 列清单(①产出规格补「多终点落在互异节点深度」+「节点深度=自入口最长路径步数」赋值句,依据=D2:119+D1:96+卡③ 契约 6) |
| `design/gdd/systems/冒险循环/关卡节点地图.md` | :65「节点深度=从入口沿路走过来的步数」与「最长路径步数」在合流图上的赋值一致性宜钉成「自入口最长路径步数」(消歧) | 反哺点 · 列清单(②深度赋值消歧补注,依据=契约 2 推导;无歧义实现则记「无」) |
| `design/gdd/systems/冒险循环/冒险结构.md` | :293 覆盖义务措辞「精确行」随深度带换代(归卡③ 反哺点);:264「旧模板池随实现批清数据」归卡② 完成后注销(本卡不动模板数据) | 反哺点 · 列清单(③仅登记本卡产出深度域供覆盖核对,覆盖措辞归卡③ 落——本卡零改动) |
| `design/gdd/ux/level-map.md` | 图形态随参数变化(多入口/多终点/含岔口/深度域扩面)呈现面自适应义务(06 条目连带面②)——本卡不改呈现代码 | 反哺点 · 列清单(④呈现面随动需求登记归卡④/level-map 文档批) |
| `待办清单.md`(06 登记处) | 本卡登记条状态推进「已写卡(`reports/需求卡片-节点图生成器核心批-2026-10-21.md`)」(req-card 06 状态回写义务) | 反哺点 · 列清单(⑤状态回写与条目退役记载——本会话文件面限于本卡一个文件,回写由批次收口/用户发令执行,防四卡并行互踩) |
| `roadmap.md` | 迭代行编入笔与批内状态刷新 | 反哺点 · 列清单(⑥) |
| `game/core/node_map_generator.gd`、`game/data/schemas/level_gen_params.gd`、`game/data/tables/level_gen_params.tres`、`game/core/rng_service.gd`、`game/core/config_db.gd` | 生成器本体+参数档数据表+RNG 纯流面+ConfigDB 注册 | 实施本体(可写) |
| `game/tests/unit/core/node_map_generator_test.gd`、`game/tests/unit/core/node_map_growth_test.gd`、`game/tests/unit/data_config/level_gen_params_test.gd` | 验收断言面(§8 V 清单;game/smoke/ 已退役〔16c6f136〕——批 B 后断言面全落 `game/tests/` 宿主) | 实施本体(可写) |
| `game/tests/run_all.gd` | 三套新测试套件 manifest 登记(`_suites()` 追加三行 `expect=0`——manifest 数即闸 02 计数口径,未登记=闸 02 不执行) | 实施本体(可写) |
## 7. 任务卡
> 估时按 Claude 工作日口径;每卡出口自跑轻闸;开工日 T0 复核本卡全部行号与取用条款行号。回归措辞模板沿用:里程碑步(T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套。生成算法长图步骤(HOW)归实现(D1:28),本卡只钉产出规格、签名、取值与断言。
### 卡前 · 文件结构图
| 文件 | 职责 |
|---|---|
| `game/data/schemas/level_gen_params.gd`(新建) | 参数档 schema:五旋钮+战斗保底+岔口去路数域,`rows: Array[Dictionary]`(键=level_index)+`validate()` 域校验+`row_by_level_index()` 单点读 |
| `game/data/tables/level_gen_params.tres`(新建) | L1/L2/L3 三行参数档数据(provisional 值) |
| `game/core/node_map_generator.gd`(新建) | 生成器核心:`generate(params, seed) -> Dictionary` 产合法图;产出侧自证(产出约束五条+结构铁律+摆放约束三条);确定性(RngService 纯流面);参数无解 fail-fast |
| `game/core/rng_service.gd`(改) | 新增纯流面 `pure_stream(seed_val: int, scope: int) -> RandomNumberGenerator`(seed 键值、纯函数、不推 `_counter`、不落日志)——生成器结构取数唯一源 |
| `game/core/config_db.gd`(改) | 注册 `level_gen_params` 表(_tables 映射+成员+装载)+访问器 `level_gen_params_row(level_index: int) -> Dictionary` |
| `game/tests/unit/core/node_map_generator_test.gd`(新建) | 生成器验收断言(产出合格/可复现/岔路取舍/必经恰一店/归属锁定/多终点深度互异/战斗保底/L1 出口恒 1·大岔口 L2 起) |
| `game/tests/unit/data_config/level_gen_params_test.gd`(新建) | 参数档 schema validate+值域断言(五旋钮/合计 1/出口范围/层深下限) |
| `game/tests/unit/core/node_map_growth_test.gd`(新建) | 生长递增断言(L1/L2/L3 最长路径步数与节点总数递增、Δ(L2→L3)>Δ(L1→L2))+参数无解 fail-fast 断言 |
### 接口块(全卡共用,邻卡引用以此为准——卡② T0 按此对齐)
- **产出(供卡② 消费侧):生成器产图接口(本卡定稿)**——`generate(params: Dictionary, seed: int) -> Dictionary`。返回形状:`{"nodes": Array[Dictionary], "entries": Array[int], "terminals": Array[int]}`。节点字段:`{"id": int(图内唯一句柄), "type": String(battle/boss/reward/rest/shop), "depth": int(自入口最长路径步数), "next": Array[int](出边目标句柄)}`。`entries`=入口句柄数组(无入边节点,个数=params.entry_count);`terminals`=终点句柄数组(type=boss、无出边,个数=params.exit_count)。**两条硬语义不随签名浮动**:① 同(seed, params)⇒ 逐位同图;② 纯函数复现——图=(seed, params) 的函数,复现不依赖统一流全局计数器号位。**签名修正(对卡② 期望签名 `generate(level_index, params, seed)` 的定稿裁剪)**:`generate` **不收 `level_index`**(契约 6「生成器只吃参数档、不认关卡号」,D1:72);调用方自行 level_index→params 解析后调 `generate(params, seed)`。卡② T0 按本卡去掉 level_index 形参接线。
- **产出(供卡②/卡③ 定位信息)**:节点 `depth`=遭遇坐标深度轴,喂 enc `node_depth`(键名不变、值=`depth`);多终点落在互异 `depth`(契约 2)。enc 三键 `level_index`/`node_depth`/`node_type` 与卡③ `resolve_enemy_rowset(L, D, row_kind)` 衔接零改动。
- **产出(参数档数据表)**:`level_gen_params` schema+table;ConfigDB 访问器 `level_gen_params_row(level_index: int) -> Dictionary`(返回该关五旋钮行);卡② 只读该参数档传给 `generate`,不自定值。字段名(schema 键):`layers`(层深)、`branch_density`(分支密度)、`battle_ratio`/`reward_ratio`/`rest_ratio`/`shop_ratio`(配比四类)、`entry_count`(入口个数)、`exit_count`(出口个数)、`battle_floor`(战斗保底数)、`fork_ways_min`/`fork_ways_max`(岔口去路数,锁 2/3)。
- **取用(RngService 纯流面)**:`RngService.pure_stream(seed_val: int, scope: int) -> RandomNumberGenerator`(本卡新增;生成器结构取数唯一源,禁 `open_stream`/`randomize()`/自建 RNG)。`scope`=生成器取数分域(代拍板 §10 ①:单流多次取数 vs 逐决策 scope,约束=纯函数、counter 无关、同图)。
- **校验边界**:生成器产出侧自证(本卡)=产前强制过产出约束五条+结构铁律+摆放约束三条;卡② 消费侧加载校验(`validate_graph`)=独立防御(四检+良构),两者同源 D1 产出规格、分工不重叠(本卡不实现消费侧校验)。
### T0 事实坐实与跨卡接口对齐(≈0.5–1d)
- [ ] 复核 §3 全部 file:line 与 §2 取用条款行号(D1 v1.1 条款行、F1–F8 落点),漂移即订正本卡。可核查结果:订正记录或「零漂移」声明进实现报告素材。
- [ ] 与卡② T0 对齐四件:产图签名(去 level_index 的 `generate(params, seed)`)、图数据形状(id/type/depth/next 字段名)、参数档 schema 字段名、复现语义(纯函数/counter 无关两条硬语义确认);与卡③ 对齐 `depth`=遭遇坐标深度轴+多终点深度互异。可核查结果:对齐纪要(定稿签名对照 §7 接口块,漂移处回写邻卡接口块或记「一致」)。
- [ ] 定稿 RNG 纯流面机制(§10 ① 域内):`pure_stream(seed_val, scope)` 具体签名与 scope 分域策略(约束=纯函数/counter 无关/同图/禁自建 RNG)。可核查结果:机制定稿进实现报告(签名+scope 取值)。
- [ ] 定稿「支路」度量口径(§10 ② 域内):岔口各出边支路的分解(自出边起至再汇合/终点止的节点子图)与类型构成度量(集合 vs 多重集)。可核查结果:度量口径定稿进实现报告。
- [ ] 改前读数基线采集(冒烟/单测通过数,两入口铁规下随 T1 迭代 loop 首跑取值)。可核查结果:基线读数记录在案。
- [ ] §6 反哺点①–⑥ 条目起草(一节一改一依据)。可核查结果:反哺点草稿段落在 T4 产物成文前就绪。
### T1 参数档数据表(schema+.tres+ConfigDB 注册)(≈1–1.5d)
- [ ] 实装 `game/data/schemas/level_gen_params.gd`:类 `LevelGenParams`(extends Resource),`rows: Array[Dictionary]`(键=level_index),`validate() -> Array`(域校验:五旋钮在域、配比四类合计 1、出口 L1=1/L2L3∈[1,3]、层深 L1≥6、岔口去路数 2/3、战斗保底≥0),`row_by_level_index(level_index: int) -> Dictionary` 单点读。可核查结果:schema 编译通过、validate 对合法行零错误对越域行报错。
- [ ] 实装 `game/data/tables/level_gen_params.tres`:L1/L2/L3 三行五旋钮 provisional 值(取值照 §8.1 表逐行填)。可核查结果:表加载零诊断、三行值与 §8.1 provisional 表对上、validate 全绿。
- [ ] 实装 `game/core/config_db.gd` 注册:`_tables` 映射加 `"level_gen_params": "level_gen_params.tres"`(对齐 :20 体例)、成员 `var level_gen_params`、装载(对齐 :142)、访问器 `level_gen_params_row(level_index: int) -> Dictionary`(对齐 :245 体例,缺行返回 `{}`)。可核查结果:ConfigDB 装载该表、访问器按 level_index 读回正确行、缺行返回空字典。
- [ ] manifest 登记:`game/tests/run_all.gd` `_suites()` 追加 `{"path": "res://tests/unit/data_config/level_gen_params_test.gd", "expect": 0}`(对齐既有行体例;批 B 协议——禁「文件在 manifest 不在」空窗)。可核查结果:run_all 实跑套件数 +1 且新套件 PASS。
- [ ] 验收步骤:跑 `godot --headless --path game --script res://tests/unit/data_config/level_gen_params_test.gd`,期望 schema validate+值域断言全绿。
- [ ] 变异验证(注入→最窄闸见红→`git checkout` 还原→记录):把 L1 出口改 2(应=1)→ 期望值域断言红;把配比四类改合计 0.5 → 期望合计 1 断言红。记录表进实现报告。
### T2 生成器核心(产合法图+产出自证+RNG 纯流面确定性)(≈2.5–3.5d)
- [ ] 实装 `game/core/rng_service.gd` 纯流面 `pure_stream(seed_val: int, scope: int) -> RandomNumberGenerator`:seed 键值纯派生(复用 `_mix64`/`derive_at` 派生模型)、返回 RNG、**不推 `_counter`、不落事件日志**;类头纪律注释补「纯流面=结构生成专用(生成器),counter 无关、同 (seed,scope) 同流」。可核查结果:同 (seed_val, scope) 两次 `pure_stream` 返回同序列;`counter()` 前后不变;不同 seed 序列不同。
- [ ] 实装 `game/core/node_map_generator.gd`:类 `NodeMapGenerator`(extends RefCounted,Core 零 UI、RngService 经构造注入〔`--script` 禁裸 autoload,code-conventions:71〕);`generate(params: Dictionary, seed: int) -> Dictionary` 产出 `{nodes, entries, terminals}`(节点字段 id/type/depth/next)。**长图算法(HOW)归实现**(D1:28),只钉产出必须满足 §4 契约 3 全部产出约束+结构铁律+摆放约束三条+契约 2 深度赋值。取数只经 `pure_stream`(契约 1)。可核查结果:对 L1/L2/L3 参数档各以固定种子产图,图非空、字段齐备。
- [ ] 实装产出侧自证 `validate_output(graph: Dictionary) -> Array`(生成器内、产前强制):过产出约束五条+结构铁律+摆放约束三条(道路系统/宽度/层高/归属锁定/战斗保底/无环/多入口多终点/每路径恰一入一出/商店位/岔路取舍两条/多终点深度互异)。可核查结果:合法产出自证零错误;构造违规夹具图(环/断头/孤儿/双终点同深/缺店/岔口同类型下一跳)各报对应错误类别(沿 `structural`/`dangling_next`/`dup_key`/`enum`/`domain` 词表)。
- [ ] 实装确定性:`generate` 同 (seed, params) 两次逐位同图(深比较 nodes/entries/terminals);counter 无关(不同 `_counter` 初值下同 (seed,params) 同图)。可核查结果:`node_map_generator_test` 可复现断言绿。
- [ ] manifest 登记:`game/tests/run_all.gd` `_suites()` 追加 `{"path": "res://tests/unit/core/node_map_generator_test.gd", "expect": 0}`(对齐既有行体例)。可核查结果:run_all 实跑套件数 +1 且新套件 PASS。
- [ ] 验收步骤:跑 `godot --headless --path game --script res://tests/unit/core/node_map_generator_test.gd`,期望产出合格+可复现断言全绿。
- [ ] 变异验证:生成器取数改 `open_stream`(推计数器)→ 期望 counter 无关断言红;把 depth 赋值改「最短路径」→ 期望「出边目标 depth>源」无环判据对某合流图误判/多终点深度互异断言红;产出自证注释「终点恒 Boss」判据 → 期望非 Boss 终点夹具红。记录表进实现报告。
### T3 验收断言批总装(生长递增/专项/参数无解 fail-fast)+变异验证(≈2–2.5d)
- [ ] 实装 `game/tests/unit/core/node_map_generator_test.gd` 专项断言:① 含岔口与出口结构(三关参数档生成图各含 ≥1 岔口节点〔出度≥2,第一关即含、非单链取值〕;L1 出口恒 1、大岔口〔多终点归属锁定〕自 L2 起——L2/L3 exit>1 时图含分区域大岔口);② 岔路取舍·下一跳(任意岔口各去路下一节点类型互不相同);③ 岔路取舍·支路构成(任意岔口各支路类型构成互不相同、每支路至少一个独有类型);④ 必经恰一店(任意入口→终点路径恰过一家店);⑤ 归属锁定(多出口图每终点前一层去路集合恰含一个终点、各区域互不连达);⑥ 多终点深度互异(L2/L3 多终点 depth 两两不同);⑦ 战斗保底(战斗节点数 ≥ battle_floor)。可核查结果:七类断言对 L1/L2/L3 参数档×固定种子扫描面全绿。
- [ ] 实装 `game/tests/unit/core/node_map_growth_test.gd` 生长递增断言:同子下 L1/L2/L3 生成图的最长路径步数与节点总数均逐关递增,且节点总数增幅 Δ(L2→L3)>Δ(L1→L2)。可核查结果:三档读数表断言绿。
- [ ] 实装参数无解 fail-fast 断言:构造无解参数档(如 layers=1 且 branch_density 强制零岔口而出口要求分区域、或必经店无法满足)→ 期望 `generate` 致命中止(push_error+assert/既有 fatal,返回前不产出残图),无兜底图回退。可核查结果:无解参数夹具触发致命、断言「无残图返回、无兜底图路径」。
- [ ] 变异验证(新增/改写断言逐条注入实验,记录表进实现报告):终点前驱改非店 → 期望「必经恰一店」红;把两终点设同 depth → 期望多终点深度互异红;把岔口两去路设同类型 → 期望岔路取舍·下一跳红;把战斗节点砍到低于 battle_floor → 期望战斗保底红;生长断言把 L2/L3 参数调成节点数增幅倒挂 → 期望生长递增红;把 `generate` 无解路径改「返回空图」→ 期望 fail-fast 断言红。逐条执行「注入→最窄闸见红→`git checkout` 精确还原→记录」。
- [ ] manifest 登记:`game/tests/run_all.gd` `_suites()` 追加 `{"path": "res://tests/unit/core/node_map_growth_test.gd", "expect": 0}`(对齐既有行体例)。可核查结果:run_all 实跑套件数 +1 且新套件 PASS。
- [ ] 验收步骤:T 段出口跑一次全套闸(`tools/run_all_gates.sh` 按改动域选档,本批碰 `game/` 代码与数据表+测试 → 代码域档),期望生成器/参数档断言全绿、探针段无红。
- [ ] 件核:全仓 `generate` 调用点不传 level_index(契约 6);生成器内零 `randomize()`/零自建 RandomNumberGenerator/零 `open_stream`(契约 1,`pure_stream` 除外)。
### T4 产出物落位卡(≈0.5d,末卡——三份 `reports/` 文件写齐才算收口)
- [ ] 轻闸全绿后、合并前写齐三份:`reports/iter<N>-实现报告-<完成日>.md`(各卡状态+变异验证记录表+实机目检总清单+遗留读数义务)/`reports/iter<N>-代拍板追认单-<完成日>.md`(§10 白名单内代拍项留痕:纯流面 scope 分域、支路度量口径、图内部持有结构等)/`reports/iter<N>-反哺点-<完成日>.md`(§6 六条每条一落点:①生成规格补多终点深度互异+深度赋值句、②地图深度赋值消歧、③覆盖核对登记、④呈现面随动登记、⑤06 状态回写、⑥roadmap 编入笔)。可核查结果:三文件在 `reports/` 且 §6 同步面每条有落点。
**估时合计 ≈6.5–9d**(T0 0.5–1+T1 1–1.5+T2 2.5–3.5+T3 2–2.5+T4 0.5)。切分预案:T1 可单独一轮(数据层、不碰生成器);T2 为生成器主体(可再切「图数据结构+基本长图」/「约束自证+确定性」两小段,若一轮超 3.5d);T3 依赖 T2 产出(断言驱动生成器);超软盒(>9d)预挂:T2 若约束自证超一孔,先落产出约束五条+结构铁律+确定性主链,摆放约束三条+专项断言次轮补,全绿才收口。
## 8. 验证闸(逐需求点验收清单)
| # | 需求点 | 测什么(断言/行为) | 落点/判定手段 |
|---|---|---|---|
| V1 | 产出合格(产出约束五条+结构铁律) | 任意参数档产出图过:道路系统(除岔口外每节点恰一条去路、岔口去路 2–3)/宽度分叉生长(宽度源于岔口、不摆平行层)/层高(L1≥6)/出口归属锁定/战斗保底;结构铁律(无环、多入口多终点且入口数/终点数=params.entry_count/exit_count、每路径恰一入一出);入口=无入边节点、终点=type=boss 且无出边 | 单测 `node_map_generator_test.gd`(产出自证零错误+入口/终点计数断言+违规夹具各报对应错) |
| V2 | 参数档 schema+.tres | 五旋钮在域、配比合计 1、出口 L1=1/L2L3∈[1,3]、层深 L1≥6、岔口 2/3、战斗保底≥0;L1/L2/L3 三行 provisional 值与 §8.1 对上;ConfigDB 单点读回正确 | 单测 `level_gen_params_test.gd`(validate+值域+访问器读回) |
| V3 | 可复现(纯函数+counter 无关) | 同(seed, params)两次产图逐位同图;不同 `_counter` 初值同图;同 params 不同 seed 不同图 | 单测 `node_map_generator_test.gd`(深比较+counter 无关) |
| V4 | 执行边界(无兜底图/fail-fast) | 参数无解 → 致命中止(push_error/assert),无残图返回、无兜底图/软回退路径;不合格产出不进玩法(自证不过不上图) | 单测(无解参数夹具触发致命)+件核(生成器零回退分支) |
| V5 | 岔路取舍两条 | 任意岔口各去路下一节点类型互不相同;各支路节点类型构成互不相同、每支路至少一个独有类型 | 单测 `node_map_generator_test.gd`(岔口扫描) |
| V6 | 必经恰一店+归属锁定+多终点深度互异 | 任意入口→终点路径恰过一家店;多出口图每终点前一层去路集合恰含一个终点、各区域互不连达;多终点 depth 两两不同 | 单测 `node_map_generator_test.gd`(DFS 路径枚举+区域可达+depth 比对) |
| V7 | 战斗保底 | 任意合法产出战斗节点数 ≥ battle_floor | 单测 `node_map_generator_test.gd`(计数断言) |
| V8 | 生长递增 | L1/L2/L3 最长路径步数与节点总数逐关递增;Δ(L2→L3)>Δ(L1→L2) | 单测 `node_map_growth_test.gd`(三档读数对拍) |
| V9 | 含岔口与出口结构(第一关即含岔口/L1 出口恒 1/大岔口自 L2 起) | 三关参数档生成图各含 ≥1 岔口节点(出度 ≥2,第一关即含、非单链退化取值);L1 生成图终点恰 1(无多终点归属大岔口);L2/L3 exit>1 时含分区域大岔口(归属锁定) | 单测 `node_map_generator_test.gd`(岔口存在性+出口计数+区域结构) |
| V10 | RNG 单点(纯流面) | 生成器取数只经 `pure_stream`;`counter()` 前后不变;零 `randomize()`/零自建 RNG/零 `open_stream` | 件核+单测(counter 不变断言)+静态扫描 |
| V11 | 反哺点清单 | §6 六条每条有落点 | 件核对表(T4) |
### 8.1 参数档 provisional 取值表(provisional 占位,定值批落终值;数值全 provisional)
> 域校验(V2)对全部行强制:配比四类合计=1;出口 L1 恒 1、L2/L3∈[1,3];层深 L1≥6 且逐关递增增幅变大;岔口去路数恒 (2,3);战斗保底≥0。取值须使 V8 生长递增成立(L1/L2/L3 最长路径步数与节点总数递增、Δ(L2→L3)>Δ(L1→L2));provisional 可在域内微调(§10 ④),禁改已锁域(层深下限、出口 L1=1、岔口 2/3、商店数=出口数)。配比 `shop_ratio` 为名义值——商店实数由摆放约束①钉死=出口数(每终点前一店),生成器以「摆放优先、配比填余、战斗保底兜底」次序兑现。
| 参数(schema 键) | L1 | L2 | L3 | 域/状态 |
|---|---|---|---|---|
| `layers`(层深=最长路径步数) | 6 | 9 | 13 | ≥6,逐关递增增幅变大(L1 下限已锁,L2/L3 provisional) |
| `branch_density`(分支密度) | 0.30 | 0.50 | 0.70 | [0,1],provisional;逐关递增(决策点密度递增);L1 取值须保证第一关即含 ≥1 岔口 |
| `battle_ratio`/`reward_ratio`/`rest_ratio`/`shop_ratio`(配比) | .50/.20/.20/.10 | .50/.20/.15/.15 | .55/.15/.15/.15 | 四类合计 1,战斗保底优先;provisional |
| `entry_count`(入口个数) | 1 | 2 | 2 | ≥1,provisional |
| `exit_count`(出口个数) | 1 | 2 | 3 | L1 恒 1(已锁);L2/L3∈[1,3](已锁范围),provisional |
| `battle_floor`(战斗保底数) | 4 | 6 | 8 | ≥0,provisional |
| `fork_ways_min`/`fork_ways_max`(岔口去路数) | 2/3 | 2/3 | 2/3 | 恒 2/3(已锁) |
**测试方式两分法(2026-10-11 用户定)**:V1–V11 全部机检自动化(单测为主);能力验证可经调试接口直改参数档/种子驱动生成图(沿用现役 DebugOverlay/DS_DEBUG 门控,不走正常资源积累流程)。**用户目检项**:「三关生成图选路观感(多入口/大岔口取舍/多终点走向可见、第一关即有选择)」+「生成图规模随关卡推进变大(生长递增可感知)」两条——观测项写进 `reports/iter<N>-实现报告-<完成日>.md` 实机目检总清单,登记不阻塞(验收时间用户自行安排;呈现依赖卡②/卡④ 落地后目检)。
**闸口径**:轻闸每任务卡出口自跑;批末重闸=`tools/run_all_gates.sh` 按改动域选档(本批碰 `game/` 代码与数据表+测试 → 代码域档)全绿才合并+改前改后读数对拍。回归措辞:里程碑步(T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套。
**变异验证伴生**(新增/改写验收函数逐条注入实验,记录表进实现报告):L1 出口改 2(V2 红)/配比合计 0.5(V2 红)/取数改 `open_stream` 推计数器(V3 counter 无关红)/depth 赋值改最短路径(V3/V6 多终点深度互异或无环红)/产出自证注「终点恒 Boss」(V1 红)/终点前驱改非店(V6 红)/两终点同 depth(V6 红)/岔口两去路同类型(V5 红)/战斗砍低于 battle_floor(V7 红)/生长倒挂(V8 红)/无解路径改返回空图(V4 红)/生成路径强制无岔口(V2/fv9 岔口存在性红)/L1 参数出口置 2 产出侧(fv9 出口计数红)。变异不红则改判据或如实标注拦截边界。
### 8.2 改动—验收对照表(2026-10-21 验收闭合批新规,test-conventions §9.3)
> 各新增断言 desc 统一尾缀〔fv#〕(本表「验收测试」列可 grep 定位);撤销/变异证明逐条对应 §8 变异验证伴生与 T1–T3 变异步、T4 件核(每张任务卡至少一条,test-conventions §9.4)——T0 为事实对齐卡(无行为改动),其事实核对红证并入 fv2(参数档 schema 事实面)与 fv10(RngService 现用法事实面)。层级列只填 §9.2 四层词(单元/接口/集成/探针);件核是证明方式不是层级,留在「撤销或变异证明」格。纯产出物行按 §9.1 标「非行为改动」。
| 需求点 | 改动(文件:行/行为) | 验收测试(名称+文件:行+尾缀) | 层级 | 真实入口 | 撤销或变异证明 |
|---|---|---|---|---|---|
| fv1 产出合格(产出约束五条+结构铁律) | `game/core/node_map_generator.gd`(新建)`validate_output()` 产出侧自证:道路系统/宽度/层高/归属锁定/战斗保底+结构铁律(无环/多入口多终点/每路径恰一入一出) | `node_map_generator_test` 产出合格+违规夹具〔fv1〕 `game/tests/unit/core/node_map_generator_test.gd` | 单元 | `NodeMapGenerator.validate_output(graph)`+`generate(params, seed)` 产前强制 | 变异:产出自证注「终点恒 Boss」→ 非 Boss 终点夹具红(T2) |
| fv2 参数档 schema+.tres | `game/data/schemas/level_gen_params.gd`(新建)`validate()`/`row_by_level_index()`;`game/data/tables/level_gen_params.tres`(新建)三行;`game/core/config_db.gd` 注册+访问器 `level_gen_params_row()`(对齐 :20/:142/:245 体例) | `level_gen_params_test` validate+值域+读回〔fv2〕 `game/tests/unit/data_config/level_gen_params_test.gd` | 单元 | `LevelGenParams.validate()`/`ConfigDB.level_gen_params_row()` 直调 | 变异:L1 出口改 2/配比合计 0.5 → 值域、合计 1 断言红(T1) |
| fv3 可复现(纯函数+counter 无关) | `node_map_generator.gd` 同(seed, params)逐位同图+counter 无关;`game/core/rng_service.gd` `pure_stream()` 不推 `_counter` | `node_map_generator_test` 可复现(深比较+counter 无关)〔fv3〕 `game/tests/unit/core/node_map_generator_test.gd` | 单元 | `generate(params, seed)` 同种子两次直调 | 变异:取数改 `open_stream` 推计数器 → counter 无关断言红(T2) |
| fv4 执行边界(无兜底图/fail-fast) | `node_map_generator.gd` 参数无解致命中止(push_error/assert),无残图、无兜底回退分支 | `node_map_growth_test` 参数无解 fail-fast〔fv4〕 `game/tests/unit/core/node_map_growth_test.gd`+件核(生成器零回退分支) | 单元 | 无解参数档调 `generate(params, seed)`(期望 fatal) | 变异:无解路径改「返回空图」→ fail-fast 断言红(T3) |
| fv5 岔路取舍两条 | `node_map_generator.gd` `validate_output()` 岔路取舍判据(下一跳类型互异/支路构成互异) | `node_map_generator_test` 岔路取舍两条〔fv5〕 `game/tests/unit/core/node_map_generator_test.gd` | 单元 | `validate_output()` 岔口扫描直调 | 变异:岔口两去路设同类型 → 下一跳断言红(T3) |
| fv6 必经恰一店+归属锁定+多终点深度互异 | `node_map_generator.gd` 商店位/归属锁定/多终点 depth 互异判据(契约 2/5) | `node_map_generator_test` 必经恰一店+归属锁定+多终点深度互异〔fv6〕 `game/tests/unit/core/node_map_generator_test.gd` | 单元 | `validate_output()`+DFS 路径枚举/区域可达/depth 比对 | 变异:终点前驱改非店→必经恰一店红、两终点同 depth→深度互异红(T3);depth 赋值改最短路径→互异或无环红(T2) |
| fv7 战斗保底 | `node_map_generator.gd` 战斗保底判据(battle_floor) | `node_map_generator_test` 战斗保底〔fv7〕 `game/tests/unit/core/node_map_generator_test.gd` | 单元 | 产图战斗节点计数断言 | 变异:战斗节点砍低于 battle_floor → 战斗保底红(T3) |
| fv8 生长递增 | 三档参数档产图读数(`level_gen_params.tres` provisional 域内取值) | `node_map_growth_test` 生长递增三档读数〔fv8〕 `game/tests/unit/core/node_map_growth_test.gd` | 单元 | L1/L2/L3 `generate` 读数对拍 | 变异:L2/L3 参数节点数增幅倒挂 → 生长递增红(T3) |
| fv9 含岔口与出口结构(第一关即含岔口/L1 出口恒 1/大岔口自 L2 起) | `node_map_generator.gd` 道路系统/出口归属产出(契约 3) | `node_map_generator_test` 岔口存在性+出口计数+区域结构〔fv9〕 `game/tests/unit/core/node_map_generator_test.gd` | 单元 | 产图结构扫描(三关参数档×固定种子) | 变异:生成路径强制无岔口(分支密度 0)→ 岔口存在性断言红;L1 参数出口置 2 → 出口计数断言红(T1/T3 变异步,与 fv2 出口值域注入同发) |
| fv10 RNG 单点(纯流面) | `game/core/rng_service.gd`(改)新增 `pure_stream(seed_val, scope)` 纯流面(不推 `_counter`、不落日志),生成器取数唯一源 | `node_map_generator_test` counter 不变断言〔fv10〕 `game/tests/unit/core/node_map_generator_test.gd`+件核/静态扫描(零 `randomize()`/零自建 RNG/零 `open_stream`) | 单元 | `RngService.pure_stream()` 直调+`counter()` 前后读数 | 变异:取数改 `open_stream` 推计数器 → counter 不变断言红(T2,与 fv3 同发注入) |
| fv11 反哺点清单(**非行为改动**——纯文档产出物,无游戏行为,§9.1) | §6 六条反哺点落 `reports/iter<N>-反哺点-<完成日>.md`(T4) | 件核对表〔fv11〕(§6 六条每条一落点)`reports/iter<N>-反哺点-<完成日>.md` | 非行为改动 | T4 产出物件核(六条落点逐条核对) | 撤销:反哺点缺条 → 件核对表不收口(T4,纯文档产物无代码变异) |
**旧断言预声明(test-conventions §9.5)**:本卡零旧断言改写——断言面全新建(node_map_generator/growth/level_gen_params 三套新测试),`rng_service.pure_stream()` 为新增纯函数、不触既有断言。实现期确需改旧断言=上游缺陷,停卡呈报;未声明的削弱由独立审计判红。
**独立验收审计(test-conventions §9.7,2026-10-21 起)**:合并前由未参与实现的迭代 loop 内子代理(或用户点名会话)审计——只读本卡、实现报告实际对照表、diff 与测试文件,自跑最窄测试抽查,不采信「已全绿」;审计报告落 `reports/iter<N>-验收审计-<完成日>.md`(逐行「通过/缺漏/例外及依据」)。**审计未通过不得合并**(T4 合并前置)。
## 9. 异常分级
- **L1(自救)**:断言措辞、命名、注释、错误类别命名沿用;参数档字段注释与 provisional 标注。
- **L2(记录继续)**:RNG 纯流面机制细节(`pure_stream` 签名形态、scope 分域策略);「支路」度量口径(分解边界、集合 vs 多重集);生成图在生成器内的持有结构;长图算法具体步骤(D1:28 归实现);参数档 .tres 行键/字段名细节(§10 域内)。
- **L3(停机呈报)**:纯流面机制与「随机只经 RngService 统一流」红线不可调和(若「统一流」被裁定仅指 counter 流、纯流面不算——须用户改契约 1);执行中发现同 depth 多终点图样(推论条款 A 被破,契约 2);任何触碰「生成器只吃参数档不认关卡号」「纯函数复现」「无兜底图/fail-fast」的诉求;生成图深度域超出敌/板表覆盖且数据批无人接手(§0 交付序列失管);产出约束/结构铁律/摆放约束被判据要求放宽(违 D1:41-51)。
## 10. 代拍板白名单(超清单必呈报)
1. RNG 纯流面机制细节(`pure_stream(seed_val, scope)` 具体签名、`scope` 分域策略=单流多次取数 vs 逐决策 scope、派生式复用 `_mix64`/`derive_at` 的哪种)——约束:纯函数、counter 无关(不推 `_counter`)、同(seed, params)同图、随机只经 RngService、禁自建 RNG/`randomize()`/`open_stream`(契约 1)。
2. 「支路」度量口径(岔口各出边支路分解=自出边起至再汇合/终点止;类型构成度量=集合或多重集)——约束:满足「各支路构成互不相同、每支路至少一个独有类型」设计意图(D1:84),可被 V5 断言核查。
3. 生成图在生成器内的持有结构、节点句柄载体(int id 的赋值序)、`generate` 返回字典的内部组装——约束:读面字段名 id/type/depth/next 不变(§7 接口块)、句柄唯一、depth=自入口最长路径步数。
4. 参数档 .tres 行键/字段名内部细节(键=level_index 的行式 vs 其它)、provisional 取值微调(保持 §8 域与生长递增成立)——约束:五旋钮齐全、域校验过、生成器只读不改值、数值全 provisional(定值批落终值)。
5. 长图算法具体步骤(怎么从旋钮长出一张合法图)——约束:产出必过 §4 契约 3 全部+确定性(D1:28「图怎么长出来是实现的事」)。
6. 提交切分与 worktree 分支命名。
## 11. 待裁点
**零待裁点,开工门=U0。**
五处灰色地带已按「设计权威文档+硬纪律+跨卡派发」推导定值(用户可否决,随 T4 反哺点清单呈报可见):
- **RNG/复现机制(契约 1,卡② defer 给本卡)**:备选「`open_stream` 统一流取数」——淘汰依据=`open_stream` 推全局计数器(`rng_service.gd:86-99`),产图随号位漂移,与「同种子+同参数档=同图」(D1:60)+「断点停点号位重生成同图」(D3:264 存档复现)冲突(resume 在停点号位、非产图号位);备选「自建 RandomNumberGenerator」——淘汰依据=AGENTS.md:73「禁自建 RandomNumberGenerator」红线;**定值=RngService 纯流面** `pure_stream(seed, scope)`(seed 键值、纯函数、不推 counter),生成器取数唯一源。依据=D1:60+D3:264+AGENTS.md:73 合取,counter 无关是「存档复现重生成」的必然要求;**「统一流」口径加固**:RngService 本就含纯派生面 `derive_at(scope)`(`rng_service.gd:34-37`,不推计数器)+号位取号面 `open_stream` 双面,纯流面即 `derive_at` 的流化(同服务内既有分工、非另起第二套流),故「随机只经 RngService 统一流」=经 RngService 服务取数成立(自建 RNG 才是红线违例)。**唯一残余风险**:若用户裁定「统一流」严格专指 counter 取号流、纯流面不算,则契约 1 须改(L3 呈报口,§9 已列)——本卡按「RngService 服务内既有纯派生/取号双面」定值。
- **节点深度赋值(契约 2,卡② grilling 注记「depth 赋值一致性归卡①」)**:备选「最短路径(BFS 距离)」——淘汰依据=合流/多入口下出边目标 depth 可 ≤ 源(如目标经更短入口可达),「出边目标 depth 严格大于源」无环判据(卡② 契约 1④)失效;**定值=自入口最长路径步数**(多入口取距任一入口最长)。依据=D1:47「层高=沿路步数(最长路径)」+D2:65「节点深度=自入口步数」+无环判据有效性(最长路径使每边 target>source)三者合取。
- **多终点深度互异(契约 2,卡③ 契约 6 推论条款 A 派发本卡兑现)**:备选「同 depth 多终点」——淘汰依据=「定位信息只有两样(关,深)」(D2:119)下同 depth 多终点不可区分,「多终点各配 Boss 行、走哪条路决定打谁」(D1:96)落空;**定值=多终点落在互异 depth**(图侧,本卡产出约束)。依据=D2:119+D1:96+卡③ 契约 6 合取;(深度带互异的带切法归卡③ 契约 5,本卡不读敌表)。
- **「支路」度量口径(摆放约束③)**:备选「全子图类型多重集」——淘汰依据=合流支路共享尾段使多重集趋同、判据过弱;**定值=岔口各出边支路=自出边起至再汇合/终点止的节点子图,类型构成按该互斥段度量**(集合或多重集落 §10 ②)。依据=D1:84「各支路构成互不相同、每支路至少一个独有类型」的设计意图(每条路通向不同的东西)+可核查性。
- **generate 签名去 level_index(契约 6,对卡② 期望签名的裁剪)**:备选「保留 `generate(level_index, params, seed)`」——淘汰依据=D1:72「生成器只吃参数档、不认关卡号」明文,收 level_index 即违反;**定值=`generate(params: seed)`(去 level_index 形参),调用方 level_index→params 解析后调用**。依据=D1:72 直读;卡② 契约 7「签名以卡①定稿为准」授权本卡裁剪,卡② T0 对齐接线。
---
**自审五查记录(2026-10-21)**:① 规格覆盖——§1 四件本体/八项完成定义逐条挂 T 卡(参数档=T1、生成器产出合格+确定性=T2、专项+生长+fail-fast+变异=T3、反哺点=T4;确定性横跨 T2 纯流面+V3 断言),无漏项;② 步骤扫描——全部步骤一步一动作一可核查结果,实现体只给签名+判据名(`generate`/`pure_stream`/`validate_output` 签名、产出约束判据清单、七类专项断言名),长图算法(HOW)明写归实现(D1:28)不抄写、无占位符、无推诿措辞、无本批未定义的类型/函数名;③ 类型一致性——§7 接口块签名与 T 卡/邻卡引用逐字一致(`generate(params: Dictionary, seed: int) -> Dictionary`、返回 `{nodes,entries,terminals}`、节点 `{id,type,depth,next}`、`pure_stream(seed_val: int, scope: int) -> RandomNumberGenerator`、`level_gen_params_row(level_index: int) -> Dictionary`、字段名 layers/branch_density/battle_ratio/reward_ratio/rest_ratio/shop_ratio/entry_count/exit_count/battle_floor/fork_ways_min/fork_ways_max);④ 审查焦点——补挂失败模式:产图失败回退残图(V4 变异)、复现漂移(V3 变异)、多终点同深错兑付(V6 变异)、岔口同类型下一跳(V5 变异)、必经店漏店(V6 变异)、战斗被挤没(V7 变异)、生长倒挂(V8 变异)、取数推计数器(V3 counter 无关变异);⑤ 篇幅比例——规格约 2 屏、任务卡步骤与实现面 1:1,函数体零展开(长图算法不抄写),产出规格/执行边界照录 D1 不增删。
**v1.1 修订自审(2026-10-24,宿主重锚批——六查复核)**:动笔面=§3 行号重锚(F2 探测块 :156-159→:149-158 等、F3 校验体随 level_table.gd 现态、F4 enc 组装 :467-482→:513-525、F7 validate :17-31→:13-27)+§6 断言面行 smoke_all→tests 三宿主+run_all manifest 行+T1/T2/T3 各补 manifest 登记步(阻断 4 闭合)+归属句卡③④ 状态换代(已落地·迭代 34)。①规格覆盖——设计面零变动(§1/§2/§4/§8 未触),新增 manifest 步各挂 T1/T2/T3 与 fv2/fv1-fv3/fv4-fv8 宿主执行面;②步骤扫描——三步均一步一动作+可核查结果(实跑套件数 +1);③类型一致性——签名与邻卡引用零变动;④改动覆盖——本修订纯指认面订正+测试基建登记步,零游戏行为改动,无新增对照表行义务;⑤篇幅比例——零函数体;⑥落位复用——manifest 登记沿批 B 既有行体例(`{"path":…, "expect": 0}`)、断言宿主沿批 B 16 宿主体制,无新增件无重复落点。重锚依据=`reports/批B-断言迁移账本-2026-10-22.md`+2026-10-24 master 实查(16c6f136 后现态)。
**grilling 复核记录(2026-10-21,设计树对抗复核,不采访用户——可推导定值写依据、真归用户列 §11)**:按设计树走查八支——① RNG/复现(三案淘汰两案定纯流面,§11 留统一流口径否决口);② 深度赋值(最长路径 vs 最短路径,最短路径破无环判据→定最长路径);③ 多终点深度互异(卡③ 推论条款 A 派发→定互异 depth,深度带归卡③);④ generate 签名(D1:72「不认关卡号」→去 level_index,卡② 授权裁剪);⑤ 支路度量(互斥段口径保设计意图+可核查);⑥ 产出约束五条 vs 结构铁律 vs 摆放约束的分工(五条=合法图定义、铁律=无环/多入多出/每路径恰一入一出、摆放=商店位/岔路取舍——三者产出自证全兜,卡② 加载校验是独立防御不重叠);⑦ 大岔口自 L2 起(D1:70「大岔口自第二关起、第一关出口恒 1」→L1 出口恒 1、多终点归属锁定 L2+,与「第一关即含岔口〔普通选择岔口〕」不矛盾——普通岔口 L1 有、归属大岔口 L1 无);⑧ 覆盖依赖(生成深度域 vs 敌/板表覆盖=真实跨卡缺口,卡③ §5 已登记归口后续表批——本卡写死交付序列依赖 §0,不扩敌数值)。code-conventions 对照:§2.2「位置/句柄/键语义单一」= 契约 2(id/depth 拆分)的规范依据(node_depth 双语义是现役违规态);§71 `--script` 禁裸 autoload=生成器 RngService 注入依据;§4.11 新单测不经 autoload 无冲突。AGENTS.md 硬红线逐条过:数值单点(参数档 .tres 经 ConfigDB、生成器零数值字面量定值)、RNG 单点(纯流面出自 RngService、禁自建 RNG/randomize——「统一流」口径留 §11 否决口)、测试两入口(T 卡只写断言不跑测)、实现批禁写 design/(§6 义务全走反哺点、零旧口径的同步措辞)、fail-fast(参数无解致命无兜底图)、数值全 provisional(定值批落终值)。**本轮对抗复核实改两处**:① 入口/终点数=参数档(D1:51「个数=参数档」)此前无验收断言兜住(入口/出口两旋钮兑现缺口)→ 补进 V1 结构铁律;② 纯流面「统一流」口径加固(援引 RngService 已有纯派生面 `derive_at`〔rng_service.gd:34〕,纯流面=其流化非第二套流,「只经 RngService 统一流」成立)。结论:零待裁点,五处灰色推导已定值并留 §11 供用户否决。
+3 -3
View File
@@ -5,8 +5,8 @@
## 当前位(只回答「现在该做什么」;三行内随批次换代,禁止在此扩写成状态快照)
- **阶段**:M3——Alpha 版本的完整实现(2026-10-09 立规:未明令宣布完成前停留 M3,迭代只排 M3 需求,M4 不排期;根目录 stage.txt 为旧阶段开关仅存档)。
- **迭代位**:迭代 1–34 全部已完成——迭代 34 两卡于 2026-10-22 合回、2026-10-24 完成批后收尾;迭代 35 卡① 已合回、卡② 停机待覆盖批;迭代 36 三卡已合回;迭代 37 起未编排——编入哪一迭代由用户经迭代编排段发令。
- **下一步**:迭代 35「生成图深度扩面覆盖批」立卡后重编卡②;迭代 36 补记迭代总表行(现仍写「待开工」,与实际不符);迭代 37 编排由用户发令(迭代编排段入口)。待编池:营地交互重做卡⑤(排卡④之后)、卡④(已退回美术设计段,美术设计闭合后重立卡)、冒险前资源配比预设(冻结备选)、迭代 30 原卡②③(2026-10-17 已剔出迭代 30 规划、退回待设计,待美术/设计定稿后重新立卡)、玩家面残留禁字清扫(待写卡)、结算明细日志行序重锚(2026-10-21 授权发起、时点另定)。
- **迭代位**:迭代 1–35 全部已完成——迭代 34 于 2026-10-24 完成批后收尾;迭代 35 两卡于 2026-10-25 合回并完成批后收尾;迭代 36 三卡已合回;迭代 37 起未编排——编入哪一迭代由用户经迭代编排段发令。
- **下一步**:迭代 36 补记迭代总表行(现仍写「待开工」,与实际不符);迭代 37 编排由用户发令(迭代编排段入口)。待编池:营地交互重做卡⑤(排卡④之后)、卡④(已退回美术设计段,美术设计闭合后重立卡)、冒险前资源配比预设(冻结备选)、迭代 30 原卡②③(2026-10-17 已剔出迭代 30 规划、退回待设计,待美术/设计定稿后重新立卡)、玩家面残留禁字清扫(待写卡)、结算明细日志行序重锚(2026-10-21 授权发起、时点另定)。
## 里程碑时间线
@@ -68,7 +68,7 @@
| 迭代 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 | 已完成(2026-10-22) | 已退役(git 历史可考) | 2026-10-21 | ≈11 个工作日〔用户特批 2026-10-21 超 10 个工作日〕 | 已退役(git 历史可考) |
| 迭代 35 | 待开工 | reports/需求卡片-节点图生成器核心批-2026-10-21.md<br>reports/需求卡片-节点图消费侧换代批-2026-10-21.md | 2026-10-21 | ≈15.25 个工作日〔用户特批 2026-10-21 超 10 个工作日〕 | — |
| 迭代 35 | 已完成(2026-10-25) | 已退役(git 历史可考) | 2026-10-21 | ≈15.25 个工作日〔用户特批 2026-10-21 超 10 个工作日〕 | 已退役(git 历史可考) |
| 迭代 36 | 待开工 | reports/需求卡片-开场后缀营地灰字迷雾测点批-2026-10-24.md<br>reports/需求卡片-文案与禁字清扫批-2026-10-24.md<br>reports/需求卡片-状态面板瘦身批-2026-10-23.md | 2026-10-24 | ≈5.25 个工作日 | — |
- 历史行的「—」= 该列事实不可考:迭代 1~8 早于需求卡片制;编排时点与预计周期不再回溯,细节查 git 提交史。
+15
View File
@@ -363,3 +363,18 @@
| 4 | 大图完整可见观感(卡④) | 大图(11 层×6 槽)整幅落在画布内,无节点被裁切或挤在一角 |
- **红灯信号**:改动前后遭遇敌人数量/外观不一致;雾下房间读作漏画或类型文字漏出;双 Boss 只有一侧带描边;大图有节点出界。
- **结论回流**:实现缺陷归待办清单登记新条目;观感问题归关卡节点图呈现面后续批。
---
## ㉝ 迭代 35——生成图换代实机目检(2026-10-25 随收尾写入登记)
> 两卡把图的来源从模板池换成「参数档×种子」生成图:卡① 落生成器与产出规格,卡② 切消费侧并清出 15 张模板。机检已覆盖生成图确定性、深度带覆盖、商店三性质、断点代差拒绝等;选路观感、首局教学图与画幅观感仍要人眼看。登记不阻塞(2026-10-12 真人检测立规);总收口时点=迭代 35 实现报告(已退役,git 可考)。
| # | 目检项 | 判据 |
|---|---|---|
| 1 | 三关选路观感不回归(卡②) | 第二/三关开局即出现两个可选入口且都能进入;岔口候选互异且分属不同支路;走 A 支只遇 A 支终点 Boss;每个终点前恰一家店 |
| 2 | 首局教学图体验(卡②,种子 42 固定图) | 新档开局(`is_first_adventure_done==false`)每次都是同一张图;入口战→岔口→商店→Boss 的顺序可读,含至少一个奖励位与一个恢复位 |
| 3 | 三关生成图选路观感(卡①) | 图规模与分支形态逐关变大;岔口有实际取舍,不是「只有一条路能走」 |
| 4 | 大图完整可见观感(卡①+画布缺口) | L2/L3 生成图整幅落在 1280 屏内、节点不被裁切且都可点到——已知冻结画布公式在 L3 深度域 0–13 下可能超宽,本项同时验证该缺口是否已在实机显形 |
- **红灯信号**:第二/三关只有一个入口或第二入口不可进入;岔口候选同类型或同支路;走 A 支遇到 B 支 Boss;教学图每次开局不同;节点出屏或点不到;三关图规模不递增。
- **结论回流**:实现缺陷归待办清单登记新条目;观感与画幅问题归呈现批(待办清单「超预算图策略升级路径」条)。
+26 -26
View File
@@ -4,8 +4,8 @@
#### 超预算图策略升级路径——等比缩放与滚动视口两案待裁(2026-10-24 登记,来源=批次移交,设计面=文档轨)
**现状**:迭代 34 卡④(信息迷雾可见性批,已合回 master,提交 16a7ec80)按「参数限图」交付,图包络约 10 层×8 槽即当前冻结画布的屏预算上限。若后续定值批需要更大的完整可见图,两条升级路径都要动冻结件,均未设计:①等比缩放——动「节点图标 20px 烘焙 1:1」与「通道折线冻结 2/3/4px」两条冻结值;②滚动视口——新增视口交互范式。
- 相关文档 design/gdd/systems/冒险循环/关卡节点图生成.md v1.2(调参表「图包络」行)
**现状**:迭代 34 卡④(信息迷雾可见性批,已合回 master,提交 16a7ec80)按「参数限图」交付,图包络约 10 层×8 槽即当前冻结画布的屏预算上限。若后续定值批需要更大的完整可见图,两条升级路径都要动冻结件,均未设计:①等比缩放——动「节点图标 20px 烘焙 1:1」与「通道折线冻结 2/3/4px」两条冻结值;②滚动视口——新增视口交互范式。迭代 35 生成图实测深度域 L3 达 0–13,已超出该上限(level-map 已登记随动缺口,本批不裁方案)。
- 相关文档 design/gdd/systems/冒险循环/关卡节点图生成.md v1.3(调参表「图包络」行)
- 相关文档 design/gdd/ux/level-map.md(画布冻结公式)
**缺口**:两案需用户裁决后再走设计讨论;未裁前禁改画布冻结件。
@@ -47,6 +47,30 @@
**状态**:待写卡
#### 验证集清单快照重生成——断言索引含退役措辞与旧行号(2026-10-25 登记,来源=审计发现,设计面=工程直入)
**现状**:工程债证据=迭代 35 卡② 验收审计申报(git 历史可考:合回提交 5499eb9c 内的 reports/iter35-卡②-验收审计-2026-10-24.md,该产出物已按吸收即死退役):game/tests/验证集清单.md 是批 B 迁移时的断言文本快照索引,只由 tools/extract_checks.py 手工重生成、不进任何闸;卡② 断言面换代后十余行仍含 first_script/template_pick 等退役措辞与过期行号(实测 first_script 8 处、template_pick 2 处),与宿主现文不符。
**归属**:game/tests/验证集清单.md+tools/extract_checks.py(重生成或清单头注记两路,写卡时定)
**状态**:待写卡
#### 测试宿主改名——node_map_templates_test.gd 已承载生成图确定性断言(2026-10-25 登记,来源=审计发现,设计面=工程直入)
**现状**:工程债证据=迭代 35 卡② 反哺点⑧:game/tests/integration/node_map_templates_test.gd 现承载「生成图确定性断言套」,文件名中的 templates 是模板时代遗留;manifest 登记行=game/tests/run_all.gd:90。改名为 node_map_determinism_test.gd 须同批改 manifest 路径行。
**归属**:game/tests/integration/+game/tests/run_all.gd manifest
**状态**:待写卡
#### level.tres 表尾注释含迭代叙事(2026-10-25 登记,来源=审计发现,设计面=工程直入)
**现状**:工程债证据=迭代 35 卡② 反哺点⑨:game/data/tables/level.tres 表尾注释写「旧 15 张模板池(3 关 × 5)随迭代 35 卡② 清出」,与 doc-conventions §5 禁写变更叙事有张力;卡② 卡片 T3 明令表尾写模板去向注记,故处置面限于叙事形态(删迭代号、保留图源换代事实句),不删去向事实。
**归属**:game/data/tables/level.tres
**状态**:待写卡
#### 架构与规范对齐批——代码结构审查发现的文档-实现漂移(2026-10-24 登记,来源=审计发现,设计面=文档轨)
**现状**:审计报告=reports/审计-game代码结构审查-2026-10-24.md(§二 C3/C4/C5+§三 漂移清单)。漂移与待裁件七件:①架构文档「模块归属」多行 API 清单与实现不符(A2 try_* 便捷形/B2 ambush_grant_plan/B4 equivalence_supply 不存在;实有 grant_reserve_ap/finish_round_stop/check_skill_unlocks 未登记;damage_controller 与 settlement/ 五段类零条目——S7 落地的前置);②code-conventions §1.3 核心写调用位置——三拆件控制器(presentation/curio_interact_controller.gd、camp_shop_presenter.gd、treasure_interact_controller.gd)持写调用 vs 规范「只允许在组合根出现」的 spec-AC 冲突,须裁「改规范成文组合根家族」vs「调用收回 main」;③A3→EffectEngine 反向依赖(core/action_economy.gd:43-49)——真违约或事实源失真二选一(effect_engine 降层登记基础层 vs B1 代发 vs 仅补登记);④架构文档 :149/151 层合同计数写死 17 项 vs LAYER_CONTRACT 实 18 项;⑤明细行协议三处三个数(头注 9/实发 13/架构文档 15);⑥§1.3 例举 submit_window_selection 符号已退役;⑦core/effect_engine.gd:360 校验文案「9 项」实为 18 项。
@@ -165,30 +189,6 @@
**状态**:待文档设计(备选)
#### 关卡节点图重构——可选节点太少(2026-10-13 登记,来源=playnote,设计面=文档轨)
**现状**:来源=playnote 用户试玩记录「关卡节点图展示得有问题,希望可以优化一下。可以参考哥布林弹珠的那种方式去移动」。2026-10-13 用户明确定性:**这是当前关卡节点图的重构,不是呈现优化**——理由是**现在的可选节点太少**(用户原话),所以不是换一种画法或移动方式就能解决的事。
关联文档清单:
- 设计定稿 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)
**现行实态**(`level.tres` 实查,三关各 5 张模板):**第一关五张模板全是单链排列变体**——7 个节点=战斗 ×4 + 奖励 + 休整 + Boss,战斗深度序单调保难度坡,**变化面只有奖励与休整两位的先后次序**,全链零分叉,玩家在选路上**没有任何选择**;第二/三关是网状图(10 节点,带 `next` 分支,最大层宽 4–5),有分叉,但用户仍判选择量不足。参考方向=Peglin(哥布林弹珠)的节点图移动与选路方式。
**范围(重构面,非呈现面)**:节点数量、分叉度、选路自由度。连带三面——① 关卡节点图生成(旧版文档已删、随重构重写;现行 15 张骨架=3 关 ×5 已判过期,随重构清理);② [level-map](design/gdd/ux/level-map.md)(选路枢纽三停点布局定稿版,图结构改则屏面随之改);③ [敌人系统](design/gdd/systems/战斗循环/敌人系统.md)(遭遇表按 `enemy.tres` 的 (level_index, node_depth) 坐标索引,节点数与编号一改,行集坐标与首遇教学位断言面全部随动)。
**量化要求补登(2026-10-16 playnote 用户补写)**:「需要统计一下第 123 关 path 的路径长度,路径长度需要递增,并且后续关卡的节点数增幅应该更大」(第 123 关=第 1/2/3 关)——已定稿成验收形态:读数=最长路径步数与节点总数(口径见[关卡节点图生成](design/gdd/systems/冒险循环/关卡节点图生成.md)验收标准),两者逐关递增、节点总数增幅 Δ(L2→L3)>Δ(L1→L2);基线采集发起权归用户,读对象=生成图(旧模板已裁不作参考)。
**前置(用户 2026-10-13 裁)**:**须先做文档设计讨论,不可直接开发**——参考调研+重构方案先行、过人闸后才可开卡。版本标准侧已登记为 Alpha 待做项,见 [08-Alpha版本标准](design/gdd/08-Alpha版本标准.md)「一 · 系统 · 冒险循环」。
**缺口(2026-10-24 迭代 35 开工检查登记)**:迭代 35 停机退回——卡①② 已于同日 v1.1 修订重锚断言宿主(game/smoke/ 退役后现态,卡① 可独立成批开工);卡② 阻塞于「生成图深度扩面覆盖批」未立卡——生成图深度域(L1 0–6/L2 0–9/L3 0–13,卡① §8.1 provisional)未被敌带与板键覆盖(敌侧战斗带顶 L1=3/L2=L3=7、Boss 各关单带 4/9/9;板侧 board_gen `node_depth` 精确行同域缺口),且 L2/L3 多终点 Boss 各终点深度需解析带键可互异;切源即 `band_of` 越顶 -1 加载致命。立卡要件(归口=卡③ §5):敌侧每 (关, row_kind) 顶带键 ≥ 该关最大生成深度+Boss 带键可互异;板侧 board_gen 键域覆盖生成深度全域;数值 provisional。覆盖批落地前卡② 不得切源合入(卡② §0 硬交付序列),落地后重编迭代交付卡①②。
**归属**:[关卡节点地图](design/gdd/systems/冒险循环/关卡节点地图.md)(图结构与节点语义,主责)+ [关卡节点图生成](design/gdd/systems/冒险循环/关卡节点图生成.md)(产出规格与生成参数)+ [level-map](design/gdd/ux/level-map.md)(选路呈现)+ [敌人系统](design/gdd/systems/战斗循环/敌人系统.md)(遭遇行集坐标连带);版本标准侧已登记为 Alpha 待做项,见 [08-Alpha版本标准](design/gdd/08-Alpha版本标准.md)「一 · 系统 · 冒险循环」
**状态**:文档设计已闭合+已写卡+已编迭代 34+已编迭代 35
#### 扩展节点类型——危险/精英节点与特殊地形节点(2026-10-21 登记,来源=会话提及,设计面=文档轨)
**现状**:用户 2026-10-21 会话定方向:Alpha 版只留现行四类(战斗/奖励/恢复/商店),以下两类留到以后再做——①危险/精英节点(怪物与普通战斗不同、奖励肥);②特殊地形节点(效果修饰:地图战斗资源、敌我伤害、金币比例等)。内容未设计。