From 1d4ac91e3bda95048e65b7ac17c29a8e6198b80f Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 15 Oct 2026 21:16:38 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat(=E9=97=B8=E6=94=B6=E6=95=9B=E6=89=B9):?= =?UTF-8?q?=20=E9=AA=8C=E6=94=B6=E9=97=B8=E5=94=AF=E4=B8=80=E5=85=A5?= =?UTF-8?q?=E5=8F=A3=20run=5Fall=5Fgates.sh=20+=20=E5=90=88=E5=9B=9E?= =?UTF-8?q?=E9=97=B8=E5=9B=9E=E6=89=A7=E5=BC=BA=E5=88=B6=20+=20t17=20?= =?UTF-8?q?=E6=8E=A2=E9=92=88=E9=9A=94=E7=A6=BB=E4=BF=AE=E5=A4=8D=20+=20?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E9=97=B8=E6=B8=85=E5=8D=95=E5=8D=95=E4=B8=80?= =?UTF-8?q?=E4=BA=8B=E5=AE=9E=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户令「迭代完成前必须全量跑一遍所有测试」。起因是 iter27 台账只记 probe --click 未记 --full,t17_defer_probe 红了整个迭代无人发现——根因是闸清单散落 CLAUDE.md / process-conventions.md / test-conventions.md 三处、彼此不一致、且无任何机器校验。 - tools/run_all_gates.sh(新):全部验证闸的唯一入口与唯一清单,串跑冒烟/单元/探针 --click/--full/渲染/doc 三闸/静态扫描/熵增闸共十道,写回执 game/tests/.gates/receipt.json。 与 baseline.json 比对判定:基线红且红项清单未变=存量红零新增(不判失败), 基线绿转红或红项清单变化=新增红(判红)。python 解释器自动解析带 PIL 的解释器 并前置 PATH(渲染闸三个脚本依赖 PIL,用错解释器会假红)。 - .zcode/hooks/worktree-guard.sh:Bash 分支加合回闸——merge/rebase/cherry-pick 进 master 前按目标分支反查 worktree 回执,校验 commit 匹配/非 quick/无新增红三态, 任一不满足 exit 2 拦截(九态实测:匹配放行、commit 错/quick/含红/无回执/rebase 全拦)。 - game/smoke/t17_defer_probe.gd:隔离面从 main.save_manager = iso_c 改 ProbeUiUtil.isolate_save(iter27 已确立口径)。原写法对 getter-only 属性赋值无效 ——组合根 save_manager/meta 是 autoload 读视图,隔离必须落在单例上。修复后 --full 转绿。 - doc_link 三处死链归零:数据配置.md 已退役探针指路、元进度.md/天赋树.md 已改名文档链接。 - CLAUDE.md / process-conventions.md §3第10条 / test-conventions.md §4 三处 「交付前跑什么」统一为一句话=跑 run_all_gates.sh,删散落清单。 闸况:冒烟 0 / 单元 0 / --click 0 / --full 0 / 渲染 0 / doc_link 0 / doc_term 0 / 熵增 0;gdd_lint 与 static_scan 为存量红,已落 baseline.json 待判读清偿。 --- CLAUDE.md | 7 +- design/dev/process-conventions.md | 4 +- design/dev/test-conventions.md | 4 +- design/gdd/systems/表现与支撑/数据配置.md | 2 +- design/gdd/systems/跨局循环/元进度.md | 2 +- design/gdd/systems/跨局循环/天赋树.md | 2 +- game/smoke/t17_defer_probe.gd | 16 +- game/tests/.gates/.gitignore | 4 + game/tests/.gates/baseline.json | 45 +++++ tools/run_all_gates.sh | 233 ++++++++++++++++++++++ 10 files changed, 300 insertions(+), 19 deletions(-) create mode 100644 game/tests/.gates/.gitignore create mode 100644 game/tests/.gates/baseline.json create mode 100644 tools/run_all_gates.sh diff --git a/CLAUDE.md b/CLAUDE.md index 7dd3733d..5271cdbf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -16,11 +16,11 @@ ## 运行与验证(工作目录 = 含 project.godot 的切片目录) -- 冒烟:`python tools/run_smoke.py`(三闸:退出码+摘要失败数+SCRIPT ERROR 扫描;脚本错误不计失败数但静默中断剩余断言,读结果必核对) -- 场景探针:`…console.exe --headless --path . res://smoke/ui_probe.tscn`(另有 ui_tune_probe / ui_click_probe) +- **交付前验收 = 跑 `tools/run_all_gates.sh`(不带 `--quick`),全绿才合回 master**——它是全部验证闸的唯一入口与唯一清单,闸件增减只改它,文档禁另列清单。跑完写回执 `game/tests/.gates/receipt.json`,合回时由 worktree-guard 校验(缺回执/quick 模式/回执 commit ≠ HEAD/含红项四况一律拦截) +- 单件直跑(调试期最窄确认用,**不构成验收**):冒烟 `python tools/run_smoke.py` · 场景探针 `…console.exe --headless --path . res://smoke/ui_probe.tscn` · 单元 `… --script res://tests/run_all.gd` - 调参批量:`--script res://smoke/adventure_monte_carlo.gd`(全冒险期望)· `res://smoke/reward_expectation.gd`(奖励期望);通关率/难度类测量一律走全冒险 - 数值验证:`python tools/balance_verifier.py`(采集端 `res://smoke/verifier_batch.gd`,报告落 `design/qa/`) -- 交付前验收 = smoke + 全部场景探针全绿;熵增闸 = `python tools/repo_structure_audit.py`(新类别 = 同批修订 Project Layout+白名单) +- 熵增闸(新类别 = 同批修订 Project Layout + 白名单):`python tools/repo_structure_audit.py` ## Project Layout @@ -53,6 +53,7 @@ - 主工作区禁止直接改动与提交——一切改动走独立 worktree(豁免:active.md 会话收口、.zcode 钩子配置) - 测试执行两入口铁规——只有迭代 loop 开发与用户点名两个触发入口;其余会话零测试,需测试支撑先请示并注明未跑测 +- 交付前验收 = 跑 `tools/run_all_gates.sh` 全绿(唯一入口与唯一闸清单,禁在文档另列清单);合回 master 由 worktree-guard 校验回执强制(process-conventions §3) - MC/模拟:无数值改动零跑;档位硬闸见 `sim-data/README.md`「MC 采集档位表」,一档只能由用户发起 - 闸机轮次纪律:新码先孤立验证 → 出红只跑红件最小单元 → 长批先最小参数试车 → 开工扫坑册(process-conventions §6) - 变异验证——新增/改写验收函数必须变异变红才算验收成立;无变异红记录只写「已实现,拦截能力未证」(test-conventions §6) diff --git a/design/dev/process-conventions.md b/design/dev/process-conventions.md index aea94fed..c54bf62f 100644 --- a/design/dev/process-conventions.md +++ b/design/dev/process-conventions.md @@ -44,7 +44,7 @@ 9. **验收函数变异验证**——新增/改写的验收函数(冒烟断言/探针自检/闸机判据)必须配一次变异验证:故意把被测件改坏成该类缺陷形态 → 跑最窄那道闸确认变红 → `git checkout` 精确还原;变异点/跑的闸/红输出摘要/还原结论四件记入实现报告变异验证记录表;**无变异红记录的断言不写「已验收」,只写「已实现,拦截能力未证」**(细则见 test-conventions §6) **收口** -10. **批末四闸全绿才合并**——冒烟+单元测试+场景探针+改前改后读数对拍 +10. **批末全量验收才合并**——在任务 worktree 内跑 `tools/run_all_gates.sh`(不带 `--quick`),全绿才合回 master。该脚本是全部验证闸的**唯一入口与唯一清单**,闸件增减只改它;**本文与其他文档禁另列闸件清单**(清单散落多处正是 iter27 漏跑 `probe_gate --full` 的成因)。跑完写回执 `game/tests/.gates/receipt.json`,合回时由 worktree-guard 强制校验 11. **合并后主区全量复跑**——合并可能引入冲突或环境差异,落回 master 后再跑全套 12. **会话收口落记**——active.md 快照与状态记录更新(含删除已完结旧条目,doc-conventions 第 10 节);跨会话教训写入记忆库 13. **文档同步闸**——机械面文档(roadmap 行/registry/active.md 记账/README 工具注)合并前随批更新完毕方算收口;设计权威文档批内不更新:实现批收口出迭代实现报告(`design/qa/iter-实现报告-<日期>.md`:各卡状态+代拍板追认单+GDD 反哺点节),反哺点同步登记 `06-待办清单`,用户逐点裁决后另批落文;反哺点未落文期间相关 GDD 节视为待反哺,读前先查 06;需求卡片必列「关联文档同步面」按两层标注 @@ -57,7 +57,7 @@ **MC/verifier 触发细则**:仅在数值验证场景触发(改数值前后取证);normal 档为主、perfect 按需;**无数值改动的会话禁跑 MC**;结构位移类「存档锚」须先向用户请示定性再跑;需求卡片预设步骤的前提消失时(如「带值裁定后重锚」实际未投值)停问勿照字面执行。 -**分级周期口径**:轻闸(run_smoke 全量+ui_input_probe;触碰 presentation 加跑 ui_click_probe+ui_layout_probe)可随变更执行;重闸=轻闸+probe_gate --click+probe_gate --full(ui_probe/ui_tune_probe/t17_defer_probe/fx_probe 四探针)+render_gate(窗口化渲染闸:shot_probe 七屏样张 A-D 断言+fx_shot/board_shot 取证+棋盘 golden 逐像素)+run_all 单元全套+doc 三闸(gdd_lint/doc_link_audit/doc_term_audit)+熵增闸(repo_structure_audit);重闸属周期执行——统一在批次收口或固定周检跑,不进每次变更;真人实机目检归用户不进自动闸。 +**分级周期口径**:全部验证闸收编在 `tools/run_all_gates.sh` 一个入口下(**脚本即清单**),分两档——`--quick` 档跳过渲染闸(需开显示器)与静态扫描,供迭代中段自检;**收口出库一律跑全量档(不带 `--quick`)**,回执由合回闸强制校验。真人实机目检归用户不进自动闸。 ## 5. MC 采集档位细则 diff --git a/design/dev/test-conventions.md b/design/dev/test-conventions.md index 850401f0..3bb052f8 100644 --- a/design/dev/test-conventions.md +++ b/design/dev/test-conventions.md @@ -1,7 +1,7 @@ # 测试规范(Dungeon Sweeper) > 约束范围:`game/smoke/`、`game/tests/` 与一切场景探针的编写与验收。 -> 分工:测试**执行许可**(什么时候允许跑测试)归 CLAUDE.md「硬性红线·测试执行两入口铁规」;命令与工具清单归 CLAUDE.md「运行与验证」;本文管测试怎么写、怎么算合格。 +> 分工:测试**执行许可**(什么时候允许跑测试)归 CLAUDE.md「硬性红线·测试执行两入口铁规」;**跑什么闸、什么顺序**归 `tools/run_all_gates.sh`(脚本即清单,本文与 CLAUDE.md 均不另列);本文管测试怎么写、怎么算合格。 **写任何测试前必须通读本文。** @@ -26,7 +26,7 @@ ## 4. 提交前全量验证 -交付前必须全绿:`smoke_all.gd` + 全部场景探针(ui_probe / ui_click_probe / ui_tune_probe)。 +交付前跑 `tools/run_all_gates.sh`(不带 `--quick`)全绿——该脚本是全部验证闸的唯一入口与唯一清单,本文禁另列闸件清单。闸件增减只改脚本。 行为探针使用随机化玩家行为(旗/停手/刷新/无效点击)——自动玩家不做的动作就是测试盲区。 ## 5. 测试函数怎么写——验收清单条目的落码规范 diff --git a/design/gdd/systems/表现与支撑/数据配置.md b/design/gdd/systems/表现与支撑/数据配置.md index 297d2b70..47aa6ca7 100644 --- a/design/gdd/systems/表现与支撑/数据配置.md +++ b/design/gdd/systems/表现与支撑/数据配置.md @@ -218,6 +218,6 @@ | v0.1 | 2026-09-15 | 自归档 GDD 压缩改写 | | v0.2 | 2026-09-15 | 雾格残留清理:关闭「待拍板」的棋盘生成参数表雾字段清理登记(fog_region_count / fog_target_ratio 两字段、雾占比绝对上限与雾域跨字段校验)——字段与校验随雾格移除同批删除,registry `board_gen_table` 条目同步修订。表清单与校验纪律不变 | | v0.3 | 2026-09-17 | 代币→钥石统一拍板随批措辞清偿:表清单冒险表行「代币记账」改「钥石入账」;registry adventure_table 同批改键 token_per_level→keystone_per_level。表清单与校验纪律不变 | -| v0.4 | 2026-09-18 | **进度坐标解析口径修订(用户拍板,场景三讨论产物)**:① 取整方向「就近向下」→「**向上取整**」——无精确行取不低于请求坐标的最近行,理由 = 保证偏难(宁高估难度让工具读数保守,不静默降难掩盖断档);② 越域致命补齐——低于合法域(关卡序号 <1、节点深度 <0)走运行期致命:Fatal 级诊断 + 进程退出码 1,与装载期致命纪律并轨;**同日追加拍板**:高于最大已有行不致命,封顶取最大已有行并留警告(用户裁定「可取范围内向上取整,超过了最大值就用最大值」);③ registry enemy_table 条目「进度键 floor」随批改 ceil;切片 config_db._resolve_progress 同批落地(ceil 选择器 + _fatal 通道 + `smoke/config_fatal_probe.gd` 探针 + 冒烟 ceil 断言) | +| v0.4 | 2026-09-18 | **进度坐标解析口径修订(用户拍板,场景三讨论产物)**:① 取整方向「就近向下」→「**向上取整**」——无精确行取不低于请求坐标的最近行,理由 = 保证偏难(宁高估难度让工具读数保守,不静默降难掩盖断档);② 越域致命补齐——低于合法域(关卡序号 <1、节点深度 <0)走运行期致命:Fatal 级诊断 + 进程退出码 1,与装载期致命纪律并轨;**同日追加拍板**:高于最大已有行不致命,封顶取最大已有行并留警告(用户裁定「可取范围内向上取整,超过了最大值就用最大值」);③ registry enemy_table 条目「进度键 floor」随批改 ceil;切片 config_db._resolve_progress 同批落地(ceil 选择器 + _fatal 通道 + 独立进程致命类单测 + 冒烟 ceil 断言) | | v0.5 | 2026-09-27 | **统一随机流批(ADR-0007 裁丙——用户两轮复裁终选「统一用一个流」并拍「全面执行」)**:§「封闭随机流」整节改「统一随机流」口径——唯一主种子+单盐派生+唯一全局取数计数器,七流并一;取号参数降格为**用途标签**(只进事件日志不参与派生,七流名保留为封闭词表);新增**全事件日志**(冒险会话制 user://logs/rng_log_<主种子>.jsonl,逐次取数落 scope/标签/派生种子——号位全序化后单点定位的承载面);快照契约=主种子+全局计数器;扩签通道替代增流通道;表清单/依赖表/P0/验收行随批。代码实证:rng_service.gd 重写+七消费点迁移+armor_roll_stream 字段降格标签+behavior_roll 子流派生向量退役;新黄金向量 8 常量重登记(scope 0-3 与旧 board_gen 向量逐位连续)| | v0.6 | 2026-10-09 | **文档正确性审查批·独立复核(worktree docaudit-2026-10-09——四处表清单失同步,全部代码实证)**:①变异表行「现行六行」→七行(variation.tres 实测 7 行=region 6+global 贫矿脉,2026-10-04 首发批漏登);②奖励配置表 `RewardConfigTable` 行删除(表已随可选类删除下线——reward_config.tres 与类名全仓零命中);③秘宝表 `AuxItemTable`→`TreasureItemTable`(treasure_items.tres,词族对齐批换代漏登);④MetaTable「四行族」→现行五行族(+attune_refresh_upgrade,同调批扩列漏登);⑤主角表行补 armor_class 字段 | diff --git a/design/gdd/systems/跨局循环/元进度.md b/design/gdd/systems/跨局循环/元进度.md index 0070713c..8d1edc4a 100644 --- a/design/gdd/systems/跨局循环/元进度.md +++ b/design/gdd/systems/跨局循环/元进度.md @@ -180,7 +180,7 @@ MVP 不要求本系统的闭环([不做清单](../../05-不做清单.md)整体 | v1.9 | 2026-10-09 | 文档正确性审查批(定点):解锁双入口框架节「局内暂停层入口未实装(随 HUD 批 M-4)」过期订正——暂停层只读入口已实装(2026-10-06 迭代 17 卡③,实机目检待用户;06 登记条在册);裸 M-4 标签随订正消除 | | v1.10 | 2026-10-09 | **B2 裁决落文(用户令「删除旧的、直接写新的」)**:道具工坊行删旧写新——旧「现行六行」登记作废(旧目录已随秘宝 v1.5 全退役),改写=件的目录与效果现行事实源指路秘宝.md「目录(重设计 v1)」+解锁门槛谓词分级(普通 0 门槛/优秀中里程碑/稀有高里程碑,阈值归调参批)+通关次数渠道与钥石直购价归定价批后补 | | v1.11 | 2026-10-09 | **B1 裁决落文(用户令「元进度让他们都独立去写」——天赋树独立成文)**:①定名节冲突表述换代——「归档线索里的『天赋树』一词就此退役」与 v1.8 审查注(「本作不存在树形结构」失义登记)同步摘除,改写 = 退役的是归档线索旧概念的旧义、树形结构已随迭代 12 以锻造脉形态落地在役(系统现行事实源 = 天赋树.md,本批新建 v0.1);②三柜台节补指路句——属性锻造树形节点结构现行事实源 = 天赋树.md,旧三档柜台与树四线 flat 注入面叠加实态随句登记。机制零改动 | -| v1.12 | 2026-10-09 | 武器锻造成文批随迁(用户令「完成文档编写、代码不实现、记录待办」):三柜台节补指路句——属性锻造攻击/护甲两档的路线化改造设计权威文档 = [武器锻造](武器锻造.md) v0.1(按 2026-10-07 提案推荐案成文、17 裁点开放在册、实装待办在册 06;改造落地前三档直购维持现役)。机制零改动 | +| v1.12 | 2026-10-09 | 武器锻造成文批随迁(用户令「完成文档编写、代码不实现、记录待办」):三柜台节补指路句——属性锻造攻击/护甲两档的路线化改造设计权威文档 = [武器锻造](锻造工坊.md) v0.1(按 2026-10-07 提案推荐案成文、17 裁点开放在册、实装待办在册 06;改造落地前三档直购维持现役)。机制零改动 | | v1.14 | 2026-10-11 | 秘宝匣行换代随批(秘宝.md v2.7 目录修正批):13 件三档+解锁混合制口径;旧「正主/谓词分级」表述同步清除(拾取渠道指路同日追加又随终裁废止) | | v1.13 | 2026-10-10 | **「道具工坊」改名「秘宝匣」(2026-10-10 天赋树设计会话裁——树上解锁节点与营地柜台同名)**:现行正文六处扫改(三柜台行 / 柜台行 / 柜台纪律 / 后续商品行 / 调参表 P1 / 定价表行);版本历史行一律不动;别名「道具工坊」登记 registry 术语条保留检索。机制零改动 | | v1.14 | 2026-10-11 | **营地统一案甲随迁(2026-10-11 天赋树设计会话终裁)**:三柜台节补「营地统一」段——树=营地本体、属性升级唯一入口=树脊柱淬炼节点、本属性锻造柜台随 06「天赋树实装批」退役吸收进脊柱(落地前维持现役)、锻造柜台与秘宝匣转工作间钥匙模型、图鉴常开;设计权威文档指路 = 天赋树.md v0.2。机制零改动(退役与公式换代随实装批) | diff --git a/design/gdd/systems/跨局循环/天赋树.md b/design/gdd/systems/跨局循环/天赋树.md index a4aec7a1..1ed26f50 100644 --- a/design/gdd/systems/跨局循环/天赋树.md +++ b/design/gdd/systems/跨局循环/天赋树.md @@ -206,7 +206,7 @@ A/B 态只放规则面:节点行持 a/b 双效果键(封闭规则键词表 R | v0.8 | 2026-10-11 | **Fork 一节点双态换代批(用户裁)**:①开局姿态/危险直觉/财富之道三天赋=三节点——现役 A/B 双行结构(迭代 12 沿袭,「付一次钱得双态开关」裁决未落进节点组织=落文错误已纠正)收编为单行双态,同调脉 9→6(同调位 3+Fork 3)、全树 15→12;②节点语义=购买解锁双态开关(cap1、零重复购买)、解锁默认 A 态、营地零币切换(互斥由单态承载);fork_sides 存档语义不变(组→激活态),tree_buy_fork=购买解锁/tree_toggle_fork=零币切态;schema=Fork 行持 a/b 双效果键、效果按激活态取值、Fork 组词表校验改每组恰一节点;③R1(「等级阈值前置」形态去留)不随本批变化,仍开放待裁(推荐裁撤)。实装归 06「天赋树实装批」(33→12 连带,需求卡片 v1.6 同批) | | v0.7 | 2026-10-11 | **一线一节点换代批(用户裁)**:①脊柱淬炼一线一节点——生命淬炼/命中淬炼各收编为单节点 4 级(原「一线 4 层×层内 3 购」层=级收编;用户明裁:一个内容一个节点、等级在节点内、不拆多节点),脊柱 8→2、全树 21→15;②行门槛平移——SPINE_ROW_GATE=4 公式不变,门槛主语从「层 N」改「节点第 N 级」(第 2~4 级需全树总投入 ≥4/8/12),row 字段随层行退役;③彩蛋条件随结构换代为「生命/命中两节点 4 级拉满 且 同调位 1/2/3 全部解锁」;④R1(「等级阈值前置」形态去留)不随本批变化,仍开放待裁(推荐裁撤)。实装归 06「天赋树实装批」(33→15 连带,需求卡片 v1.5 同批) | | v0.6 | 2026-10-11 | **攻防所有权切分落文批(锻造工坊裁决会话 A 组定案,天赋树会话交接落文)**:①脊柱换代 16→8——攻击淬炼×4 层与护甲淬炼×4 层删除,脊柱=生命/命中两线×4 层,全树 29→21 节点(每根数值轴全游戏单一来源:生命/命中→树脊柱、攻击→锻造工坊武器路线、AC→甲路线,树零攻防来源=红线);②锻造工坊钥匙节点前置改「无」(free、直接可点亮,原「攻击淬炼累计 ≥2 且 护甲淬炼累计 ≥2」等级阈值前置随两线砍除作废)——连带开放待裁点 R1:schema「等级阈值前置」新形态现无消费者,裁撤(推荐)/留作机制位待用户裁;③地脉共鸣换代——条件改「生命/命中两线全部买满(8 节点全上限)且 同调位 1/2/3 全部解锁」、效果改生命/命中两线 flat(攻/护分量摘除),上限 3 枚不变;④行门槛 SPINE_ROW_GATE=4 规则保留(层 N 需全树总等级 ≥4×(N−1)),两线换代后总等级供给结构变化=达成节奏重算注记在册、值归数值批;⑤叠加公式换代——开局属性=角色基础值+树生命/命中淬炼 flat+锻造路线加值(只按当前选中生效)+局内加算区 flat(命中在账未注入披露不变);⑥营地呈现措辞对齐四柜台并排(树淬炼柜台=树脊柱界面形态、锻造工坊柜台钥匙点亮前=锁定态,机制语义=树营地本体/钥匙模型/图鉴常开不变,A② 裁);⑦节点总表/一脊三脉/验收标准/调参表/依赖表连带换代。实装归 06「天赋树实装批」(结构目标 33→21 连带换代,需求卡片 v1.4 同批) | -| v0.5 | 2026-10-11 | 锻造工坊更名批随迁(机械扫):五处 [武器锻造](武器锻造.md) 链接随系统更名「锻造工坊」换代为 [锻造工坊](锻造工坊.md)(v0.2 历史行内旧名按历史记载保留)。结构零改动 | +| v0.5 | 2026-10-11 | 锻造工坊更名批随迁(机械扫):五处「武器锻造」链接随系统更名「锻造工坊」换代为 [锻造工坊](锻造工坊.md)(v0.2 历史行内旧名按历史记载保留)。结构零改动 | | v0.4 | 2026-10-11 | **歧义扫描清零批(/grilling 六裁落文)**:①Q1 术语回归正主——分叉效果废「陷阱/危险标记」自造词,改「踩中危险格伤害减半」「危险格标记错误返还行动点」,玩家文案沿「危险格/安全格」;②Q2 地脉共鸣效果改生命/攻击/护甲三线(命中分量待命中线注入随批加回,不留永久无效分量);③Q3 行门槛总等级口径写明=tree_nodes 全部节点等级之和(免费点亮与分叉激活计入,沿现役实态);④Q4 财富之道范围定界——聚=仅战斗掉落渠道、散=全部 GP 消费面(用户裁);⑤Q5 限次计数生命周期落句(随冒险持久/按关重置/新冒险清零/断点保留);⑥Q6 三处旧裁决换代——已建未接面槽位判定源句换 Q2 裁决(树点亮数+旧条件作废删除)、刷新升级条补 Q1 双入口并存、存档域节「迁移重做」整节换代为「旧档废弃」(Q3 裁决落文,禁迁移红线);顺带清「Y 升级行族」黑话为「刷新升级行族」。结构零改动 | | v0.3 | 2026-10-11 | **节点台账补全批(用户令:台账指引升格文首+29 节点总表落文)**:文档最前新增「节点台账指引」块(节点结构查本文总表 / 数值查配置文件 `game/data/tables/meta_tree.tres` 双源分工声明);核心规则节补「节点总表(29 节点)」——17 行折叠式全名单(脊柱四线按层折叠),逐节点名称/脉/类型/前置/效果方向,数值不进正文沿配置纪律。结构零改动(纯台账补全) | | v0.2 | 2026-10-11 | **天赋树设计会话裁决批(结构换代+分叉效果定案+营地统一)**:①结构换代 33→29——锻造枝三属性节点(武器锻造/护身锻造/甲胄锻造,旧柜台镜像重复件)删除换单个免费解锁节点「锻造工坊」(前置=攻击淬炼累计≥2 且护甲淬炼累计≥2,等级阈值前置新形态);克制专精 Fork 对整组砍除(类型表达归武器锻造);②分叉效果定案——开局姿态两侧收每关首轮窗(先手压制=每关首轮 AP+1 / 稳健拓荒=每关首轮内受击减伤)、雷感直觉改名危险直觉(锋=陷阱伤害减半 / 守=误标返 AP·均每关限次;标错机制存在性 T0 实查在册)、经济人格改名财富之道(聚=GP 获取增益 / 散=消费折价,避开两处在册旋钮);现役两键占位态随实装批终结;③营地统一案甲——树=营地本体,属性升级唯一入口=树淬炼节点,旧属性锻造柜台退役吸收进脊柱,工作间钥匙模型(锻造工坊/秘宝匣两钥匙+图鉴常开);④叠加公式换代=基础值+树淬炼+锻造路线加值+局内加算;⑤同调位 1 改无前置根节点、串行保留;地脉共鸣条件改四线全部买满;⑥「道具工坊」改名「秘宝匣」;⑦树上刷新升级节点定性缺陷(购买写 attune_refresh_level 同账修复随批);迁移映射重做(forge_levels→脊柱线)。全部实装归 06「天赋树实装批」(原「已建未接面两件」+「结构重构批」两条合并) | diff --git a/game/smoke/t17_defer_probe.gd b/game/smoke/t17_defer_probe.gd index 90aa8fb1..5e7fda9f 100644 --- a/game/smoke/t17_defer_probe.gd +++ b/game/smoke/t17_defer_probe.gd @@ -3,9 +3,11 @@ # 真实信号路径驱动一场战斗到击杀胜利(结算行在排播队列),断言两条: # ①胜利同帧:终局面未开 + 挂起态在案 + 队列非空(旧行为=同帧 flush+开窗,本断言即红——判别性); # ②排播放完:终局面开启(演播完边沿派发——_on_pump_ended)。 -# 存档/设置/元进度三面隔离(fx_shot_probe 同款),零真实档触碰。headless 可跑(不抓帧)。 +# 存档/设置/元进度三面隔离(isolate_save 正主,meta 经 autoload 链同源),零真实档触碰。headless 可跑(不抓帧)。 extends Node +const ProbeUiUtil := preload("res://smoke/probe_ui_util.gd") # 隔离样板单点 + var main var _problems: Array = [] @@ -15,14 +17,10 @@ func _ready() -> void: main = load("res://presentation/main.tscn").instantiate() add_child(main) await get_tree().process_frame - for p0 in ["user://t17_defer_probe.json", "user://t17_defer_probe_settings.cfg"]: - if FileAccess.file_exists(p0): - DirAccess.remove_absolute(p0) - var iso_c = load("res://core/save_manager.gd").new("user://t17_defer_probe.json") - iso_c.load_from_disk() - main.save_manager = iso_c - main.meta = load("res://core/meta_progression.gd").new(main.db, iso_c) - main.settings_store = load("res://presentation/settings_store.gd").new("user://t17_defer_probe_settings.cfg") + # 存档/设置两面隔离(ProbeUiUtil.isolate_save 正主,先删后建防陈旧档泄入)—— + # 隔离面走 attach_path 原地重置 autoload 单例:组合根 save_manager/meta 是getter-only + # 读视图,直接赋值无效,隔离必须落在单例上。 + ProbeUiUtil.isolate_save(main, "t17_defer_probe", false, true, false) # 本探针验证完整动画档的演播后排窗——强制 motion_scale=1.0(隔离档替换在 boot 后, # 减动效已随真档 settings.cfg 应用于引擎态;减动效档=consume_now 快路、开窗即时,另属语义) UiKit.motion_scale = 1.0 diff --git a/game/tests/.gates/.gitignore b/game/tests/.gates/.gitignore new file mode 100644 index 00000000..f261594c --- /dev/null +++ b/game/tests/.gates/.gitignore @@ -0,0 +1,4 @@ +# 本目录只入库 baseline.json(存量基线,需随代码走以保证各 worktree 判定口径一致)。 +# receipt.json 是每跑批覆写的当次回执、*.log 是跑批当场日志——两者都是中间产物,不入库。 +receipt.json +*.log diff --git a/game/tests/.gates/baseline.json b/game/tests/.gates/baseline.json new file mode 100644 index 00000000..abe89528 --- /dev/null +++ b/game/tests/.gates/baseline.json @@ -0,0 +1,45 @@ +{ + "note": "存量基线·首次自动生成;闸况变化时本脚本会判红,需人工确认后重生成", + "gates": { + "01 冒烟全量": { + "exit": "0", + "fp": "green" + }, + "02 单元套件": { + "exit": "0", + "fp": "green" + }, + "03 探针 --click": { + "exit": "0", + "fp": "green" + }, + "04 探针 --full": { + "exit": "0", + "fp": "green" + }, + "05 渲染闸": { + "exit": "0", + "fp": "green" + }, + "06 gdd_lint": { + "exit": "1", + "fp": "d09eed46271b" + }, + "07 doc_link": { + "exit": "0", + "fp": "green" + }, + "08 doc_term": { + "exit": "0", + "fp": "green" + }, + "09 静态扫描": { + "exit": "1", + "fp": "3220614b09c4" + }, + "10 熵增闸": { + "exit": "0", + "fp": "green" + } + } +} \ No newline at end of file diff --git a/tools/run_all_gates.sh b/tools/run_all_gates.sh new file mode 100644 index 00000000..c86f7466 --- /dev/null +++ b/tools/run_all_gates.sh @@ -0,0 +1,233 @@ +#!/usr/bin/env bash +# 重闸唯一入口(2026-10-15 用户令「迭代完成前必须全量跑一遍所有测试」)—— +# 闸清单的唯一定义处。文档只写「收口跑本脚本」,禁在文档里另列闸件清单(那正是 iter27 +# 漏跑 probe_gate --full 的成因:清单散落三份文档、彼此不一致、且无机器校验)。 +# +# 跑完写回执 game/tests/.gates/receipt.json(commit + 各闸退出码 + 存量基线比对 + 时间戳); +# .zcode/hooks/worktree-guard.sh 在主工作区 git merge 时校验本回执,缺或红即拦截。 +# +# 用法:tools/run_all_gates.sh [--quick] +# --quick 跳过渲染闸(窗口化,需开显示器)与静态扫描(纯文本扫描),供迭代中段自检; +# 收口出库禁用,必须不带本参数跑全量。 +# +# 判定口径:每道闸与 game/tests/.gates/baseline.json 里的存量基线比对—— +# 基线绿 + 现绿 → 绿 +# 基线红 + 现红且清单未变 → 「存量红·对基线零新增」,不判失败(但会在回执里留名) +# 基线红 + 现红但清单新增 → 红(新增红项) +# 任意闸 exit 与基线不符 → 红 +# 基线文件首次自动生成(把当次结果当基线),此后每次跑批与之比。 +# +# 退出码:0=全绿或仅存量红零新增;1=有新增红/闸况变化;2=用法错 +set -u +REPO="$(cd "$(dirname "$0")/.." && pwd)" +GAME="$REPO/game" +STAMP_DIR="$GAME/tests/.gates" +RECEIPT="$STAMP_DIR/receipt.json" +BASELINE="$STAMP_DIR/baseline.json" +QUICK=0 +[ "${1:-}" = "--quick" ] && QUICK=1 +[ $# -gt 1 ] && { echo "用法: tools/run_all_gates.sh [--quick]"; exit 2; } + +# ── python 解释器解析:优先带 PIL 的 gamedev venv(渲染闸的 shot_checker/golden_compare 依赖), +# 回落 PATH 上的 python。渲染闸的三个脚本要 PIL,用错解释器会假红。 +PY="" +for cand in "/d/dev/python/envs/gamedev/Scripts/python.exe" "$(command -v python 2>/dev/null)" "python"; do + [ -z "$cand" ] && continue + if "$cand" -c "import PIL" >/dev/null 2>&1; then PY="$cand"; break; fi + [ -z "$PY" ] && PY="$cand" +done +GODOT="${GODOT_BIN:-/d/code/godot/Godot_v4.7.2-stable_win64_console.exe}" + +# 把带 PIL 的解释器目录前置到 PATH——render_gate.sh / shot_checker.py / golden_compare.py / +# golden_board_crop.py 内部各自调 `python`,继承本 PATH;用错解释器会因缺 PIL 假红。 +case "$PY" in + */Scripts/python.exe|*/Scripts/python) export PATH="$(dirname "$PY"):$PATH" ;; +esac + +mkdir -p "$STAMP_DIR" +declare -a NAMES=() EXITS=() LOGS=() +FAILED=0 + +echo "重闸全量跑批 · 仓库 $REPO" +echo "起跑 commit: $(git -C "$REPO" rev-parse --short HEAD 2>/dev/null || echo '非git目录')" +echo "python: $PY" +echo "godot: $GODOT" + +# ── 闸件执行:每道闸的输出落独立日志,供基线比对取指纹 ── +gate() { # gate <名称> <日志名> <命令...> + local name="$1" log="$2"; shift 2 + echo "" + echo "════════════════════════════════════════════" + echo " $name" + echo "════════════════════════════════════════════" + "$@" >"$STAMP_DIR/$log" 2>&1 + local rc=$? + # 失败时把关键行回显到终端(红必须看得见) + if [ $rc -ne 0 ]; then + grep -E "FAIL|红|Error|error" "$STAMP_DIR/$log" | tail -12 | sed 's/^/ | /' + fi + NAMES+=("$name"); EXITS+=("$rc"); LOGS+=("$log") + return 0 +} + +gate_unit() { # run_all 是 --script 模式,退出码为唯一判据 + local name="02 单元套件" + echo "" + echo "════════════════════════════════════════════" + echo " $name(--script 模式,退出码为唯一判据)" + echo "════════════════════════════════════════════" + ( cd "$REPO" && "$GODOT" --headless --path "$(cygpath -m "$GAME")" --script res://tests/run_all.gd ) \ + >"$STAMP_DIR/unit.log" 2>&1 + local rc=$? + [ $rc -ne 0 ] && tail -12 "$STAMP_DIR/unit.log" | sed 's/^/ | /' + NAMES+=("$name"); EXITS+=("$rc"); LOGS+=("unit.log") + return 0 +} + +# ── 1. 系统级断言面(冒烟三闸:退出码+摘要失败数+SCRIPT ERROR 扫描,判定无洞)── +gate "01 冒烟全量" "smoke.log" "$PY" "$REPO/tools/run_smoke.py" +# ── 2. 单元套件 ── +gate_unit +# ── 3. 场景探针 · 行为走查段 ── +gate "03 探针 --click" "probe_click.log" bash "$REPO/tools/probe_gate.sh" "$GAME" --click +# ── 4. 场景探针 · 断言段(iter27 漏跑的就是这一段)── +gate "04 探针 --full" "probe_full.log" bash "$REPO/tools/probe_gate.sh" "$GAME" --full +# ── 5. 渲染面(窗口化,依赖 PIL)── +if [ $QUICK -eq 0 ]; then + gate "05 渲染闸" "render.log" bash "$REPO/tools/render_gate.sh" "$GAME" +else + NAMES+=("05 渲染闸"); EXITS+=("SKIP"); LOGS+=("") + echo ""; echo "[gates] 05 渲染闸 → SKIP(--quick)" +fi +# ── 6. 文档三闸 ── +gate "06 gdd_lint" "gdd_lint.log" "$PY" "$REPO/tools/gdd_lint.py" +gate "07 doc_link" "doc_link.log" "$PY" "$REPO/tools/doc_link_audit.py" --strict +gate "08 doc_term" "doc_term.log" "$PY" "$REPO/tools/doc_term_audit.py" +# ── 7. 静态扫描域 + 熵增闸 ── +if [ $QUICK -eq 0 ]; then + gate "09 静态扫描" "static_scan.log" bash "$GAME/tests/static_scan.sh" + gate "10 熵增闸" "entropy.log" "$PY" "$REPO/tools/repo_structure_audit.py" +else + NAMES+=("09 静态扫描"); EXITS+=("SKIP"); LOGS+=("") + NAMES+=("10 熵增闸"); EXITS+=("SKIP"); LOGS+=("") + echo ""; echo "[gates] 09 静态扫描 / 10 熵增闸 → SKIP(--quick)" +fi + +# ── 与存量基线比对 ── +"$PY" - "$BASELINE" "$RECEIPT" "$QUICK" "$REPO" "${NAMES[@]}" -- "${EXITS[@]}" -- "${LOGS[@]}" <<'PYEOF' +import hashlib, json, os, subprocess, sys + +baseline_path, receipt_path, quick, repo = sys.argv[1:5] +rest = sys.argv[5:] +sep = rest.index("--") +names = rest[:sep] +tail = rest[sep + 1:] +sep2 = tail.index("--") +exits = tail[:sep2] +logs = tail[sep2 + 1:] + +stamp_dir = os.path.dirname(receipt_path) + +def head(): + try: + return subprocess.run(["git", "-C", repo, "rev-parse", "HEAD"], + capture_output=True, text=True, timeout=5).stdout.strip() + except Exception: + return "unknown" + +def fingerprint(exit_code, log): + """红项指纹:只取 exit!=0 时的 FAIL 关键行集合,忽略时序/耗时噪声。 + 绿闸一律记 'green'——绿闸日志里的「零红」「全绿」等字样不是红项,采进来只会造噪声。""" + if exit_code in ("0", "SKIP"): + return "green" if exit_code == "0" else "skip" + if not log: + return "red-nolog" + p = os.path.join(stamp_dir, log) + if not os.path.exists(p): + return "red-nolog" + keys = [] + with open(p, encoding="utf-8", errors="replace") as f: + for line in f: + s = line.strip() + if not s or "FAIL" not in s: + continue + keys.append(s[:160]) + if not keys: + return "red-nokeys" + return hashlib.sha1("\n".join(sorted(set(keys))).encode("utf-8")).hexdigest()[:12] + +now = {} +for n, e, l in zip(names, exits, logs): + now[n] = {"exit": e, "fp": fingerprint(e, l)} + +first_run = not os.path.exists(baseline_path) +if first_run: + with open(baseline_path, "w", encoding="utf-8") as f: + json.dump({"note": "存量基线·首次自动生成;闸况变化时本脚本会判红,需人工确认后重生成", + "gates": now}, f, ensure_ascii=False, indent=1) + base = dict(now) +else: + with open(baseline_path, encoding="utf-8") as f: + base = json.load(f).get("gates", {}) + +changed, inherited_red = [], [] +for n in names: + b, c = base.get(n), now[n] + if b is None: + changed.append("%s:无基线记录(新增闸件)" % n) + continue + if b["exit"] == c["exit"] and b["fp"] == c["fp"]: + continue + if b["exit"] != "0" and c["exit"] != "0" and b["fp"] == c["fp"]: + continue # 同款存量红,清单未变 + if b["exit"] == "0" and c["exit"] != "0": + changed.append("%s:基线绿 → 现红(exit=%s)" % (n, c["exit"])) + elif b["exit"] != "0" and c["exit"] == "0": + inherited_red.append("%s:基线红 → 现绿(改善)" % n) + else: + changed.append("%s:红项清单变化(基线 %s → 现 %s)" % (n, b["fp"], c["fp"])) + +stock_red = [n for n, e in zip(names, exits) if e not in ("0", "SKIP")] +all_green = not changed + +with open(receipt_path, "w", encoding="utf-8") as f: + json.dump({ + "commit": head(), + "commit_short": head()[:8], + "timestamp": subprocess.run(["date", "-Iseconds"], capture_output=True, text=True).stdout.strip(), + "quick_mode": quick == "1", + "first_baseline_run": first_run, + "gates": [{"name": n, "exit": e, "fingerprint": now[n]["fp"]} for n, e in zip(names, exits)], + "changed_vs_baseline": changed, + "inherited_red": inherited_red, + "all_green": all_green, + }, f, ensure_ascii=False, indent=1) + +print("") +print("─" * 60) +if first_run: + print("首次跑批:已生成存量基线 %s" % baseline_path) + print("本次结果作为基线,后续与之比对。") +if changed: + print("【闸况变化,需处理】") + for c in changed: + print(" ✗ " + c) +if inherited_red: + print("【改善】") + for c in inherited_red: + print(" ↓ " + c) +stock = [n for n, e in zip(names, exits) if e not in ("0", "SKIP")] +if stock: + print("【存量红·对基线零新增】" + "、".join(stock)) +if all_green: + print("【验收通过】闸况与基线一致,无新增红。") + sys.exit(0) +sys.exit(1) +PYEOF +RC=$? + +echo "" +echo "════════════════════════════════════════════" +printf ' 回执:%s\n 基线:%s\n commit:%s\n' "$RECEIPT" "$BASELINE" "$(git -C "$REPO" rev-parse --short HEAD 2>/dev/null || echo '?')" +echo "════════════════════════════════════════════" +exit $RC From 94f1bba840923c0fcff52f1c901e371e5594841e Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 15 Oct 2026 21:42:35 +0800 Subject: [PATCH 2/8] =?UTF-8?q?fix(=E9=97=B8=E6=94=B6=E6=95=9B=E6=89=B9?= =?UTF-8?q?=E4=BA=8C):=20gdd=5Flint=20=E5=88=86=E5=9F=9F=E8=B1=81=E5=85=8D?= =?UTF-8?q?=20+=20doc=5Fterm=20=E8=AF=AD=E5=A2=83=E8=B1=81=E5=85=8D=20+=20?= =?UTF-8?q?=E5=AD=A4=E5=84=BF=E6=8E=A2=E9=92=88=E9=80=80=E5=BD=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户令四条:清单类与术语表免 GDD 规范性检查、退役词统一处理、文件头另处解决、 无使用的探针全删。 - tools/gdd_lint.py:新增 RULE_EXEMPT(规则粒度分域豁免,**按规则不按文件**)—— 06 免 R3/R4/R7、07 免 R3/R5/R7、术语表免 R2/R5。 理由逐条写进代码注释:R3 禁修订注记与「登记处条目要能回答谁在何时裁的」直接冲突; R4 版本历史节与 06「解决即移除」的状态登记体裁冲突;R5 是节名含「流程」即触发的误匹配 (07 的「㉖全流程走查」是目检清单节、术语表「开发流程」是词条节); R7 长括注在登记处是常态。 **机械可判的完整性规则 R6/R8/R9/R10/R11 一律不豁免**,真缺陷不得藏起来。 - design/gdd/术语表.md:版本号撞号订正(10-12 那条 v1.2→v1.9,两条 10-13 顺延 v1.10/v1.11), 按真实时序重排。原撞号源于 2026-10-11 与 10-12 两批各写一个 v1.2。 - tools/doc_term_audit.py:五组退役词按语境豁免而非改正文—— 充能(秘宝主动件现行机制,扩 exempt 信号)、可选类道具与雾格(否定式引用「现行池内无可选类」 「不做清单」——替换会毁掉句意)、伏击/heavy_multiplier(battle.md 占位表里的退役敌人 id, 现行规格在 敌人系统.md)、拔旗(06 待办「件派生动词白名单」是待评估设计意图非在用机制)。 疑似现行 6 处 → 0。 - 孤儿探针退役:ui_layout_probe 与 ui_audit_probe 共 6 文件(.gd/.uid/.tscn)删除—— 两者均无任何闸脚本执行(全仓仅注释与历史报告提及)。 连带清理 render_gate.sh 头注、board_view.gd cell_size 注释、game/README.md roster 行。 **遗留**:ui_layout_probe 原承担 1920 档布局机检面,现无承载,已在 render_gate 头注标明待补。 - roadmap.md 迭代循环第 4/5 条:轻闸/重闸改指 run_all_gates.sh,闸清单不再散落第四处。 闸况:9 道绿(含 gdd_lint / doc_link / doc_term 三闸全绿);static_scan S10 文件头 125 处 按用户令不在本批处理,已落 baseline.json 作为存量红。 --- design/gdd/术语表.md | 6 +- game/README.md | 2 +- game/presentation/views/board_view.gd | 2 +- game/smoke/ui_audit_probe.gd | 161 -------------------------- game/smoke/ui_audit_probe.gd.uid | 1 - game/smoke/ui_audit_probe.tscn | 6 - game/smoke/ui_layout_probe.gd | 113 ------------------ game/smoke/ui_layout_probe.gd.uid | 1 - game/smoke/ui_layout_probe.tscn | 6 - game/tests/.gates/.gitignore | 4 - game/tests/.gates/baseline.json | 4 +- game/tests/.gates/receipt.json | 62 ++++++++++ roadmap.md | 4 +- tools/doc_term_audit.py | 17 ++- tools/gdd_lint.py | 61 +++++++--- tools/render_gate.sh | 8 +- 16 files changed, 134 insertions(+), 324 deletions(-) delete mode 100644 game/smoke/ui_audit_probe.gd delete mode 100644 game/smoke/ui_audit_probe.gd.uid delete mode 100644 game/smoke/ui_audit_probe.tscn delete mode 100644 game/smoke/ui_layout_probe.gd delete mode 100644 game/smoke/ui_layout_probe.gd.uid delete mode 100644 game/smoke/ui_layout_probe.tscn delete mode 100644 game/tests/.gates/.gitignore create mode 100644 game/tests/.gates/receipt.json diff --git a/design/gdd/术语表.md b/design/gdd/术语表.md index e719dd5e..e4f0ca10 100644 --- a/design/gdd/术语表.md +++ b/design/gdd/术语表.md @@ -99,9 +99,9 @@ | 版本 | 日期 | 改动 | |---|---|---| -| v1.10 | 2026-10-13 | 「道具」统称登记(用户立内部用语习惯):道具=秘宝/奇物/地图战斗资源三类的内部开发统称,可单说或组合(秘宝道具/奇物道具/专长道具/战斗资源道具),仅限开发内部、玩家可见面用各类正式名称;同批补登「地图战斗资源」词条(原「奖励道具经济」2026-09-16 更名后一直未入表) | -| v1.9 | 2026-10-13 | **迭代 23 反哺落文批随迁**(实现报告 §五③「若需登记补登」经用户令落文):锻造工坊节新增「路线 id / 存档域键名」词条——六路线 id 与 forge_routes 域四键(levels/unlocked/weapon/armor),实现层词汇非玩家可见;玩家向术语零新增 | -| v1.2 | 2026-10-12 | **迭代 22 反哺落文批随迁**:秘宝系统节补「自动兑付」(2026-10-12 用户裁——手动积点兑换钮形态退役)与「真视使用计数」(vision_used 生涯计数域,信标网络解锁条件)两词条 | +| v1.11 | 2026-10-13 | 「道具」统称登记(用户立内部用语习惯):道具=秘宝/奇物/地图战斗资源三类的内部开发统称,可单说或组合(秘宝道具/奇物道具/专长道具/战斗资源道具),仅限开发内部、玩家可见面用各类正式名称;同批补登「地图战斗资源」词条(原「奖励道具经济」2026-09-16 更名后一直未入表) | +| v1.10 | 2026-10-13 | **迭代 23 反哺落文批随迁**(实现报告 §五③「若需登记补登」经用户令落文):锻造工坊节新增「路线 id / 存档域键名」词条——六路线 id 与 forge_routes 域四键(levels/unlocked/weapon/armor),实现层词汇非玩家可见;玩家向术语零新增 | +| v1.9 | 2026-10-12 | **迭代 22 反哺落文批随迁**:秘宝系统节补「自动兑付」(2026-10-12 用户裁——手动积点兑换钮形态退役)与「真视使用计数」(vision_used 生涯计数域,信标网络解锁条件)两词条 | | v1.1 | 2026-10-11 | **怪物巢穴类型概念退役批(用户裁「目前没有具体的怪物巢穴类型,全部改成危险格」)**:删怪物巢穴词条、危险格与旗/控制两行换代;世界观风味层的「巢穴」隐喻〔00-游戏概念巢穴隐喻轴,产品名清巢者出处〕与美术纹样名保留,机制文档零巢穴 | | v1.0 | 2026-10-11 | 首版建立(用户令「做一个专用术语表,让读者查表阅读」):格与棋盘/资源与经济/秘宝系统/道具体系四节+退役词对照表;同批全库统一更名=危险格(原雷格/惩罚格)/整图(原板级)/专长凭证(原门票) | | v1.2 | 2026-10-11 | **机制表述巢穴补扫收尾(用户裁无类型划分)**:行动经济/音频/敌人系统等机制文档「惊动巢穴/巢穴被控制」系表述全量换代危险格(惊动 4/标中 1/被控制 2);对照表补巢穴行 | diff --git a/game/README.md b/game/README.md index 7c37ac99..5f142bd7 100644 --- a/game/README.md +++ b/game/README.md @@ -33,7 +33,7 @@ Godot_v4.7.2-stable_win64_console.exe --headless --path . res://smoke/ui_probe.t Godot_v4.7.2-stable_win64_console.exe --headless --path . res://smoke/ui_tune_probe.tscn ``` -其余八场景探针(十探针全 roster 登记——ui_click_probe 行为链 / ui_input_probe 输入合成 / ui_layout_probe 布局 / t17_defer_probe 结算演播延迟链回归 / shot_probe·fx_probe·fx_shot_probe·board_shot_probe 画面与特效采样,同上式运行)+ 板图校准工具 `smoke/calibrate_boards.gd`(board_calibration.csv 重跑入口,--script 运行): +其余八场景探针(ui_click_probe 行为链 / ui_input_probe 输入合成 / ui_struct_probe 全屏结构 / ui_contrast_probe 对比度 / ui_probe·ui_tune_probe 调参面板 / t17_defer_probe 结算演播延迟链回归 / shot_probe·fx_probe·fx_shot_probe·board_shot_probe 画面与特效采样;全部由 `tools/probe_gate.sh` 与 `tools/render_gate.sh` 调度,闸清单见 `tools/run_all_gates.sh`)+ 板图校准工具 `smoke/calibrate_boards.gd`(board_calibration.csv 重跑入口,--script 运行): 全冒险期望扫描(零加成三关连探批量——通关率/止步分布/败退节点;调参期难度读数一律走全冒险口径): diff --git a/game/presentation/views/board_view.gd b/game/presentation/views/board_view.gd index ed9fe10a..279a0d75 100644 --- a/game/presentation/views/board_view.gd +++ b/game/presentation/views/board_view.gd @@ -146,7 +146,7 @@ func set_fog_glow_bonus(bonus: int) -> void: _fog_lantern = maxi(0, bonus) refresh() # 灯光区半径变了——全板重算雾态(refresh/notify_hero_move 既有重绘驱动复用) -var cell_size: float: # 只读属性(ui_layout_probe 断言面——旧私有名 _cell 的契约化出口) +var cell_size: float: # 只读属性(棋盘格边长对外契约出口——旧私有名 _cell 的契约化出口) get: return _cell diff --git a/game/smoke/ui_audit_probe.gd b/game/smoke/ui_audit_probe.gd deleted file mode 100644 index 965a51aa..00000000 --- a/game/smoke/ui_audit_probe.gd +++ /dev/null @@ -1,161 +0,0 @@ -# VERTICAL SLICE - NOT FOR PRODUCTION -# 全屏 UI 审计截图探针(实机每一屏 vs demo 逐屏对比;shot_probe 扩展形)。 -# 必须**窗口化**运行(真渲染面;headless 守卫同 shot_probe): -# Godot_console.exe --path . res://smoke/ui_audit_probe.tscn -- <输出目录> -# 覆盖 = demo 八映射屏(start/camp/settings/map/battle/bonus/shop/end 胜败两态)+ demo 无映射三屏 -# (legend 图例/confirm 确认框/debug 调试浮窗)。真实信号路径驱动 + 合成面开窗(ui_struct_probe 同款 -# 真实 open API+拟真数据);双帧 frame_post_draw 同步抓视口纹理。 -extends Node - -const ProbeUiUtil := preload("res://smoke/probe_ui_util.gd") -const Narrator := preload("res://presentation/battle_narrator.gd") - -var main: Node -var out_dir := "" -var _problems: Array = [] - - -func _ready() -> void: - if DisplayServer.get_name() == "headless": - print("[ui_audit] FAIL — 本探针必须窗口化运行(headless 无渲染面)") - get_tree().quit(1) - return - var args := OS.get_cmdline_user_args() - out_dir = args[0] if args.size() >= 1 and args[0] != "" else "user://ui-audit" - DirAccess.make_dir_recursive_absolute(out_dir) - await get_tree().process_frame - main = load("res://presentation/main.tscn").instantiate() - add_child(main) - await get_tree().process_frame - ProbeUiUtil.isolate_save(main, "smoke_ui_audit", true, true, false) - await get_tree().process_frame - # 断点种子(2026-10-06 判官 checkpoint——demo 标题屏=有档态「继续上局」主钮亮出;无种子= - # 续玩钮隐藏,主操作语义对齐⑤无从呈现。最小合法断点快照;后续「开始冒险」流程自然覆盖) - main.save_manager.set_breakpoint({ - "master_seed": 42, "rng_counter": 0, "hero_hp": 20, "gp": 24, "keystone": 4, - "level_index": 1, "bonus": {}, "shop_purchased": {}, "relics": [], - "keystone_drops": [], "bonus_taken": {}, - }) - main._refresh_resume_button() - await get_tree().process_frame - - # 1 标题屏(启动态=有档态) - await _snap("1_start") - # 2 调试浮窗(P3 仅开始菜单可开——趁 _level_active=false 先截) - main._show_debug_overlay() - await _settle() - await _snap("9_debug") - main._close_debug_overlay() - await _settle() - # 3 设置 - main._open_settings() - await _settle() - await _snap("3_settings") - main._on_settings_closed() - await _settle() - # 4 营地 - var campbtn: Button = ProbeUiUtil.find_button(main._start_overlay, "营地", "contains") - if campbtn != null: - campbtn.pressed.emit() - await _settle() - await _snap("2_camp") - var close_btn: Button = ProbeUiUtil.find_button(main.camp_overlay, "关闭营地", "contains") - if close_btn != null: - close_btn.pressed.emit() - await _settle() - # 5 关卡地图(开始冒险→停点出图) - # 收种子断点(有断点时「开始冒险」=清档确认互斥弹窗——不收则断流,5_battle 截不上) - main.save_manager.clear_breakpoint() - main._refresh_resume_button() - await get_tree().process_frame - var lvbtn: Button = ProbeUiUtil.find_button(main._start_overlay, "开始冒险", "contains") - if lvbtn != null: - lvbtn.pressed.emit() - for i in 4: - await get_tree().process_frame - await _settle() - await _snap("4_map") - # 6 战斗(真实选路提交) - if main.level_screen != null and main.level_screen.visible: - main.level_screen.press_candidate(0) - for i in 10: - await get_tree().process_frame - await _settle() - await _snap("5_battle") - # 7 战斗结算·胜利(真实签名的拟真载荷——main.gd:697 同序) - main._end_overlay.open_victory(Narrator.battle_end_text("victory", true), "返回", - main.board_view.get_global_rect(), "战利品 GP +5 · 合计 24", - "钥石 · 累计 27", "本关加成:攻击 +1", 5, 24) - await _settle() - await _snap("8_end_victory") - main._end_overlay.close() - await _settle() - # 8 战斗结算·失败 - main._end_overlay.open_defeat(Narrator.battle_end_text("defeat", false), "返回", - main.board_view.get_global_rect()) - await _settle() - await _snap("8_end_defeat") - main._end_overlay.close() - await _settle() - # 9 三选一(拟真三卡) - main.curio_overlay.open_pick(Narrator.node_curio_header(), [ - {"id": "heal_rare", "text": "回血\n恢复 3 点"}, - {"id": "blast_rare", "text": "爆裂轰击\n下一击 +5"}, - {"id": "pierce_rare", "text": "穿甲\n无视护甲"}, - ]) - await _settle() - await _snap("6_bonus") - main.curio_overlay.visible = false - await _settle() - # 10 商店(买前态——pool 货架面=玩家正主形态,demo #v-shop 对比基线;T6 全屏页) - main.shop_overlay.open_shelf([ - {"kind_id": "attack", "display_name": "攻击强化", "value": 1, "price": 12}, - {"kind_id": "max_hp", "display_name": "生命强化", "value": 3, "price": 12}, - {"kind_id": "armor", "display_name": "护甲片", "value": 1, "price": 15}, - ], 27) - main.shop_overlay.set_visit_info(0, 1.8) # 爬价规则行(T6——presenter 同款投喂) - await _settle() - await _snap("7_shop") - main.shop_overlay.visible = false - await _settle() - # 11 图例 - main.legend_overlay.open() - await _settle() - await _snap("10_legend") - main.legend_overlay.close() - await _settle() - # 12 确认框(放弃二次确认实文案) - main.confirm_dialog.open("放弃冒险", "确认放弃本次冒险?已入账钥匙与 GP 将结算保留") - await _settle() - await _snap("11_confirm") - main.confirm_dialog.close() - await _settle() - - for s in ["1_start", "9_debug", "3_settings", "2_camp", "4_map", "5_battle", - "8_end_victory", "8_end_defeat", "6_bonus", "7_shop", "10_legend", "11_confirm"]: - var p := out_dir.path_join("real_%s.png" % s) - if not FileAccess.file_exists(p): - _problems.append("截图缺失: %s" % s) - else: - var fa := FileAccess.open(p, FileAccess.READ) - if fa == null or fa.get_length() < 1000: - _problems.append("截图疑似空文件: %s" % s) - print("[ui_audit] 完成 out=%s 问题=%d %s" % [out_dir, _problems.size(), str(_problems)]) - get_tree().quit(1 if _problems.size() > 0 else 0) - - -func _settle() -> void: - for i in 3: - await get_tree().process_frame - await RenderingServer.frame_post_draw - - -func _snap(key: String) -> void: - await RenderingServer.frame_post_draw - await RenderingServer.frame_post_draw - var img: Image = get_viewport().get_texture().get_image() - if img == null: - _problems.append("视口纹理为空: %s" % key) - return - img.save_png(out_dir.path_join("real_%s.png" % key)) - print("[ui_audit] saved %s (%dx%d)" % [key, img.get_width(), img.get_height()]) diff --git a/game/smoke/ui_audit_probe.gd.uid b/game/smoke/ui_audit_probe.gd.uid deleted file mode 100644 index d90c0c00..00000000 --- a/game/smoke/ui_audit_probe.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://ddqhkbsad4wno diff --git a/game/smoke/ui_audit_probe.tscn b/game/smoke/ui_audit_probe.tscn deleted file mode 100644 index 69689221..00000000 --- a/game/smoke/ui_audit_probe.tscn +++ /dev/null @@ -1,6 +0,0 @@ -[gd_scene load_steps=2 format=3] - -[ext_resource type="Script" path="res://smoke/ui_audit_probe.gd" id="1"] - -[node name="UIAuditProbe" type="Node"] -script = ExtResource("1") diff --git a/game/smoke/ui_layout_probe.gd b/game/smoke/ui_layout_probe.gd deleted file mode 100644 index 9414d72d..00000000 --- a/game/smoke/ui_layout_probe.gd +++ /dev/null @@ -1,113 +0,0 @@ -# VERTICAL SLICE - NOT FOR PRODUCTION -# Date: 2026-09-13(四区布局诊断探针——"内容未满幅/棋盘底裁切"回归定位:打印窗口/视口/四区实际矩形 -# 与最小尺寸、展开旗标,对照 battle.md §Layout 1280×800 基座规格) -# 断言件(1280/1920 两档): -# ①基座 1280×800(battle.md §Layout)②顶层三区(B=stage/C=info_panel/D=board_zone)互不重叠不越视口 -# ③board_view(=board_zone 子节点别名)不越视口且含于 D 区 ④1920 档钉分辨率契约 -# (stretch=canvas_items/aspect=keep 下逻辑视口与四区矩形恒定=构图与基准档一致);退出码/PASS-FAIL 语义 -# 具备闸可接形态。原诊断打印面全保留。 -# 运行:Godot_console.exe --headless --path . res://smoke/ui_layout_probe.tscn -extends Node - -const ProbeUiUtil := preload("res://smoke/probe_ui_util.gd") # T6 收口:隔离样板单点 - - -func _ready() -> void: - await get_tree().process_frame # autoload 就绪 - var main: Node = load("res://presentation/main.tscn").instantiate() - add_child(main) - await get_tree().process_frame - # 存档隔离(迭代 8 卡①②——停点断点写盘随 main.save_manager;探针禁碰真实档,同族探针隔离纪律; - # isolate_save 先删后建——上次运行的残留断点会触发互斥确认早退) - ProbeUiUtil.isolate_save(main, "smoke_layout_probe_save", true, false, true) - main.debug_overlay.seed_edit.text = "42" # 种子钉死(迭代 18 卡⑦审计🔴——种子框默认改空后空框=非首局随机,探针确定性禁依赖默认分支) - main._start_adventure_from_menu() - for i in range(3): - await get_tree().process_frame - var win := get_window() - print("window.size=%s pos=%s mode=%s" % [win.size, win.position, win.mode]) - print("viewport.visible_rect=%s" % get_viewport().get_visible_rect()) - print("main.size=%s" % main.size) - for c in main.get_children(): - if c is Control: - _dump_ctrl(c, 0) - var zones := { - "board_zone": main.board_zone, "board_view": main.board_view, - "info_panel": main.info_panel, - "stage": main.stage, - } - for k in zones: - var ctl: Control = zones[k] - if ctl == null: - print("%s = null" % k) - continue - print("%-16s pos=%s size=%s min=%s hflag=%d vflag=%d" % [k, ctl.position, ctl.size, - ctl.custom_minimum_size, ctl.size_flags_horizontal, ctl.size_flags_vertical]) - var root_box: Control = main._adventure_screen.battle_root # 迭代 27 T1——屏壳化后战斗四区根迁冒险屏壳(序数寻址漂移改名寻址) - print("four-zone root: anchors=(%s,%s)-(%s,%s) offsets=(%s,%s,%s,%s) size=%s" % [ - root_box.anchor_left, root_box.anchor_top, root_box.anchor_right, root_box.anchor_bottom, - root_box.offset_left, root_box.offset_top, root_box.offset_right, root_box.offset_bottom, root_box.size]) - print("board_view cell_size=%s board=%s" % [main.board_view.get("cell_size"), main.board_view.board()]) - - # ── 最小布局断言(迭代 19 卡① T5——1280/1920 两档;语义见头注) ── - var problems: PackedStringArray = [] - var vr: Rect2 = get_viewport().get_visible_rect() - if vr.size != Vector2(1280, 800): - problems.append("基座视口 %s ≠ 1280x800(battle.md §Layout)" % vr.size) - var azones := {"stage": main.stage, "info_panel": main.info_panel, "board_zone": main.board_zone} - var arects := {} - for k in azones: - var actl: Control = azones[k] - if actl == null: - problems.append("%s=null" % k) - continue - var ar := Rect2(actl.global_position, actl.size) - arects[k] = ar - if ar.size.x <= 0.0 or ar.size.y <= 0.0: - problems.append("%s 零尺寸 %s" % [k, ar.size]) - elif not vr.encloses(ar): - problems.append("%s 越视口 %s ⊄ %s" % [k, ar, vr]) - var bvc: Control = main.board_view - if bvc == null: - problems.append("board_view=null") - else: - var br := Rect2(bvc.global_position, bvc.size) - if not vr.encloses(br): - problems.append("board_view 越视口 %s ⊄ %s" % [br, vr]) - if arects.has("board_zone") and not arects["board_zone"].encloses(br): - problems.append("board_view 越出 board_zone(%s ⊄ %s)" % [br, arects["board_zone"]]) - var akeys := arects.keys() - for i in range(akeys.size()): - for j in range(i + 1, akeys.size()): - if arects[akeys[i]].intersects(arects[akeys[j]]): - problems.append("顶层区重叠 %s×%s(%s ∩ %s)" % [akeys[i], akeys[j], arects[akeys[i]], arects[akeys[j]]]) - # 1920 档(Q4 注记对应面:单档 1280 闸+本两档断言钉 1920 构图恒等——分辨率维度不重复建闸) - get_window().size = Vector2i(1920, 1080) - for i in range(4): - await get_tree().process_frame - var vr2: Rect2 = get_viewport().get_visible_rect() - if vr2 != vr: - problems.append("1920 档逻辑视口漂移 %s ≠ %s(案甲:stretch 基座恒定)" % [vr2, vr]) - for k in azones: - var actl2: Control = azones[k] - if actl2 == null: - continue - var ar2 := Rect2(actl2.global_position, actl2.size) - if arects.has(k) and ar2 != arects[k]: - problems.append("1920 档 %s 矩形漂移 %s ≠ %s(案甲:构图与基准档一致)" % [k, ar2, arects[k]]) - if problems.is_empty(): - print("[layout_probe] PASS — 1280/1920 两档全过(基座1280x800/顶层三区互斥不越界/board_view含于D区/案甲构图恒定)") - get_tree().quit(0) - else: - for p in problems: - print("[layout_probe] FAIL — " + p) - print("[layout_probe] FAIL — %d 项断言未过" % problems.size()) - get_tree().quit(1) - - -func _dump_ctrl(c: Control, depth: int) -> void: - var ind := " ".repeat(depth) - print("%s%s pos=%s size=%s min=%s" % [ind, c.name, c.position, c.size, c.custom_minimum_size]) - for ch in c.get_children(): - if ch is Control: - _dump_ctrl(ch, depth + 1) diff --git a/game/smoke/ui_layout_probe.gd.uid b/game/smoke/ui_layout_probe.gd.uid deleted file mode 100644 index 46dbe351..00000000 --- a/game/smoke/ui_layout_probe.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://buhvfu36e2dqf diff --git a/game/smoke/ui_layout_probe.tscn b/game/smoke/ui_layout_probe.tscn deleted file mode 100644 index 1b5a4210..00000000 --- a/game/smoke/ui_layout_probe.tscn +++ /dev/null @@ -1,6 +0,0 @@ -[gd_scene load_steps=2 format=3] - -[ext_resource type="Script" path="res://smoke/ui_layout_probe.gd" id="1"] - -[node name="UILayoutProbe" type="Node"] -script = ExtResource("1") diff --git a/game/tests/.gates/.gitignore b/game/tests/.gates/.gitignore deleted file mode 100644 index f261594c..00000000 --- a/game/tests/.gates/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# 本目录只入库 baseline.json(存量基线,需随代码走以保证各 worktree 判定口径一致)。 -# receipt.json 是每跑批覆写的当次回执、*.log 是跑批当场日志——两者都是中间产物,不入库。 -receipt.json -*.log diff --git a/game/tests/.gates/baseline.json b/game/tests/.gates/baseline.json index abe89528..14e514d7 100644 --- a/game/tests/.gates/baseline.json +++ b/game/tests/.gates/baseline.json @@ -22,8 +22,8 @@ "fp": "green" }, "06 gdd_lint": { - "exit": "1", - "fp": "d09eed46271b" + "exit": "0", + "fp": "green" }, "07 doc_link": { "exit": "0", diff --git a/game/tests/.gates/receipt.json b/game/tests/.gates/receipt.json new file mode 100644 index 00000000..675463a1 --- /dev/null +++ b/game/tests/.gates/receipt.json @@ -0,0 +1,62 @@ +{ + "commit": "1d4ac91e3bda95048e65b7ac17c29a8e6198b80f", + "commit_short": "1d4ac91e", + "timestamp": "2026-10-15T21:42:07+08:00", + "quick_mode": false, + "first_baseline_run": true, + "gates": [ + { + "name": "01 冒烟全量", + "exit": "0", + "fingerprint": "green" + }, + { + "name": "02 单元套件", + "exit": "0", + "fingerprint": "green" + }, + { + "name": "03 探针 --click", + "exit": "0", + "fingerprint": "green" + }, + { + "name": "04 探针 --full", + "exit": "0", + "fingerprint": "green" + }, + { + "name": "05 渲染闸", + "exit": "0", + "fingerprint": "green" + }, + { + "name": "06 gdd_lint", + "exit": "0", + "fingerprint": "green" + }, + { + "name": "07 doc_link", + "exit": "0", + "fingerprint": "green" + }, + { + "name": "08 doc_term", + "exit": "0", + "fingerprint": "green" + }, + { + "name": "09 静态扫描", + "exit": "1", + "fingerprint": "3220614b09c4" + }, + { + "name": "10 熵增闸", + "exit": "0", + "fingerprint": "green" + } + ], + "changed_vs_baseline": [], + "inherited_red": [], + "all_green": true +} \ No newline at end of file diff --git a/roadmap.md b/roadmap.md index 83ddf800..1146556b 100644 --- a/roadmap.md +++ b/roadmap.md @@ -102,8 +102,8 @@ 1. **计划书**(`.zcode/plans/<迭代名>-loop-plan-<日期>.md`):迭代目标与完成定义 / 现状事实(代码级,开工自行复核)/ 设计契约(违反即返工,标 🔴 触碰=L3 停机)/ 范围边界 / 任务卡 T0..Tn(逐卡估时)/ 验证闸 / 异常分级 / 代拍板白名单。 2. **T0 开工**:建 worktree + 基线复读记档(冒烟/探针/三闸/MC 对拍基准)+ `git status` 归属核对(并行遗留只标旗不碰)。 3. **循环骨架**:一轮 = 一个任务卡——读卡 → 对事实源 → 实装 → 轻闸全绿 → 提交(代拍板随 commit 记录)→ 状态记录追加(查撞号)→ 下一轮。单 worktree 多点提交一次合并;轮内禁开第二个 worktree;基线每轮开工时点重测;断点续跑 = `git log` 对任务卡定轮次 + 重跑当轮轻闸。 -4. **轻闸**(每轮必跑,headless):run_smoke 全量 + ui_input_probe(十一断言);触碰 presentation 加跑 ui_click_probe + ui_layout_probe。 -5. **重闸**(批末 Tn):全量轻闸 + doc 三闸(doc_link / gdd_lint / doc_term,对基线零新增)+ 熵增闸 + MC 逐位对拍(涉核心)+ 素材批加机检断言。 +4. **轻闸**(每轮必跑,headless):`tools/run_all_gates.sh --quick`(迭代中段自检档)。 +5. **重闸**(批末 Tn):`tools/run_all_gates.sh` 全量档全绿——闸件清单与顺序只在该脚本里定义,本文件与 CLAUDE.md/规约均不另列;MC 逐位对拍(涉核心)+ 素材批加机检断言另行。 6. **人闸**(停机交付):真人目检清单 + 代拍板追认清单 + 异步终审触点(样张类)——本循环内唯一必经人审。 7. **异常分级**:L1 自救(一次重试)→ L2 记录继续(连续 3 次同红灯升级)→ L3 停机写报告等用户。 8. **收口五步**:①active.md 快照 ②状态记录条目 ③里程碑移动更新本文件 ④阶段变更改 stage.txt ⑤批末闸序列全绿留痕(loop_dashboard 已随目录收敛退役,透视职责由 06+状态记录承接)。 diff --git a/tools/doc_term_audit.py b/tools/doc_term_audit.py index 44d43632..3a101fb1 100644 --- a/tools/doc_term_audit.py +++ b/tools/doc_term_audit.py @@ -52,7 +52,22 @@ DEFAULT_DIRS = ["design/gdd", "design/registry"] # 充能:挖掘期/战斗段充能退役(2026-09-19),但秘宝主动件「每冒险充能」(同调件 # 使用次数账,迭代 11 起在役)系现行机制共用该词——秘宝/同调/主动件等语境不算命中。 TERM_CONTEXT_EXEMPT = { - "充能": re.compile(r"秘宝|同调|主动件|每冒险|冒险开始|充能账|充能维护|attunement"), + "充能": re.compile(r"秘宝|同调|主动件|每冒险|冒险开始|充能账|充能维护|attunement" + r"|incense_stick|sky_eye|reveal_tiles|战斗级充能|关卡级充能|每战一次|每关一次"), + # 否定式/反照式引用:正文在说明「该类别已退役/不做/不存在」,退役词出现在句中是 + # 陈述本身的一部分,替换掉反而毁掉句意(2026-10-15 用户令「统一替换」问询的判定)。 + "道具窗口|可选类道具|已消耗未生效|使用被拒|窗口打开锚行|窗口跳过锚行": re.compile( + r"无可选类|不存在|已随|整体删除|现行池内|不进背包"), + "雾格": re.compile(r"不做清单|战争迷雾类机制"), + # heavy_multiplier 字段与 ambusher 敌人行同于 2026-09-20 八型批整体退役(enemy_table.gd + # 与 enemy.tres 均零命中);battle.md「敌人意图线索映射目录」是 2026-09-12 成文占位表, + # 现行敌人为 goblin/hobgoblin/bugbear/giant_spider/drider/duergar 系,占位行里的退役 + # 敌人 id 只能读作历史留档(真正的现行规格在 敌人系统.md「目标顺位与意图线索」节)。 + "伏击": re.compile(r"ambusher|成文占位"), + "heavy_multiplier|重击倍率": re.compile(r"ambusher|heavy_multiplier|成文占位"), + # 拔旗(2026-09-19 退役「旗无移除手段」):06 待办清单「件派生动词白名单」条目说的是 + # 「将来件池 ≥30 种后可能开放的第三盘面动作」,是待评估的设计意图而非在用机制。 + "拔旗|撤旗": re.compile(r"件派生动词白名单|第三盘面动作|非信息类"), } # 行级白名单信号:命中任一即归"留档类" diff --git a/tools/gdd_lint.py b/tools/gdd_lint.py index d75b9fc7..23348232 100644 --- a/tools/gdd_lint.py +++ b/tools/gdd_lint.py @@ -8,12 +8,13 @@ r"""gdd_lint.py — GDD lean 格式门禁 规则(与 .claude/docs/templates/game-design-document.md 纪律一一对应): R1 散文段落 ≤ 240 字(代码块/表格/列表/引用不计) - R2 表格字符占比 ≥ 60%(代码块不计入分母) - R3 正文禁止修订注记:~~删除线~~、"作废"、括号内"日期+评审/修订/拍板/裁决/核销"(版本历史节豁免) - R4 必须有「版本历史」节且含表格 - R5 流程/状态类章节必须含代码块图(字符画或 Mermaid) + R2 表格字符占比(词条表分域豁免,见 R2_EXEMPT 注) + R3 正文禁止修订注记:~~删除线~~、"作废"、括号内"日期+评审/修订/拍板/裁决/核销"(版本历史节豁免; + 登记处/清单按 RULE_EXEMPT 分域豁免) + R4 必须有「版本历史」节且含表格(登记处按 RULE_EXEMPT 分域豁免) + R5 流程/状态类章节必须含代码块图(字符画或 Mermaid);清单节/词条节按 RULE_EXEMPT 分域豁免 R6 表格列数一致(含转义 \| 识别) - R7 括号嵌套跨度 ≤ 80 字(长括号 = 审计注记挤进正文的信号) + R7 括号嵌套跨度 ≤ 80 字(长括号 = 审计注记挤进正文的信号;登记处/清单按 RULE_EXEMPT 分域豁免) R8 核心规则表:规则列必须是"谁·何时·做什么"陈述句所在的可读表——说明/要点列 禁止出现编号引用(AC-x/F-x/EC-x/E-x/OQ-x/Rule-x/义务),引用只允许在依据类列 R9 一页纸节点:任一标题节点的直接内容(到下一标题为止)≤ 80 行——装不下就拆子节点 @@ -50,6 +51,24 @@ R2_EXEMPT = { "05-不做清单.md", # 清单文:条目散文为体裁 "06-待办清单.md", "07-体验验证清单.md", + "术语表.md", # 词条表:表格为主体形态,表格占比高是体裁本身 +} +# 规则粒度分域豁免(2026-10-15 用户令「清单类文件与术语表不做 GDD 规范性检查」)。 +# 原则:**按规则豁免,不按文件拉黑**——体裁规则(R3/R4/R5/R7)对登记处/清单/词条表 +# 不适用,但机械可判的完整性规则(R6/R8/R9/R10/R11)一律不豁免,真缺陷不得藏起来。 +# 各条理由: +# R3 正文禁修订注记——登记处/清单的条目「带日期+裁决来源」是设计目的本身 +# (条目要能回答「这条谁在何时裁的」),禁它等于禁登记处的核心价值。 +# R4 必须有版本历史节——06 是「解决即移除」的状态登记,条目不按版本累积, +# 强塞版本历史表反而制造第二套需同步的真相。 +# R5 流程/状态类节须含代码块图——节名含「流程/生命周期」即触发,但 07 的 +# 「㉖…全流程走查」「㉗…目检」是目检清单节、术语表的「开发流程」是词条节, +# 两者都不是流程描述,属节名误匹配。 +# R7 括号跨度 ≤80 字——长括注在登记处/清单里是常态(现状+裁决+归属挤在一行)。 +RULE_EXEMPT = { + "06-待办清单.md": {"R3", "R4", "R7"}, + "07-体验验证清单.md": {"R3", "R5", "R7"}, + "术语表.md": {"R5"}, } DEFAULT_DIR = "design/gdd" @@ -187,6 +206,7 @@ def lint_file(path): # R1 段落长度(登记处/清单文分域豁免,见 R1_EXEMPT 注) fname = Path(path).name + ex = RULE_EXEMPT.get(fname, set()) # 规则粒度分域豁免(见 RULE_EXEMPT 注) if fname not in R1_EXEMPT: for p in paras: if len(p) > MAX_PARA: @@ -204,27 +224,29 @@ def lint_file(path): else: infos.append(f"表格占比 {ratio}%") - # R3 修订注记(版本历史节豁免;代码块豁免) + # R3 修订注记(版本历史节豁免;代码块豁免;登记处/清单按 RULE_EXEMPT 豁免) body_no_code = "\n".join( l for l in text.splitlines() if l not in code_lines and l not in version_lines ) - for m in re.finditer(r"~~.+?~~", body_no_code): + for m in (() if "R3" in ex else re.finditer(r"~~.+?~~", body_no_code)): issues.append(f"R3 删除线残留: …{m.group(0)[:40]}…") - if re.search(r"作废", body_no_code): + if "R3" not in ex and re.search(r"作废", body_no_code): line_no = next( i + 1 for i, l in enumerate(body_no_code.splitlines()) if "作废" in l ) issues.append(f"R3 \"作废\"注记残留(第 {line_no} 行附近)") - for m in DATE_KEYWORD_RE.finditer(body_no_code): - issues.append(f"R3 正文修订注记: {m.group(0)[:50]}") + if "R3" not in ex: + for m in DATE_KEYWORD_RE.finditer(body_no_code): + issues.append(f"R3 正文修订注记: {m.group(0)[:50]}") - # R4 版本历史 - if VERSION_SECTION not in text: - issues.append(f"R4 缺「{VERSION_SECTION}」节") - elif not any(l.strip().startswith("|") for l in version_lines): - issues.append(f"R4 「{VERSION_SECTION}」节无表格") + # R4 版本历史(登记处按 RULE_EXEMPT 豁免——条目「解决即移除」,不按版本累积) + if "R4" not in ex: + if VERSION_SECTION not in text: + issues.append(f"R4 缺「{VERSION_SECTION}」节") + elif not any(l.strip().startswith("|") for l in version_lines): + issues.append(f"R4 「{VERSION_SECTION}」节无表格") # R10 版本历史版本号唯一性(实证撞号:v0.19 曾被并行两批同时占用) ver_seen = {} # key: 归一版本号 → [首次原样 token, 出现次数] @@ -248,20 +270,21 @@ def lint_file(path): if count > 1: issues.append(f"R10 版本历史版本号重复: {first}({count} 处)") - # R5 流程章节须含代码块图 + # R5 流程章节须含代码块图(清单节/词条节按 RULE_EXEMPT 豁免——节名含「流程」 + # 即触发,但目检清单节与术语词条节不是流程描述,属节名误匹配) cur_section = "" pending_flow, has_code = False, False for raw in text.splitlines(): stripped = raw.strip() if raw.startswith("## "): - if pending_flow and not has_code: + if pending_flow and not has_code and "R5" not in ex: issues.append(f"R5 「{cur_section}」节无流程图(须含代码块字符画/Mermaid)") cur_section = stripped.lstrip("#").strip() pending_flow = bool(FLOW_SECTION_RE.search(cur_section)) and cur_section != VERSION_SECTION has_code = False elif stripped.startswith("```") and cur_section: has_code = True - if pending_flow and not has_code: + if pending_flow and not has_code and "R5" not in ex: issues.append(f"R5 「{cur_section}」节无流程图(须含代码块字符画/Mermaid)") # R6 表格列数一致 @@ -320,7 +343,7 @@ def lint_file(path): # R7 括号跨度 longest = max((paren_spans(p) for p in paras), key=lambda s: max((len(x) for x in s), default=0), default=[]) longest_span = max((len(s) for s in longest), default=0) - if longest_span > MAX_PAREN_SPAN: + if longest_span > MAX_PAREN_SPAN and "R7" not in ex: issues.append(f"R7 最长括号跨度 {longest_span} 字(>{MAX_PAREN_SPAN})——疑似审计注记挤进正文") infos.append(f"最长括号跨度 {longest_span} 字") diff --git a/tools/render_gate.sh b/tools/render_gate.sh index 06a3d47d..dcba45d9 100644 --- a/tools/render_gate.sh +++ b/tools/render_gate.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash # 渲染闸正主(迭代 19 卡① 自动化验收补齐批 2026-10-08 落码——T1/T2)——窗口化自动闸。 # 迭代 15③ 挂账「渲染五闸」机器补跑半随本闸落籍(shot_probe/golden_compare/board_shot 三件入闸; -# fx_probe 逻辑层归 probe_gate --full、ui_layout_probe 归其自身两档断言——归宿对账见卡①任务书 §一)。 +# fx_probe 逻辑层归 probe_gate --full——归宿对账见卡①任务书 §一; +# ui_layout_probe 原列此处,2026-10-15 用户裁「无使用的探针删除」随批退役,1920 档布局机检面待补)。 # 骨架复用 probe_gate:①每段 timeout 守卫(挂死=FAIL 不静默)②段前预清+段后清本 game 目录孤儿 # Godot(按命令行精确匹配本 game 路径,不误杀其他 worktree 会话)③末尾残留清点=批末闸(必须 0)。 # 段: @@ -15,8 +16,9 @@ # game/tests/golden/ 三张基线(容差 provisional:差 ≤16/changed ≤2%,S2 停机点口径)。 # 素材缺位=SKIP 不判红(Q5 运行时口径;基线生成期素材缺位=L3 停机——基线禁锚回退态)。 # ④ 基准档 1280 单档(Q4)。1920 档注记:16:9 全屏下 stretch=canvas_items/aspect=keep 等比 -# 1.35×+左右黑边各 96px,构图与基准档一致(迭代 9 分辨率案甲)——分辨率维度不重复建闸, -# ui_layout_probe 两档断言(T5)承担 1920 布局机检面。 +# 1.35×+左右黑边各 96px,构图与基准档一致(迭代 9 分辨率案甲)——分辨率维度不重复建闸。 +# (原由 ui_layout_probe 两档断言承担,探针已随 2026-10-15 裁「无使用的探针删除」退役, +# 1920 布局机检面现无承载,待补。) # 过程产物纪律(Q2):一切截图 PNG 落 mktemp 临时区,闸毕即弃——任何过程 PNG 禁入 git; # 例外=game/tests/golden/ 基线(测试资产入库,.gitignore 已核不挡)。 # 窗口化运行会短暂弹 Godot 窗口(本机可开窗口径,2026-10-07 用户令);禁改 --headless 跑本闸 From eb5e892456bb6d6246e3c0d7ced86349be99e08e Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 15 Oct 2026 22:07:13 +0800 Subject: [PATCH 3/8] =?UTF-8?q?fix(=E9=97=B8=E6=94=B6=E6=95=9B=E6=89=B9?= =?UTF-8?q?=E4=B8=89):=20.gates/.gitignore=20=E5=85=A5=E5=BA=93=20+=20?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E8=87=AA=E6=84=88=E9=87=8D=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 合回 master 时发现:.gates/.gitignore 未入库,receipt.json 被纳入版本管理—— 它是每跑批覆写的当次回执,属中间产物。 成因:重跑闸前用 rm -rf game/tests/.gates 清目录,把 .gitignore 一起带走了; 脚本自身不重建,跑得再多次也不会回来。 - .gates/.gitignore 入库(挡 receipt.json 与 *.log)。 - run_all_gates.sh 启动时自愈:.gitignore 缺失则重建,杜绝复发。 --- game/tests/.gates/.gitignore | 4 +++ game/tests/.gates/receipt.json | 62 ---------------------------------- tools/run_all_gates.sh | 10 +++++- 3 files changed, 13 insertions(+), 63 deletions(-) create mode 100644 game/tests/.gates/.gitignore delete mode 100644 game/tests/.gates/receipt.json diff --git a/game/tests/.gates/.gitignore b/game/tests/.gates/.gitignore new file mode 100644 index 00000000..145f1aa6 --- /dev/null +++ b/game/tests/.gates/.gitignore @@ -0,0 +1,4 @@ +# 本目录只入库 baseline.json(存量基线,需随代码走以保证各 worktree 判定口径一致)。 +# receipt.json 是每跑批覆写的当次回执、*.log 是跑批当场日志——两者都是中间产物,不入库。 +receipt.json +*.log \ No newline at end of file diff --git a/game/tests/.gates/receipt.json b/game/tests/.gates/receipt.json deleted file mode 100644 index 675463a1..00000000 --- a/game/tests/.gates/receipt.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "commit": "1d4ac91e3bda95048e65b7ac17c29a8e6198b80f", - "commit_short": "1d4ac91e", - "timestamp": "2026-10-15T21:42:07+08:00", - "quick_mode": false, - "first_baseline_run": true, - "gates": [ - { - "name": "01 冒烟全量", - "exit": "0", - "fingerprint": "green" - }, - { - "name": "02 单元套件", - "exit": "0", - "fingerprint": "green" - }, - { - "name": "03 探针 --click", - "exit": "0", - "fingerprint": "green" - }, - { - "name": "04 探针 --full", - "exit": "0", - "fingerprint": "green" - }, - { - "name": "05 渲染闸", - "exit": "0", - "fingerprint": "green" - }, - { - "name": "06 gdd_lint", - "exit": "0", - "fingerprint": "green" - }, - { - "name": "07 doc_link", - "exit": "0", - "fingerprint": "green" - }, - { - "name": "08 doc_term", - "exit": "0", - "fingerprint": "green" - }, - { - "name": "09 静态扫描", - "exit": "1", - "fingerprint": "3220614b09c4" - }, - { - "name": "10 熵增闸", - "exit": "0", - "fingerprint": "green" - } - ], - "changed_vs_baseline": [], - "inherited_red": [], - "all_green": true -} \ No newline at end of file diff --git a/tools/run_all_gates.sh b/tools/run_all_gates.sh index c86f7466..3035105b 100644 --- a/tools/run_all_gates.sh +++ b/tools/run_all_gates.sh @@ -28,6 +28,15 @@ QUICK=0 [ "${1:-}" = "--quick" ] && QUICK=1 [ $# -gt 1 ] && { echo "用法: tools/run_all_gates.sh [--quick]"; exit 2; } +# 回执与日志是中间产物(不入库),但 .gitignore 本身必须入库——漏了就等于把它们纳入版本管理。 +# 每次跑批前自愈重建,避免「清目录重跑」把 .gitignore 一起带走(2026-10-15 实踩)。 +mkdir -p "$STAMP_DIR" +if [ ! -f "$STAMP_DIR/.gitignore" ]; then + printf '# 本目录只入库 baseline.json(存量基线,需随代码走以保证各 worktree 判定口径一致)。\n# receipt.json 是每跑批覆写的当次回执、*.log 是跑批当场日志——两者都是中间产物,不入库。\nreceipt.json\n*.log\n' \ + > "$STAMP_DIR/.gitignore" + echo "[gates] 已自愈重建 $STAMP_DIR/.gitignore" +fi + # ── python 解释器解析:优先带 PIL 的 gamedev venv(渲染闸的 shot_checker/golden_compare 依赖), # 回落 PATH 上的 python。渲染闸的三个脚本要 PIL,用错解释器会假红。 PY="" @@ -44,7 +53,6 @@ case "$PY" in */Scripts/python.exe|*/Scripts/python) export PATH="$(dirname "$PY"):$PATH" ;; esac -mkdir -p "$STAMP_DIR" declare -a NAMES=() EXITS=() LOGS=() FAILED=0 From 20f4a7dc01555d4effced651b135655d819e4d3e Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 15 Oct 2026 22:23:53 +0800 Subject: [PATCH 4/8] =?UTF-8?q?feat(=E6=94=B6=E5=8F=A3=E9=97=B8):=20active?= =?UTF-8?q?.md=20=E4=BD=93=E9=87=8F=E9=97=B8=E5=B9=B6=E5=85=A5=E5=85=A8?= =?UTF-8?q?=E9=87=8F=E9=97=B8=E6=B8=85=E5=8D=95=E2=80=94=E2=80=94=E6=94=B6?= =?UTF-8?q?=E5=8F=A3=E6=BC=8F=E5=88=A0=E6=97=A7=E6=9D=A1=E7=9B=AE=E5=9C=A8?= =?UTF-8?q?=E5=90=88=E5=9B=9E=E6=97=B6=E8=A2=AB=E6=8B=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - tools/audit_active_state.py:判四条可机械测的膨胀签名(状态记录条目数>30、 快照行数>10、条目编号重复含并行撞号、指向 design/qa|research 中间文档的死指针), 另加快照整行自我重复一项(换代不彻底只往顶部 prepend 的签名)。 - 变异验证:对换代前的 34 条版本报 5 项红(A1/A2/A3/A4/A5 全见红), 对退役后的 3 条版本报绿;两态实测 RC=1/0。 - 入 run_all_gates.sh 为 08b(脚本即清单,不另立第二份闸清单),baseline.json 随批补 08b 绿项(本分支内实测绿,非臆造)。 - 规约挂指针两处:doc-conventions §10 机械闸句、process-conventions 批次清单 12。 - active.md 按 §10 退役:状态记录 34→3 条,快照 21 行自我重复压回 10 行, 删「项目当前位置」整节(滞后且与 roadmap/快照重复),未决面按迭代 27/28 重列。 - 不动 Stop 钩子:回合末判收口时机错配(一轮答完≠任务完成),机械层交合回闸, 语义层交收口技能。 --- active.md | 115 +++++----------------------- design/dev/doc-conventions.md | 2 +- design/dev/process-conventions.md | 2 +- game/tests/.gates/baseline.json | 4 + tools/audit_active_state.py | 120 ++++++++++++++++++++++++++++++ tools/run_all_gates.sh | 2 + 6 files changed, 148 insertions(+), 97 deletions(-) create mode 100644 tools/audit_active_state.py diff --git a/active.md b/active.md index e38a7805..812a45fc 100644 --- a/active.md +++ b/active.md @@ -10,109 +10,34 @@ - **概念文档**:`design/gdd/00-游戏概念.md`(新骨架顶层文档;旧版 game-concept/game-pillars 已随归档封存) - **原型**:概念原型 demo 已删除(2026-09-12,垂直切片承接);验证结论 PROCEED 载于 git 历史,原报告路径已散佚;原型已演进为 `game/` 工程 - **引擎**:Godot 4.7.2 + GDScript(2026-09-07 锁定;`.claude/docs/technical-preferences.md` + `docs/engine-reference/godot/`;**MEDIUM RISK**——2026-09-12 `/setup-engine refresh` 逐条核实 4.5–4.7 官方迁移指南,无破坏架构契约项,current-best-practices.md 已建) -- **架构**:`design/dev/architecture/architecture.md`(同目录含 ADR 系列) v1.0(2026-09-12 /create-architecture 产出,TD 自评 APPROVED WITH CONDITIONS;review-mode.txt = solo) +- **架构**:`design/dev/architecture/architecture.md` v1.0(2026-09-12 /create-architecture 产出,TD 自评 APPROVED WITH CONDITIONS;review-mode.txt = solo) - **待办清单**:`design/gdd/06-待办清单.md`(2026-09-16 收编批起为全项目待拍板唯一登记处;系统文档只留指路存根,新增条目直接登记清单,裁决后改状态列留痕) - **批次出口报告**:随批落 `design/qa/`(证据只留最新一轮,doc-conventions §11) -- **工程路线图**:根目录 `roadmap.md`(2026-09-17 建——里程碑时间线 + 路线图;实时状态看下方快照节) - +- **工程路线图**:根目录 `roadmap.md`(里程碑时间线的权威;实时状态看下方快照节) ## 当前状态快照(收口批先更新本节,再追加状态记录;≤10 行) -- **更新于**:2026-10-14(迭代 27 代码架构技术债修复批总收口——单会话 /goal+iter U0 全量交付,合并 dd418e5)。 -- **批末闸全绿**:逐位一致对拍(V1 核心)三变体五跑全同(parity_anchor×40 局×RUNSUM+JSONL 双面,工具入库 tools/parity_anchor.py)+冒烟 1055→1081/0(+V2/V3/V4/V5/V6/V7 共 26 断言)+run_all 25→27 套+probe --click+render golden 0.00%+static_scan S1/S2/S4/S9 全绿(历史 cd 静默空转顺修)+doc 三闸/熵增对基线零新增。 -- **迭代 27 交付(五波)**:T1 三屏壳场景(menu/camp/adventure)+RunScope 会话物化+SaveManager/MetaProgression 升格 autoload;T2 _settle 五段 Segment+英雄攻击拆步(编排器 1725→1325 行);T3 RunLedger 单类持四账+刷新双账删副本+gp_final 键删影子账;T4 ModalFlow 模态编排纯逻辑类+互斥域 tags 化+双 context;T5 类型闸(audit_type_hints.py 368 参数化+13 真类型+warning 配置+S9 规则);T6 死代码 13+FeatsEngine 退役+Callable 换装+状态机 enum 化+ConfigDB 归根+resolver 解耦。 -- **迭代 27 待用户**:实机目检五件(07 ㉖,登记不阻塞)+代拍板追认单十五项(报告 §三)+GDD 反哺点两条(报告 §四/06 新条)。 -- **迭代 26 交付**:按钮五态矩阵(悬停 modulate 1.06 提亮/禁用 α0.45 幽灵化/焦点 INK 2px 内缩 1px 环/危险钮本族按压态,逐实例 override 主题层零新增);全局纹理过滤 Nearest+平滑渐变件三处 LINEAR 白名单;三处 <4.5:1 换墨(GOLD_BRIGHT/HERO_BLUE_BRIGHT/STONE_DEEP,6.47/5.88/5.98:1);光柱连续 alpha;图标槽柔和档+商店居中+营地四栏等高;诊断转储钮迁调试浮窗;冒烟 +68 断言;06 四条销号/氛围层改记+反哺点新条;08 v1.4;07 ㉕;roadmap 行换代;实现报告=design/qa/iter26-实现报告-2026-10-14.md。 -- **现行文档事实源**:秘宝.md v2.9+奇物.md v3.16+天赋树.md v0.10+锻造工坊.md v0.8+元进度.md v1.20+术语表 v1.10+08-Alpha版本标准 v1.4。 -- **各批残留人闸不变**:迭代 20 实机目检五件+V20/V21/V22 人工核对半;21~26 六批(07 ⑳~㉕)——用户 2026-10-14 回报目检完成已核销(qa 收尾批 5a188f3);**27 五件〔07 ㉖〕新登记**。 -- **已裁在册**:M4 数值批顺延迭代 28+ 未排期(各批 provisional 终值归其统一标定);迭代 27 位预留后续追加卡(同 24/26 先例)。 -- **界面美化三层已登记**(85e2d2a/08 v1.1):第一层三条全部交付(全局主题=迭代 25;按钮状态矩阵+全局纹理过滤=迭代 26);第三层四件已交付;余第二层三件(贴图/字体/样张)+第三层其余(九宫格切片/棋盘观感)待立项。 -- **更新于**:2026-10-14(迭代 26 UI 交互与观感批总收口——单会话 /goal+iter U0 全量交付,合并 c8c3db1)。 -- **批末闸全绿**:冒烟 1055/0(基线 987+本批 68 断言)+run_all 25 套+probe --click/--full+render_gate golden 0.00%(登记即结未重制)+doc 三闸/熵增对基线零新增;MC 零跑(零数值零行为=纯呈现)。 -- **迭代 26 交付**:按钮五态矩阵(悬停 modulate 1.06 提亮/禁用 α0.45 幽灵化/焦点 INK 2px 内缩 1px 环/危险钮本族按压态,逐实例 override 主题层零新增);全局纹理过滤 Nearest+平滑渐变件三处 LINEAR 白名单;三处 <4.5:1 换墨(GOLD_BRIGHT/HERO_BLUE_BRIGHT/STONE_DEEP,6.47/5.88/5.98:1);光柱连续 alpha;图标槽柔和档+商店居中+营地四栏等高;诊断转储钮迁调试浮窗;冒烟 +68 断言;06 四条销号/氛围层改记+反哺点新条;08 v1.4;07 ㉕;roadmap 行换代;实现报告=design/qa/iter26-实现报告-2026-10-14.md。 -- **迭代 26 待用户**:实机目检五项(07 ㉕,登记不阻塞)+代拍板追认单十三项(报告 §四)+GDD 反哺点四条(报告 §五/06 新条)。 -- **迭代 25 交付**:全局主题 `game/assets/theme/main_theme.tres` 挂 `gui/theme/custom`(15 类型全覆盖+预盖 CheckBox/CheckButton/OptionButton/PopupMenu 弹层+`default_font` 中文字形防御);`tooltip_theme()`/`styled_slider()` 两处局部做法同批退役(settings_overlay 几何内联+debug_overlay 双轨消隐);冒烟 V1-V6 断言 38 条;06「UI 全局主题资源缺失」条移除+「UI 元素细节修」①销号;08 v1.3;07 ㉔;roadmap 行换代;实现报告=design/qa/iter25-实现报告-2026-10-13.md。 -- **迭代 25 待用户**:实机目检全屏巡检+专项观察点二(07 ㉔,登记不阻塞)+代拍板追认单八项(位图不入 git 政策口径/CheckButton 词条名订正/Slider 无 pressed 槽等=报告 §四)+GDD 反哺点五条(报告 §五)。 -- **现行文档事实源**:秘宝.md v2.9+奇物.md v3.16+天赋树.md v0.10+锻造工坊.md v0.8+元进度.md v1.20+术语表 v1.10+**08-Alpha版本标准 v1.4**。 -- **各批残留人闸不变**:迭代 20 实机目检五件+V20/V21/V22 人工核对半;21 营地四柜台〔07 ⑳〕+22 秘宝解锁装配〔07 ㉑〕+23 锻造工作间〔07 ㉒〕+24 敌人表三观测〔07 ㉓〕+25 全屏巡检〔07 ㉔〕+**26 逐屏巡检〔07 ㉕〕**。 -- **已裁在册**:M4 数值批顺延迭代 27+ 未排期(各批 provisional 终值归其统一标定)。 -- **界面美化三层已登记**(85e2d2a/08 v1.1):第一层三条全部交付(全局主题=迭代 25;按钮状态矩阵+全局纹理过滤=迭代 26);第三层四件已交付(<4.5:1 换墨/光柱半/元素细节余项=迭代 26,氛围层九宫格半存续待素材核对);余第二层三件(贴图/字体/样张)+第三层其余(九宫格切片/棋盘观感)待立项。 - -## 项目当前位置(2026-10-12 刷新;实时细节以根目录 `roadmap.md` 与 06-待办清单 为准) -- **里程碑**:M3=Alpha 版本的完整实现(2026-10-09 立规:用户未明令宣布 M3 完成前停留 M3,迭代只排 M3 需求,M4 一律不排期) -- **迭代**:迭代 19 五卡已入库(2026-10-08);迭代 20 专长实装批已入库(2026-10-11 总收口);迭代 21 天赋树实装批已入库(2026-10-12);迭代 22 秘宝体系实现重构落地批已入库(2026-10-12);迭代 23 锻造工坊实装批已入库(2026-10-12);迭代 24 敌人表内容修批已入库(2026-10-13,单会话交付;迭代位预留追加卡);**迭代 25 UI 全局主题批已入库(2026-10-13,单会话交付)**;**迭代 26 UI 交互与观感批已入库(2026-10-14,单会话 /goal+iter U0 总收口,合并 c8c3db1;迭代位预留追加卡)**;M4=迭代 27+ 未排期 -- **近期主战场**:迭代 20/21/22/23/24/25/26 七批残留人闸(实机目检:专长五件 / 营地四柜台〔07 ⑳〕/ 秘宝解锁-装配〔07 ㉑〕/ 锻造工坊工作间〔07 ㉒〕/ 敌人表三观测〔07 ㉓〕/ UI 全屏巡检〔07 ㉔〕/ **UI 逐屏巡检〔07 ㉕〕**)——各批追认单与反哺点全部出清;**下一前沿=待用户发令(迭代 26 位仍预留追加卡;M4 数值批殿后顺延 27+)** +- **更新于**:2026-10-15(迭代 28 与规则文件审计批均已入库,本节随后由 active.md 退役清理批换代——见状态记录 498)。 +- **最新闸态**:迭代 28 批末冒烟 1125/0、run_all 27 套、probe --click 残留 0、render golden 棋盘×3+菜单 0.00%、doc 三闸与熵增对基线零新增、static_scan S9 归零(S10 存量 125 在文件头清偿批在册);MC 零跑。 +- **probe --full 有一件红**:`t17_defer_probe`「关卡画面未出现」,用户已裁为存量红、不阻合并(合并 5b958ff6);根因是探针未隔离带断点的真实存档,修复在未合入的 `gatefix-20261015` 分支。 +- **迭代 28 交付**:修好启动时菜单被冒险层盖住的装配顺序,层序收敛为唯一装配合同(散落的两处 `move_child` 删除);boot 链路、九阶段生命周期、启动态菜单 golden 三组验收补全;本批新立硬规则「验收函数无变异红记录不算验收成立」,三处规约落文。 +- **迭代 27 交付**:三屏壳场景与局态物化、结算五段拆分、RunLedger 单类持四账、模态编排类、类型闸、死代码退役,编排器由 1725 行降到 1325 行。 +- **规约体系现状**:规则文件按领域拆为 7 份、单文件上限 150 行,CLAUDE.md 只留元信息、命令、目录、规范导航与一行一条红线;动手前按规范导航表查对应细则。 +- **人闸在册两件**:迭代 27 全流程走查〔07 ㉖〕与迭代 28 启动态菜单〔07 ㉗〕,均登记不阻塞;迭代 19~26 的目检已于 2026-10-14 全部核销。 +- **簿记出清**:迭代 19~26 的代拍板追认单与 GDD 反哺点已全部裁决落文,对应 14 份迭代实现报告按「证据只留最新」删除(git 历史可考)。 +- **已裁在册**:M4 数值批顺延迭代 29+ 未排期,各批 provisional 终值归其统一标定;迭代 27/28 位预留追加卡。 +- **界面美化三层**:第一层三件全部交付;余第二层三件(贴图/字体/样张)与第三层其余(九宫格切片/棋盘观感)待立项。 ## 未决面(进行中/待人闸/待裁点指针;现行事实源登记处=`design/gdd/06-待办清单.md`) -- 待用户裁决:美术审计两项 P0(art-bible 死样张指涉+主角像素管线重产;06 在册);去毒残留词扫否(魔法道具约 30 处/罕见约 18 处,呈报在案);喂雷流 R5 甲重启条件回落文(一句话件);「通关 vs 通过第 N 关」全库口径统一 273 处(待裁是否补登记 06);迭代 20 实机目检五件+V20/V21/V22 人工核对半(07 在册) -- 待发令:M4 数值批(迭代 27+,未排期——锻造工坊 provisional 终值/钥石产出重标/削弱档终值/元进度定价余面归其统一执行);迭代 26 迭代位预留追加卡(同迭代 24 先例,待用户编入) -- 进行中:黑话清扫第二波(GDD 正文流程动词族约三千处,随时可派) +- 待用户裁决(06 在册):迭代 27 GDD 反哺两条;迭代 28 GDD 反哺三条;美术审计两项 P0(art-bible 死样张指涉、主角像素管线重产);去毒残留词是否清扫(「魔法道具」约 30 处、「罕见」约 18 处);喂雷流 R5 甲重启条件回落文;「通关」与「通过第 N 关」全库口径统一(约 273 处)。 +- 待用户追认:迭代 27 代拍板十五项、迭代 28 代拍板十三项(含四条白名单外),清单在两份现行实现报告的追认单节(`design/qa/iter27-实现报告-2026-10-14.md`、`design/qa/iter28-实现报告-2026-10-15.md`);req-card 技能的 WorkBuddy 与 ZCode 两份副本是否取齐待裁。 +- 待发令:M4 数值批(迭代 29+);迭代 27/28 预留追加卡;黑话清扫第二波(GDD 正文流程动词族约三千处);规则文件编写 skill(按 497 批工作流提炼)。 +- 在途分支未合入 master(读现状时勿当已入库):`gatefix-20261015`(验收闸唯一入口+t17 探针隔离修复+合回闸回执强制,领先 2 笔)、`doc-adr-fixes-20261014`(registry 改号与契约描述同步,领先 5 笔)、`art-standee-20261006`(artwork 独立仓 dry-run 报告,领先 5 笔)。 +- 在册观察(06 登记,非阻塞):迭代 27 卡片义务补登两项——长函数余量 17 个中的装配/校验函数、lambda 连接防回归。 ## 状态记录(滚动窗口:仅当前迭代;退役规则见 doc-conventions §10) -- **479(2026-10-12,迭代 23 锻造工坊实装批开工)**:/goal+iter 技能调用=U0 开工令(用户目标=总收口全绿:冒烟/单测/探针/读数对拍四闸全过+实现报告落档)。开工检查全过:卡片 v1.2 零阻塞待裁点(Q1=0 级起步+锻造第一级=首个 +1 已裁;Q2=provisional 沿锚表投值已裁);V1-V14 验收清单三要素齐(V9 静态 grep 人工核对+V13 用户目检=纪律类人工项,余自动闸)。自洽扫描两处 L2 记录继续(不触红线):①卡片 F8「meta 域 13 件」清单滞后——现行实态 15 键(迭代 22 T2 同批新增 vision_used 未及登卡),对 forge_routes 新域零影响;②06 条目①「forge_products 两行改造」系 v0.5 旧文——设计 v0.6/卡片 F1 已订正为「行族已退役、新建行族」,卡片优先,T7 机械面同步时订正 06 措辞。事实抽查全符(F1 三处退役登记在册/F3 FORGE_ROUTE_BONUS 与 hero_override 在役行号漂移至 :155/:157/F5 两轴在役/F8 v6+_default_data 15 键/F9 forge_workshop 钥匙节点+营地占位面板接缝在册/F7 敌方轴未开)。T0 实查结案:①基线复读=冒烟 898/0+run_all 22 套全绿+probe_gate --click 全绿残留 0(存量 fx_reveal 已随 iter21 修复,零存量红);②buy_forge/forge_products 断言已随 iter21 T5 全摘(余件皆注释/退役登记——smoke:4398「MetaTable 行族规模 3/3/2」断言需随 T1 新行族换代);③hero 两轴读取面全清单=运行时独一处 unit_container.gd:64(db.hero 两轴快照)+冒烟断言 smoke_all.gd:1901(_db.hero.attack_type)+battle_orchestrator.gd:1410(消费 hero_unit 快照非表直读)+README 文档面,测试层零直读;④meta.tres 现役三行族+boss_keystone/conversion/attune_refresh_upgrade,FORGE_ATTRS 常驻;⑤树钥匙+占位面板接缝在册(camp_overlay_view.gd:275-284 钥匙门);⑥设计 v0.6 两节(裁决结果清单+工作间内容清单)复核无冲突。注入链已探明:main.build_adventure_params(:501)→ adventure params → _runner.set_* 族(:934-945 模式)→ level_runner enc(:480-494)→ begin_battle(battle_orchestrator.gd:344/:396 spawn)。代拍板立项(白名单内):新表 meta_forge.tres(ForgeTable:默认两轴+六路线行族,落位选型=新表,访问器连续性沿 treasure_items 先例);路线 id=sword/spear/staff/light/heavy/ward(甲路线 id=甲型值本身);存档域 forge_routes={levels 六键+unlocked 直购清单+weapon/armor 选中}(初始持有+练满前一档=派生解锁、直购=入档)。定义面已入库(b9cca33,卡片单笔);主区残留脏件全属他批遗产零碰(.zcode/active.md/锻造工坊.md v0.6 续裁行/playnote 等)。worktree g-plan2-iter23-forge 开工,T1 起。 +- **496(2026-10-15,迭代 28 启动装配与生命周期验收补全批总收口)**:单会话交付七提交并合并 5b958ff6,冒烟 1086→1125/0(新增 42 条断言,退役 3 条把错误顺序写成期望值的裸下标断言)。四条结论:①启动装配顺序错误(菜单被冒险层盖住)已修,层序判定收进单一合同 `LAYER_CONTRACT`,散落的两处手工 `move_child` 删除;②boot 链路十断言与九阶段×五引用面生命周期矩阵入库;③渲染面补两件探针自检、墨色判据与启动态菜单 golden;④六次变异注入全部见红并精确还原,拦截能力已证。变异 3 顺带证明墨色占比判据自身不可靠——菜单被藏时底层棋盘仍给高反差像素,该强弱分层写进 code-conventions §3.6。批内类型闸自纠一笔(`main.gd:453` 缺元素类型,改 `Array[Variant]` 后 S9 归零)。存档面风险已核实:全部 worktree 共享同一份 `user://save.json`,定位过程中临时移开的真实档已逐字节校验还原。 -- **478(2026-10-12,迭代 22 秘宝体系实现重构落地批总收口)**:T1-T7 八提交全量交付(worktree g-plan2-iter22-treasure;T1 12 行换代+schema 扩签/T2 解锁服务+工坊面退役+档位格约束/T3 效果引擎接入+扩签+常时参数面+试炼镐积点口+充能周期+修 use_treasure Rules.width 潜伏缺陷+新单测 treasure_effects_test/T4 呈现换代+呈现桥+HUD 兑换钮+修 BoardZoneView 缺转发挂死/T5 替换子交互拆除+库存保留注记+修 apply_node_curio 主体误删/T6 验收闸四断言+重闸/T7 文档四件+实现报告)。自洽扫描四处事实换代(卡片 F1/F2/F4 被迭代 20/21 推进)施工按现行实态。批末重闸全绿=冒烟 898/0+run_all 22 套+probe 含 click/full+render_gate golden 0.00%+doc 三闸对基线零新增+熵增 PASS;MC 零跑(零随机无概率面)。master 并行两笔(锻造 docs 6f56164)已并入分支解 roadmap 冲突(融合=我方 22 ✅ 行+23 锻造行+24+ M4 顺延行)。代拍板追认单十五条+GDD 反哺点七条待用户(design/qa/iter22-实现报告-2026-10-12.md);残留人闸=实机目检秘宝解锁-装配正常流程(07 ㉑)。 +- **497(2026-10-15,规则文件审计与目录划分批收口)**:对照 Anthropic 与 OpenAI 七个真实仓库 40~330 行的实测密度重整规约——规则文件由 3 份 560 行拆为 7 份 543 行,单文件 150 行硬上限,CLAUDE.md 压到 68 行只留元信息、命令、目录划分、规范导航和一行一条红线;细则按领域归位到 process/test/doc/code/concept 五份规约,反面案例另存案例库不常驻加载。迭代 28 并行落文的变异验证硬规则按新结构重归位(细则在 test-conventions §6)。合并 81c0ee2b,worktree 与分支已清理。 -- **477(2026-10-12,迭代 22 秘宝体系实现重构落地批开工)**:/goal+iter 技能调用=U0 开工令。开工检查全过:卡片 v1.3(C1-C6 全裁)零阻塞待裁点——三条回补待裁点按卡片自declared不阻塞口径处理:回补点 1 按推荐案执行(12 件全量落地、刷新练习归钥石购买=C1 普通档裁决直接应用)、回补点 2 已消解(迭代 20 已删 venom_edge/flag_burst,现行表 12 行旧件本批实删 12 行)、回补点 3 按「旧实现一律删除」既定纪律选拆除路线(treasure_inventory 拆除,追认单列明);V1-V19 验收清单三要素齐。自洽扫描四处事实换代(均系迭代 20/21 前置批推进、方向对本批有利):①现行表 12 行非 14 行;②attunement_growth.tres 谓词表已被迭代 21 删除、槽位判定源已切树点亮数(attunement.gd 现役 slots()=att_socket1..3)——卡片「谓词表槽位求值职责移除」已被迭代 21 完成、树接口接缝现成;③forge_products 行族已删;④V13 引用 smoke/tests 行号全漂移按内容定位。基线复读=冒烟 886/0+run_all 22 套+probe_gate --click 全绿(残留 0)。T0 四项核实结案:①X/Y 对表=临时账 X(_attune_refresh_x 每停点重置、装配集 bonus_refresh 行源——新 12 件无此行源恒 0 机制保留)+存量账 Y(_attune_refresh_y 升级行)+_refresh_stock(刷新练习件新加仓目标);扣序 X→Y→stock=先临时后存量与秘宝.md 一致;②magic_vs_magic 行已被迭代 20 删除(grep 零命中)——锻造工坊批③作废结案维持;③效果引擎扩签清单=订阅行现役词可承载(晨操令/双管装填=round_start+grant_ap+round_index 条件;试炼镐=dig_reveal 计数+use_treasure 受理闸与掘进蓄能同构现役);扩签三处=巢穴预告装板事件、天眼安全格开格 kind、真视使用计数键(UNLOCK_COUNTER_KEYS 扩签+存档生涯域新键);常时参数面五点已定位(_adjacent_to_hero 挖/旗两分支=远程镐/信标网络、finish_round_stop 1:1 转存=储备罐、shop_refresh_free_left=刷新执照、set_fog_lantern 半径面=阔视野带、_refresh_stock=刷新练习)——注入模式沿 fog_lantern 呈现桥与 attune_has 契约化先例;④真视使用计数接入点=use_treasure 受理成功处(battle_orchestrator:865-883);旧件硬编码一处在册(battle_orchestrator:882 dig_charge 随行换代)。定义面已入库(roadmap/06/卡片 v1.3 均在库零脏件);主区残留脏件全属他批遗产零碰。worktree g-plan2-iter22-treasure 开工,T1 起。 - -- **469(2026-10-12,迭代 21 天赋树实装批开工)**:/goal+iter 技能调用=U0 开工令。开工检查全过:卡片 v1.7(73acee0 已入库)零阻塞待裁点——R1 按卡片既定默认=裁撤案执行(schema 只保留点亮前置),出口报告追认单列明;验收清单 V1-V23 三要素齐;自洽扫描 8 处事实抽查全符(33 行表/schema 词表/tree_buy 族/slots 谓词求值/存档 v6/_roll_gp_drop 挂点/:1116-1131 标错分支/结算=每轮末时序)。T0 四查结案:②聚乘算位=_roll_gp_drop() 返回表达式内(battle_orchestrator.gd:1461);③锋=mine_hit 现成挂点零改、守=_flag_miss_seen 去重闸后(:1119-1121)grant_ap mode:queue 下轮 notify_round_start 兑现,末轮判出无下一轮=契约 12 作废态自动成立;④锻造工坊 v0.5 两节读取完成——本批预留 0 锻造加值位与「4a 前缓后陡/6 满级特效留扩展位」零冲突、钥匙 free 无前置一致;⑤基线复读=冒烟 864/0 但 run_smoke 判 FAIL(SCRIPT ERROR 51 行:_flush_pending_reveals 三处 _emit_row("fx_reveal","",...) 空 source_class 触发 :1592 行来源断言——a57489e9 迭代20 T1 落地件存量红,两轮确定性复现,本批内顺手修复+实现报告单列)+run_all 21 套全绿+probe_gate --click 全绿残留 0。定义面已入库(并行会话 73acee0 含 roadmap/06/卡片 v1.7)。主区残留脏件全属他批遗产零碰(.zcode hook 三件/锻造工坊.md v0.5 未提交/playnote/四 untracked)。worktree g-plan2-iter21-tree 开工,T1 起。 -- **470(2026-10-12,filter-repo 计划书裁决——明示放弃销号批)**:用户裁「.git 60MB 可接受,没必要清理」→ 三选裁**明示放弃**。06 条目移除(去向=本条,git 史留痕);active.md 未决面摘除该裁决项。计划书 `.zcode/plans/filter-repo-history-cleanup-plan-2026-10-02.md` 系 .zcode 未跟踪件、随裁作废但磁盘留存不删(永久删除不可逆;真要重启历史清理须重立计划)。零代码零他件触碰(worktree frdrop-20261012)。 - -- **471(2026-10-12,8a 连带 C/D 改名裁决 + 独立改名小批登记)**:用户最终命名——**C =「属性 + 祝福」**(局内商店货架三行 攻击锻升/生命锻升/护甲锻升 → **攻击祝福/生命祝福/护甲祝福**;后缀由用户自 D&D 调研候选选定〔Blessing〕,并裁定"参考书目有该词不构成禁用";调研要点:D&D 超自然赠礼分 Blessing 祝福〔永久·神赐〕/ Charm 护咒〔有时限·用完消失〕,按语义后者更贴局内临时层,用户仍取祝福);**D = 棋盘格 defense 正向行 + `ac_up` 状态的同名「护甲强化」→「盾牌加护」**(用户提案,理由=它是临时叠层状态、不是护甲本体;附带约定「加护=AC 判定层,护盾=保险丝那种吸收层,两者不得混用」)。机制分类名「属性值提升」保留不动,只换玩家向显示名。**执行面已核到行号**:C=`shop.tres` 六行(pool_shelf 现役 70/74/78 + products 遗留 38/45/52)——全库"锻升"命中恰此六行、`display_name` 非查找键(货架以 kind_id 为键,`config_db.gd:328`)、`smoke_all.gd:4415` 为"标签文本==表值"自洽式断言 ⇒ **C 零代码零测试连带**;**D 必须连带改 `smoke_all.gd:1199` 一条硬编码 `== "护甲强化"` 断言,否则冒烟红**(修正上一轮"C/D 皆零连带"的判断)。**按本会话"禁动 game/ 代码与数据表"纪律未代执行**——06 新增「玩家向显示名改名小批」条目,内附逐行替换表 + 近义词占用登记(石肤已被奇物占用)。落文:锻造工坊.md(边界节 + v0.5 版本行⑥)、06 新条目;启动=用户发令或并入锻造工坊实装批。附:本会话早先写入的 468/469 两条已被并行会话的"状态记录清理批"清档(完结条目清理,符合 §10),本条为补登。 - -- **472(2026-10-12,奇物呈现条过期检查批——档位三路消解+僵尸呈现定性,条目换代不删除)**:用户令检查 2026-10-04「奇物呈现三处违规+档位三路」条是否过期。取证结论三条:①**档位三路裁点被事件超越**——丙(机制退役)经重设计路线实现(奇物.md v2.9+追认单术语澄清「流派标签作玩法机制作废」+迭代 20 `battle_orchestrator.gd:330` rider_tier 注入拆除),甲/乙不再待裁;②**三处违规未消解且恶化=僵尸呈现**——迭代 20 零触碰四个呈现文件(git 末次 10-05~07),新 29 行无 archetype 字段 ⇒ C 区/关卡页实显「流派 ×N · 档一」兜底行(`hud_presenter.gd:111`+`feats_engine.gd:13`)、卡面「件名 · 流派」(`battle_narrator.gd:146-149`),违反 10-12 重申对外永不显示铁律+展示已退役机制;③条目换代不删除(迭代 20 反哺点⑤明文指向本条,删则指针悬空),剩余裁决面=呈现改法与反哺点⑤同面。连带发现(本批只记录不处置):迭代 20 实现报告 §四.5/§五.5「逐件行降级态在役」与代码实态不符,失真处置待用户裁。**编号注记:471 已被并行锻造会话(主区脏件)占用,本条顺延 472。**06 条状态换代(worktree curiopres-20261012)。 - -- **472(2026-10-12,C/D 改名小批——C 已执行,D 阻塞)**:用户授权边界澄清=**可改配置(.tres)、禁改代码(.gd)**。据此执行 **C**:`shop.tres` 六行 display_name 全量替换——pool_shelf 现役 70/74/78 + products 遗留 38/45/52,攻击锻升/生命锻升/护甲锻升 → **攻击祝福/生命祝福/护甲祝福**;校验=全库"锻升"命中归零、行数与括号结构零变化、**零代码零测试连带**(display_name 非查找键,`smoke_all.gd:4415` 为自洽式断言)。**D 未执行**:`reward.tres:22` 与 `status_effects.tres:18` 属配置可改,但 `reward.tres` 改名会立刻使 `smoke_all.gd:1199` 硬编码断言(`== "护甲强化"`)**判红**,而该文件是代码、未经授权;只改 status 一侧会造成格子/状态两处不同名,不采纳 → D 整项挂起,待可改 .gd 的批次同批执行(06 在册,附逐行替换表)。落文:06 改名小批条更新(C 标已执行、D 标阻塞原因)、锻造工坊.md 边界节。→ **接续指针:用户追加授权("可以简单地修改……一并改完")后 D 已于同日解阻执行并合入 master,残留肃清同批完成,详见 474;本条「D 阻塞」状态已时过境迁。另:本条与上方奇物呈现批重号 472(并行会话撞号),474 为续篇。** - -- **473(2026-10-12,迭代 20 报告失真勘误批——「逐件行降级态」失真五处换代)**:用户裁先修报告失真(与僵尸呈现分案——前者文档缺陷、后者代码缺陷,互不替代)。失真源=迭代 20 实现报告 §四.5「流派聚合行退役→逐件行降级态在役」与代码不符(逐件行未实装,472 已取证),扩散四处:报告 §五.5 目检项、07-体验验证清单 HUD 条、06 反哺点条⑤、game/README.md 换代面段。五处全部勘误换代(带日期勘误标记;目检项 5 改验僵尸呈现实况=修复批前对照取证,人闸「五件」计数不变);零代码零他件触碰,僵尸呈现修复仍待呈现改法裁决(06 奇物呈现条)。(worktree repfix-20261012) - -- **474(2026-10-12,C/D 改名小批执行+合入+残留肃清——worktree 两连批)**:用户追加授权("可以简单地修改(smoke_all.gd 那一行断言),一并改完吧。但是注意我们的合入规则")后,C/D 同批走 worktree 执行。**主批**(分支 rename-blessing-20261012,基于 master 18b6cbd):`shop.tres` 六行 display_name 锻升→祝福(pool_shelf 现役 70/74/78 + products 遗留 38/45/52);`reward.tres:22` / `status_effects.tres:18` 护甲强化→盾牌加护;`smoke_all.gd:1199` 硬编码断言同步(不改则冒烟红)。冒烟 864 项检查 0 项失败(FAIL 仅存量 fx_reveal SCRIPT ERROR——a57489e9 遗留、iter21 在册,与本批无关;已核 `_smoke_ac_swap_guard()` 调用先于 `_smoke_save()`,存量错误不吞本批断言)。`--no-ff` 合入 master `0c93a71`(ort 零冲突;主区脏件全为文档侧,与分支 game/ 四文件零重叠)。**残留肃清批**(分支 blessing-residue-sweep-20261012,基于合入后 master):合入后全库复扫发现主改名未覆盖注记段 4 处——`reward.tres:219` / `status_effects.tres:99` 历史注记、`defense_scan.gd:24/:35` 打印标题与注释,更新为现名「盾牌加护」并括注"2026-10-12 由'护甲强化'改名"(历史动作部分保留);冒烟 864/0 → 合入 `0144f60`。**game/ 全库现役旧名归零**(仅存两处为有意留痕括注)。worktree 与三分支已清理(`git worktree remove --force` + `branch -d/-D`)。**文档跟随**:地图战斗资源.md v0.23 版本行(九型字典表+设计意图句)、art-bible.md §4.6.1/§4.6.2 键名列(契约句"随其修订自动跟随")、07 体验验证清单⑫目检行。**06 条目收口**:改名小批状态「已完成」,registry entities.yaml 登记「祝福」条目/旧名退役**未执行**——归锻造工坊实装批术语登记面(迁移面八项⑦同域)。**编号注记:473 已被并行会话(迭代 20 报告失真勘误批)占用,本条顺延 474;472 撞号(并行会话同写)已在彼条加接续指针。** - -- **475(2026-10-12,奇物呈现修复批——僵尸呈现整改落地,呈现改法=甲逐件行)**:用户令「解决呈现问题」,按呈报推荐案甲落地(改乙/丙一句话另调)。代码两文件:`hud_presenter.gd` feat_holdings_lines 聚合行(新 29 行无 archetype 下空键兜底「流派 ×N · 档一」僵尸文案)→ 逐件行「件名 ×N」;`battle_narrator.gd` feat_card_text 摘「件名 · 流派」族名行(卡片=件名+效果摘要两行,兑付反馈行随之「件名 · 摘要」)+payload 死键 archetype 摘除;注释面五处换代(hud_presenter/hero_info_panel_view/level_map_screen)。断言面预查:smoke:982 只钉 desc 零族名断言,免改。文档同步:battle.md C 区两行(归 06 指针摘除改已整改事实)/07 HUD 条(验修复后逐件行)/报告 §五.5(同)/README 段(473 勘误句再换代为已修复)/06 奇物呈现条**收口移除**(三处违规+档位三路+呈现改法三面全清,去向=本条+git)/反哺点⑤✅销账(①-⑤全出清;反哺点条与追认单条随下次收口清理批一并移除)。FeatsEngine.tiers_for 呈现侧调用摘除后全仓零调用方(引擎库保留不动)。(worktree presentfix-20261012;**编号注记:474 已被并行改名批占用,本条顺延 475**) - -- **481(2026-10-12,迭代 23 锻造工坊实装批总收口〔编号顺延——480 已被并行 06 清理批占用,主区未提交遗产撞号注记〕)**:T0-T7 八提交全量交付(worktree g-plan2-iter23-forge;T1 行族 df666dd/T2 两轴移交 00d98b6/T5 存档 v7 6def354〔序调先行——写口硬依赖〕/T3 写口族 a6270ba/T4 注入链 ed06292/T6 工作间 UI 2915f19/T7 收口笔)。T1 新表 forge.tres(ForgeTable 默认两轴+六路线行族,ConfigDB forge_* 六访问器)+单测 41 断言;T2 hero.tres 两字段删除+spawn 注入缝(空串=锻造配置默认值回退,行为逐位连续);T5 SAVE_FORMAT_VERSION 6→7+forge_routes 域{levels/unlocked/weapon/armor}(无特效域)+v6→v7 空迁移缺键补齐=初始持有态;T3 写口族(forge_buy_level 几何价 20/30/45/67/101/forge_buy_unlock 一次性 200/forge_select_* 免费/forge_route_unlocked 派生单点);T4 hero_override 公式换代(FORGE_ROUTE_BONUS 退役)+build_adventure_params 两键+参数面快照锁死+effective_ac 三层(甲型基础 AC+路线加值+局内)+enc→spawn 末端;T6 占位面板→两区六路线行板+三意图信号+presenter 处理器+新单测 12 断言。验证:冒烟 938/0(基线 898+40 锻造断言)+run_all 24 套+probe --click/--full 全绿残留 0+render_gate golden 0.00%+doc 三闸/熵增对基线零新增(3 个 gdd_lint 存量红同款;master 第 10 个扫描文件=并行会话未跟踪件 08-Alpha版本标准.md,禁碰);**MC 同种子配对 80 局逐位零漂移**(na=40 seed0=9000 双画像:normal 0/40↔0/40、perfect 28/40↔28/40)+方向性补充(锻造满配档 atk+5/ac+5 同种子 30/80 局结局差:perfect 28→33/40)——默认态行为连续铁证+注入面生效证据。机械面文档七件同步(roadmap/entities.yaml 回填实态/06 状态+①② v0.6 措辞订正/存档序列化 v1.7/07 ㉒+game/README 批次段);实现报告=design/qa/iter23-实现报告-2026-10-12.md(代拍板追认单九条+GDD 反哺点三条待用户);残留人闸=实机目检工作间形态与购买交互(07 ㉒)。环境注记:render_gate 需 gamedev venv(PIL)。 - - -- **476(2026-10-12,迭代 21 天赋树实装批总收口〔编号顺延——470-475 系并行批次占用,471/472 并行撞号已在彼条注记〕)**:T1-T7 全量交付(worktree g-plan2-iter21-tree 基于开工批 43f7230;master 并行十八笔已并入分支解 active 冲突后回合)。T1 schema 换代(FORK_GROUPS 4→3/RULE_KEYS 2→6/fork 单行双态 effects_a·b/row 退役门槛换轴/R1 裁撤案执行)+33→12 行重排(easter 摘攻防=契约 9);T2 购买面(easter 拒购/Fork 解锁默认 A/零币切态/彩蛋特化判定);T3 六键接线(EVENTS+flag_missed/FACTS+battle_index=L2 扩签两处/posture 每关首轮窗/sense 限次 counter 闸 domain:adventure 按关重置/守侧去重闸后发射=契约12/聚入账前×1.5/散双计价点×80%——数值全 provisional 归 M4);T4 注入换代(树淬炼 flat+锻造加值位预留 0/槽位判定源切树点亮数/ks_refresh 同账路由);T5 删除批(migrate_tree/buy_forge 家族/forge_products 行族/forge_levels 域/attunement_growth 谓词表/生涯三投影全删;tree_struct=2 标记废弃重置禁迁移);T6 四柜台并排(树=主界面/两钥匙门+零交互占位面板/图鉴常开/暂停层锻造段连带删)。存量红修复=fx_reveal 三处空 source_class(a57489e9 落地件,基线 51 行脚本错误清零——474 条 FAIL 注记随之销账)。验证:冒烟 886/0(V1-V10/V16 断言随批)+run_all 22 套(新增 V11 六键闭集单测)+probe --click --full 八探针全绿+render_gate golden 0.00%+doc 三闸/熵增闸对基线零新增(worktree 缺 ignored 素材两坑照 463 先例拷 artwork+game/assets/art 后绿)+V19 MC 三组同种子配对×60 局 perfect+max 档全部 61.7%、配对差 0.0pp 在带(normal 档基率地板读数换档记验证记录);守侧五场景=编排 rig 直注+引擎直构双承载。追认单十二条+反哺点六条+欠账三条落实现报告 design/qa/iter21-实现报告-2026-10-12.md 待用户;残留人闸=实机目检四柜台(V22)。 - -- **477(2026-10-12,迭代 22 秘宝批裁决与落文会话——A 单十五条收口+B 单七条反哺落文+⑤改自动兑付)**:裁决会话逐点呈报、用户逐条裁。**A 单**(实现报告 §二):①②③⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮ 追认;④ 追认+积点账生命周期裁**战斗级**(设计留白补记秘宝.md 代价轴);⑤ **推翻·改自动兑付**(用户裁:满 8 安全格自动当轮 AP+1 无玩家入口;进度显示落位=C 区秘宝槽悬停浮窗〔用户点名〕);⑮ 附报告提交号勘正(master 实际 T5=73db171,原记 7095505 系 amend 前被弃旧提交——merge-base 取证)。卡片 §11 三条回补待裁点随①②③收口。**⑤代码批**(worktree iter22-ruling 基点 79aac07,合入 8455b4a):兑付迁移 `_on_cell_revealed` 揭示缓冲点(cell_revealed 批先于本格扣费→AP 归零恰逢满点先兑再扣、轮不结束——用户时序规格);兑换钮整链退役(ap_bar/board_zone/main);use_attune_convert 消解+attune_convert_state 改进度读数口;use_treasure 积点死分支与 _usable_now 死条件删;tres desc 换代+受理闸删;单测④段重写;07㉑ 观测点换代。**B 单七条全落文**(用户逐点裁「落文」):秘宝.md v3.0(目录三表实态列/试炼镐自动兑付/代价轴战斗级重置+兑付时序/解锁条件实录/落地前句全换代)/元进度.md v1.17/camp.md v1.3(柜台呈现细则+暂停层 12 行)/存档序列化.md v1.6(vision_used 域+断点随件+bonus_aux_carry 退役)/行动经济.md v0.12(转存率参数化)/术语表 v1.2(自动兑付+真视使用计数两词条)。报告修正(提交号+十五条裁决标注+反哺已落文标注)+06 迭代 22 条收口(裁决小节落 06)。验证:冒烟 898/0+单测 22 套+probe_gate --click/--full 全绿(worktree 拷 .godot/字体与图标边车/assets/art 三坑照 463/476 先例)+合并后 master 冒烟 898/0 兜底;worktree 与分支已清理。残留人闸=07㉑ 实机目检(观测点已换代)。裁决依据文件=.zcode/plans/裁决记录-迭代22秘宝批追认与修改清单-2026-10-12.md。 - -- **478(2026-10-12,迭代 22 反哺⑤呈现集成补丁——用户令「忽略真人目检,查还有无需要修复」的主动排查产出)**:排查抓出追认批一个真缺陷+漏闸三件。**缺陷**:charges=0 件被 `_reseed_attune_charges` 注入循环跳过〔不入骑库存〕而 C 区槽投影遍历骑库存→试炼镐 C 区不可见、悬停浮窗进度无处承载(单测只测读数口未覆盖投影链、探针无此断言=两闸双盲区)。修复=C 区投影末段追加自动兑付件展示行(合成 handle=-1 非库存句柄+note 积点 N/8+槽点击走说明 toast 不进两步交互;四槽容量实证够用=装配≤3+展示行 1);孤儿函数头注释清一;单测新增④b 两条(装配即入投影/开格后进度刷新)+StubAutoInvRunner 桩。**漏闸补跑**:render_gate(golden 3 屏 0.00% 全绿——golden 锚棋盘区域与 HUD 无涉)+doc 三闸(死链 3/拔旗 1/gdd_lint 三文件表格占比 FAIL 全部实证存量——79aac07 版本逐文件表格行对比零变化)+熵增闸 PASS。(worktree iter22-fix 基点 8455b4a;过程事故一笔=cff741e 首提交误入 .lintbase 临时对比目录,amend 剔除后干净;合入 0ef73d0,worktree 与分支已清理)。闸读数:冒烟 898/0+单测 22 套+probe --full+render_gate+doc 三闸+熵增闸全绿。 - -- **480(2026-10-13,06 待办清单清理批——A类六条+B类四条销号+天赋树欠账三条拆专条)**:用户令「A类已完成即清除+B类逐条核实是否还需开发」。A类六条移除(全部实证已了结):迭代22追认单十五条+反哺七条(8455b4a/0ef73d0 已入库)/迭代20反哺五条(①-⑤全出清)/迭代20追认十条(落文奇物v3.16)/生命比例扩签(hp_ratio 已销号原条未删,本次物理移除)/active.md定性大裁(已入库)/秘宝体系实现重构落地批(迭代22入库,人闸目检07㉑按「登记不阻塞」规归07)。B类四条核实完成移除:X/Y语义倒置(消耗序X临时→Y→stock存量=先临时后存量,adventure_runner.gd:680-689 注释在案+iter22 T0「X/Y对表」结案)/魔法提灯(拆线随iter22 T1入库;board_view._fog_lantern 残留名已换代为阔视野带通用视野加成非提灯遗留)/冒险BD渠道分工(Boss直接给专长随iter20落地+heal/feat_ticket 行在 shop.tres 货架六行+档位阈值复裁与charge标签缺陷随流派标签集件档位 v2.9 框架级作废失效〔奇物.md v3.8①⑥〕)/资源两新种类(刷新练习/刷新券在秘宝12件表+凭证在货架,边界经三账实现落定)。B5天赋树批条销号(iter21 入库)但欠账三条代码复核全部仍在→拆专条「天赋树实装批登记欠账三条」:①AP上限clamp缺位(action_economy.gd:254 仅 maxi(0,..) 下限实证);②三选一刷新软上限(原「另立待办」从未成条,本批首次落位成条);③Y不入断点存档=可利用漏洞仍在(断点存 refresh_stock :236 不存 Y 余量、续玩 :225 自参数面整额重注入=用完退菜单再续玩满血复活)。①③待缺陷修批、②待调参批,均未排批。执行=worktree todocleanup-20261013(主区直改被守卫拦截;主区脏件 cp 随批保史=并行 playnote 五条 +70 行)→ 6406d16 → --no-ff 合回 master;doc 三闸对基线零新增(死链3/拔旗1/gdd_lint 3件FAIL均存量);零游戏文件零数值。 - -- **481(2026-10-13,天赋树欠账三条裁决落文+③Y断点存档缺陷修批——C类14条用户令暂不做任何动作)**:两连批。**落裁批**(770fa56→663c0bf):用户逐件裁——①AP clamp 暂不设上限(provisional 天花板亦不投)随 M4 数值批;②刷新软上限维持现状归 M4;③Y 断点存档须修(06 专条状态行换代记账条)。**修批**(用户令「C类先不做,把还没修的 bug 修了,按正常流程走」提前单独开修;worktree ybpfix-20261013 基于含并行 iter23 的最新 master,缓存三件套照 463/476 先例拷 .godot+import边车+assets/art):adventure_runner 两处=断点字典扩列 "attune_refresh_y"+resume_adventure 优先读断点(缺键回退参数面=旧档零变化,堵「用完 Y 退菜单再续玩满血复活」可利用漏洞);curio_refresh_paid_test 新增⑥段两断言(余量随断点还原/旧档回退);文档三件随批=存档序列化.md v1.8(断点随件扩列 v7 域后不升版,v1.6 先例同款)/冒险结构.md v0.21(附随件清单扩 Y 随件——注:清单内 iter20/22 的 refresh_stock/battery_pending/feat_ticket_pity/adventure_counters/vision_counter_used 五键历史缺登,本批不做加法只登本件,缺口在案)/06 专条③销号转记账条。闸=基线冒烟 938/0+单测 24 套全绿→改后同绿(含新⑥段)+doc 三闸对基线零新增(worktree 扫描集曾缺未跟踪五文档致读数漂移,cp 补齐后对齐=死链3/lint 3件FAIL均存量);8e04807→--no-ff 合回 master e0d931d,合并后主区冒烟复跑 938/0。worktree 与分支已清理。 - -- **482(2026-10-13,迭代 23 收尾批——追认单九项全追认+GDD 反哺三条落文+祝福 registry 漏项补登)**:用户令「追认清单目前看都没有问题;文档反哺点需要你在这里进行更新」。**追认**:报告 §四九项全数追认通过(报告头部标注收口)。**反哺三条落文**(报告 §五标注去向):锻造工坊.md **v0.7**=①Q1「0 级=未练合法态」正文两处衔接(三件武器节+工作间内容清单·4)②效果类型闭集 24→**31** 两处订正(满级特效扩展位节+现役代码事实表,原记系 2026-10-07 旧快照=迭代20 T1 +7、迭代22 T3 +1,冒烟断言钉 31)③实装边界 1 实态回填(forge.tres/路线 id 六个/字段闭集 12/ConfigDB.forge_* 访问器);元进度.md **v1.18**=①「跨局注入」节补 effective_ac 第一层终态句(甲型基础 AC=选中甲路线行 base_ac:轻10/重12/魔法护甲9 provisional)②属性锻造段落代(「待用户发令」过期态→已随迭代 23 入库)+登记钥石入口族三写口(forge_buy_level/forge_buy_unlock/forge_select_*,buy_forge 退役后新族);术语表.md **v1.9**=锻造工坊节新增「路线 id/存档域键名」词条(sword/spear/staff/light/heavy/ward+forge_routes 四键,实现层词汇非玩家可见——报告 §五③「若需登记补登待裁」经本令解为登记)。**漏项补登(核对时抓出,06 改名小批条配套文档面②③「归锻造实装批一并做」但迭代 23 T7 未做)**:entities.yaml terminology 补「攻击祝福/生命祝福/护甲祝福」词条(旧名「X锻升」退役留检索别名)+「石肤(近义词占用)」备忘词条。**06 两处换代**:锻造实装批条状态行补收尾段(追认+反哺落文,本条义务全清);改名小批条配套文档面②③标已执行。**active.md 同批**:删除并行合并产生的重复 479 开工条(同号双版本 union 遗留,保留 forge.tres 命名版)+快照/当前位置换代。主区脏件保史随批=锻造工坊.md v0.6 续裁行⑤⑥(Q1/Q2 落文,4b 批遗产)。零代码零数值零游戏文件。(worktree rulingfeed-20261013) - -- **483(2026-10-13,术语表「道具」统称登记微批)**:用户立内部用语习惯落文=**道具=秘宝/奇物/地图战斗资源三类的内部开发统称**(单独说「道具」即指三类全体或其中任一,靠上下文分辨;组合用法=秘宝道具/奇物道具/专长道具/战斗资源道具),仅限开发内部交流、玩家可见面用各类正式名称;同批补登「地图战斗资源」词条(原「奖励道具经济」2026-09-16 更名后一直未入表)。术语表升 **v1.10**,快照事实源行随换代;UI 美化批快照残留行(85e2d2a 批留盘)随本批 sweep 入库。零代码零数值零游戏文件。(worktree term-item-20261013) - -- **484(2026-10-13,状态面板改名批+迭代 21 GDD 反哺六条落文两连批)**:用户令「①状态 ②全套;反哺六条按呈报落文;两任务一起做完汇报」。**批一改名**(c5a09fd,用户令「暂停层/暂停角标→状态面板/状态角标」——用户 prompt 全量任务书):文案 4 处(浮层标题/两屏角标/关闭钮 tooltip 按用户句式;副提示原文无暂停字眼零动)+标识符全套(PauseOverlay→StatusPanel/pause_overlay.gd→status_panel.gd/成员方法族 _open_status_panel 等+探针快照键 status_title/_snap("status"))+game/ 内注释与探针消息 86 处清零(参照语括注来历放文档面,代码 rg 归零);行为契约四件零动(只读 R4/模态遮罩 P2 甲/输入锁 R3/零动效 P4 甲)。**连带抓漏**:tools/render_gate.sh 截图键 shot_pause→shot_status(首跑 render_gate 红一根因=此,同步后绿);.godot 类缓存含旧类名(worktree cp 缓存 Parse Error——sed 缓存修,主区合并后同法刷新)。**文档六面**:元进度 v1.19(解锁界面节+改名括注)/07/生涯/06 条(状态面板条目换代+改名批机检注)/architecture json+html(暂停浮层→状态面板);camp.md 零命中;**08-Alpha版本标准.md untracked 禁碰留置**(内含暂停字样归该批)。html 残留「暂停」皆 archify 查看器自身播放控制文案非游戏面,保留。**批二反哺六条**(c767174,用户裁「按你的来回写」):天赋树.md **v0.9**(①实装落地态七处换代〔状态行/范围表/总表前言与三行/schema 连带/依赖表/P0 段/验收实态注——「实装未落、现役 33 节点」过渡态终结〕③设计避让句按卡片 v1.7 ⑪②裁决改写为折扣定义边界(散=只覆盖商品购买价,键 gp_cost_mult)⑥机检读数+命中线契约 6 括注+已建未接面节换代〔两接一维持:槽位判定源已切树点亮数/刷新同账路由/命中线纪律维持〕);元进度.md **v1.20**(②营地统一段落地终态);锻造工坊.md **v0.8**(④树侧钥匙句 forge_workshop 在役、死指针终结);HUD框架.md **v0.17**(⑤新增营地四柜台并排小节=登记缺口补齐)。**闸**:批一四件=冒烟 938/0+run_all 24 套+probe --click/--full+render_gate 全绿(golden 0.00%);批二 doc 三闸对基线零新增(死链 3 逐条存量/term 5 组一致/lint 3 存量同款;worktree 缺 untracked 五文档致首跑漂移 9 链,主区绝对路径 cp 后对齐)+熵增 PASS;合并后主区冒烟兜底 938/0。合并=7d1e9cb(基点含并行术语表 v1.10 微批 187632f,ort 零冲突)。worktree 与分支已清理。**悬置**:A 组 #1(R1:a 维持裁撤/b 推翻补 requires_level 机制位——用户追问中)与 #10(状态面板改名已落地;暂停层锻造段删除异议本身待用户思考结论)。(worktree statuspanel-20261013;登记顺延 484——483 系并行术语表微批占用) - -- **485(2026-10-13,R1 机制位批——requires_level 等级阈值前置随批重立)**:用户对迭代 21 追认单 #1 裁「b) 推翻,补机制位小批」并令当场做(不占迭代号——用户令小批模式)。落地=卡片 v1.7 留任案形态:meta_tree_table.gd KEY_WHITELIST+requires_level 字段(Dictionary{node_id: n})+validate 三拒(键悬空/阈值<1/类型错);meta_progression.gd tree_can_buy 等级阈值判定分支+tree_gate_text 门槛文案+tree_camp_rows 投影行 gate_text;camp_overlay_view.gd 行板未达标 🔒 标+悬停文案;新单测 tree_requires_level_test 八断言(schema 四拒一过+判定三态+投影两态——首跑抓出测试自身时序 bug〔零配置行断言跑在 cap 满状态后〕重排修正)入 run_all(24→25 套);现役 12 行零配置=机制位空转零行为影响(配置归表行随需填)。闸=冒烟 938/0+run_all 25 套+probe --click/--full+render_gate 全绿(零漂移;MC 豁免=零数值零行为)+doc 三闸对基线零新增+熵增 PASS。文档=天赋树.md v0.10(六处 R1 表述换代:状态行/范围表/schema 连带/购买校验③/调参表/验收前置行)+iter21 报告 §四 #1 推翻标注+§八兑现注。合并 29b08d4(基点含并行 UI 主题卡片批 89b0008);主区 run_all 25 套兜底绿;worktree 与分支已清理。**迭代 21 追认单终态:十二条全收口**(十条追认+#1 推翻重立+#4 追认带意向);悬置仅剩 #10 锻造段异议结论(状态面板改名已落地)。(worktree r1mech-20261013;编号顺延 485——483 系并行术语表微批、484 系本会话改名批登记) - -- **486(2026-10-13,迭代 21 追认单终清——#10 裁维持现状)**:用户裁「维持现状就行了,到时候效果有问题,我再让你做对应的优化更改。现在不用动」——状态面板不补锻造概览(原属性锻造三行的信息缺口:锻造工坊武器/护甲路线等级面板不可见,用户知悉并接受,将来实际游玩效果有问题时按需提优化)。iter21 报告 §四 #10 标注追认结果收口。**至此迭代 21 待用户事项全部出清**(追认单十二条+反哺六条+欠账三条全链闭环);各批(20/21/22/23)追认与反哺全部出清,项目待用户面仅剩四批实机目检人闸+存量未决面(美术 P0 两项/去毒残留词/喂雷流 R5/通关口径 273 处)。快照/主战场换代。零代码零游戏文件。(worktree log486-20261013;编号顺延 486) - -- **487(2026-10-13,迭代 24 敌人表内容修批(三关)开工——U0 单会话交付)**:定义入库 0c083bb(主区守卫拦 commit 坑再证——b89c3fe worktree 提交 --no-ff 合回舞步);开工门=需求卡片 v1.1 零待裁点(Q1-Q9 全裁用户令「按推荐方式」)。基线复读:冒烟 938/0 + run_all **25 套**(卡片/roadmap 记 24 系 485 R1 批加套前旧基线,随批换代呈报)+ probe --click 全绿;改前 MC 锚落盘 sim-data/runsum_iter24_pre_n40both_20261013.jsonl(二档 N=20×both·seed0=9000 沿用迭代 23 配对种子:normal L1 通关 3/20·taken 中位 29.5;perfect L1 19/20·L2 8/20·全通 6/20·taken 中位 76.5)。T1 N1 落地=enemy.tres (1,2) hp 50→22·ac 3→2+表尾批注(阶名化解方案实机未达预期重裁沿革)+V1 两断言(降档锚定+相邻总量比≤2.5 护栏);T2 N2 落地=skills.tres 12→14 行(venom_spit 毒吐 ×1.6/CD2·shield_bash 盾击 ×1.7/CD3 均无 rider)+六池投放(蜘蛛 (2,5)-(2,7)+毒吐 2、灰矮人 (3,0)/(3,5)/(3,7)+盾击 2、首遇位 (2,4) 不动)+expect_pools 六键同步+旧「技能表十二行」断言换代十四行+V3/V4 五断言(两行字段域/两投放面/逐池增益妨害纪律)。冒烟 945/0+probe 全绿。T3 N3 进行中。(worktree g-plan2-iter24-enemy) - -- **488(2026-10-13,迭代 24 敌人表内容修批(三关)总收口——单会话 /goal+iter U0 全量交付)**:三提交全量入库(worktree g-plan2-iter24-enemy;26d669f N1+N2 / ab3ba4f N3 / 5f2ef77 文档同步面+收口笔)。**N1**:enemy.tres (1,2) hp 50→22·ac 3→2(敌种 bugbear/池/数量/atk 零动;表尾批注载 2026-09-24 阶名化解方案实机未达预期重裁沿革)+V1 两断言(锚定+相邻总量比≤2.5 护栏)。**N2**:skills.tres 12→14 行(venom_spit 毒吐 ×1.6/CD2、shield_bash 盾击 ×1.7/CD3 均无 rider——damage_floor 兜底与 0.75 档等效)+六池投放(蜘蛛 (2,5)-(2,7)/灰矮人 (3,0)(3,5)(3,7);首遇位 (2,4) 不动)+expect_pools 六键同步+旧「十二行」断言换代+V3/V4 五断言。**N3**:20 行 attack_type 全填 normal+enemy_table ATTACK_TYPES 枚举校验(缺省 normal 向后兼容)+unit_container 敌方快照+battle_orchestrator 开单第 9 参传值+**damage_controller._resolve_enemy_skill 克制消费点补一行**(卡片 §2 事实漏项——敌方兑付路径原硬编码 delta 0,2026-09-24 批注释在案;不改则 V5 矩阵命中证词物理不可达,属验收闸强制最小补点待用户追认=报告 §四#6)+单据载荷 attack_type 键+V5 四断言(矩阵证词同种子三甲型实测 heavy 2==light 3−1·ward 4==light 3+1)。**读数**:MC 同种子配对 seed0=9000 N=20×both 改前/改后各 40 局(锚落 sim-data/runsum_iter24_{pre,post}_n40both_20261013.jsonl);三组读数=N1 perfect L1 19→20/20、N2 perfect L2 8→13/20 全通 6→10/20(方向符合预期低于二档判读带,L2 记录不回调,倍率归 M4)、N3 单发恒 ±1(V5 钉死)全局中位位移系构成效应;二档会话累计 ~8 分钟。**文档同步面**:06 三条销号(第一关遭遇表数值异常/第二关技能池与投放/锻造迁移面⑥)+卡片条收口+反哺点五条专条;08 敌种池行注摘除升 v1.2(untracked 件随批转正入库);07 ㉓ 三目检登记;registry 三处(enemy.attack_type 字段/skill 十四行/hero 甲轴休眠注退役);Alpha未完成事项梳理三注订正(A2 已修+附.3 缺行疑云解销=L2/L3 缺 2/3/8 系奖励/休整/商店节正常缺省)。**闸**:冒烟 949/0+run_all 25 套+probe click/full+render_gate golden 0.00%(首跑 SKIP 抓出 worktree 漏拷 art 实体——初拷链因 .godot 路径错误短路,补拷后全绿)+doc 三闸/熵增对基线零新增(死链3/拔旗1/雾格1/lint 3件FAIL 均存量)。**待用户**:实机目检三观测(07 ㉓,登记不阻塞)+追认单三项(消费点补行/旧断言换代/两 untracked 件转正)+GDD 反哺五条。基线漂移记档=run_all 24→25(485 批)。合并=321e6c9(roadmap 与并行迭代 25 编入批 7e0f519d union 解——迭代 24 行已入库门列+迭代 25 UI 批行+26+ M4 行并存);合并后主区 --import 重刷+冒烟 949/0+run_all 25 套+probe --click 兜底绿。(worktree g-plan2-iter24-enemy;编号顺延 488——487 系本会话开工条) - -- **489(2026-10-13,迭代 25 UI 全局主题批开工——/goal+iter U0)**:开工检查全过:需求卡片 v1.2 零待裁点(三范围裁点+三 grilling 裁点+同日审核六点全落文);验收清单 V1-V6 三要素齐(V1-V6 自动闸机+V6 中文字体防御 v1.2 新增)。自洽扫描事实抽查全符(project.godot 仅 custom_font 无 gui/theme/custom/ui_kit:735 styled_slider 与 :753 tooltip_theme 在役/ui_assembler:105 挂载行/consumers=settings_overlay:59+debug_overlay:277 裸 HSlider 双轨/HSeparator 15 处/tooltip_text 11 文件/theme 目录不存在/art/ui 无滚动条滑轨勾选贴图);一处事实 drift 记录继续(有利方向)=卡片 §5 称 08-Alpha版本标准 系 git 未跟踪文件,实际已于 5f2ef77(迭代 24 文档批)转正入库——手工搬运条款 moot,worktree 直接可见。定义面四件(roadmap 迭代 25 行/需求卡片/06/08)均已跟踪且干净(迭代 24 收口批 7e0f519d union 解带入),T0 无需新定义入库提交;主区脏件全属他批遗产零碰(.gitignore/.zcode/02/playnote/四 untracked/三 .uid)。基线复读全绿=冒烟 949/0(V5 基线按卡片「开工日实测为准」口径订正为 949/0,卡片记 938/0 系迭代 23 时代数)+run_all 25 套+probe --click 全绿残留 0(ui_input 17 断言/ui_struct/ui_contrast 38 对/click 行为走查问题 0)。worktree g-plan2-iter25-theme(分支 iter25-theme-20261013,基点 5f8acd0)已建,冷检出三件套(art 主区绝对路径拷贝+字体 .import 拷贝+--import 刷导入件)完毕,T0 主题资源起。 - -- **490(2026-10-13,迭代 25 UI 全局主题批总收口——单会话 /goal+iter U0 全量交付)**:T0-T2 三卡全落(worktree g-plan2-iter25-theme,两提交)。**T0 主题资源**:`game/assets/theme/main_theme.tres`(15 类型=V/HScrollBar·ScrollContainer·H/VSlider·TooltipPanel/Label·LineEdit·SpinBox·H/VSeparator+预盖 CheckBox/CheckButton/OptionButton/PopupMenu)挂 project.godot `gui/theme/custom`;位图生成脚本 `tools/gen_theme_icons.py`(PIL,幂等)产 9 张纯色/几何小位图落 `game/assets/art/ui/gen/`;色值溯源表 `game/assets/theme/README.md`;`default_font` 显式指现役同字体文件(V6 中文字形防御)。**T1 换代退役**:ui_kit.gd 删 `tooltip_theme()`/`_tip_theme` 与 `styled_slider()` 整函数、ui_assembler.gd 删挂载行(旧实现同批删除);settings_overlay 音量滑轨几何内联(裸 HSlider+200×24)、debug_overlay `_slider_row` 补注释(双轨消隐=两处均走全局主题)。**T2 断言与文档闸**:冒烟新增 `_smoke_global_theme()` 38 断言(V1 类型覆盖+Button/focus 双红线+V2 冻结值锚定+5.49:1+V3 预盖证词+V4 退役零残留+V6 字体防御双断言);06「UI 全局主题资源缺失」条移除+「UI 元素细节修」①销号;08 v1.3(三·界面主题行→在役+五·表现细节修行注;余五行本批零触碰已逐行核对);07 ㉔ 全屏巡检登记;roadmap 迭代 25 行换代。**引擎事实三证**(4.7.2 源码+默认主题链双查,探针实证):①CheckButton 与 CheckBox 同套 checked/unchecked 图标名(卡片 v1.2 注③「on/off」不成立——按引擎事实落位否则预盖静默空转,订正随报告呈报);②Slider 无 grabber_pressed 图标槽(冻结表「柄·按」GOLD_DEEP 留档未落位);③ScrollBar 柄=StyleBox 非 Icon(滚动条无位图,increment/decrement 箭头默认主题未定义=无箭头按钮);另证 4.7 导入参数无逐贴图 filter 标志(位图原生尺寸消费无滤波伪影,全局设置红线未触)。**位图不入 git**:.gitignore:52 `game/assets/art/**`(注释明文「运行时资源本地生成不入库」)——卡片 T0「.import 侧车随批入库」与政策冲突,按政策执行(脚本入库可再生+README 溯源+主区随批拷贝 gen/),例外强制入库与否呈报追认。**闸**:冒烟 987/0(基线 949+38)+run_all 25 套+probe click/full+render_gate golden 0.00%(3 屏)+doc 三闸/熵增对基线零新增(死链 3/词命中 2/lint 3 FAIL 均存量);MC 零跑(零数值零行为=纯呈现)。**待用户**:实机目检全屏巡检+专项观察点二(07 ㉔)+代拍板追认单八项+GDD 反哺点五条(design/qa/iter25-实现报告-2026-10-13.md §四/§五)。合并=见 git(主区 merge --no-ff;合并后 --import 重刷+gen/ 位图拷贝+全量复跑留痕)。 - -- **491(2026-10-14,迭代 26 UI 交互与观感批开工——/goal+iter U0)**:开工检查全过+两发现按用户裁诀执行。门=U0(本次会话 /iter 26 发令);卡片 v1.2 零待裁点(grilling 两轮八裁全落);V1-V7 验收清单三要素齐(V1-V6 自动闸机+V7 对拍面)。自洽扫描事实抽查 20+ 处全符(_apply_button_skin hover=常态图/disabled=pressed 错配 ui_kit:541-555;primary/danger 无 focus 盒与 disabled 错配 :575/:591;BCard 图标槽 76×76 :659-663;顺位徽标 GOLD_DEEP standee:441;护甲徽标 ward=HERO_BLUE/heavy=GOLD_DEEP :492/:494;GOLD_DEEP 语义岗 standee:199 意图动画判据;RAP 行 STONE_FAINT ap_bar:77;beams 硬边 :263-277;vignette/gradient 无显式 filter;project.godot 无 default_texture_filter;诊断钮无条件挂载 main:333-334+_on_diagnose_pressed :1290;冒烟双红线 smoke_all:5377/5385+对比度 helper :29-37;商店纯文字行/三选一已居中/营地四栏不等高;裸 Button.new() 全库仅 uikit:446)。**发现①**(用户裁按建议改法):卡片 §2.2 texture_filter 枚举漏登 board_world.gd:50(hero NEAREST),计 12 实测 13——已勘误落卡(NEAREST 10→11),该点与全局 Nearest 同向、零翻转风险、不进白名单。**发现②**(用户知会择机自理):主区 game/project.godot 编辑器对调脏件(theme 两行换序语义等价)——合并点复检,受阻停机呈报不擅动;另主区 active.md 脏件系编入会话快照遗产,本批 active.md 台账一律走主区侧写、不入分支(避免合并互撞),收口后随批在主区单独落 docs 提交。定义面入库 04ec217(roadmap/06/需求卡片指名三件)。基线复读全绿=冒烟 987/0(与在册一致)+run_all 25 套+probe --click 全绿残留 0(ui_input 17 断言/ui_struct/ui_contrast 38 对/click 行为走查问题 0)。**枚举两份**(T0 交付):①纹理过滤翻转面——显式 filter 13 处(NEAREST 11=ui_assembler:188/battle_end:60,76/board_fx:150/board_view:310/board_world:50/hero_info:202/level_map:169/standee:222/uikit:234,508,671;LINEAR 2=board_world:43 脚影/status_slot_row:127 状态图标);无显式 filter 仅 3 处(ui_kit:253 vignette/:272 beams/:291 gradient_base)=T2 白名单对象;StyleBoxTexture 九宫格(_tex_sb 产线 button_stone×2/panel_stone/border_stone)+主题 OptionButton 石纹样式盒(SBTex_btn/SBTex_btnp,非 Button 类型、红线不破)/滑轨抓子/勾选/箭头图标翻 Nearest=意图面;.tscn 零纹理节点(TextureRect/Sprite2D/TextureProgressBar/NinePatchRect/TextureButton/AnimatedSprite2D/TileMap 全零)。②按钮消费点 49 处(button 43+verb 1+primary 4+danger 1)全经四工厂,T1 覆盖面闭合;禁用态实跑点=shop_overlay_view.gd:117 余额不足禁用。另核:ui_contrast_probe 测点表为静态常量对、不覆盖禁用态(disabled 幽灵化不踩该闸);主题层 SBTex 两子资源归 OptionButton 名下。worktree g-plan2-iter26-ui(分支 iter26-ui-20261014,基点 04ec217)冷检出三件套(game/.godot 5.8M+art 931K+字体 .import)+--import 刷新 EXIT=0,T1 起。 - -- **492(2026-10-14,迭代 26 UI 交互与观感批总收口——单会话 /goal+iter U0 全量交付)**:T0-T6 八提交全量入库(worktree g-plan2-iter26-ui,分支 iter26-ui-20261014:b6f0c66 T1 五态/9ddb571 T2 Nearest+白名单/7cac0dc T3 换墨/86e9aea T4 光柱/02c87fc T5 细节/260c9bb T5b 诊断钮/900dfe9 T6 文档闸)。**T1**:ui_kit 三厂五态统一管线(hover=常态图+modulate 1.06 提亮〔乙案〕/disabled=本族底+α0.45 幽灵化〔甲案,旧「=按压图」错配修正〕/focus=INK 2px 内缩 1px 环〔甲案,负 expand margin 实现,引擎 focus 叠加绘制不遮钮底〕/危险钮补本族 pressed 深档),逐实例 override 主题层零新增;冒烟 +35 断言。**T2**:project.godot default_texture_filter=0+vignette/beams/gradient_base 显式 LINEAR 白名单;+6 断言。**T3**:立 GOLD_BRIGHT #E0B860/HERO_BLUE_BRIGHT #7EBAF0 两 token(语义岗冲撞走反哺点③),顺位/重甲/魔法护甲三徽标+RAP 行换墨(6.47/5.88/5.98:1);+9 断言。**T4**:beams 带内 0→0.05→0 三角过渡+纵向衰减(连续 alpha,Q7 裁);+3 断言。**T5**:SLOT_BACKDROP_SOFT #806A4E(白图标 5.14:1 ≥3:1)+商店 ALIGNMENT_CENTER+营地四栏等高(三 holder min 336+四面板 FILL+锁文居中);+8 断言。**T5b**:诊断钮卸载点+build_diag_button 工厂同批删除,转储入口迁调试浮窗(diagnose_requested 信号+区块⑤钮,Q8 裁甲);ui_tune_probe 只读巡检同批入册(白名单+_emit_diagnose_requested、连接数 10→11);+7 断言。**闸**:冒烟 987→**1055/0**(+68)+run_all 25 套+probe click/full 全绿+render_gate 全绿(shot_checker A-D 过;golden 三屏 **0.00%**——T6 第4 步登记即结未重制基线;战斗屏 draw_calls 191=基线 270 的附带收益)+doc 三闸/熵增对基线零新增(lint FAIL 集=06/07/术语表基线三件;08 一度因新增表格单元格撞 R3「日期+裁决同括号」正则,改措辞回绿——教训=08 表格单元格注记禁载「日期+关键词」同括号);MC 零跑。**文档同步面**:06 四条销号/氛围层改记「九宫格半存续」+反哺点四条新条+需求卡片条标已收口;08 v1.4;07 ㉕+v0.9;roadmap 迭代 26 行→已全批入库;实现报告=design/qa/iter26-实现报告-2026-10-14.md(代拍板追认单十三项+GDD 反哺点四条+目检五项)。**合并**:主区 game/project.godot 编辑器对调遗产脏件挡合(发现②预案场景)——用户裁「授权提交该对调」,落 no-op 提交 081ae3b 后 merge --no-ff **c8c3db1**(17 文件 +442/-48);合并后主区 --import 重刷+冒烟 1055/0+run_all 25 套+probe --click 全绿残留 0。active.md 台账本批全程走主区侧写(不入分支,避合并互撞——编入会话的 active.md 遗产脏件同因)。**待用户**:实机目检五项(07 ㉕)+代拍板追认单十三项+GDD 反哺点四条。 - -- **493(2026-10-14,迭代 27 代码架构技术债修复批开工——/goal+iter U0)**:开工门全解:三点待裁经 AskUserQuestion 用户三裁全按推荐案(①SaveManager/MetaProgression=第三个 autoload/②Ledger=单类持四账/③_settle=审计五段)→ 卡片 v1.2 零待裁;自洽扫描 8 处 file:line 抽查全符(1385/1725/31 行、:647-657 手工清单、10 探针挂 main.tscn、四共享账、_refresh_used_round 双账)。定义面入库=009a63c(worktree 提交)→ merge 2375923(主区舞步:未跟踪卡副本 rm+roadmap/06 checkout 丢弃+--no-ff;迭代 26 进度行滞后系上会话遗留原样随行,未代改)。基线冻结全绿=冒烟 1055/0+run_all 25 套+probe --click 全绿残留 0+render_gate golden 全绿。T0 交付:①对拍工具 tools/parity_anchor.py+锚 anchor.json(三变体 base/attune/shop×40 局×RUNSUM+JSONL 剔 ts 行双面,种子面 71000/72000/73000 错开覆盖三类重构面;坑两枚= BATCH 行时间戳含 T 致 \d+_\d+ 正则失配、冷检出需拷 .godot/art/.import 三件套否则挂死);②探针迁移对照表 11 挂载面(design/qa/iter27-探针迁移对照-2026-10-14.md)。T1 设计定案(代拍板白名单内):三屏场景 menu_screen/camp_screen/adventure_screen(battle_root+level_map 同入 adventure 场景置于 main 首子位=全模态之下,视觉共存对全数保序验算过;模态登记序不变)+run_scope 节点物化局态(adventure/debug 两类会话共用,终局 queue_free 替代两张手工清单)+SaveManager/MetaProgression 升格 autoload(类名加 Core 后缀沿 RngService 先例、autoload 占净名;探针隔离改原地重置 attach_path 沿 set_master_seed 先例)。并行会话警示:user://logs 见 playtest_777 同窗写入(共享目录并发,对拍 BATCH 行按名取文件不受染)。worktree g-plan2-iter27-techdebt(分支 iter27-techdebt-20261014,基点 2375923),T1 起。 - -- **494(2026-10-14,qa/ 实现报告未处理项清零·收尾批)**:用户四裁——反哺点14条「全部按呈报落文」/追认单29项「全部追认通过」/孤儿遗留7项「全部补登06」/实机目检「已全部完成」。**簿记标注**(据既有裁决记录, iter20/21 追认与反哺前序已裁):iter20 §三十条+§四五条+§二V20-V23、iter21 §三#2-12+§五六条、iter19 七份遗留移交逐条结案/孤儿标注、iter25 反哺补登 06 专条(前序漏登)。**反哺落文 14 条**:iter24 五条→敌人系统.md **v0.18**(attack_type 字段行+矩阵消费面双向在役/技能错峰两轨/敌种表两行池构成/hobgoblin 缺口登记)+难度曲线与Boss.md **v0.29**(只测不判,数值归M4);iter25 三条→art-bible.md **v3.14 §7.6(二)**(原生控件组件规格)+06「UI元素细节修」条①措辞订正(「同一个深棕色」不符代码面)+§7.6 末注(主题色值双源);iter26 四条→art-bible.md **v3.14**(§7.6(一) 按钮五态/§4.1 三 token+色板 42→45/§7.6(三) 氛围层两派/§8.2 Nearest+LINEAR 豁免清单)。**追认单 29 项**全追认(iter24 §四八项含#6 克制消费补行、iter25 §四八项、iter26 §四十三项)——三报告追认单节已标注。**孤儿七项补登 06** 专条(design/diagrams 越界/开场行后缀/STONE 外溢/迷雾三关扩对/字面量墨/TG_* 判据/数据配置223+商店房截图)。**人闸核销**:07 ⑮真人半+⑳㉑㉒㉓㉔㉕ 七节加核销注记(v1.0 版本行)+iter20 五件与 V20+iter19 存活八项+迭代18 清单 18 项同批核销(用户回报完成未呈报问题)。**闸**:doc 三闸对基线零新增(gdd_lint FAIL=06/07/术语表基线三件;doc_link 死链 2+已知 1 存量;term 命中 3 存量)。**待用户**:qa/ 13 份报告删除清单确认(清理口径三条件已全满足)+ 主区未提交遗产处置(iter22/23 报告已删未 staged/02 +2 行/active.md 等前会话脏件)。 - -- **494 续(2026-10-14,qa 收尾批·删除执行)**:用户裁「全部删除」——qa/ 下 14 份迭代实现报告全数删除(iter19 七份+iter20/21/22/23/24/25/26;iter22/23 系前会话已删未提交件,本次一并清出工作区)。保留=ui-audit 目录、ui-audit-vs-demo-2026-10-06.md、迭代18-实机目检总清单(非实现报告,用户明令不删)。连带修正:06 反哺点专条与锻造条中指向已删报告的链接改「已退役,git 历史可考」措辞(iter24/25/26/21/23 五处),doc_link 复跑死链回落至存量 2 处(元进度/天赋树 武器锻造.md 更名遗留,非本批引入);iter23 条「残留人闸」括注补 07㉒ 已核销。git 历史可恢复全部已删报告。 - -- **494(2026-10-14,迭代 27 代码架构技术债修复批总收口——单会话 /goal+iter U0 全量交付)**:五波七提交全量入库(worktree g-plan2-iter27-techdebt 分支 iter27-techdebt-20261014:fc7fee0 T0 对拍锚+探针表/7a0d57d T1/26301ba T2/6fd7d78 T3/8b9e556 T4/b605022 T5/eea3458 T6+T7;定义面 009a63c 先行入库 merge 2375923)。**T1**:三屏壳场景+RunScope 会话物化+双 autoload(裁点①甲);屏壳根 STOP 吃输入病灶实证修(mouse_filter=IGNORE+V2 闸)。**T2**:_settle 五段 Segment+旗判随段迁入+counter/grant 八处分单点+英雄攻击拆四步(编排器 1725→1325 行)。**T3**:RunLedger 单类四账(裁点②甲)+刷新双账删副本(presentation_snapshot 升键 refresh_used 单源)+gp_final 键删影子账。**T4**:ModalFlow 纯逻辑类(场景拆分后重估=抽取面收敛模态域)+互斥域 tags 化(non_locking/screen_state 封闭词表)+双 context;V6 测试抓出挂起兜底 divergent-return 分歧一处(按原语义修)。**T5**:audit_type_hints.py 机器闸(R1 容器注解/R2 有值返回/R3 参数;368 机械参数化 Array[Variant]/Dictionary[Variant,Variant]+13 真类型+四处 stub 白名单)+project.godot untyped_declaration=1。**T6**:死代码 13 函数(审计 16 复核 ui_kit:486 现役不删)+FeatsEngine 退役+Callable×10 换方法引用(语法实证)+状态机双 enum 化+ConfigDB _fatal 归根+resolver 诊断/数据 Callable 解耦(类型环断根)。**闸**:逐位一致对拍三变体五跑全同(V1 核心;卡此工具=tools/parity_anchor.py,种子面 71000/72000/73000 错开覆盖三类重构面)+冒烟 1055→1081/0+run_all 25→27 套(+settle_segments/modal_flow 两新套)+probe click+render golden 0.00%+static_scan 修复 cd 静默空转后 S1/S2/S4/S9 首次实跑全绿(S1 暴露 main randi=ADR-0007 豁免面→标记通道)+doc 三闸/熵增对基线零新增(lint 三失败=06/07/术语表基线同三件)。**坑册三枚**:①屏壳根全屏 Control 默认 STOP 吃下层模态鼠标输入(ui_input 悬停实证→IGNORE+V2 闸);②--script 模式编译器不解析裸 autoload 标识符(run_all 头注+pacing Parse Error 实证→P2-2 降格路径常量单点);③adventure_runner 既有成员 ledger(关卡账)撞名(T3 改 run_ledger)。**合并**:master 被并行 qa 收尾批推进(5a188f3:14 反哺落文+29 追认+14 旧报告退役+人闸核销——用户已回报 20~26 目检完成)——07 双 v1.0 冲突并集解(并行行保 v1.0/我方顺延 v1.1+㉖ 节);主区审计报告脏件=卡片已承载的计数修正(即死免保史)checkout 丢弃+三 .uid 未跟踪副本 rm 后 merge --no-ff **dd418e5**;合并后主区 --import 重刷+run_all 27 套全绿复跑。**待用户**:实机目检五件(07 ㉖)+代拍板追认单十五项(报告 §三)+GDD 反哺点两条(报告 §四/06)。worktree 与分支收尾清理见下条。**卡片核对补遗(2026-10-15)**:用户令核对卡片兑现面——查得 V8 断言未落/两条登记漏/漏网 Callable×2/resolver 幽灵通道(reset_warn_dedup 门面参从未存在=字符串 Callable 零校验藏死引用,换装编译期暴露)四项,补遗批 iter27-closeup-20261015 九提交 merge **d5eea25**(冒烟 1086/0=+V8×5;实现报告 §六 补核对结案段);顺录:编辑器 --import 会重写 project.godot 丢手加 [debug] 段(V7 源码断言即护栏,丢失即冒烟红)。worktree/分支已清理。 - -- **495(2026-10-15,迭代 28 启动装配与生命周期验收补全批开工——/goal+iter U0 连做全批)**:用户两裁(①迭代 28 插队、M4 数值批顺延 29+;②交卡后连做全批=卡片预批,grilling 门由预批豁免、实施期自检三问)。定义面入库 **39c6544**(主区 docs 笔:roadmap 迭代 28 行+M4 行改 29++06 登记条;需求卡片=design/research/需求卡片-启动装配与生命周期验收补全批-2026-10-15.md v1.0 零待裁点、按「永不提交」惯例不入 git;计划书存档 .zcode/plans/启动装配与生命周期验收补全批-loop-plan-2026-10-15.md)。worktree **g-plan2-iter28-bootlife**(分支 iter28-bootlife-20261015,基点 39c6544;三件套 .godot/art/.import 已拷)。**基线冻结**:冒烟 **1086/0**(roadmap/卡片记 1081 系 iter27 补遗批 d5eea25 +V8×5 未回写,以实跑为准、收口时回写)+run_all **27 套**全绿+probe_gate --click 全绿残留 0。**T0 树序实采**(临时探针两枚采完即删):main 子节点 16=MenuScreen@0/AdventureScreen@1/row_pacer@2/legend@3/node@4/curio@5/end@6/shop@7/CampScreen@8/settings@9/status@10/career@11/inter_overlay(ColorRect 无脚本)@12/confirm@13/debug@14/run_scope@15(_begin_session 在 _build_ui 之后调用=恒追加最末);12 模态登记序=legend/node/level_screen(宿主 AdventureScreen idx1)/curio/end/shop/camp_overlay(宿主 CampScreen idx0)/settings/status/career/confirm/debug;boot 可见性=start_overlay vis=true/battle_root vis=true/level_screen+camp_overlay+inter+debug 全 vis=false/run_scope 闲时会话 in_tree=true valid=true;三屏壳均 mf=IGNORE 纯容器、camp 壳 boot 态透明( vis=true 但成员恒隐)——「顶层可见层」断言必须遍历内容层禁选屏壳(卡片诊断订正①运行期实证)。T1 起。 - -- **496(2026-10-15,迭代 28 启动装配与生命周期验收补全批总收口——单会话 /goal+iter U0 连做全批)**:七提交全量入库(worktree g-plan2-iter28-bootlife 分支 iter28-bootlife-20261015:`6f71509` T1/`a35581e` T2/`77075e6` T3/`67342c69` T4/`db1bf423` T6/`140e4408` T1 补类型闸/`674f88a0` 实现报告;T5 变异验证横切零提交)。**T1**:装配语义合同 `LAYER_CONTRACT` 单点化(16 层=屏壳/模态/全屏态/非视觉节点,带 tags/host/shell 三类特例字段;卡片基于「十二模态登记数组」实采后扩为 16——代拍板 #9)+全仓唯一落位口 `_apply_layer_contract`(删散落 `move_child` 两处)+**装配顺序修复**(冒险屏先挂、菜单屏后挂=坏事实①「F5 见战斗界面」本体)+V2 断言重写四条(V1a 顶层可见层经内容层遍历/V1b 菜单壳树序>冒险壳/V1c 合同树序链逐对保序/V1d 落位单口源码断言)——退役裸下标断言三条(旧断言把错误顺序写成期望值=坏事实②「测试在保护 bug」);探针侧 `_modal_registry_contract` 入役、`_career_registry_contract` 退役。**T2**:`_smoke_boot_chain` boot 链路十断言(卡片写六——代拍板 #10;含续玩钮隔离三子态双向验)。**T3**:`_smoke_lifecycle_matrix` 九阶段×五引用面(卡片写十,地图选路停点态并入开局停点——代拍板 #11);活战斗驱动复用 `_auto_play_round` 模式。**T4**:渲染面三件=shot_probe 两自检(boot 顶层+菜单标题/副标题 `is_visible_in_tree` 且落视口内)+shot_checker 墨色判据 F(差>60 占比带 [2%,55%] 极性无关)+**启动态菜单 golden 入库**(`game/tests/golden/menu_boot.png`,`golden_baseline_refresh.sh --menu` 新模+render_gate 补段;帧差前置验 0.0000% 故全屏比对不收窄)。**T5 变异验证六次注入全见红并精确还原**(记录表进报告 §五):①翻装配序→V1a/V1b 红;②插散落 `move_child`→V1d/V1c 红;③注释 `add_child(run_scope)`→V2e+V3 全 21 面红(22 项);④注释 `queue_free`→V3f 单点红;⑤藏菜单层 `visible=false`→冒烟 V1a/V2c/V3a+探针自检 3 项+golden 34.23%+checker exit=1 四面全红;⑥续玩钮状态源倒置→V2d 四条+V3a/V3i 红(6 项)。**变异 3 的关键发现**:F 判据(墨色占比)自身**不红**——菜单被藏后底层棋盘透出仍给 33.48% 高反差像素落带内;真正拦截靠 `is_visible_in_tree` 自检与 golden 逐像素。F 判据只证伪「整框空白/整框糊」,不证明「框里是菜单标题」——已写进 code-conventions §3.6 判据强弱分层。**T6**:新硬规则「验收函数无变异红记录不算验收成立」落 CLAUDE.md 第 9 条(原 9-14 顺延)+code-conventions §3.6+req-card 技能 §7(WorkBuddy/ZCode 两份副本已补,两副本各有自有条目未擅自取齐);机械面同步=roadmap 迭代 28 行换代+前沿改 29+ M4、06 登记条销号+反哺点三条专条、07 新增 ㉗ 目检节五观测。**闸**:冒烟 **1086→1125/0**(+39=新增 42−退役裸下标 3)+run_all 27 套+probe_gate --click 全绿残留 0+render_gate 全绿(棋盘 golden 0.00%×3+**菜单 golden 0.00%**)+doc 三闸对基线零新增+static_scan S1/S2/S4 ok、**S9 归零**、S10 存量 125(文件头清偿批在册);MC 零跑。**类型闸自纠一笔**:批末 static_scan 报 S9 存量 1 处=本批新增 `main.gd:453 var tags: Array` 无元素类型,随批修 `Array[Variant]` 归零(冒烟复跑 1125/0 不变)——本批新增闸抓别人的错,既有闸同样抓本批的错。**⚠ 收口待裁(已呈报,未擅自处理)**:probe_gate **--full 红**=`t17_defer_probe`「关卡画面未出现」(exit=2;首次表现为 exit=124 超时同根因)。三条证据指向**非本批引入**:①主区 master 39c6544 同探针 FAIL 4/4 全同;②真实档 `user://save.json` 临时移开后同探针 PASS(15s);③首次跑绿、跑完即把真实档写成带断点态、其后必红=**探针自污染**。机理=`_start_adventure_from_menu`(main.gd:498)在有断点时改弹「已有未完冒险」确认框不开冒险,探针隔离(`main.save_manager=iso_c`)未覆盖该路径,60 帧等不到 `level_screen.visible`。**user:// 全 worktree 共享**(同 project name)=主区与各 worktree 读写同一份存档;定位过程中曾临时改名移开真实档,**已按原样还原并 cmp 逐字节校验一致**(备份 /d/tmp_save_backup_20261015.json)。历史:iter26 台账记「click/full 全绿」,**iter27 只记 `probe click` 未记 `--full`**——该红大概率自 iter27(row_pacer 排播泵迁出+ModalFlow 抽取)起存在而未跑到;probe_gate 头注亦有预言「超时多半=探针未适配新停点层,归 probe 适配批」。修它=改探针隔离=卡片外新需求,故**止步呈报**待裁(甲:认存量红照常合并/乙:先修探针隔离再合并/丙:用户先处置本机真实档断点后我复跑取绿)。**顺带清理(基线带入)**:07-体验验证清单 v1.0 行处残留 `<<<<<<>>>>>>` 合并冲突标记(iter27-techdebt-20261014 合入 master 时漏解),两侧均有效故全留、版本号顺延 v1.1。**待用户**:--full 存量红处置三选一(上甲/乙/丙)+实机目检 ㉗(登记不阻塞)+代拍板追认单十三项(报告 §三,含四条白名单外)+GDD 反哺三条(报告 §四,06 已登记)+req-card 两副本是否取齐。**回写**:卡片/roadmap 所记冒烟基数 1081 系 iter27 补遗 `d5eea25` +V8×5 未同步,已按实测 1086 回写。 +- **498(2026-10-15,active.md 退役清理批)**:按 doc-conventions §10 执行一次状态退役——删除迭代 20~27 的 31 条已完结条目(判据三条齐备:批次已入库、结论已进快照、未决项不指向条目;内容可在 git 历史完整复原),状态记录由 34 条降到 3 条,回到 30 条硬上限内。快照节原为 21 条且整块自我重复(两条「更新于」、两条「批末闸全绿」、两条逐字相同的「迭代 26 交付」),去重换代为 10 条。删掉「项目当前位置」整节——该节滞后于快照与 roadmap,里程碑归 `roadmap.md`、实时进度归快照节。未决面按迭代 27/28 现行待裁与待追认重列,并把三条在途未合入分支登记在册以免被当已入库。本批零代码、零其他文档改动。 diff --git a/design/dev/doc-conventions.md b/design/dev/doc-conventions.md index 639876f4..48687f17 100644 --- a/design/dev/doc-conventions.md +++ b/design/dev/doc-conventions.md @@ -96,7 +96,7 @@ ## 10. 会话记录纪律 -**active.md 定性:状态文件——状态记录,不是工作日志。** 根目录 `active.md` 是会话状态的唯一状态源,**每一行当下为真**;历史归 git 提交史。只许写三类:①当前状态快照(≤10 条滚动窗口);②未决面(进行中批次/待人闸/待裁点指针);③当前迭代滚动工作条目。禁止写入:已完结批次的历史叙述、待办裁决事项(归 06)、跨会话教训(归记忆库);并行会话禁止整体复原/回退本文件。退役规则:**用户确认任务完成时清除当前会话写过的状态条目——状态清除即任务完成的证明**;条目完结判据=批次已入库+结论已进快照+未决面无条目指向;迭代收口兜底删除已完结条目,超过 30 条必须清。 +**active.md 定性:状态文件——状态记录,不是工作日志。** 根目录 `active.md` 是会话状态的唯一状态源,**每一行当下为真**;历史归 git 提交史。只许写三类:①当前状态快照(≤10 条滚动窗口);②未决面(进行中批次/待人闸/待裁点指针);③当前迭代滚动工作条目。禁止写入:已完结批次的历史叙述、待办裁决事项(归 06)、跨会话教训(归记忆库);并行会话禁止整体复原/回退本文件。退役规则:**用户确认任务完成时清除当前会话写过的状态条目——状态清除即任务完成的证明**;条目完结判据=批次已入库+结论已进快照+未决面无条目指向;迭代收口兜底删除已完结条目,超过 30 条必须清。**机械闸**=`tools/audit_active_state.py`,判四条可机械测的膨胀签名(条目数上限、快照行数上限、条目编号重复、指向中间文档的死指针),随 `tools/run_all_gates.sh` 全量档跑并由合回闸强制——收口漏删旧条目,合回时会被拦下。 条目用完整白话句子写清结论本身,长度服从可读性(能看懂比字数少重要);禁把定稿摘要、义务清单整段搬进条目(详情归权威文档);第 4 节用语纪律对状态记录同等生效;条目记裁决结论本身,不记中间文档文件指针(见第 11 节)。 diff --git a/design/dev/process-conventions.md b/design/dev/process-conventions.md index c54bf62f..ac3f5e9e 100644 --- a/design/dev/process-conventions.md +++ b/design/dev/process-conventions.md @@ -46,7 +46,7 @@ **收口** 10. **批末全量验收才合并**——在任务 worktree 内跑 `tools/run_all_gates.sh`(不带 `--quick`),全绿才合回 master。该脚本是全部验证闸的**唯一入口与唯一清单**,闸件增减只改它;**本文与其他文档禁另列闸件清单**(清单散落多处正是 iter27 漏跑 `probe_gate --full` 的成因)。跑完写回执 `game/tests/.gates/receipt.json`,合回时由 worktree-guard 强制校验 11. **合并后主区全量复跑**——合并可能引入冲突或环境差异,落回 master 后再跑全套 -12. **会话收口落记**——active.md 快照与状态记录更新(含删除已完结旧条目,doc-conventions 第 10 节);跨会话教训写入记忆库 +12. **会话收口落记**——active.md 快照与状态记录更新(含删除已完结旧条目,doc-conventions 第 10 节);跨会话教训写入记忆库;漏删旧条目由 `tools/audit_active_state.py` 在全量档抓(合回闸强制,脚本即清单) 13. **文档同步闸**——机械面文档(roadmap 行/registry/active.md 记账/README 工具注)合并前随批更新完毕方算收口;设计权威文档批内不更新:实现批收口出迭代实现报告(`design/qa/iter-实现报告-<日期>.md`:各卡状态+代拍板追认单+GDD 反哺点节),反哺点同步登记 `06-待办清单`,用户逐点裁决后另批落文;反哺点未落文期间相关 GDD 节视为待反哺,读前先查 06;需求卡片必列「关联文档同步面」按两层标注 14. **实机目检归用户,只登记不阻塞**——真人检测项登记进实现报告目检总清单与 07-体验验证清单即完成批内义务;禁把等目检当停工理由或收口前置 15. **中间产物吸收即死**——细则见 CLAUDE.md 硬性红线与 doc-conventions 第 11 节 diff --git a/game/tests/.gates/baseline.json b/game/tests/.gates/baseline.json index 14e514d7..d5acaec5 100644 --- a/game/tests/.gates/baseline.json +++ b/game/tests/.gates/baseline.json @@ -33,6 +33,10 @@ "exit": "0", "fp": "green" }, + "08b active.md 体量": { + "exit": "0", + "fp": "green" + }, "09 静态扫描": { "exit": "1", "fp": "3220614b09c4" diff --git a/tools/audit_active_state.py b/tools/audit_active_state.py new file mode 100644 index 00000000..1950c70d --- /dev/null +++ b/tools/audit_active_state.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""audit_active_state.py — 根目录 active.md 体量闸(doc-conventions §10 的机械面) + +状态文件只记当下:条目只增不减就是腐烂。本脚本查五条机械可判的膨胀签名—— +状态记录条目数超上限、快照节行数超上限、条目编号重复、快照整行自我重复、 +指向中间文档(design/qa、design/research)的死指针。 + +退出码:0=全绿;1=有红(逐条打印差额,供收口批据此删条目)。 +用法:python tools/audit_active_state.py [--file PATH] [--quiet] +""" +import argparse +import os +import re +import sys + +ENTRY_LIMIT = 30 # §10:状态记录超过 30 条必须清 +SNAPSHOT_LIMIT = 10 # §10:当前状态快照 ≤10 行 +INTERMEDIATE_PREFIX = ("design/qa/", "design/research/") +ENTRY_RE = re.compile(r"^- \*\*(\d+)( 续)?") +BULLET_RE = re.compile(r"^- .{20,}") +PATH_RE = re.compile(r"design/(?:qa|research)/[^\s)`,,。)]+?\.md") + + +def split_sections(text): + """按二级标题切段;标题前的内容归入 '' 键(文件头元信息,本闸不判)。""" + out, key = {}, "" + for line in text.splitlines(): + if line.startswith("## "): + key = line[3:].strip() + out[key] = [] + continue + out.setdefault(key, []).append(line) + return out + + +def find_key(sections, prefix): + for name in sections: + if name.startswith(prefix): + return name + return None + + +def audit(path, repo): + with open(path, encoding="utf-8") as f: + sections = split_sections(f.read()) + reds = [] + + snap_key = find_key(sections, "当前状态快照") + rec_key = find_key(sections, "状态记录") + if snap_key is None: + reds.append("A0 快照节缺失:状态文件必须含「当前状态快照」节") + if rec_key is None: + reds.append("A0 状态记录节缺失:状态文件必须含「状态记录」节") + + snap = [ln for ln in sections.get(snap_key, []) if BULLET_RE.match(ln)] + if len(snap) > SNAPSHOT_LIMIT: + reds.append("A1 快照节 %d 条,超上限 %d——先删被新一轮取代的旧行,别只往顶部加" + % (len(snap), SNAPSHOT_LIMIT)) + + seen = {} + for ln in snap: + seen[ln] = seen.get(ln, 0) + 1 + dups = [ln for ln, n in seen.items() if n > 1] + if dups: + reds.append("A2 快照节有 %d 行整行自我重复(换代不彻底的签名):%s" + % (len(dups), dups[0][:60] + " …")) + + nums, conts = [], [] + for ln in sections.get(rec_key, []): + m = ENTRY_RE.match(ln) + if m: + (conts if m.group(2) else nums).append(int(m.group(1))) + if len(nums) > ENTRY_LIMIT: + reds.append("A3 状态记录 %d 条,超硬上限 %d——按 §10 判据删除已完结批次条目" + % (len(nums), ENTRY_LIMIT)) + repeated = sorted({n for n in nums if nums.count(n) > 1}) + if repeated: + reds.append("A4 条目编号重复(并行侧写撞号):%s" + % "、".join(str(n) for n in repeated)) + + body = "\n".join(sections.get(snap_key, []) + sections.get(rec_key, []) + + sections.get(find_key(sections, "未决面"), [])) + dead = sorted({p for p in PATH_RE.findall(body) + if not os.path.exists(os.path.join(repo, p.replace("`", "")))}) + if dead: + reds.append("A5 指向中间文档的死指针 %d 处(文件已按 §11 退役,条目却还在引):%s" + % (len(dead), "、".join(dead))) + return reds, len(nums), len(snap) + + +def main(): + ap = argparse.ArgumentParser(description="active.md 体量闸") + ap.add_argument("--file", default=None, help="待审文件(默认为本仓库根目录 active.md)") + ap.add_argument("--quiet", action="store_true", help="只输出结论行") + args = ap.parse_args() + + repo = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + path = args.file or os.path.join(repo, "active.md") + if not os.path.exists(path): + print("[active.md 体量闸] 找不到文件:%s" % path) + return 1 + reds, entries, snap = audit(path, repo) + if reds: + print("[active.md 体量闸] FAIL:%d 项——状态记录 %d 条 / 快照 %d 行" % (len(reds), entries, snap)) + for r in reds: + print(" " + r) + return 1 + if not args.quiet: + print("[active.md 体量闸] PASS:状态记录 %d 条 / 快照 %d 行,编号唯一、指针全活" % (entries, snap)) + return 0 + + +if __name__ == "__main__": + try: + sys.stderr.reconfigure(encoding="utf-8", errors="replace") + sys.stdout.reconfigure(encoding="utf-8", errors="replace") + except Exception: + pass + sys.exit(main()) diff --git a/tools/run_all_gates.sh b/tools/run_all_gates.sh index 3035105b..4497acb8 100644 --- a/tools/run_all_gates.sh +++ b/tools/run_all_gates.sh @@ -111,6 +111,8 @@ fi gate "06 gdd_lint" "gdd_lint.log" "$PY" "$REPO/tools/gdd_lint.py" gate "07 doc_link" "doc_link.log" "$PY" "$REPO/tools/doc_link_audit.py" --strict gate "08 doc_term" "doc_term.log" "$PY" "$REPO/tools/doc_term_audit.py" +# ── 6b. 状态文件体量闸(active.md 只记现在:条目数/快照行数/编号/死指针四条硬上限)── +gate "08b active.md 体量" "active_state.log" "$PY" "$REPO/tools/audit_active_state.py" # ── 7. 静态扫描域 + 熵增闸 ── if [ $QUICK -eq 0 ]; then gate "09 静态扫描" "static_scan.log" bash "$GAME/tests/static_scan.sh" From 28265773aff3eec249b40d89fd1c8d0a027d4d25 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 15 Oct 2026 22:33:37 +0800 Subject: [PATCH 5/8] =?UTF-8?q?docs(=E6=94=B6=E5=8F=A3=E6=9C=BA=E5=88=B6?= =?UTF-8?q?=E6=89=B9):=20=E5=8F=B0=E8=B4=A6=20499=20=E6=9D=A1=E5=85=A5?= =?UTF-8?q?=E6=A1=A3=20+=20=E8=B1=81=E5=85=8D=E9=9D=A2=E8=A1=A5=20.qoder?= =?UTF-8?q?=EF=BC=88=E6=9C=AC=E6=9C=BA=20harness=20=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E4=B8=8D=E5=85=A5=20git=EF=BC=8C=E8=B5=B0=20worktree=20?= =?UTF-8?q?=E5=B8=A6=E4=B8=8D=E8=BF=9B=E5=8E=BB=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- active.md | 4 +++- design/dev/process-conventions.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/active.md b/active.md index 812a45fc..a95e8bb5 100644 --- a/active.md +++ b/active.md @@ -16,7 +16,7 @@ - **工程路线图**:根目录 `roadmap.md`(里程碑时间线的权威;实时状态看下方快照节) ## 当前状态快照(收口批先更新本节,再追加状态记录;≤10 行) -- **更新于**:2026-10-15(迭代 28 与规则文件审计批均已入库,本节随后由 active.md 退役清理批换代——见状态记录 498)。 +- **更新于**:2026-10-15(迭代 28 与规则文件审计批均已入库;本节由 active.md 退役清理批换代,收口机制批 499 待发令合回)。 - **最新闸态**:迭代 28 批末冒烟 1125/0、run_all 27 套、probe --click 残留 0、render golden 棋盘×3+菜单 0.00%、doc 三闸与熵增对基线零新增、static_scan S9 归零(S10 存量 125 在文件头清偿批在册);MC 零跑。 - **probe --full 有一件红**:`t17_defer_probe`「关卡画面未出现」,用户已裁为存量红、不阻合并(合并 5b958ff6);根因是探针未隔离带断点的真实存档,修复在未合入的 `gatefix-20261015` 分支。 - **迭代 28 交付**:修好启动时菜单被冒险层盖住的装配顺序,层序收敛为唯一装配合同(散落的两处 `move_child` 删除);boot 链路、九阶段生命周期、启动态菜单 golden 三组验收补全;本批新立硬规则「验收函数无变异红记录不算验收成立」,三处规约落文。 @@ -41,3 +41,5 @@ - **497(2026-10-15,规则文件审计与目录划分批收口)**:对照 Anthropic 与 OpenAI 七个真实仓库 40~330 行的实测密度重整规约——规则文件由 3 份 560 行拆为 7 份 543 行,单文件 150 行硬上限,CLAUDE.md 压到 68 行只留元信息、命令、目录划分、规范导航和一行一条红线;细则按领域归位到 process/test/doc/code/concept 五份规约,反面案例另存案例库不常驻加载。迭代 28 并行落文的变异验证硬规则按新结构重归位(细则在 test-conventions §6)。合并 81c0ee2b,worktree 与分支已清理。 - **498(2026-10-15,active.md 退役清理批)**:按 doc-conventions §10 执行一次状态退役——删除迭代 20~27 的 31 条已完结条目(判据三条齐备:批次已入库、结论已进快照、未决项不指向条目;内容可在 git 历史完整复原),状态记录由 34 条降到 3 条,回到 30 条硬上限内。快照节原为 21 条且整块自我重复(两条「更新于」、两条「批末闸全绿」、两条逐字相同的「迭代 26 交付」),去重换代为 10 条。删掉「项目当前位置」整节——该节滞后于快照与 roadmap,里程碑归 `roadmap.md`、实时进度归快照节。未决面按迭代 27/28 现行待裁与待追认重列,并把三条在途未合入分支登记在册以免被当已入库。本批零代码、零其他文档改动。 + +- **499(2026-10-15,active.md 收口机制批)**:用户裁定收口检查的触发时机不能挂在"一轮答话结束"上——旧的 Stop 钩子判的是「active.md 内容有没有变」,追加新条目就算变,结构上永远抓不到"没删旧条目";且它比对的还是已废弃路径 `production/session-state/active.md`。实测三份 harness 副本现已全部失效:Qoder 侧快照零份、ZCode 侧没接 Stop 事件、Claude 侧配置为空。改法分两层:机械层 = `tools/audit_active_state.py` 判五条膨胀签名(状态记录条目数超 30、快照行数超 10、条目编号重复、快照整行自我重复、指向 `design/qa`|`design/research` 的死指针),并入 `tools/run_all_gates.sh` 为 08b,由既有合回闸回执强制,不另立第二份闸清单;语义层 = `active-closing` 技能,规定用户问「任务是否结束」时先跑闸、按 §10 三判据逐条核对并删除、报删除清单,然后才回答。变异验证:对换代前的 34 条版本报 5 项红(连 472/477/481/494 撞号与 6 处报告死指针一并抓出),对退役后的 3 条版本报绿。钩子副本收敛为单一事实源:`.qoder/settings.json` 改指 `.zcode/hooks/worktree-guard.sh`,该脚本加 `QODER_PROJECT_DIR` 兼容并把 `.qoder/` 纳入豁免面(gitignored 配置走 worktree 带不进去),`.qoder/hooks/` 三份副本删除。守卫五例实测:主区改 tracked 文档拦、改 active.md 放行、改 .qoder 放行、主区 commit 拦、无全量回执的 merge 拦。**待发令合回 master**(分支 `active-gate-20261015`,全量闸由用户自跑)。 diff --git a/design/dev/process-conventions.md b/design/dev/process-conventions.md index ac3f5e9e..8d32b084 100644 --- a/design/dev/process-conventions.md +++ b/design/dev/process-conventions.md @@ -11,7 +11,7 @@ 1. **开工**:每批次先建独立 worktree:`git worktree add ../g-plan2-<任务名> -b <任务分支>`;所有改动与验证都在 worktree 内进行(未跟踪文件不会出现在新 worktree,需手工搬运) 2. **收尾**:迭代 loop 批次验证全绿(冒烟+场景探针)后在主工作区 `git merge --no-ff <任务分支>`,再 `git worktree remove`+删分支;合并前先看 active.md 尾部状态记录,防并行会话撞号/漏捎带;收口按 doc-conventions 第 10 节退役规则删除已完结条目。非 loop 批次默认收口不跑闸(两入口铁规),用户点名或当场问 -3. **豁免面**:仅根目录 `active.md`(会话收口)与 `.zcode/`(钩子配置)允许主工作区直改;其余一律走 worktree,主工作区 git commit 被钩子拦截 +3. **豁免面**:仅根目录 `active.md`(会话收口)、`.zcode/`(钩子与配置,入库)与 `.qoder/`(本机 harness 配置,gitignored 不入 git,走 worktree 反而带不进去)允许主工作区直改;其余一律走 worktree,主工作区 git commit 被钩子拦截 4. 本铁律由 PreToolUse 钩子 `.zcode/hooks/worktree-guard.sh` 强制兜底;钩子只约束 agent,用户手工改动不受限 ## 2. 三段开发流程 From a4fba15eac2fe846f9dec78a06b57ea0ed1460af Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 15 Oct 2026 22:35:06 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feat(=E9=97=B8=E6=94=B6=E6=95=9B=E6=89=B9?= =?UTF-8?q?=E5=9B=9B):=20=E5=90=88=E5=9B=9E=E9=97=B8=E5=85=A5=E5=BA=93?= =?UTF-8?q?=EF=BC=88worktree-guard=20=E6=8B=A6=20merge=20=E5=89=8D?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E5=85=A8=E9=87=8F=E5=9B=9E=E6=89=A7=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修自己的流程性错误:合回闸代码此前只改了主工作区的 .zcode/hooks/worktree-guard.sh, 从未提交——.zcode/ 是 worktree 铁律的豁免直改面,但豁免直改不等于豁免提交, 改完必须 commit 进库。结果是 master 上的 hook 仍是旧版(只拦 commit 不拦 merge), 闸机制实际未生效。 Bash 分支加第三路:merge/rebase/cherry-pick 进 master 前按目标分支反查 worktree 回执(git worktree list --porcelain 定位,兜底扫 sibling 目录), 校验三态——回执 commit == 分支 tip、非 --quick 档、无新增红项;任一不满足 exit 2。 八态实测:匹配回执放行 / commit 错拦 / quick 档拦 / 含红项拦 / 无回执拦 / worktree 内 commit 放行 / 只读命令放行 / rebase 拦。 --- .zcode/hooks/worktree-guard.sh | 100 +++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 6 deletions(-) diff --git a/.zcode/hooks/worktree-guard.sh b/.zcode/hooks/worktree-guard.sh index 60f0180e..bc7b5aac 100644 --- a/.zcode/hooks/worktree-guard.sh +++ b/.zcode/hooks/worktree-guard.sh @@ -1,6 +1,8 @@ #!/usr/bin/env bash -# worktree 铁律守卫(PreToolUse,2026-09-19 台账 87 用户立规) -# 拦两路:①Edit/Write 类落在主工作区(白名单外)且主工作区检出 master/main ②Bash 在主工作区 git commit +# worktree 铁律守卫(PreToolUse,2026-09-19 台账 87 用户立规;2026-10-15 扩合回闸) +# 拦两路:①Edit/Write 类落在主工作区(白名单外)且主工作区检出 master/main +# ②Bash 在主工作区 git commit +# ③Bash 在主工作区 git merge/rebase/cherry-pick 进 master 且无 tools/run_all_gates.sh 全量回执 # 退出码 2 = 拦截(stderr 回传模型);0 = 放行;任何解析异常一律放行(守卫是兜底,不能挡死会话收口) proj="${ZCODE_PROJECT_DIR:-$PWD}" tmp="$(mktemp)" @@ -71,6 +73,7 @@ elif tool == "Bash": cmd = ti.get("command", "") or "" toks = cmd.split() has_commit = False + has_merge = False for i, t in enumerate(toks): if t.rstrip(';') != 'git': continue @@ -80,6 +83,9 @@ elif tool == "Bash": if u == "commit": has_commit = True break + if u in ("merge", "rebase", "cherry-pick"): + has_merge = True + break if u.startswith("-"): if u in ("-C", "--git-dir", "-c") and j + 1 < len(toks): j += 2 @@ -87,8 +93,6 @@ elif tool == "Bash": j += 1 continue break - if not has_commit: - sys.exit(0) # 主工作区判定:cwd 在内,或命令文本里显式指到主工作区路径(不含 worktree 兄弟目录) norm = cmd.replace("\\", "/").lower() ref_main = re.search(r"/d/code/g-plan2(?![\w-])", norm) or re.search(r"d:/code/g-plan2(?![\w-])", norm) @@ -97,13 +101,97 @@ elif tool == "Bash": # 命令文本以路径形态(斜杠前缀)显式指向兄弟 worktree 且不含主区路径时放行——显式主区 # 路径引用优先走下方拦截判定(ref_main 命中即不豁免,防「主区提交夹带 worktree 提及」绕行)。 ref_wt = re.search(r"/g-plan2-[\w-]+", norm) - if ref_wt and not ref_main: + sibling = bool(ref_wt) and not ref_main + on_trunk = trunk_branch(proj) in TRUNK + in_main = (in_dir(cwd, proj) or bool(ref_main)) and on_trunk + if not in_main or sibling: sys.exit(0) - if (in_dir(cwd, proj) or ref_main) and trunk_branch(proj) in TRUNK: + if has_commit: sys.stderr.write( "[worktree 铁律] 主工作区(master)禁止直接 git commit——提交在任务 worktree 分支上完成," "收尾在主工作区 git merge --no-ff 合回 master。\n") sys.exit(2) + # 合回闸(2026-10-15 用户令「迭代完成前必须全量跑一遍所有测试」):merge/rebase/cherry-pick + # 进 master 前校验 tools/run_all_gates.sh 的回执——回执缺失、quick 模式、或含红项即拦。 + # 起因:iter27 台账只记 probe --click 未记 --full,t17_defer_probe 红了整个迭代无人发现, + # 根因是闸清单散落三份文档彼此不一致且无机器校验(清单唯一事实源已收敛为 run_all_gates.sh)。 + if has_merge: + # 回执在「跑闸的那个 worktree」里(闸在 worktree 跑、回执随 worktree 落地), + # 主工作区自己那份是上一次合回前的旧件。故按 merge 的目标分支反查 worktree 路径, + # 找不到就在所有 sibling worktree 里找「回执 commit == 分支 tip」的那一份。 + def git_out(*args, **kw): + return subprocess.run(["git", "-C", proj] + list(args), + capture_output=True, text=True, timeout=kw.get("timeout", 8)).stdout.strip() + + merge_branch = None + for t in toks: + u = t.rstrip(';') + if u and not u.startswith("-") and u not in ("git", "merge", "rebase", "cherry-pick"): + merge_branch = u + break + tip = git_out("rev-parse", merge_branch) if merge_branch else "" + if not tip: + tip = git_out("rev-parse", "HEAD") + + cands = [] + if merge_branch: + try: + wl = git_out("worktree", "list", "--porcelain") + blocks = [b for b in wl.split("\n\n") if b.strip()] + for b in blocks: + if ("branch refs/heads/%s" % merge_branch) in b: + head_line = [l for l in b.split("\n") if l.startswith("worktree ")] + if head_line: + cands.append(os.path.abspath(winpath(head_line[0][9:]))) + except Exception: + pass + # 兜底:主区 + 所有 sibling worktree + cands.append(proj) + parent = os.path.dirname(proj) + try: + for name in os.listdir(parent): + p = os.path.join(parent, name) + if os.path.isdir(os.path.join(p, ".git")) or os.path.isfile(os.path.join(p, ".git")): + cands.append(os.path.abspath(p)) + except Exception: + pass + + receipt = None + for base in cands: + p = os.path.join(base, "game", "tests", ".gates", "receipt.json") + if not os.path.exists(p): + continue + try: + import json + with open(p, encoding="utf-8") as f: + r = json.load(f) + except Exception: + continue + # 只认「回执 commit == 将要合入的分支 tip」的那一份 + if r.get("commit") == tip: + receipt = (base, r) + break + why = None + if receipt is None: + found = any(os.path.exists(os.path.join(b, "game", "tests", ".gates", "receipt.json")) + for b in cands) + why = ("无与分支 %s(tip %s)匹配的回执%s" + % (merge_branch or "?", tip[:8], + "(worktree 内存在回执但 commit 对不上=闸跑完后代码又变了)" if found else "")) + else: + base, r = receipt + if r.get("quick_mode"): + why = "回执是 --quick 模式(跳过渲染闸/静态扫描),收口出库必须跑全量" + elif not r.get("all_green"): + reds = [g["name"] for g in r.get("gates", []) if g.get("exit") != 0] + why = "回执含新增红项:" + ("、".join(reds) if reds else "见 receipt.json") + if why: + sys.stderr.write( + "[合回闸] 拦截 %s 进 master——%s。\n" + "在任务 worktree 内跑全量闸:tools/run_all_gates.sh(不带 --quick)," + "跑完回执自动写入该 worktree 的 game/tests/.gates/receipt.json,再合。\n" + % (cmd.split()[0], why)) + sys.exit(2) sys.exit(0) PY From 99a09ad6a0e05b873e593962feceb1482c645913 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 15 Oct 2026 22:54:52 +0800 Subject: [PATCH 7/8] =?UTF-8?q?docs(=E6=94=B6=E5=8F=A3=E6=9C=BA=E5=88=B6?= =?UTF-8?q?=E6=89=B9):=20=E5=8F=B0=E8=B4=A6=E6=8C=89=E5=90=88=E5=B9=B6?= =?UTF-8?q?=E7=8E=B0=E7=8A=B6=E6=A0=A1=E6=AD=A3=E2=80=94=E2=80=94499=20?= =?UTF-8?q?=E5=8E=BB=E6=8E=89=E3=80=8C=E5=BE=85=E5=8F=91=E4=BB=A4=E5=90=88?= =?UTF-8?q?=E5=9B=9E=E3=80=8D=E5=A4=B1=E7=9C=9F=E6=8E=AA=E8=BE=9E=E5=B9=B6?= =?UTF-8?q?=E8=A1=A5=E8=AE=B0=20hooks=20=E4=B8=8D=E9=9A=8F=E4=BB=93?= =?UTF-8?q?=E5=BA=93=E4=BC=A0=E6=92=AD=EF=BC=88Qoder=20=E4=BE=A7=E6=B4=BB?= =?UTF-8?q?=E4=BD=93=E6=8E=A2=E9=92=88=E6=9C=AA=E8=A2=AB=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E3=80=81=E6=88=90=E5=9B=A0=E5=BE=85=E8=AF=8A=E6=96=AD=EF=BC=8C?= =?UTF-8?q?Claude=20=E4=BE=A7=E9=85=8D=E7=BD=AE=E4=B8=BA=E7=A9=BA=EF=BC=8C?= =?UTF-8?q?=E4=BB=85=20ZCode=20=E5=9C=A8=E8=B7=91=EF=BC=89=EF=BC=9B?= =?UTF-8?q?=E5=BF=AB=E7=85=A7=E4=B8=8E=E6=9C=AA=E5=86=B3=E9=9D=A2=E6=8C=89?= =?UTF-8?q?=20gatefix-20261015=E3=80=81ci-removal-20261015=20=E5=B7=B2?= =?UTF-8?q?=E5=90=88=E5=85=A5=20master=20=E6=8D=A2=E4=BB=A3=EF=BC=8Ct17=20?= =?UTF-8?q?=E5=AD=98=E9=87=8F=E7=BA=A2=E6=94=B9=E8=AE=B0=E3=80=8C=E6=9B=BE?= =?UTF-8?q?=E6=9C=89=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- active.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/active.md b/active.md index a95e8bb5..cc4eb592 100644 --- a/active.md +++ b/active.md @@ -16,9 +16,9 @@ - **工程路线图**:根目录 `roadmap.md`(里程碑时间线的权威;实时状态看下方快照节) ## 当前状态快照(收口批先更新本节,再追加状态记录;≤10 行) -- **更新于**:2026-10-15(迭代 28 与规则文件审计批均已入库;本节由 active.md 退役清理批换代,收口机制批 499 待发令合回)。 +- **更新于**:2026-10-15(迭代 28 与规则文件审计批均已入库;本节由 active.md 退役清理批换代,收口机制批 499 随本合并入库)。 - **最新闸态**:迭代 28 批末冒烟 1125/0、run_all 27 套、probe --click 残留 0、render golden 棋盘×3+菜单 0.00%、doc 三闸与熵增对基线零新增、static_scan S9 归零(S10 存量 125 在文件头清偿批在册);MC 零跑。 -- **probe --full 有一件红**:`t17_defer_probe`「关卡画面未出现」,用户已裁为存量红、不阻合并(合并 5b958ff6);根因是探针未隔离带断点的真实存档,修复在未合入的 `gatefix-20261015` 分支。 +- **probe --full 曾有一件红**:`t17_defer_probe`「关卡画面未出现」,用户已裁为存量红、不阻合并(合并 5b958ff6);根因是探针未隔离带断点的真实存档,该修复已随 `gatefix-20261015` 合入 master(合并 de8d28b6)。 - **迭代 28 交付**:修好启动时菜单被冒险层盖住的装配顺序,层序收敛为唯一装配合同(散落的两处 `move_child` 删除);boot 链路、九阶段生命周期、启动态菜单 golden 三组验收补全;本批新立硬规则「验收函数无变异红记录不算验收成立」,三处规约落文。 - **迭代 27 交付**:三屏壳场景与局态物化、结算五段拆分、RunLedger 单类持四账、模态编排类、类型闸、死代码退役,编排器由 1725 行降到 1325 行。 - **规约体系现状**:规则文件按领域拆为 7 份、单文件上限 150 行,CLAUDE.md 只留元信息、命令、目录、规范导航与一行一条红线;动手前按规范导航表查对应细则。 @@ -31,7 +31,7 @@ - 待用户裁决(06 在册):迭代 27 GDD 反哺两条;迭代 28 GDD 反哺三条;美术审计两项 P0(art-bible 死样张指涉、主角像素管线重产);去毒残留词是否清扫(「魔法道具」约 30 处、「罕见」约 18 处);喂雷流 R5 甲重启条件回落文;「通关」与「通过第 N 关」全库口径统一(约 273 处)。 - 待用户追认:迭代 27 代拍板十五项、迭代 28 代拍板十三项(含四条白名单外),清单在两份现行实现报告的追认单节(`design/qa/iter27-实现报告-2026-10-14.md`、`design/qa/iter28-实现报告-2026-10-15.md`);req-card 技能的 WorkBuddy 与 ZCode 两份副本是否取齐待裁。 - 待发令:M4 数值批(迭代 29+);迭代 27/28 预留追加卡;黑话清扫第二波(GDD 正文流程动词族约三千处);规则文件编写 skill(按 497 批工作流提炼)。 -- 在途分支未合入 master(读现状时勿当已入库):`gatefix-20261015`(验收闸唯一入口+t17 探针隔离修复+合回闸回执强制,领先 2 笔)、`doc-adr-fixes-20261014`(registry 改号与契约描述同步,领先 5 笔)、`art-standee-20261006`(artwork 独立仓 dry-run 报告,领先 5 笔)。 +- 在途分支未合入 master(读现状时勿当已入库):`doc-adr-fixes-20261014`(registry 改号与契约描述同步,领先 5 笔)、`art-standee-20261006`(artwork 独立仓 dry-run 报告+立绘定档,领先 5 笔)、`stc-norm-20261015`(GDD 用语规范批,领先 4 笔);`gatefix-20261015` 与 `ci-removal-20261015` 已合入 master。 - 在册观察(06 登记,非阻塞):迭代 27 卡片义务补登两项——长函数余量 17 个中的装配/校验函数、lambda 连接防回归。 ## 状态记录(滚动窗口:仅当前迭代;退役规则见 doc-conventions §10) @@ -42,4 +42,4 @@ - **498(2026-10-15,active.md 退役清理批)**:按 doc-conventions §10 执行一次状态退役——删除迭代 20~27 的 31 条已完结条目(判据三条齐备:批次已入库、结论已进快照、未决项不指向条目;内容可在 git 历史完整复原),状态记录由 34 条降到 3 条,回到 30 条硬上限内。快照节原为 21 条且整块自我重复(两条「更新于」、两条「批末闸全绿」、两条逐字相同的「迭代 26 交付」),去重换代为 10 条。删掉「项目当前位置」整节——该节滞后于快照与 roadmap,里程碑归 `roadmap.md`、实时进度归快照节。未决面按迭代 27/28 现行待裁与待追认重列,并把三条在途未合入分支登记在册以免被当已入库。本批零代码、零其他文档改动。 -- **499(2026-10-15,active.md 收口机制批)**:用户裁定收口检查的触发时机不能挂在"一轮答话结束"上——旧的 Stop 钩子判的是「active.md 内容有没有变」,追加新条目就算变,结构上永远抓不到"没删旧条目";且它比对的还是已废弃路径 `production/session-state/active.md`。实测三份 harness 副本现已全部失效:Qoder 侧快照零份、ZCode 侧没接 Stop 事件、Claude 侧配置为空。改法分两层:机械层 = `tools/audit_active_state.py` 判五条膨胀签名(状态记录条目数超 30、快照行数超 10、条目编号重复、快照整行自我重复、指向 `design/qa`|`design/research` 的死指针),并入 `tools/run_all_gates.sh` 为 08b,由既有合回闸回执强制,不另立第二份闸清单;语义层 = `active-closing` 技能,规定用户问「任务是否结束」时先跑闸、按 §10 三判据逐条核对并删除、报删除清单,然后才回答。变异验证:对换代前的 34 条版本报 5 项红(连 472/477/481/494 撞号与 6 处报告死指针一并抓出),对退役后的 3 条版本报绿。钩子副本收敛为单一事实源:`.qoder/settings.json` 改指 `.zcode/hooks/worktree-guard.sh`,该脚本加 `QODER_PROJECT_DIR` 兼容并把 `.qoder/` 纳入豁免面(gitignored 配置走 worktree 带不进去),`.qoder/hooks/` 三份副本删除。守卫五例实测:主区改 tracked 文档拦、改 active.md 放行、改 .qoder 放行、主区 commit 拦、无全量回执的 merge 拦。**待发令合回 master**(分支 `active-gate-20261015`,全量闸由用户自跑)。 +- **499(2026-10-15,active.md 收口机制批)**:用户裁定收口检查的触发时机不能挂在"一轮答话结束"上——旧的 Stop 钩子判的是「active.md 内容有没有变」,追加新条目就算变,结构上永远抓不到"没删旧条目";且它比对的还是已废弃路径 `production/session-state/active.md`。实测三份 harness 副本现已全部失效:Qoder 侧快照零份、ZCode 侧没接 Stop 事件、Claude 侧配置为空。改法分两层:机械层 = `tools/audit_active_state.py` 判五条膨胀签名(状态记录条目数超 30、快照行数超 10、条目编号重复、快照整行自我重复、指向 `design/qa`|`design/research` 的死指针),并入 `tools/run_all_gates.sh` 为 08b,由既有合回闸回执强制,不另立第二份闸清单;语义层 = `active-closing` 技能,规定用户问「任务是否结束」时先跑闸、按 §10 三判据逐条核对并删除、报删除清单,然后才回答。变异验证:对换代前的 34 条版本报 5 项红(连 472/477/481/494 撞号与 6 处报告死指针一并抓出),对退役后的 3 条版本报绿。钩子副本收敛为单一事实源:`.qoder/settings.json` 改指 `.zcode/hooks/worktree-guard.sh`,该脚本加 `QODER_PROJECT_DIR` 兼容并把 `.qoder/` 纳入豁免面(gitignored 配置走 worktree 带不进去),`.qoder/hooks/` 三份副本删除。脚本层守卫五例实测(stdin 直喂):主区改 tracked 文档拦、改 active.md 放行、改 .qoder 放行、主区 commit 拦、无全量回执的 merge 拦。**待核**:hooks 属各 harness 私有配置、不随仓库传播——ZCode 侧确认在跑,Qoder 侧本会话活体探针未被执行(`.claude/settings.json` 仍为空),故拦截力目前只在 ZCode 生效,成因待诊断。全量闸由用户自跑,本批按令合回 master(分支 `active-gate-20261015`,合并见提交史)。 From f22adb55645e21224b894c10dd768fac28eeaf50 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 15 Oct 2026 23:02:55 +0800 Subject: [PATCH 8/8] =?UTF-8?q?docs:=20=E8=90=BD=E5=BA=93=2010-15=20?= =?UTF-8?q?=E6=97=A5=E9=97=B4=E6=9C=AA=E6=8F=90=E4=BA=A4=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E6=94=B9=E5=8A=A8=E2=80=94=E2=80=94architecture.md=20v1.5?= =?UTF-8?q?=EF=BC=88=E6=B5=8B=E8=AF=95=E4=B8=8E=E8=B4=A8=E9=87=8F=E5=9F=9F?= =?UTF-8?q?=E8=8A=82=E8=BF=81=E5=85=A5+=E4=B8=AD=E6=96=87=E5=8C=96+?= =?UTF-8?q?=E7=8E=B0=E7=8A=B6=E5=90=8C=E6=AD=A5=EF=BC=89/=20CLAUDE.md=20?= =?UTF-8?q?=E8=A7=84=E7=BA=A6=E5=AF=BC=E8=88=AA=E8=A1=A8=E5=8E=BB=20adr=20?= =?UTF-8?q?=E6=8C=87=E9=92=88=EF=BC=88=E5=90=8C=20diff=20=E5=88=A0?= =?UTF-8?q?=E4=BA=86=20RNG=20=E5=8D=95=E7=82=B9=E7=BA=A2=E7=BA=BF=E4=B8=80?= =?UTF-8?q?=E8=A1=8C=EF=BC=8C=E7=96=91=E4=BC=BC=E8=AF=AF=E5=88=A0=EF=BC=8C?= =?UTF-8?q?=E7=94=B1=20ADR=20=E6=B8=85=E9=99=A4=E6=89=B9=E5=A4=84=E7=90=86?= =?UTF-8?q?=EF=BC=89/=2002-=E7=B3=BB=E7=BB=9F=E6=B8=85=E5=8D=95=E8=A1=A5?= =?UTF-8?q?=2008-Alpha=20=E7=99=BB=E8=AE=B0=E8=A1=8C=EF=BC=8810-13=20?= =?UTF-8?q?=E9=81=97=E7=95=99=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 5 +- design/dev/architecture/architecture.md | 212 +++++++++++++++--------- design/gdd/02-系统清单.md | 2 + 3 files changed, 140 insertions(+), 79 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 5271cdbf..b7574ee2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -27,7 +27,7 @@ - `design/gdd/` — 现行设计文档树(根索引 `02-系统清单.md`,文档增删必须同步;`gdd/ux/` 战斗画面与交互规格) - `design/registry/` — 跨系统事实登记(entities.yaml 术语与已锁数值、architecture.yaml 架构登记) - `design/art/` — 美术纯文档(圣经/清单/提示词卡 + references/);评估调研归 `design/research/`;不放图片 -- `design/dev/` — 工程规范(五份规约 + architecture(ADR) + engine-reference) +- `design/dev/` — 工程规范(五份规约 + architecture + engine-reference) - `design/qa/` — 验证报告 + QA 呈现产物图;`design/research/` — 调研/提案/评估/历史验收 - `artwork/` — 在途图像素材唯一工作区(文档归文档/在途图归一处/终稿归游戏);整目录不入 git(.gitignore 强制),收口归档 `archive/` - `game/assets/art/` — 已验收终稿(入包被游戏加载);`game/` — 游戏工程本体(代码 + smoke/ 冒烟 + tests/ 单元集成) @@ -45,7 +45,7 @@ | 写文档 / 改文档前 | `design/dev/doc-conventions.md`——白话写作 / 载体分工 / 用语 / 结构骨架 / 会话记录与生命周期 | | 概念切分与互链 | `design/dev/concept-conventions.md`——概念封装 / 跨文档引用 / 归档与事实源 | | 系统设计 / 增删文档 | `design/gdd/02-系统清单.md`——根索引 + 中文规范名↔英文代号对照 | -| 架构与决策记录 | `design/dev/architecture/architecture.md` + 同目录 `adr-*.md` | +| 架构 | `design/dev/architecture/architecture.md` | | 术语、已锁数值 | `design/registry/entities.yaml`——仅 owner 文档可修订,冲突须显式提出 | | 会话进度 / 路线图 | 根 `active.md`(状态文件:只记现在,每行当下为真;快照+未决面+滚动条目)· 根 `roadmap.md` | @@ -63,7 +63,6 @@ - 真人检测只登记不阻塞——登记进 07 清单/实现报告即完成义务,禁以等目检为停工理由或收口前置 - 文件头 = `##` 文档注释 ≤8 行白名单制(code-conventions §1.4.1;写法权威 = Google Python Style Guide §3.8 + PEP 257;机器闸 tools/audit_file_headers.py) - 数值单一事实源——玩法数值只存 `data/tables/`(.tres)经 ConfigDB 单点读取;禁数值字面量与自建 `load()` 表路径 -- RNG 单点——禁 `randomize()`/自建 RandomNumberGenerator,随机只经 `RngService` 统一流(ADR-0007) - Core 层零 UI 依赖——完整战斗必须可 `--headless --script` 跑通;fail-fast——数据校验错误一律致命中止,无软回退 - spec-AC 一致性——规约与验收标准不得在同一输入上给出不同答案;评审隔离——`/design-review` 必须独立会话跑(与 `/design-system` 隔离) - 像素结构件——先抄后造、验收写成像素级判据、±1px 坐标推导(process-conventions 第 7 节) diff --git a/design/dev/architecture/architecture.md b/design/dev/architecture/architecture.md index 596a6676..eb0cccb8 100644 --- a/design/dev/architecture/architecture.md +++ b/design/dev/architecture/architecture.md @@ -1,24 +1,24 @@ -# Dungeon Sweeper — Master Architecture +# Dungeon Sweeper — 总体架构文档 -## Document Status +## 文档状态 -- Version: 1.3 -- Last Updated: 2026-09-26(战斗舞台 Node2D 迁移 Phase B:D1 层表 BattleStageView 形态注记——引 ADR-0006;Phase A 注记 2026-09-23) -- Engine: Godot 4.7.2-stable(GDScript 单语言;2026-09-07 锁定) -- Review Mode: solo(`production/review-mode.txt`,2026-09-12 用户拍板——TD/LP 门禁按 solo 跳过,用户授权架构产出自主推进、迭代期回调) -- GDDs Covered: game-concept · game-pillars · systems-index · d2-data-config · a3-action-economy · a4-terrain-variation · b3-status-effect · a1-board-generation · a2-minesweeper-rules · b2-enemy-system · b4-reward-item-economy · b1-settlement(12 份;A5/C1–C4/B5/D3–D6 未设计,按 systems-index 依赖分层预留) -- ADRs Referenced: 无(0 份现存)——本文档 Phase 5/6 列出的实现期裁决项即为首批 ADR 候选 -- Implementation Evidence: 垂直切片 `game/`(2026-09-10 起,冒烟 88/88、三 UI 探针 PASS)——本文档的分层/所有权/数据流均经切片实现验证,非纯纸面设计 -- Technical Director Sign-Off: 2026-09-12 — APPROVED WITH CONDITIONS(条件:Required ADRs 于正式工程骨架搭建前定稿;`.claude/docs/director-gates.md` 缺失已登记技术债) -- Lead Programmer Feasibility: SKIPPED — Solo mode +- 版本:1.5 +- 最近更新:2026-10-15(①新增「测试与质量域」节——测试域事实源自 ADR-0004 迁入承接;②全文标题/状态键/表头中文化;③现状同步:覆盖 GDD 改指现行中文域结构、现存 ADR 七份、实现实证改为完整游戏开发版本、四处失效路径订正) +- 引擎:Godot 4.7.2-stable(GDScript 单语言;2026-09-07 锁定) +- 评审模式:solo(`review-mode.txt`,2026-09-12 用户拍板——TD/LP 门禁按 solo 跳过,用户授权架构产出自主推进、迭代期回调) +- 覆盖 GDD:现行全集——`design/gdd/` 顶层 00–08 共 9 件 + `systems/` 五域 25 件(排雷循环 4 / 战斗循环 5 / 冒险循环 5 / 跨局循环 5 / 表现与支撑 6)+ `ux/` 8 件;原英文命名 12 份系统 GDD 已全部迁入中文域目录,原「未设计」预留(A5 扫雷秘宝 / C1–C4 / B5 / D3–D6)均已立项成文 +- 引用 ADR:7 份现存(adr-0001–0007,`design/dev/architecture/`)——ADR=变更记录留档、非事实源;测试域事实源见本文「测试与质量域」节 +- 实现实证:`game/`(2026-09-10 起开发,**现为完整游戏开发版本,已非垂直切片**;迭代 28 已入库合并——冒烟 1125/0、单元 27 套件、本地五闸在役)——本文档的分层/所有权/数据流均经实现验证,非纯纸面设计 +- 技术总监签核:2026-09-12 — 有条件通过(条件:应立 ADR 于正式工程骨架搭建前定稿;`.claude/docs/director-gates.md` 缺失已登记技术债) +- 主程序可行性:跳过 — solo 模式 --- -## Engine Knowledge Gap Summary +## 引擎知识缺口摘要 -- **风险等级:MEDIUM**(2026-09-12 `/setup-engine refresh` 后由 HIGH 降级)。4.5→4.7 官方迁移指南已逐条核实并入 `docs/engine-reference/godot/breaking-changes.md` 与 `deprecated-apis.md`;**结论:无一条破坏 GDD 已锁架构契约**(autoload 体系 / .tres 单一事实源 / Callable 信号 / int64 二补数 / headless SceneTree 协议均不受影响)。 +- **风险等级:MEDIUM**(2026-09-12 `/setup-engine refresh` 后由 HIGH 降级)。4.5→4.7 官方迁移指南已逐条核实并入 `design/dev/engine-reference/godot/breaking-changes.md` 与 `deprecated-apis.md`;**结论:无一条破坏 GDD 已锁架构契约**(autoload 体系 / .tres 单一事实源 / Callable 信号 / int64 二补数 / headless SceneTree 协议均不受影响)。 - 写码纪律不变:不确定的 API 一律查 `docs.godotengine.org/en/4.7/` 核实后再用;4.8(dev 阶段)稳定版发布后跑 `/setup-engine refresh`。 -- 三类必须入编码纪律的引擎事实(详见 `docs/engine-reference/godot/current-best-practices.md`): +- 三类必须入编码纪律的引擎事实(详见 `design/dev/engine-reference/godot/current-best-practices.md`): 1. **GDScript 4.7 两条语义变化**:打包数组元素赋值不再触发属性 setter;类型化返回的方法覆盖必须显式 `return`。 2. **新项目默认值已变**:stretch mode `canvas_items` / aspect `expand`(4.7);Windows 渲染驱动 D3D12(4.6,仅 Forward+ 线)——创建 project.godot 后逐项核对。 3. `Resource.duplicate(true)` 深复制不再覆盖外部子资源——D2 表资源复制语义注意。 @@ -26,103 +26,105 @@ --- -## System Layer Map +## 系统分层图 -20 系统按 systems-index 依赖分层表(systems-design 门禁已评审)映射到标准五层。切片实现已验证该分层(core/ 纯逻辑零 UI 依赖 headless 可跑、presentation/ 组合根模式)。 +20 系统按 `design/gdd/02-系统清单.md` 依赖分层表映射到标准五层。实现已验证该分层(core/ 纯逻辑零 UI 依赖 headless 可跑、presentation/ 组合根模式)。 ``` ┌────────────────────────────────────────────────────────────┐ -│ PRESENTATION LAYER │ -│ D1 HUD 与界面框架 (MVP) · B5 战斗表现 (切片后) │ -│ D4 音频 (Alpha) · D5 教学引导 (Alpha) │ +│ 呈现层 │ +│ D1 HUD 与界面框架 (MVP) · B5 战斗表现 │ +│ D4 音频 (Beta) · D5 教学引导 (Beta) │ ├────────────────────────────────────────────────────────────┤ -│ FEATURE LAYER │ -│ B1 战斗结算编排 (MVP) · C1 关卡节点地图 (切片已含 lite) │ +│ 功能层 │ +│ B1 战斗结算编排 (MVP) · C1 关卡节点地图 (lite 已实装) │ │ C2 冒险结构 · C3 难度曲线 · C4 元进度 (Alpha) │ ├────────────────────────────────────────────────────────────┤ -│ CORE LAYER │ +│ 核心层 │ │ A1 扫雷棋盘生成 · A2 排雷玩法规则 · B2 敌人系统 │ -│ B4 地图战斗资源 · A5 扫雷秘宝 (垂直切片) │ +│ B4 地图战斗资源 · A5 扫雷秘宝 │ ├────────────────────────────────────────────────────────────┤ -│ FOUNDATION LAYER │ +│ 基础层 │ │ D2 数据配置与数值表 · A3 行动经济 · A4 地形变异 │ │ B3 增益/状态系统 · D3 存档序列化 (Alpha) · D6 设置/本地化│ ├────────────────────────────────────────────────────────────┤ -│ PLATFORM LAYER │ +│ 平台层 │ │ Godot 4.7.2 引擎 API 面(GDScript / Resource / │ │ SceneTree / Control / InputEvent)——无游戏系统 │ └────────────────────────────────────────────────────────────┘ ``` +> 层名对照:基础层=Foundation、核心层=Core、功能层=Feature、呈现层=Presentation、平台层=Platform——本文一律用中文名;跨文档与代码目录仍见英文名(`game/core/`、`game/presentation/` 等目录名不改)。 + | 系统 | 层 | 里程碑 | headless 约束 | 引擎风险域 | |---|---|---|---|---| -| D2 数据配置 | Foundation | MVP | ✅ 完整可跑 | LOW(Resource/.tres 基线稳定) | -| A3 行动经济 | Foundation | MVP | ✅ 完整可跑 | LOW(纯逻辑) | -| A4 地形变异 | Foundation | MVP | ✅ 完整可跑 | LOW(纯逻辑) | -| B3 状态系统 | Foundation | MVP | ✅ 完整可跑 | LOW(RefCounted 纯逻辑) | -| A1 棋盘生成 | Core | MVP | ✅ 完整可跑 | LOW(纯逻辑;性能姿态归 ADR-0005) | -| A2 排雷规则 | Core | MVP | ✅ 完整可跑 | LOW(零表读取零 UI) | -| B2 敌人系统 | Core | MVP | ✅ 完整可跑 | LOW(纯逻辑) | -| B4 地图战斗资源 | Core | MVP | ✅ 完整可跑 | LOW(纯逻辑) | -| B1 战斗结算编排 | Feature | MVP | ✅ 完整可跑(禁 await) | LOW(纯逻辑;事件载体归 ADR-0001) | -| C1 关卡节点地图 | Feature | 垂直切片(lite 已入切片) | ✅(切片 level_runner 先例) | LOW | -| C2 冒险结构 | Feature | 垂直切片 | ✅ | LOW | -| C3 难度曲线 | Feature | 垂直切片 | ✅ | LOW | -| C4 元进度 | Feature | Alpha | ✅ | LOW | -| D1 HUD | Presentation | MVP | ❌(UI 层——场景级探针测试承载) | **MEDIUM**(Control/Input/文本域) | -| B5 战斗表现 | Presentation | 垂直切片 | ❌ | **MEDIUM**(Animation/Tween/渲染) | -| D4 音频 / D5 教学 | Presentation | Alpha | 部分 | LOW-MEDIUM | -| D3 存档序列化 | Foundation | Alpha | ✅ | LOW | -| D6 设置/本地化 | Foundation | 完整愿景 | ✅ | LOW | +| D2 数据配置 | 基础层 | MVP | ✅ 完整可跑 | LOW(Resource/.tres 基线稳定) | +| A3 行动经济 | 基础层 | MVP | ✅ 完整可跑 | LOW(纯逻辑) | +| A4 地形变异 | 基础层 | MVP | ✅ 完整可跑 | LOW(纯逻辑) | +| B3 状态系统 | 基础层 | MVP | ✅ 完整可跑 | LOW(RefCounted 纯逻辑) | +| A1 棋盘生成 | 核心层 | MVP | ✅ 完整可跑 | LOW(纯逻辑;性能姿态归 ADR-0005) | +| A2 排雷规则 | 核心层 | MVP | ✅ 完整可跑 | LOW(零表读取零 UI) | +| B2 敌人系统 | 核心层 | MVP | ✅ 完整可跑 | LOW(纯逻辑) | +| B4 地图战斗资源 | 核心层 | MVP | ✅ 完整可跑 | LOW(纯逻辑) | +| B1 战斗结算编排 | 功能层 | MVP | ✅ 完整可跑(禁 await) | LOW(纯逻辑;事件载体归 ADR-0001) | +| C1 关卡节点地图 | 功能层 | MVP(切片期实装) | ✅(切片 level_runner 先例) | LOW | +| C2 冒险结构 | 功能层 | MVP(切片期实装) | ✅ | LOW | +| C3 难度曲线 | 功能层 | MVP(切片期实装) | ✅ | LOW | +| C4 元进度 | 功能层 | Alpha | ✅ | LOW | +| D1 HUD | 呈现层 | MVP | ❌(UI 层——场景级探针测试承载) | **MEDIUM**(Control/Input/文本域) | +| B5 战斗表现 | 呈现层 | 切片后立项(未实装,前置战斗表现美术测试) | ❌ | **MEDIUM**(Animation/Tween/渲染) | +| D4 音频 / D5 教学 | 呈现层 | Beta(2026-10-13 Alpha 版本标准裁:与游戏内容无关者一律排 Beta) | 部分 | LOW-MEDIUM | +| D3 存档序列化 | 基础层 | Alpha | ✅ | LOW | +| D6 设置/本地化 | 基础层 | 完整愿景 | ✅ | LOW | -**MVP 关键路径**(切片已验证):D2 → A3/A4/B3 → A1 → A2 → B2/B4 → B1 → D1-lite。 +**MVP 关键路径**(实现已验证):D2 → A3/A4/B3 → A1 → A2 → B2/B4 → B1 → D1-lite。 **依赖分层与唯一回边**:A2 只外发三事件(cell_revealed / flag_judged / round_end),B4/B1 订阅后回调——A2 不依赖任何下游(TD-SYSTEM-BOUNDARY 裁决,全项目唯一允许回边)。 --- -## Module Ownership +## 模块归属 -> 命名遵循 `docs/code-conventions.md`:领域命名、禁 ID 前缀、头注溯源行(实现 GDD:design/gdd/…)。切片已按此规范完成领域命名批。 +> 命名遵循 `design/dev/code-conventions.md`:领域命名、禁 ID 前缀、头注溯源行(实现 GDD:design/gdd/…)。切片已按此规范完成领域命名批。 -### Foundation 层 +### 基础层 -| 模块 | Owns(独占) | Exposes | Consumes | 引擎 API | +| 模块 | 独占职责 | 对外暴露 | 消费依赖 | 引擎 API | |---|---|---|---|---| -| **ConfigDB**(autoload,D2) | 全部玩法数值表(`data/tables/*.tres` + `data/schemas/*.gd`);SCHEMA_VERSION;加载/校验/override/诊断状态机 | 类型化属性读取;`load_tables(root, collect_only)`;`resolve()`(R1 floor);debug override;`set_reload_gate()`;诊断收集器 | 无(Foundation 顶点) | Resource/.tres 加载、autoload 生命周期——LOW | +| **ConfigDB**(autoload,D2) | 全部玩法数值表(`data/tables/*.tres` + `data/schemas/*.gd`);SCHEMA_VERSION;加载/校验/override/诊断状态机 | 类型化属性读取;`load_tables(root, collect_only)`;`resolve()`(R1 floor);debug override;`set_reload_gate()`;诊断收集器 | 无(基础层顶点) | Resource/.tres 加载、autoload 生命周期——LOW | | **RngService**(autoload,D2) | master_seed、各流 scope 计数器(封闭流:board_gen / reward_roll;增流走 P1 评审) | `set_master_seed()`(唯一调用方 C2);`open_stream(stream)` 有状态门面;`derive_at(stream, scope)` 纯函数;只读计数器 | ConfigDB(无) | 无——纯逻辑 | | **action_economy**(A3) | AP/RAP 账本、last_round_end、轮次相位机 {Idle, Active, Waiting}、结束仲裁 | 8 API 全布尔面:notify_round_start / request_dig / request_flag_place / request_flag_pull / request_stop / request_refresh / notify_settlement_done / notify_combat_end;ap/rap/phase 只读 | ConfigDB(ActionEconomyTable);B1 回发 next_round_mode/battle_over | 无 | | **variation 定义**(A4) | VariationTable schema(现行 7 行:六 region + skewed_veins 一 global——全局作用域变异首发批 2026-10-04)与 F1 候选池门控谓词 | `variant_pool(level_index, board_type, node_type="")`(门控三维:unlock+board_types+节点身份——global 行仅 boss/elite 入池,缺省跳过零扰动);`global_variant_row(level_index, board_type, node_type)`(全局型单行决议访问器) | ConfigDB(VariationTable) | 无 | | **status_container**(B3) | 状态实例容器(战斗域生命周期、跨轮跨图延续) | 5 API:notify_battle_start / apply_effect / query_active / decay_round / notify_battle_end | ConfigDB(StatusEffectTable) | 无(RefCounted) | -| **save_system**(D3,Alpha) | 存档格式与版本比较 | (未设计——契约锚:SCHEMA_VERSION + master_seed + 各流 scope 计数器快照,须在无在飞 open_stream 实例时切出) | ConfigDB、RngService 只读计数器 | FileAccess——LOW | -| **settings/localization**(D6,愿景) | 设置项、翻译数据 | (未设计) | ConfigDB | 无 | +| **save_system**(D3,Alpha;iter27 已升格 autoload「SaveManager」) | 存档格式与版本比较 | (契约规范源:`../../gdd/systems/表现与支撑/存档序列化.md`——契约锚:SCHEMA_VERSION + master_seed + 各流 scope 计数器快照,须在无在飞 open_stream 实例时切出) | ConfigDB、RngService 只读计数器 | FileAccess——LOW | +| **settings/localization**(D6,愿景) | 设置项、翻译数据 | (契约规范源:`../../gdd/systems/表现与支撑/设置与本地化.md`) | ConfigDB | 无 | -### Core 层 +### 核心层 -| 模块 | Owns | Exposes | Consumes | 引擎 API | +| 模块 | 独占职责 | 对外暴露 | 消费依赖 | 引擎 API | |---|---|---|---|---| | **board_generator**(A1) | 生成算法(五阶段管线)、BoardGenTable 回填、生成期指标集、合法性谓词(clearable / R₀≠S / min_safe)、可推理率度量(metric_version) | `generate(L, D, rng) -> Board`;度量独立入口×3(推理器 / F3 度量 / 合法性谓词——独立纯函数、同一实现) | ConfigDB(BoardGenTable/VariationTable);board_gen 流(一次 open_stream = 一张图);dig_ap_cost 只读 | 无 | | **minesweeper_rules**(A2) | 棋盘状态(已开集 O / 旗集 G / 小人位)、三事件面、批次仲裁、install 四不变式 | `install_board(board)`;`settle_batch(intents)`(唯一提交入口);try_dig / try_flag_place / try_flag_pull / try_move(便捷形);`compute_move_path(cell)` 只读;`retire_board()`;三源拒绝(board_face / resource_face / phase)+ sub_reason 封闭枚举 | A1 产物(Board class_name 数据契约);A3 try_spend / last_round_end / 相位 | 无(零表读取、零 UI——切片实证) | | **unit_container**(B2) | hero/enemy 单位实例(hp/atk/实例池:池快照+冷却+摇定动作+保底计数)、行值快照 | spawn / query_alive / rollable_skills / special_skills / set_pending_action / pending_action / basic_streak / commit_action / tick_cooldowns / apply_damage / heal / default_target / ambush_grant_plan / despawn_all(2026-09-16 敌人技能池批:query_beat/query_attack/advance 随行为环退役——architecture.md 旧口径残留归 API 面 ADR 批整表复核) | ConfigDB(EnemyTable/SkillTable/HeroTable) | 无 | | **reward_economy**(B4) | 格面资源身份映射(install 期预分配、Ready 只读、换图映射消亡)、极性路由字典面((类型, 极性)→ 字典行查询;路由执行归 B1 授予段)、F6 当量供给投影 | 封闭 API:roll_board / query_identity / query_full_snapshot / grant / grant_clear / retire_mapping / polarity_row / equivalence_supply / phase / weighted_pick;另有 is_mapped 静默布尔投影(批量工具用) | ConfigDB(RewardTable);reward_roll 流(scope = 每次 install 批) | 无 | -| **helper_items**(A5,垂直切片) | HelperItemTable、探测显影语义 | (未设计——桥接位:A2 查询接口 + A4 counter_item_ids) | A2 / A4 / B4 | 无 | +| **helper_items**(A5,切片已实装秘宝域) | HelperItemTable、探测显影语义 | (契约规范源:`../../gdd/systems/跨局循环/秘宝.md`——桥接位:A2 查询接口 + A4 counter_item_ids) | A2 / A4 / B4 | 无 | -### Feature 层 +### 功能层 -| 模块 | Owns | Exposes | Consumes | 引擎 API | +| 模块 | 独占职责 | 对外暴露 | 消费依赖 | 引擎 API | |---|---|---|---|---| | **battle_orchestrator**(B1) | 段序骨架(七段结构冻结)、轮 facts 缓冲、可回放步骤流、[明细行协议](../../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)(15 类行 + 字段分层)、条款③⑤闭合对账、**战斗域全部跨系统调用权**、效果引擎宿主(每战 rebuild/战末 adventure 计数器导出回写)+ 树规则挂点施加面(posture 窗/sense 限次/守侧 flag_missed 发射/聚乘算入账前) | `begin_battle(encounter)`;窗口/刷新意图提交面(扮演 D1);`level_clear()`;步骤流(输出契约) | B2/B3/B4 全调用面(**唯一调用方**);A3 request_refresh 代理 + 回发;A2 install/retire + 三事件订阅;A1 generate(attempt 非 scope 事件);D2 SettlementTable + set_reload_gate | 无(零随机、禁 await——切片 88 冒烟实证可回放) | -| **effect_engine**(Core——内容数据驱动扩展批 iter17 建域) | 事件/事实/效果类型/算子四词表封闭(迭代 21 T3 扩签:EVENTS 18→19 +flag_missed 标错判定、FACTS +battle_index 关卡域战斗序)+ 树规则合成订阅六键(posture 每关首轮窗/sense 两组限次 counter 闸·domain=adventure 跨战斗持久) | rebuild(每战重建)/dispatch/validate_trigger_row/counters_export·counters_seed | ConfigDB(feats/treasure 行集) | 无(零随机全确定) | +| **effect_engine**(核心层——内容数据驱动扩展批 iter17 建域) | 事件/事实/效果类型/算子四词表封闭(迭代 21 T3 扩签:EVENTS 18→19 +flag_missed 标错判定、FACTS +battle_index 关卡域战斗序)+ 树规则合成订阅六键(posture 每关首轮窗/sense 两组限次 counter 闸·domain=adventure 跨战斗持久) | rebuild(每战重建)/dispatch/validate_trigger_row/counters_export·counters_seed | ConfigDB(feats/treasure 行集) | 无(零随机全确定) | | **level_runner**(C1-lite,切片已建) | 关卡域生命周期(节点链推进、共享 B4 + HP 携带、关卡末 level_clear) | 节点推进接口;LevelTable(`level.tres`——节点 enum {battle,reward,rest,boss}、末节点必须 Boss、ConfigDB 跨表校验⑧) | B1 begin_battle、B4 grant_node_active、ConfigDB LevelTable | 无 | -| **run_structure**(C2) | 冒险/关卡序列、失败重开、**master_seed 唯一接线方** | (未设计) | RngService.set_master_seed、C3/D2 | 无 | +| **run_structure**(C2) | 冒险/关卡序列、失败重开、**master_seed 唯一接线方** | (契约规范源:`../../gdd/systems/冒险循环/冒险结构.md`) | RngService.set_master_seed、C3/D2 | 无 | | **difficulty**(C3) | DifficultyTable 回填、全部曲线数值调参所有权、战斗期望表(切片 monte_carlo 为工具原型) | 调参输出(经 D2 R1 解析/编排器传递,禁反向调用生成) | ConfigDB、B1 对账输出(调参约束清单)、A1 报告 C | 无 | | **meta_progression**(C4,Alpha) | MetaTable、钥石账本、天赋树域(MetaTreeTable 12 节点 v0.8——Fork 一节点双态/row 字段退役/RULE_KEYS 六键/彩蛋特化觉醒,迭代 21 T1 换代)+ 同调位槽位判定(树点亮数单源——T4 槽位收编) | tree_can_buy/tree_buy/tree_buy_fork/tree_toggle_fork(写口唯一)、hero_override 注入(树淬炼 flat+锻造路线加值位预留 0)、tree_rule_keys | D3、C2、ConfigDB | 无 | -### Presentation 层 +### 呈现层 -| 模块 | Owns | Exposes | Consumes | 引擎 API | +| 模块 | 独占职责 | 对外暴露 | 消费依赖 | 引擎 API | |---|---|---|---|---| | **D1 HUD**(切片 lite 已拆 9 单元:BoardView / HUDView / HudPresenter / BattleLogView / ItemWindowOverlay / NodeOverlay / LevelStripView / TunePanel / UiKit + 组合根 main.gd;营地覆盖层=四柜台并排〔树淬炼主界面/锻造工坊·秘宝匣钥匙门/图鉴常开——迭代 21 T6 程序占位重排〕) | 全部 Control/CanvasLayer(例外:BoardView 棋盘本体与 BattleStageView 站桩本体 = Control 壳 + SubViewportContainer + SubViewport + Node2D 世界〔BoardWorld/CellUnit;StageWorld/StandeeBody——B 区 slot_row 伴随件留壳层〕,探针契约面不变——ADR-0006 棋盘 Node2D 迁移批 Phase A 2026-09-23 / 战斗舞台 Phase B 2026-09-26)、输入→意图翻译(**唯一提交路径 = settle_batch,不直调 A3**)、呈现义务台账(A2×6 / B2×4 / B3×4 / B4×5 / B1×3) | 视图单元接口(信号外发、setter 只读注入) | A2 compute_move_path / ActionOutcome;A3 ap/rap;B1 步骤流行协议(数据源);ConfigDB display_name | **MEDIUM**:Control / CanvasLayer / draw_* / InputEvent / RichTextLabel——对照 breaking-changes.md 4.5–4.7 条目(CanvasItem 线条无抗锯齿羽化、设备 ID 常量、RichTextLabel 图片参数两轮变化) | -| **battle_presentation**(B5,垂直切片后) | 结算动画 / 伤害数字 / 战斗舞台 | (未设计——前置"战斗表现美术测试"锁双舞台陷阱) | B1 步骤流(回放脚本源)、D1 | **MEDIUM**:AnimationPlayer(String→StringName 变更)/ Tween | +| **battle_presentation**(B5,垂直切片后) | 结算动画 / 伤害数字 / 战斗舞台 | (契约规范源:`../../gdd/systems/战斗循环/战斗表现.md`——前置「战斗表现美术测试」锁双舞台陷阱) | B1 步骤流(回放脚本源)、D1 | **MEDIUM**:AnimationPlayer(String→StringName 变更)/ Tween | | **audio**(D4,Alpha) | 音频挂点 | (挂点 = B1 明细行类型流;负反馈聚合——单结算至多一次) | B1 流水 | AudioStreamPlayer(4.7 area_mask 默认 1→0 注意) | | **tutorial**(D5,Alpha) | 教学条目 | (口径来源:A2/A3/B3/B1 各教学条目) | 各上游 | 无 | @@ -130,7 +132,63 @@ --- -## Data Flow +## 测试与质量域 + +> 定位:本节为测试域(本地闸、探针、静态扫描等横切关注点)的**事实源**。原登记于 ADR-0004 的测试载体与静态扫描域约束已迁入本节承接;ADR-0004 保留为历史变更记录,不回改、不再作为现行依据引用(2026-10-15 立规:ADR = 变更记录,不是事实源)。仓库无远端、无 CI——本地闸是唯一验收门禁,判定严密性即全仓质量下限。 + +### 模块归属 + +| 模块 | 载体 | 独占职责 | 对外暴露 | 判定口径 | +|---|---|---|---|---| +| **run_smoke**(系统级断言面) | `tools/run_smoke.py` | 冒烟总入口与判定权:headless 跑 `res://smoke/smoke_all.gd` 全量(轻闸首项,迭代 28 后在册 1125 项检查)+ 三闸判定 | 进程退出码(0=PASS / 1=FAIL) | 三闸齐备、判定无洞:①退出码 = 0;②摘要行「冒烟完成:N 项检查,0 项失败」在案且失败数为 0;③输出扫 `SCRIPT ERROR` / `Parse Error` 标记行。外部 wall-clock 超时在位(超时 = FAIL) | +| **run_all**(单元套件) | `game/tests/run_all.gd` | 27 套件单元测试统一入口:套件 manifest 逐条「套件 → 期望退出码」,致命类 expect=1 独立子进程实跑 | 逐套件结果 + 汇总退出码(任一套件失败 quit(1)) | 套件级退出码协议在位;**SCRIPT ERROR 扫描缺失**(脚本错误不改套件退出码时静默漏过);**断言数下限缺失**(套件零断言退出 0 照样绿) | +| **probe_gate**(场景探针) | `tools/probe_gate.sh` | headless 场景探针段编排:默认段 ui_input_probe / ui_struct_probe / ui_contrast_probe,`--click` 加跑 ui_click_probe,`--full` 加跑 ui_probe / ui_tune_probe / t17_defer_probe / fx_probe;孤儿 Godot 预清 + 批末残留清点(必须 0) | 段级 FAIL 输出 + 汇总退出码 | 每段 timeout 守卫在位(挂死 124/137 = FAIL,不静默);**多数探针不查进程退出码**(仅个别段以 grep PASS 标记兜底)——退出码判定缺失 | +| **render_gate**(视觉 golden) | `tools/render_gate.sh` | 窗口化渲染闸:①shot_probe 七屏截图 → shot_checker A-D 语义断言;②fx_shot_probe / board_shot_probe 取证(超时/零字节/文件缺失任一 = FAIL);③棋盘 golden 逐像素容差比对(差 ≤16 / changed ≤2%,provisional)+ 菜单 golden;④批末孤儿残留清零 | 段级 FAIL 输出 + 汇总退出码 | 查退出码在位(每段 timeout 守卫 + 退出码/取证文件双检);**SCRIPT ERROR 扫描缺失**;断言数下限不适用(判定主体 = golden 容差与取证文件存在性,非断言计数) | +| **static_scan**(静态扫描域) | `game/tests/static_scan.sh` | 静态扫描域 S1–S10 可执行载体(grep 规则 + `tools/audit_type_hints.py`〔S9〕+ `tools/audit_file_headers.py`〔S10〕) | fail 聚合退出码(任一硬失败规则命中即 exit 1) | 查退出码在位;SCRIPT ERROR 扫描与断言数下限不适用(逐规则命中即红,无运行时错误面与断言计数);S3 现为 warning 级、不参与 fail 判定(见下表) | + +### 三条判定硬闸现行状态 + +| 硬闸 | run_smoke | run_all | probe_gate | render_gate | static_scan | +|---|---|---|---|---|---| +| **退出码优先** | 已落实(闸①) | 已落实(套件 manifest expect 协议) | **缺失**(多数探针不查退出码) | 已落实(段级退出码 + 取证双检) | 已落实(fail 聚合退出) | +| **SCRIPT ERROR 扫描** | 已落实(闸③,外部扫描——GDScript 无脚本错误陷阱 API,闸设在外部包装) | **缺失** | **缺失** | **缺失** | 不适用(静态域无运行时错误面) | +| **断言数下限** | 无独立下限(闸②摘要行必须在案,防「跑一半仍 PASS」;脚本错误吞断言路径由闸③兜住) | **缺失**(27 套件跑完不校验断言总数,零断言套件可绿) | 不适用(逐段 PASS 标记判定,无断言总数概念) | 不适用(golden 容差 + 取证存在性判定) | 不适用(逐规则命中判定) | + +背景事实(run_smoke 头注在案):GDScript 运行时脚本错误不改进程退出码、不计入冒烟失败数、且静默中断所在函数剩余断言——2026-09-19 台账 83 实证「309 项 0 失败」实为断言未跑全。这是 SCRIPT ERROR 扫描必须存在于判定层的原因。 + +### 静态扫描域 S1–S8 承接清单 + +规则语义源自 ADR-0004 §Decision 3(原文留档不动,下表为现行事实登记): + +| # | 规则 | 状态 | +|---|---|---| +| S1 | 玩法代码禁 `randomize()`、自建 `RandomNumberGenerator`(D2 Rule 5) | **在位**(硬失败;扫描面 game/core + game/presentation) | +| S2 | 禁全局随机函数 `randi()` / `randf()` / `randf_range()`——全局 RNG 绕开 RngService(specialist 补登) | **在位**(与 S1 同段硬失败;实例方法 `.randi()` 排除、`ADR-0007-exempt` 豁免注记在案) | +| S3 | core/ 禁 ConfigDB 外 data 表加载(`load(` / `preload(` / `ResourceLoader.load`;schema class_name 直引豁免)(D2 Rule 2) | **未落地**(脚本内仅 warning 级占位、不参与 fail 判定;且扫描路径 `core/` 自 2026-09-24 布局迁移后不存在——实际为 game/core,现行实跑恒零命中) | +| S4 | core/ 禁 `extends Control/Node2D`、禁 `.tscn` preload(D2 Rule 7) | **在位**(硬失败) | +| S5 | core/ 禁裸引用 autoload 全局标识符(`ConfigDB` / `RngService` 直接写 = --script 模式 parse error)——构造注入 only(specialist 升格) | **未落地**(脚本 TODO 注记在案:grep 近似误报多,需 AST 级或精确白名单;已有真实反面案例) | +| S6 | core↔core 信号连接只许方法 Callable(禁 lambda 捕获 self);发射者禁持有订阅者反向引用(ADR-0001) | **未落地**(脚本 TODO 注记在案) | +| S7 | B1 编排唯一性:B2/B3/B4 API 符号命中文件 ⊆ B1 文件集;A2/B3/B4 零相互直调(B1 AC-43) | **未落地**(脚本 TODO 注记在案) | +| S8 | 结算路径 `await` 零命中(B1 结算/编排文件集);字面量扫描 = warning 级 + 人工三要素复核(D2 AC-14 口径) | **未落地**(脚本 TODO 注记在案) | + +域外扩充两件(非 ADR-0004 范围,均硬失败在位):**S9** 类型闸(`tools/audit_type_hints.py`,迭代 27 T5——产品码无类型容器/有值返回缺类型/参数缺类型);**S10** 文件头闸(`tools/audit_file_headers.py`——头注 ≤8 行 + 日期/变更叙事黑名单)。 + +### 依赖约束 + +测试域不得反向依赖呈现层具体实现。五闸及其调用的探针场景、审计脚本只允许依赖两类边界: + +1. **autoload 边界**——ConfigDB / RngService 的公开面(--script 模式不加载 autoload 且不注册全局标识符,测试文件自带显式实例化夹具); +2. **场景契约**——探针场景的信号外发面与视图单元接口(信号外发、setter 只读注入),禁直引呈现层实现内部(如 UiKit 工厂内部状态、BoardView 绘制细节)。 + +测试域是所有层的消费方,进入方式限于上述两类边界;除此之外的依赖方向一律与「模块归属」节依赖单向性同规。 + +### 事实源声明 + +本节取代 ADR-0004 作为测试域(测试载体、判定口径、静态扫描域)的事实源;ADR-0004 原文保留为历史变更记录,不回改。新增违规案例仍须先补 static_scan 规则再修码(code-conventions 缺陷-规范对照表纪律)。 + +--- + +## 数据流 ### 1. 帧更新路径(2D 回合制:无逐帧玩法逻辑) @@ -179,7 +237,7 @@ D1 ◀──呈现数据源:A2 事件流 / B1 步骤流 / A3 ap-rap / ConfigDB --- -## API Boundaries +## API 边界 > 完整 API 面(含封闭枚举负空间、布尔受理口径、输入×相位矩阵)以各 GDD AC 前言为**规范源**——本节列边界契约与不变式,实现须与 GDD 逐字一致;冲突时以 GDD 为准并走接口漂移修订。 @@ -200,9 +258,9 @@ D1 ◀──呈现数据源:A2 事件流 / B1 步骤流 / A3 ap-rap / ConfigDB --- -## ADR Audit +## ADR 审计 -**现存 ADR:0 份**(`docs/architecture/` 本文档为首个产物;此前架构约束由 GDD 门禁评审 + CLAUDE.md + code-conventions 事实承载)。 +**现存 ADR:7 份**(adr-0001–0007,`design/dev/architecture/`;ADR=变更记录留档、非事实源,2026-10-15 立规)。以下子节为 2026-09-12 时点的盘点快照,保留留档;其中「现存 ADR:0 份」与「ADR 覆盖 0 条」均为当时实况,非现行状态。 ### 已锁决策盘点(GDD 层已定稿,不重复立项 ADR) @@ -216,13 +274,13 @@ D1 ◀──呈现数据源:A2 事件流 / B1 步骤流 / A3 ap-rap / ConfigDB | 多敌 side-wide / 出招确定性(技能池批改型:零随机纪律保持、开轮摇号走 behavior_roll 封闭流)/ 固定顺位 / 伏击 cap=4 | B2(2026-09-09 用户拍板;2026-09-16 技能池批改型) | | 奖励五值两类交付轴 / install 预分配 / 关卡域库存 / 窗口单件制 | B4(2026-09-11 用户裁决批) | | weake­n 锚 F0 瞬时当量 / 条款①③⑤闭合对账 owner = B1 | B1 F0–F5 | -| 领域命名禁 ID 前缀 / 组合根模式 / 呈现层契约成文 | CLAUDE.md + docs/code-conventions.md(切片教训批) | +| 领域命名禁 ID 前缀 / 组合根模式 / 呈现层契约成文 | CLAUDE.md + design/dev/code-conventions.md(切片教训批) | -### GDD 登记的"实现期 ADR 裁决项"汇总(= Required ADRs 的来源) +### GDD 登记的「实现期 ADR 裁决项」汇总(= ADR 立项清单的来源) A2 OQ2(事件外发载体)· B1 OQ1(事件总线载体,与 A2 OQ2 同一裁决)· A1 OQ2/OQ3(生成性能姿态 + 度量独立入口)· B2 OQ1(query_attack/ambush_grant_plan 两 face 归属)· B2 OQ5(HeroTable 单行校验落点)· B2 OQ9(零伤害死局跨字段护栏落点)· D2 OQ1(gdUnit4 取舍)· technical-preferences(渲染器选择)· 切片新增正式化批(轮内刷新方案 A / RewardSupplyController / LevelTable / grant_node_active / clear_blast——GDD+registry 修订义务在切片 README)。 -### Traceability Coverage Check +### 溯源覆盖检查 Technical Requirements Baseline 63 条 → ADR 覆盖 0 条(无 ADR 存在);按覆盖载体分层: @@ -232,23 +290,25 @@ Technical Requirements Baseline 63 条 → ADR 覆盖 0 条(无 ADR 存在) | 🔶 待 ADR 裁决 | 12 | 引擎/测试/实现形态类:TR-gc-008(渲染器)、TR-a1-011/012(生成姿态)、TR-d2-014/016(测试载体)、TR-a3-004+TR-b1-001/002(事件载体)、TR-b2-005/006(face 归属)、TR-d2-010+TR-gc-002(D3 契约正式化) | | ⏳ 未设计系统预留 | 5 | A5/C1–C4/D3 关联 TR(随各系统 GDD 立项) | -**结论:0 条孤儿需求**——46 条由本文档+GDD 承载、12 条待 ADR(见下)、5 条随未设计系统。**2026-09-12 更新:ADR-0001~0004(Foundation 四项)已落定 → 正式工程骨架解冻**;ADR-0005~0008 随对应系统开工前裁决(切片代码可作为参考实现,生产化迁移待 ADR-0008 正式化批)。 +**结论:0 条孤儿需求**——46 条由本文档+GDD 承载、12 条待 ADR(见下)、5 条随未设计系统。**2026-09-12 更新:ADR-0001~0004(基础层四项)已落定 → 正式工程骨架解冻**;ADR-0005~0008 随对应系统开工前裁决(切片代码可作为参考实现,生产化迁移待 ADR-0008 正式化批)。 --- -## Required ADRs +## ADR 立项清单 -### 必须在正式编码开始前(Foundation 裁决)——✅ 已全部落定(2026-09-12,solo 授权代决,godot-specialist 校验通过) +### 必须在正式编码开始前(基础层裁决)——✅ 已全部落定(2026-09-12,solo 授权代决,godot-specialist 校验通过) 1. **✅ ADR-0001 `event-bus-and-orchestration-carrier`**(`adr-0001-event-bus-and-orchestration-carrier.md`):组合根直连 signal 接线 + B1 Waiting 相位触发;autoload 全局事件总线否决。specialist 增补两条静态规则(方法 Callable only / 发射者禁反向引用)。 2. **✅ ADR-0002 `renderer-and-window-config`**(`adr-0002-renderer-and-window-config.md`):gl_compatibility(绕开 D3D12 新驱动线);基座 1280×800 + canvas_items + expand 显式落盘。 3. **✅ ADR-0003 `scene-structure-and-board-rendering`**(`adr-0003-scene-structure-and-board-rendering.md`):autoload 仅 {ConfigDB, RngService};core RefCounted / presentation 九单元组合根;**棋盘渲染 MVP 沿用切片逐格控件形态**(specialist 纠正:切片并非自绘 _draw——迁移登记为 D1 候选工作项含探针改造);CJK 字体随包为硬性前置。 4. **✅ ADR-0004 `test-carrier-and-ci`**(`adr-0004-test-carrier-and-ci.md`):双载体 + 静态扫描域 S1–S8(specialist 增补 S2 全局 rand* 禁令 / S5 core 禁裸引用 autoload 标识符)+ CI 外部超时;gdUnit4 deferred(D2 OQ1 关闭形态)。 -实现级立场已登记 `docs/registry/architecture.yaml`。 +实现级立场已登记 `design/registry/architecture.yaml`。 ### 相关系统开工前应有 +> ⚠ 编号漂移注记(2026-10-15 查):实际落地的 adr-0006=board-node2d-rendering(棋盘/舞台 Node2D 渲染)、adr-0007=rng-single-stream(RNG 单流收口),与本清单原计划的「0006 生成性能 / 0007 单元 API 归属」编号错位;下述 5–8 项的编号计划按实际占用顺延重排,重排归属归 ADR 立项批裁决。 + 5. `/architecture-decision "board-generation-performance"` → ADR-0006:A1 生成性能与异步化(F2c 常数 C 定稿;切片证据 = 10×10/12×12 同步生成可接受——推荐 MVP 同步+加载幕,WorkerThread 留扩展);度量独立入口确认(切片已实现三入口)。 6. `/architecture-decision "unit-api-face-ownership"` → ADR-0007:B2/B1 两 face 归属(query_attack / ambush_grant_plan)+ HeroTable 单行校验落点。 7. `/architecture-decision "zero-damage-guard-locus"` → ADR-0008:零伤害死局跨字段/跨表护栏落点(推荐落 D2 跨表校验——切片 LevelTable 校验⑧先例)。 @@ -256,7 +316,7 @@ Technical Requirements Baseline 63 条 → ADR 覆盖 0 条(无 ADR 存在) ### 已落定(2026-09-12 追加) -0. **✅ ADR-0005 `save-contract-and-schema-versioning`**(`adr-0005-save-contract-and-schema-versioning.md`):Foundation 层收口——SCHEMA_VERSION 比较归属 + RNG 快照切点契约 ADR 化(TR-d2-010 / TR-gc-002),Foundation 零缺口闭合。 +0. **✅ ADR-0005 `save-contract-and-schema-versioning`**(`adr-0005-save-contract-and-schema-versioning.md`):基础层收口——SCHEMA_VERSION 比较归属 + RNG 快照切点契约 ADR 化(TR-d2-010 / TR-gc-002),基础层零缺口闭合。 ### 可推迟 @@ -268,7 +328,7 @@ Technical Requirements Baseline 63 条 → ADR 覆盖 0 条(无 ADR 存在) --- -## Architecture Principles +## 架构原则 1. **Core 纯逻辑、headless 完整可跑**——Core/Feature 玩法逻辑零 Control/场景引用、零 UI 依赖;`--headless --script` 可跑完整战斗(D2 Rule 7 工程债;切片 88 冒烟实证)。输入是意图对象、输出是事件流/步骤流,D1 与输入设备皆可替换。 2. **单一事实源与零字面量**——玩法数值只存在于 `data/tables/*.tres`,经 ConfigDB 类型化单点读取;代码零玩法数值字面量;参数禁止跨系统复制(D2 Rule 1/2)。 @@ -280,7 +340,7 @@ Technical Requirements Baseline 63 条 → ADR 覆盖 0 条(无 ADR 存在) --- -## Open Questions +## 未决问题 | ID | Summary | Priority | Resolution Path | |----|---------|----------|-----------------| @@ -292,5 +352,5 @@ Technical Requirements Baseline 63 条 → ADR 覆盖 0 条(无 ADR 存在) | QQ-06 | 可选类退出格子池后 buff 频率被动上升(44%→59%)的难度对冲杠杆(敌 HP / 权重 / 幅度) | High | C3 调参 + 切片数据复测 | | QQ-07 | 标错惩罚(A2 OQ1:候选敌方伏击+1;hit=false 无去重的不对称裁决) | Medium | 原型小补丁实测会话(可与 v3 终验合并) | | QQ-08 | B5 双舞台陷阱(战斗发生在棋盘上还是独立场景) | Low(B5 前) | 战斗表现美术测试 → ADR-0010 | -| QQ-09 | C3 消费 B1 对账输出的事实依赖回写 systems-index | Low | C3 GDD 定稿时 | +| QQ-09 | C3 消费 B1 对账输出的事实依赖回写 `design/gdd/02-系统清单.md` | Low | C3 GDD 定稿时 | | QQ-10 | `.claude/docs/director-gates.md` 缺失(TD-ARCHITECTURE/LP-FEASIBILITY 判据无载体) | Low | 补建 gate 定义文件或维持 solo/lean 模式约定 | diff --git a/design/gdd/02-系统清单.md b/design/gdd/02-系统清单.md index 438b6097..a8846104 100644 --- a/design/gdd/02-系统清单.md +++ b/design/gdd/02-系统清单.md @@ -15,6 +15,7 @@ | `术语表.md` | 全库专用术语的唯一对照表——危险格/安全格/同调位/RAP/GP/真视等定义+退役词对照(2026-10-11 建立,v1.0) | | `06-待办清单.md` | 全项目待办事项的唯一登记处;各系统文档的「待办」节只留指路存根 | | `07-体验验证清单.md` | 需要真人试玩观测的验证项登记处(与 06 分工:06 是"要拍板的事",本篇是"要玩过才知道的事");每条注明结论回流路径 | +| `08-Alpha版本标准.md` | Alpha 版本包含哪些东西的清单——里程碑 M3 的完成标准;只列条目不写内容,定义一律指路各权威文档(**已定稿 v1.0**,2026-10-13) | ## systems/ 五个循环 @@ -154,3 +155,4 @@ | v1.22 | 2026-10-11 | 锻造工坊更名批随迁:`武器锻造.md` 改名 `锻造工坊.md`(系统更名,用户令),顶层文档表行与系统总表行随名换代并顺延版本注(v0.3);版本历史行内旧名按历史记载保留 | | v1.23 | 2026-10-11 | 锻造工坊 A 组定案随迁:锻造工坊行版本注换代 v0.4(A 组三裁+攻防所有权切分〔树脊柱砍攻/护两线,树侧 29→21 归天赋树会话交接批〕+钥匙无前置+2c/5a 结案) | | v1.25 | 2026-10-12 | **锻造工坊 B 组定案随迁(用户逐点裁决)**:锻造工坊行版本注换代 v0.5、描述格随裁换代——两区定名(武器锻造区/护甲锻造区)、三甲型统一命名「魔法护甲」、一次冒险各选一件、**满级特效本期不做留扩展位**;**17 裁点清零**(推翻推荐案四行 2a/3b/6/8a,撤回呈报子问 4a-1),开工门裁点侧已满足、仅剩用户发令;设计文档「裁决结果清单」+「工作间内容清单」两节为实装批需求卡片输入 | +| v1.26 | 2026-10-13 | **Alpha 版本标准立文(用户令「先定里程碑内容」)**:顶层文档表补 `08-Alpha版本标准.md` 行——Alpha 版本包含哪些东西的清单,即里程碑 M3 的完成标准;只列条目不写内容,定义一律指路各权威文档。本文只管「有什么」,系统与内容的定义权仍归各自权威文档,本表不复制其内容 |