Merge branch 'master' into reqcards-20261024

This commit is contained in:
DKChan committed 2026-10-25 01:11:45 +08:00
commit 6835f96df0
39 files changed
+2209 -935

No files matched your search

@@ -0,0 +1,29 @@
# 迭代 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 回放确定性对拍按前批裁决不补跑。
@@ -0,0 +1,25 @@
# 迭代 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 已把它列为用户目检项,登记不阻塞) |
@@ -0,0 +1,172 @@
# 迭代 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 条目「覆盖批未立卡」缺口段现况已过期(覆盖数据已随本批落地),状态回写归文档批。
@@ -0,0 +1,117 @@
# 迭代 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 定位、断言真实存在,不影响验收。