test(迭代35卡①): 合流图夹具改按契约 2 语义重写(合法合流=第二入口直插主链取长路值+声明深度虚高必拒)——使深度赋值判据可被变异拦下;代拍板追认单落 reports/

This commit is contained in:
DKChan committed 2026-10-24 06:00:50 +08:00
1 parent 16c776e9f3
commit a391512e98
2 files changed
+43 -8

No files matched your search

@@ -340,15 +340,26 @@ func _test_negative_fixtures() -> void:
{"id": 1, "type": "battle", "depth": 1, "next": []}])
Kit.check("非 Boss 终点夹具命中「终点(无出边)非 Boss」判据〔fv1〕",
_has_msg(_gen.validate_output(noBoss), "终点(无出边)非 Boss"))
# 合流图深度赋值语义(契约 2):跳边让某节点的最长路径值高于其声明值 → 必须被拒
var conf_short := _fx([
{"id": 0, "type": "battle", "depth": 0, "next": [1, 3]},
# 合流图深度赋值语义(契约 2「自入口最长路径步数」):
# (a) 合法合流——第二入口直插主链中段,该节点深度必须取长路值而非短路值
var conf_legal := _fx([
{"id": 0, "type": "battle", "depth": 0, "next": [1]},
{"id": 1, "type": "battle", "depth": 1, "next": [2]},
{"id": 2, "type": "reward", "depth": 2, "next": [3]},
{"id": 3, "type": "shop", "depth": 1, "next": [4]},
{"id": 4, "type": "boss", "depth": 4, "next": []}])
Kit.check("合流图深度写 shortest(=1)被拒(须最长路径步数)〔fv1〕",
_has_msg(_gen.validate_output(conf_short), "自入口最长路径步数"))
{"id": 2, "type": "battle", "depth": 2, "next": [3]},
{"id": 3, "type": "shop", "depth": 3, "next": [4]},
{"id": 4, "type": "boss", "depth": 4, "next": []},
{"id": 5, "type": "battle", "depth": 0, "next": [3]}])
Kit.check("合法合流图(第二入口直插主链,深度取最长路 3)自证零错误〔fv1〕",
_gen.validate_output(conf_legal).is_empty())
# (b) 声明深度高于真实最长路值 → 必被拒(前进方向不破,专测深度判据)
var conf_high := _fx([
{"id": 0, "type": "battle", "depth": 0, "next": [1]},
{"id": 1, "type": "battle", "depth": 1, "next": [2]},
{"id": 2, "type": "battle", "depth": 2, "next": [3]},
{"id": 3, "type": "shop", "depth": 4, "next": [4]},
{"id": 4, "type": "boss", "depth": 5, "next": []}])
Kit.check("声明深度高于最长路径步数被拒(深度=自入口最长路径步数)〔fv1〕",
_has_msg(_gen.validate_output(conf_high), "自入口最长路径步数"))
# 环/回边:深度不前进
var loop := _fx([
{"id": 0, "type": "battle", "depth": 0, "next": [1]},
@@ -0,0 +1,24 @@
# 迭代 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×层高), 可用锚点数)——L2 实测 3 岔口、L3 实测 2 岔口生效(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)`——只构型、不自证不致命,供断言逐条读产出规格违例(卡片 §8「测试方式两分法」授权经调试接口直改参数档/种子驱动生成图)。生产路径仍只走 `generate`。
## 遗留读数义务(实现报告同步在册)
- 用户目检两条未做(登记不阻塞):三关生成图选路观感、生成规模随关卡变大可感知——呈现依赖卡②/卡④ 落地。
- MC/对拍零跑:本批无数值改动、未涉核心结算,按红线不发起跑批。