合并(精英专属池批·登记+文档设计+写卡): 待办拆条(个体化变体池→同种分型 Beta/精英专属池新登 Alpha)+新登「战斗节点遭遇编排方式」+敌人系统 v1.9 精英行节(独立行/elite 行类/池继承基础池+附加技/合并池过纪律/暂不接线)+难度曲线与Boss v1.6 指路+需求卡片 v1.1 成立(只读子代理复核 21 条全处置, 零待裁)+能力清单增精英行能力+待办状态 文档设计已闭合+已写卡; 工程顺带: pipeline_gate 行锚正则放行中文路径(用户 2026-11-06 裁); 另登待办「卡片复核报告文件口径: 闸件与技能不一致」。分支内凭据: pipeline_gate PASS, run_all_gates --docs 对已提交 master 零新增红; 合回前置检查钩子读数见本提交落地态; post-merge 钩子推送触发远端 CI
ci / gates (push) Failing after 4m49s

This commit is contained in:
DKChan committed 2026-11-06 23:21:54 +08:00
commit 9e81408efc
7 files changed
+406 -10

No files matched your search

@@ -1,7 +1,7 @@
# 难度曲线与Boss
> 一句话:难度曲线、期望值带与 Boss 设计
> 状态:已定稿;现行为 v1.5
> 状态:已定稿;现行为 v1.6
## 设计目的
@@ -55,7 +55,7 @@
|---|---|---|
| 关间台阶(关卡序号) | 每关至少投放一项新内容(新敌种或既有池新技能),加基准数值跳升 | 台阶必须能归因到看得见的变化,不是纯数字膨胀;投放断档是内容生产缺口,调参修补不了 |
| 关内坡度(节点深度) | 同敌种数值平缓上移,深度也可表达为敌人成群 | 数量是比单体质变更优先的深度表达:保持技能池 EV 读数不变(权重即旋钮、EV 重锚顺带登记)、总量受控 |
| Boss 与精英修饰(预留第三轴) | Boss 走最深深度直填行;精英只有字段命名空间预留 | Boss 不走修饰表;修饰乘数表 MVP 为空表、零行为,首个使用场景 = 精英节点(随[关卡节点地图](关卡节点地图.md)定稿联动);数值所有权在本系统,[棋盘生成](../排雷循环/棋盘生成.md)只按表生成。精英怪设定已登记预留(与其他普通小怪同一立绘 + 附加特征标记 + 数值更强;视觉特征三件 = 名称前后缀「精英·」+ 底座光环 + 描边变色,色板合规与样张闸义务随怪物设定批实装) |
| Boss 与精英修饰(预留第三轴) | Boss 走最深深度直填行;精英怪本体走敌人表精英行(独立行+池继承附加,语义见[敌人系统](../战斗循环/敌人系统.md)「精英行」节),精英节点修饰只有字段命名空间预留 | Boss 不走修饰表;修饰乘数表 MVP 为空表、零行为,首个使用场景 = 精英节点(随[关卡节点地图](关卡节点地图.md)定稿联动);数值所有权在本系统(含精英行数值与附加技权重),[棋盘生成](../排雷循环/棋盘生成.md)只按表生成。精英怪设定:与其他普通小怪同一立绘 + 附加特征标记 + 数值更强;视觉特征三件 = 名称前缀「精英·」(由精英行名字行值承载)+ 底座光环 + 描边变色,后两件的色板合规与样张闸义务随怪物设定批实装 |
**结论**:关内坡度 = 每深一档同敌种基准上移,或按"深度也可表达为敌人成群"改由数量承载——单体生命随深度的具体走向以 `enemy.tres` 行值为准(数量优先于单体;s_hp 线性式为建模工具,现行行值不承诺随深度单调上移);关间台阶 = 相邻关同敌种基准乘 1.3–1.6(域语义如上;s_hp / k_L 现行行值读 `enemy.tres`,取值域归敌人表字段定义)。
@@ -1,7 +1,7 @@
# 敌人系统
> 一句话:敌人数据、技能池出招、意图呈现
> 状态:已定稿;现行为 v1.8
> 状态:已定稿;现行为 v1.9
## 设计目的
@@ -138,6 +138,20 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错
举证:**摇定结果 = 可摇集合按权重份额归一的一次抽签;当前可摇集合 = 实例池排除冷却中与触发条件不满足的技能(保底命中时 = 条件满足的全部特殊技)。**连带可判别:把权重当固定百分比、把冷却当只锁高伤技、把蓄力当重击前奏,都是与本规约相悖的旧口径。
### 精英行:现役敌种的强化版,池=继承基础池+附加技
精英怪是某个现役敌种的强化版本:玩家看到的是同一种怪(同立绘、名字带「精英·」前缀),数值更强、出招多几样。它在敌人表里是独立的一行——自己的 enemy_id、自己的数值、自己的专属池,和基础敌种的行互不覆盖;外显与内部定义因此可以是一对多(一个外观对应基础行与精英行两份定义)。精英身份由行类承载:敌人表行类新增 elite 值。
| 规则 | 含义 |
|---|---|
| 独立行 | 精英=敌人表行类为 elite 的一行,enemy_id 独立、不与基础敌种同名;名字前缀「精英·」由该行名字行值承载。数值字段(生命、攻击、护甲两轴、数量)与战斗行同一套定义与取值域 |
| 基础敌种引用 | 精英行用基础敌种引用字段指向一个基础敌种的 enemy_id;被指敌种必须在同关战斗行类里存在,指向不存在的敌种或另一条精英行,加载期拒绝 |
| 专属池=继承+附加 | 精英行不写自己的池模板,只写附加技清单({skill_id, weight} 数组);它的池模板=基础池+附加技合并。基础池取自同关、战斗行类、该基础敌种深度带最小的那一行的池模板——继承不复制:基础池调参自动传到精英。附加技的 skill_id 与基础池重复,加载期拒绝 |
| 合并池过同一纪律 | 池构成纪律(恰一普攻、增益 ≤1、妨害 ≤1、至少一行无条件特殊技、悬空引用致命、权重域)校验的对象是合并后的池;开战快照、实例池、冷却、保底、触发条件语义全部不变——精英实例拿到的就是合并后池的快照 |
| 暂不接线 | 精英行落表即合法;开战寻址只按节点类型取战斗或 Boss 行集,精英行在接线前不会被任何节点读到,静置合法、不返回错误。精英遭遇怎么投放到节点,归待办清单「战斗节点遭遇编排方式」条目 |
举证:**精英池模板 = 基础池条目 ∪ 附加技条目(两者 skill_id 不相交)**;中签率公式不变,可摇权重合计含附加技权重——加附加技会摊薄基础池各技能的中签率,EV 重锚归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)。各精英行的数值与附加技行值读敌人表(`enemy.tres`),本文不登记。
### 触发条件:情境技与闩型解锁共用一套门槛
技能行可以带一个触发条件:条件不满足的拍,这行技能不进可摇集合——与冷却中的排除同一待遇;条件满足时,按正常权重照摇。它服务两类出招:情境技(自身低血才用的防御、上轮玩家停手才会出的偷袭等)让怪物像在"看情况出招",停手与压血因此有了代价;闩型解锁(半血解锁)让大招只在血量跌破阈值后才可被摇出。两类用例、一套机制——条件只管"现在能不能被摇到",不改权重、不强制出手。
@@ -236,7 +250,8 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错
| 优先级 | 内容 | 后置原因 |
|---|---|---|
| P1 | 情境条件触发器(低血触发防御、玩家停手时偷袭技等) | 已实装(三 Boss 闩型+两示范投放,见「触发条件」节与「首批落地」段) |
| P1 | 个体化变体池(A 型好斗 / B 型守势、精英专属池) | 共识点 A 的 A2 案;登记[待办清单](../../../../待办清单.md) |
| P1 | 个体化变体池(同种个体分型:A 型好斗 / B 型守势) | 共识点 A 的 A2 案;排期 Beta,登记[待办清单](../../../../待办清单.md) |
| P1 | 精英遭遇接线、精英底座光环与描边变色、精英钥石掉落 | 精英行已落表静置(见「精英行」节);接线归[待办清单](../../../../待办清单.md)「战斗节点遭遇编排方式」条目,视觉二件随怪物设定批,钥石随接线批 |
| P1 | 全局特殊间隔旋钮 | 特殊技背靠背实测仍嫌时的备用闸;登记[待办清单](../../../../待办清单.md) |
| P1 | 新效应词汇(妨害技 + 必中附加分量已实装——实装面 = L2 Boss 卓尔;多段命中经用户拍板退役) | 妨害类型 + rider_mult 字段已落地;登记[待办清单](../../../../待办清单.md)(已解决移除,去向见状态记录) |
| P1 | 敌种扩容与投放节奏(含第二关池与投放) | 投放节奏是关卡命脉,归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
@@ -253,7 +268,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错
| 参数 | 取值域 | 说明 |
|---|---|---|
| level_index(关卡序号) | int ≥ 1 | 行集坐标第一维:第几关;每关必有战斗类、深度带 0 的一行(锚行)与至少一行 Boss 类行——加载校验强制;关间台阶的坐标轴,行值投值归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
| row_kind | {battle, boss} | 行类:battle = 战斗节点配池(非 Boss 的战斗节点一律取此类),boss = 终点行集——Boss 战按终点配置,多终点各配一行(走哪条路决定打谁);开战按节点类型取对应类的行集 |
| row_kind | {battle, boss, elite} | 行类:battle = 战斗节点配池(非 Boss 的战斗节点一律取此类),boss = 终点行集——Boss 战按终点配置,多终点各配一行(走哪条路决定打谁);elite = 精英行(见核心规则「精英行」节,接线前不被任何节点读到);开战按节点类型取对应类的行集 |
| depth_band | int ≥ 0 | 深度带 = 节点深度所在的区间(定义见核心规则「行集构成纪律」):配池按带不按点,难度坡随带递增;节点深度落在带与带之间时取首个 ≥ 深度的带键(偏难一侧);越顶带加载校验判为调参事故;带键投放归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
| unit_count | [1, 3] | 遭遇数量区间下界;有上界的行开战时在区间内掷定,教学位节点同样掷骰 |
| unit_count_max | [unit_count, 3],可省略 | 数量区间上界;开战时在区间内掷定本战实际数量;缺省 = 定值 |
@@ -263,7 +278,9 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错
| armor_class(护甲等级) | int [0, 999],缺省 0 | 防守方护甲等级——基础攻击掷点的折扣判定读数,掷点结算归[战斗结算](战斗结算.md);与 armor_type(克制属性轴)两概念禁止混用;行值投值归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md) |
| hp | [1, 999] | 单位生命基线(难度修饰前) |
| atk | [0, 999] | 攻击基线 |
| pool(池模板) | {skill_id, weight} 数组,weight ∈ (0, 9999] | 技能行引用在技能表;池构成纪律与悬空引用加载期拒绝(校验在数据配置跨表通道) |
| pool(池模板) | {skill_id, weight} 数组,weight ∈ (0, 9999] | battle / boss 行必填、elite 行禁填;技能行引用在技能表;池构成纪律与悬空引用加载期拒绝(校验在数据配置跨表通道) |
| base_ref(基础敌种引用) | enemy_id 字符串 | 仅 elite 行、必填(其余行类禁填);须指向同关 battle 行类存在的敌种,悬空或指向 elite 行加载期拒绝 |
| pool_extra(附加技清单) | {skill_id, weight} 数组,weight ∈ (0, 9999],非空 | 仅 elite 行、必填(其余行类禁填);skill_id 与基础池不相交;合并后池过池构成纪律 |
技能表(全局单表,技能行主键 skill_id):
@@ -305,6 +322,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错
- 表校验:越域值、池权重 ≤ 0、空池、普攻配倍率/冷却、池增益 > 1、skill_id 悬空、行集构成违例(行集内同敌种第二行 / 同带键多行不相邻)均在加载期返回错误并止动;域内合法极端(攻击基线 0)不拒;主角表恰一行、攻击配 0 拒绝。
- 零随机回放:同一动作与受击序列驱动两个独立实例,存活投影、逐实例摇定轨迹、顺位返回序列逐项相同。
- 表实一致:敌人表、主角表、技能表三张配置表的字段与各自字段定义逐字段一致。
- 精英行:elite 行的池模板 = 基础池(同关、战斗行类、基础敌种深度带最小行)+附加技清单,开战快照拿到合并后池;基础池改表后精英合并池随之改变;elite 行落表时任何战斗节点与 Boss 节点开战都不读到它;elite 行缺基础敌种引用或附加技清单、基础敌种引用悬空或指向 elite 行、精英 enemy_id 与基础敌种引用同名、附加技与基础池 skill_id 重复、合并池违反池构成纪律、elite 行写自己的池模板、非 elite 行写基础敌种引用或附加技清单——均在加载期返回错误并止动。
## 待办
+2 -1
View File
@@ -191,6 +191,7 @@ tests/
| 状态实例按个体归属:个体隔离/全体授予逐体发/死亡即清/同体合并照旧 | 增益状态 | `StatusContainer.apply_effect()`(个体键)/`purge_owner()` | `system_contracts_test.gd:_test_status_individual_isolation`;`system_contracts_test.gd:_test_status_grant_all_per_unit`;`system_contracts_test.gd:_test_status_death_clears`;`system_contracts_test.gd:_test_status_merge_per_unit` |
| 敌方增益自体落点与乘区池按个体 | 敌人系统×战斗结算×增益状态 | 技能兑付编排链/`DamageController.clamped_pool()` | `round_flow_skill_pool_test.gd:_smoke_enemy_buff_targets_self`;`damage_controller_test.gd:_test_pool_consumption_per_unit`;`damage_controller_test.gd:_test_defender_ac_per_unit`;`battle_narrator_test.gd:_test_snapshot_effects_per_unit` |
| 敌人技能池跨表链接校验 | 数据配置×敌人系统 | `ConfigDbCrossValidator.validate_skill_pool_links()` | `config_db_cross_validator_test.gd:_test_all_links_valid`;`config_db_cross_validator_test.gd:_test_dangling_skill_id`;`config_db_cross_validator_test.gd:_test_cast_side_mismatch` |
| 精英行:池继承合并、加载期校验与暂不接线 | 敌人系统×数据配置 | `ConfigDB.load_tables()`/`EnemyTable.validate()`/`EnemyTable.effective_pool()`/`ConfigDbCrossValidator.validate_skill_pool_links()`/`EnemyTable.resolve_rowset()` | `elite_row_test.gd:_test_elite_validation_rejects`;`elite_row_test.gd:_test_effective_pool_merge`;`elite_row_test.gd:_test_base_pool_change_propagates`;`elite_row_test.gd:_test_merged_pool_composition`;`elite_row_test.gd:_test_elite_unreachable_by_encounter`;`elite_row_test.gd:_test_production_goblin_elite` |
**覆盖域表**(`design/gdd/systems/` 逐篇对照——状态三档:已覆盖/部分覆盖/未覆盖;部分与未覆盖行的缺口指待办清单条目,覆盖面提升时同批改本表):
@@ -205,7 +206,7 @@ tests/
| 战斗循环 | 增益状态.md | 系统间契约词表与受理口径:五配方互异/掷点标签成员性/增益布尔受理;同名状态合并策略(叠加/累加/并存)与剩余次数语义;状态效果结算链(逐值衰减/到期移除/战斗结束全清/满层拒绝/独立并存/首授快照);状态实例按个体归属:个体隔离/全体授予逐体发/死亡即清/同体合并照旧;敌方增益自体落点与乘区池按个体;封印与极性路由/不可逆 | 部分覆盖 | 结算链剩余缺口由「断言补齐批」承接;见待办清单「能力清单覆盖缺口补齐」条 |
| 战斗循环 | 战斗结算.md | 伤害公式与掷点乘区;伤害单据编排与回放;轮内流与结算五段全序 | 已覆盖 | — |
| 战斗循环 | 战斗表现.md | 站桩敌人呈现与结算演出落点;站桩呈现定值与素材绑定;站桩显示档与素材分辨率绑定 | 已覆盖 | 死亡灰化与减动效演出档以探针+人工目检为终态(2026-11-02 用户裁除名,不再补自动断言) |
| 战斗循环 | 敌人系统.md | 技能池数据面与回放独立;Boss 半血解锁技门控;敌人技能池跨表链接校验 | 已覆盖 | — |
| 战斗循环 | 敌人系统.md | 技能池数据面与回放独立;Boss 半血解锁技门控;敌人技能池跨表链接校验;精英行:池继承合并、加载期校验与暂不接线 | 部分覆盖 | 精英行「开战快照拿到合并后池」随接线批验收;见待办清单「战斗节点遭遇编排方式」条 |
| 排雷循环 | 地形变异.md | 变异布置门控;表结构守卫:域校验/行序键/跨字段互锁/配额锚 | 已覆盖 | — |
| 排雷循环 | 排雷玩法.md | 装板与开局免费展开(封锁格无资源、计入清图);挖/封印合法性与可辨拒绝(拒绝零副作用);封印不可逆与挖开封印格放行(兑付改判四情况) | 已覆盖 | — |
| 排雷循环 | 棋盘生成.md | 棋盘按参数行出图、数字恒真;同参数同种子逐位复现、异种子不退化;可推理率与清图可达(合法性先于质量分)、重试有界、降级诚实 | 已覆盖 | — |
@@ -0,0 +1,37 @@
# 复核报告 · 精英专属池需求卡片(2026-11-06)
> 接收方:`reports/需求卡片-精英专属池-2026-11-06.md` 第 16 节「复核记录」(本报告留发现原文与依据索引;四类去向与处置以卡内第 16 节为准)
> 被复核对象:该卡 v1.0 成文态
> 复核者:未参与撰写的只读子代理(独立会话,禁写文件、禁跑闸、禁运行测试),任务=对卡内每一处行号、契约、判据与任务步逐条开火
> 复核轮次:1
> 复核对象工作副本:`D:/code/g-plan2-elite-pool`(分支 elite-pool)
## 复核者总判原文(摘录)
> 这张卡不能按现在的样子开工。①生产表行数断言漏网(`level_shop_economy_test.gd:732`「表回 29 行」必红,不在 §3.4 也不在削弱申报);②暂不接线的验收(V5)没有区分力——改动前后都绿;③gdstyle 预算算不通,卡里给的备用拆法也会撞线;④夹具和类别规定前后不一;⑤行号多处整体偏移(§3.1–§3.3 基本准确,错的集中在 §3.4 和 T 步骤)。全仓其余读 pool、遍历敌人行、读 row_kind 的地方均已查过,除上述外无别的会坏或漏写处。
## 发现与依据索引(21 条)
| # | 卡内位置 | 发现 | 依据 |
|---|---|---|---|
| 1 | §3.4/§8 R7/削弱申报/T3.5 | 漏一处必红的存量断言 | `game/tests/unit/core/level_shop_economy_test.gd:732` `int(_db.combat.enemy.rows.size()) == 29`;函数 `_smoke_level_graph`(:444 起);`run_all_gates.sh:224-226` `--code` 跑全部套件 |
| 2 | §3.4、T1.10、T3.3、T3.4、申报 | 行号整体偏移 | round_flow `row.pool` 实在 :530/:541/:560/:619/:627/:640/:655,`expect_pools` :579-611;guard `expect_keys` :219-230、断言 :235-236、`l1_totals` :387-394(循环首 :388)、曲线 :395-407;config_db_test 样本 :261、文案 :268;resolver_test :111-112;compendium_dump :18、:95-97;battle_orchestrator :591/:594 |
| 3 | §8 R5/T2.4 | V5 无区分力;「唯一取行门」不准 | `config_db_resolver.gd:84`、`:95-96` 按 row_kind 精确过滤;`:41` 行类门;`battle_orchestrator.gd:299` 亦调 resolve_rowset;`config_db.gd:57-62` 生产 push_diag 走 push_error(test-conventions §5.6) |
| 4 | §13/T1.4 | `_validate_elite_fields` 分支预算算不通 | `enemy_table.gd:138-158`(条目循环 :144-157);阈值出处 `reports/审计-gdstyle存量债清点与清偿方案-2026-10-26.md` 第 22 行 |
| 5 | §13/T1.5 | `_validate_elite_refs` 预算 ≤5 写不出 | 直写形态约 8–9 分支;§11 白名单未覆盖新增产品码私有函数 |
| 6 | §13 | 漏局部变量预算 | `enemy_table.gd:37-63` validate() 局部变量 10 个=阈 10 |
| 7 | §8 R1/T1.6 | 「恰命中」与「含」矛盾;夹具①连带报 dangling_base | T1.5 字面 |
| 8 | T1.6 | 夹具缺字段,合法夹具会报错 | `enemy_table.gd:89-112`、`:141`;`config_db_cross_validator_test.gd:55-57`;正例 `config_db_test.gd:212-214` |
| 9 | T1.7/T1.8 | 取最浅带断言区分不了「取首行」实现 | 夹具顺序未定;`t.rows[0]` 指代 |
| 10 | §8 反向覆盖 | T1.4 若干分支无断言 | test-conventions.md:100;敌人系统.md:325 |
| 11 | §8/§5 | 「开战快照拿到合并后池」半句无交代 | 敌人系统.md:325、:150;`unit_container.gd:141` |
| 12 | T1.9/T1.10 | 步骤顺序反 | — |
| 13 | T1.5、T1.6、T3.1 | 一步多动作 | req-card「步骤粒度」 |
| 14 | T1.6 | 登记位置不合分组 | `run_all.gd:251` 属 core 段;data_config 段 :170-195 |
| 15 | T1.7、T1.8、T2.3、T2.4、T3.2 | 判据出处注记写法不完整 | test-conventions.md:105 |
| 16 | T1.2/T1.3 | Godot 与静态扫描坑:点号读行类、非字典条目、裸 Dictionary 注解 | `round_flow_skill_pool_test.gd:880-916` 夹具无 row_kind;`config_db.gd:117-120`;`tools/audit_type_hints.py:22`;`enemy_table.gd:148` |
| 17 | T1.1 | 注释会过时 | `enemy_table.gd:11`;`level_table.gd:11` |
| 18 | T4.1/T4.2 | 图鉴工具两处未跟上 | `compendium_dump.gd:6-7`;`compendium_gen.py:43-49`、`:120-125` |
| 19 | §16 | 缺五格轮次表;称新规禁另设报告文件 | `.zcode/skills/req-card/SKILL.md:64` |
| 20 | 设计 :147 vs :325 | 「精英 enemy_id 不与基础敌种同名」无校验(复核者标待裁,建议甲=加校验) | 敌人系统.md:147;`enemy_table.gd:81` 去重键含 row_kind |
| 21 | 观察 | T2.3 夹具与 side 守卫一致;fv5 仍成立;全仓无测试断言 ROW_KINDS 内容;`l1_totals` 不跳过也不红(band 0 12→32,下一档 10/32);`enemy.tres` 插行不致 `static_scan.sh:194/:218/:221` 新误判 | `config_db_cross_validator.gd:179-180`;`static_scan.sh` |
@@ -0,0 +1,309 @@
# 需求卡片 · 精英专属池(2026-11-06)
> **来源**:待办清单条目「精英专属池」(2026-11-06 登记,来源=会话提及;状态=文档设计已闭合+待写卡)
> **唯一事实源**:`design/gdd/systems/战斗循环/敌人系统.md` v1.9 §精英行(第 141–153 行)+§调参表 row_kind/pool/base_ref/pool_extra 四行(第 271、281、282、283 行)+§验收标准 精英行条(第 325 行)
> 验收档:高(改动落在数值表结构校验——敌人表行类枚举、字段互锁与跨表池构成纪律;做错的后果是坏表放行或好表误拒,随加载期传播到全部战斗。判据=req-card 第 16 节单维失败代价)
> **改动面**:游戏代码(`game/data/schemas`、`game/core`、`game/data/tables/enemy.tres`、`game/tests`、`game/sim`)+工具代码(`tools/compendium_gen.py` 展示词)。本卡不携任何 `design/` 改动。
> **编排状态**:未编迭代(待 iter-plan 段编排)
---
## 1. 目标与完成定义
精英怪=现役敌种的强化版,在敌人表里是独立的一行:行类 elite、独立 enemy_id、不写自己的池模板,而是「继承基础敌种的池+附加技」。本批把这套机制落进表结构与校验,并落第一只精英——地精精英;精英遭遇暂不接线(任何节点都读不到 elite 行),投放归待办清单「战斗节点遭遇编排方式」条目。
1. **elite 行类合法**——敌人表行类枚举扩为 {battle, boss, elite};elite 行必带基础敌种引用(base_ref)与非空附加技清单(pool_extra)、禁带池模板(pool),精英 enemy_id 不得与 base_ref 同名;非 elite 行禁带 base_ref/pool_extra。
2. **池继承合并**——精英行的有效池=基础池(同关、battle 行类、基础敌种深度带最小那一行的 pool)+附加技清单;按需现算、不复制,基础池改表即传到精英。
3. **合并池过同一纪律**——跨表池构成纪律(恰一普攻/增益 ≤1/妨害 ≤1/至少一行无条件特殊技/skill_id 悬空致命)对精英行校验的是合并后的池。
4. **暂不接线**——开战寻址的行类门只放行 battle/boss;表里有 elite 行时,任何寻址请求都拿不到它。
5. **地精精英落表**——`enemy.tres` 新增一行 goblin_elite(行值见第 2 节表),全表加载零错。
**完成定义**:五条全落、第 8 节对照表每行真实入口断言当轮执行通过、生产表加载零新增错误、第 6 节反哺点清单与实现报告落 `reports/`,即算这批做完。
## 2. 设计事实源
唯一事实源=`design/gdd/systems/战斗循环/敌人系统.md` v1.9(与待办清单条目状态段闭合凭据一致):
| 规则 | 出处行 |
|---|---|
| 精英=独立行,enemy_id 独立、不与基础敌种同名;名字前缀由行值承载 | 敌人系统.md:143、:147 |
| 基础敌种引用:须指向同关 battle 行类存在的敌种;悬空或指向 elite 行拒绝 | 敌人系统.md:148、:282 |
| 专属池=继承+附加;基础池取同关 battle 行类基础敌种深度带最小行;继承不复制;附加技与基础池 skill_id 重复拒绝 | 敌人系统.md:149、:283 |
| 池构成纪律校验合并后池;快照/冷却/保底/触发语义不变 | 敌人系统.md:150 |
| 暂不接线:寻址只取 battle/boss,elite 行静置合法 | 敌人系统.md:151 |
| 行类域 {battle, boss, elite};pool 仅 battle/boss 必填、elite 禁填 | 敌人系统.md:271、:281 |
| 加载期拒绝清单(含精英 enemy_id 与基础敌种引用同名) | 敌人系统.md:325 |
**首只精英行值**(2026-11-06 用户点头的草案 v0,全部 provisional,投值所有权归难度曲线与Boss;GDD 不登记行值):
| 字段 | goblin_elite 行值 | 对照:地精锚行 (1,battle,0,goblin) |
|---|---|---|
| level_index / row_kind / depth_band | 1 / elite / 0 | 1 / battle / 0 |
| enemy_id / display_name | goblin_elite / 精英·地精 | goblin / 地精 |
| hp | 20 | 8 |
| atk / atk_min / atk_max | 2 / 1 / 3 | 1 / 0 / 2 |
| armor_class / armor_type / attack_type | 2 / light / normal | 0 / light / normal |
| unit_count(无 unit_count_max) | 1 | 1(max 2) |
| base_ref | goblin | — |
| pool_extra | [{skill_id: heavy, weight: 2}] | — |
| 有效池(合并结果) | attack 9 / lunge 1 / desperate_guard 1 / heavy 2 | attack 9 / lunge 1 / desperate_guard 1 |
合并池纪律核:普攻 1(attack);增益 1(desperate_guard,`skills.tres:88-90` type buff);妨害 0;无条件特殊技 ≥1(lunge、heavy)——合规。
## 3. 现状事实(2026-11-06 实查,经复核轮 1 校正;开工日自行复核行号)
### 3.1 敌人表 schema
- `game/data/schemas/enemy_table.gd:11-12` 注释「行类封闭枚举(对齐关卡节点 type 词表)」+`const ROW_KINDS := ["battle", "boss"]`;消费点只有两处:`enemy_table.gd:87`(行类枚举校验,`:88` 文案写死「域 {battle, boss}」)与 `game/core/config_db_resolver.gd:41`(寻址入口行类域门,`:42` 文案同样写死)。全仓无测试断言 ROW_KINDS 内容。
- `enemy_table.gd:36-71` `validate()`:局部变量现 10 个(errs、seen、last_rowset_key、closed_rowset、anchor_ok、boss_ok、eid2、rowset_key、L2、rk2),已到 gdstyle 局部变量阈 10;逐行调 `_validate_row_base`(:47)/`_validate_row_numbers`(:49)/`_validate_row_atk_range`(:50)/`_validate_row_pool`(:51)/`_validate_row_types`(:52);锚行登记 `:62-69`。
- `enemy_table.gd:138-158` `_validate_row_pool`:`:140` 取 `row.get("pool", [])`,`:141-142` 空池报 domain;条目循环 `:144-157`(非字典 domain/skill_id 空 domain/重复 dup_key/权重越 (0,9999] domain),现 6 分支。
- `enemy_table.gd:148` 条目类型写法 `var entry: Dictionary[Variant, Variant] = entry_v`(S9 R1 合格形态)。
- 公开方法现 4 个(validate/band_of/bind_resolver/resolve_rowset),类变量 2 个(rows/_resolver);`tools/gdstyle_baseline.txt` 无本文件键。
### 3.2 跨表池构成校验
- `game/core/config_db_cross_validator.gd:185-214` `validate_skill_pool_links`:`:191` 遍历全部敌行、无行类过滤,`:194` `for entry in row.get("pool", [])`——elite 行会得空池、报两条 pool_composition 误错。调用链=`ConfigDB.load_tables()`(`config_db.gd:117`)→ `_cross_validate`(`:120`)→ `cross_validate` 第⑤步 `_cv_skill_pool`(`config_db_cross_validator.gd:22`、`:82-87`)。单表校验出错后跨表校验照跑(`config_db.gd:117-120`)。
- `_pool_cast_side_errs`(`:171-182`)状态表找不到 buff_ref 时不报 cast_side(`:179-180`)。
### 3.3 寻址与开战
- `config_db_resolver.gd:14-19` 构造 `_init(diag_cb, board_gen_rows_cb, enemy_rows_cb, difficulty_cb)`(四个 Callable);`:33-67` `resolve_enemy_rowset`:`:41-43` 行类不在 `ROW_KINDS` 即经 `_diag` 报 fatal request_oob;`:84`、`:95-96` 按 row_kind 精确过滤——battle/boss 查询本就读不到 elite 行,被本批改动的面是 `:41` 行类门。
- 取行入口两处共用同一 resolver:`unit_container.gd:51`、`battle_orchestrator.gd:299`;行类来源=节点类型(`level_runner.gd:491-493` 只对 battle/boss 开战;`level_table.gd:11` 节点类型词表无 elite)。
- 开战快照 `unit_container.gd:139-153` `_pool_snapshot(row)` 读 `row.get("pool", [])`(`:141`)——本批不改,接线批改读有效池(已登记进「战斗节点遭遇编排方式」条目缺口)。
### 3.4 会因新增 elite 行而失守的存量测试与工具
- `game/tests/unit/data_config/config_db_test.gd:261` 拿 `"elite"` 当非法行类样本,`:268` 断言〔fv7〕文案「封闭枚举 {battle, boss}」——elite 合法后样本失效。
- `game/tests/unit/core/config_db_resolver_test.gd:111-112` `resolve_enemy_rowset(1, 0, "elite")` 断言 fatal〔fv5〕——T2.2 后仍成立,不改。
- `game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd` `_smoke_skill_pool_data`:七处全表遍历以 `row.pool` 直取(`:530`、`:541`、`:560`、`:619`、`:627`、`:640`、`:655`;所在循环 `:529-532`/`:540-543`/`:559-566`/`:613-622`/`:625-632`/`:637-649`/`:653-660`)——elite 行无 pool 键即脚本错误;`:579-611` `expect_pools` 精确键集;`:623` 文案「二十九行」。另两处遍历(`:571-575`、`:791-794`)有前置过滤,elite 行进不去,不改。
- `game/tests/unit/data_config/table_structure_guard_test.gd` `_smoke_enemy_bands`:`:215` print 与 `:216` 注释写「29 行」、`:219-230` `expect_keys`、`:232-234` 收键循环、`:235-236` 断言 `rows.size() == 29`;`_smoke_ac_swap_guard` `:387-394` `l1_totals` 对第一关全部行按带累加(循环首 `:388`),喂 `:395-407` 曲线比 ≤2.5 护栏。
- `game/tests/unit/core/level_shop_economy_test.gd:732`(`_smoke_level_graph`,`:444` 起):注入 4 行再删后断言 `rows.size() == 29`——生产表加一行后必红。
- `game/sim/compendium_dump.gd:6-7` 头注写「行字典原样(零新增字段)」,`:18` `ENEMY_REQUIRED_KEYS` 含 `"pool"`,`:95-97` 缺键即 fail-fast;`tools/compendium_gen.py:34` `ROW_KIND_CN` 无 elite,`:43-49` `FIELD_CN` 无 base_ref/pool_extra,`:120-125` 属性表只跳过 `pool`(pool_extra 会被当普通属性渲染成原始列表)。
- `roll_multiplier_test.gd:72-78` 要求每行 `attack_type == "normal"`——goblin_elite 显式写 normal 即过;`trigger_cond_test.gd:134-141` V7 生产表零 pool_composition——经 T2.1 后仍过;`round_flow_skill_pool_test.gd:880-916` 的夹具行无 row_kind 键,经 T2.1 进 `effective_pool`——T1.4 规定以 `row.get("row_kind", "")` 读取,不受影响。
## 4. 设计契约(红线,违反=L3 停机呈报)
1. 🔴 **继承不复制**:精英有效池每次查询时从基础行现算,禁在加载期把合并结果写回 elite 行或缓存(`enemy_table.gd` 不新增类变量)。依据=敌人系统.md:149。
2. 🔴 **寻址零接线**:resolver 行类门只放行 battle/boss;本批禁改 `unit_container.gd`、`battle_orchestrator.gd`、`level_runner.gd`、`level_table.gd` 任何一行。依据=敌人系统.md:151。
3. 🔴 **算法唯一落点**:合并算法只写在 `EnemyTable.effective_pool()` 一处;池条目域校验只写在 `_validate_pool_entries()` 一处(pool 与 pool_extra 共用,权重上限 9999 不出现第二份);跨表校验、测试、图鉴导出一律调它们,禁各自重写。
4. 🔴 **既有错误类别不改名、既有文案不改字**:现役 category(domain/dup_key/cross_field/rowset_rule/anchor/pool_composition/dangling_skill)语义不动,`_validate_row_pool` 对 pool 的报错文案逐字不变;新增类别只有 `dangling_base` 一个。
5. 🔴 **数值单一事实源**:精英行值只进 `enemy.tres`;产品码零数值字面量。
## 5. 范围边界
做:第 1 节五条;为此必须的存量测试同步(第 3.4 节逐项);图鉴导出工具适配(非玩法行为改动)。
不做(去向):
- 精英遭遇接线投放、开战快照改读有效池(敌人系统.md:325「开战快照拿到合并后池」半句)→ 待办清单「战斗节点遭遇编排方式」(缺口已写明承接);能力清单覆盖域表敌人系统行已标「部分覆盖」指向该条。
- 精英底座光环与描边变色 → 随怪物设定批(敌人系统.md P1 后置行)。
- 精英钥石掉落、GP 精英档掉落(`battle_orchestrator.gd:591` 注释留分支位、`:594` 取档)→ 随接线批。
- 精英 EV 重锚与数值终值 → 难度曲线与Boss(Alpha 阶段零读数,process-conventions §3 第 5 条),本批零 MC。
- 其他敌种的精英版 → 用户裁「先只做地精,看看效果」。
## 6. 关联文档同步面
| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 |
|---|---|---|
| `design/gdd/systems/战斗循环/敌人系统.md` v1.9 | 精英行节、调参表、验收条已按本批目标态成文 | 无需反哺(设计先行,已落定);实现与文档不一致时列反哺点进 `reports/iter<N>-反哺点-<日期>.md` |
| `design/gdd/systems/表现与支撑/数据配置.md` 加载期错误类别表(第 104 行) | 新增 `dangling_base` 属「悬空引用」既有类别的一个实例,表述不变 | 无需反哺;若审计认为需点名,列反哺点 |
| `design/gdd/03-内容规模.md` 第 66 行「精英节点与词缀系统——只预留了字段位」 | 精英怪本体已落表(行类+池继承),节点仍未接线 | 列反哺点进 `reports/iter<N>-反哺点-<日期>.md`,由文档批落文 |
| `game/tests/README.md` 能力清单 | 新增能力行「精英行:池继承合并、加载期校验与暂不接线」;覆盖域表敌人系统行改部分覆盖 | 写卡段已同批入表(实现批禁写);批末只核对名实 |
## 7. 文件结构图
| 文件 | 职责 | 新增/复用 | 行为改动? |
|---|---|---|---|
| `game/data/schemas/enemy_table.gd` | 行类双常量、池条目共用校验、elite 字段校验与引用校验、最浅带行查找、有效池合并 | 复用既有件扩展 | 是(R1–R6) |
| `game/core/config_db_cross_validator.gd` | 池构成纪律改读有效池 | 复用 | 是(R4) |
| `game/core/config_db_resolver.gd` | 行类门改读可寻址常量 | 复用 | 是(R5) |
| `game/data/tables/enemy.tres` | 新增 goblin_elite 一行 | 复用 | 是(R6) |
| `game/tests/unit/data_config/elite_row_test.gd` | 精英行六组验收 | **新增** | 测试件 |
| `game/tests/run_all.gd` | 登记新套件 | 复用 | 测试编排 |
| `game/tests/unit/data_config/config_db_test.gd` | fv7 非法样本换值 | 复用 | 测试同步(R1) |
| `game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd` | 全表遍历改读有效池+期望池增一行 | 复用 | 测试同步(R7) |
| `game/tests/unit/data_config/table_structure_guard_test.gd` | 行数与键序增一行+曲线护栏只算遭遇行 | 复用 | 测试同步(R7) |
| `game/tests/unit/core/level_shop_economy_test.gd` | 注入还原断言改相对基数 | 复用 | 测试同步(R7) |
| `game/sim/compendium_dump.gd` | 导出行对 elite 写有效池 | 复用 | 非行为改动(测量工具适配,见第 8 节表外说明) |
| `tools/compendium_gen.py` | 行类与字段展示词增 elite/base_ref/pool_extra,属性表跳过 pool_extra | 复用 | 非行为改动(同上) |
## 8. 验证闸(改动—验收对照表)
| 行 | 需求点(判据出处行锚) | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|---|---|---|---|---|---|---|---|
| R1 | elite 行类合法与字段互锁、引用校验(`design/gdd/systems/战斗循环/敌人系统.md:325`、`:271`、`:282`、`:283`) | `enemy_table.gd:12` 增 elite;新私有 `_validate_pool_entries`/`_validate_elite_fields`/`_validate_elite_refs`;`_validate_row_pool` 对 elite 早返 | `elite_row_test.gd:_test_elite_validation_rejects`〔精英批 V1〕;`config_db_test.gd:_test_rowset_discipline` fv7 样本换 `"miniboss"` | 接口 | `EnemyTable.validate()`(ConfigDB 加载第一道,`config_db.gd:117`) | 返回错误列表:合法夹具为空;十一个违例夹具各自的错误列表「含」预期 category(message 子串见 T1.11) | 新增:精英行:池继承合并、加载期校验与暂不接线 |
| R2 | 有效池=基础池+附加技,基础池取深度带最小行(`design/gdd/systems/战斗循环/敌人系统.md:149`) | 新公开 `EnemyTable.effective_pool(row)`、新私有 `_min_band_row` | `elite_row_test.gd:_test_effective_pool_merge`〔精英批 V2〕 | 接口 | `EnemyTable.effective_pool()` | 返回数组折成 {skill_id: weight} 字典逐位相等;夹具里深带行排在浅带行之前(取首行的错误实现必红) | 新增:精英行:池继承合并、加载期校验与暂不接线 |
| R3 | 继承不复制:基础池改表传到精英(`design/gdd/systems/战斗循环/敌人系统.md:149`) | 同 R2(按需现算、零缓存) | `elite_row_test.gd:_test_base_pool_change_propagates`〔精英批 V3〕 | 接口 | `EnemyTable.effective_pool()` | 改基础行 pool 某权重后再查,精英有效池对应权重=新值;改写返回数组条目后表内行不变 | 新增:精英行:池继承合并、加载期校验与暂不接线 |
| R4 | 合并池过池构成纪律(`design/gdd/systems/战斗循环/敌人系统.md:150`) | `config_db_cross_validator.gd:194` 改读 `enemy_table.effective_pool(row)` | `elite_row_test.gd:_test_merged_pool_composition`〔精英批 V4〕 | 接口 | `ConfigDbCrossValidator.validate_skill_pool_links()` | 返回错误中 pool_composition 计数:合规精英 =0;附加第二普攻、附加第二增益两夹具各 =1 且 message 含精英 enemy_id | 新增:精英行:池继承合并、加载期校验与暂不接线 |
| R5 | 暂不接线:表里有 elite 行时寻址拿不到它(`design/gdd/systems/战斗循环/敌人系统.md:151`) | `enemy_table.gd` 新常量 `ENCOUNTER_ROW_KINDS`;`config_db_resolver.gd:41` 改读它 | `elite_row_test.gd:_test_elite_unreachable_by_encounter`〔精英批 V5〕 | 接口 | `ConfigDbResolver.resolve_enemy_rowset()`——夹具构造的 resolver,敌行回调返回含 elite 行的行集(开战两处取行门 `unit_container.gd:51`/`battle_orchestrator.gd:299` 共用此方法) | ①请求 `(1, 0, "elite")` 返回空数组且捕获的诊断含 fatal 与 request_oob——只做 T1.1 不做 T2.2 时此请求会返回 goblin_elite,故此判据绑行类门改动;②同夹具 battle/boss 查询返回行中 row_kind=="elite" 计数 =0(非空前置:返回行数 >0) | 新增:精英行:池继承合并、加载期校验与暂不接线 |
| R6 | 地精精英落表且全表加载零错(`design/gdd/systems/战斗循环/敌人系统.md:147`) | `enemy.tres` L1 行区末尾增 goblin_elite 行 | `elite_row_test.gd:_test_production_goblin_elite`〔精英批 V6〕 | 集成 | 生产表 `ConfigDB.load_tables("res://data/tables", true)` | 诊断 error 级计数 =0;该行 12 个字段逐位=第 2 节表、无 `unit_count_max`/`pool` 键;有效池字典={attack 9, lunge 1, desperate_guard 1, heavy 2} | 新增:精英行:池继承合并、加载期校验与暂不接线 |
| R7 | 存量生产表冒烟随新行同步、判据不放宽(`design/gdd/systems/战斗循环/敌人系统.md:325`) | round_flow 七处 `row.pool`→有效池、期望池增一键;guard 行数 29→30、键序增一键、`l1_totals` 跳过 elite;level_shop 还原断言改相对基数 | `round_flow_skill_pool_test.gd:_smoke_skill_pool_data`;`table_structure_guard_test.gd:_smoke_enemy_bands`;`table_structure_guard_test.gd:_smoke_ac_swap_guard`;`level_shop_economy_test.gd:_smoke_level_graph` | 集成 | 生产表 `ConfigDB.load_tables()` | 既有断言原判据照旧(精确键集、行数精确等、键序逐位、逐池纪律、注入全量还原);仅扩期望集与读法 | 既有:技能池数据面与回放独立;既有:表结构守卫:域校验/行序键/跨字段互锁/配额锚 |
**表外改动(非玩法行为改动申报)**:`game/sim/compendium_dump.gd` 与 `tools/compendium_gen.py` 属测量面工具(不进游戏包、不被玩家玩到),本批改动只为让图鉴导出认得 elite 行;验证=process-conventions §4 工具件改完即测:两件最小参数全路径直跑一遍含产出落盘(T4.5),不进本对照表。
**设计验收条未在本批验的半句**:敌人系统.md:325「开战快照拿到合并后池」——本批不接线、无入口可验,移交接线批(「战斗节点遭遇编排方式」条目缺口已承接;README 覆盖域表敌人系统行已标部分覆盖)。
**测试改动申报**(以下改动经本卡预先申报,其余一律不许):
1. `config_db_test.gd:261` 非法行类样本 `"elite"`→`"miniboss"`;`:268` 文案「{battle, boss}」→「{battle, boss, elite}」。理由:elite 已合法,断言意图(非法枚举被拒)不变。
2. `round_flow_skill_pool_test.gd` 七处(第 3.4 节)`row.pool` → `_db.combat.enemy.effective_pool(row)`;`expect_pools` 增一键;`:623` 文案「二十九行」→「三十行」。理由:battle/boss 行有效池=自身 pool,读法等价;elite 行没有 pool 键。
3. `table_structure_guard_test.gd:235-236` 行数 29→30(`:215`/`:216` 文案同步)、`expect_keys` 在 `"1|boss|6|ogre_chief"` 后插 `"1|elite|0|goblin_elite"`;`:388` 循环首加「row_kind == elite 即跳过」。理由:曲线护栏管的是遭遇曲线,elite 行不进遭遇(敌人系统.md:151);不跳过时 :406 文案「12/10/22/34/72」失真(band 0 会从 12 变 32)。
4. `level_shop_economy_test.gd:732` 改为注入前记 `var base_n: int = _db.combat.enemy.rows.size()`、还原后断言 `== base_n`(文案去掉「29 行」写死数)。理由:不写死行数,属加强。
**独立验收审计**:入口=iter 技能第 5 步;报告落 `reports/iter<N>-验收审计-<日期>.md`;高档全量(test-conventions §8.7)。
**测试方式两分法**:本卡全部需求点归自动化能力验证(直构夹具表与生产表加载,不经 UI);精英暂不接线,无玩家可见面,**零用户目检项**。
**回归措辞**:里程碑步(T 段)出口跑一次全套闸;段内修复只做出红最小单元的最窄确认;新增测试先行孤立验证(单套件直跑)再并入全套。
## 9. 任务卡
### T1|敌人表 schema:行类双常量、elite 校验与有效池(≈0.5 工作日)
取用:无。
- [ ] T1.1 实装:`enemy_table.gd:12` 改 `const ROW_KINDS := ["battle", "boss", "elite"]`,`:11` 注释改「行类封闭枚举:表内允许出现的行类(battle/boss 对齐关卡节点 type 词表,elite=精英行)」;`:88` 文案域改「{battle, boss, elite}」。
- [ ] T1.2 实装:在 `ROW_KINDS` 下一行新增 `const ENCOUNTER_ROW_KINDS := ["battle", "boss"]`,上方注释一行「开战寻址可读的行类——elite 接线前不在此列」。
- [ ] T1.3 实装:新增私有 `func _min_band_row(level: int, eid: String, kind: String) -> Dictionary`——在 `rows` 中取 level_index==level、row_kind==kind、enemy_id==eid 的行里 depth_band 最小的一行,无则返回 `{}`;行字段一律 `row.get(...)` 读取。
- [ ] T1.4 实装:新增公开 `func effective_pool(row: Dictionary) -> Array[Dictionary]`——`String(row.get("row_kind", ""))` 不是 elite:返回该行 pool 中每个 `is Dictionary` 条目的 `duplicate()`;是 elite:先放 `_min_band_row(level, base_ref, "battle")` 的 pool 条目、再放本行 pool_extra 条目(均只取 `is Dictionary` 条目并 `duplicate()`),基础行为空时基础部分为空。局部变量类型写 `:=` 或 `Dictionary[Variant, Variant]`(不写裸 `Dictionary` 注解)。
- [ ] T1.5 实装:把 `_validate_row_pool` 的条目循环(`:144-157`)提成新私有 `func _validate_pool_entries(entries: Array, eid: String, field: String) -> Array[Dictionary]`,文案前缀改为 `"%s %s …" % [eid, field]`;`_validate_row_pool` 以 `field="pool"` 调它——pool 报错文案逐字不变(契约 4)。
- [ ] T1.6 实装:`_validate_row_pool` 首句加「`String(row.get("row_kind", "")) == "elite"` 即返回空错误列表」。
- [ ] T1.7 实装:新增私有 `func _validate_elite_fields(row: Dictionary, eid: String) -> Array[Dictionary]`——elite 行:base_ref 缺或空串 → cross_field;base_ref == enemy_id → cross_field;pool_extra 缺键或空数组 → cross_field;带 pool 键 → cross_field;pool_extra 非空时以 `field="pool_extra"` 调 `_validate_pool_entries`。非 elite 行:带 base_ref 或 pool_extra 键 → cross_field。若实写超 8 分支,拆为 `_validate_elite_row_fields`(elite 行必备字段)与 `_validate_plain_row_fields`(非 elite 行禁带字段)两个私有函数,由 `_validate_elite_fields` 按行类转调。
- [ ] T1.8 实装:`validate()` 在 `:51` 之后加一行 `errs.append_array(_validate_elite_fields(row, eid2))`(零新增局部变量)。
- [ ] T1.9 实装:新增私有 `func _validate_elite_refs() -> Array[Dictionary]`——对每条 elite 行:base_ref 缺或空串即跳过(已由 T1.7 报);`_min_band_row(level, base_ref, "battle")` 为空时报 `dangling_base`,若 `_min_band_row(level, base_ref, "elite")` 非空则 message 写「指向 elite 行」,否则写「同关 battle 行类无此敌种」;基础行在时,pool_extra 与基础 pool 的 skill_id 交集非空 → dup_key。实写超 8 分支时把交集判提成私有 `func _extra_overlap_errs(row: Dictionary, base_row: Dictionary, eid: String) -> Array[Dictionary]`。
- [ ] T1.10 实装:`validate()` 循环结束后、`_validate_anchor_rows` 调用之前加一行 `errs.append_array(_validate_elite_refs())`(零新增局部变量)。
- [ ] T1.11 验收:新建 `game/tests/unit/data_config/elite_row_test.gd`(`extends SceneTree`;头注写本套件断言面;`_init()` 依次调六个测试函数后 `quit(Kit.finish("elite_row_test"))`;夹具一律 `rows.assign([...])`;行构造助手照 `config_db_test.gd:212-214` `mk_row` 写全字段〔level_index/row_kind/depth_band/enemy_id/display_name/unit_count/hp/atk/pool〕,elite 行形态=去掉 pool、加 base_ref/pool_extra)。本步写 `_test_elite_validation_rejects`,注记 `# oracle: design/gdd/systems/战斗循环/敌人系统.md:325 elite 行字段互锁与基础引用违例加载期返回错误`:合法夹具〔(1,battle,0,goblin) pool attack9/lunge1 + (1,boss,9,ogre_chief) 带 pool + (1,elite,0,goblin_elite) base_ref goblin pool_extra [heavy 2]〕`validate()` 返回空;十一个违例夹具(各在合法夹具上改一处)的错误列表各「含」:①elite 删 base_ref → cross_field ②base_ref="goblin_elite"(与自身同名)→ cross_field ③pool_extra 为空数组 → cross_field ④elite 删 pool_extra 键 → cross_field ⑤elite 加 pool → cross_field ⑥battle 行加 base_ref → cross_field ⑦battle 行加 pool_extra → cross_field ⑧base_ref="hobgoblin" → dangling_base ⑨再加一条 (1,elite,0,goblin_elite2) 行、goblin_elite 的 base_ref 改指它 → dangling_base 且 message 含「elite」 ⑩pool_extra 含 lunge → dup_key ⑪pool_extra 条目权重 0 → domain 且 message 含「pool_extra」〔精英批 V1〕。
- [ ] T1.12 实装:`game/tests/run_all.gd:181`(table_structure_guard_test 行)之后登记 `{"path": "res://tests/unit/data_config/elite_row_test.gd", "expect": 0},`。
- [ ] T1.13 验收:同文件写 `_test_effective_pool_merge`,注记 `# oracle: design/gdd/systems/战斗循环/敌人系统.md:149 精英有效池=同关战斗行类基础敌种深度带最小行的池+附加技`:夹具行序为 (1,battle,3,goblin) pool attack5/charge2 在前、(1,battle,0,goblin) pool attack9/lunge1 在后,加 boss 行与 elite 行 base_ref goblin pool_extra [heavy 2]——elite 有效池字典 == {attack 9, lunge 1, heavy 2}、size 3;band 0 battle 行有效池字典 == {attack 9, lunge 1}、size 2〔精英批 V2〕。
- [ ] T1.14 验收:同文件写 `_test_base_pool_change_propagates`,注记 `# oracle: design/gdd/systems/战斗循环/敌人系统.md:149 继承不复制——基础池调参自动传到精英`:同 T1.13 夹具,先查一次,再按 depth_band==0 找到基础行把其 pool 中 attack 条目权重改 7,再查 elite 有效池 attack == 7;另把首次返回数组的首条目权重改 99,断言表内基础行 attack 权重仍为 7〔精英批 V3〕。
- [ ] T1.15 实装(测试改动申报第 1 条):`config_db_test.gd:261` 样本改 `"miniboss"`,`:268` 文案改「{battle, boss, elite}」。
- [ ] T1.16 验证:`…console.exe --headless --path game --script res://tests/unit/data_config/elite_row_test.gd` 与 `--script res://tests/unit/data_config/config_db_test.gd` 各退出码 0、输出无 SCRIPT ERROR。
产出:`EnemyTable.ROW_KINDS`、`EnemyTable.ENCOUNTER_ROW_KINDS`、`EnemyTable.effective_pool(row: Dictionary) -> Array[Dictionary]`、错误类别 `dangling_base`。
### T2|跨表纪律读合并池、寻址门只放可寻址行类(≈0.25 工作日)
取用:T1 产出 `effective_pool`、`ENCOUNTER_ROW_KINDS`。
- [ ] T2.1 实装:`config_db_cross_validator.gd:194` 改为 `for entry in enemy_table.effective_pool(row):`(其余不动)。
- [ ] T2.2 实装:`config_db_resolver.gd:41` 改为 `if not EnemyTable.ENCOUNTER_ROW_KINDS.has(row_kind):`(`:42` 文案保持「row_kind 域 {battle, boss}」)。
- [ ] T2.3 验收:`elite_row_test.gd` 写 `_test_merged_pool_composition`,注记 `# oracle: design/gdd/systems/战斗循环/敌人系统.md:150 池构成纪律校验对象是合并后的池`;技能表夹具五行 attack〔basic〕/lunge〔damage〕/heavy〔damage〕/harden〔buff〕/charge〔buff〕,状态表夹具传空表(`_pool_cast_side_errs` 找不到 buff_ref 时不报,`config_db_cross_validator.gd:179-180`):合规精英(基础 attack/lunge+附加 heavy)pool_composition 计数 =0;附加 attack 的精英 → 计数 =1 且 message 含 `goblin_elite`;基础 attack/lunge/harden+附加 charge 的精英 → 计数 =1 且 message 含 `goblin_elite`〔精英批 V4〕。
- [ ] T2.4 验收:同文件写 `_test_elite_unreachable_by_encounter`,注记 `# oracle: design/gdd/systems/战斗循环/敌人系统.md:151 精英行接线前不会被任何节点读到`:`preload("res://core/config_db_resolver.gd").new(捕获诊断到局部数组的 Callable, 返回空数组的 Callable, 返回含 (1,battle,0,goblin)/(1,boss,9,ogre_chief)/(1,elite,0,goblin_elite) 三行的 Callable, 返回 null 的 Callable)`;①`resolve_enemy_rowset(1, 0, "elite")` 返回 size =0 且诊断里有含「fatal」与「request_oob」的一条;②`resolve_enemy_rowset(1, 0, "battle")` 与 `(1, 9, "boss")` 返回行合计 >0 且其中 row_kind=="elite" 计数 =0〔精英批 V5〕。
- [ ] T2.5 验证:`elite_row_test.gd`、`config_db_cross_validator_test.gd`、`config_db_resolver_test.gd` 三件单跑退出码 0。
产出:无新名字。
### T3|地精精英落表与存量冒烟同步(≈0.5 工作日)
取用:T1、T2 全部产出。
- [ ] T3.1 实装:`game/data/tables/enemy.tres` 在 `(1,boss,6,ogre_chief)` 行(`:182-208`)之后、`(2,battle,0,bugbear)` 行之前插入一行,字段与取值逐项照第 2 节表(含 `"attack_type": "normal"`、`"armor_type": "light"`;不写 `unit_count_max`、不写 `pool`)。
- [ ] T3.2 实装:`enemy.tres` 文件尾批注区追加一行:精英专属池批首只精英=地精精英,行值 provisional,来源 2026-11-06 用户点头草案 v0(措辞避开术语表退役词)。
- [ ] T3.3 验收:`elite_row_test.gd` 写 `_test_production_goblin_elite`,注记 `# oracle: design/gdd/systems/战斗循环/敌人系统.md:147 精英=敌人表行类为 elite 的独立一行`:生产表 `load_tables("res://data/tables", true)` 后 error 级诊断计数 =0;enemy_id=="goblin_elite" 的行恰 1 条,level_index 1/row_kind elite/depth_band 0/display_name「精英·地精」/hp 20/atk 2/atk_min 1/atk_max 3/armor_class 2/armor_type light/unit_count 1/base_ref goblin 逐位相等,且无 `unit_count_max`、无 `pool` 键;有效池字典 == {attack 9, lunge 1, desperate_guard 1, heavy 2}〔精英批 V6〕。
- [ ] T3.4 实装(测试改动申报第 2 条):`round_flow_skill_pool_test.gd` 七处 `row.pool` 改 `_db.combat.enemy.effective_pool(row)`;`expect_pools` 增 `"1_elite_0_goblin_elite": {"attack": 9, "lunge": 1, "desperate_guard": 1, "heavy": 2}`;`:623` 文案改「三十行」。
- [ ] T3.5 实装(测试改动申报第 3 条):`table_structure_guard_test.gd:235-236` 行数改 30、`:215`/`:216` 文案同步、`expect_keys` 在 `"1|boss|6|ogre_chief"` 后插 `"1|elite|0|goblin_elite"`;`:388` 循环首加 `if String(row.get("row_kind", "")) == "elite": continue`。
- [ ] T3.6 实装(测试改动申报第 4 条):`level_shop_economy_test.gd` 注入段前记 `var base_n: int = _db.combat.enemy.rows.size()`,`:732` 断言改 `== base_n`、文案去掉「29 行」。
- [ ] T3.7 验证:`elite_row_test.gd`、`round_flow_skill_pool_test.gd`、`table_structure_guard_test.gd`、`level_shop_economy_test.gd`、`roll_multiplier_test.gd`、`trigger_cond_test.gd` 六件单跑退出码 0、无 SCRIPT ERROR。
- [ ] T3.8 验证(里程碑出口):`bash tools/run_all_gates.sh --code` 所选域全绿。
产出:生产表 goblin_elite 行。
### T4|图鉴导出认得精英行(≈0.25 工作日,非玩法行为改动)
取用:T1 `effective_pool`;T3 生产表 goblin_elite 行。
- [ ] T4.1 实装:`game/sim/compendium_dump.gd` 在 `:30` 取 `enemy_rows` 之后构造导出行数组:逐行 `duplicate()`,row_kind=="elite" 的副本写 `"pool" = db.combat.enemy.effective_pool(row)`;`_validate_rows` 与 payload `"enemy_rows"` 改用导出行数组(表内行不被改写)。
- [ ] T4.2 实装:`compendium_dump.gd:6-7` 头注「行字典原样(零新增字段)」改为「行字典原样,elite 行另补合并后的 pool 供展示」。
- [ ] T4.3 实装:`tools/compendium_gen.py:34` `ROW_KIND_CN` 增 `"elite": "精英行"`;`:43-49` `FIELD_CN` 增 `"base_ref": "基础敌种"`、`"pool_extra": "附加技"`。
- [ ] T4.4 实装:`compendium_gen.py:120-125` 属性表循环跳过条件由 `key == "pool"` 改为 `key in ("pool", "pool_extra")`。
- [ ] T4.5 验证:`…console.exe --headless --path game --script res://sim/compendium_dump.gd -- out=<区内 sim-data/compendium/dump.json 绝对路径>` 退出码 0;`python tools/compendium_gen.py` 退出码 0,产出 `index.html` 中「精英·地精」与「精英行」两串 grep 计数各 ≥1,读数写进提交信息。
产出:无。
### T5|产出物落位卡(≈0.25 工作日,末卡)
- [ ] T5.1 写 `reports/iter<N>-实现报告-<日期>.md`:各卡状态、实际对照表(第 8 节七行补「结果」格与测试 `文件:行`)、实现决定记录(零拍板则写一行「零拍板」)、遗留读数义务(精英 EV 重锚归数值统一修正批)、实机目检总清单(本批零项,理由=暂不接线无玩家可见面)。
- [ ] T5.2 写 `reports/iter<N>-反哺点-<日期>.md`:第 6 节「03-内容规模.md 第 66 行」一条(改成:精英怪本体已落敌人表精英行〔行类+池继承附加〕,精英节点与投放仍未接线;依据=本批实现);实现与敌人系统 v1.9 有出入的点逐条补列。
- [ ] T5.3 核对 `game/tests/README.md` 能力行代表用例名与实际落地函数名逐字一致(不一致=停卡退回,实现批禁写该文件)。
**估时合计**:0.5+0.25+0.5+0.25+0.25=1.75 工作日(区间 1.5–2.25;超软盒预案=T4 可整卡后移为工程直改)。
## 10. 异常分级
- **L1 自救**:Godot 导入缓存缺失(拷主区 `.godot/` 后重跑);单套件首跑脚本错误属本批新码笔误,修后单跑确认。
- **L2 记录继续**:存量套件出现与本批改动面无关的红(先比对主区同套件读数,确认是既有红则记实现报告继续)。
- **L3 停机呈报**:
1. 第 3.4 节之外又发现读 `row.pool`/`row_kind` 列表、或写死敌人表行数而被新行打破的存量件(卡没写全=上游缺陷,停卡退回写卡段)。
2. 任一验收断言需要第 8 节测试改动申报之外的改判。
3. gdstyle(S13)对 `enemy_table.gd`、`config_db_cross_validator.gd`、`config_db_resolver.gd` 报新键(预算见第 13 节;机检预算互斥=上游缺陷停卡退回写卡段)。
4. 违反第 4 节任一契约才能落地。
5. 生产表加载出现 `dangling_base`、cross_field 或 pool_composition 错误(说明行值或合并算法与第 2 节不符)。
## 11. 代拍板白名单
1. 第 9 节已点名的私有函数内部变量名与报错文案措辞(类别与 T1.7/T1.9 规定一致、pool 文案逐字不变即可)。
2. `elite_row_test.gd` 内夹具助手函数的拆法与命名(不对外)。
3. `enemy.tres` 新行内字段书写次序(与相邻行同款即可)与批注措辞。
4. 测试断言消息文案(尾缀〔精英批 Vn〕必须在)。
超清单事项(含新增第 9 节未点名的产品码函数)记入实现报告「实现决定记录」并呈报。
## 12. 落位与可复用性预检(与第 7 节结构图互指)
| 新增项 | 复用面(为什么不能复用既有那一个) | 唯一面 | 分层与交互面 |
|---|---|---|---|
| `EnemyTable.effective_pool()` | 盘上无「按行求有效池」的实现(grep `effective_pool`/`merged_pool`/`pool_of` 零命中);`_pool_snapshot`(`unit_container.gd:139`)是开战快照、属运行期实例层,不承担表层合并 | 合并算法只此一处(契约 3) | 数据层 schema 件,零 UI 依赖;被 core 跨表校验件、sim 工具、测试调用,方向 core/sim → data |
| `ENCOUNTER_ROW_KINDS` | 既有 `ROW_KINDS` 是「表里允许出现的行类」,扩 elite 后不再等于「可寻址行类」 | 与 `ROW_KINDS` 同文件相邻定义;全仓只有 resolver 一处读它 | resolver(core)读 data 层常量,方向不变 |
| `_validate_pool_entries` | 由既有 `_validate_row_pool` 条目循环提出(复用既有逻辑,非新造);pool_extra 条目域与 pool 相同 | 池条目域校验唯一落点(契约 3) | 私有,`_validate_row_pool` 与 `_validate_elite_fields` 两处调用 |
| `_validate_elite_fields`/`_validate_elite_refs`(及 T1.7/T1.9 点名的备用拆件) | 既有 `_validate_row_*` 族各管一个单字段面;elite 字段互锁与跨行引用是新职责,塞进 `_validate_row_pool` 会超分支预算 | 同落 `enemy_table.gd`,与 `_validate_row_*` 族同位 | 私有,只被本类 `validate()` 调用 |
| `_min_band_row` | 盘上无「按 (关, 敌种, 行类) 取最浅带行」的查询(resolver 的 `_band_rows` 按带键取整行集,语义不同) | 基础行查找与「是否指向 elite」判别共用它 | 私有,被 `effective_pool` 与 `_validate_elite_refs` 调用 |
| `dangling_base` 错误类别 | 既有 `dangling_skill` 专指技能悬空(跨表件),基础敌种引用是表内引用 | 只在 `_validate_elite_refs` 产出 | 经既有 `validate()` 错误列表通道外发,ConfigDB 消费方式不变 |
| `elite_row_test.gd` | `config_db_test.gd`(全表装载与行集纪律)、`config_db_cross_validator_test.gd`(跨表链接)、`config_db_resolver_test.gd`(寻址)各已成体量;精英行六组断言共属一个能力行,拆进三件会把一个能力散到三处 | 精英行能力的代表用例全部落此一件 | 测试从公开入口进入:`validate()`/`effective_pool()`/`validate_skill_pool_links()`/`resolve_enemy_rowset()`/`ConfigDB.load_tables()` |
## 13. 实现规范预算(与第 7 节结构图互指)
本批无新增产品文件;新测试件不在 gdstyle 扫描面。存量触面预算(阈=gdstyle 默认:公开方法 ≤20、类变量 ≤15、分支 ≤8、返回 ≤6、局部变量 ≤10):
| 文件/函数 | 预算 | 依据 |
|---|---|---|
| `enemy_table.gd` 公开方法 | 4 → 5(+`effective_pool`) | 第 3.1 节 |
| `enemy_table.gd` 类变量 | 2 → 2 | 契约 1 |
| `validate()` | 局部变量 10 → 10(两处新调用都写成 `errs.append_array(...)`);分支不增 | 第 3.1 节实数 |
| `_validate_row_pool` | 条目循环提走后分支 ≤3(elite 早返、空池、调用)、返回 2 | T1.5/T1.6 |
| `_validate_pool_entries` | 分支 5(for、非字典、空 id、elif 重复、权重)、返回 1 | 原循环形态 `:144-157` |
| `_validate_elite_fields` | elite 支 5 判+非 elite 支 1 判+分派 1 ≈7–8;超 8 按 T1.7 拆两函数 | T1.7 |
| `_validate_elite_refs` | for、非 elite 跳过、base_ref 空跳过、基础行空、指向 elite 判别、交集两层 for 与判 ≈8;超 8 按 T1.9 提 `_extra_overlap_errs` | T1.9 |
| `_min_band_row` | 分支 ≤3 | T1.3 |
| `effective_pool` | 分支 ≤6(行类判、两段 for 各含字典判、基础行空判) | T1.4 |
| `config_db_cross_validator.gd`/`config_db_resolver.gd` | 只改一行表达式,各指标不变 | T2.1/T2.2 |
| 基线键 | `tools/gdstyle_baseline.txt` 无上述三文件键——零登记,任何新键即红(L3 第 3 条) | 第 3.1 节 |
## 14. 拆分边界纪律
本卡非拆分/重构类。第 13 节两个备用拆法均按职责轴给出(`_validate_elite_row_fields`/`_validate_plain_row_fields` 各自变化原因=elite 行必备字段集合变/非 elite 行禁带字段集合变;`_extra_overlap_errs` 变化原因=附加技与基础池重叠判定规则变),不以阈值为动机。禁为迎合机检消息文本保留或新增无效成员。
## 15. 待裁点
零待裁点(设计裁决全部在文档设计段落定:1B 池继承+附加、首只地精、草案 v0 行值,2026-11-06 用户点头;复核轮 1 的一条「待裁」建议经核为自判,见第 16 节)。开工门=U0。
## 16. 复核记录
复核者身份=未参与本卡撰写的只读子代理(Agent 工具起的独立会话,禁写文件、禁跑闸、禁运行测试)。轮次 1,发现 21 条,四类去向逐条登记;发现原文与依据索引见复核报告 reports/复核-精英专属池-2026-11-06.md。
| 轮次 | 复核者身份 | 发现(一句话) | 去向 | 处置结果 |
|---|---|---|---|---|
| 1 | 只读子代理·未参与撰写 | `level_shop_economy_test.gd:732` 写死「表回 29 行」,加行必红,卡未列 | 补写 | §3.4 补列;§8 R7 增该套件;测试改动申报第 4 条(改相对基数,属加强);T3.6、T3.7 |
| 1 | 同上 | §3.4 与 T 步多处行号整体偏移(round_flow +7、guard +3、config_db_test +7、resolver_test +6、compendium、battle_orchestrator) | 自判 | 按复核者实查行号全部改正(§3.4、§5、§8 申报、T1.15、T3.4–T3.6) |
| 1 | 同上 | V5 用 battle/boss 查询断 elite 计数=0,改动前后都绿,没绑行类门 | 补写 | R5/T2.4 改为夹具 resolver 含 elite 行、请求 elite 断空+fatal/request_oob;「唯一取行门」改为两处共用 |
| 1 | 同上 | `_validate_elite_fields` 分支预算算不通,备用拆法也撞线 | 自判 | 条目循环提成共用 `_validate_pool_entries`(T1.5,契约 3,9999 不出第二份);§12、§13 重算 |
| 1 | 同上 | `_validate_elite_refs` 预算 ≤5 写不出 | 补写 | `_base_row_of` 泛化为 `_min_band_row(level, eid, kind)` 兼作指向 elite 判别(T1.3、T1.9);§13 按实写重算并点名备用拆件 `_extra_overlap_errs` |
| 1 | 同上 | `validate()` 局部变量已 10/10,未入预算 | 补写 | §3.1 记实数;§13 增行;T1.8、T1.10 规定零新增局部变量 |
| 1 | 同上 | §8「恰命中」与 T1.6「含」矛盾,缺 base_ref 会连带报 dangling_base | 自判 | T1.9 规定 base_ref 缺或空即跳过;§8 R1 判据统一为「含」 |
| 1 | 同上 | 夹具照跨表测试助手形态缺 hp/atk 等字段,合法夹具做不到零错 | 补写 | T1.11 改照 `config_db_test.gd:212-214` `mk_row` 写全字段,boss 行带 pool |
| 1 | 同上 | 「取最浅带」夹具未定行序,取首行的错误实现也能过 | 补写 | T1.13 深带行在前、浅带行在后;T1.14 按 depth_band 查基础行 |
| 1 | 同上 | pool_extra 非字典/空 id/重复/权重越界、非 elite 带 pool_extra、缺 pool_extra 键等分支无断言 | 补写 | T1.11 违例夹具扩到 11 个(增 ②同名 ④缺键 ⑦battle 带 pool_extra ⑪权重 0);条目非字典/空 id/重复与 pool 共用 `_validate_pool_entries`,由既有 pool 断言与 ⑪ 覆盖 |
| 1 | 同上 | 设计验收「开战快照拿到合并后池」半句本批无入口可验且未申报 | 补写 | §5、§8 表外申报移交;待办清单「战斗节点遭遇编排方式」缺口写明承接;README 覆盖域表敌人系统行改部分覆盖 |
| 1 | 同上 | 验证 config_db_test 的步排在修它的步之前 | 自判 | 修样本步(T1.15)移到单跑验证步(T1.16)之前 |
| 1 | 同上 | 原 T1.5、T1.6、T3.1 一步两动作 | 自判 | 拆为现 T1.5/T1.6、T1.11/T1.12、T3.1/T3.2 |
| 1 | 同上 | 新套件登记在 core 段,与 data_config 目录不合 | 自判 | T1.12 改登记在 `run_all.gd:181` 之后(data_config 段) |
| 1 | 同上 | 多个测试函数只写「注记锚」,缺 `# oracle:` 全格式与判据句 | 补写 | T1.13、T1.14、T2.3、T2.4、T3.3 补全注记原文 |
| 1 | 同上 | `effective_pool` 点号读行类会在无 row_kind 夹具上脚本错误;非字典条目 duplicate 会丢错误;裸 Dictionary 注解撞 S9 | 补写 | T1.3、T1.4 规定 `row.get` 读取、只取 `is Dictionary` 条目、类型写 `:=` 或 `Dictionary[Variant, Variant]` |
| 1 | 同上 | `enemy_table.gd:11` 注释「对齐关卡节点 type 词表」加 elite 后不实 | 自判 | T1.1 同步改注释 |
| 1 | 同上 | 图鉴导出头注不实;gen 的 FIELD_CN 缺两字段且 pool_extra 会被当属性渲染 | 补写 | T4.2、T4.3、T4.4 |
| 1 | 同上 | §16 只有外部报告引用、无五格轮次表,且称新规禁另设报告文件 | 自判 | 本节改五格表。外部报告文件保留——依据:流水线闸 C6 现行判据要求节内申报复核报告路径且文件在盘(`tools/pipeline_gate.py:689-696`),与 req-card 技能「不另设报告文件」口径不一致,属规约冲突,已另登待办条目「卡片复核报告文件口径:闸件与技能不一致」 |
| 1 | 同上 | 设计写「精英 enemy_id 不与基础敌种同名」但拒绝清单与卡均无此校验(复核者标待裁) | 自判 | 权威文档 敌人系统.md:147 已定规则,唯一答案=校验;T1.7 加 base_ref==enemy_id → cross_field、T1.11 夹具②;拒绝清单句 敌人系统.md:325 同批补「精英 enemy_id 与基础敌种引用同名」(设计分支未合回,v1.9 内修订) |
| 1 | 同上 | 观察:T2.3 夹具与 side 守卫一致、fv5 仍成立、l1_totals 不跳过也不红、enemy.tres 插行不致静态扫描误判 | 自判 | 不改+依据(复核者实查);测试改动申报第 3 条理由改写为「不改则 :406 文案失真且 elite 不属遭遇」;T3.2 批注避开退役词 |
+1 -1
View File
@@ -66,7 +66,7 @@ GRADE_RULE_DATE = (2026, 11, 5)
GRADE_RE = re.compile(r"验收档\s*[::]\s*[高中低]")
# C5 判据出处行锚(2026-11-05 立;test-conventions §8.3:需求点格须带现行文档判据句锚)
ANCHOR_RULE_DATE = (2026, 11, 5)
ANCHOR_RE = re.compile(r"([A-Za-z0-9_\-.\\/]+\.(?:md))\s*:\s*(\d+)")
ANCHOR_RE = re.compile(r"([^\s`'\"()(),,、::|]+\.md)\s*:\s*(\d+)") # 路径段放行中文名(系统文档全是中文名,test-conventions §8.3)
# C6 复核记录(2026-11-05 立,生效 2026-11-06;req-card 必备结构第 17 节+纪律「复核发现四类分流」)
REVIEW_RULE_DATE = (2026, 11, 6)
REVIEW_HEADING_RE = re.compile(r"^#{2,4}\s*\d*\.?\s*复核记录")
+33 -2
View File
@@ -103,15 +103,46 @@
#### 个体化变体池(2026-10-18 登记,来源=会话提及)
**实况**:A 型好斗/ B 型守势、精英专属池(技能池共识点 A 的 A2 案);现行同敌种同池模板,实例分歧只来自摇号涌现。
**实况**:A 型好斗/ B 型守势——同种敌个体间技能池不同(技能池共识点 A 的 A2 案);现行同敌种同池模板,实例分歧只来自摇号涌现。排期 Beta(立项时按 roadmap 开卡)。
**缺口**:还差敌人系统的变体池设计讨论——A2 案的池构成方案与精英专属池边界。
**缺口**:还差敌人系统的分型池设计讨论——同种怎么分成两型、两型池各配什么。
- 相关文档:[敌人系统](design/gdd/systems/战斗循环/敌人系统.md)(P1)
**改动面**:文档
**状态**:待文档设计
#### 精英专属池(2026-11-06 登记,来源=会话提及)
**实况**:精英怪本体(独立行+elite 行类+池继承基础池加附加技+暂不接线),首只=地精精英;排期 Alpha(现行里程碑内完成)。投放接线归战斗节点遭遇编排方式条目。
- 设计定稿:`design/gdd/systems/战斗循环/敌人系统.md` v1.9(「精英行」节+调参表三字段+验收标准精英行条)
- 相关文档:`design/gdd/systems/冒险循环/难度曲线与Boss.md` v1.6(精英修饰预留轴指路与视觉三件分工)
- 需求卡片:reports/需求卡片-精英专属池-2026-11-06.md v1.1
- 复核报告:reports/复核-精英专属池-2026-11-06.md
**改动面**:文档+游戏代码+工具代码
**状态**:文档设计已闭合+已写卡
#### 卡片复核报告文件口径:闸件与技能不一致(2026-11-06 登记,来源=审计发现)
**实况**:req-card 技能必备结构第 17 节写「复核凭据=本节自身,不另设复核报告文件(2026-11-06 用户裁)」(`.zcode/skills/req-card/SKILL.md:64`);流水线闸 C6 仍要求「复核记录」节申报复核报告路径且文件在盘(`tools/pipeline_gate.py:689-696`),doc-conventions §12.1「已写卡」证据项仍列复核报告路径。精英专属池卡按闸件现行判据保留了报告文件。
**改动面**:文档+工具代码
**状态**:待执行
#### 战斗节点遭遇编排方式(2026-11-06 登记,来源=会话提及)
**实况**:现状机制已查实的部分——战斗节点递「关卡序号+节点深度」落深度带读行集(行键=关卡×行类×深度带×enemy_id),同带节点读同一行集、仅数量区间掷定;遭遇内容全靠敌人表手配行,无生成器;设计面未开过讨论。
**缺口**:还差编排方式的设计讨论——固定配置与生成器两条路的取舍(含同带多套遭遇怎么轮换、新怪怎么进编排、精英遭遇的接线;接线时开战快照须改读精英有效池,承接敌人系统 v1.9 精英行验收条「开战快照拿到合并后池」)。
- 相关文档:[敌人系统](design/gdd/systems/战斗循环/敌人系统.md)(行集构成纪律)与[关卡节点地图](design/gdd/systems/冒险循环/关卡节点地图.md)(遭遇构成编排面)+[难度曲线与Boss](design/gdd/systems/冒险循环/难度曲线与Boss.md)(投值所有权)
**改动面**:文档
**状态**:待文档设计
#### 全局特殊间隔旋钮(2026-10-18 登记,来源=会话提及)
**实况**:异名特殊技背靠背现行概率低(是变化不是失控);若实测仍嫌,备用闸=全局「特殊技后至少隔 N 拍」——登记备用,未实测不启用。