diff --git a/game/tests/README.md b/game/tests/README.md index bfb6ed59..9b75dd0f 100644 --- a/game/tests/README.md +++ b/game/tests/README.md @@ -156,7 +156,7 @@ tests/ | 四柜台拆解后五界面入口改挂与写口零回归 | 营地五界面 | 五界面意图信号 → `CampShopPresenter` → `MetaProgression.tree_buy()` 写口 | `forge_workbench_test.gd:_run`(承载类同迁断言十二项);`ui_click_probe.gd:_ready`(写口链段) | | 营地篝火回主菜单与笔记本改挂动线 | 营地交互流 | 笔记本命中区真点(`push_click_at`)→ `CareerOverlay.open()`;篝火命中区真点 → ConfirmDialog 真钮二次确认 → 主菜单(2026-11-06 真输入化) | `ui_struct_probe.gd:_ready`(career 段);`screen_flow_probe.gd:_ready`(篝火/开合段——真输入驱动) | | 确认弹窗按钮位次与语义同钉 | HUD框架 | `ConfirmDialog.open()`/`ConfirmDialog.open_three()` 开态读按钮行子节点序(定值=推进钮在左/次推进居中/维持钮在右,四处共用件同一序);探针在弹窗开态取按钮行 child(0) 的全局矩形中心经 `ProbeUiUtil.push_click_at` 真点 | `confirm_dialog_test.gd:_test_two_button_row_order`;`confirm_dialog_test.gd:_test_three_button_row_order`;`ui_click_probe.gd:_ready`(大门无断点段推进钮坐标真点) | -| 营地顶栏栏体定值与落座 | 营地场景视图 | 真实工程 boot 后经装配链 `MainUiBuild`→`CampSceneView.set_hud_band()` 读 `ui.modals.camp.scene.hud_band`(定值=`CAMP_HEADER_BAND`×α0.80、48px 全宽浮层、徽章右位顶格);单元经 `camp_scene_layout_table.gd` 的 `hud_band_h` 出口读背景贴图落位带像素算对比 ≥3:1 | `system_test.gd:_smoke_camp_hud_band`;`camp_scene_layout_test.gd:_test_hud_band_contrast_over_bg` | +| 营地顶栏栏体定值与落座 | 营地场景视图 | 真实工程 boot 后经装配链 `MainUiBuild`→`CampSceneView.set_hud_band()` 读 `ui.modals.camp.scene.hud_band`(定值=`CAMP_HUD_BAND`×α0.80、48px 全宽浮层、徽章右位顶格);单元经 `camp_scene_layout_table.gd` 的 `hud_band_h` 出口读背景贴图落位带像素算对比 ≥3:1 | `camp_scene_layout_test.gd:_test_hud_band_contrast_over_bg`(对比度算式,几何五钉定值承载=系统测试宿主 _smoke_camp_hud_band) | | 关卡画面视口跟随 | 关卡画面(选路枢纽) | 停点切换与兑付回图经真实屏流程;读面 `LevelMapViewport.viewport_center_canvas_pos()` | `level_map_viewport_probe.gd:_probe_follow_anchor`;`level_map_viewport_probe.gd:_probe_smooth_scroll_reduced_motion` | | 关卡画面视口平移 | 关卡画面(选路枢纽) | 合成拖拽沿与滚轮沿经 `push_input`(`ProbeUiUtil.push_drag_at()`/`push_wheel_at()`) | `level_map_viewport_probe.gd:_probe_drag_pan`;`level_map_viewport_probe.gd:_probe_wheel_pan`;`level_map_viewport_probe.gd:_probe_clamp_bounds_and_columns`;`level_map_viewport_probe.gd:_probe_drag_no_submit` | | 关卡画面视口指引 | 关卡画面(选路枢纽) | 深图经 `LevelMapScreen.open_choices()` 真实停点 | `level_map_viewport_probe.gd:_probe_guidance_chrome` | diff --git a/reports/iter54-反哺点-2026-11-07.md b/reports/iter54-反哺点-2026-11-07.md deleted file mode 100644 index 363fa90c..00000000 --- a/reports/iter54-反哺点-2026-11-07.md +++ /dev/null @@ -1,20 +0,0 @@ -# 迭代 54 反哺点清单(2026-11-07) - -> 本清单逐卡增量落笔;用户在会话中裁决后由文档批写入 `design/` 并把该条清掉(AGENTS 红线:实现批禁写 `design/`,迭代实现报告与反哺点归 `reports/`)。 - -## 卡 1|QA harness 缺陷与覆盖遗漏收口批——申报:零条 - -卡 1 §6 申报「无关联文档」——A2 为容错修复、B1/B2 为测试驱动面,零设计语义变化。核过面:`design/gdd/systems/排雷循环/排雷玩法.md`(停手语义句 :162/:167 与实装一致)、`design/engineering/test-conventions.md`(真输入管线条文 §2 与实装一致)——两处无需改句。 - -## 卡 2|营地交互修复批——两条 - -1. **`design/engineering/architecture/architecture.md` 呈现层模块表 CampHudBand 行(约 :175)**:现句「顶栏 48px 全宽窄条:钥石余额 badge 唯一呈现」已失真——本批落地后顶栏呈现物=栏体色面(`CAMP_HEADER_BAND`×α0.80 全宽)+钥石徽章(右位顶格)两件。建议改成:栏体与徽章两呈现物的实际形态描述;依据=实装读数(栏体 1280×48 全局矩形、徽章 end.x=栏右缘−12,system_test R5 五钉读数)。实现批禁写该文档,由文档批落文。 -2. **根 `体验验证清单.md` 增一行观测项**:营地顶栏观感(「成一条可辨窄带、徽章落在带内」)——需真人试玩下结论,已在实现报告目检总清单登记;由文档批落进清单正式在册。依据=卡 2 §6 同步面表行。 - -(未列项核对:camp.md §顶栏 与 art-bible §6.2 —— α0.80/栏高 48/色值零改值,按卡 2 §6「未改值不列」不列;HUD框架 §提示与弹层·其三「四处共用同一件同一序」——实装后句码一致,无发现不列;architecture.md :168 D1 HUD 视图单元接口——CampHudBand 仍为信号外发+setter 只读注入形态、新出口为 UiKit 工厂面(工厂单点先例在案),未失真不列。) - -## 卡 3|精英专属池——一条 - -1. **`design/gdd/03-内容规模.md` 第 66 行「精英节点与词缀系统——只预留了字段位」**:精英怪本体已落敌人表精英行(行类 elite+池继承合并附加)——「只预留字段位」的表述落后于实况;建议改成「精英怪本体已落敌人表(行类+池继承附加),精英节点与投放仍未接线」。依据=本批实现(enemy.tres (1,elite,0,goblin_elite) 行+卡 3 对照表 R1–R6 全绿);由文档批落文。 - -(未列项核对:敌人系统.md v1.9——实现与文档零出入(V6 生产表 12 字段逐位+有效池四键精确);数据配置.md 加载期错误类别表——dangling_base 属「悬空引用」既有类别的实例,表述不变,不列。) diff --git a/reports/iter54-实现报告-2026-11-07.md b/reports/iter54-实现报告-2026-11-07.md deleted file mode 100644 index 5c19f3bb..00000000 --- a/reports/iter54-实现报告-2026-11-07.md +++ /dev/null @@ -1,146 +0,0 @@ -# 迭代 54 实现报告(2026-11-07) - -> 三卡:QA harness 缺陷与覆盖遗漏收口批 → 营地交互修复批 → 精英专属池。本报告随各卡末卡增量落笔(卡 1 QA 收口段先行,卡 2/卡 3 段随后补齐),总收口前为完整版。 -> 独立验收审计:已完成,总判定=通过(三卡全过;审计深度卡 1/卡 2=中档、卡 3=高档全量——对照表逐行核对+测试削弱检查删除断言合计恰卡 3 申报 4 条+卡 3 窄复跑自跑 27/27 PASS)。报告已随批后收尾退役,git 历史可考。未阻塞观察两条已迁:①卡 2 T2 摘要提交哈希笔误就地校正(原引 46287043 不可解,实为 af127b15);②覆盖登记件对非 BaseButton 控件(地图画布、bcard)无命中键属结构性局限,归 QA harness 条目 B5 面处置。 - -## 卡 1|QA harness 缺陷与覆盖遗漏收口批——状态:已完成 - -### 各任务卡状态 - -| 任务卡 | 状态 | 摘要 | -|---|---|---| -| T1 A2 关闭容错修复 | 完成 | battle_end_overlay.gd close(:194) 与 _play_celebrate(:331) 两处 `get_meta(&"celebrate_tw", null)` 改 `has_meta` 前置判断,语义不变(有则必杀、无则无事)〔提交 57f3cc75〕 | -| T2 B1 探针定型化停手段 | 完成 | ui_click_probe 新增 `_stoptest_tick` 状态机(镜像 `_locktest_tick` 形态)+`_stoptest_assert_hit`,挖掘期触发窗真点停手钮,断言①覆盖登记停手键在场②相位离开 Active〔提交 816aaae5〕 | -| T3 B1 journey 停手+S4c 8 处转换 | 完成 | journey_player 新增停手行为(每战至多一次,挖掘期确定性触发)+8 处真输入转换+头注方法口句换代〔提交 2f5c734e〕 | -| T4 B2 ui_click_probe 16 处+candidate_rect | 完成 | LevelMapScreen 删 press_candidate 增 candidate_rect(index)->Rect2(命中面与 _candidate_at 同源,全局坐标,越界空 Rect2);ui_click_probe 候选 2+节点继续 2+三选一 10+弃图刷新链 2 全转真输入,既有落点断言逐条原样〔提交 afcfbf37〕 | -| T5 B2 其余 7 探针 11 处 | 完成 | 候选 6+停点 1+调试浮窗 4;shot_probe 头注同步〔提交 22903043〕 | -| T6 B2 非探针层 6 处+死接缝清理 | 完成 | system_test 1 处+reward_overlay_test 5 处真输入;死接缝 11 方法删除(ap_bar_view 2+curio_pick_overlay 4+node_overlay 1+debug_overlay 3,level_map_screen 1 随 T4)〔提交 710df6ce〕 | -| T7 产出物落位 | 完成 | 本报告+反哺点清单+批末选档跑闸(读数见下)+审计入口预约 | - -### 实际对照表(R1–R9,补「结果」格) - -| 行 | 验收测试 | 结果 | -|---|---|---| -| R1 终局结算框关闭动线零引擎报错 | fx_probe+screen_flow_probe 直跑 grep「SCRIPT ERROR」「celebrate_tw」 | 绿——两探针各 exit=0、SCRIPT ERROR 0、celebrate_tw 0(提交 57f3cc75 读数) | -| R2 停手钮真输入命中与落效 | ui_click_probe 直跑(_stoptest_tick 断言①②) | 绿——exit=0、问题=0、覆盖落盘停手键命中 1 次(确定性触发实证;提交 816aaae5 读数) | -| R3 journey 停手+方法口清零 | journey 全线跑批 | 绿(读数判据满足)——fatal 0、上报结构不变(2 条=已知缺陷 A1 双指纹,改前基线同源)、覆盖登记停手键 6 次+停点键在场(结算面继续 6/确认 3)、屏到达 16 类含战斗/终局;exit=1 为 A1 基线态(营地交互修复批承接中,本卡不做动作——卡 1 §5 范围边界) | -| R4 停点链真输入化(ui_click_probe 16 处) | ui_click_probe 直跑+既有落点断言+登记键集不回退 | 绿——exit=0、问题=0、覆盖 43 命中/30 控件较改前 39/28 不回退、新增停点链键(curio 确认选择 2/继续 2)、冒险终局在案选路口点击 9 次 | -| R5 到达型候选+停点(7 探针) | 7 探针逐件孤立直跑 | 绿——headless 五件(ui_struct/layout/ui_probe/t17_defer/ui_tune)exit=0+SCRIPT ERROR 0;窗口化两件(shot 七屏 PNG 齐、fx_shot PASS 演出帧 7 张挖格 3)exit=0 | -| R6 调试浮窗面(4 处) | ui_tune_probe 直跑 | 绿——PASS 全链路(含模拟 N=10 输出与种子三分断言) | -| R7 系统测试宿主候选真输入化 | 系统测试直跑 | 绿——69 项检查 0 失败、三闸过(V3c 阶段真实选路提交在跑批中执行) | -| R8 三选一覆盖层单元真输入化 | 单元与集成套件直跑 | 绿——82 套件 all green、exit=0、0 FAIL(reward_verify 断言在册) | -| R9 死接缝同批清理(5 文件 11 方法) | 全仓 .gd 双模式 grep | 绿——定义清 `func press_(candidate\|continue\|card\|confirm\|refresh\|apply\|reset\simulate)` 与调用清 `.press_(…)` 双零命中 | - -### 卡 1 批末选档跑闸读数(T7) - -`bash tools/run_all_gates.sh --code`(游戏码批选档)=**【验收通过】闸况与基线一致,无新增红**。回执六闸全绿:冒烟测试(smoke_boot.log)=绿/单元与集成测试(unit.log)=绿/系统测试(system_test.log)=绿/场景探针(probe.log)=绿/渲染闸(render.log)=绿/静态扫描(static_scan.log)=绿。改前改后对拍:改前基线=master 40a3ac12 远端 CI run 99 绿;改后=本跑批无新增红(闸况与基线一致)。 - -### 实机目检总清单(卡 1) - -| 目检项 | 登记处 | 义务口径 | -|---|---|---| -| 覆盖面板控件下钻停手键与停点链键在场 | 本表(数据面读数:probe_hits_ui_click.js 停手 1 次、停点链键在案) | 真人检测只登记不阻塞(AGENTS 红线)——登记即完成义务 | - -### 遗留读数义务(卡 1) - -- 无 MC/verifier 义务(本卡零数值零随机面)。 -- 远端 CI 现查读数(合回后):审计与追绿按 process-conventions §1 第 3 条按需现查。 - -### 实现决定记录(卡 1,超白名单事项备案) - -1. **reward_overlay_test.gd 五处行号就地校正**:卡面申报 :60/:64/:65/:66/:76,实查为 :63/:67/:68/:69/:79(漂移 +3,内容与描述全一致)——依卡内 T1 开工核对条款就地校正,未呈报(漂移远小于一屏)。 -2. **ui_click_probe 停手段与 system_test 行号就地校正**:停手触发/驱动 :1041-1045/:1063-1065 → 实查 :1051-1055/:1074-1077;system_test :433 → :440。同上依据。 -3. **排版帧插入**:三选一选卡→确认之间、reward_overlay_test 刷新/确认/继续点击前、journey _drive_curio 卡→确认之间插入 1–2 帧等待——确认钮/继续钮现形当帧容器重排在途,矩形未成形真点必落空。属驱动机制细节(白名单「使能窗等待时长、触发条件的具体写法」同族)。 -4. **ui_tune ⑤ sim 真点的折叠区滚轮通道**:初跑发现 sim 钮真点落空——根因=滚动列表 boot 滚位下钮矩形跨出 ScrollContainer 视口底边(hit 面被裁;emit 路径历史性掩盖)。按 test-conventions §2「折叠区控件先以真输入滚轮滚入可视区再点」落滚轮通道(一档滚入实证后定装),并配 12 档上限+滚入失败 problem 上报(正面效力自检)。⑧ 应用前置重开浮窗(同款机制先例=④ 重开浮窗)。属真输入通道的实现形态(卡片白名单「具体写法」族),随提交留痕。 -5. **候选/bcard 覆盖登记键的结构性缺口**:覆盖登记件自动登记通道=BaseButton pressed+营地自绘物件两源;地图画布与 BCard 非 BaseButton、无 pressed 信号,真输入命中不产键(登记件零改动——卡 1 §13 申报)。候选/弃图确认键的对照表括注预期键与登记件能力不符:效力由既有落点断言承载(R4 判据绑定面=既有落点断言逐条+键集不回退,两者均成立)。弃图确认链在 ui_click_probe 受 is_refresh_ready(RAP≥8)门槛四种子未触发——改前同门槛不可达,链面真输入效力由 journey 既有真点链承载。此为观测面局限申报,非缺陷。 -6. **T2 断言①的登记件读取形态**:`_stoptest_assert_hit` 经 `_recorder._node_keys`/`_recorder._hits` 直读登记件命中表(登记件为探针共用面、卡 1 §13 申报零改动——不新增公开读口,探针面读私有沿现役惯例:ap_bar._btn_stop 同型先例)。 -7. **卡 2 T4.4「等用户发令再走收口」与迭代单合并语义的冲突处置**:卡 2 写卡时为独立批(编入迭代 54 前),其末卡收口语义已被编排段换代为迭代级总收口(iter 技能第 5 步:一次合并、五步登记)。本批按迭代级收口执行,不逐卡等发令;此冲突为编排换代遗留,随本报告呈报。 - -## 卡 2|营地交互修复批——状态:已完成 - -### 各任务卡状态 - -| 任务卡 | 状态 | 摘要 | -|---|---|---| -| T1 开局路径隐藏点收一处 | 完成 | `_start_adventure()` 首句加开始层隐藏(开局唯一出口,契约 1)+删 `_start_adventure_from_menu()` 冗余句;探针大门无断点段追加 R1/R2〔提交 4d9687eb〕 | -| T2 确认弹窗按钮位次镜像 | 完成 | `add_child` 三句次序镜像(确认→次→取消,其余零动——契约 3);新单元套 confirm_dialog_test 入册;探针 R4 位次真点〔提交 af127b15 区段〕 | -| T3 营地顶栏可见栏体 | 完成 | ui_kit 新增 CAMP_HUD_BAND+camp_hud_band_surface(host) 出口(契约 4/5);camp_hud_band 调出口+徽章右对齐容器落座;R5 五钉(系统测试)+R6 对比(单元套)〔提交 1958d329〕 | -| T4 产出物落位 | 完成 | 本报告卡 2 段+反哺点+gdstyle 基线修订(见下)+能力行名实核对 | - -### 实际对照表(R1–R8,补「结果」格) - -| 行 | 验收测试 | 结果 | -|---|---|---| -| R1 大门无断点按「是」后开始层不可见 | ui_click_probe 大门段〔营地交互批 V1〕 | 绿——探针直跑问题=0,断言在跑批中执行(修复前该句恒红判据零命中) | -| R2 开局落节点图选路停点 | ui_click_probe 大门段〔营地交互批 V2〕 | 绿——同批(3 帧口径下 level_screen.visible 断言过) | -| R3 两/三钮形态位次=推进→次→维持 | confirm_dialog_test 两函数 | 绿——直跑 exit=0 七断言全 PASS | -| R4 左位真点即推进 | ui_click_probe R4〔营地交互批 V3〕 | 绿——真点前 consumer=="gate_new" 前置读+child(0) 中心真点+真点后 is_adventure 翻转+consumer 清零,全部在跑批中执行 | -| R5 顶栏栏体几何与徽章落座 | system_test._smoke_camp_hud_band | 绿——76 检查 0 失败;T3.0 前置读数=徽章 min 高 48.0;五钉全过(色面 6e4526cc、铺满 1280×48、IGNORE、首子件、徽章顶格右位 end.x−12) | -| R6 栏体对落位带底色对比 ≥3:1 | camp_scene_layout_test._test_hud_band_contrast_over_bg | 绿——直跑 exit=0,规格侧算式实测 4.29:1(与卡面复核推算一致,顶带均色≈#DEEAE7) | -| R7 回归·件1 未动三条动线 | 既有大门两分支段+篝火段断言 | 绿——探针直跑问题=0(既有断言原样通过) | -| R8 回归·件2 路由与件数断言 | 探针次钮隐藏断言+system_test 三钮计数 | 绿——system_test 76/0(三钮计数断言在册);探针既有次钮断言原样通过 | - -### 卡 2 批末读数 - -- 静态扫描(S13)直跑:首跑出 `ui_kit.gd|quality/max-public-methods = 24(基线登记 23)` 恶化键——卡 2 §13 预申报的例外(用户 11-06 终裁「整件外观封公共件一个具名出口」的直接代价),按申报把 `tools/gdstyle_baseline.txt` 该行 23→24 修订后复跑绿(基线内 7 条、恶化 0)。基线修订的批准依据=卡 2 §13「本条即申报与请求」+U0 批卡。 -- 系统测试 76 检查 0 失败;单元侧 confirm_dialog_test/camp_scene_layout_test 直跑绿;探针直跑问题=0。卡 3 T3.8 的里程碑出口跑闸(--code 全档)覆盖本卡改动面的全档回归。 - -### 实机目检总清单(卡 2) - -| 目检项 | 登记处 | 义务口径 | -|---|---|---| -| 营地顶栏观感——成一条可辨窄带、徽章落在带内 | 本表(渲染闸七屏段营地截图随批产出可对照;卡 2 §1 真人目检项) | 真人检测只登记不阻塞——登记即完成义务 | - -### 遗留读数义务(卡 2) - -- 远端 CI 现查读数(合回后,按需现查)。 - -### 实现决定记录(卡 2 新增条目) - -8. **T2.3「前置重开」步重构为原位 R4**:卡面 T2.3 设计=既有确认真点后重开营地再测 R4;但该流程下 is_adventure 已为真、R4 主证「翻转」恒空转(且 `_on_confirm_declined` 同样清零 consumer,清零判据无判别力)。R4 对照表行的判据绑定面(主证=is_adventure 翻转)优先于任务卡步骤机制——改为真点前 is_adventure=false 的原位确认:既有确认成员点击替换为按钮行 child(0) 坐标真点,翻转成为真判据。既有断言(is_adventure+营地隐藏)原样保留。 -9. **T1.5 `--quick` 闸壳步以探针直跑代证**:改完即测铁规频率口径(轮内不跑闸壳全套含 --quick)下,T1.4 探针直跑即该件最窄确认(同一判据同源读数),未另起 --quick 闸壳跑批。 -10. **T3.0 读数实测 48.0**(卡面 L3 第 5 条警戒项未触发)——顶格落座前提成立,R5⑤ 判据照卡落装。 - -## 卡 3|精英专属池——状态:已完成 - -### 各任务卡状态 - -| 任务卡 | 状态 | 摘要 | -|---|---|---| -| T1 敌人表 schema | 完成 | ROW_KINDS 增 elite+ENCOUNTER_ROW_KINDS 行类门常量+_min_band_row+effective_pool+_validate_pool_entries 提取(pool 文案逐字不变)+_validate_elite_fields/_validate_elite_refs(dangling_base 新类别)+_extra_overlap_errs;新套件 elite_row_test 入册;config_db_test fv7 样本换代〔T1+T2 合并提交〕 | -| T2 跨表纪律+寻址门 | 完成 | cross_validator :194 改读 effective_pool(合并池过纪律);resolver :41 行类门改读 ENCOUNTER_ROW_KINDS(文案保持 {battle, boss}) | -| T3 地精精英落表+存量同步 | 完成 | enemy.tres 新行 (1,elite,0,goblin_elite)(卡面 §2 表值逐字段)+尾批注 provisional 来源行;round_flow 七处读法换代+expect_pools 增键+文案换代;guard 行数 30+键序插行+l1_totals skip elite;shop 还原断言改相对基数〔提交 e538e2cb〕 | -| T4 图鉴导出 | 完成 | compendium_dump 导出行数组 elite 副本写 effective_pool(表内行零改写);gen.py 词表三处〔提交 f4865ad8〕 | -| T5 产出物落位 | 完成 | 本报告卡 3 段+反哺点+能力行名实核对 | - -### 实际对照表(R1–R7,补「结果」格) - -| 行 | 验收测试 | 结果 | -|---|---|---| -| R1 elite 行类合法与字段互锁、引用校验 | elite_row_test._test_elite_validation_rejects〔精英批 V1〕 | 绿——合法夹具零错+十一违例各「含」预期类别(cross_field×7/dangling_base×2/dup_key×1/domain+pool_extra 定位×1);config_db_test fv7 样本换代后直跑绿 | -| R2 有效池=基础池+附加技、基础池取深度带最小行 | _test_effective_pool_merge〔精英批 V2〕 | 绿——深带行在前夹具下 {attack9,lunge1,heavy2}(取首行错误实现必红);battle 行读法等价面 {attack9,lunge1} | -| R3 继承不复制 | _test_base_pool_change_propagates〔精英批 V3〕 | 绿——基础池权重改 7 传到精英;改写返回数组条目后表内行不变 | -| R4 合并池过池构成纪律 | _test_merged_pool_composition〔精英批 V4〕 | 绿——合规精英计数 0;附加第二普攻/第二增益两夹具各计 1 且 message 含 goblin_elite | -| R5 暂不接线:寻址拿不到 elite | _test_elite_unreachable_by_encounter〔精英批 V5〕 | 绿——请求 elite 返回空+诊断含 fatal/request_oob;同夹具 battle/boss 查询合计>0 且零 elite 行 | -| R6 地精精英落表且全表加载零错 | _test_production_goblin_elite〔精英批 V6〕 | 绿——error 级诊断计数 0;行恰 1 条、12 字段逐位、无 unit_count_max/pool 键;有效池 {attack9,lunge1,desperate_guard1,heavy2} | -| R7 存量生产表冒烟随新行同步 | round_flow/guard/shop/roll_multiplier/trigger_cond 五件直跑 | 绿——五件 exit=0 零 SCRIPT ERROR;既有断言原判据照旧(精确键集/行数精确等/键序逐位/注入全量还原),仅扩期望集与读法 | - -### 卡 3 批末读数(T3.8 里程碑出口) - -`bash tools/run_all_gates.sh --code`=**【验收通过】闸况与基线一致,无新增红**(冒烟/单元与集成/系统/场景探针/渲染闸/静态扫描六闸全绿)——卡 3 全改动面(schema+core+enemy.tres+存量测试+图鉴工具)全档回归在案。 - -### 实机目检总清单(卡 3) - -**零项**——理由:精英暂不接线(敌人系统.md:151),无玩家可见面(卡 3 §8 测试方式两分法申报在案)。 - -### 遗留读数义务(卡 3) - -- 精英 EV 重锚与数值终值 → 难度曲线与Boss(Alpha 阶段零读数;本批零 MC——卡 3 §5 申报)。 -- 开战快照改读有效池(敌人系统.md:325 半句)→ 待办清单「战斗节点遭遇编排方式」条目承接(本批无入口可验)。 - -### 实现决定记录(卡 3 新增条目) - -11. **T2.3 夹具的 ogre_chief 行补合规池**:卡面 T2.3 夹具规格未点 boss 行池值——_mk_row 默认池(仅普攻)自身违反「至少一行无条件特殊技」纪律,pool_composition 误红。boss 行补 attack+lunge(自身合规),断言只数精英违规——夹具 mechanics 决策(白名单「夹具助手函数的拆法」族),V4 判据面不变。 -12. **round_flow 七处转换的批次内第 4 处豁免核**:卡面申报「另两处遍历(:571-575、:791-794)有前置过滤」;实查另核卡面未列的 :844(resolve_rowset 结果池读取)——经行类门 resolver elite 行结构性不可达,同豁免逻辑,不改不改判据。全文件 row.pool 直取残留恰 1 处(:574)与卡面申报一致。 -13. **expect_pools 键与文案的完成形态**:卡面 T3.4 定「:623 文案改『三十行』」;实改「三十行十一种池模板」——池模板计数同句失真(精英合并池为第 11 种),一并换代。键插入位置=字典尾(顺序无关,判据面=精确键集比对)。 -14. **S13 基线零新键确认**:enemy_table.gd/config_db_cross_validator.gd/config_db_resolver.gd 三件静态扫描零新增键(卡 3 §13 预算全数守住——validate() 局部变量 10/10 零新增、各私有函数分支在预算内),--code 跑闸静态扫描段绿为凭。 diff --git a/reports/iter54-验收审计-2026-11-07.md b/reports/iter54-验收审计-2026-11-07.md deleted file mode 100644 index 0b5de566..00000000 --- a/reports/iter54-验收审计-2026-11-07.md +++ /dev/null @@ -1,169 +0,0 @@ -# 迭代 54 独立验收审计报告(2026-11-07) - -> **审计者身份**:独立验收审计子代理——未参与本批实现的只读会话,全量凭据自取(diff 逐笔自读、grep 自跑、窄复跑自跑),未采信任何报告自述的「已全绿」。 -> **对象**:分支 `iter54`(工作区 `D:\code\g-plan2-iter54`),基底=master `a2e500a4`,三笔卡提交:`96123978`=卡 1(QA 缺陷收口批)、`4c424af3`=卡 2(营地交互修复批)、`f9c9caf5`=卡 3(精英专属池)。原史(逐 T 步提交与当轮跑批读数)在 `backup/iter54-20261107-030512` 与 `iter54-premerge-backup` 两分支在案。 -> **审计输入**:三张需求卡片(reports/需求卡片-QA缺陷收口批-2026-11-06.md/需求卡片-营地交互修复批-2026-11-05.md/需求卡片-精英专属池-2026-11-06.md)+实现报告+反哺点+三笔提交完整 diff。 -> **执行证据口径(申报在案)**:卡 1/卡 2 为中档审计,最窄复跑省略——执行证据=逐 T 步提交信息内的当轮跑批读数(`iter54-premerge-backup` 在案,T1–T7 每步读数齐全)+合回后远端 CI 现查(合回落地后按 process-conventions §1 第 3 条现查)。卡 3 为高档审计,窄复跑由审计者本机自跑(§3.5 原样读数)。 - ---- - -## 卡 1|QA harness 缺陷与覆盖遗漏收口批——判定:通过 - -### 1.0 申报验收档与实际执行深度 - -卡面申报验收档=中。实际执行:对照表 R1–R9 全量逐行核对+测试削弱检查(diff 删除行全扫)+内部字段直查受控例外核对逐条+死接缝删除判据(双模式 grep)审计者自跑。窄复跑按中档口径省略(证据口径见头部申报)。 - -### 1.1 对照表逐行核对(R1–R9) - -| 行 | 核对结论 | 证据 | -|---|---|---| -| R1 终局结算框关闭动线零引擎报错 | 通过 | close() 与 _play_celebrate() 两处均改 `has_meta` 前置判断(battle_end_overlay.gd,diff 确认 :191–198/:329–336 两处,语义=有则必杀、无则跳过);验收形态按卡面自陈=grep 读数(「该缺陷唯一提交面=报错打印本体」),当轮读数〔T1 提交 57f3cc75〕=fx_probe/screen_flow_probe 各 exit=0、SCRIPT ERROR 0、celebrate_tw 0 | -| R2 停手钮真输入命中与落效 | 通过 | `_stoptest_tick`+`_stoptest_assert_hit` 在案(ui_click_probe.gd:1172–1236),断言①停手键命中登记、②相位离开 Active、120 帧超时红、终局竞态静默弃测守卫,尾缀〔QA收口 V2〕grep 命中 2 处;驱动=`_click_stop()`(`ap_bar._btn_stop` 真钮 push_input);当轮读数〔T2 提交 816aaae5〕=ui_click_probe exit=0、问题=0、停手键命中 1 次 | -| R3 journey 停手+方法口清零 | 通过(候选键一项按申报例外记) | journey_player 停手行为(每战至多一次,Active+停手钮使能+本轮已挖 ≥1+盘面有挖)+8 处方法口转换逐处核对在 diff(:380→node_overlay._btn 真点、:441→candidate_rect(0) 矩形中心、:449/:451/:452/:454/:455/:457→curio 真钮/bcard 矩形中心);头注「方法口已清零」换代在案。当轮读数〔T3 提交 67f16cc2〕=fatal 0、停手键命中 6 次、停点键在场、屏到达 16 类含战斗/终局、exit=1 为已知缺陷 A1 基线态(卡 1 §5 明示不收件,卡 2 承接)。「候选键在场」未产出——登记件登记通道=BaseButton pressed+营地自绘物件两源,地图画布与 BCard 非 BaseButton(结构性不可产出),实现报告决定记录 5 申报为观测面局限;效力承载面=屏到达 16 类+段间推进(当轮在跑批执行)。审计认定:判据字面一项偏差已申报且有替代效力证据,不构成缺漏 | -| R4 停点链真输入化(16 处) | 通过 | 逐处清点 diff:候选 2(:426/:536→push_click_at(candidate_rect))+节点继续 2(:448/:656→push_click(node_overlay._btn))+三选一 10(:473/:475/:476/:478/:479/:481/:649/:651/:652/:654→bcard 矩形中心/真钮)+弃图刷新链 2(:972→`_btn_refresh`、:975→`_confirm_row` 内 Button 子件)=16,全部经 ProbeUiUtil;既有落点断言删除行全扫=0 条。当轮读数〔T4 提交 2067461f〕=exit=0、问题=0、覆盖 43 命中/30 控件较改前 39/28 不回退、新增停点链键。弃图确认链四种子未触发(is_refresh_ready RAP≥8 门槛,改前同不可达)——申报在案,效力由 journey 真点链承载 | -| R5 到达型候选+停点(7 探针 11 处) | 通过 | 7 件 diff 逐件核对:fx_shot_probe:47/layout_probe:32/shot_probe:147/ui_probe:83/t17_defer_probe:39/ui_tune_probe:143(原 :109 行号就地校正)→ push_click_at(candidate_rect(0).get_center());ui_struct_probe:275(原 :257)→ push_click(node_overlay._btn);shot_probe:9 头注同步。当轮读数〔T5 提交 46493f73〕=headless 五件 exit=0+SCRIPT ERROR 0,窗口化两件 exit=0 | -| R6 调试浮窗面(4 处) | 通过 | ui_tune_probe:③应用→find_button 真点、④重置→find_button 真点、⑤模拟→`_sim_btn` 真点(折叠区滚轮滚入通道=test-conventions §2 现役条文,12 档上限+失败 problem 上报正面效力自检)、⑧应用→前置重开+真点=4 处全转真输入。当轮读数〔T5〕=ui_tune PASS 全链路(含 N=10 模拟输出与种子三分断言) | -| R7 系统测试宿主候选真输入化 | 通过 | system_test.gd:440(原 :433)→ push_click_at(candidate_rect(0).get_center()),`const ProbeUiUtil := preload("res://probe/probe_ui_util.gd")` 复用单点;当轮读数〔T6 提交 97d6b0a5〕=69 检查 0 失败三闸过(V3c 阶段真实选路提交在跑批中执行) | -| R8 三选一覆盖层单元真输入化(5 处) | 通过 | reward_overlay_test.gd 刷新/首卡/次卡/确认/继续 5 处真输入(bcard 矩形中心+真钮),断言语义逐位保持(diff 确认仅驱动行与消息文案换代,判定表达式零改);经 preload 复用 ProbeUiUtil。当轮读数〔T6〕=82 套件 all green、exit=0、0 FAIL | -| R9 死接缝同批清理(5 文件 11 方法) | 通过 | diff 确认删除:ap_bar_view 2+curio_pick_overlay 4+node_overlay 1+debug_overlay 3+level_map_screen 1=11。**审计者自跑双模式 grep**:定义清 `func press_(candidate\|continue\|card\|confirm\|refresh\|apply\|reset\|simulate)` 与调用清 `\.press_(…)`(--include=*.gd,全仓)双双零命中 | - -尾缀 grep 口径说明:〔QA收口 V2〕在码 2 处(T2 新断言的唯一在码尾缀);V1(grep 读数)、V3(journey 跑批读数)、V9(grep 判据)按卡面对照表自陈为读数型判据、无在码断言载体;V4–V8 验收载体=既有断言保持+当轮直跑读数(卡面未为转换行立新尾缀)。与卡面 §11 白名单「尾缀编号分配」一致,无缺漏。 - -### 1.2 测试削弱检查 - -- 三笔提交 diff 删除行全扫(`^-` 行筛 `_problems.append`/`Kit.check`/`check(`):卡 1 删除断言行=**0 条**。 -- 允许删除面(只验证被删 press_* 死接缝的护栏):实际无此类护栏被删——死接缝方法体内无断言。 -- 驱动行替换未触判定表达式;reward_overlay_test 仅消息文案「press_refresh 未外发」→「真点刷新未外发」换代,判定 `refreshed.size() == 1` 原样。 -- ui_click_probe 主循环冻结条件由 `_locktest_state != 1` 扩为 `_locktest_state != 1 and _stoptest_state != 1`——新增冻结窗,非弱化。 -- 判据不放宽面核对:无阈值改动、无断言删除、无跳过逻辑新增。 - -### 1.3 例外核对(内部字段直查受控例外逐条) - -- 产品码私取新增=0(A2 为视图内部容错;candidate_rect 为卡面 §13 申报的唯一新公开面,命中面与 `_candidate_at` 同源——审计比对 level_map_screen.gd:452 与 :478 的半宽常量 `NODE_HALF + Vector2(HIT_PAD, HIT_PAD)` 逐字节一致)。 -- 探针/测试面私有直读逐条:`ap_bar._btn_stop`/`_btn_refresh`/`_confirm_row`、`node_overlay._btn`、curio `_bcards`/`_confirm_btn`/`_continue_btn`、`debug_overlay._sim_btn`、登记件 `_recorder._node_keys`/`_hits`(决定记录 6 申报)——全部属探针族现役惯例(ui_click_probe 既有 `ap_bar._btn_stop` 同型先例),封装扫描件射程不含探针(presentation_encapsulation_sweep_test 只套五个 flow 件)。 -- tests 面合成输入件检查:game/tests 全目录 grep `InputEvent`=**零命中**;system_test 与 reward_overlay_test 均经 preload 复用 ProbeUiUtil(禁第二份合成输入件契约成立)。probe/sim 面持 push_input 的文件(ui_input_probe、screen_flow_probe 等)全部为改前既有件,本批零新增。 -- 改动面越界检查:卡 1 提交触面 17 文件=卡面 §7 结构图逐项+产出物 2 件,零越申报面。 - ---- - -## 卡 2|营地交互修复批——判定:通过 - -### 2.0 申报验收档与实际执行深度 - -卡面申报验收档=中。实际执行:对照表 R1–R8 全量逐行核对+测试削弱检查+允许改动 0 条既有断言核对+判据形态核对+UiKit 出口形参核对。窄复跑按中档口径省略(证据口径见头部申报)。 - -### 2.1 对照表逐行核对(R1–R8) - -| 行 | 核对结论 | 证据 | -|---|---|---| -| R1 大门无断点按「是」后开始层不可见 | 通过 | `_start_adventure()` 首句加 `ui.screens.start_overlay.visible = false`(main.gd:293,在 `ui.flow.close` 之前——契约 1 落点);`_start_adventure_from_menu()` 冗余句删除(:194 注释换代)。探针 R1 断言〔营地交互批 V1〕在案(ui_click_probe 大门段),真实入口=大门命中区真点→R4 推进钮真点→同链断言。当轮读数〔T1 提交 bf8d30c1〕=探针 exit=0、问题=0(修复前该句恒红判据零命中) | -| R2 开局落节点图选路停点 | 通过 | R2 断言〔营地交互批 V2〕(level_screen.visible)与既有 is_adventure 断言同批在案;await 1 帧→3 帧帧口径落实(T1 提交信息记「停点成形最小帧数实测=3 帧内成形」)。判据绑定面按卡面 R2 自陈=开局终态在位断言,特有提交面由 R1 承载——两行同批缺一即红结构保持 | -| R3 两/三钮形态位次=推进→次→维持 | 通过 | confirm_dialog.gd 三句 `add_child` 次序镜像为 确认→次→取消,对象创建、三句 connect、成员声明、open()/open_three() 签名零改动(diff 确认,契约 3);新套 confirm_dialog_test.gd=7 断言(双钮 3+三钮 4),判据=公开子节点序+Button 公开 text,零私有直读,双钮形态 child(2) 非 child(1) 硬知识与非空前置(子节点数=3)在案;入册 run_all.gd(+1 行)。当轮读数〔T2 提交 af127b15〕=直跑 exit=0 七断言全 PASS | -| R4 左位真点即推进 | 通过 | 探针 R4〔营地交互批 V3〕:真点前 `_confirm_consumer == "gate_new"` 前置读(探针既有直读先例)、按钮行 child(0) 全局矩形中心 push_click_at(非行矩形左位——卡面轮次 4 硬伤修正的落法)、真点后 is_adventure 翻转+consumer 清零。T2.3「前置重开」→「原位 R4」重构=实现报告决定记录 8 申报(主证绑定翻转才有判别力),既有确认断言原样保留。当轮读数〔T2〕=R4 在跑批执行且通过 | -| R5 顶栏栏体几何与徽章落座 | 通过 | `_smoke_camp_hud_band()` 接进 `_split_tail()` await 链(system_test.gd:47,非 _initialize——卡面 T3.4 硬伤修正落法);五钉:①`to_html(true) == "6e4526cc"`(禁浮点分量直等判据形态成立,全文件无 `.a == 0.80` 型断言)②铺满(栏体矩形对顶栏矩形等值+高 48)③IGNORE④栏体为第一子件⑤徽章顶格(y 对齐栏顶)+右位(end.x=栏右缘−12),几何容差 0.51。T3.0 前置读数=徽章 min 高实测 48.0(L3 第 5 条未触发,决定记录 10)。当轮读数〔T3 提交 8f2eab7c〕=76 检查 0 失败 | -| R6 栏体对落位带底色对比 ≥3:1 | 通过 | `_test_hud_band_contrast_over_bg()`:规格侧算式——测试内写死 `#6E4526`/α0.80(Color(0x6e/255.0, …) 字面构造),**未把视图件 color 喂进算式**(oracle 镜像禁令成立);带高取 `camp_scene_layout_table.gd` 数据出口;双层全像素扫描+扫描面非空前置;WCAG ≥3.0。当轮读数〔T3〕=实测 4.29:1,与卡面复核推算一致 | -| R7 回归·件 1 未动三条动线 | 通过 | 既有大门两分支段与篝火段断言零改写(diff 确认无删除行);三处未改动隐藏点核在位:`_resume_from_menu()`(main.gd:246)、boot 默认(:137)、其余 11 处自管点全部原样(grep 全列与卡面 13 处清单一致)。当轮读数〔T1〕=既有断言原样通过 | -| R8 回归·件 2 路由与件数断言 | 通过 | 探针次钮隐藏断言(ui_click_probe.gd:739,〔营地图批 V3〕原文原样)与 system_test 三钮计数断言(:193–201,V2d 三钮在位+渲染面可见钮计数==3)均未被本批触碰(两笔 diff 删除行全扫=0)。位次改动后二者仍绿=契约 3 未被违。当轮读数=探针问题=0、系统测试 76/0 | - -### 2.2 测试削弱检查 - -- diff 删除断言行=**0 条**(三笔提交中卡 2 段全扫)。 -- camp_scene_layout_test 入口重构(单 quit 迁至 `_run_all` 统一收尾):断言集零增删,早退路径从 quit 改 return 后仍会被 `_run_all` 收尾 quit 接住,无静默跳过——非削弱。 -- 允许改动 0 条既有断言:成立。 - -### 2.3 例外与申报面核对 - -- 契约 1:开局隐藏点唯一(`_start_adventure()`),续玩唯一(`_resume_from_menu()`),禁改的 13 处自管点逐一 grep 在位,`camp_shop_presenter.gd:85` 语义句未动(契约 2)。 -- 契约 4:`camp_hud_band_surface(host)` 形参只有 host——色值、α、铺满、IGNORE、挂载、返回句柄六事全在体内(ui_kit.gd:666–676 审读);无 color/pass_input 形参(开了即违——未开);盘上三处同形铺面(ui_assembler.gd overlay_bg、ui_kit `_modal_dim`、page_shell 底板)零触碰(不在 diff 文件清单)。 -- 契约 5:IGNORE 在出口内写死;camp_hud_band.gd 内右对齐容器自身 IGNORE 同批落(漏一处即顶排点不动的双点纪律成立);本文件内 `ColorRect.new()` grep=零命中。 -- S13 基线修订:ui_kit max-public-methods 23→24——卡 2 §13 预申报的例外(「本条即申报与请求」+U0 批卡),diff 仅此一行;非越权改基线。 -- 改动面越界检查:提交触面=卡面 §7 结构图 9 件+run_all 入册+gdstyle_baseline+产出物 2 件,零越申报面;design/ 与两份根流程清单零触碰(契约 6)。 -- 能力行名实核对:README:158/:159 两行与实际落地(confirm_dialog_test 两函数、`_smoke_camp_hud_band`、`_test_hud_band_contrast_over_bg`)逐字相符。 - ---- - -## 卡 3|精英专属池——判定:通过(高档全量) - -### 3.0 申报验收档与实际执行深度 - -卡面申报验收档=高。实际执行:①对照表 R1–R7 逐行核对;②判据绑定面抽查;③测试削弱检查(含 4 条申报测试改动逐条 diff 核对);④直查例外核对+契约核四条;⑤窄复跑抽查——审计者自跑两件;⑥oracle 出处核对抽查 5 条。 - -### 3.1 对照表逐行核对(R1–R7) - -| 行 | 核对结论 | 证据 | -|---|---|---| -| R1 elite 行类合法与字段互锁、引用校验 | 通过 | elite_row_test `_test_elite_validation_rejects`=合法夹具零错+11 个违例夹具(①删 base_ref ②同名 ③pool_extra 空 ④删键 ⑤带 pool ⑥battle 带 base_ref ⑦battle 带 pool_extra ⑧悬空 ⑨指向 elite ⑩重叠 ⑪权重 0)各「含」预期类别,与卡面 T1.11 逐条对应;`_validate_elite_fields`/`_validate_elite_refs`/`dangling_base` 实装与 T1.7/T1.9 一致。config_db_test fv7 样本 miniboss 换代在 diff(申报第 1 条) | -| R2 有效池=基础池+附加技、基础池取深度带最小行 | 通过 | `_test_effective_pool_merge`:夹具深带行(band 3, attack5/charge2)在前、浅带行(band 0, attack9/lunge1)在后——取首行的错误实现必红;期望 {attack9,lunge1,heavy2}+size 3;battle 行读法等价面 {attack9,lunge1}。实装 `_min_band_row`(遍历取 band 最小)与 `effective_pool`(基础池条目+pool_extra 条目,均 duplicate)与 T1.3/T1.4 一致 | -| R3 继承不复制 | 通过 | `_test_base_pool_change_propagates`:基础行 attack 改 7 后再查=7(按需现算);改写首次返回数组条目为 99 后表内行仍=7(duplicate 隔离)。enemy_table.gd 类变量 grep=仍仅 `rows`+`_resolver` 两个,**零新增类变量**(契约 1) | -| R4 合并池过池构成纪律 | 通过 | `_test_merged_pool_composition`:合规精英 pool_composition=0;附加第二普攻/第二增益两夹具各=1 且 message 含 goblin_elite。boss 行补合规池=决定记录 11 申报(夹具 mechanics,`_mk_row` 默认单普攻池自身违纪律会误红);跨表件 `:194` 改读 `enemy_table.effective_pool(row)` 单行 diff(T2.1) | -| R5 暂不接线 | 通过 | `_test_elite_unreachable_by_encounter`:夹具 resolver 敌行回调返回含 elite 行的三行行集;①`resolve_enemy_rowset(1, 0, "elite")` 返回空+诊断含 fatal/request_oob——判据绑行类门改动(只改枚举不改为门时该请求会返回 goblin_elite);②battle/boss 查询合计>0 且零 elite 行(非空前置内嵌判据)。resolver :41 改读 `ENCOUNTER_ROW_KINDS`、文案保持「row_kind 域 {battle, boss}」逐字(T2.2);该常量全仓 grep 仅 resolver 一处消费(卡面 §12 单点申报成立);`unit_container.gd`/`battle_orchestrator.gd`/`level_runner.gd`/`level_table.gd` 零触碰(契约 2) | -| R6 地精精英落表且全表加载零错 | 通过 | `_test_production_goblin_elite`:生产表 load_tables(true) 后 error 级诊断=0;行恰 1 条;12 字段逐位断言表+无 unit_count_max/无 pool 键+有效池四键精确。enemy.tres diff:行插 (1,boss,6,ogre_chief) 之后、(2,battle,0,bugbear) 之前(T3.1),15 键中 12 判据字段与卡面 §2 表逐值一致(hp 20/atk 2/1/3/armor 2/light/unit 1/base_ref goblin/pool_extra heavy 2),attack_type normal 由 roll_multiplier_test 既有「全行 normal」断言覆盖 | -| R7 存量冒烟随新行同步、判据不放宽 | 通过 | 逐条核对见 3.3——行数 29→30 精确等、键序逐位插行、池模板精确键集比对、曲线护栏阈 ≤2.5 未动、注入还原改相对基数(加强);五件存量套件当轮读数〔T3 提交 75a4afe2〕=exit=0 零 SCRIPT ERROR | - -### 3.2 判据绑定面抽查 - -- V5 绑定改动特有面:判据①在「只做 T1.1 不做 T2.2」的反事实下必红(elite 请求会返回行而非空)——断言钉在行类门改动本身,非改动前后双绿的常真断言。审计按卡面反事实推演复核成立。 -- V2 绑定取带语义:夹具行序(深带在前)使「取首行」实现必红——钉在 `_min_band_row` 的取最小带逻辑,非常真。 -- V3 绑定零缓存:改表后再查+改写返回不回灌,两钉分别排除缓存实现与引用泄漏——绑契约 1。 -- V4 绑定合并池:单看基础行或单看附加技都不违规,唯合并后违规——钉在「纪律校验对象=合并池」。 - -### 3.3 测试改动申报 4 条逐条 diff 核对(无越面改判) - -| 申报条 | diff 实况 | 结论 | -|---|---|---| -| 1. config_db_test fv7 样本 elite→miniboss+文案 {battle, boss, elite} | 恰两处(样本行+断言消息),判定逻辑(domain+含 "row_kind")零改 | 相符 | -| 2. round_flow 七处 row.pool→effective_pool+expect_pools 增键+文案 | diff 恰 7 处读法换代(:530/:541/:560/:621/:627/:642/:657 区段)+expect_pools 增 `"1_elite_0_goblin_elite"` 键+文案「二十九行十种」→「三十行十一种」(十种→十一种为决定记录 13 申报的完成形态,池模板计数同句失真一并换代);期望字典判定 `got != expect_pools[rk]` 零改 | 相符 | -| 3. guard 行数 30+键序插行+l1_totals skip elite | 行数断言 `== 30` 精确等(未放宽为 ≥);expect_keys 在 `"1|boss|6|ogre_chief"` 后恰插 `"1|elite|0|goblin_elite"`;`:389` 循环首加 elite 跳过(两行);头注与 print 文案同步 | 相符 | -| 4. level_shop 还原断言改相对基数 | 注入前记 `base_n`,断言 `== base_n`,文案去写死数——卡面自陈「属加强」 | 相符(加强) | - -三笔提交删除断言行全扫:恰上述 4 条申报改判的旧行,无第 5 条。**无越面改判。** - -### 3.4 契约核(四条全过)与例外核对 - -- 契约 1 继承不复制:enemy_table.gd 类变量 grep=2 个(rows/_resolver),零新增;effective_pool 每次现算、返回条目 duplicate、零缓存零写回(V3 断言实证)。 -- 契约 3 算法唯一落点:合并算法 grep `pool_extra` 全仓仅 enemy_table.gd/elite_row_test/round_flow/compendium_dump 四处(后三处为消费/测试/导出面,非第二份算法);权重上限 9999 在 schemas 面仅 enemy_table.gd:171 一处(meta_tree 的 9999 为价格域既有件,非池权重)。 -- 契约 4 既有文案逐字不变:`_validate_row_pool` 四条报错文案经 field 参数化后对 field="pool" 渲染逐字节等值(「%s pool 条目非字典」「%s pool 条目 skill_id 空」「%s pool 内 skill_id 重复」「%s pool 权重越域 (0,9999]」——diff 左右对比确认);既有错误类别零改名,新增类别仅 dangling_base;`:88` row_kind 文案域换代=卡面 T1.1 申报项。 -- 直查例外:产品码零私取新增(新增公开面=effective_pool+ENCOUNTER_ROW_KINDS,均卡面 §12 申报);elite_row_test 全部经公开入口(validate/effective_pool/validate_skill_pool_links/resolve_enemy_rowset/load_tables)进出,零私有直读。 -- 残留读法豁免核:round_flow 残留 `row.pool` 恰 3 处(:574 种带过滤 row_kind=="battle"、:795 species 名单 ["goblin","bugbear","ogre_chief"] 精确等值不含 goblin_elite、:846 resolver battle 查询结构性不可达)——与卡面 §3.4+决定记录 12 一致,豁免成立。 -- 改动面越界检查:提交触面=卡面 §7 结构图 12 件+产出物,零越申报面;design/ 零触碰。 - -### 3.5 窄复跑读数(审计者本机自跑,2026-11-07) - -`Godot_v4.7.2-stable_win64_console.exe --headless --path . --script res://tests/unit/data_config/elite_row_test.gd`: - -- 退出码=**0**;`[PASS]` 计数=**27/27**(V1 合法夹具+①–⑪ 共 12、V2×2、V3×2、V4×3、V5×2、V6×6);`[FAIL]` 与 `SCRIPT ERROR` 扫描=零行。原样尾行: - `[elite_row_test] PASS — 精英行校验/有效池/继承不复制/合并池纪律/暂不接线/生产表落行 全过` - V6 关键 PASS 行原样:`生产表加载 error 级诊断计数=0(实得 0)〔精英批 V6〕`/`行值 12 字段逐位相等(失配项 无)〔精英批 V6〕`/`有效池字典={attack9,lunge1,desperate_guard1,heavy2}(实得 { "attack": 9, "lunge": 1, "desperate_guard": 1, "heavy": 2 })〔精英批 V6〕` -- 同目录 `config_db_test.gd` 抽跑:退出码=**0**,尾行 `[config_db_test] all green (29 checks)`(fv7 换代样本所在套件全绿)。 -- (退出时 ObjectDB 泄漏警告为引擎常规退出清场噪音,与本套件断言面无关,headless 直跑既有形态。) - -### 3.6 oracle 出处核对抽查(5 条,均非 oracle 镜像) - -| 断言 | oracle 注记指向 | 独立推导核对 | -|---|---|---| -| V1 十一违例 | 敌人系统.md:325 拒绝清单 | :325 逐句可独立推出 11 个违例面:缺基础引用/缺附加技/悬空/指向 elite/同名/附加重复/合并池违纪/elite 写池/非 elite 带两键——①–⑦⑨⑩ 与之一一对应;⑪ 权重 0 由 :283「weight ∈ (0, 9999]」推出。**可独立写出,通过** | -| V2 合并池 | 敌人系统.md:149 | :149「基础池取自同关、战斗行类、该基础敌种深度带最小的那一行的池模板」——期望值 {attack9,lunge1,heavy2}=band 0 行池+附加,规格句独立可推;夹具反事实(取首行必红)为审计加验。**通过** | -| V3 传到精英 | 敌人系统.md:149「继承不复制:基础池调参自动传到精英」 | 改权重 7 期望读 7 直由该句推出。**通过** | -| V4 合并池纪律 | 敌人系统.md:150「校验的对象是合并后的池」 | 「附加第二普攻→违规」唯在合并口径下成立(基础行单独合规、附加技单独合法),规格句独立可推。**通过** | -| V6 十二字段 | 敌人系统.md:147+卡 3 §2 表 | :147 出「精英=敌人表行类为 elite 的独立一行」的结构面;行值出处=卡面 §2(2026-11-06 用户点头草案 v0,GDD 明示不登记行值)——12 字段值(hp 20/atk 2/1/3/armor_class 2/armor_type light/unit_count 1/base_ref goblin/display_name「精英·地精」等)与卡 §2 表逐值一致,预期值独立于实现存在(需求合同面)。**通过,非镜像** | - -抽查结论:5 条抽查均能由注记指向的规格句(或卡面用户已裁行值表)独立写出预期值,未发现「预期值只在实现里有的」oracle 镜像。 - -### 3.7 报告引用瑕疵(不阻塞项) - -实现报告卡 3 T3 摘要引用提交 `e538e2cb`/`f4865ad8`、卡 1 各 T 摘要引用 57f3cc75 等 10 个哈希均于 `iter54-premerge-backup` 分支在案可解;唯卡 2 T2 摘要引用「提交 46287043 区段」全库(含 reflog 与 dangling)不可解——该步实际提交=af127b15(premerge-backup),已折叠进重塑提交 4c424af3。属报告引用笔误,改动本身已由本审计在 diff 与跑批读数双面核实,不影响判定。 - ---- - -## 总判定:通过(三卡全过) - -| 卡 | 申报档 | 判定 | 关键依据 | -|---|---|---|---| -| 卡 1 QA 缺陷收口批 | 中 | 通过 | R1–R9 全量核对通过;死接缝双模式 grep 审计自跑双零;削弱检查零删除断言;41 处转换全经 ProbeUiUtil 单点;候选键观测面局限已申报且效力有替代承载 | -| 卡 2 营地交互修复批 | 中 | 通过 | R1–R8 全量核对通过;允许改动 0 条既有断言成立(次钮隐藏/三钮计数原样且绿);to_html 判据形态合规;出口形参仅 host;S13 基线修订在预申报通道内 | -| 卡 3 精英专属池 | 高 | 通过 | R1–R7 全量核对通过;窄复跑自跑 27/27 PASS+config_db_test all green;4 条申报测试改动与 diff 逐条相符无越面;四条契约全过;oracle 抽查 5 条均非镜像 | - -- 测试削弱总核:三笔提交删除断言行合计恰卡 3 申报 4 条,其余零削弱;禁变异类测试与撤销类取证——三笔 diff 内未发现人为制造红或回退取证的形态。 -- 最窄复跑省略(中档卡)的执行证据口径=批内逐 T 提交读数(`iter54-premerge-backup` 每步在案)+合回后远端 CI 现查;卡 3 高档窄复跑由审计者自跑实证。 -- 遗留义务核对:真人目检两项(覆盖面板下钻/顶栏观感)已登记实现报告(登记即了结义务);「开战快照拿到合并后池」半句与精英 EV 重锚的移交去向(待办清单「战斗节点遭遇编排方式」/难度曲线与Boss)在卡 3 §5 与实现报告遗留义务节闭合;反哺点三条(architecture CampHudBand 行/体验验证清单一行/03-内容规模.md:66)落点明确待用户裁决。 -- 未阻塞观察两条(供后续批次参考,不构成本批缺漏):①上节 3.7 报告哈希引用笔误一处;②卡 1 R3/R4 覆盖登记件对非 BaseButton 控件(地图画布、bcard)无命中键为登记件结构性局限——若日后需要该面命中证据,归「控件级零命中缺口」B5 既有条目处置,非本批义务。 diff --git a/reports/复核-精英专属池-2026-11-06.md b/reports/复核-精英专属池-2026-11-06.md deleted file mode 100644 index 21dbead2..00000000 --- a/reports/复核-精英专属池-2026-11-06.md +++ /dev/null @@ -1,37 +0,0 @@ -# 复核报告 · 精英专属池需求卡片(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` | diff --git a/reports/复核-营地交互修复批-2026-11-05.md b/reports/复核-营地交互修复批-2026-11-05.md deleted file mode 100644 index e4632a3f..00000000 --- a/reports/复核-营地交互修复批-2026-11-05.md +++ /dev/null @@ -1,109 +0,0 @@ -# 复核报告 · 营地交互修复批需求卡片(2026-11-05) - -> 被复核对象:`reports/需求卡片-营地交互修复批-2026-11-05.md`(v1.0 成文态) -> 复核者:未参与撰写的只读子代理(独立会话,禁写文件、禁跑闸、禁运行游戏测试),任务=对卡内每一处行号、契约、判据逐条开火 -> 复核轮次:1(第 16 节逐条登记去向与处置;本报告留发现原文与依据索引) -> 复核对象工作副本:`D:/code/g-plan2-camp-interact`(分支 camp-interact-20261105) - -## 复核者总判原文(摘录) - -> 按现状不能进实现段。缺四块闭合:①契约1 收窄措辞(否则实现首帧即自触 L3);②R3/R4 的按钮行句柄定义+§12 受控例外改判(否则判据落不了码);③T3.1 的 `UiAssembler` 引用形态+T3.2 内缩实现与 R5 的 x 向判据(否则 12px 无机制、断言可假绿);④R6 呈色输入来源改绑视图实件(否则撞 §8.7 第 5 条判红)。另有 6 处纯事实订正可自判直改。T 卡估时合计 0.25+0.5+0.75+0.5=2.0 与「≈1.75–2.0」自洽;四处消费方与 HUD框架:90 语义映射核过无冲突。 - -## 发现与依据索引(22 条) - -| # | 卡内位置 | 发现 | 复核者给的依据 | 去向 | 写卡段处置 | -|---|---|---|---|---|---| -| 1 | §4 契约1 | 「隐藏点只许两处」按字面过宽,仓库另有 5 处以上 | `camp_shop_presenter.gd:43`、`main_overlay_flow.gd:8/41/95`、`main_debug_flow.gd:88` | 退回上游(复核者判) | 改自判:契约1 收窄为「限开局/续玩路径」,12 处显隐点逐条列名。定名不采纳——卡内措辞问题,非规范冲突 | -| 2 | §3.1 | `_start_adventure()` 行号段错(写 311) | `main.gd:308`=`return`,`:311`=下一函数声明 | 自判 | 改 292-308 | -| 3 | §9 T1.1 | 失败分支的开始层终态变化未申报 | `main.gd:306-307` `fatal_screen` | 补写 | §3.1 补终态申报 | -| 4 | §8 R2/§9 T1.4 | 段内 await 1 帧不足以让选路停点成形 | `ui_click_probe.gd:703`;先例 `screen_flow_probe.gd:186-192` 用 `_frames(3)` | 补写 | T1.4 补帧口径+实测最小帧数入实现报告 | -| 5 | §8 R3 | `btn_row` 是局部变量,判据无法写 | `confirm_dialog.gd:27`(成员仅 `:13-16`) | 补写(阻塞) | T2.1 升成员 `_btn_row`;R3 按 test-conventions §8.2 受控例外申报 | -| 6 | §12 | 自称不直取私有,实际 R3/R4 直取 | `confirm_dialog.gd` 成员表;`main._confirm_consumer` | 自判 | 改为受控例外口径,不再谎称 | -| 7 | §9 T2.3 | `:702` 真点已消耗 `gate_new`,R4 无左位可点 | 段结构 `ui_click_probe.gd:684-705`;`main.gd:215` 置空 | 补写 | T2.3 补前置重开步与坐标取法 | -| 8 | §10 L1 | `:679` 引用定性错;直发面在 `:697`;归属应系 §8.3 而非契约7 | 复核者回读 | 自判 | **部分不采信**:`:679` 经写卡段回读确为段头注「大门两分支断言段」,断点注入起 `:706`;直发行号实为 `:696`(复核者写 697 亦偏);§8.3 归属采纳。附带自查纠正 R8 的次钮断言行 `:696`→`:694` | -| 9 | §9 T3.1/§12 | `UiAssembler` 无 `class_name`,`views/` 零引用先例,卡内调用写法不成立 | `ui_assembler.gd:1-5`(`extends RefCounted`+头注「供组合根接线」)、引用方 `main_ui_build.gd:7`/`scenes/adventure_screen.gd:21`/`scenes/menu_screen.gd:15`、`views/` 内联先例 `battle_end_overlay.gd:261/289/314` | 待裁 | 第 15 节 Q1 两案并列;T3.1 改「待 Q1 后落」 | -| 10 | §3.3/§8 R5 | 徽章自高 48 系推导,`panel_flat` `border_w=1` 若计入则 50 | `ui_kit.gd:640`+`panel_flat` `ui_kit.gd:455-464`(复核者自标「这是推测,未跑批」) | 补写 | T3.0 新增前置读数;≠48 走 L3 第 5 条 | -| 11 | §9 T3.2/§11.3 | 12px 内缩无可达机制(宽度随位数变);R5 缺 x 向判据=改了仍绿 | `camp_hud_band.gd:16`(现值写死 x)+`:22`(文案「钥石 %d」) | 待裁+补写 | Q2 三案并列;R5 已补 `end.x == 栏 end.x − 12` | -| 12 | §8 R6 | 呈色若取自实现表达式=oracle 镜像 | test-conventions §8.7 第 5 条 | 自判 | R6 改规格侧写死值,禁喂视图件 color | -| 13 | §11.4 | 「4×8 步长沿该件口径」错,该件全像素扫描 | `terrain_tile_sets_test.gd:105-107` | 自判 | 白名单第 4 条改全扫描并声明旧口径作废 | -| 14 | 数学校核 | 全扫与抽样均色皆 RGB(223,235,232)(卡 `#DEEAE7` 差 ≤1/255);叠后 4.29:1、徽章对天空 1.30:1;落位带 0–48 只含背景成立 | `camp_scene_layout.tres:9`(背景 `Rect2(0,0,1280,800)`)、围墙 y=261、大门 y=250;`project.godot:30` 视口宽 1280 | 自判(确认+读数微差) | 差值落 L2 容差,阈值不放宽;卡内读数保留 | -| 15 | §1/§5 | 「七行」与对照表实数 R1–R8 不符 | 卡内自相 | 自判 | 改八行 | -| 16 | §5 | 引「第 1 节行为表」——卡内无该表(悬空引用) | 卡内自相 | 自判 | 改自足表述 | -| 17 | §7 | 结构图验收行缺 R7/R8 | 卡内自相 | 补写 | 两行补齐 | -| 18 | §13/§10 L3 第4条 | gdstyle 不扫 tests,新件三查与互斥条对新件无触发路径;套件入口是 `_initialize()` 非 `_init` | `tools/gdstyle_gate.py:45`(SCAN_DIRS 三目录)+头注 `:8`(probe/sim/tests 排除);`camp_scene_layout_test.gd:12` | 自判 | §13 改「对本件不适用」;L3 第 4 条限定 presentation 面;T2.2 入口名与先例行号订正 | -| 19 | §13 存量一查 | 核过无误:基线 `:11`=32、`:12`=23;`main.gd` 公开方法 31+1 静态=32 持平 | `tools/gdstyle_baseline.txt` | 自判(确认类) | 无改动,留档已核 | -| 20 | §4 契约4 依据 | 称五 token 对齐机检「查无该件」(`palette_check.py` 无 CAMP_HEADER 逻辑,全仓只命中视图用法) | 复核者 grep | 退回上游(复核者判) | **不采信其结论**:写卡段回读 `tools/palette_check.py:22` 有 `ui_tokens.png`=ui_kit 全量 Color8 token 快照基线,机制存在但不逐名比对表内五行;契约4 依据改成该准确口径 | -| 21 | §9 T2.2 | 册为硬编码清单,「接进套件册」不够具体 | `game/tests/run_all.gd:166` 起条目形态 `{"path":…, "expect":0}`+行尾注 | 补写 | T2.2 写死条目全文 | -| 22 | 横面 | `ANCHOR_RE` 字符类不含中文段→中文名现行文档无法被机检认锚 | `tools/pipeline_gate.py:68` | 退回上游 | 列 §6 末行;本批不动闸件,是否登记归用户发令 | - -## 采信统计与残余 - -- 采信并落卡:19 条(自判 11/补写 8)。 -- 转待裁(不代用户选):2 条(#9、#11 的机制案),落第 15 节 Q1/Q2。 -- 不采信结论:2 条(#8 的 `:679` 定性、#20 的「机检不存在」),均经写卡段逐行回读推翻,依据记在表内。 -- 残余(本卡范围外):#22 机检件缺口;以及本批既有的「art-bible §4.5 #7 破坏性确认异位是否追认」——早于本卡在册,见第 5 节不做表。 - -**卡片状态**:轮次 1 后为「待裁未清零」;轮次 2 后见下节。 - ---- - -## 轮次 2(Q1/Q2 裁决落卡之后,另起一个未参与撰写的只读子代理) - -任务书限定只查五处,且每处须给 `文件:行号` 依据。发现五条: - -| # | 卡内位置 | 发现 | 依据 | 去向 | 处置 | -|---|---|---|---|---|---| -| 1 | §8 R3/§9 T2.2 | 双钮形态断言「child(1)=维持」必红——次钮只 `visible=false`、不移除 | `confirm_dialog.gd:47` | 补写 | 改 child(2) + 子节点数=3 非空前置(已落卡) | -| 2 | §8 R5 | 未写「须先开营地」前置,boot 态营地屏为隐读不到尺寸 | `camp_scene_view.gd:51` | 补写 | 真实入口补 `open_camp()`+await 排版帧(已落卡) | -| 3 | §9 T3.0 | PanelContainer 最小尺寸入树排版后才可信,刚 `new()` 读数不可信,时机未写 | `ui_kit.gd:634-656` | 补写 | 改为经公开句柄读在树的现成实例、await 后再读(已落卡) | -| 4 | §3/§8 确认类 | 八处行号全对;`to_html(true)` 追加 α 两位、`6e4526cc` 串对;1280×48 尺寸链可达;「按类型找第一个 HBoxContainer」在本弹窗树内唯一 | `main.gd:211-212`/`:223-224`/`:292-308`、`ui_kit.gd:640`、`ui_assembler.gd:100/214/224-230`、`ui_kit.gd:189/190/200`、`standee_present_values_test.gd:36`、`scenes/camp_screen.tscn:7-11`、`project.godot:30-31` | 自判(留档) | 无改动 | -| 5 | §15 Q1 | 裁决句字面只覆盖「色值放公共层」这条轴,「矩形谁建」是写卡段的展开 | 对话原话序列:写卡段推荐句为「色值进公共件、矩形留在顶栏件自建」,用户回话「那没有问题,就按放在公共区域的这一层的方案来实现」 | 待裁(复核者判)→ 按自判落并报备 | 卡内第 15 节与第 16 节各写入解释面一句;用户不认该读法即重开,重开范围仅止于矩形建造方 | - -轮次 2 总判:三条补写已落卡,一条确认留档,一条按自判落并向用户报备。**该"自判闭合"事后被判无效**——见轮次 3 与卡片第 15/16 节的裁决史。 - ---- - -## 轮次 3(11-06 用户驳回"值与形拆两处"、改判整案收编之后;第三个只读子代理) - -| # | 卡内位置 | 发现 | 依据 | 去向 | 处置 | -|---|---|---|---|---|---| -| 1 | 契约4/§12 | 两处旧实现确未设 mouse_filter,ColorRect 默认即 STOP,出口默认值取 STOP 才不改三处旧遮罩语义 | `ui_assembler.gd:224-230`、`ui_kit.gd:486-491`;旁证 `ui_kit.gd:540`/`:864`、`camp_scene_view.gd:145` | 自判(确认) | 卡内补入旁证 | -| 2 | T3.2 | 三处既有调用点都是"挂宿主+把返回句柄当父用",转调在层序上等值 | `ui_assembler.gd:100-110`/`:214`/`:232-239`、`ui_kit.gd:511-514` | 自判(确认) | 无需改 | -| 3 | R9/T3.7 | `_modal_dim()` 经 `modal_shell()` 扇出 11 家消费件,R9 只点两处探针=覆盖不足 | `grep modal_shell(` 全仓 12 命中(含定义) | 补写 | 判据改源扫描式,并如实写明覆盖面(2 家断言+其余渲染闸与目检承接) | -| 4 | R5②⑤ | 1280 宽的承重链引错(非 tscn 锚点,是注册层 FULL_RECT);⑤ 全局矩形与局部 position 混写 | `camp_scene_view.gd:13-14`、`ui_registry.gd:26`/`:61` | 补写 | R5 改引注册层、⑤ 改 `get_global_rect()` | -| 5 | R9/T3.2 | "两文件 ColorRect 合计=1"算术不成立(`ui_kit` 实有 3 处自建) | `ui_kit.gd:487`/`:537`/`:862` | 补写 | 判据改为"两个被收编函数体内不再自建",范围显式声明,不写全仓唯一 | -| 6 | R9 | `:537` 页壳底板与出口形状相同、仅显式 STOP 与实色之差——是否同一件事,判为待裁 | `ui_kit.gd:536-542` | **待裁** | 新增 Q4(两案代价并列,不自决) | -| 7 | 多处 | 数字与交叉引用过期:显隐点 12→13(漏 `main_overlay_flow.gd:101`)、`views/` 自建先例 8 文件→7 文件 15 处、§5 与 §1 行数不一致、§12 步骤号未随重排更新、T4.1 应引 T3.9、§14/§15 把 tooltip 底误算进收编用途(`TIP_BG:190` 不经这两个函数) | `grep start_overlay.visible` 实测 13 处写点;`grep -c ColorRect.new()` views/*.gd 实测 7 文件 15 处 | 补写 | 全部按实测改正 | -| 8 | 轮次 2 记录 | 复核者上一轮给的 `camp_scene_view.gd:53` 才是正确行号,**写卡段上一轮"纠正复核者"改成的 `:51` 是错的** | 本轮 grep 复核 | 自判(推翻写卡段自己) | 全文改回 `:53`,卡片第 16 节轮次 3 记一条 | - -**写卡段对轮次 3 的不采信项**:无——这一轮唯一被推翻的是写卡段自己上一轮的判断。 - -**轮次 3 总判**:不能进实现段;除 Q4 待用户一句裁决外,其余补写已全部落卡。 - -## 轮次 4(11-06 撤收编版落卡后的独立复核) - -复核者=第四个未参与撰写的只读子代理(禁写禁跑,须给 `文件:行号`)。审的是撤收编后的终态(`UiKit.camp_hud_band_surface(host)` 单参具名出口+零收编)。它报 17 条:硬伤 2、事实错 2、一致性 4、补写 3、确认 5、外部 1;未新增待裁点。 - -| # | 卡片位置 | 发现 | 依据 | 去向 | 落卡 | -|---|---|---|---|---|---| -| 1 | R4 | 「按按钮行实际矩形算左位坐标」必打空:行 `alignment=CENTER`,双钮可见宽 216+12+216=444<壳宽 460,左位落 8px 空档 | `confirm_dialog.gd:29`、`ui_kit.gd:578`、`confirm_dialog.gd:20` | 补写 | R4 入口改取按钮行 child(0) 全局矩形中心并写入算式(与 T2.3 统一) | -| 2 | T3.4/§7/§11.5 | 「`_smoke_camp_hud_band()` 接进 `_initialize()`」不成立:`_initialize` 只调 `_split_tail()`,摘要与 `quit()` 在尾段,不被 await=静默不执行=假绿 | `system_test.gd:26-28`/`:35-48`/`:40` 行尾注/`:213-217` | 补写 | 三处同批改「接进 `_split_tail()` 的 await 链」,段内自持 instantiate/queue_free 照 `_smoke_run_lifecycle()` | -| 3 | §3.2/R3 | 四消费方行号偏一(卡 72/76-78/82,实 73/79-80/83;129 对) | `main_overlay_flow.gd:69-83`/`:125-129` | 自判 | 两处改正 | -| 4 | R5② | 营地场景根代码 new 的位置引错:`camp_scene_view.gd:13-14` 是命中区名表,new 在屏壳 | `camp_scene_view.gd:12-15`、`scenes/camp_screen.gd:13-14`、`camp_screen.tscn` 根锚 preset=15 | 自判 | 改引 `scenes/camp_screen.gd:13-14`(**同时推翻轮次 3 第 4 行沿用的 `camp_scene_view.gd:13-14`**) | -| 5 | R3 | 括注「`modal_shell()` 产 VBox+HSeparator」不实,HSeparator 是弹窗自加 | `ui_kit.gd:509-525`、`confirm_dialog.gd:26` | 自判 | 改为「产 CenterContainer+PanelContainer+VBox,不产横排」 | -| 6 | T3.3/§12 | 「`confirm_dialog.gd:27-29` 是容器右对齐先例」不准:该处 alignment 取 CENTER,是同机制先例 | `confirm_dialog.gd:29` | 自判 | 措辞改正,明写本件取 END 才是右对齐 | -| 7 | R6 | 「§8.4」未冠文档名,卡内无 8.4 小节 | `test-conventions.md` 正面效力自检条 | 自判 | 改「test-conventions §8.4」 | -| 8 | R4 | 读 `main._confirm_consumer`(私有)与 §12「不读私有」口径不一,但探针先例在案、扫描射程不含探针 | `ui_click_probe.gd:272`/`:286`、`presentation_encapsulation_sweep_test.gd:80-94`(该件在 `game/tests/unit/presentation/`,复核者误记 `unit/contracts/`) | 自判 | 主证改列 `is_adventure`,私有一读注明先例与射程;**路径误记已纠正,结论不受影响** | -| 9 | §14.1 | 出口职责句「返回句柄供顶栏件摆放徽章」与实际(返回值不用于摆位)不符 | 卡 T3.2/T3.3 | 自判 | 职责句改「供调用方读取与断言」,摆位归 T3.3 容器 | -| 10 | T3.0/L3.5 | 徽章自高≠48 只列描边一因,漏 18px 文字行高这一同因 | `ui_kit.gd:648`(Label 取 `FS_SUB`)/`:438` | 补写 | 两因并列,处置强度不变 | -| 11 | R2 | 判据非件1 改动特有面 | `ui_click_probe.gd:704` 既有同面断言 | 补写 | R2 注明特有提交面由 R1 承载、两行同批缺一即红 | -| 12 | 待办清单 | 实况仍写「两轮独立复核报告」 | `待办清单.md:30` | 补写 | 改「四轮」 | -| 13 | 全文 | 收编版残留扫描:无一处把收编/通用出口/color·pass_input/R9/改 `ui_assembler` 写成现行方案;T3.0–T3.7、R1–R8、白名单、L3、裁决史交叉引用零悬空 | 逐节比对+符号 grep | 确认 | 无需改 | -| 14 | 全文 | 40 处行号引用逐行打开无误(不含本表第 3、4 两条例外) | 复核者逐行比对 | 确认 | 无需改 | -| 15 | R5②③ | 未入树调 `set_anchors_preset(FULL_RECT)` 铺满成立、1280 宽承重链成立、色面必须入 `_init()`(入树前) | `ui_kit.gd:486-491`、`ui_assembler.gd:227`、`ui_registry.gd:61` | 确认 | 判据不变;按建议在 T3.4 补时机一句 | -| 16 | §2 实测句 | `Color(常量, α)` 构造子库内大量现役;const 引同文件 const 无库内先例,卡凭 11-06 临时工程实测(仓库无产物可复验=推测),失配属编译期 fail-fast | grep 零命中 | 确认 | 维持实测句,不设断言 | -| 17 | 契约/§5/§13/README | 契约4·5 与 §5 不做行无矛盾无空隙;两行新增能力名与 `tests/README.md:159/162/163` 逐字一致;预算实算正确(29 static func-6 私有=23→24) | 逐处比对 | 确认 | 无需改 | - -**写卡段对轮次 4 的不采信项**:1 条——第 8 行的文件路径误记(实际在 `game/tests/unit/presentation/`),已按正确路径落卡,其结论经回读成立。 - -**轮次 4 总判**:两条硬伤与四处事实错、四条一致性问题、三条补写全部落卡,未新增待裁点。撤收编后的终态设计至此经独立复核闭合:零待裁点,开工门=U0(用户批卡)。 diff --git a/reports/需求卡片-QA缺陷收口批-2026-11-06.md b/reports/需求卡片-QA缺陷收口批-2026-11-06.md deleted file mode 100644 index cac8dac8..00000000 --- a/reports/需求卡片-QA缺陷收口批-2026-11-06.md +++ /dev/null @@ -1,238 +0,0 @@ -# 需求卡片——QA harness 缺陷与覆盖遗漏收口批(2026-11-06) - -> **来源**:待办清单「QA harness 三批缺陷与覆盖遗漏收口」条目(P0,2026-11-06 批次移交登记)——需求性工程条目,状态行整行无设计线段、首段落「待写卡」。 -> **设计事实源(唯一事实源)**:`reports/QA-harness三批-缺陷与覆盖遗漏报告-2026-11-06.md`(A2=其§一 A2、B1=其§二 B1、B2=其§二 B2,逐条带文件:行号与登记处指针)+待办清单条目实况同源指认。设计线跳过依据=需求性工程条目(缺陷修复+测试驱动面,凭实况里的证据指认跳过设计线,doc-conventions §12.1)。 -> 验收档:中——判由:改动面=呈现层一行级容错(A2)与探针/测试驱动面(B1/B2);做错的后果不随存档或结算传播(本批零持久状态触碰),但覆盖登记件读数进证据链,失真并非即看即知,按三档判据取中。A2 单看属低档,本卡多面按最高档申报。 -> **预计周期(估时中值和)**:≈4.875 个工作日(编排段按区间中值核对的口径;T1–T7 逐卡区间见各卡头)。 -> **范围检查**:单卡单子系统——三件缺陷同源于 QA harness 三批的同一发现面(探针真输入化与覆盖登记),拆卡只增加合并登记次数,不拆。 - -## 1. 目标与完成定义 - -本批做三件事:修一个探针跑批持续输出的引擎报错噪声(A2);把停手钮的「存在但从未被真输入点到」驱动空洞补成确定性覆盖(B1,探针+自动试玩两处);把探针族与测试宿主里剩余的「视图方法口驱动」全部换成真输入管线驱动(B2,全清 41 处)。 - -规格项(每条指到任务卡与对照表行): - -- S1 终局结算框关闭动线零引擎报错——T1、对照表 R1。 -- S2 停手钮使能窗真输入命中、命中登记与停手收轮落效(探针定型化段)——T2、对照表 R2。 -- S3 自动试玩(journey_player)停手行为入线,停手成为全动线真输入行为之一——T3、对照表 R3。 -- S4 视图方法口驱动全清转真输入——S4a ui_click_probe 16 处(T4、R4);S4b 其余 7 探针 11 处(T5、R5/R6);S4c journey_player 8 处(T3、R3 附属);S4d 非探针层 6 处(T6、R7/R8)。 -- S5 转换后零调用的 press_* 死接缝同批删除——T4/T6、对照表 R9。 - -完成定义=S1–S5 全部有对照表行、每行验收断言在当轮真实跑批执行并通过、独立验收审计通过、合回后远端 CI(游戏码批全量档)绿。 - -## 2. 设计事实源 - -见头部声明。证据指认逐条(与待办清单条目实况一致): - -- A2:`game/presentation/views/battle_end_overlay.gd:194`——`get_meta(&"celebrate_tw", null)` 在 meta 缺失时引擎仍打印报错(当前引擎版对显式 null 缺省值照样报错);败走/放弃路径每次触发(`game/probe/fx_probe.gd:58-66` 的 open_defeat→close 循环、screen_flow_probe 终局段)。关闭动线功能不受影响,属持续日志噪声。 -- B1:两探针与自动试玩均未以真输入点过停手钮;覆盖面板控件下钻(ui_click 探针 seen 91/命中 27)与 `probe_hits_ui_click.js` 零停手键。驱动代码其实在——`game/probe/ui_click_probe.gd:1063-1065` 已是 `ProbeUiUtil.push_click` 真输入,但触发条件(已花 ≥3 AP 时 15% 随机)实际跑批从未命中使能窗,随机静默回退。 -- B2:视图方法口驱动清单(本次逐处 grep 复核后共 41 处,分四类面,见 §3)。 - -## 3. 现状事实(代码级,开工自行复核;行号以 2026-11-06 master 7aa0126b 为准) - -**A2 面**: - -- `game/presentation/views/battle_end_overlay.gd:194`:`var tw: Tween = get_meta(&"celebrate_tw", null)`——败走路径(open_defeat,:175-186)不设该 meta,close()(:189-198)每次在此报错。同型第二处=`battle_end_overlay.gd:331`(`_play_celebrate` 取同一 meta——close 后已 remove_meta(:197),下一次 open_victory 到此同款报错)。 -- 报错形态为引擎层打印,场景探针闸的脚本错误扫描(`tools/probe_gate.sh:49` 经 `tools/error_scan.py`)不判红——闸绿但噪声持续,故验证形态=探针孤立直跑+日志零该报错行读数。 -- `ui_run_modals.gd:10`:`end_overlay: BattleEndOverlay`——screen_flow_probe 的「终局」即本件。 - -**B1 面**: - -- `game/probe/ui_click_probe.gd:1041-1045`:停手触发=已花 ≥3 AP 时 15% 随机、或无挖可走时;:1063-1065 `_click_stop()`=`ProbeUiUtil.push_click(main, main.ui.battle.board_zone.ap_bar._btn_stop)`。 -- 使能投影:`game/presentation/hud_presenter.gd:92`(alive∧digging)→ `game/presentation/views/ap_bar_view.gd:146-147`(`_btn_stop.disabled`)。 -- 停手消费端:`game/presentation/main.gd:690` `_on_stop_pressed` → `settle_batch([{"action":"stop"}])`(批次唯一结算入口,排雷玩法.md:162);停手=玩家主动收轮(排雷玩法.md:167);已清图时 voided(toast「本轮已清图,停手未执行」)。 - -**B2 面——方法口驱动全清单(41 处,本次 grep 复核)**: - -| 组 | 调用点 | -|---|---| -| ①ui_click_probe 点名三组(16 处) | `ui_click_probe.gd:426`、`:536`(press_candidate);`:448`、`:656`(node_overlay.press_continue);`:473`、`:475`、`:476`、`:478`、`:479`、`:481`、`:649`、`:651`、`:652`、`:654`(curio press_continue/press_card/press_confirm);`:972`、`:975`(ap_bar press_refresh_for_probe/press_confirm_for_probe) | -| ②journey_player 方法口(8 处) | `journey_player.gd:380`(node_overlay.press_continue);`:441`(press_candidate);`:449`、`:457`(curio press_continue);`:451`、`:452`、`:454`、`:455`(curio press_card/press_confirm) | -| ③其余探针到达型+停点+调试浮窗(11 处,7 件) | `fx_shot_probe.gd:47`、`ui_tune_probe.gd:109`、`shot_probe.gd:147`、`ui_probe.gd:83`、`t17_defer_probe.gd:39`、`layout_probe.gd:32`(press_candidate);`ui_struct_probe.gd:257`(node_overlay.press_continue);`ui_tune_probe.gd:59`、`:62`、`:67`、`:97`(debug press_apply/press_reset/press_simulate_for_probe) | -| ④非探针层(6 处) | `system_test.gd:433`(press_candidate);`reward_overlay_test.gd:60`、`:64`、`:65`、`:66`、`:76`(press_refresh/press_card/press_confirm/press_continue) | - -**被点控件形态(真输入可行性依据)**: - -- 三选一卡=BCard gui_input 点选(`curio_pick_overlay.gd:157-160` M7 注——真实路径与 press_card 同一 `_select_card` 处理器);确认/继续/刷新=真 Button(:163-173 emit 形态即假入口)。 -- 节点停点=真 Button(`node_overlay.gd:32-34`)。 -- 弃图刷新=真 Button `_btn_refresh`(`ap_bar_view.gd:110-111` 创建+接线,disabled 守卫=真实拒绝路径);确认 chips=真 Button(:88-96,`_confirm_row` 子件)。 -- 地图候选=自绘命中路径:`level_map_screen.gd:469-479` press_candidate 内部走「节点中心坐标 → `_candidate_at` 命中检测 → 提交」——真输入化=点候选命中矩形中心,经画布 gui_input 走同一命中面。 -- 非探针层宿主在树:`reward_overlay_test.gd` extends SceneTree、`root.add_child(ov)`——`push_input` 可用;system_test 驱动完整宿主,同可用。 - -## 4. 设计契约(违反即返工;🔴 触碰=L3 停机呈报) - -1. 🔴 **真输入唯一通道**:所有转换一律经 `game/probe/probe_ui_util.gd` 的 `push_click`/`push_click_at`(合成 InputEvent 走 `push_input`,press+release 成对;tests 面经 preload 复用同一件,禁复制第二份合成输入件);禁回退信号直发;〔接线断言〕豁免面零新增(test-conventions §2)。 -2. 🔴 **转换零弱化**:每个转换点的既有动线断言逐条保持,落点判定(点了之后到哪个屏/哪层可见)不删、不改判;实现期发现既有断言保不住绿且非驱动问题=疑似产品缺陷浮出,停卡呈报登记,禁顺手改断言或改产品码。 -3. 🔴 **死接缝同批清**:转换后零调用的 press_* 方法与只验证旧口的护栏同批删除;禁为机检文本保留无效成员或别名(code-conventions §1.1⑤);机检键与本契约互斥时停卡呈报,不自造第三条路。 -4. 🔴 **封装边界**:产品码零私取新增(本批产品码改动仅 A2 一处容错与一个公开读口);探针/测试面读私有控件沿用现役惯例(`ap_bar._btn_stop` 同型先例在案:ui_click_probe.gd:1065);本批新增公开面仅 `LevelMapScreen.candidate_rect` 一个。 -5. 🔴 **零数值零随机面**:本批零数值改动、零 MC 跑批、零 RNG 触碰;Core 层零触碰(改动全部落在 presentation/probe/sim/tests)。 -6. 🔴 **不触画面呈现规格**:无预览图义务、无 golden 扩项——缺陷修复以现行规格与在库基线为准(test-conventions §8.2)。 - -## 5. 范围边界 - -**收件**:S1–S5(§1)。 - -**不收件与去向**: - -- A1(开局被开始层盖住):随 camp-interact 分支(0977a548)合回即消,无需新批——该分支截至写卡时尚未合回 master;合回后自动试玩对应上报自然消失,本卡不做任何动作。 -- B3(存量 996 条断言判据出处精锚):归待办清单「测试面真输入化分期与存量断言逐条精锚」条目②,本卡不碰。 -- B4(本体对账缺口 212 条)/B5(控件级零命中缺口):须人工逐条复核后再分流(真缺口立事项/假缺口豁免清单核销),本卡不预收——合回后原条目继续在册。 -- B6(自动试玩判据收紧轮):触发权与执行归用户复核轮,本卡不碰。 -- 覆盖面板 UI 改动、闸件改动(error_scan 扫描面不扩):均不做——本批只修源头,不动机检面。 - -## 6. 关联文档同步面 - -无关联文档——本批不动任何设计文档的任何陈述(A2 为容错修复,B1/B2 为测试驱动面,零设计语义变化)。能力清单(`game/tests/README.md`)归写卡段随卡同批维护(已随本卡增行,见 §9 能力行列),非实现批义务。 - -| 文档 | 关联点 | 同步义务 | -|---|---|---| -| 无关联文档 | — | — | - -## 7. 卡前·文件结构图 - -| 文件 | 职责 | 行为改动 | -|---|---|---| -| `game/presentation/views/battle_end_overlay.gd` | 终局结算框:close() 容错(A2) | 行为改动(R1) | -| `game/presentation/views/level_map_screen.gd` | 关卡地图屏:press_candidate 接缝退役、新增 candidate_rect 命中矩形读口 | 非行为改动(接缝置换,玩家可见行为零变化,R9) | -| `game/presentation/views/ap_bar_view.gd` | AP 条:press_refresh_for_probe/press_confirm_for_probe 死接缝删除 | 非行为改动(R9) | -| `game/presentation/views/curio_pick_overlay.gd` | 三选一覆盖层:press_card/press_confirm/press_continue/press_refresh 死接缝删除 | 非行为改动(R9) | -| `game/presentation/views/node_overlay.gd` | 节点停点层:press_continue 死接缝删除 | 非行为改动(R9) | -| `game/presentation/views/debug_overlay.gd` | 调试浮窗:press_apply/press_reset/press_simulate_for_probe 死接缝删除 | 非行为改动(R9) | -| `game/probe/ui_click_probe.gd` | 主 UI 探针:定型化停手段+16 处真输入转换 | 行为改动(R2/R4) | -| `game/sim/journey_player.gd` | 自动试玩:停手行为入线+8 处转换+头注通道标注更新 | 行为改动(R3) | -| `game/probe/fx_shot_probe.gd`/`ui_tune_probe.gd`/`shot_probe.gd`/`ui_probe.gd`/`t17_defer_probe.gd`/`layout_probe.gd`/`ui_struct_probe.gd` | 各 1–5 处真输入转换(③组 11 处) | 行为改动(R5/R6) | -| `game/tests/system_test.gd` | 1 处真输入转换(④组) | 行为改动(R7) | -| `game/tests/unit/presentation/reward_overlay_test.gd` | 5 处真输入转换(④组) | 行为改动(R8) | -| `game/tests/README.md` | 能力清单 3 行新增(写卡段随卡同批,已落) | 非行为改动 | - -结构图与「落位与可复用性预检」互指:标「新增」的件=candidate_rect 一个(理由与唯一落点见 §13);其余全部为「复用既有」或删除。 - -## 8. 任务卡 T1..T7 - -**T1|A2 关闭容错修复**(估时 [0.25, 0.5],中值 0.375) - -- [ ] 开工核对:§3 现状事实逐条 file:line 复核;master 若已推进致行号漂移就地校正,漂移超一屏呈报。 -- [ ] 实装:`battle_end_overlay.gd:194`(close)与 `:331`(_play_celebrate)两处同改——`get_meta(&"celebrate_tw", null)` 改 `has_meta(&"celebrate_tw")` 前置判断,有句柄才取并 kill,无句柄跳过;语义不变(有则必杀、无则无事)。 -- [ ] 验证:`…console.exe --headless --path . res://probe/fx_probe.tscn` 直跑,输出 grep「SCRIPT ERROR」与「celebrate_tw」零命中。 -- [ ] 验证:`res://probe/screen_flow_probe.tscn` 直跑,同判据零命中。 -- [ ] 读数写进本步提交信息。 - -**T2|B1 探针定型化停手段**(估时 [0.5, 1],中值 0.75) - -接口——产出:`ui_click_probe` 新增 `_stoptest_tick()`(状态机形态镜像现役 `_locktest_tick`:待命→点击→核效→完);被对照表 R2 与能力行「停手钮真输入命中与停手收轮落效」承接。 - -- [ ] 新增定型化段:每 run 一次;触发条件=战局挖掘期(行动经济相位 Active、停手钮使能、盘面未清、本 run 尚未测过);触发 tick 冻结其余随机行为,仅提交停手。 -- [ ] 驱动:`ProbeUiUtil.push_click(main, …ap_bar._btn_stop)`(与 :1065 同型)。 -- [ ] 断言①命中登记:点击后覆盖登记件停手键在场(`probe_coverage_recorder` 现役命中登记口);零命中即红(正面效力自检——防驱动中断空转假绿)。 -- [ ] 断言②落效:点击后行动经济相位离开 Active(停手收轮;本 tick 零挖掘提交,排除清图混淆)。 -- [ ] 验证:ui_click_probe 孤立直跑绿,读数入提交信息。 - -**T3|B1 自动试玩停手+journey 方法口 8 处转换**(估时 [0.75, 1.5],中值 1.125) - -接口——取用:T4 的 `LevelMapScreen.candidate_rect(index: int) -> Rect2`。产出:journey 覆盖登记含停手键。 - -- [ ] journey_player 新增停手行为:每战至多一次,条件=挖掘期(Active、停手钮使能、AP 已花 ≥1、盘面未清)时 `ProbeUiUtil.push_click` 停手钮(确定性触发,无随机占比——触发时点微调在代拍板白名单)。 -- [ ] 8 处方法口转换:`:380` → `push_click(node_overlay._btn)`;`:441` → `push_click_at(level_screen.candidate_rect(0).get_center())`;`:449`/`:457` → `push_click(curio 继续真钮——`_continue_btn`,驱动分支已按其 visible 分发)`;`:451`/`:454` → 选卡(bcard 全局矩形中心 push_click_at);`:452`/`:455` → `push_click` 确认真钮。 -- [ ] 头注(:14)「两处方法口如实标注通道」句更新为方法口清零。 -- [ ] 试车:journey 跑批 ≥2 分钟,先最小参数跑通全链(解析/落盘/登记件写出)再放全线(闸机轮次纪律)。 -- [ ] 验证:journey 全线跑批一次——读数=①覆盖登记件新增停手键与候选/停点键 ②journey_report meta 零 fatal、上报结构不变。读数入提交信息。 - -**T4|B2 ui_click_probe 16 处转换+candidate_rect 读口**(估时 [0.75, 1.25],中值 1.0) - -接口——产出:`LevelMapScreen.candidate_rect(index: int) -> Rect2`(候选命中矩形,全局坐标,命中面=同 `_candidate_at` 的节点方块面;index 越界返回空 Rect2,调用方跳过)。 - -- [ ] `level_map_screen.gd`:新增 candidate_rect(内部复用 `_cand_ids`/`_layout` 计算,矩形与 press_candidate 命中面同源);删除 press_candidate(:469-479)。 -- [ ] 候选 2 处(`:426`/`:536`)→ `push_click_at(candidate_rect(…).get_center())`。 -- [ ] 节点继续 2 处(`:448`/`:656`)→ `push_click(node_overlay._btn)`。 -- [ ] 三选一 10 处(`:473`/`:475`/`:476`/`:478`/`:479`/`:481`/`:649`/`:651`/`:652`/`:654`)→ 选卡=bcard 全局矩形中心 push_click_at;确认/继续=真钮 push_click。 -- [ ] 弃图刷新链 2 处(`:972`/`:975`)→ `push_click(_btn_refresh)`(disabled 守卫即真实拒绝路径)+`push_click(确认 chips 真钮——`_confirm_row` 内 Button 子件)`。 -- [ ] 逐处核对既有动线断言落点判定原样保持(🔴 契约 2)。 -- [ ] 验证:ui_click_probe 孤立直跑绿+覆盖登记件键集较改前不回退(新增停点链/候选/弃图确认键)。读数入提交信息。 - -**T5|B2 其余 7 探针 11 处转换**(估时 [0.5, 1],中值 0.75) - -接口——取用:T4 的 candidate_rect。 - -- [ ] 候选 6 处:`fx_shot_probe.gd:47`、`ui_tune_probe.gd:109`、`shot_probe.gd:147`、`ui_probe.gd:83`、`t17_defer_probe.gd:39`、`layout_probe.gd:32` → `push_click_at(candidate_rect(0).get_center())`。 -- [ ] 停点 1 处:`ui_struct_probe.gd:257` → `push_click(node_overlay._btn)`。 -- [ ] 调试浮窗 4 处:`ui_tune_probe.gd:59`/`:62`/`:67`/`:97` → `push_click`(对应按钮控件)。 -- [ ] `shot_probe.gd:9` 头注同步(「真实选路提交」语随形态更新)。 -- [ ] 验证:7 个探针逐件孤立直跑绿。读数入提交信息。 - -**T6|B2 非探针层 6 处转换+死接缝清理**(估时 [0.5, 0.75],中值 0.625) - -- [ ] `system_test.gd:433` → `push_click_at(candidate_rect(0).get_center())`(tests 面经 preload 复用 ProbeUiUtil)。 -- [ ] `reward_overlay_test.gd` 5 处(`:60`/`:64`/`:65`/`:66`/`:76`)→ 真输入(root 已挂树):刷新/确认/继续=对应真钮 push_click,选卡=bcard 矩形中心 push_click_at;断言语义逐位保持(三卡呈现/选择外发/强制确认两段式/结果态)。 -- [ ] 死接缝删除(全仓 grep 确认零调用后逐个删):ap_bar_view(2)、curio_pick_overlay(4)、node_overlay(1)、debug_overlay(3)、level_map_screen(press_candidate,T4 已删)。 -- [ ] 验证:系统测试直跑绿+单元与集成套件直跑绿+全仓 .gd 面双模式 grep 零命中——定义清 `func press_(candidate|continue|card|confirm|refresh|apply|reset|simulate)` 与调用清 `\.press_(candidate|continue|card|confirm|refresh|apply|reset|simulate)`(均 `--include=*.gd`,排除 reports/ 与注释外文档;`shot_probe.gd:9` 注释随 T5 同步后 .gd 面应零命中)。读数入提交信息。 - -**T7|产出物落位卡**(估时 [0.25, 0.25],中值 0.25) - -- [ ] `reports/iter-实现报告-<日期>.md`:各卡状态+实机目检总清单(本批目检项=覆盖面板控件下钻停手键与停点链键在场)+遗留读数义务+实现决定记录。 -- [ ] `reports/iter-反哺点清单-<日期>.md`:照写(本卡申报「无关联文档」,零条)。 -- [ ] 批末按改动域选档跑闸(游戏码批),里程碑步出口一次;改前改后读数对拍在案。 -- [ ] 独立验收审计入口预约:`reports/iter-验收审计-<日期>.md`(未参与实现的会话或子代理;未过不合回)。 - -## 9. 验证闸(改动—验收对照表) - -| 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 | -|---|---|---|---|---|---|---| -| `design/engineering/test-conventions.md:60` 终局结算框关闭与庆祝续播动线零引擎报错 | battle_end_overlay.gd:194(close)与 :331(_play_celebrate)两处 get_meta 缺省 null 报错 → has_meta 前置判断 | fx_probe+screen_flow_probe 孤立直跑,日志零「celebrate_tw」报错行〔QA收口 V1〕(grep 读数) | 探针 | fx_probe 真实实例化 open_victory→close→open_defeat→close 全序(两处报错点均经真实动线触达) | 探针日志零报错行。观测面局限申报:该缺陷唯一提交面=报错打印本体,无状态面可钉——静态+日志读数承载,对照表行内申报在案 | 新增:终局结算框关闭动线零引擎报错 | -| `design/engineering/test-conventions.md:23` 停手钮使能窗真输入命中与落效(探针) | ui_click_probe 新增 _stoptest_tick 定型化段 | ui_click_probe 直跑:①登记件停手键在场②相位离开 Active 收轮③零命中即红〔QA收口 V2〕 | 探针 | AP 条停手钮 push_input 真点击(使能窗内) | 覆盖登记件停手键+行动经济相位收轮(落效规格句=design/gdd/systems/排雷循环/排雷玩法.md:167 停手=玩家主动收轮、:162 批次唯一结算入口) | 新增:停手钮真输入命中与停手收轮落效 | -| `design/engineering/test-conventions.md:23` 自动试玩停手行为入线+方法口清零(S3+S4c) | journey_player 新增停手行为+8 处方法口转换(:380/441/449/451/452/454/455/457)+头注通道句更新 | journey 全线跑批:登记件停手键与候选/停点键在场+meta 零 fatal〔QA收口 V3〕 | sim | journey_player 全线跑批(sim 直跑) | journey 覆盖登记件停手键+候选/停点键+上报零 fatal | 新增:停手钮真输入命中与停手收轮落效;新增:停点链与控件级真输入命中 | -| `design/engineering/test-conventions.md:23` 停点链真输入化(ui_click_probe 16 处) | ui_click_probe.gd:426/448/473-481/536/649-656/972-975 方法口→push_input 驱动 | ui_click_probe 直跑绿+既有动线断言逐条保持(落点判定)+登记件新增对应键〔QA收口 V4〕 | 探针 | 候选矩形中心/停点真钮/三选一卡面 push_input | 既有落点断言逐条+覆盖登记件键集不回退 | 新增:停点链与控件级真输入命中 | -| `design/engineering/test-conventions.md:23` 到达型候选+停点真输入化(7 探针) | fx_shot_probe.gd:47/ui_tune_probe.gd:109/shot_probe.gd:147/ui_probe.gd:83/t17_defer_probe.gd:39/layout_probe.gd:32 → candidate_rect+push_click_at;ui_struct_probe.gd:257 → push_click(node_overlay._btn) | 7 探针各孤立直跑绿〔QA收口 V5〕 | 探针 | 候选节点矩形中心与停点真钮 push_input | 各探针既有断言保持绿+登记件候选/停点键 | 新增:停点链与控件级真输入命中 | -| `design/engineering/test-conventions.md:23` 调试浮窗面真输入化(4 处) | ui_tune_probe.gd:59/62/67/97 → push_click | ui_tune_probe 孤立直跑绿〔QA收口 V6〕 | 探针 | 调试浮窗真钮 push_input | 既有断言保持绿+登记件浮窗键 | 新增:停点链与控件级真输入命中 | -| `design/engineering/test-conventions.md:23` 系统测试宿主候选真输入化 | system_test.gd:433 → candidate_rect+真输入 | 系统测试套件直跑绿〔QA收口 V7〕 | 系统 | system_test 宿主 push_input | 既有断言保持绿 | 新增:停点链与控件级真输入命中 | -| `design/engineering/test-conventions.md:23` 三选一覆盖层单元真输入化(5 处) | reward_overlay_test.gd:60/64/65/66/76 → 真输入 | 单元与集成套件直跑绿,断言语义逐位保持〔QA收口 V8〕 | 单元 | 覆盖层 root 挂树 push_input | 既有断言逐条(三卡呈现/选择外发/强制确认两段式/结果态) | 新增:停点链与控件级真输入命中 | -| `design/engineering/test-conventions.md:52` 死接缝同批清理(5 文件 11 方法) | ap_bar_view 2+curio_pick_overlay 4+node_overlay 1+debug_overlay 3+level_map_screen 1 删除 | 全仓 .gd 面双模式 grep 零命中(定义清+调用清)〔QA收口 V9〕 | 单元 | 不适用(非行为改动——依据=转换后零调用,玩家可见行为零变化;grep 判据 .gd 面可复跑) | 全仓 .gd 面 grep(词表 candidate/continue/card/confirm/refresh/apply/reset/simulate,--include=*.gd):定义行 `func press_` 与调用行 `.press_` 各零命中(正则全文见 T6 验证步) | 新增:停点链与控件级真输入命中 | - -测试削弱申报:本批允许删除的旧断言=只验证被删 press_* 死接缝的护栏(如有)——删除随 T6 同批、逐处 grep 在案;其余既有断言零削弱。能力清单同批增行 3 行(game/tests/README.md 旅程段六:终局结算框关闭动线零引擎报错/停手钮真输入命中与停手收轮落效/停点链与控件级真输入命中)——已随卡落盘。 - -## 10. 异常分级 - -- **L1 自救(一次重试)**:探针驱动落点断言失配(矩形中心取点偏移、使能窗 tick 时机)——修驱动重跑该探针。 -- **L2 记录继续(连续 3 次同红灯升级)**:转换点在特定战局形态下偶发不命中——记录场景、缩窄触发条件后继续。 -- **L3 停机写报告等用户**:①使能窗在真实局不可达成(停手钮使能投影与相位快照永久错位)——停卡呈报;②既有断言保不住绿且非驱动问题(疑似产品缺陷浮出)——停卡登记,禁顺手修;③机检预算互斥/闸判据与本卡契约冲突——停卡退写卡段;④journey 全线跑批读数结构性变化(上报结构变、fatal 新增)——停卡呈报。 - -## 11. 代拍板白名单 - -- 断言失败消息文案与尾缀编号(〔QA收口 V1〕–〔QA收口 V9〕)分配。 -- `_stoptest_tick` 状态机 tick 上限、使能窗等待时长、触发条件的具体写法。 -- candidate_rect 矩形命中面的扩边余量(以 `_candidate_at` 命中面同源为准)。 -- journey 停手行为触发时点微调(每战至多一次框架内的具体时点)。 -- 死接缝删除的批次内顺序与头注/注释同步措辞。 - -## 12. 待裁点 - -零待裁点,开工门=U0。两个范围分叉已于 2026-11-06 由用户裁决写入:B1=探针面+自动试玩(C);B2=全清 41 处(含调试浮窗面与非探针层)。 - -## 13. 落位与可复用性预检 - -- **复用面**:真输入合成单点复用 `game/probe/probe_ui_util.gd`(push_click/push_click_at/push_wheel 现役共用面——grep 同职责实现仅此一件,tests 面经 preload 复用,禁复制第二份);覆盖登记复用 `game/probe/probe_coverage_recorder.gd`(现役命中登记口,零改动);定型化段形态复用 ui_click_probe 现役 `_locktest_tick` 状态机先例。 -- **唯一面**:本批新增公开面仅 1 个——`LevelMapScreen.candidate_rect(index: int) -> Rect2`。为什么不能复用既有:press_candidate 是「按序号提交选路」的动作口而非矩形出口,真输入点击需要命中矩形坐标;其内部 `_cand_ids`/`_layout`/`_candidate_at` 均为私有计算面——公开读口是唯一合规出口,且与命中检测同文件同源(落点唯一)。新增前已 grep:全仓无同名与同义标识符。 -- **分层与交互面**:本批零产品码新依赖——A2 为视图内容错;candidate_rect 为视图公开读口(零核心写调用,依赖方向不新增);探针/sim/tests 面改动不进任何 S 系静态扫描面(code-conventions §4.13 分档在案),其可靠性由场景探针/冒烟/单元与集成/系统测试四条运行期通道承接。 - -## 14. 禁为机检文本保留无效成员 - -本批含删除面(死接缝 11 方法)。条款:禁止为迎合机检消息文本(含计数)而保留或新增无效成员/别名;全仓 grep 零残留(T6)是删除完成的唯一判据;机检键与本契约互斥时实现段停卡呈报,不得自造第三条路。 - -## 15. 实现规范预算 - -无新增文件。存量触面一查:`level_map_screen.gd` 公开方法数=删 press_candidate(−1)+增 candidate_rect(+1)=净持平,较登记基线不升;其余 5 个视图文件只删不增(下降)。探针/sim/tests 面不在 S 系扫描面(code-conventions §4.13),无预算对账键;新写测试件全类型标注照 test-conventions §6 执行。 - -## 16. 复核记录 - -| 轮次 | 复核者身份 | 发现 | 去向 | 处置结果 | -|---|---|---|---|---| -| 1 | 只读子代理(Explore,未参与本卡撰写,2026-11-06) | F1 验收档行粗体致 C4 正则不匹配 | 补写 | 头部行去粗体,「验收档:中」冒号紧随词面(pipeline_gate.py:66) | -| 1 | 同上 | F2 journey_player.gd:449/:457 误标 node_overlay——实证 :446 `co`=curio_overlay,实为三选一继续钮 | 补写 | §3 表②与 T3 更正映射::449/:457 → curio 继续真钮;:380 保持 node_overlay._btn | -| 1 | 同上 | F3 battle_end_overlay.gd:331(_play_celebrate)同型第二处 get_meta 漏修——只修 :194 则 V1 在胜利轮仍红 | 补写 | T1 实装与 R1 扩至 :194+:331 两处同改;R1 真实入口改 open_victory→close→open_defeat→close 全序 | -| 1 | 同上 | F4 ui_struct_probe.gd:257 停点转换无对照表行承接(反向闭合缺口) | 补写 | R5 行扩为 7 探针(到达型候选+停点),改动格并入 :257 | -| 1 | 同上 | F5 V9 grep 字面命中卡自身与 shot_probe.gd:9 注释——审计复跑必红 | 补写 | V9 限定全仓 .gd 面(--include=*.gd);注释随 T5 同步清零 | -| 1 | 同上 | F6 V9 点模式抓不到定义残留(func 行无点前缀) | 补写 | V9 扩双模式:定义清+调用清各零命中 | -| 1 | 同上 | F7 R9「6 文件 11 方法」计数误(实为 5 文件) | 自判 | 改「5 文件 11 方法」(逐文件数 2/4/1/3+1=11,grep 实证) | -| 1 | 同上 | F8 R1 锚语义弱——test-conventions.md:60 为闸件条文非行为规格句,design/ 无更强句 | 自判(判定不改) | 不改+依据:缺陷修复行预期值来源=设计事实源指认的缺陷本体;:60 为「报错标记即违规」工程规范句、C5 存在性过;为日志噪声修复新立设计句不成比例 | -| 1 | 同上 | F9 两处行号微漂(ap_bar :111→:110-111;press_candidate :469-477→:469-479) | 自判 | 就地校正 | -| 1 | 同上 | C3 机检红——R9 能力行格「非行为改动(R9)」不符 CAP_ROW_RE | 补写 | R9 能力行格改「新增:停点链与控件级真输入命中」,非行为改动标记留在真实入口格(pipeline_gate.py:617-622) | -| 1 | 同上 | 引擎三查:get_meta/has_meta 报错行为「未判」(NEVER/Gotchas 无条目);push_input 成对与 Tween.kill 守卫两查成立 | 自判(不改) | T1 直跑 grep 判据可实证收口,不阻塞开工 | diff --git a/reports/需求卡片-精英专属池-2026-11-06.md b/reports/需求卡片-精英专属池-2026-11-06.md deleted file mode 100644 index 67a28355..00000000 --- a/reports/需求卡片-精英专属池-2026-11-06.md +++ /dev/null @@ -1,309 +0,0 @@ -# 需求卡片 · 精英专属池(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-反哺点-<日期>.md` | -| `design/gdd/systems/表现与支撑/数据配置.md` 加载期错误类别表(第 104 行) | 新增 `dangling_base` 属「悬空引用」既有类别的一个实例,表述不变 | 无需反哺;若审计认为需点名,列反哺点 | -| `design/gdd/03-内容规模.md` 第 66 行「精英节点与词缀系统——只预留了字段位」 | 精英怪本体已落表(行类+池继承),节点仍未接线 | 列反哺点进 `reports/iter-反哺点-<日期>.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-验收审计-<日期>.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-实现报告-<日期>.md`:各卡状态、实际对照表(第 8 节七行补「结果」格与测试 `文件:行`)、实现决定记录(零拍板则写一行「零拍板」)、遗留读数义务(精英 EV 重锚归数值统一修正批)、实机目检总清单(本批零项,理由=暂不接线无玩家可见面)。 -- [ ] T5.2 写 `reports/iter-反哺点-<日期>.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 批注避开退役词 | diff --git a/reports/需求卡片-营地交互修复批-2026-11-05.md b/reports/需求卡片-营地交互修复批-2026-11-05.md deleted file mode 100644 index 99f5b079..00000000 --- a/reports/需求卡片-营地交互修复批-2026-11-05.md +++ /dev/null @@ -1,438 +0,0 @@ -# 需求卡片 · 营地交互修复批(2026-11-05) - -> **来源**:待办清单条目「营地交互修复批——大门无断点开局被开始层盖住/确认框钮序/营地顶栏无栏体」(2026-11-05 登记,来源=会话提及) -> **唯一事实源**:`design/gdd/ux/camp.md` v2.8 §顶栏 · §点选反馈 + `design/gdd/systems/表现与支撑/HUD框架.md` §提示与弹层(三条纪律·其三) + `design/gdd/systems/冒险循环/关卡节点地图.md` §核心循环位置 + `design/art/art-bible.md` v3.43 §6.2 -> 验收档:中(三件做错的后果都是玩家可见但不损持久状态——呈现与交互逻辑;不触存档写读、不触结算公式、不触 RNG 流。判据=本技能第 16 节单维失败代价) -> **改动面**:游戏代码(`game/` 表现层+测试面)。文档面已由文档批落定为现行规格,本卡不携任何 `design/` 改动。 -> **编排状态**:未编迭代(roadmap 现行最高编号=迭代 52,已完成;本卡待 iter-plan 段编排) - ---- - -## 1. 目标与完成定义 - -三件互不相干的营地屏交互缺陷,一批修完: - -1. **大门无断点开局被开始层盖住**——玩家点大门、按「是」之后,冒险其实已经开局,但主菜单层(开始层)重新显出来并把冒险画面盖住,玩家看到的是主菜单,误以为没开始。修完=从大门真实点击进入后,开始层不可见、关卡画面(节点图选路停点)可见。 -2. **确认弹窗按钮位次反直觉**——同一个共用弹窗件把「维持现状」那颗放在左、「推进」那颗放在右,四处消费方(删档/大门三出口/大门两出口/篝火)皆然。修完=整体镜像为「推进在左、次推进居中、维持在右」,且位次与语义的绑定有真点验收。 -3. **营地顶栏看不出是一行 HUD 栏**——顶栏件已装配、已落座、预留位 48px 全宽都在,缺的是那层看得见的底:现在是透明 Control 只挂一枚徽章,而徽章的烛光黄底对背后天空均色只有 1.29:1。修完=按 camp.md v2.8 §顶栏 定值画出栏体(`CAMP_HEADER_BAND` × 不透明度 0.80),徽章顶格右位落进栏内,并有尺寸与对比的机检。 - -**完成定义**:四条全落即算这批做完—— - -- 对照表(第 8 节)八行断言(R1–R8)在当轮真实跑批中执行且通过,无红项遗留; -- 第 8 节标注的两行新增能力已随写卡段落进 `game/tests/README.md`,实现批末核对名实相符; -- 回归面(第 5 节列的七条未改动动线)在跑批中仍绿,未因位次改动或栏体新增而失守; -- 末卡产出物(实现报告+反哺点清单)写齐,`reports/` 两份落位。 - -真人目检项(营地顶栏观感)登记进实现报告实机目检总清单即算义务了结,**不作合回前置**(AGENTS.md 红线:真人检测只登记不阻塞)。 - ---- - -## 2. 设计事实源 - -本节为卡片设计依据的唯一出处声明,与待办清单条目实况的闭合凭据同批一致: - -| 需求点 | 现行规格句 | 出处 | -|---|---|---| -| 件1 | 点大门永远先出确认,无未完冒险=是否开始新冒险 | `design/gdd/ux/camp.md:16` | -| 件1 | 关卡开始 → 呈现节点图选路停点(关卡画面;入口不自动进入) | `design/gdd/systems/冒险循环/关卡节点地图.md:78` | -| 件2 | 确认弹窗的按钮位次定值:推进钮在左、维持现状钮在右,三钮形态次推进居中,四处共用同一件同一序 | `design/gdd/systems/表现与支撑/HUD框架.md:90` | -| 件3 | 栏体底=`#6E4526`×不透明度 0.80、高 48px 全宽浮层、栏内只钥石徽章一件右位顶格、验收=目检窄带可辨+机检对落位带底色 ≥3:1 | `design/gdd/ux/camp.md:41` | -| 件3 | 色板五件对齐表在册色 `CAMP_HEADER_BAND #6E4526`(机检〈ui_kit 五 token 与本表一致〉) | `design/art/art-bible.md:452` | -| 件3 | 命中区不侵入顶栏禁区(y ≤ 48) | `design/gdd/ux/camp.md:37` | - -预览人审在案:2026-11-05 会话内实尺 HTML 预览(十张已过审场景层按 `camp_scene_layout.tres` 现值叠放+1:1 顶栏放大条+页内 WCAG 即时算式),用户审语「我看了预览的效果是OK的」,选定项=甲 深棕带 × 不透明度 0.80;快照文件 `chat-session-visualizations/…/visualizations/snapshot-444250310dc22234ac755b11fb31ce6885adb634b271c7083d53cc5d72b98640.html`(会话侧不可变快照,非仓库件)。像素级判据句已随附进 `camp.md` v2.8 §顶栏。 - -顶栏这块带子的落点定稿(用户 2026-11-05/11-06 四次裁决的终态,全程留痕见第 15 节 Q1 裁决史):**一个 UI 物件的外观不得拆两处**——色值与透明度、铺满方式、不吃点击、挂上宿主、返回句柄这五件事全在公共件 `ui_kit.gd` 的**一个具名公开出口**里;出口只接「挂到谁身上」一个形参,色与点击语义写死在它内部(它们是这块带子的定义,不是调用方每次要重述的选择)。同时**不收编盘上任何同形旧实现**:`ui_assembler.gd:224-230`、`ui_kit.gd:486-491`、`ui_kit.gd:537` 只是形状撞车、变化原因各不同,把它们绑进同一个出口=为没到来的问题做设计,并把回归面扩到全站弹窗底与两个全屏页。顶栏件只调该出口一次,不再自建 ColorRect。两项引擎实测(4.7.2,工程外临时工程跑通后即删,与本条封装方式无关,仍成立):①`Color(母token, 0.80)` 形态的 const 派生编译通过,`to_html(true)` 读数 `6e4526cc`、三分量与母 token 逐一相等;②**色道存单精度浮点,`.a == 0.80` 判为 false**(实测 `a=0.80000001192093`)——断言一律写 `to_html(true) == "6e4526cc"` 或整体等值比较,禁浮点分量直等,否则实现正确而断言红,最容易的自救就成了放宽阈值(触 test-conventions §8.5 禁止削弱测试)。 - ---- - -## 3. 现状事实(2026-11-05 实查;开工日自行复核行号) - -### 3.1 件1——开始层可见性无单点 - -- `game/presentation/camp_shop_presenter.gd:85`:`on_camp_closed()` 体内无条件 `start_overlay.visible = true`。该函数的本职是「回主菜单」,篝火离场(`game/presentation/main.gd:214`)与 Esc 返回主菜单(`game/presentation/main_esc_flow.gd:46`)都靠这句显出菜单——**语义正确,不是缺陷本体**。 -- `game/presentation/main.gd:211-212`(`_on_confirm_accepted()` 的 `"gate_new"` 分支)与 `game/presentation/main.gd:223-224`(`_on_confirm_secondary()` 的 `"gate"` 分支):两处都是先调 `camp_pres().on_camp_closed()`(把开始层显出来),紧接着调 `_start_adventure()`。 -- `game/presentation/main.gd:292-308`:`_start_adventure()` 全函数体(体止于 `:308` 的 `return`,`:311` 已是下一函数声明行)零处触碰 `start_overlay`——于是上面那句「显出来」没有对手句把它收回去。失败分支(`main.gd:306-307` `fatal_screen`)在 T1.1 落笔后开始层终态由「可见」变「隐藏」,该终态差在本卡第 5 节明示为可接受(致命屏自会接管,无菜单可用)。 -- 既有先例=每条启动路径在自己函数内部自管开始层:`game/presentation/main.gd:194`(`_start_adventure_from_menu()` 内先隐藏再转调)、`game/presentation/main.gd:246`(`_resume_from_menu()` 内隐藏)。所以现状的隐藏点是散在入口层的两处,缺的是开局那一条。 -- `_start_adventure()` 全库调用点仅三处(`main.gd:195`/`212`/`224`),无一需要开局后保留开始层。 -- 层序事实:`game/tests/system_test.gd:87-89` 断言「start_overlay 在冒险屏壳之上(盖住战斗内容)」——被盖住的正是冒险画面,故真机观感=「画面回主菜单」。 -- 覆盖缺口事实:`game/presentation/main.gd:210` 的 `"gate_new"` 与 `main.gd:223` 的次确认分支,现有断言只核 `run_scope.is_adventure` 与营地场景屏隐藏(`game/probe/ui_click_probe.gd:703-705`),**没有一条核开始层可见性**,故缺陷在绿批里静默存活。 - -### 3.2 件2——弹窗件位次写死 - -- `game/presentation/views/confirm_dialog.gd:31-39`:`_init()` 内三颗钮的 `btn_row.add_child()` 次序=取消 → 次 → 确认。 -- 信号按按钮对象路由、不按位次:`confirm_dialog.gd:32/35/38` 各自 `.pressed.connect(_emit_cancelled/_emit_secondary/_emit_confirmed)`——换序不改路由,文案也不用来认钮。 -- 四处消费方(全部经同一件):删档确认 `game/presentation/main_overlay_flow.gd:129`(钮标「删除」/「取消」)、大门有断点三出口 `main_overlay_flow.gd:79-80`(「继续上一段冒险」/「开始新冒险」/「取消」)、大门无断点 `main_overlay_flow.gd:83`(「是」/「否」)、篝火离场 `main_overlay_flow.gd:73`(「离开」/「留下」)。 -- 现有断言只核「次钮在两出口形态下隐藏」(`ui_click_probe.gd:696`),**无一条核位次**。 - -### 3.3 件3——顶栏件有装配无栏体 - -- `game/presentation/views/camp_hud_band.gd:10-17`:`_init()` 设 `PRESET_TOP_WIDE` + `custom_minimum_size=(0,48)` + `mouse_filter=MOUSE_FILTER_IGNORE`,体内只挂一枚徽章,**无任何底色件**——即整条顶栏是透明的。 -- 徽章现状:`camp_hud_band.gd:15-16` 设 `PRESET_CENTER_RIGHT` 后 `position=Vector2(-160, 8)`(注释自标「代拍板 3」)。 -- 徽章自高=48px:`game/presentation/views/ui_kit.gd:640` 的 `panel_flat(..., Vector4(14, 8, 14, 8))` 给图标 32px 上下各加 8px 内边距=48px,正等于栏高——**顶距 8px 在栏内放不下**,落座只能顶格。 -- 装配链在位:`game/presentation/main_ui_build.gd:120-121` 造件并调 `set_hud_band()` → `game/presentation/views/camp_scene_view.gd:88-91` 把件塞进 `_hud_slot` → `camp_scene_view.gd:188` 预留位 `custom_minimum_size=(0, layout.hud_band_h)`,取数自 `game/data/tables/camp_scene_layout.tres` 的 `hud_band_h=48`(schema 见 `game/data/schemas/camp_scene_layout_table.gd:7`)。 -- 盘上「新建 ColorRect+铺满宿主」的写法现有三处,意图各不相同,本批一处都不动:`game/presentation/ui_assembler.gd:224-230` `overlay_bg(host, color)`(亮底面板与模态压暗遮罩共用,外部调用者零、仅该文件自身 `:100`/`:214` 用,**没设 mouse_filter**);`game/presentation/views/ui_kit.gd:486-491` 私有 `_modal_dim()`(同一份东西的第二实现,同样不设 mouse_filter,仅 `:511` 经 `modal_shell()` 一处用、经该壳扇出 11 家模态消费件);`ui_kit.gd:537` 页壳底板(`page_shell()` 内,**显式**写 `MOUSE_FILTER_STOP`、色取 `BG_BRIGHT`/`BG_ROOT` 实色,其后紧跟石纹层与暗角层作兄弟节点)。三者与顶栏带只有形状撞车:前两者的变化原因是「遮罩挡不挡点击」,页壳底板的变化原因是「这块屏用哪档底色」,顶栏带的变化原因是「这条 HUD 带的定值」。另:顶栏件 `camp_hud_band.gd:14` 现役已在调 `UiKit.keystone_badge()`——视图件引公共件在本文件内就有先例,故出口落 `ui_kit`、不经装配器。用户 2026-11-06 终裁=**顶栏带的外观整件封进公共件一个具名出口,同形旧实现不收编**(早先两版——「值进公共件+矩形视图自建」与「四份同形收成带形参的通用出口」——都已作废,逐次理由见第 15 节 Q1 裁决史与第 12 节末段)。 -- 落位带实际背景:营地背景层 `game/assets/art/scene/scene_camp_bg.png` 的 y0–48 带均色实测 `#DEEAE7`(逐像素取样,画面最上的可点物件是大门,顶缘 y=250,故 48px 带整条落在远景天空上)。徽章烛光黄底 `#F6C667` 对该天空 1.29:1;定值 `#6E4526`×0.80 叠后呈色 `#84664D`,对天空 4.27:1、对徽章底 3.31:1。 -- 像素取样先例:`game/tests/unit/presentation/terrain_tile_sets_test.gd:107` 已用 `img.get_pixel()` 在单元套内取样贴图。 -- 无 golden 锚:`game/tests/golden/README.md`「未建锚面备案」明写营地屏无改前 golden 锚,该面等价证据=探针/单元断言+实机目检。 - ---- - -## 4. 设计契约(红线,违反=L3 停机呈报) - -- 🔴 **契约1|冒险启动路径的隐藏点收一处**:**限「开局」与「续玩」两条路径**——隐藏责任只许落在 `_start_adventure()`(开局)与 `_resume_from_menu()`(续玩)两个函数内部。第 3.1 条的先例形态即本契约依据。**本契约不管其余开层自管点**:全库开始层显隐共 13 处(`camp_shop_presenter.gd:43`/`:85`、`main.gd:137`/`:194`/`:246`、`main_adventure_flow.gd:145`、`main_debug_flow.gd:88`、`main_overlay_flow.gd:8`/`:17`/`:41`/`:48`/`:95`/`:101`),那些是选档层/生涯页/终局回菜单等各自开合面的自管句,本批一律不动、也不受本契约约束。禁再新增**开局或续玩路径**上的第三处隐藏点,禁把隐藏写回 gate 出口(调用方)。 -- 🔴 **契约2|`on_camp_closed()` 语义不动**:`camp_shop_presenter.gd:85` 那句显示开始层是本批禁改项——篝火离场与 Esc 返回主菜单两条动线靠它。改动=回退主菜单功能。 -- 🔴 **契约3|位次改动只动 `add_child` 次序**:`confirm_dialog.gd:31-39` 的三句连接(`.pressed.connect(...)`)、三个钮对象的创建与文案参数一律不动;四处消费方的 `open()`/`open_three()` 传参零改动。位次与语义的绑定由第 8 节 R4 行的坐标真点断言钉。 -- 🔴 **契约4|这块带子的全部外观封在公共件的同一个具名出口里**:`ui_kit.gd` 出一个公开出口(本卡定名 `camp_hud_band_surface(host)`,实现可按同文件命名习惯微调后缀形态,见白名单第 6 条),**色值与 α、铺满、不吃点击、挂上宿主、返回句柄**五件事全在它内部;**形参只有 host 一个**——禁把颜色与「吃不吃点击」开成形参(那等于把这块带子的定义推回调用方每次重述,也正是本契约要禁的拆两处)。色值取派生常量 `Color(CAMP_HEADER_BAND, 0.80)`(三分量继承在册 token,同文件先例 `TOAST_BG:189`/`TIP_BG:190`/`HP_BAR_TRACK:200` 注「收口单点——非色板新增」)。**同时禁收编无关同形件**:`ui_assembler.gd:224-230`、`ui_kit.gd:486-491`、`ui_kit.gd:537` 三处原样不动,出口也不得被它们转调——形状撞车不等于同一件事,绑起来就得到一个同时要回答「页底用哪档色」「遮罩挡不挡点击」「HUD 带穿不穿点击」三个变化原因的函数,并把回归面扩到全站弹窗底(用户 2026-11-06 终裁,见第 15 节 Q1 裁决史④与第 12 节末段)。依据=`ui_kit.gd:2`「全站取色/描边唯一出口,换皮只改本文件」+ code-conventions §1.1 一个类一个职责、单一变化原因判据。色板快照不受新常量影响(`tools/gen_palette_baseline.py:42` 只正则 `Color8(数字,数字,数字)`,带 α 的 `Color(...)` 从不进快照)。 -- 🔴 **契约5|不吃点击由出口内部保证**:栏体必须 `mouse_filter = Control.MOUSE_FILTER_IGNORE`,写死在出口内、不靠调用方记得设(顶栏件自身 `camp_hud_band.gd:13` 同款设置是既有锚)。漏设=48px 带内点击被栏体吃掉,与 `camp.md:37` 禁区纪律叠加成「顶排物件点不动」;且 ColorRect 默认即 STOP,漏设不会报错只会静默失守(同文件 `:540` 显式 STOP、`:864` 与 `camp_scene_view.gd:145` 须显式 IGNORE 为旁证)。本条与契约4 合起来把这块带子的外观压到一处。 -- 🔴 **契约6|本批禁写文档面**:`design/` 整个目录、`待办清单.md`/`体验验证清单.md` 两份根流程清单、`game/tests/README.md` 一律禁改(能力两行已由写卡段落表,实现批只改名实相符);产出物只准落 `reports/`。 -- 🔴 **契约7|禁变异类测试与撤销类取证**(test-conventions §8.4,全项目红线):本批所有断言从真实入口进入、绑被测改动特有的可观测提交面,禁人为制造红、禁回退 hunk 取证。 - ---- - -## 5. 范围边界 - -**做**: -1. `_start_adventure()` 入口收一个隐藏点,摘掉 `main.gd:194` 的冗余句; -2. `ConfirmDialog` 三颗钮的 `add_child` 次序整体镜像; -3. 公共件出一个具名出口封装这块带子的全部外观(色值与 α、铺满、不吃点击、挂上宿主、返回句柄)+ `CampHudBand` 改调该出口、徽章落座改右对齐容器; -4. 上述三件各自的测试(对照表 8 行 R1–R8)+能力清单两行(写卡段已落)+回归面确认。 - -**不做(含去向)**: - -| 不做的东西 | 为什么 | 去向 | -|---|---|---| -| 「破坏性确认与常规确认禁止同位」(art-bible §4.5 清单 #7 后半句/interaction-patterns §7)在弹窗层的闭合 | 该句系 2026-09-14 文档骨架初版提交随件进入,全库查无用户裁决记录,且 battle.md:335 指定的无障碍基线权威(HUD框架 §可访问性基线)不含它——它是不是用户定的规则,本身待裁 | 本卡不动它;现状四处同位属既有状态,不随本批产生或消失。要不要闭合,归用户另发令,另立待办条目 | -| 顶栏栏内加第二件(存档位号/关卡语境等) | 用户 2026-11-05 裁「栏内只放钥石徽章一件」,左位不放件 | 无 | -| 营地场景层坐标、素材、七物件摆放的重排 | 属场景重排批,不与本卡混装(用户 2026-11-05 口径:代码批与素材批分两张卡) | 归那一批自己的卡 | -| 把盘上三处同形铺面写法(`ui_assembler.gd:224-230`、`ui_kit.gd:486-491`、`ui_kit.gd:537`)收敛成一个通用铺面器 | 形状同而变化原因不同(遮罩遮挡语义/页面底色档位/HUD 带定值);收编=把三个不相关变化原因绑进一个带形参的函数,回归面扩到全站弹窗底与两个全屏页底板,而这三个地方今天都没有待改的东西——为没到来的问题做设计(用户 2026-11-06 终裁,第 15 节 Q1 裁决史④) | 无。三处原样留底;日后若真出现意图相同的第二个消费者,届时按 code-conventions §1.1 重议 | -| 营地屏 golden 建锚 | 无改前基线可留底,新建锚不属缺陷修 | 不登记(顶栏观感走目检) | -| `main.gd:137` 的 boot 期 `start_overlay.visible = true` | 启动默认态,与三件无关 | 无 | - -**回归面(本批不改、但跑批必须仍绿)**:七条未改动动线——大门有断点按「继续上一段冒险」/大门按「取消」「否」/篝火「离开」「留下」/Esc 浮窗三项/五功能窗开合/进入存档与生涯页返回的开始层显隐/终局回菜单。其中前三条已被 `ui_click_probe.gd:679-723` 段覆盖(段止于「开场行三路径段」头注之前),本批在该段内追加断言,不新建平行段。 - ---- - -## 6. 关联文档同步面 - -实现批禁写 `design/` 与根规则文件;下表逐条给出「要改哪一节、改成什么、依据是什么」,实现批把命中项列进 `reports/iter<53>-反哺点-<日期>.md`,由用户在会话中裁决后归文档批落文。 - -| 文档 | 关联点 | 同步义务 | -|---|---|---| -| `design/gdd/ux/camp.md` v2.8 §顶栏 | 本批把「栏体定值」变成实装;若实现期样张/目检意见要求改 α、改右位内缩或改栏高,现行句即落后 | 反哺点:只在**实际改值**时列,附实测读数;未改值不列 | -| `design/art/art-bible.md` v3.43 §6.2 钥石余额行 | 同上(该行已把事实源指回 camp §顶栏,改值须两处同改) | 反哺点:与上一行同批列,禁单改一处 | -| `design/gdd/systems/表现与支撑/HUD框架.md` §提示与弹层·其三 | 「四处共用同一件同一序」实装后须与代码一致;若实现发现某消费方不遵此序(例如自拼按钮行的弹窗件),句与码冲突 | 反哺点:发现即列,附 `文件:行` | -| `design/engineering/architecture/architecture.md` 呈现层模块表 | 两处随本批失真:`:175` CampHudBand 行现写「顶栏 48px 全宽窄条:**钥石余额 badge 唯一呈现**」——加可见栏体后badge 不再是唯一呈现物;`:168` D1 HUD 行的视图单元接口若因本批改动而与「信号外发、setter 只读注入」不符亦须同步 | 反哺点:实现批禁写该文档;本批落地后把该行的实际形态(栏体色面+badge 右位)列进反哺点清单,附 `文件:行` 与实装读数 | -| `体验验证清单.md` | 顶栏观感属「需真人试玩才能下结论」项,需一行观测项 | 反哺点:实现批禁写该清单,由文档批落;卡内先在实现报告目检总清单登记 | -| `game/tests/README.md` 能力表 | 两行新增能力已由写卡段落表(第 8 节能力行列名即清单名) | 实现批禁写;批末只核「清单名=实际落地函数名」,名实不符=停卡退回写卡段 | -| `roadmap.md` 迭代总表 | 本卡尚未编入迭代 | 非实现批义务,归 iter-plan 段 | -| (非文档面·写卡期发现一)`tools/pipeline_gate.py:68` 判据出处行锚的机检式 `ANCHOR_RE` 字符类=`[A-Za-z0-9_-.\\/]`,不含中文段 | 本库现行设计文档多为中文名(`HUD框架.md`/`关卡节点地图.md`/`待办清单.md`),凡判据句落在这类文档即无法被机检认锚——本卡 R2/R3/R4/R8 因此同时挂一个 ASCII 路径锚(`camp.md`/`level-map.md`),中文出处改以「第 N 行」散文形写明 | **已登记**:待办清单「流水线闸认锚式不含中文名文档」条(工具代码/待执行),本批不动闸件 | -| (非文档面·写卡期发现二)`game/tests/unit/contracts/source_guard_test.gd:85-99` 列目录不递归 | 「V1d 层序落位单口」的扫描面漏掉 `views/` 与 `scenes/` 两个子目录(注释仍写「presentation 无子目录」,实为两个);视图层的插位不在该闸视野内。当前无漏网真违规(`views/ui_kit.gd:841` 属卡片内部重排) | **已登记**:待办清单「层序落位单口检查的扫描面不含子目录」条(工具代码/待执行);两目录是否纳入扫描面本条不预裁,启动时再裁 | - ---- - -## 7. 文件结构图 - -| 文件 | 职责 | 新增/改动 | 行为改动 | 验收行 | -|---|---|---|---|---| -| `game/presentation/main.gd` | 组合根:冒险启动与确认分派编排 | 改动(`_start_adventure()` 加一句;`_start_adventure_from_menu()` 删一句) | 行为改动 | R1、R2 | -| `game/presentation/views/confirm_dialog.gd` | 通用确认弹窗视图件 | 改动(三句 `add_child` 次序,**不动成员面**) | 行为改动 | R3、R4 | -| `game/presentation/views/ui_kit.gd` | 呈现层共享工厂与全站取色单点 | 改动(新增带 α 派生常量 + **新增一个具名公开出口**,该出口承载这块带子的全部外观;既有三处同形铺面写法一律不动) | 行为改动(顶栏呈现源) | R5、R6 | -| `game/presentation/views/camp_hud_band.gd` | 营地顶栏 HUD 件 | 改动(调该出口得栏体,不再自建 ColorRect;徽章落座改右对齐容器) | 行为改动 | R5、R6 | -| `game/probe/ui_click_probe.gd` | 真点探针:大门两分支段所在宿主 | 改动(同段追加断言) | 非行为改动(测试面) | R1、R2、R4、R7、R8 | -| `game/tests/system_test.gd` | 系统测试宿主 | 改动(新增 `_smoke_camp_hud_band()`,接进 `_split_tail()` 的 await 链〔`:40-44`〕) | 非行为改动(测试面) | R5、R8 | -| `game/tests/unit/presentation/camp_scene_layout_test.gd` | 营地屏布局与顶栏禁区单元套 | 改动(新增 `_test_hud_band_contrast_over_bg()`) | 非行为改动(测试面) | R6 | -| `game/tests/unit/presentation/confirm_dialog_test.gd` | 确认弹窗按钮位次与语义单元套 | **新增** | 非行为改动(测试面) | R3 | -| `game/tests/README.md` | 能力清单 | 改动(两行,写卡段落) | 非行为改动 | — | - -结构图与第 12 节「落位与可复用性预检」互指:改动件七个(四件表现层+三件测试面)、新增件仅一枚单元套;这块带子的全部外观收在公共件的同一个具名出口里,出口只服务这块带子(判据见第 15 节 Q1 裁决史④与契约4)。 - ---- - -## 8. 验证闸(改动—验收对照表) - -| 行 | 需求点(判据出处行锚) | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 | -|---|---|---|---|---|---|---|---| -| R1 | 件1 大门无断点按「是」后开始层不可见(`design/gdd/ux/camp.md:16`+`design/gdd/systems/冒险循环/关卡节点地图.md:78`) | `main.gd:211-212` 分支经 `main.gd:292` 新入口隐藏 | `ui_click_probe.gd:_ready`(大门无断点段追加「确认后开始层不可见」) | 探针 | 营地场景根大门命中区 → `ProbeUiUtil.push_click_at` 真点 → 弹窗「是」钮 `ProbeUiUtil.push_click(_confirm_btn)` 真点 | `main.ui.screens.start_overlay.visible` 取值(被测改动特有的可见性提交面) | 既有:营地大门两分支确认与断点续玩接线 | -| R2 | 件1 开局落在节点图选路停点(`design/gdd/ux/level-map.md:69`;停点句唯一出处=`design/gdd/systems/冒险循环/关卡节点地图.md` 第 78 行「关卡开始 → 呈现节点图选路停点」) | 同 R1 | `ui_click_probe.gd:_ready`(同段追加「关卡画面在位」) | 探针 | 同 R1 真点链(大门命中区真点 →「是」钮真点) | `run_scope.is_adventure` + `main.ui.modals.run.level_screen.visible`(停点呈现面,非终态推断)。**本行是开局终态在位断言,被测改动的特有提交面由 R1 承载**——`is_adventure` 在既有探针已断(`ui_click_probe.gd:704`),把件1 的改动绑在它上不成立,故本行的效力=与 R1 同批缺一即红 | 既有:营地大门两分支确认与断点续玩接线 | -| R3 | 件2 两出口与三出口形态的按钮位次=推进→次→维持(`design/gdd/ux/camp.md:16`;位次定值唯一出处=`design/gdd/systems/表现与支撑/HUD框架.md` 第 90 行「三条纪律·其三」) | `confirm_dialog.gd:31-39` 三句 `add_child` 次序镜像;**成员面与连接一律不动** | `confirm_dialog_test.gd:_test_two_button_row_order`;`confirm_dialog_test.gd:_test_three_button_row_order` | 单元 | 视图件对外入口 `ConfirmDialog.open(text, confirm_label, cancel_label)`/`open_three(text, confirm_label, secondary_label, cancel_label)`——即四消费方实际用的那两个公开方法(`main_overlay_flow.gd:73`/`:79`/`:83`/`:129`) | 测试自己传入三档互异文案(如「推进」「次推」「维持」),从弹窗节点向下按类型定位那个横排容器(HBoxContainer),断言其 `get_children()` 的**子节点顺序**:双钮形态 child(0) 文案=「推进」且 **child(2)** 文案=「维持」——次钮在 `open()` 里只是 `visible=false`、不从子节点表移除(`confirm_dialog.gd:47`),双钮形态下子节点仍为 3 个,按下标断必须取 child(2)(写 child(1) 必红);三钮形态 child(0)/child(1)/child(2)=「推进」「次推」「维持」。另配非空前置:按钮行子节点数=3(防扫描面缩水静默绿)。按类型定位可成立已核:该弹窗树内只有这一个 `HBoxContainer`(`UiKit.modal_shell()` 产 CenterContainer+PanelContainer+VBox,不产横排——`ui_kit.gd:509-525`;`confirm_dialog.gd:26` 那条 HSeparator 与 `UiKit.button()` 的产件都不是 HBoxContainer)。判据面=树的公开子节点序(同 `system_test.gd:81-89` 断言层序的先例形态),**不读任何私有成员**,避开 `architecture.md:168` 视图单元接口与 `:323` 禁直引实现内部 | 新增:确认弹窗按钮位次与语义同钉 | -| R4 | 件2 左位那颗真点下去就是推进(`design/gdd/ux/camp.md:16`;位次定值出处同 R3) | 同 R3 | `ui_click_probe.gd:_ready`(大门无断点段内,`push_click_at` 打**推进钮自身**全局矩形中心) | 探针 | 弹窗开态下按类型定位按钮行 `HBoxContainer`,取其 child(0) 的 `get_global_rect()` 中心真点——**禁按「行矩形左位」算坐标**:该行 `alignment=CENTER`(`confirm_dialog.gd:29`),双钮可见宽 216+12+216=444<壳宽 460(`ui_kit.gd:578` 钮默认 `min_w=216.0`/`confirm_dialog.gd:20` 壳 `Vector2(460,0)`),左右各留 8px 空档,打行矩形左位会落空 | 主证=`run_scope.is_adventure` 翻转+`_confirm_consumer` 清零;真点前置读 `main._confirm_consumer == "gate_new"`(该私有的直读属**探针既有先例**,`ui_click_probe.gd:272`/`:286` 现役同款,封装扫描件只覆盖 flow 件的 `root._`——见 `presentation_encapsulation_sweep_test.gd:80-94`,故本行不新开辟读面)——位次若错接,坐标命中的将是「否」,主证面即红 | 新增:确认弹窗按钮位次与语义同钉 | -| R5 | 件3 顶栏栏体几何与徽章落座(`design/gdd/ux/camp.md:41`) | `camp_hud_band.gd:10-17` 改为调公共件出口得栏体+徽章落座改右对齐容器;`ui_kit.gd` 加带 α 常量与公开出口 | `system_test.gd:_smoke_camp_hud_band` | 集成 | 真实工程 boot 后经装配链 `main_ui_build.gd:120-121` → `camp_scene_view.gd:88-91` 落座;**须先开营地**(营地屏 boot 态为隐,`camp_scene_view.gd:53`),走 `main._camp_pres.open_camp()` 探针既有用法并 await 排版帧,再读 `main.ui.modals.camp.scene.hud_band`(`camp_scene_view.gd:49` 的公开句柄) | ①栏体色 `color.to_html(true) == "6e4526cc"`——即规格「`#6E4526` × α0.80」的字面编码;**禁写 `.a == 0.80`**(实测色道单精度使该比较为 false,见第 2 节实测句);②栏体铺满:出口产出的那块色面 `get_global_rect()` 宽=1280、高=48——**宽度不是 tscn 锚点给的**(营地场景根由屏壳代码 new——`game/presentation/scenes/camp_screen.gd:13` `CampSceneView.new()` + `:14` `add_child`,该根自身无锚无尺寸;承重实为 `ui_registry.gd:26`/`:61` 打的 FULL_RECT 注册,屏壳 `camp_screen.tscn` 根锚 preset=15 满铺),故实现首步先按 T3.0 同款时机量一次顶栏件现尺寸,再以此定断言值;③`mouse_filter == MOUSE_FILTER_IGNORE`;④栏体是顶栏件的**第一个子节点**(子节点序=绘制序,色面必须先入才不盖徽章);⑤徽章 `get_global_rect().position.y == 0` 且 `get_global_rect().end.x == 顶栏 get_global_rect().end.x − 12`(x 向缺判据则位次改错仍绿,故与顶格同批配齐;两项都用全局矩形,不与局部 `position` 混写)。前置量测=T3.0 读 `get_combined_minimum_size().y` 须为 48(描边若计入得 50 → 触第 10 节 L3 第 5 条) | 新增:营地顶栏栏体定值与落座 | -| R6 | 件3 栏体对落位带底色对比 ≥3:1(`design/gdd/ux/camp.md:41`+`design/art/art-bible.md:452`) | 同 R5 | `camp_scene_layout_test.gd:_test_hud_band_contrast_over_bg` | 单元 | 单元从 `camp_scene_layout_table.gd` 的 `hud_band_h` 出口取带高,读现行背景贴图 `res://assets/art/scene/scene_camp_bg.png` 该带像素(`load(...)` 取纹理再 `get_image()`+`get_pixel`,先例=`terrain_tile_sets_test.gd:105-107` 的全像素扫描) | 规格侧算式核验(与 R5 分工:R5 核实装等值,本行核规格值本身达标)=测试内按 `camp.md:41` 写死 `#6E4526` 与 α0.80,与该带实测均色 alpha 合成后算 WCAG 对比,断言 ≥3.0;扫描面非空前置照 test-conventions §8.4(正面效力自检)配齐。**禁把视图件的 color 直接当预期值喂进算式**(那是 oracle 镜像,test-conventions §8.7 判红) | 新增:营地顶栏栏体定值与落座 | -| R7 | 回归·件1 未动的三条动线(`design/gdd/ux/camp.md:16`/`:22`) | 无改动(`main.gd:208`/`214`、`main_esc_flow.gd:46`) | `ui_click_probe.gd:_ready`(既有大门两分支段+篝火离场段现有断言,本批零改写) | 探针 | 既有真点链 | 既有绑定面原样:`is_adventure` 不翻转、营地场景根 `visible`、`_camp_data()["balance"]` 不变 | 既有:营地大门两分支确认与断点续玩接线 | -| R8 | 回归·件2 未触的路由与件数断言(`design/gdd/ux/camp.md:16`;位次与件数定值出处同 R3) | 无改动 | `ui_click_probe.gd:_ready`(次钮隐藏断言 `:694`)+ `system_test.gd:_smoke_boot_chain`(开始层三钮计数 `:195`) | 探针/集成 | 既有真点与 boot 链 | 既有绑定面:`_secondary_btn.visible` 为假(两出口形态)、开始层可见钮数 == 3 | 既有:营地大门两分支确认与断点续玩接线 | - -闸口径:本批改动含 `game/` 下非 `.md` 的行为载体,合回后远端 CI 走代码域全档;开发期按改完即测铁规以 `tools/run_all_gates.sh --code` 为选档入口(域划分唯一出处在脚本内,卡内不列闸件名单)。里程碑步出口跑一次所选档全套;波内修复只做出红件的最小单元最窄确认;新增测试先行孤立验证再并入全套。 - -**测试削弱申报**:允许改动 0 条既有断言。`ui_click_probe.gd:694`(次钮隐藏)与 `system_test.gd:195`(三钮计数)必须原样通过;本批位次改动若使二者失守=契约3 被违,停卡呈报,禁改判据求绿。**唯一允许的判据形态约束**:涉及色值与透明度的断言一律走 `to_html(true)` 或整体等值比较,禁浮点分量直等(第 2 节实测依据)。 - -**独立验收审计**:入口=`reports/iter<53>-验收审计-<日期>.md`;由未参与实现的只读会话或子代理执行,未过不得合回(test-conventions §8.7+iter 技能第 5 步)。验收档=中 ⇒ 审计深度按 §8.7 中档梯度。 - ---- - -## 9. 任务卡 - -### T1|开局路径的隐藏点收一处(≈0.25 工作日) - -取用:`main.gd:292 func _start_adventure() -> void`(既有签名,零参数零返回)。 - -- [ ] T1.1 实装:`game/presentation/main.gd:292` `_start_adventure()` 函数体首行加 `ui.screens.start_overlay.visible = false`(位置在该函数现有第一句 `ui.flow.close(...)` 之前)。 -- [ ] T1.2 实装:删除 `game/presentation/main.gd:194` 那句 `ui.screens.start_overlay.visible = false`(转调 T1.1 后它已无职责)。 -- [ ] T1.3 验证:`python tools/run_system_test.py` 全绿——核 `_smoke_boot_chain` 与 `_smoke_run_lifecycle` 的既有开始层断言(`system_test.gd:170-171`/`:253`/`:261`)未失守。 -- [ ] T1.4 验收:`ui_click_probe.gd` 大门无断点段(`:684-705` 区间内)追加两条断言并实跑——R1(确认后 `main.ui.screens.start_overlay.visible` 为假)、R2(`main.ui.modals.run.level_screen.visible` 为真,与既有 `is_adventure` 断言同批)。**帧口径**:段内既有 await 只 1 帧(`:703-704`),选路停点成形的先例是 3 帧(`screen_flow_probe.gd:185-193`,该段在 `await _frames(3)` 后断言「入口停点未落在关卡地图屏(level_screen 不可见)」——但它走 `_start_adventure_from_menu()` 函数直调,那条路径自带隐藏,所以从未抓到本缺陷)——追加断言前 await 到 3 帧,并把「停点成形所需最小帧数」实测值记进实现报告。落点=既有段内,不新建段。 -- [ ] T1.5 验证:`python tools/run_all_gates.sh --quick` 对该件做最窄确认(探针闸段),先红后绿记进实现报告。 - -产出(T2/T3 无关,供回归引用):`_start_adventure()` 成为开始层隐藏的唯一开局出口。 - -### T2|确认弹窗按钮位次镜像(≈0.5 工作日) - -取用:`confirm_dialog.gd:43 func open(text: String, confirm_label: String, cancel_label: String = "取消") -> void`;`confirm_dialog.gd:55 func open_three(text: String, confirm_label: String, secondary_label: String, cancel_label: String) -> void`。三颗钮的成员声明(`:14-16`)与连接属本卡禁动面,不取用。 - -- [ ] T2.1 实装:`game/presentation/views/confirm_dialog.gd:31-39` 三颗钮的 `add_child()` 次序整体镜像为 确认 → 次 → 取消。对象创建、`.pressed.connect(...)` 三句连接、成员声明(`:14-16`)、`open()`/`open_three()` 签名与文案参数一律不动(契约3)——**本卡不给测试开任何新成员或新公开出口**,位次判据走公开子节点序(依 `architecture.md:168` 视图单元接口与 `:323` 禁直引呈现层实现内部)。 -- [ ] T2.2 验收(新增件):新建 `game/tests/unit/presentation/confirm_dialog_test.gd`,套件入口=`func _initialize() -> void`(视图件套形态先例=`camp_scene_layout_test.gd:12-13` 的 `call_deferred` 串法,**不是** `_init`),体内 `call_deferred` 两个私有函数——`_test_two_button_row_order()`:自造实例后调 `open("t", "推进", "维持")`,从该实例向下按类型定位那个 `HBoxContainer`,断言其 `get_children()` 的 child(0).text 为「推进」、**child(2).text** 为「维持」,且子节点数=3(次钮只置 `visible=false` 不移除——`confirm_dialog.gd:47`,双钮形态下维持钮在 child(2) 不是 child(1));`_test_three_button_row_order()`:调 `open_three("t", "推进", "次推", "维持")`,断言 child(0)/child(1)/child(2) 文案依次=「推进」「次推」「维持」。全程只读公开树面与 Button 的公开 `text`,不触任何私有成员。入册=在 `game/tests/run_all.gd:166` 起的硬编码清单里追加一行 `{"path": "res://tests/unit/presentation/confirm_dialog_test.gd", "expect": 0}` 并行尾注一句本套件职责(清单条目形态照同目录既有行)。 -- [ ] T2.3 验收:`ui_click_probe.gd` 大门无断点段内追加 R4。**前置重开**:`:702` 那一次真点已把 `gate_new` 消费掉(`main.gd:215` 置空),故本步须先 `main._camp_pres.open_camp()` → `ProbeUiUtil.push_click_at(gate 命中区中心)` 重出弹窗,再取按钮行左位——坐标=自弹窗节点向下按类型定位到的 `HBoxContainer` 的 child(0) 全局矩形中心,经 `ProbeUiUtil.push_click_at` 真点;断言真点前 `_confirm_consumer == "gate_new"`、真点后 `run_scope.is_adventure` 为真且 `_confirm_consumer` 清零。 -- [ ] T2.4 验证:孤立先跑 T2.2 新套(`… --script res://tests/run_all.gd` 单套件口径),绿后并入全套;四处消费方动线由 `ui_click_probe.gd` 既有段与 `run_all` 单元套确认未失守(R8)。 - -产出:位次成为规格钉死的呈现定值,推进钮恒为该按钮行的 child(0)。 - -### T3|营地顶栏可见栏体(整件外观封在公共件一个具名出口,≈0.75 工作日) - -取用:`UiKit.CAMP_HEADER_BAND`(`ui_kit.gd:195`,色值单点);`UiKit.keystone_badge(text: String) -> KeystoneBadge`(`ui_kit.gd:655`);`CampHudBand._init()`(`camp_hud_band.gd:10`,该件 `:14` 现役已在调 `UiKit`)。**盘上三处同形铺面写法不在取用面**(`ui_assembler.gd:224-230`、`ui_kit.gd:486-491`、`ui_kit.gd:537`)——本批既不让顶栏件复用它们,也不把它们收编进出口,理由见第 3.3 条、契约4 与第 12 节末段。 - -- [ ] T3.0 前置读数:**入树之后**再量——`KeystoneBadge` 是 PanelContainer(`ui_kit.gd:634-656`),最小尺寸由容器排版产出,刚 `new()` 未入树时读数不可信。落点=在系统测试宿主里经 `main.ui.modals.camp.scene.hud_band` 链取**已在树的现成徽章实例**,先开营地并 `await` 排版帧(帧数口径同 T1.4),再读 `get_combined_minimum_size().y`(`ui_kit.gd:640` 的 `panel_flat(...Vector4(14,8,14,8))` 加在 32px 图标上下各 8=48,两个未证实项都能把它推离 48:①`border_w=1` 是否计入最小尺寸;②徽章内 Label 用 18px 档(`ui_kit.gd:648` 取 `FS_SUB`,常量见 `:438`),字体行高若大于 32 则最小高由文字而非图标决定——**这两条都是推导,不是实测量**)。读数=48 → 按 T3.3 顶格落座;读数≠48(如 50)→ 停步走第 10 节 L3 第 5 条呈报,禁自行改栏高或改徽章内边距。读数与取数时机一并写进实现报告。 -- [ ] T3.1 实装·出口本体(Q1 终裁·11-06 用户裁「整件外观封在公共件一个具名出口,同形旧实现不收编」):`game/presentation/views/ui_kit.gd` 色板段加 `const CAMP_HUD_BAND := Color(CAMP_HEADER_BAND, 0.80)`(带 α 先例=同文件 `:189`/`:190`,收口非新增语义色的先例=`:200`);工厂段加公开出口 **`static func camp_hud_band_surface(host: Control) -> ColorRect`**,体内依次=新建 ColorRect + `rect.color = CAMP_HUD_BAND` + `rect.set_anchors_preset(Control.PRESET_FULL_RECT)` + `rect.mouse_filter = Control.MOUSE_FILTER_IGNORE` + `host.add_child(rect)` + `return rect`。**形参只有 host**:色、α、铺法、点击语义全写死在体内——这就是「一个物件的外观不得拆两处」的确切实现形(对照两个作废形态:值在公共件+铺法在视图=拆两处;出口开 color/pass_input 形参=把物件定义推回调用方,并为无关同形件预留通用性)。出口名钉死在这块带子上,不作通用铺面器。 -- [ ] T3.2 实装·顶栏件:`camp_hud_band.gd` 的 `_init()` 内在挂徽章之前调 `UiKit.camp_hud_band_surface(self)`(契约5 的 IGNORE 由出口内部保证,调用方没有可以忘记的形参);子节点序即绘制序,栏体先入、徽章后入。本文件内不再出现 `ColorRect.new()`。 -- [ ] T3.3 实装·徽章落座(**Q2 已裁乙·2026-11-05 用户裁**):`camp_hud_band.gd` 内加一层右对齐容器承载徽章——`HBoxContainer` 铺满栏体(`PRESET_FULL_RECT` 后置 `offset_right = -12.0`)、`alignment = BoxContainer.ALIGNMENT_END`、**`mouse_filter = Control.MOUSE_FILTER_IGNORE`(容器自身默认 STOP,与出口内那处 IGNORE 是两个点、必须同批落,漏一处顶排物件就点不动)**;替换 `camp_hud_band.gd:15-16` 现值(`PRESET_CENTER_RIGHT` + `position=(-160, 8)`),位数增宽自然向左展。容器摆位机制先例=`confirm_dialog.gd:27-29`(同件同机制,那里 alignment 取 CENTER、这里取 END);内缩 12px 见白名单第 3 条。 -- [ ] T3.4 验收:`game/tests/system_test.gd` 新增 `_smoke_camp_hud_band()`,**接进 `_split_tail()` 的 await 链**(`:40-44` 那一串 `await _smoke_*()` 之后追加 `await _smoke_camp_hud_band()`),**不是接进 `_initialize()`**——`_initialize()` 只调一句 `_split_tail()`(`:26-28`),而摘要打印与 `quit()` 都在该尾段末尾(`:47-48`),协程段不被 await 就会在首个 await 处被 quit 截断=静默不执行=假绿(该教训已写在 `:40` 行尾注里)。段内自持 `load("res://presentation/main.tscn").instantiate()`+`root.add_child`+await 帧、末了 `queue_free()`,形态照 `_smoke_run_lifecycle()`(`:213-217`/`:206-207`)。实现 R5 的五项判据(色值走 `to_html(true) == "6e4526cc"` 或整体等值比较,**禁浮点分量直等**;`get_global_rect()` 的尺寸=顶栏件实测宽 × 48;`mouse_filter == MOUSE_FILTER_IGNORE`;栏体是顶栏件的第一个子节点;徽章全局矩形 `position.y == 0` 且 `end.x == 顶栏 end.x − 12`)。**出口须在 `_init()`(入树前)被调**:`set_anchors_preset(PRESET_FULL_RECT)` 是把四边 offset 归零的入树前动作,与 `_modal_dim()`/`overlay_bg()` 的现役形态一致。 -- [ ] T3.5 验收:`game/tests/unit/presentation/camp_scene_layout_test.gd` 新增 `_test_hud_band_contrast_over_bg()` 实现 R6:读 `hud_band_h` 与背景贴图该带**全像素**均色(取样法照 `terrain_tile_sets_test.gd:105-107` 的双层全扫,非步长抽样),规格值 `#6E4526`/α0.80 按 `camp.md:41` 在测试内写死后合成算 WCAG 对比,断言 ≥3.0;扫描面非空前置照 §8.4 配齐。 -- [ ] T3.6 验证:两条新测先行孤立跑绿再并入 `--code` 全套。本批不触任何既有遮罩/亮底/页壳件,故无等值回归义务——回归证据=第 5 节七条未改动动线与全站弹窗现有断言在 `--code` 全档中仍绿。营地屏截图面由渲染闸的七屏段随批产出,作 R5/R6 对照取证。 -- [ ] T3.7 目检登记:营地顶栏观感(「成一条可辨窄带、徽章落在带内」)登记一行进实现报告实机目检总清单,登记即完成义务。 - -产出:`CAMP_HUD_BAND` + `camp_hud_band_surface()` 是这块带子外观的唯一出处(同文件相邻两段);`CampHudBand` 的外观=该出口+右对齐容器+徽章三件,视图内无一处自建 ColorRect;盘上三处同形写法原样未动。 - -### T4|产出物落位卡(≈0.5 工作日,末卡) - -- [ ] T4.1 代码域全档全绿后、合并前写 `reports/iter<53>-实现报告-<日期>.md`:各卡状态+实机目检总清单(含 T3.7)+遗留读数义务+实现决定记录(超白名单的微决策逐条登记)。 -- [ ] T4.2 写 `reports/iter<53>-反哺点-<日期>.md`:第 6 节每条命中项都要有落点(哪一节、改成什么、依据什么);无命中也要写「本批零反哺点」并附核过哪几处。 -- [ ] T4.3 核对 `game/tests/README.md` 两行新增能力名与实际落地函数名逐字一致(名实不符=停卡退回写卡段)。 -- [ ] T4.4 呈报合回清单,等用户发令再走收口(冻结→件核→并 master→重塑→删区)。 - -**估时合计 ≈2.0 个工作日**(T1 0.25+T2 0.5+T3 0.75+T4 0.5)。T3 的 0.75=出口一枚(十行内)+顶栏件改两处(调出口+落座容器)+两条新测+孤立验证。无收编、无等值回归、无两次全档义务。 - ---- - -## 10. 异常分级 - -- **L1 自救**:探针坐标算错导致 R4 打空——重算按钮行全局矩形中心,禁改为信号直发(段内既有 `ui_click_probe.gd:696` 的 `cancelled.emit()` 是取消路径的信号注入先例,注释自陈「真实信号——cancelled 钮同源」;本批 R4 要钉的正是**位次**,直发不经位次,等于没测——依据=test-conventions §8.3 真实入口收窄条,契约7 同源)。 -- **L2 记录继续**:R6 均色取样读数与卡内实测 `#DEEAE7` 有 ≤3/255 的取样步长差——按实测值断言、卡内读数差写进实现报告,不改阈值。 -- **L3 停机呈报(写报告等用户)**: - 1. boot 后 `main.ui.modals.camp.scene.hud_band` 取不到实例(装配链与第 3.3 条现状不符)=卡片现状事实失效,停卡退写卡段; - 2. R4 坐标真点无法区分左位钮与相邻钮(按钮行 `alignment=CENTER` 下实际矩形与规格不符)=位次与语义绑不上观测面,触 test-conventions §8.4「判据绑不上=停卡呈报」出口; - 3. 位次改动使 `system_test.gd:195` 或 `ui_click_probe.gd:694`(次钮隐藏断言)失守=契约3 被违,禁改判据求绿; - 4. 机检预算互斥限**本批触碰的 presentation 面文件**:`tools/gdstyle_gate.py:45` 的扫描面=`game/core`/`game/data`/`game/presentation`,脚本头注(`:8`)明写排除 probe/sim/tests——故新增单元套**不在** S13 射程,该条只对 `main.gd`/`confirm_dialog.gd`/`camp_hud_band.gd` 生效。若这三个件的 S13 键与第 13 节预算数字冲突且无豁免通道=上游缺陷,停卡退回写卡段,禁自造第三条路(本技能第 13/14 节)。 - 5. T3.0 量得徽章 `get_combined_minimum_size().y` ≠ 48(描边宽 1px 计入、或 18px 文字行高高于 32px 图标使最小高由文字决定,两条都会推得 >48)=「顶格落座」在 48px 栏内放不下,第 2 节与 `camp.md:41` 的推导句失效,停步呈报,禁自行改栏高、改徽章内边距或放宽 R5 判据。 - ---- - -## 11. 代拍板白名单(超清单必进实现报告「实现决定记录」并呈报) - -1. 断言消息尾缀文案(照 `〔营地图批 V3〕` 形态自拟)。 -2. 新单元套件的套件注册名与 `run_all.gd` 册内落点序。 -3. **徽章水平内缩 12px**:`camp.md` v2.8 只钉「右位顶格」未钉内缩值,取 UiKit 钮间距同档 12(先例=`confirm_dialog.gd:28` `separation=12`)。 -4. R6 取样密度——照 `terrain_tile_sets_test.gd:105-107` 的**双层全像素扫描**(该件不是步长抽样,卡内早先写的「每 4 行×每 8 列」口径作废)。 -5. `_smoke_camp_hud_band()` 在 `_split_tail()` await 链内的插入位(不改变既有段序;接进 `_initialize()` 不成立——见 T3.4)。 -6. 出口与常量的命名(卡内定名 `UiKit.camp_hud_band_surface()` 与 `CAMP_HUD_BAND`)——可按同文件命名习惯微调后缀形态;**若实现把它改成带 color/pass_input 形参的通用铺面器、改成「值与形分两处」、或另起第二家公共出口,一律触契约4,属 L3 呈报**。 - -不在白名单:α 值、栏底色、栏高、位次序、隐藏点数量与位置——这些是规格钉死项,改动一律 L3 呈报。 - ---- - -## 12. 落位与可复用性预检(与第 7 节结构图互指) - -| 新增/改动件 | 复用面(盘上已有什么) | 唯一面 | 分层与交互面 | -|---|---|---|---| -| 顶栏带外观出口(T3.1/T3.2) | **现成件已复用**:徽章走 `UiKit.keystone_badge()`(`ui_kit.gd:655`,`camp_hud_band.gd:14` 是现役调用方),色值走在册 `CAMP_HEADER_BAND`(`:195`)。盘上另有三处「新建 ColorRect+铺满宿主」的同形写法(`ui_assembler.gd:224-230` 外部调用者零、`ui_kit.gd:486-491` 私有且仅 `:511` 一处用、`ui_kit.gd:537` 页壳底板)——**本批三者都不复用也不收编**:它们的变化原因是遮罩遮挡语义与页面底色档位,与本带的 HUD 定值无关。出口落 `ui_kit`、不经装配器,因顶栏件已在引用 `UiKit`,而 `views/` 引装配器零先例。早先两版判据(「两份都不复用、按 views 现行形态自建」与「四份同形收成带形参的通用出口」)都已作废,逐次理由见第 15 节 Q1 裁决史 | 这块带子的外观全仓一处定义=`CAMP_HUD_BAND`+`camp_hud_band_surface()`(同文件相邻两段);禁在别处出现第二组「同一色+同一 α」;出口内 `MOUSE_FILTER_IGNORE` 写死——旁证:同文件 `:540` 页壳底板显式写 STOP、`:864` 与 `camp_scene_view.gd:145` 须显式写 IGNORE,可见 ColorRect 默认即 STOP,漏设不报错只会静默吃掉顶排点击 | 呈现层内一个纯构建出口,零状态、零信号、不持引用;顶栏读数仍经 `camp_data()` 投影单口(`camp_hud_band.gd:26-27`);`ui_assembler.gd` 与 `modal_shell()`/`page_shell()` 一律不动 | -| 开始层隐藏(T1.1) | **复用** 既有语义句本身——`main.gd:194`/`:246` 就是同一条责任,本卡把它收进被调方 | 开局路径隐藏点唯一(`_start_adventure()`),续玩路径唯一(`_resume_from_menu()`);其余 10 处开层自管点不在本契约射程(契约1 已收窄) | 组合根内;不触 Core,不新增信号 | -| 按钮位次(T2.1) | 无新增件——只镜像既有三句的次序。**本卡不新增成员、不新增公开出口**:位次判据走公开子节点序(R3),语义判据走坐标真点(R4) | 位次定值只写在视图件 `_init()` 一处,四处消费方零副本 | 呈现层;信号对象路由不动;依 `architecture.md:168`「视图单元接口=信号外发+setter 只读注入」与 `:323`「禁直引呈现层实现内部」,不为测试开成员面(该写法曾在本卡出现过,已撤回,登记在第 16 节轮次 2) | -| 徽章落座(T3.3,Q2 已裁乙) | 已有做同样事的东西:`HBoxContainer` + `alignment` 摆位机制(`confirm_dialog.gd:27-29`——该件 `alignment` 取的是 `ALIGNMENT_CENTER`,**是同一机制的先例、不是右对齐的先例**;本件同处改取 `ALIGNMENT_END` 即右对齐)——**Q2 已裁乙(2026-11-05 用户裁)**,采容器右对齐形态;另两案(锚点生长、`size_updated` 回调)作淘汰留档见第 15 节 | 内缩值 12px 只在落座一处出现一次,禁在断言里另写第二套推导 | 呈现层内 | -| `confirm_dialog_test.gd`(T2.2 新增) | 盘上无 ConfirmDialog 专属单元套(grep 命中面=`system_test.gd`/探针的宿主级引用与 `README.md:159` 能力行);同目录 `camp_scene_layout_test.gd:12-13` 是可参照的套件形态(入口 `_initialize()`+`call_deferred`),不是可复用的承载 | 位次判据只此一处;R4 探针判据与之互补(一个核序、一个核语义) | 测试层;经 `ConfirmDialog.open()/open_three()` 公开入口进出,断言只读公开子节点序与 Button 的公开 `text`——「读私有成员」的写法曾在 R3 出现,已按 `architecture.md:323` 撤回 | -| `system_test.gd:_smoke_camp_hud_band`(T3.4)/`camp_scene_layout_test.gd:_test_hud_band_contrast_over_bg`(T3.5) | **扩展**既有套件,不新建宿主;取样法复用 `terrain_tile_sets_test.gd:105-107` 的双层全扫+`get_pixel` 路径 | 几何判据落系统测试、对比判据落布局单元套——两处职责已由套件名界定,禁第三处重复断言 | 测试层 | - -**为什么出口只服务这块带子(2026-11-06 用户终裁;本段取代本卡此前两份互相矛盾的留痕句——「接受第四处重复故不抽工厂」与「四份同形收成带形参的通用出口」)**:用户裁的是两件事的合成。①**一个物件的外观不得拆两处**——色值、α、铺法、点击、挂载这五件事必须在同一个出口内定义,不许「常量在公共件、矩形在视图」;那等于要求每个改它的人同时记得两处,漏一处就得到一个自相矛盾的物件。本会话确有改漏实例:同一组色值要在两份文档里成对改,卡内同步面还写了「禁单改一处」的防呆,却在代码面上造出另一个新的成对结构。②**抽不抽公共器不由形状撞车决定**——不得为了「全仓只剩一处 ColorRect 铺满」这种读数好看,把遮罩、页底、HUD 带三个变化原因绑进一个带形参的通用器;那既不内聚(一个函数回答三个不相关的问题)也不低耦合(改顶栏带要回归全站弹窗底与两个全屏页),而这三处今天都没有待改的东西。**早先那份「三次法则、意图未第三次出现故不抽工厂」的留痕句,其动机经用户点破是「少动文件」而非纪律,作废**;但据此反弹出的「整案收编+形参化点击语义」同样作废。代价面(`ui_kit` 公开方法 23→24 须修订登记基线)见第 13 节例外申报;回归面因不收编而留在本件射程内,估时相应回落。 - ---- - -## 13. 实现规范预算(与第 7 节结构图互指) - -**新件三查**——本批新增文件仅 `game/tests/unit/presentation/confirm_dialog_test.gd`: - -- **三查对本件不适用**:`tools/gdstyle_gate.py:45` 扫描面=`game/core`/`game/data`/`game/presentation`,脚本头注 `:8` 明写「probe/sim/tests 测量面」排除——测试面文件不进 S13 读数,无键可对账。 -- 尺寸预期(照套件形态先例自持,不作机检项):套件入口 1 个(`func _initialize() -> void`,**非** `_init`——先例=`camp_scene_layout_test.gd:12-13`)+私有 `_test_*` 2 个+类变量 0–1。 -- 迁移函数对账:无迁入(该件全新增,`tools/gdstyle_baseline.txt` 无历史键,跑批后若出超默认新键须申报) - -**存量触面一查**——S13 键较登记值只降不升: - -| 文件 | 基线登记(`tools/gdstyle_baseline.txt`) | 本批预期 | -|---|---|---| -| `game/presentation/main.gd` | 第 11 行 `quality/max-public-methods = 32` | 不动公开方法面(函数体内加一句+另一函数删一句)→ 读数 32 持平 ✓ | -| `game/presentation/views/ui_kit.gd` | 第 12 行 `quality/max-public-methods = 23` | 本批**加一枚 `const` + 加一个公开出口方法** → 读数预期 23→**24**,超登记值 → 见下方「指标例外申报」。色板快照面不受常量影响(`tools/gen_palette_baseline.py:42` 只正则 `Color8(数字,数字,数字)`,带 α 的 `Color(...)` 从不进快照,同文件 `TOAST_BG`/`TIP_BG` 即此形态);但**方法数是真升**,不申报就是假绿 | -| `game/presentation/views/confirm_dialog.gd` | 无登记键(在默认阈值内) | 仅语句重排,分支与返回数不变 ✓ | -| `game/presentation/views/camp_hud_band.gd` | 无登记键 | `_init()` 换成调出口+加一层容器,分支数不变 ✓ | -| `game/probe/ui_click_probe.gd` | 无登记键(探针大文件另有基线口径) | 同段追加断言,函数不拆;若单函数分支数超默认,按 L3 第 4 条呈报而非自拆 | -| `game/tests/system_test.gd` | 无登记键 | 新增一个私有函数,公开方法面不变 ✓ | - -**指标例外申报(本批一项)**:`game/presentation/views/ui_kit.gd|quality/max-public-methods` 由登记值 23 升至 24,起因=用户 2026-11-06 裁「一个物件的外观不得拆两处」,要求在公共件出一个公开出口承载这块带子的整件外观。处置=实现批跑出该新键后,把 `tools/gdstyle_baseline.txt` 该行改为 24 并在提交信息里申报(基线手动修订须经用户批准——本条即申报与请求)。除此之外本批不申请任何超默认项。 - ---- - -## 14. 拆分边界纪律 - -本批新增的可复用单元只有公共件里那一个出口函数,故本节条款的适用面=该出口,判据权威=code-conventions §1.1 拆分判据,此处不复制定文: - -1. **它有可陈述的职责与单一变化原因**:`UiKit.camp_hud_band_surface()` 的职责语句=「把营地顶栏这块带子按定值铺满宿主并挂上去,返回句柄供调用方读取与断言」;单一变化原因=这块带子的外观要变(以后要求圆角、内缩、换遮挡方式,都只改这一个函数+那枚常量)。它不承载玩法状态、不承载文案、不做判定、不接形参选择;徽章的摆位不由它负责(归顶栏件内那层右对齐容器,T3.3)。 -2. **集体身份成立**:它服务的是营地顶栏这一块具名带子,不是「所有 ColorRect 铺满动作」的收纳盒。**故意不做**成通用铺面器:若把模态遮罩、页壳底板一并收进来(用户 2026-11-06 否掉的形态),这个单元就从「一块带子的定义」变成「三种不相关意图的并集」——正是拆分判据要拦的形态。 -3. **「过阈值」只作发现信号**:本批不以任何计数变好看为目标;公开方法数上升是它的代价(见第 13 节例外申报),不是它的动机。 -4. **拆不出内聚单元即停卡呈报**:若实现期发现该出口必须塞进条件分支才能同时容纳顶栏带与其它用途,说明本卡对「只有这一个消费者」的判断失真——停卡呈报退设计段重议,禁硬并为凑绿。新增单元仅这一个出口函数+一枚常量+一个私有测试套件,无段件/状态件迁出。code-conventions §1.1 与本节互指;实现期若需拆 `camp_hud_band.gd` 或 `main.gd` 才落得下,属卡片未预见的结构动作=L3 呈报,禁为凑绿硬拆。 - ---- - -## 15. 待裁点(三轮复核产生;Q1 因写卡段自决被驳回而重开过、又因出口的执行形态被再裁一次——全程留痕) - -独立复核(未参与撰写的只读子代理)三轮:轮次 1 打回一次,四条闭合里三条由写卡段按权威文档自决落卡,第四条拆成两案呈用户裁决;轮次 2 抓到「矩形谁建」这条轴属越权自决;轮次 3 抓到收编版四处硬伤并生成 Q4。**当前状态:Q1/Q2/Q3 已裁尽,Q4 因 11-06 用户再裁而消解(不再是一条分叉),本卡零待裁点,开工门=U0(用户批卡)。** - -### Q1|顶栏这块色面从哪来——**已裁(终态=公共件一个具名单参出口,同形旧实现一律不动)** - -事实底座:`ui_assembler.gd:224-230` 的 `overlay_bg()` 做了「新建 ColorRect+铺满锚点+挂上宿主+返回句柄」四步,**没设 mouse_filter**(ColorRect 默认 STOP),外部调用者零(只有该文件自身 `:100` 传 `BG_BRIGHT` 亮底、`:214` 传黑 0.6 遮罩);`ui_kit.gd:486-491` 的私有 `_modal_dim()` 是同一份东西的第二实现(同样不设 mouse_filter,仅 `:511` 一处用);`ui_kit.gd:537` 页壳底板同形但**显式**写 STOP、色为实色、后有石纹/暗角兄弟层;`views/` 目录自建 ColorRect 有 7 个文件 15 处先例;顶栏件 `camp_hud_band.gd:14` 现役已在调 `UiKit`。 - -当时并列过的案与代价:甲=顶栏件 preload 装配器复用那一个出口(零重复,但给 `views/` 开一条该目录零先例的引用路径,且该文件头注自陈「接线拓扑唯一归组合根」);乙=顶栏件自建(与 `views/` 现状同构,但重复四行,且色值与铺法分居两处);丙=公共件出一个出口(真「整件外观一处定义」,代价是 `ui_kit` 公开方法 23→24 要修订登记基线)。 - -> **裁决史(四次)** -> ① **11-05**:用户裁「就按放在公共区域的这一层的方案来实现」。写卡段把它解释成"采纳我当轮给的整条推荐",落成**色值进公共件+矩形留在视图自建**,并在第 12 节写下"不抽公共工厂"的留痕句。 -> ② **11-06 用户驳回①并重裁**:驳回理由是那条解释本身——"值"和"形"是同一个 UI 物件的两半,拆两处就要求每个改它的人同时记得两处,而"少动文件"不是纪律。**当时落成的重裁结果=丙的整案**:公共件出一个 `band_surface(host, color, pass_input)` 通用出口封装铺面与点击语义,并把 `_modal_dim()`、`overlay_bg()` 连同三处调用点同批收编,据此生成 Q4。 -> ③ **11-06 写卡段据 Q4 呈「页壳底板收不收」**,用户判该设计整体不成立(原话:「你现在是有非常严重的设计问题」)——出口一旦需要形参承载三种点击语义,它就不再是「一个物件」而是三个意图的并集;会问出 Q4 本身就说明抽象切错了。 -> ④ **11-06 终裁(现行)**:出口**只服务营地顶栏这块带子**——具名 `camp_hud_band_surface(host)`,**形参只有 host**,色值、α、铺满、穿点击全写死在体内;`ui_assembler.gd:224-230`、`ui_kit.gd:486-491`、`ui_kit.gd:537`、`ui_kit.gd:862` 一律**不收编、不动**。已落契约4/5、§2、§3.3、§5、§7、§12、§14、T3.1–T3.3。 -> ⑤ 流程账:轮次 2 复核当时已把①那条轴标为**待裁**(原话:裁决句字面只覆盖色值轴),写卡段改成"自判+报备"自行闭合——那是越权(规矩:待裁必须问用户、禁代裁),第 16 节轮次 2 相应行按实情登记。 - -### Q2|徽章「右位顶格+内缩 12px」用什么机制随位数自适应——**已裁(2026-11-05 用户裁乙·容器右对齐)** - -事实底座:徽章文案是 `"钥石 %d" % v`(`camp_hud_band.gd:22`,格式串单点在 `UiKit` badge 工厂),**宽度随余额位数变**;现值 `position = Vector2(-160, 8)`(`camp_hud_band.gd:16`)把 x 写死——R5 要断言「徽章右缘 == 栏右缘 − 12」,写死偏移在位数变化时必然失位(现值 -160 只对当时那个位数读数成立)。 - -| 案 | 做法 | 代价 | -|---|---|---| -| 甲 | 锚点右钉 + `grow_horizontal = GROW_DIRECTION_BEGIN` + `offset_right = -12`、`offset_top = 0` | 纯声明式、无回调;依赖 Control 生长语义(须开工首步实测读数确认,Godot 4.7 锚点+offset 与 custom_minimum_size 的相互作用我不凭记忆断言) | -| 乙 | 栏体内套一个右对齐 `HBoxContainer`(`alignment = END`),徽章作子件由容器摆位 | 与 `UiKit` 既有容器用法同构(弹窗钮行 `confirm_dialog.gd:27-29` 就是 `HBoxContainer` + `alignment`);代价是多一层容器节点,栏体色面与容器的父子关系要重排 | -| 丙 | 保持现锚点,接徽章 `size_updated` 信号在回调里重算 x | 改动面最小;代价是多一条运行期回调路径(与「显式触发才变」的顶栏刷新纪律并存,需在卡内申报新观测路径) | - -写卡推荐=**乙**,理由=仓内已有同类摆位先例(容器 `alignment` 摆位,非手算偏移),且 R5 的 x 向判据在容器形态下读数最直白。甲依赖我不肯凭记忆断言的引擎语义(AGENTS.md:不确定的 API 一律核实后再用,核实前不作推荐)、丙新增运行期路径。 - -> **裁决(2026-11-05 用户裁·乙 容器右对齐)**:已落 T3.3 与第 12 节,Q2 清零。 - -**Q1/Q2 与第三条(闸件缺口是否登记)都已裁完并落卡,本卡零待裁点,开工门=U0。** - -### Q4|页壳底板要不要一并收进同一个出口——**已消解(11-06 用户终裁:不收编,出口只服务顶栏带)** - -留档(非现行分叉):`ui_kit.gd:537` 页壳底板与出口形状相同(新建 ColorRect、赋色、铺满、挂上宿主),差别是它**显式**写 `MOUSE_FILTER_STOP`、色取 `BG_BRIGHT`/`BG_ROOT` 实色,且后面紧跟石纹层与暗角层作兄弟节点——它是「页面底」,不是「遮罩/条带」。`ui_kit.gd:862`(竖卡 18×16 小色块)不同形(手工 position/size、不铺满)。轮次 3 把前者判为待裁并生成 Q4,呈报时并列「不收编(甲)/一并收编(乙)」两案。用户回话否定的是这条呈报的**前提**:出口本来就不该是通用铺面器,所以「第四处收不收」不成立。按终裁④,`ui_assembler.gd:224-230`、`ui_kit.gd:486-491`、`ui_kit.gd:537`、`ui_kit.gd:862` 四处全部原样不动。 - -### 其余复核发现的处置(已落卡,非待裁) - -自判与补写两类已按复核者自己落卡的规矩改进行内:契约1 收窄措辞、`_start_adventure()` 函数体行号订正、失败分支终态申报、帧口径、R6 输入来源改读实件、R8 行号与能力行拆正、结构图验收行补 R7/R8、悬空「行为表」引用、L1 引用行号、白名单第 4 条取样口径、`_initialize()` 入口名、新件三查对 tests 不适用、`main.gd:137` 与其余开层点不受契约1 约束的明示、R3 child(2) 硬伤、R5 开营地前置与 await 时机、T3.0 入树读数时机、1280 宽承重链改引 `ui_registry.gd:26`/`:61`、徽章 x 向判据改全局矩形、显隐点 12→13、`views/` 先例 8 文件→7 文件 15 处、步骤号与 R 行口径重编号。(轮次 1 对 R3 给的「升成员供测试直取」处置已在轮次 2 撤回——它抵触 `architecture.md:168` 视图单元接口与 `:323` 禁直引呈现层实现内部,改判为公开子节点序判据。) - -两条闸件面发现**均已登记为工程改动待办**(用户 2026-11-05 口径:登记后本批不管):认锚式字符类不含中文段(`tools/pipeline_gate.py:68`)、层序落位单口的扫描面不含子目录(`game/tests/unit/contracts/source_guard_test.gd:85-99`)。两条都在待办清单在册(改动面=工具代码/状态=待执行),本批不动闸件。 - -复核未采信两条:复核者称 `ui_click_probe.gd:679` 是断点写盘句(实为段头注,断点注入在 `:706` 起);称 art-bible:452 宣称的五 token 机检「查无该件」(`tools/palette_check.py:22` 的 `ui_tokens.png` 就是 ui_kit 全量 Color8 token 快照基线,机制存在,只是不逐名比对该表五行——已写进契约4 依据,未采纳其结论)。 - ---- - -## 16. 复核记录 - -复核者身份=未参与本卡撰写的只读子代理(Agent 工具起的独立会话,禁写文件、禁跑闸),形态=只读子代理。轮次 1,发现 22 条,四类去向逐条登记: - -| 轮次 | 复核者身份 | 发现(一句话) | 去向 | 处置结果 | -|---|---|---|---|---| -| 1 | 只读子代理·未参与撰写 | 契约1「隐藏点只许两处」按字面过宽——全库开始层显隐共 13 处 | 退回上游(复核者判)→ 落卡改自判 | 契约1 收窄为「限开局/续玩两条路径」,13 处逐条列名(`camp_shop_presenter.gd:43`/`:85`、`main.gd:137`/`:194`/`:246`、`main_adventure_flow.gd:145`、`main_debug_flow.gd:88`、`main_overlay_flow.gd:8`/`:17`/`:41`/`:48`/`:95`/`:101`)。复核者的「退回上游」定名不采纳:这是卡内条款措辞过宽,非规范冲突,写卡段可自改 | -| 1 | 同上 | `_start_adventure()` 函数体行号错(写 311,实止 308) | 自判 | §3.1 改 `292-308` 并注明 `:311` 是下一函数声明行 | -| 1 | 同上 | T1.1 落笔后启动失败分支的开始层终态由可见变隐藏,卡未申报 | 补写 | §3.1 该行补终态申报(致命屏自接管,无菜单可用) | -| 1 | 同上 | 大门段 await 只 1 帧,选路停点成形先例是 3 帧 | 补写 | T1.4 补帧口径+最小帧数实测记进实现报告;引 `screen_flow_probe.gd:185-193` | -| 1 | 同上 | `btn_row` 是 `_init()` 局部变量,R3「逐位相等」写不出来 | 补写(阻塞) | 当时把 `btn_row` 升为成员并申报受控例外;该处置在轮次 2 撤回(抵触 `architecture.md:168` 视图单元接口与 `:323` 禁直引呈现层实现内部),现行判据=公开子节点序,不新增成员 | -| 1 | 同上 | §12 自称「不直取私有」,R3/R4 实际直取私有成员 | 自判 | 同上:先改为受控例外口径,轮次 2 再改为完全不读私有成员(R3 走子节点序、R4 走坐标真点) | -| 1 | 同上 | `:702` 真点已消耗 `gate_new`,R4 需重开营地+大门才有左位可点 | 补写 | T2.3 补「前置重开」步与坐标取法 | -| 1 | 同上 | L1 引用的 `ui_click_probe.gd:679` 不是旧口径注释;段内直发面在 `:696`;「emit 不算真实入口」属 §8.3 而非契约7 | 自判+**部分不采信** | L1 改引 `:696` 的 `cancelled.emit()` 并注依据=test-conventions §8.3。**但复核者称 `:679` 是断点写盘句,经我回读不成立**——`:679` 确为段头注「大门两分支断言段」,断点注入起 `:706`;另 R8 原引 `:696` 亦错,次钮隐藏断言实为 `:694` | -| 1 | 同上 | `ui_assembler.gd` 无 `class_name`,现网一律 preload,`views/` 零先例;卡内 `UiAssembler.overlay_bg(...)` 写法不成立 | 待裁 | 第 15 节 Q1 全案并列(复用装配器/视图内自建/公共件出出口),含三案代价;T3.1 改为「待 Q1 裁决后落」 | -| 1 | 同上 | 徽章自高 48 系推导,`panel_flat` 带 `border_w=1`,描边若计入则 50、R5 顶格判据即红 | 补写(复核者自标「这是推测,未跑批」) | T3.0 新增前置读数步(量 `get_combined_minimum_size().y`);≠48 走 L3 第 5 条;§3.3 与 R5 的推导句标为未实测 | -| 1 | 同上 | 12px 内缩无可达机制(徽章宽随位数变,现值写死 x 偏移);R5 只断 y 向,x 写错仍绿 | 待裁+补写 | 第 15 节 Q2 三案并列(锚点生长/容器右对齐/size_updated 回调);T3.3 改「待 Q2 裁决后落」;R5 已补 x 向判据(`end.x == 栏 end.x − 12`) | -| 1 | 同上 | R6 若把实现的 `Color(UiKit.CAMP_HEADER_BAND, 0.80)` 当输入=oracle 镜像 | 自判 | R6 改为规格侧算式核验(测试内按 `camp.md:41` 写死 `#6E4526`/α0.80),并明写「禁把视图件 color 喂进算式」,依据=test-conventions §8.7 | -| 1 | 同上 | §11.4 称 4×8 步长「沿 `terrain_tile_sets_test` 口径」错,该件是全像素扫描 | 自判 | 白名单第 4 条改全像素双层扫描,并声明卡内早先步长口径作废 | -| 1 | 同上 | 数学校核:全扫与抽样均色=RGB(223,235,232),与卡内 `#DEEAE7` 差 ≤1/255;叠后对比 4.29:1(卡 4.27)、徽章对天空 1.30:1(卡 1.29) | 自判(读数采纳,容差不改) | 落位带前提经其独立核对(背景层 `Rect2(0,0,1280,800)`、围墙 y=261、大门 y=250 → 0–48 带只含背景);差值落 L2 容差内,不放宽阈值 | -| 1 | 同上 | §1 完成定义与 §5 写「七行」,对照表实为 R1–R8 | 自判 | 完成定义改「八行(R1–R8)」(收编版曾扩到 R9,随该版作废回到八行) | -| 1 | 同上 | §5 引「第 1 节行为表」,本卡无该表(悬空引用) | 自判 | 改为「七条未改动动线」自足表述 | -| 1 | 同上 | §7 结构图 `ui_click_probe`/`system_test` 的验收行列缺 R7/R8 | 补写 | 结构图两行补齐 R1、R2、R4、R7、R8 / R5、R8 | -| 1 | 同上 | gdstyle 只扫 core/data/presentation,tests 不在面 → §13 新件三查与 L3 第 4 条对新件无触发路径;套件入口是 `_initialize()` 非 `_init` | 自判 | §13 三查改「对本件不适用」并给依据(`tools/gdstyle_gate.py:45`+头注 `:8`);L3 第 4 条限定为 presentation 面三件;T2.2 入口名改 `_initialize()` 并附先例行号 | -| 1 | 同上 | §13 存量一查核过无误(基线 32/23,`main.gd` 公开方法 31+1 静态=32 持平成立) | 自判(确认类) | 无需改动,留档为已核项 | -| 1 | 同上 | 契约4 依据「加枚即触五 token 机检表」查无该件 | 自判+**不采信其结论** | 复核者称机检不存在,经我回读:`tools/palette_check.py:22` 的 `ui_tokens.png`=ui_kit 全量 Color8 token 快照基线,机制在——只是不逐名比对该表五行。契约4 依据改写成这个准确口径,仍禁新增 token | -| 1 | 同上 | `run_all.gd` 册是硬编码清单,T2.2「接进套件册」不够具体 | 补写 | T2.2 写死条目形态 `{"path": "res://tests/unit/presentation/confirm_dialog_test.gd", "expect": 0}` +行尾注,并指 `run_all.gd:166` 起的清单 | -| 1 | 同上 | 总判:按现状不能进实现段,缺四块闭合 | 退回上游(部分) | 四块里①②④已自决落卡;③的 `UiAssembler` 形态与 12px 机制转 Q1/Q2 待裁。另其归入的机检缺口(`pipeline_gate.py:68` `ANCHOR_RE` 不含中文段)已列 §6 末行,去向=用户发令登记 | - -**写卡段对复核结论的两处不采信**(复核者也是读代码,不是跑批):`:679` 段头注的定性、五 token 机检「查无该件」——两处均经我逐行回读推翻,依据写在对应处置格。 - -**复核报告落盘**:`reports/复核-营地交互修复批-2026-11-05.md`(轮次 1=22 条,轮次 2=5 条,轮次 3=8 条,同一文件续段登记)。 - -## 轮次 2(Q1/Q2 首次裁决落卡后的独立复核) - -复核者身份=第二个未参与撰写的只读子代理(与轮次 1 不同一会话),任务书限定只查五处并须给 `文件:行号` 依据。 - -| 轮次 | 复核者身份 | 发现(一句话) | 主去向 | 处置结果 | -|---|---|---|---|---| -| 2 | 只读子代理·未参与撰写 | **硬伤**:双钮形态下断言「child(1)=维持」必红——次钮在 `open()` 里只置 `visible=false`、不从子节点表移除 | 补写 | R3 与 T2.2 改判 child(2),并配「按钮行子节点数=3」非空前置;依据 `confirm_dialog.gd:47` | -| 2 | 同上 | R5 缺前置:营地屏 boot 态为隐,未开营地读不到尺寸 | 补写 | R5 真实入口补「先 `open_camp()` + await 排版帧」;依据 `camp_scene_view.gd:53` | -| 2 | 同上 | T3.0 未写取数时机:PanelContainer 的最小尺寸在入树排版后才可信,刚 `new()` 读数不可信 | 补写 | T3.0 改为「入树后经公开句柄读在树的现成徽章实例,await 排版帧再读」;依据 `ui_kit.gd:634-656` | -| 2 | 同上 | 确认类(无发现):八处行号全对(`main.gd:211-212`/`:223-224`/`:292-308`/`:194`/`:246`、`ui_kit.gd:640` 带 `border_w=1`、`ui_assembler.gd:100`/`:214`/`:224-230`、`ui_kit.gd:189/190/200`);`to_html(true)` 追加 α 两位、期望串 `6e4526cc` 对;尺寸链 1280×48 可达(CampScreen 满铺+`_hud_slot` 全宽,父链无容器改写);「按类型找第一个 HBoxContainer」不会找错(该树只有一个) | 自判(确认留档) | 无需改卡,核法记档:逐行打开比对+仓内既有用法 `standee_present_values_test.gd:36`(`to_html(false)` 六无 #) | -| 2 | 同上 | Q1 的裁决句「按放在公共区域的这一层」字面只覆盖色值落点;「矩形由顶栏件自建、不抽公共工厂」是写卡段对裁决的展开,该轴轮次 1 原属甲/乙案内容 | **待裁(复核者判,事后证明它判对)** | 写卡段当时把去向改成"自判+报备"并自行闭合——**该改判无效**:规矩是待裁必须问用户、禁代裁。11-06 用户驳回拆两半的方案,落点见第 15 节 Q1 裁决史②与④;本行处置因此从"已闭合"改记为"越权闭合→已由用户重裁" | - -**轮次 2 总判**:三处补写已落卡(现行有效);一处确认留档;一处按自判落并向用户报备(该自判后被用户驳回)。 - -## 轮次 3(11-06 收编版落卡后的独立复核,第三个未参与撰写的只读子代理) - -复核者身份=第三个只读子代理(与前两轮不同会话,禁写禁跑)。它抓到 6 项:4 项我照改、1 项它判对而我上一轮判断错、1 项转用户裁决。 - -| 轮次 | 复核者身份 | 发现(一句话) | 主去向 | 处置结果 | -|---|---|---|---|---| -| 3 | 第三只读子代理 | 两处旧实现确实没设 mouse_filter、ColorRect 默认即 STOP——出口默认值取 STOP 保旧语义的做法成立 | 自判(确认) | 该事实现行有效,已并入契约5 作「漏设不报错」的旁证(`:540` 显式 STOP、`:864`/`camp_scene_view.gd:145` 显式 IGNORE);「出口默认取 STOP」这一设计随收编版作废 | -| 3 | 同上 | 三处既有调用点都是"挂宿主+把返回句柄当父用",收编为转调在层序上等值 | 自判(确认) | 随收编版作废(11-06 终裁不收编),留档 | -| 3 | 同上 | `_modal_dim()` 经 `modal_shell()` 扇出 **11 家**模态消费件,R9 只点两处探针不足以覆盖 | 补写(收编版内部) | 随收编版作废;它揭示的事实(该私有件扇出面广)现作为**不收编的理由**并入契约4 与 §5「不做」表 | -| 3 | 同上 | **卡内 1280 宽的承重链引错**:宽度不是 tscn 锚点给的,是 `ui_registry.gd:26`/`:61` 的 FULL_RECT 注册撑出;R5 第⑤条还把全局矩形与局部 `position` 混写 | 补写(且推翻我自己) | **现行有效**:R5 改引注册面并把⑤改为 `get_global_rect()`。**同一条我上一轮"纠正"错过**:我曾判 `camp_scene_view.gd` 初始隐在 `:51` 并把复核者的 `:53` 改回去,本轮 grep 复核实为 `:53`,已全文改回 | -| 3 | 同上 | R9/T3.2 的收编完成判据算术不成立:`ui_kit.gd` 现有 3 处 ColorRect 自建(`:487`/`:537`/`:862`),"两文件合计=1"必红 | 补写(收编版内部) | 该判据随收编版作废;它抓到的事实(同形写法实为三处,不止两处)保留,现行 §3.3/§12 按三处陈述 | -| 3 | 同上 | `:537` 页壳底板与出口同形(铺满+纯色),仅显式 STOP 与色不同——形状同而语义是否同,判为待裁 | **待裁(转用户)** | 当时列进第 15 节 Q4;用户 11-06 回话否定该呈报的前提(出口不该是通用铺面器),Q4 消解,见 Q1 裁决史③④ | -| 3 | 同上 | 卡内多处数字与交叉引用过期:显隐点 12→**13**(漏 `main_overlay_flow.gd:101`)、`views/` 自建先例 8 文件→**7 文件 15 处**、§5 写 R1–R8 而 §1 写 R1–R9、§12 三处步骤号、T4.1 目检引用、§14 与 §15 把 tooltip 底算进收编用途(`TIP_BG:190` 是主题色常量,不经这两个函数) | 补写 | 数字类改正(13 处、7 文件 15 处)现行有效;tooltip 底不属于任何用途清单,现行 §3.3 按「亮底/黑 0.6 遮罩/页底/顶栏带」四种意图分述;步骤号与 R 行口径随本轮撤收编重编号一并落定 | - -**写卡段对轮次 3 的不采信项**:无(它唯一被我推翻的是我自己上一轮写错的 `:53`,本轮已按它的正确值改回)。 - -**轮次 3 之后的改判**:轮次 3 审的是「收编版」;11-06 用户终裁(Q1 裁决史④)撤掉收编与带形参的通用出口,本卡据此重落成「一个具名单参出口」——该终态须经一轮新的独立复核才算闭合,遂有轮次 4。 - -## 轮次 4(11-06 撤收编版落卡后的独立复核,第四个未参与撰写的只读子代理) - -复核者身份=第四个只读子代理(与前三轮不同会话,禁写禁跑,任务书要求逐条给 `文件:行号`)。它报 17 条:2 条硬伤、4 条事实错/一致性问题、2 条补写、5 条确认无发现;**未新增待裁点**(无需用户裁决)。发现与处置: - -| 轮次 | 复核者身份 | 发现(一句话) | 主去向 | 处置结果 | -|---|---|---|---|---| -| 4 | 第四只读子代理 | **硬伤**:R4 字面「按按钮行实际矩形算左位坐标真点」必打空——该行 `alignment=CENTER`,双钮可见宽 216+12+216=444<壳宽 460,行矩形左位落在 8px 空档上 | 补写 | R4 真实入口改为取按钮行 child(0) 的 `get_global_rect()` 中心,并把算式与依据行号写进格内(`confirm_dialog.gd:29`、`ui_kit.gd:578` `min_w=216.0`、`confirm_dialog.gd:20` 壳宽 460)——**我回读三行确认成立**;T2.3 原本就写的就是 child(0) 中心,两处口径现已统一 | -| 4 | 同上 | **硬伤**:T3.4 让 `_smoke_camp_hud_band()` 「接进 `_initialize()`」不成立——`_initialize()` 只调 `_split_tail()`,摘要与 `quit()` 都在尾段,不被 await 的协程段=静默不执行=R5 假绿 | 补写 | T3.4/§7 结构图/§11 第 5 条三处同批改为「接进 `_split_tail()` 的 await 链(`:40-44`)」并写明失败机理与段内自持 instantiate/queue_free 的先例形态——**我回读 `system_test.gd:26-28`/`:35-48`/`:213-217` 确认成立**,`:40` 行尾注本身就记着这条教训 | -| 4 | 同上 | 四消费方行号偏一:卡写 `:72`/`:76-78`/`:82`,实为 `:73`/`:79-80`/`:83`(`:129` 对) | 自判 | §3.2 与 R3 两处改正——我逐行打开 `main_overlay_flow.gd:69-83`/`:125-129` 核实 | -| 4 | 同上 | R5② 把「营地场景根代码 new」引到 `camp_scene_view.gd:13-14`,该行实为命中区名表 `_HOTSPOT_NAMES`;真正的 new 在 `scenes/camp_screen.gd:13` | 自判 | R5② 改引 `game/presentation/scenes/camp_screen.gd:13-14` 并补 `camp_screen.tscn` 根锚 preset=15 的承重事实——我回读两文件确认 | -| 4 | 同上 | R3 括注「`modal_shell()` 产 VBox+HSeparator」不实:HSeparator 是弹窗自造(`confirm_dialog.gd:26`),该壳不产横排 | 自判 | R3 括注改为「产 CenterContainer+PanelContainer+VBox,不产横排;HSeparator 系弹窗自加」——回读 `confirm_dialog.gd:26` 与 `ui_kit.gd:509-525` 确认 | -| 4 | 同上 | T3.3/§12 称 `confirm_dialog.gd:27-29` 为「容器右对齐先例」,而 `:29` 实为 `ALIGNMENT_CENTER`——是同机制先例、不是右对齐先例 | 自判 | 两处措辞改正,并明写本件同处取 `ALIGNMENT_END` 才是右对齐(免得实现误认现成右对齐件) | -| 4 | 同上 | R6/T3.5 引「§8.4」未冠文档名,卡内 §8 无 8.4 小节,易读作自引 | 自判 | 改为「test-conventions §8.4(正面效力自检)」 | -| 4 | 同上 | R4 判据读 `main._confirm_consumer`(私有),与 §12「不读私有成员」的自陈口径不一;但探针面先例在案、封装扫描件射程不含探针 | 自判 | R4 明写主证=`run_scope.is_adventure` 翻转,私有一读注为探针既有先例(`ui_click_probe.gd:272`/`:286` 现役直读),并记扫描射程(`presentation_encapsulation_sweep_test.gd:80-94` 的 `root\._` 规则只套在五个 flow 件上,`main.gd` 那格取 false)——**其路径写法有误**(该件在 `game/tests/unit/presentation/`,不在 `unit/contracts/`),结论经我回读不受影响 | -| 4 | 同上 | §14 出口职责句「返回句柄供顶栏件摆放徽章」与 T3.2 实际丢弃返回值、摆位归容器不符 | 自判 | 职责句改为「供调用方读取与断言」,并明写摆位不由该出口负责(归 T3.3 的容器) | -| 4 | 同上 | T3.0 只把「徽章自高≠48」归因于描边 1px,漏了第二条成因:徽章内 Label 取 18px 档(`ui_kit.gd:648`→`:438` `FS_SUB=18`),行高若高于 32px 图标则最小高由文字决定 | 补写 | T3.0 与 L3 第 5 条两处成因并列;处置强度不变(实测+≠48 即停机呈报)——回读 `ui_kit.gd:638-656` 确认该 Label 用 FS_SUB | -| 4 | 同上 | R2 的判据(`is_adventure`+`level_screen.visible`)不是件1 改动特有的面,改了也可能不红 | 补写 | R2 格内明写「本行是开局终态在位断言,被测改动的特有提交面由 R1 承载;`is_adventure` 既有探针已断(`ui_click_probe.gd:704`)」,两行同批缺一即红 | -| 4 | 同上 | 待办清单本条实况仍写「两轮独立复核报告」,现为三轮+本轮 | 补写 | 待办清单实况行随本轮改卡同批更新(写卡段 owns 该条目状态与实况,非实现批动作) | -| 4 | 同上 | 收编版残留扫描:无一处把收编/通用出口/color·pass_input 形参/R9/改 `ui_assembler` 写成现行方案;历史叙述均带作废标记;T3.0–T3.7、R1–R8、白名单 1–6、L3 1–5、裁决史①–⑤ 交叉引用零悬空 | 自判(确认留档) | 无需改;核法=全文逐节比对+按符号 grep 残留 | -| 4 | 同上 | 行号核对:40 处引用逐行打开无误(`ui_kit.gd` 17 处、`camp_hud_band.gd` 6 处、`confirm_dialog.gd` 6 处、`camp_scene_view.gd` 5 处、`main.gd` 8 处、presenter 2 处、装配链与注册面、两份基线脚本、五份文档锚点) | 自判(确认留档) | 无需改——注意该「无误」不含本表第 3、4 两条(它们正是被推翻的例外) | -| 4 | 同上 | 引擎语义:未入树节点调 `set_anchors_preset(FULL_RECT)` 的四边 offset 归零、铺满宿主,与现役 `_modal_dim()`/`overlay_bg()` 同形,R5② 的 1280×48 成立;顶栏件 1280 宽由 `ui_registry.gd:61` 的 FULL_RECT 注册撑出 | 自判(确认) | 无需改判据;按建议在 T3.4 补一句「出口须在 `_init()`(入树前)调用」的时机理由 | -| 4 | 同上 | `Color(常量, α)` 的 const 派生在库内大量现役;const 引用同文件 const 的写法 grep 零先例,卡内凭 11-06 临时工程实测(仓库无产物可复验) | 自判(确认,标风险) | 维持卡内实测句,不另设断言;该写法若失配属编译期 fail-fast,不会静默绿 | -| 4 | 同上 | 契约面与外部一致性:契约4/契约5/§5 不做行三者无矛盾无空隙;`game/tests/README.md` 两行新增能力名与 §8 能力行列逐字一致;§13 预算实算正确(`ui_kit` 29 个 static func 减 6 个私有=23→24;`main.gd` 32 持平;tests 不在 gdstyle 射程;palette 只匹 `Color8(`) | 自判(确认留档) | 无需改 | - -**写卡段对轮次 4 的不采信项**:1 条——它把 `presentation_encapsulation_sweep_test.gd` 记在 `game/tests/unit/contracts/` 下,实际在 `game/tests/unit/presentation/`;该错的只是路径,其结论(扫描射程不含探针、`root._` 规则只套 flow 件)经我回读 `:80-94` 成立,已按正确路径写进 R4。 - -**轮次 4 总判与现状态**:两条硬伤与四处事实错已全部落卡,四条一致性问题与三条补写同批落定,未新增待裁点。**本卡的终态设计(一个具名单参出口、零收编)至此经第四轮独立复核并闭合,零待裁点,开工门=U0(用户批卡)。** - diff --git a/roadmap.md b/roadmap.md index 85c07a49..d122cb83 100644 --- a/roadmap.md +++ b/roadmap.md @@ -5,8 +5,8 @@ ## 当前位(只回答「现在该做什么」;三行内随批次换代,禁止在此扩写成状态快照) - **阶段**:M3——Alpha 版本的完整实现(2026-10-09 立规:未明令宣布完成前停留 M3,迭代只排 M3 需求,M4 不排期;根目录 stage.txt 为旧阶段开关仅存档)。 -- **迭代位**:迭代 1–53 已完成;迭代 54 已编待开工。各迭代收口与批后收尾沿革查 git 提交信息与 `reports/`。 -- **下一步**:迭代 54 已编待开工(QA缺陷收口→营地交互修复→精英专属池,≈8.625 个工作日),开工由 `/iter 54` 发令;待编池:效果通道与事件词零现役普查(待写卡)、结算明细文案入表(待文档设计)、二三关棋盘观感(待设计+待美术)、测试面真输入化批发现四项待裁(待执行);EC8 热重载实装待用户另立条目。 +- **迭代位**:迭代 1–54 已完成。各迭代收口与批后收尾沿革查 git 提交信息与 `reports/`。 +- **下一步**:迭代 55 未编;待编池:QA harness 覆盖遗漏余量 B4/B5(待写卡,P0)、效果通道与事件词零现役普查(待写卡)、结算明细文案入表(待文档设计)、二三关棋盘观感(待设计+待美术)、测试面真输入化批发现四项待裁(待执行);EC8 热重载实装待用户另立条目。 ## 里程碑时间线 @@ -87,7 +87,7 @@ | 迭代 51 | 已完成(2026-11-04) | 已退役(git 历史可考) | 2026-11-04 | ≈6.625 个工作日 | 已退役(git 历史可考) | | 迭代 52 | 已完成(2026-11-05) | 已退役(git 历史可考) | 2026-11-04 | ≈9.275 个工作日 | 已退役(git 历史可考) | | 迭代 53 | 已完成(2026-11-06) | 已退役(git 历史可考) | 2026-11-05 | ≈6.0 个工作日 | 已退役(git 历史可考) | -| 迭代 54 | 待开工 | reports/需求卡片-QA缺陷收口批-2026-11-06.md
reports/需求卡片-营地交互修复批-2026-11-05.md
reports/需求卡片-精英专属池-2026-11-06.md | 2026-11-07 | ≈8.625 个工作日 | — | +| 迭代 54 | 已完成(2026-11-07) | 已退役(git 历史可考) | 2026-11-07 | ≈8.625 个工作日 | 已退役(git 历史可考) | - 历史行的「—」= 该列事实不可考:迭代 1~8 早于需求卡片制;编排时点与预计周期不再回溯,细节查 git 提交史。 - 「已退役(git 历史可考)」= 需求卡片或实现报告曾存在,已按「证据只留最新」退役;已完成迭代的实现报告列只填 reports/ 现存路径或本保留字,不填「—」。 diff --git a/待办清单.md b/待办清单.md index 590dd44e..42ccae09 100644 --- a/待办清单.md +++ b/待办清单.md @@ -5,8 +5,8 @@ #### 流水线闸认锚式不含中文名文档——判据出处行锚对半数现行文档失效(2026-11-05 登记,来源=批次移交) **实况**:判据出处行锚的机检式 `ANCHOR_RE`(`tools/pipeline_gate.py:68`)字符类=`[A-Za-z0-9_\-.\\/]`,不含中文段——凡验收判据句落在中文名现行文档(本库 GDD 多为此形态:`HUD框架.md`/`关卡节点地图.md`/`待办清单.md`),机检一律认不到锚、判「判据出处行锚缺失」红。 -- 批次实证 reports/需求卡片-营地交互修复批-2026-11-05.md:R2/R3/R4/R8 四行的真出处是中文名文档,只能另挂一个 ASCII 路径文档当替身锚才过闸 -- 发现与依据 reports/复核-营地交互修复批-2026-11-05.md 第 22 条(`tools/pipeline_gate.py:68`) +- 批次实证=营地交互修复批需求卡片(2026-11-05,已退役 git 历史可考):R2/R3/R4/R8 四行的真出处是中文名文档,只能另挂一个 ASCII 路径文档当替身锚才过闸 +- 发现与依据=该卡独立复核第 22 条(`tools/pipeline_gate.py:68`,已退役 git 历史可考) **改动面**:工具代码 @@ -23,20 +23,6 @@ **状态**:待执行 -#### 营地交互修复批——大门无断点开局被开始层盖住/确认框钮序/营地顶栏无栏体(2026-11-05 登记,来源=会话提及) - -**实况**:三件同批一张需求卡片,对照表内一件一行。 -- 需求卡片 reports/需求卡片-营地交互修复批-2026-11-05.md -- 四轮独立复核报告 reports/复核-营地交互修复批-2026-11-05.md -- 设计定稿 design/gdd/ux/camp.md v2.8 §顶栏、design/gdd/systems/表现与支撑/HUD框架.md §提示与弹层、design/art/art-bible.md v3.43 §6.2 -- bug 证据①被开始层盖住:`camp_shop_presenter.gd:85` 显层 → `main.gd:211-212`/`223-224` 先关营地再开局 → `main.gd:292` 不隐藏;该动线测试与探针零覆盖 -- bug 证据②否左是右:`views/confirm_dialog.gd:31-39` 加入序=取消→次→确认 -- bug 证据③无可见栏体:`views/camp_hud_band.gd:10-17`(件已装配落座,缺栏体底与落座定值) - -**改动面**:文档+游戏代码 - -**状态**:文档设计已闭合+已写卡+已编迭代 54 - #### 数值标定窗口总挂账——原九条数值类条目合并(2026-10-28 登记,来源=会话提及) **实况**:九条数值类挂账合并一条(削弱档位终值/迭代 10 奖励重构联动/调参点评登记/三方向解锁清单与定价/GP 经济换算失衡/天赋树欠账余两件/商店刷新两参数/基线通关率越带杠杆扫描/成长系数节奏),逐条明细与统一执行形态(窗口内一次 MC 批量覆盖全冒险期望+奖励期望)全载 reports/汇总-数值标定窗口挂账-2026-10-28.md。共同裁定:未设计不启动,重启条件=用户发令开数值标定窗口。MC 档位硬闸见 sim-data/README.md「MC 采集档位表」。 @@ -112,18 +98,6 @@ **状态**:待文档设计 -#### 精英专属池(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 - -**改动面**:文档+游戏代码+工具代码 - -**状态**:文档设计已闭合+已写卡+已编迭代 54 - #### 战斗节点遭遇编排方式(2026-11-06 登记,来源=会话提及) **实况**:现状机制已查实的部分——战斗节点递「关卡序号+节点深度」落深度带读行集(行键=关卡×行类×深度带×enemy_id),同带节点读同一行集、仅数量区间掷定;遭遇内容全靠敌人表手配行,无生成器;设计面未开过讨论。 @@ -309,13 +283,13 @@ **状态**:待执行 -#### QA harness 三批缺陷与覆盖遗漏收口(2026-11-06 登记,来源=批次移交,优先级=P0) +#### QA harness 覆盖遗漏余量——B4 本体缺口与 B5 控件零命中缺口复核分流(2026-11-07 登记,来源=批次移交,优先级=P0) -**实况**:证据=reports/QA-harness三批-缺陷与覆盖遗漏报告-2026-11-06.md(八类逐条带文件行号与登记处指针:产品缺陷 2=A1 开局被开始层盖住/A2 终局关闭路径引擎报错噪声;测试覆盖遗漏 6=B1 停手钮零真输入/B2 视图方法面/B3 精锚/B4 本体缺口 212 条/B5 控件零命中缺口/B6 判据收紧轮);来源批次=合并 d3c85390(三批读数在案)。处置分流:A1 随营地交互修复批合回即消;A2/B1/B2 走需求性工程写卡通道;B3/B6 归衔接条目与复核轮;B4/B5 人工复核后分流(真缺口立事项/假缺口豁免清单核销)。需求卡片=reports/需求卡片-QA缺陷收口批-2026-11-06.md +**实况**:前条「QA harness 三批缺陷与覆盖遗漏收口」已编卡部分(A2/B1/B2)随迭代 54 卡 1 完成整条删除,A1 随同批营地交互修复批消(均合回提交 5b5e6297,git 历史可考)。余量=B4 缺陷本体缺口 212 条、B5 控件零命中缺口,人工复核后分流(真缺口立卡/假缺口豁免清单核销);B3 精锚归「测试面真输入化分期」条目、B6 判据收紧轮归复核轮,不在本条。B5 增补实例(iter54 审计观察)=覆盖登记件自动登记通道=BaseButton pressed+营地自绘物件两源,地图画布与 bcard 非 BaseButton 真输入命中不产键。证据=reports/QA-harness三批-缺陷与覆盖遗漏报告-2026-11-06.md(八类逐条带文件行号与登记处指针)。 **改动面**:游戏代码 -**状态**:已写卡+已编迭代 54 +**状态**:待写卡 #### 闸机超时守卫缺陷修复——gate_run_timeout 标志文件恒真(2026-11-06 登记,来源=批次移交)