merge: 在途线头收编——立绘定档分支 art-standee-20261006 合入+doc-adr-fixes-20261014 判废删除(worktree g-plan2-standee-tier/g-plan2-doc-adr-fixes,2026-10-17 用户令「合入;完成之后把两个工作区删除」)。落 master:10-07 三处文档修正(art-bible §8.2 站桩排版③大体档「允许向上溢出盒顶 N px」甲案与光柱脱钩/§8.3 参考核验废路径 production/mockups→artwork/mockups/battle.md 敌方站桩行同款措辞——三处 master 实查均仍为旧措辞)+06 新登「战斗区背景图替换——B 区舞台插画+临时光柱退役」条+机检三件(tools/standee_asset_check.py 逐键档高升级版、palette_check.py、path_check.py,依赖 STANDEE_TIER_H master 已有)+四份过程文档归档;merge master 时解冲突一处(art-bible 定档行取 master 用语规范版、排版行取分支甲案版),06 条目随批→顺带两处换代(08 doc_term 抓出)。未跟踪 _tmp_standee_new 13 件立绘(149K)已抢救至主区 artwork/archive/standee-tier-20261007/(素材不入 git),AI 生成像素立绘在 10-14 精细手绘像素方向下的去留归用户后裁。doc-adr-fixes 判废依据:7 份 adr-*.md 已废除(modify/delete 冲突面)、architecture.md v1.4 被 v1.8 超越、02 清单与 registry 零 ADR 字样;分支内 ADR 审查报告系分支自身删除(git 302b5b2c 可考)。该批止于 B 段工具闸,C 段引擎实装、D 段人闸未跑,roadmap 迭代位归属仍待裁。文档域闸 --docs 零新增红(回执 commit=4203d6be 与分支尖一致,domain=docs)。两 worktree 与分支随批删除;主区并行未提交件(术语表/project.godot/M4 卡片删除等)零触碰。
This commit is contained in:
commit
16fc55b5d5
11 files changed
+979
-47
No files matched your search
@@ -16,8 +16,8 @@
|
||||
- **工程路线图**:根目录 `roadmap.md`(里程碑时间线的权威;实时状态看下方快照节)
|
||||
|
||||
## 当前状态快照(收口批先更新本节,再追加状态记录;≤10 行)
|
||||
- **更新于**:2026-10-17(**迭代 30 卡① 未开格类型徽章批已合并**——代码实现批走 worktree `g-plan2-iter30-glow`/分支 `iter30-glow-20261017`,五提交合并 `7ffd1dc0`:五组微光实装(shader 主路径+ui_kit 色板单点)+断言三件(冒烟 1127→1151、单测 33→34 套件、探针 case⑰)+渲染双帧取证+`reports/` 三份产出物;群伤组色值经契约 5 停机呈报用户裁「换更暗档 #A61D37」(冻结绯红 V=0.65 档、色相零移动);代码域重闸零新增红(09 由基线红转绿)。此前同日已合并迭代 29 批 `fff4f120`、闸按域分跑批 `60c25ca3`、GDD 反哺写入批 `bd6ab32e`,M4 数值批已废归 06 待裁)。
|
||||
- **最新闸态**:重闸唯一入口 `tools/run_all_gates.sh` 按改动域分跑(代码域 01 冒烟/02 单元/03-04 探针/05 渲染/09 静态扫描/10 熵增/11 对拍,文档域 06 gdd_lint/07 doc_link/08 doc_term/08b active.md 体量/10 熵增;**域划分只在该脚本定义一处,文档禁止另列闸清单**)。文档域末次回执 commit=`3f9ec7c5`,五闸全绿零存量红。代码域末次实测读数(2026-10-17 迭代 30 卡①合并态,回执 commit=`7ffd1dc0`):冒烟 1151/0、单元 34 套件(type_glow_test 51 检查)、探针十八断言、渲染 golden 棋盘×3(0.13/0.11/0.10%)与菜单(0.14%)均在容差内、static_scan 相对基线「改善」(基线红→现绿);**11 号闸 parity 是条件闸件,本批判未触面(diff 未触数值/存档/RNG/结算面)SKIP**,迭代 29 批判为触面、须 `PARITY_APPROVED=1` 才发起,MC 未跑。
|
||||
- **更新于**:2026-10-17(**在途线头收编批已合并**——`art-standee-20261006` 立绘定档批合入+`doc-adr-fixes-20261014` 判废删除,两 worktree 与分支已清(用户令):立绘机检三件工具与 2026-10-07 三处文档修正(溢出甲案×2/参考核验废路径更正)+06 新登「战斗区背景图替换」条落 master,13 件未跟踪立绘抢救至 `artwork/archive/standee-tier-20261007/`(素材不入 git);立绘批引擎实装与人闸两段仍未跑、roadmap 迭代位归属仍待裁。此前同日已合并迭代 30 卡① `7ffd1dc0`、迭代 29 批 `fff4f120`、闸按域分跑批 `60c25ca3`、GDD 反哺写入批 `bd6ab32e`,M4 数值批已废归 06 待裁)。
|
||||
- **最新闸态**:重闸唯一入口 `tools/run_all_gates.sh` 按改动域分跑(代码域 01 冒烟/02 单元/03-04 探针/05 渲染/09 静态扫描/10 熵增/11 对拍,文档域 06 gdd_lint/07 doc_link/08 doc_term/08b active.md 体量/10 熵增;**域划分只在该脚本定义一处,文档禁止另列闸清单**)。文档域末次回执 commit=分支尖(2026-10-17 线头收编批,见合并说明),零新增红。代码域末次实测读数(2026-10-17 迭代 30 卡①合并态,回执 commit=`7ffd1dc0`):冒烟 1151/0、单元 34 套件(type_glow_test 51 检查)、探针十八断言、渲染 golden 棋盘×3(0.13/0.11/0.10%)与菜单(0.14%)均在容差内、static_scan 相对基线「改善」(基线红→现绿);**11 号闸 parity 是条件闸件,本批判未触面(diff 未触数值/存档/RNG/结算面)SKIP**,迭代 29 批判为触面、须 `PARITY_APPROVED=1` 才发起,MC 未跑。
|
||||
- **迭代 28 交付**:修好启动时菜单被冒险层盖住的装配顺序,层序收敛为唯一装配合同(散落的两处 `move_child` 删除);boot 链路、九阶段生命周期、启动态菜单 golden 三组验收补全;本批新立硬规则「验收函数无变异红记录不算验收成立」,三处规约落文。
|
||||
- **迭代 27 交付**:三屏壳场景与局态物化、结算五段拆分、RunLedger 单类持四账、模态编排类、类型闸、死代码退役,编排器由 1725 行降到 1325 行。
|
||||
- **规约体系现状**:规则文件按领域拆为 7 份、单文件上限 150 行,CLAUDE.md 只留元信息、命令、目录、规范导航与一行一条红线;动手前按规范导航表查对应细则。2026-10-17 增两条硬边界:迭代批(`/iter` 发射的代码实现)对 `design/` 只读、禁止在其中新增/修改/删除任何文件,产出物只准落 `reports/`,批末只跑代码域闸;非迭代批(工具/规则/文档改动)不占 roadmap 迭代号,按改动域跑闸。
|
||||
@@ -32,7 +32,7 @@
|
||||
- 待用户追认:仅剩 req-card 技能的 WorkBuddy 与 ZCode 两份副本是否取齐一项。迭代 27 代拍板十五项、迭代 28 十三项(含四条白名单外)、迭代 29 十二项已于 2026-10-17 用户令「追认单的所有我都是同意的」全部同意,三份实现报告(2026-10-17 文档批已迁位 `reports/`)的追认单节已就地标注追认结果;迭代 29 第四节「经你裁决的四项」不在追认范围(当时已问过已答)。
|
||||
- 待发令:**迭代 30 UI 呈现三卡批·卡②战斗一屏样张批与卡③二三关棋盘观感批**(卡①已合并 `7ffd1dc0`;②③卡片=`design/research/需求卡片-战斗一屏样张批-2026-10-16.md`/`design/research/需求卡片-二三关棋盘观感批-2026-10-16.md`,v1.2 零待裁残留,②不适用卡①的 U1 预授权并留分类结论注,③有 Q2 判据自动裁/目标带批内自定/L3 分类预授权;两批合计 ≈7.5–10.5d,逐个 `/iter` 发令);迭代 27/28 预留追加卡;黑话清扫第二波(GDD 正文流程动词族约三千处);规则文件编写 skill(按规则文件审计与目录划分批的工作流提炼,见提交 `81c0ee2b`)。
|
||||
- 待批准发起:**11 号闸 parity 回放确定性对拍**(迭代 29 把它收编为重闸里的条件闸件,每次跑批只做触面判定、不自动跑;迭代 29 批已判触面并挂 NEED-APPROVAL,批准方式=带 `PARITY_APPROVED=1` 发起,MC 须用户批准才跑)。
|
||||
- 在途分支未合并 master(读现状时勿当已入库):`art-standee-20261006`(worktree `g-plan2-standee-tier`,领先 5 笔——artwork 独立仓 dry-run 报告+立绘定档)、`doc-adr-fixes-20261014`(worktree `g-plan2-doc-adr-fixes`,领先 5 笔,**方向已废**——ADR 四节重建/修订注记与用户「ADR 不需要保存」裁定相反,分支与 worktree 去留待裁)。已合并的 worktree/分支清理(2026-10-17 用户令执行):`g-plan2-iter29-testlayers`、`g-plan2-menusub-20261016` 两工作区与分支 `adr-purge-20261015`、`adr-leak-fix-20261016` 已删;`ci-removal-20261015` 已按 2026-10-16 既裁重做(只删 `.github/workflows/tests.yml`、撤 ADR 两条)合并 `db032fb5` 后工作区与分支同删;**在盘待删**:`g-plan2-carddoc-20261017`(分支 `carddoc-20261017` 已合并 `480d8118`)、`g-plan2-iter30-glow`(分支 `iter30-glow-20261017` 已合并 `7ffd1dc0`)两工作区,删除待令。
|
||||
- 在途分支未合并 master(读现状时勿当已入库):**无**。线头清理(2026-10-17 用户令):`art-standee-20261006` 已合并入 master(立绘定档批机检三件+文档修正,见状态记录 511)、`doc-adr-fixes-20261014` 判废删除(ADR 体系已废、内容 git 历史可考),两 worktree 与分支同删。已合并的 worktree/分支清理(2026-10-17 用户令执行):`g-plan2-iter29-testlayers`、`g-plan2-menusub-20261016` 两工作区与分支 `adr-purge-20261015`、`adr-leak-fix-20261016` 已删;`ci-removal-20261015` 已按 2026-10-16 既裁重做(只删 `.github/workflows/tests.yml`、撤 ADR 两条)合并 `db032fb5` 后工作区与分支同删;**在盘待删**:`g-plan2-carddoc-20261017`(分支 `carddoc-20261017` 已合并 `480d8118`)、`g-plan2-iter30-glow`(分支 `iter30-glow-20261017` 已合并 `7ffd1dc0`)两工作区,删除待令。
|
||||
- 在册观察(06 登记,非阻塞):迭代 27 卡片义务补登两项——长函数余量 17 个中的装配/校验函数、lambda 连接防回归。
|
||||
|
||||
## 状态记录(滚动窗口:仅当前迭代;退役规则见 doc-conventions §10)
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
- **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`,合并见提交史)。
|
||||
|
||||
- **500(2026-10-15,决策文档体系废除 + architecture.md 确立架构唯一事实源,文档批)**:用户裁「ADR 不需要保存,任何决策记录在 git commit log 里记好,不需要工作日志文档存在」——七份 `adr-0001~0007` 全删(内容留 git 历史),architecture.md 删「ADR 审计」「ADR 立项清单」两节、文档状态立「事实源地位」条(唯一事实源),未决表关闭 QQ-01/02/03、立项清单在途事项转登记 QQ-11~14,补 A1 生成姿态与 autoload 四件(ConfigDB/RngService/SaveManager/MetaProgression)事实;CLAUDE.md 新增「架构事实唯一源」红线并恢复 RNG 单点红线;doc-conventions §5/§11 落架构唯一事实源条文;registry 删 18 处 adr 字段;game/ 约 60 处代码注释与 GDD/qa/research/roadmap/tests README 引用全清,豁免标记 `ADR-0007-exempt`→`rng-seed-exempt` 五处同步(main.gd/static_scan.sh/architecture.md/06/iter27);主区 4 个未跟踪今日产物(测试审计报告/两张需求卡片/自造短语清单)就地清除。走 worktree `adr-purge-20261015` 合并 4ed48b86;死链校验 1206 链接 0 死链、gdd_lint 0 不通过;按用户令未跑测试闸(本会话合回闸未触发、receipt 未生成)。代码中 `adr`/`adr5` 等为 AdventureRunner 既有局部变量名(smoke/单测 5 文件约 60 处),非文档引用、未动。**遗留呈报待用户裁**:`ci-removal-20261015` worktree 的 ADR 两条改动已被本批取代(仅 CI 清除部分对迭代 29 有效)、`doc-adr-fixes-20261014` 分支方向已废,两个 worktree/分支的去留待裁(2026-10-17 核:`ci-removal-20261015` 已合并 master、worktree 仍在盘;`doc-adr-fixes-20261014` 仍未合并,两条的现状与清理待令都记在未决面)。
|
||||
- **500(2026-10-15,决策文档体系废除 + architecture.md 确立架构唯一事实源,文档批)**:用户裁「ADR 不需要保存,任何决策记录在 git commit log 里记好,不需要工作日志文档存在」——七份 `adr-0001~0007` 全删(内容留 git 历史),architecture.md 删「ADR 审计」「ADR 立项清单」两节、文档状态立「事实源地位」条(唯一事实源),未决表关闭 QQ-01/02/03、立项清单在途事项转登记 QQ-11~14,补 A1 生成姿态与 autoload 四件(ConfigDB/RngService/SaveManager/MetaProgression)事实;CLAUDE.md 新增「架构事实唯一源」红线并恢复 RNG 单点红线;doc-conventions §5/§11 落架构唯一事实源条文;registry 删 18 处 adr 字段;game/ 约 60 处代码注释与 GDD/qa/research/roadmap/tests README 引用全清,豁免标记 `ADR-0007-exempt`→`rng-seed-exempt` 五处同步(main.gd/static_scan.sh/architecture.md/06/iter27);主区 4 个未跟踪今日产物(测试审计报告/两张需求卡片/自造短语清单)就地清除。走 worktree `adr-purge-20261015` 合并 4ed48b86;死链校验 1206 链接 0 死链、gdd_lint 0 不通过;按用户令未跑测试闸(本会话合回闸未触发、receipt 未生成)。代码中 `adr`/`adr5` 等为 AdventureRunner 既有局部变量名(smoke/单测 5 文件约 60 处),非文档引用、未动。**遗留呈报待用户裁**:`ci-removal-20261015` worktree 的 ADR 两条改动已被本批取代(仅 CI 清除部分对迭代 29 有效)、`doc-adr-fixes-20261014` 分支方向已废,两个 worktree/分支的去留待裁(2026-10-17 核:`ci-removal-20261015` 已合并 master、worktree 仍在盘;`doc-adr-fixes-20261014` 仍未合并,两条的现状与清理待令都记在未决面。同日再核:两线头已随状态记录 511 收编清偿——ci-removal 合并删净,doc-adr-fixes 判废删除)。
|
||||
|
||||
- **501(2026-10-15~16,简明技术中文用语规范批总收口)**:用户令对 design/gdd 全 45 文件做三层语言规范并融合词表——词面约 250 处按术语表「用语规范」A 表替换(不得→禁止/收口→完成/随批→顺带等 12 行,五子代理分四波执行+逐处语境裁决)、术语表 v1.12 新立「用语规范」节(STC 词表为权威+豁免三类+注销词义限定注)、词条五组(总线/抽屉、机能件/机制件、装板/摇号、坍塌显形、增益归一)+死链全库清零(3 处:config_fatal_probe 去向双证落 v0.4 行注、武器锻造漏改 2 处)+doc_term_audit 吸收 A 表 10 词与随批/台账补扫通道。**本批两教训**:①合回闸与「文档批零测试」铁规冲突时助手机械服从、擅跑全量测试两轮(含渲染闸),用户暴怒——正解=改闸的判断条件,现守卫已加「纯文档合入豁免」(merge diff 不触 game/ 直接放行,代码合入仍全量闸);②坑册新增:守卫按命令文本解析分支名(cd 前缀/环境变量前缀连坐误拦)、.import 边车被全局忽略致 worktree 冷检出探针 texture=null 假红。合并 af321c03(九提交,纯文档合入未跑测试,同日 4ed48b86 前例)。
|
||||
- **502(2026-10-16,迭代 29 编入批——roadmap 门牌登记)**:用户令「把需求卡片写进 roadmap 的迭代 29」——此前需求卡片只存在于中间文档,roadmap 仍写「下一前沿=迭代 29+ M4 数值批」,致别的会话启动迭代 29 时跑去做 M4(该卡同日已被用户删除=死引用)。本批三改:①roadmap 迭代 29 行改写为「测试分层与门禁语义修正批」(需求卡片=`design/research/需求卡片-测试分层与门禁语义修正批-2026-10-15.md`,v1.4,T0–T8≈5.5–7d,开工门 U0=Q3–Q7 裁点+卡片 v2.0 重核+`/iter` 发令),新增「迭代 30+ 位空」行记录 M4 废除(禁止再以该名义立批/规划/引用已删卡;四项欠账归 06 在册待裁),迭代 23+ 原始泊位行加作废注仅作排期史保留;②需求卡片升 v1.5(排期行与 §5 同步行更新;登记 v2.0 重核遗留=残留 CI 措辞四处+事实基线换代〔冒烟 1086→1125/0、门禁五闸→run_all_gates.sh 编排、architecture.md 测试域节已成文、Q3 的 CI timeout 前提消失〕;订正 v1.3 版本条目尾部重复段);③本文件快照与未决面三行同步换代。文档三闸全绿(gdd_lint 0 不通过/死链 0/疑似现行 0)。提交 21c83f5。**遗留待用户裁**:06 待办清单登记一条(卡片入库纪律);`ci-removal-20261015` 分支重做(撤 ADR 两条、只保留删 .github/、rebase 现行 master)。(2026-10-17 核:该分支已按现状合并、重做令失效;「06 登记一条」至今在 06 清单内查无,已改记在未决面的待登记项。)
|
||||
@@ -55,3 +55,5 @@
|
||||
- **509(2026-10-17,GDD 反哺点写入批——迭代 27/28/29 八条+一条建议逐点裁决)**:用户裁「全部按推荐案执行」(文档批,不占迭代号,worktree `g-plan2-gddfb-20261017`)。写入面:①**architecture.md v1.7→v1.8**——新增「战斗域装配现状」(结算五段 授予→增益/减益→战斗→衰减→判定,段序骨架冻结于 `SettlementTable.segment_order`;RunLedger 单类四账所有权 AdventureRunner 独占)与「呈现层装配与会话生命周期」(三屏壳+组合根句柄面/视觉层装配合同立条款、合同表不摘录——唯一事实源=`main.gd` `LAYER_CONTRACT` 现行 17 项五类 kind,登记时 16 层按代码实态订正/RunScope `_begin_session` 换会话整节点释放、无独立收束函数/九阶段×五引用面存活性矩阵认账入册/ModalFlow 互斥域 tags)两节;「初始化顺序」补启动后置条件六条(登记时「十断言」现为六组 11 条——2026-10-16 角标令 V2f 拆两条);呈现层 D1 行与实现实证读数换代。②**code-conventions.md §4 第 7–12 条**——S9 类型闸三规则与扫描面口径/`:= {}` 推断形态不算债/`# type-hint: ignore` 行级白名单/`# rng-seed-exempt` 豁免通道/--script 模式禁裸 autoload 标识符/Variant 参数化现行口径(元素精化不入硬纪律)。③④⑨**test-conventions.md 新增 §7 判定三硬闸**(闸承载三闸齐备义务+负面套件仅豁免错误扫描一闸+新写测试件全类型标注写法纪律,暂不机器闸——S9 扫描面产品码)与 **§8 判定可靠性优先于覆盖率**(§六第 4 项建议随此反映:脚本错误静默中断所在函数剩余断言的机制事实+三处实证+写验收函数自证断言全数执行义务;覆盖率度量是否引入仍 06 在册待裁)。⑤**07 v1.4**——㉖① 全流程走查保留不注销,节首加 `screen_flow_probe` 机检承接注记。三笔旧账清零:iter27/28/29 三份实现报告 `git mv` 往 `reports/`(06 条③迁位账清零,全库引用改指新路径、死链复验零死链;roadmap 九处 iter21–26 已删报告死指针改「已退役(git 历史可考)」、iter27/28/29 改指新位);iter29 报告 §六第 0 项按合并现实改写(`fff4f120` 已合回,两红各自结案:菜单 golden 重采 `dac9a94b`、01 篇 R5 流程图 `fcb8c3f8`+`8c18b52b`);06 补登迭代 29 反哺专条(该批漏登)且 27/28 反哺条按「吸收即死」退役为已写入。06 :687 死引用「code-conventions.md §3.6」顺带订正(该内容现独立成文于 test-conventions.md §6)。本批并把 508 批自述「等下一次动 active.md 的批一起入库」的主区未提交行改动随本批提交入库;主区其他并行未提交件(`game/project.godot`/M4 卡片删除/五份未跟踪文档/`layout_probe.gd.uid`)仍零触碰。文档域 --docs 零新增红(回执 commit=分支尖,见合并说明)。
|
||||
|
||||
- **510(2026-10-17,迭代 30 卡① 未开格类型徽章批总收口)**:用户「完成迭代30的开发」——三卡串行只做卡①(代码实现批,worktree `g-plan2-iter30-glow`,分支 `iter30-glow-20261017`,合回前 merge master `2aa7e8fd` 后重闸,快进合并 `7ffd1dc0`)。**实现**:Q1 丙案主路径 shader 距离场(`cell_type_glow.gdshader`+`cell_type_glow_layer.gd` 承载件,与 `_desat_mat` 共存实测未撞墙、a 案程序绘制兜底未启用);五组微光色板与九型归组单点 `ui_kit.gd`(TG_GLOW_*+`glow_group_for_cell_type`,呈现参数 α170/带宽 cell÷8);board_view 作用集=`_diggable` ∩ 身份可查 ∩ 灯光区 − r0,相位门控与接触带同源,Q4 丙案默认开。**唯一停机呈报**:群伤组初版 #FF1A31 与冻结绯红 #FF2D55 的 ΔH 5.40°(触 art-bible §4.2 既裁冻结面)→ 用户裁「换更暗档 #A61D37」(冻结值 V=0.65 档、色相零移动);五组现全数「只动明度不动色相」(ΔH ≤0.13°)。**断言三件**:冒烟八相 24 项(1127→1151,含契约 1 同板同序列 on/off 双实例 12 步 digest 对照)/单测 type_glow_test 五段 51 检查(33→34 套件)/ui_input_probe case⑰ 活板面(十八断言)。**渲染取证**:board_shot 双帧(motion_scale=0.5 停格隔离)三关 glow=2/4/4、带外零变化、生效格实绘非空;判据源探针(夹具面五组齐现)相邻组 CR 最弱对 1.232;off 帧对 2026-09-30 代 golden 三基线漂移 0.13/0.11/0.10%(≤2%,基线未重制)。**变异验证 M1–M5 五组反例实证**(归组错映/清单外静默/相位切换不重算/α=0 不绘/派生路径误触玩法 API,红输出与还原实录见实现报告 §四)。**验收**:`--code` 重闸零新增红(09 由基线红转绿判「改善」;11 号 parity 判未触面 SKIP),回执 commit=`7ffd1dc0`=分支尖。**坑档两条入注释**:探针裸视图必须接生产同源身份解析(否则作用集恒空、PASS 假绿——实跑两次 glow=0);`Callable.bind()` 动态派发对类型化参数做 Object 硬校验,回调传参改成员现值+直接方法引用。**产出物**:`reports/iter30-实现报告-2026-10-17.md`(含实机目检总清单 V10 人闸五项,登记不阻塞)/`iter30-代拍板追认单-2026-10-17.md`(§9 白名单 7 项待追认)/`iter30-反哺点-2026-10-17.md`(§5 七条待用户裁决归文档批)。**遗留**:反哺点七条待裁(06 条目状态+措辞、HUD框架 :140/:269、08 表现表、art-bible 明度档修订条目、roadmap 批内状态、Q3 两带分工+06 新待办、07 目检人闸条);实机目检人闸待用户过目(「很丑」终审位);群伤暗档 provisional 待样张批转正;阔视野带 desc「微光范围 8→12 格」与卡 §4「不扩微光」冲突属数据文本批(treasure_items.tres:47,实现报告 §六登记,不占反哺点条数);`g-plan2-iter30-glow` 工作区在盘待删(同 carddoc)。
|
||||
|
||||
- **511(2026-10-17,在途线头收编批——立绘定档分支合入+两条老线头清理)**:用户令「art-standee-20261006 合入;完成之后把两个工作区删除」。①**`art-standee-20261006` 合入**(worktree `g-plan2-standee-tier`,2026-10-06/07 立绘定档与站桩重排实装批,领先 5 笔、落后曾达 478 笔;先 merge master 解一处冲突——art-bible 定档行取 master 用语规范版、排版行取分支「允许向上溢出盒顶 N px」甲案版)。落 master 内容:10-07 三处文档修正(art-bible §8.2 站桩排版③大体档溢出甲案与光柱脱钩/§8.3 参考核验废路径 `production/mockups/`→`artwork/mockups/`/battle.md 敌方站桩行同款甲案措辞——三处 master 实查均仍为旧措辞即从未落库)+06 新登「战斗区背景图替换——B 区舞台插画+临时光柱退役」条(2026-10-07 用户点名登记)+机检三件工具(`tools/standee_asset_check.py` 逐键档高升级版、`tools/palette_check.py`、`tools/path_check.py`;依赖 `STANDEE_TIER_H` master 已有)+四份过程文档归档(实装批任务书/交接说明/artwork 独立仓 dry-run 清单/立绘读数 txt)。**该批止于 B 段工具闸,C 段引擎实装、D 段人闸未跑,roadmap 迭代位归属仍待用户裁**。②**13 件未跟踪立绘先抢救再删区**:`_tmp_standee_new/`(八敌+主角三态+九人对照总图+读数,149K,素材不入 git)已拷至主区 `artwork/archive/standee-tier-20261007/`(gitignore 豁免面零状态噪音);该批 AI 生成像素立绘在 2026-10-14「精细手绘像素」方向裁定下的去留归用户后裁。③**`doc-adr-fixes-20261014` 判废删除、不合入**(worktree `g-plan2-doc-adr-fixes`):五笔提交改的 10 文件全数失效——7 份 `adr-*.md` 已被废除批删除(modify/delete 冲突面)、architecture.md v1.4 被 v1.8 超越、02 清单与 registry 实查零 ADR 字样;分支内 ADR 审查报告已被分支自身第三笔删除,git 历史 `302b5b2c` 可考(Qoder 会话「报告仍在分支」系误报,已核)。两 worktree 与分支(`-d`/`-D`)均删,merge 说明载 --docs 闸回执。
|
||||
@@ -493,7 +493,7 @@
|
||||
- **主角战斗状态图(含 B 区站桩侧向)= 48×72**(同上暂定;v1.9 待决注记「主角立绘档空缺」由此完成);
|
||||
- **棋盘小人 = 32×32 二头身派生版(暂定,允许更小)**——独立资产,自人设定稿压缩派生(人物设计档 §5.4),不吞数字位、占位 ≤ 0.75× 格边长;36px 板 × 32px 源的占比摩擦(v1.9 待决注记①)沿「独立小源档」路线随格边长终值在样张批定终值;
|
||||
- **站桩立绘源档 = 八敌逐键定档(2026-10-06 定档批,用户确认定档总图;原三档 48/64/96 候选与 v3.0 档位上调方向候选一并完成)**:主角 48 不变;八敌源档高 = goblin 36 / giant_spider 38 / duergar 46 / hook_horror 58 / bugbear 62 / ogre_chief 74 / drider 90 / duergar_king 94,显示一律 **×2 整数档(NEAREST)** = 72–188。定档依据 = 生物体型三约束(用户拍板:钩爪恐魔>灰矮人、灰矮人<熊地精、食人魔>熊地精——体量=物种体型,非强度线性映射,人物设计档 §5.2 顺带修订);可读性实测门槛 = 源高 ≥32(24 糊/32 可读/48 清楚/64 细节完整),全阶梯 36–94 达标;派生管线 = pixel-1.png 紧裁 → 等比缩至档高 → dom_block_resize 块内众数降采样(tools/pixelize_candidates.py `STANDEE_TIER_H`,`SIZES` 降格为管线上游中间分辨率表);存在感问题(v3.0 病根 6)经方案二整屏对比(B 区 270/立绘显示上限 188)解决。
|
||||
- **站桩立绘排版 = 方案二(2026-10-06 用户拍板)**:① 区高 B 区 270(≈1/3)/C 区 530(≈2/3),**扫雷盘 438×438 原尺寸不缩、格子不变**(区高事实源 battle.md 区表;压缩由 C 区面板空档吸收);② 站桩内部重排——立绘双脚落石台上缘(弃盒内居中)、**血条+状态/名字行落底排**(立绘→血条→状态 顺序,全场血条对齐一线;血条嵌石板位、台缘线留作地面线、落影保留接地感),状态空时该行退化为名字行;③ 大体档(显示 >150px 级:drider/duergar_king)头部探出盒顶压进光柱区,血条仍落底;意图徽标悬浮头顶上方(探顶档压胸);④ 原「血条悬浮头顶+立绘盒内居中」排式退役——盒顶固定 y 与盒内居中在高盒下拉开血条-立绘空洞(2026-10-06 用户点名否决)。
|
||||
- **站桩立绘排版 = 方案二(2026-10-06 用户拍板)**:① 区高 B 区 270(≈1/3)/C 区 530(≈2/3),**扫雷盘 438×438 原尺寸不缩、格子不变**(区高事实源 battle.md 区表;压缩由 C 区面板空档吸收);② 站桩内部重排——立绘双脚落石台上缘(弃盒内居中)、**血条+状态/名字行落底排**(立绘→血条→状态 顺序,全场血条对齐一线;血条嵌石板位、台缘线留作地面线、落影保留接地感),状态空时该行退化为名字行;③ 大体档(显示 >150px 级:drider/duergar_king)**允许向上溢出盒顶 N px**(2026-10-07 用户裁甲案;N 由实装批 C0 按实测尺寸算定,**与背景/光柱无关**——现行溢出区恰为临时光柱氛围层〔§6.1 方向稿四柱,x 基准 110/900/1055/1210@1280,`battle_stage_view.gd:55-63`〕,正式舞台背景插画 `stage/stage_bg.png` 到位后该层退役/吸收进背景绘制,**溢出判定不随之变更**;横向不得压到顶部中央轮次·阶段指示,溢出上限由 C0 用真图复算 x 区间定),血条仍落底(落底排的第二个收益=头部探顶不带出血条);意图徽标悬浮头顶上方(探顶档压胸);④ 原「血条悬浮头顶+立绘盒内居中」排式退役——盒顶固定 y 与盒内居中在高盒下拉开血条-立绘空洞(2026-10-06 用户点名否决)。
|
||||
|
||||
### 8.3 导出格式与命名规范
|
||||
|
||||
@@ -512,7 +512,7 @@
|
||||
> **白话**:格子读感里的立体结构——顶面、缘件、角件、周界轮廓——必须是素材里**画出来的结构件**;素材缺件就停下报缺,拿调色/渐变/滤镜顶替不是变通,是违规。
|
||||
|
||||
- **结构件完整性**:格面立体感(高墙顶面/坡缘/角件/周界轮廓)只能来自**素材本体绘制的结构件拼装**(样例=Necesse 式缘件:专属底色+手绘细节+暗轮廓线的独立贴图);禁止以调色、渐变、明暗滤镜、跨格投影等生成手段伪造素材中不存在的结构。样稿暴露缺件时,正确动作=停下呈报缺口与「换素材/自产缺件」选项,由用户裁决后执行。
|
||||
- **参考核验**:宣称「参考 X 游戏」前,必须取得并实际查看 X 的截图证据(像素级放大核验其实现方式),证据存 `production/mockups/` 或 `design/art/references/`;仅凭文字资料、记忆或宏观印象作出「X 是这样做」的断言无效。
|
||||
- **参考核验**:宣称「参考 X 游戏」前,必须取得并实际查看 X 的截图证据(像素级放大核验其实现方式),证据存 `artwork/mockups/` 或 `design/art/references/`;仅凭文字资料、记忆或宏观印象作出「X 是这样做」的断言无效。(2026-10-07 路径核对器 B3 首跑发现更正——原 `production/mockups/` 系废路径,v3.9 批已更正asset-path-map 等四处,本条漏网)
|
||||
- **图底分离**:已开地面的明度须低于未开格墙体,由素材选型承载(选更暗的地板砖),不靠渲染压暗实现。
|
||||
- **生产分工(2026-09-26 用户拍板)**:格面地形类素材=**材质归模型、结构归程序**——AI 生图模型只出无缝填充纹理(无边框/无亮边/均匀光照/方形);一切结构件(缘件/轮廓/立面/角件/收头)一律程序化绘制或手修,因为 autotile 任意拼接的边界像素约束超出 2D 生图模型能力(实证:2026-09-25 生图 5×5 瓦片表每枚砖自带啃咬边框与宽亮带,提示词无法根除)。**镜像规则**:东西对称结构件只许水平翻转(flip_h)复用、**禁旋转**——北受光下东西侧缘光照对称,镜像无损真;旋转会把北受光转到东边。
|
||||
|
||||
|
||||
@@ -534,6 +534,14 @@
|
||||
|
||||
**状态**:挂账(随整屏样张闸前整备批启动;分章推进,每章一个章节,格式已定)
|
||||
|
||||
#### 战斗区背景图替换——B 区舞台插画 + 临时光柱退役(2026-10-07 用户点名登记)
|
||||
|
||||
**现状**:B 区舞台现行 = 程序化平色底(`UiKit.STAGE_BG`,`battle_stage_view.gd:47`)+ **顶光柱氛围层**(`:55-63` 四柱,x 基准 110/900/1055/1210@1280,60 段叠层矩形自顶向下渐宽窄渐隐〔顶 α26→0〕,层序 = bg < 光柱 < 世界)——二者均系 §6.1 方向稿的**临时占位**,用户口径「光柱只是临时方案,换正式战斗背景后效果更好」。正式件已立资产契约:`stage/stage_bg.png`(源 1280×270,B 区全高含明细带底;三关换挡走 §4.3 `wall_ambient` tint 槽,不按板出三张),属审计 P1-2 查得的「B 区舞台背景插画 0 张」缺口。**光柱在背景到位后顺带退役或吸收进背景绘制**(不再作为独立程序层)。**与立绘探顶解耦**:大体档「允许向上溢出盒顶 N px」的判定(2026-10-07 用户裁甲案)**不依赖光柱是否存在**,换背景零返工。
|
||||
|
||||
**归属**:[art-bible](../art/art-bible.md) §6.1(资产契约)+ §8.3 归档纪律 · 资产管线批;出图工单归 [art-assets-checklist](../art/art-assets-checklist.md) / 实装批任务书
|
||||
|
||||
**状态**:待办(**开工 = 用户点名**;**前置建议** = 立绘定档与站桩重排实装批的 **C0 盒高账定案后再出图**,避免 B 区高度/构图二次返工;交付后 art-status-checklist 顺带更新 ✅)
|
||||
|
||||
### 教学引导
|
||||
|
||||
> **节头注记(2026-10-04 用户拍板)**:教学引导定稿批整体改排 **Beta 阶段**——当前 Alpha 版不做教学相关工作,本节五条全部随之改排(2026-09-19 的 Alpha 排期拍板被本拍板取代)。同日五问讨论已形成初裁与设计提案,提案已归档 `archive/` 目录(磁盘留存、不入 git,Beta 批立项底稿,引用以其「归档状态与初裁记录」节为准)。初裁摘要:①教学形态=丙1 混合(首次冒险编排式首遇提示〔挂 first_script 锚、不锁操作〕+其余全程情景触发);②「因果教学顺序」问题**注销**——只教扫雷操作,结算读法不设教学(用户裁:结算只是表达、展现、演出,无策略内容;展示层每行带来源标注已自带归因;教学引导.md 旧前提〔设计目的句/P0 候选归因提示/验收第 2 条〕随 Beta 批文档定稿清除);③图例面板按循环段落分组、无结算段;④不做「再教一次」——改走独立「帮助」手册面(全部内容放一个文档);⑤教学文案内容权归设置与本地化(两文档负责表对齐随 Beta 批)。**未裁三疑点**(Beta 立项时先裁):增益叠层节奏条目去留/帮助入口位置(设置面为推荐)/图例面板与帮助手册的内容分工。
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
| 区 | 组件 | 类型 | 内容 | 交互 | 现有 demo 组件 |
|
||||
|---|---|---|---|---|---|
|
||||
| B | 主角站桩立绘 | 站桩(无框立绘+落影) | HP 条落底盘(2026-10-06 方案二拍板:站桩排式 = **立绘→血条→状态**,全场血条对齐一线;血条嵌石板位、台缘线留作地面线;原「悬浮头顶」退役——高盒下血条-立绘空洞,用户点名否决)、状态效果小图标一排挂血条正下方(形状+色相双通道、层数角标;空态不占位退化为空行)——**HP 与状态效果的唯一展示面(2026-09-26 信息归属拍板,原 C 区状态槽职责〔悬停 tooltip 来源+语义+剩余结算次数〕并入本组件)**;攻击值等规划数据仍归 C 区数据框(2026-09-20 全站桩拍板,英雄卡退役) | 悬停状态小图标看 tooltip | HUDView 拆分改造 |
|
||||
| B | 敌人站桩立绘 ×1–3 | 站桩(无框立绘+落影) | 血条+顺位徽标落底盘(同主角排式,2026-10-06 方案二;**大体档〔显示 >150px 级:drider/duergar_king〕头部探出盒顶压进光柱区,血条仍落底**)、状态小图标挂血条正下方(敌方 side-wide 增益各立绘同值呈现——蓄力/硬化/削弱/暴走/警觉;伏击层数通道随 2026-09-20 八型批退役——数据源 = 战斗结算流水经增益状态投影,敌人系统×4④;2026-09-16 敌人技能池批改型:行为环点拆除〔proposal §2.4〕,意图占位 = 本拍摇定结果的动画占位——普通攻击零表示 / 特殊技类型级提示,**意图徽标悬浮头顶上方,探顶档压胸**,敌方增益〔蓄力/硬化〕入状态图标行);死亡灰化加碎裂退场直接演在立绘上(2026-09-20 全站桩拍板,敌人卡退役);血条下名字行 = 纯名字 + 护甲类型图标(形状+色相双通道,与状态图标同行共存,状态空时为纯名字;原「底座下」随石板退位改落底排),AC 数值不展示——2026-09-26 终裁(用户口径:HP 信息已足够,攻防数值不直接写上;护甲类型图标保留克制对策可读性——类型可读、数值隐藏) | 只读 | 新建 |
|
||||
| B | 敌人站桩立绘 ×1–3 | 站桩(无框立绘+落影) | 血条+顺位徽标落底盘(同主角排式,2026-10-06 方案二;**大体档〔显示 >150px 级:drider/duergar_king〕允许向上溢出盒顶 N px(N 由实装批 C0 实算,与背景/光柱无关——现行溢出区为临时光柱氛围层,正式舞台背景插画到位后该层退役,判定不变),血条仍落底**)、状态小图标挂血条正下方(敌方 side-wide 增益各立绘同值呈现——蓄力/硬化/削弱/暴走/警觉;伏击层数通道随 2026-09-20 八型批退役——数据源 = 战斗结算流水经增益状态投影,敌人系统×4④;2026-09-16 敌人技能池批改型:行为环点拆除〔proposal §2.4〕,意图占位 = 本拍摇定结果的动画占位——普通攻击零表示 / 特殊技类型级提示,**意图徽标悬浮头顶上方,探顶档压胸**,敌方增益〔蓄力/硬化〕入状态图标行);死亡灰化加碎裂退场直接演在立绘上(2026-09-20 全站桩拍板,敌人卡退役);血条下名字行 = 纯名字 + 护甲类型图标(形状+色相双通道,与状态图标同行共存,状态空时为纯名字;原「底座下」随石板退位改落底排),AC 数值不展示——2026-09-26 终裁(用户口径:HP 信息已足够,攻防数值不直接写上;护甲类型图标保留克制对策可读性——类型可读、数值隐藏) | 只读 | 新建 |
|
||||
| B | 轮次·阶段指示 | 标签 | "第 N 轮 · 挖掘中/结算中"(终局定格「战斗结束」;Boss 变体附 Boss 名) | 只读 | 新建 |
|
||||
| B | 结算明细带 | 滚动列表 | 结算期逐行流水([战斗结算](../systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋) 9 类行协议);挖掘期收起为上轮摘要 1 行 | 点击展开明细回看 overlay(2026-10-04 P-C7 退役——带保留单行摘要,回看归「生涯」) | battle_log_view.gd 改造 |
|
||||
| B | ~~结算明细回看~~(已退役) | —— | 2026-10-04 P-C7 裁:冒险中回看退役归「生涯」——settlement_review_overlay.gd 为未接线遗留件(06 登记) | —— | —— |
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
=== ./_tmp_standee_new ===
|
||||
character_enemy_bugbear.png 51x62 colors=32 opaque=2145
|
||||
character_enemy_drider.png 67x90 colors=33 opaque=3513
|
||||
character_enemy_duergar.png 34x46 colors=33 opaque=1014
|
||||
character_enemy_duergar_king.png 66x94 colors=33 opaque=4385
|
||||
character_enemy_giant_spider.png 48x38 colors=33 opaque=1389
|
||||
character_enemy_goblin.png 36x36 colors=31 opaque=828
|
||||
character_enemy_hook_horror.png 46x58 colors=33 opaque=1538
|
||||
character_enemy_ogre_chief.png 62x74 colors=33 opaque=2886
|
||||
character_hero_portrait.png 46x48 colors=32 opaque=1228
|
||||
|
||||
|
||||
[口径澄清 · 2026-10-07]
|
||||
上表 colors 列由 _tmp_baseline.py 统计,含全透明色 (0,0,0,0),故显示 33。
|
||||
剔除透明色后的真实唯一色数(_tmp_palette.py 实测,uniq_rgb):
|
||||
bugbear 31 / drider 32 / duergar 32 / duergar_king 32 / giant_spider 32
|
||||
goblin 30 / hook_horror 32 / ogre_chief 32 / hero 31
|
||||
=> C2「色数 ≤32」全档通过,无新增色值。
|
||||
opaque 面积与 pixelize_candidates.py 注释里的实测校准值逐键吻合
|
||||
(828/1014/1389/1538/2145/2886/3513/4385),可证档位口径与讨论批定案一致。
|
||||
@@ -0,0 +1,88 @@
|
||||
# dry-run 清单:artwork/ 独立 git 仓库 · 入库/排除建议
|
||||
|
||||
> **性质**:**dry-run 只读报告**——本轮**未建仓、未 `git init`、未动任何文件**、
|
||||
> 未加任何 .gitignore。产物 = 下面这张待你逐项裁定的清单。
|
||||
> **待决口径**:artwork/ 是否独立成仓(**不用 submodule**,会污染主仓历史)。
|
||||
> 现状:`.gitignore:50` 忽略整个 `artwork/`,素材零版本历史。
|
||||
|
||||
---
|
||||
|
||||
## 0. 体量实测(2026-10-07)
|
||||
|
||||
全盘`artwork/` ≈ **131 MB / 3402 文件**(2673 png · 703 svg · 25 ttf · 17 txt · 12 html · 9 jpg · 8 url · 6 ogg · 4 xml · 3 py · 3 md · 2 pxo)。
|
||||
|
||||
| 子目录 | 体积 | 性质初判 |
|
||||
|---|---:|---|
|
||||
| `ui-reuse-2026-09-23/` | 49 MB | **草稿**(最大,且已被P2-1 登记待整理) |
|
||||
| `ui-redesign-2026-10-04/` | 22 MB | 设计迭代稿 |
|
||||
| `ui-redesign-2026-09-29/` | 18 MB | 设计迭代稿 |
|
||||
| `mockups/` | 13 MB | **样张/评审产物**(asset-path-map 登记在册) |
|
||||
| `ui-redesign-2026-10-04-optA/` | 7 MB | 设计迭代稿 |
|
||||
| `_audit-2026-10-06/` | 4 MB | 审计留底 |
|
||||
| `remote-gen-2026-09-26/` | 3 MB | **八敌生图源 + 立绘源**(本批命脉) |
|
||||
| `qa-t17fix-baseline/` | 3 MB | QA 基线截图 |
|
||||
| `qa-screens-1920-20260930/` | 3 MB | QA 截图 |
|
||||
| `qa-reduced-test/` | 3 MB | QA 测试 |
|
||||
| `qa-screens-20260930/` | 2 MB | QA 截图 |
|
||||
| `qa-golden-20260930/` | 2 MB | **golden基准**(有回归价值) |
|
||||
| `qa-t17fix-after/` | 1 MB | QA 截图 |
|
||||
| `legacy/` | 1 MB | **本批新增**:旧 48 档立绘归档(11 件) |
|
||||
|
||||
---
|
||||
|
||||
## 1. 建议**入库**(红绿线:丢了就再也回不来)
|
||||
|
||||
| 目录 | 理由 | 体积 |
|
||||
|---|---|---:|
|
||||
| `remote-gen-2026-09-26/` | **最高优先**。八敌 `pixel-1.png` = 立绘派生的**唯一管线源**;丢了 A 段产图能力彻底归零(AI 原图 `v1.jpg/png` 也只剩这里)。交接文档与项目记忆都点名它是「命脉」 | 3 MB |
|
||||
| `legacy/standee-48-legacy-20261007/` | **本批新增**。旧 48 档立绘,素材无 git 历史 ⇒ 这份拷贝是**唯一回滚路径**。不入仓 = 违反本批自己的归档纪律 | <1 MB |
|
||||
| `mockups/` | 已定稿样张(level-map 等),asset-path-map §1 在册引用 | 13 MB |
|
||||
| `qa-golden-20260930/` | golden 回归基准,对齐后有比对价值 | 2 MB |
|
||||
|
||||
> 小计≈ **19 MB**。**这是「不可再生资产」的集合,也是我建议入仓的核心。**
|
||||
|
||||
## 2. 建议**排除**(可再生/ 已过气/ 有更好的载体)
|
||||
|
||||
| 目录 | 排除理由 |
|
||||
|---|---|
|
||||
| `ui-reuse-2026-09-23/` | 49 MB 草稿。已被 P2-1 批登记「3349 草稿 dry-run 整理」——**先整理再定**,别把 49 MB 草稿直接塞进新仓(交接 §8③ 原话) |
|
||||
| `ui-redesign-2026-09-29/` | 已被 10-04 两轮迭代取代 |
|
||||
| `ui-redesign-2026-10-04/` + `-optA/` | 同上,optA 是被opt 掉的分支 |
|
||||
| `qa-screens-*/` `qa-t17fix-*/` `qa-reduced-test/` | 一次性 QA 截图,共约 9 MB,可再生 |
|
||||
| `_audit-2026-10-06/` | 一次性审计留底 |
|
||||
|
||||
## 3. 建议**先裁定再定**(需你逐项拍板)
|
||||
|
||||
| 项 | 问题 |
|
||||
|---|---|
|
||||
| `*.url`(8 个) | 快捷方式/书签类文件?入仓无意义,建议排除 |
|
||||
| `*.ttf`(25 个) | 字体是第三方资产,**版权与体积双风险**,且多半能从系统/引擎取到。倾向排除 |
|
||||
| `*.py`(3 个) | 生成脚本属**代码**,应入主仓(受版本管理),不该留在 artwork 里当过程稿。建议迁出 |
|
||||
| `*.svg`(703 个) | 大头在 ui-reuse 草稿里;若按第2 条排除该目录,svg 自然一并排除 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 若你拍板「建仓」,建议的落地形态(**本轮未执行**)
|
||||
|
||||
```bash
|
||||
# 就地独立仓,不用 submodule(理由见交接 §8③)
|
||||
cd D:/code/g-plan2/artwork
|
||||
git init
|
||||
# .gitignore 只排第2 节(草稿/QA),不排源与定稿
|
||||
```
|
||||
|
||||
要点:
|
||||
- **只入第1 节红绿线资产**(≈19 MB),第2 节列.gitignore;
|
||||
- `git add` 前**先出 dry-run 清单经你确认**(你一贯纪律:批量文件操作先dry-run);
|
||||
- 独立仓的 `.gitignore` 需**与主仓 `.gitignore:50` 解耦**(主仓那条继续有效,两仓互不干扰);
|
||||
- 立绘源/pixel-1 只增不改⇒ 可先只做一次 initial commit 拿住命脉资产,草稿等 P2-1 整理完再补第二commit。
|
||||
|
||||
---
|
||||
|
||||
## 5. 待你拍板的三件事
|
||||
|
||||
1. **入仓范围**:只入第 1 节(≈19 MB,命脉资产)?还是连设计稿一起?
|
||||
2. **`ui-reuse-2026-09-23/` 49 MB**:等 P2-1 整理完再入,还是本轮就排除?
|
||||
3. **ttf / py / url**(第 3 节):是否按建议排除/py 迁出主仓?
|
||||
|
||||
> 拍板后我再动手建仓——**绝不自行`git init`**。
|
||||
@@ -0,0 +1,105 @@
|
||||
# 交接说明:立绘定档与站桩重排实装批(美术线自立批)
|
||||
|
||||
> **用途**:本批由 2026-10-07 会话推进到「立项完成 + P1–P3 全裁 + U0 可发令」状态后交接。接手 agent 请先读本文件,再读 `任务书-立绘定档与站桩重排实装批-2026-10-07.md`(本目录)。
|
||||
> **交接时点**:2026-10-07 17:35 · 主仓 `master` 已推进到 `3e9360d`(台账到 395)。
|
||||
|
||||
---
|
||||
|
||||
## 1. 这批在做什么(一句话)
|
||||
|
||||
把八敌站桩立绘从「全敌共用 48 档」换成**按生物体型逐键定档(源高 36–94、显示 ×2 整数 = 72–188)**,并把 B 区站桩排版换成**方案二**(演出区占 1/3 屏、立绘落台、血条+状态/名字行落底排全场一线)。它修的是 playnote 里的两条实机批评:**像素粒度过低看不清 / 怪物大小比例不合理**。
|
||||
|
||||
## 2. 批次归属口径(用户 2026-10-07 明确,务必遵守)
|
||||
|
||||
- **迭代(roadmap 迭代位)只装「代码实现」类批次。**
|
||||
- **美术素材生成 + 文档修改不进迭代**,走自立批 / 自由批次(不排队、不占 roadmap 迭代序列)。
|
||||
- **推进顺序 = 先产图、后改代码**(素材尺寸是实测值,容器依实测定)。
|
||||
- 实现类改动一律走 worktree;主工作区只读(豁免仅 `active.md` 与 `.zcode/`)。
|
||||
|
||||
## 3. 已完成(全部在分支 `art-standee-20261006`)
|
||||
|
||||
| 提交 | 内容 |
|
||||
|---|---|
|
||||
| `0aa85dd` | 讨论批 9 文件主提交(art-bible v3.7/v3.11、character-design v1.8/v1.9、battle.md 区表与组件、`pixelize_candidates.py` 新增 `STANDEE_TIER_H`、06 四条、asset-path-map、art-status-checklist、两份生图单) |
|
||||
| `5953af3` | 分支内并入 master 80 提交,解 `06-待办清单` 冲突一处 |
|
||||
| `c688670` | active.md 快照 + 台账(后并入 master 时改登 **386**,因 385 被并行会话占用) |
|
||||
| → `4359445` | **主区 `merge --no-ff`**(以上三件已进 master;台账 386 在案) |
|
||||
| `1e42e6e` | **立项任务书 v0.1**(四段 A/B/C/D + T0 十项考证 + 三笔待算账 + P1–P3 全列备选案) |
|
||||
| `9556539` | **P1–P3 全裁归档** + 光柱区表述解耦 + 06 新登「战斗区背景图替换」 |
|
||||
|
||||
## 4. 当前磁盘状态(重要)
|
||||
|
||||
- **worktree**:`D:/code/g-plan2-standee-tier`,分支 `art-standee-20261006`,**工作区干净**(无未提交改动)。
|
||||
- **未并入 master**:`1e42e6e` 与 `9556539` 两个提交**尚未合并**。master 此时已推进 53 个提交到 `3e9360d`。
|
||||
- **合并姿势(接手者做,别直动主区)**:
|
||||
1. 在 worktree 内 `git merge master`(**先**在分支里解冲突);
|
||||
2. 预期冲突点 = `active.md`(并行会话台账已到 395,**本批的 386 会撞号 → 按先例改登下一个空号**,先例见台账 374/383)、可能 `06-待办清单.md`;
|
||||
3. 解完再在主区 `git merge --no-ff art-standee-20261006`;
|
||||
4. **不要**动主区在飞的脏件(`.gitignore` / `.zcode/config.json` / `playnote.md` / `project.godot`)。
|
||||
|
||||
## 5. 待办(按优先级)
|
||||
|
||||
### P0 · A 段产图(U0 已具备,可直接开工)
|
||||
|
||||
| 卡 | 动作 |
|
||||
|---|---|
|
||||
| A0 | 记录八敌现役 48 档尺寸/色数基线 |
|
||||
| A1 | 按 `STANDEE_TIER_H` 重产八敌(**命令见 §7**) |
|
||||
| A2 | 出「九人对照总图」(八敌 + 主角,真实相对体量) |
|
||||
| A3 | 拷回主区 `game/assets/art/character/` + 同步 `.import` + **旧 48 档归档** |
|
||||
|
||||
### P1 · B 段工具闸(建议提到 A3 之前跑通,理由见 §6)
|
||||
B1 `standee_asset_check` 硬闸升级(逐键档高 / 色数 ≤32 / 非整数倍痕迹 / 描边亮度)· B2 色板检查器 · B3 路径核对器。
|
||||
|
||||
### P2 · C 段引擎实装
|
||||
C0 **盒高账**(见下) → C1 区高 252→270 / 548→530 → C2 底锚落台 → C3 血条落底 → C4 探顶溢出 + 意图徽标 → C5 探针断言族。
|
||||
|
||||
### P3 · D 段样张人闸
|
||||
整屏样张 + 目检清单 + 追认单 + 出口报告(人闸归用户)。
|
||||
|
||||
## 6. 关键事实速查(别再重查)
|
||||
|
||||
- `ui_assembler.gd:22` B 区 **252**;`:26` C/D **548**(文档已改 270/530,**代码未动**)。
|
||||
- `standee_body.gd:29` `box = Vector2(150,176)`;`:231-234` 立绘盒净高 = 176−44−36 = **96px**;`:237` scale 2.0 NEAREST;`:238` **盒内居中**(方案二要改底锚);`:27` `STANDEE_FOOT_MARGIN=12`;`:475` 意图徽标 y=86;`:194-197` `_intent_scale` 峰值 **1.6**。
|
||||
- `battle_stage_view.gd:44` 舞台 `custom_minimum_size=(0,252)`;`:55-63` 顶光柱氛围层(四柱 x 110/900/1055/1210@1280,层序 bg < 光柱 < 世界);`:66-72` `_svp_container` FULL_RECT + `stretch=true` + **无 clip** ⇒ 立绘画到盒顶之上照样渲染。
|
||||
- `ui_struct_probe.gd:235-256` ⑥standee 断言族:内容矩形 ⊆ **252px** 舞台(内缩 8px)+ 底缘 ≥8px(改 270 须随改)。
|
||||
- **C0 三笔待算账**:① 188px 立绘 vs 96px 盒净高 vs 270 区高 vs 24/84 明细带;② `BattleLogView` 24/84 与 176 盒如何共存(252−176=76 装不下 84);③ 探顶溢出上限 **N**(受顶部中央轮次指示横向约束,暂按 ≤32px 量级,需真图复算)。
|
||||
|
||||
### 已裁决(P1–P3 全裁甲案,2026-10-07)
|
||||
- **P1 探顶 = 甲**:盒按最高档抬,**允许向上溢出盒顶 N px,不裁切**。判定**与光柱/背景解耦**(光柱是临时氛围层,正式 `stage/stage_bg.png` 到位后退役,判定不变)。乙(真 clip)淘汰:会切掉石君王王冠;丙(降倍率 ×1.5)淘汰:非整数倍。
|
||||
- **P2 结算期 84px 明细带 = 甲**:改**覆盖层**,不挤压站桩盒。乙(压缩盒)淘汰:站桩跳动违反减动效。
|
||||
- **P3 棋盘小人 = 甲**:不随本批,保持 32×32。
|
||||
|
||||
### ⚠ 两个必知的坑
|
||||
1. **`.gitignore:50` 忽略整个 `artwork/`** ⇒ **worktree 里没有 `artwork/`**。产图脚本在 worktree 直接跑会**静默产出 0 张**。必须传主区绝对路径。
|
||||
2. **素材不入 git** ⇒ 无版本历史、不能 git 回滚 ⇒ **替换前必须归档旧档**,且 **B 段机检是唯一防线**(不是可选项)。
|
||||
|
||||
## 7. A 段执行命令(已验证可直接跑)
|
||||
|
||||
```bash
|
||||
# 解释器(Pillow 12.3.0 已装)
|
||||
PY=D:/dev/python/envs/gamedev/Scripts/python.exe
|
||||
|
||||
# A1 重产八敌 + 主角(源用主区绝对路径,输出先落 worktree 临时目录)
|
||||
cd D:/code/g-plan2-standee-tier
|
||||
$PY tools/pixelize_candidates.py \
|
||||
D:/code/g-plan2/artwork/remote-gen-2026-09-26 \
|
||||
--standee48 --standee-out ./_tmp_standee_new
|
||||
```
|
||||
|
||||
源在盘状态(已核实,2026-10-07):八敌 `pixel-1.png` 齐全;`hero-ref/edit/{normal,attack,hit}_1x.png` 齐全。
|
||||
输出名 = `character_enemy_<键>.png` / `character_hero_portrait.png` / `character_hero_{attack,hit}.png`。
|
||||
档高表 `STANDEE_TIER_H`:goblin 36 / giant_spider 38 / duergar 46 / hook_horror 58 / bugbear 62 / ogre_chief 74 / drider 90 / **duergar_king 94**;主角 48。
|
||||
|
||||
## 8. 三项未决(等用户拍板,接手者先别自行决定)
|
||||
|
||||
1. **旧 48 档归档位置**:建议 `archive/art/standee-48-legacy-20261007/`(用户若另有素材管理体系则按其路径)。
|
||||
2. **B 段是否提前到 A3 之前**(我的建议是提前:素材无 git 保护,机检应在入包前跑通)。
|
||||
3. **`artwork/` 独立 git 子仓库**:用户提议(不想素材影响文档/程序实现)。已给方案 = 就地 `git init` 成独立仓库(**不用 submodule**,会污染主仓历史),只入定稿/源(124M 里立绘源仅 2.7M;`ui-reuse-2026-09-23/` 49M 草稿先经 P2-1 dry-run 整理再定)。**待办第一步 = 出 dry-run 入库/排除清单,不动任何文件、不建仓库。**
|
||||
|
||||
## 9. 关联登记
|
||||
|
||||
- 任务书:`design/research/任务书-立绘定档与站桩重排实装批-2026-10-07.md`
|
||||
- 06 新登五条:站桩帧动画(Alpha 定版闸前)/ 主角描边素材侧复核 / 3349 草稿 dry-run 整理 / 口号型条款机检化 / **战斗区背景图替换(B 区舞台插画 + 临时光柱退役)**
|
||||
- art-status-checklist 已对账至 ✅4 / ◐8 / ⬜3(共 15 条)
|
||||
- 台账:active.md **386**(合并时若撞号按先例改登)
|
||||
@@ -0,0 +1,185 @@
|
||||
# 任务书:立绘定档与站桩重排实装批(美术线自立批)· v0.1 草案
|
||||
|
||||
> **批次归属口径(2026-10-07 用户明确)**:**迭代只装「代码实现」类批次**;**美术素材生成 + 文档修改不进迭代**,走自立批 / 自由批次(更灵活、不排队、不占 roadmap 迭代序列)。
|
||||
> 故本任务书**不登记进 roadmap 迭代序列表**,只落 `design/research/` + `art-status-checklist` + `06-待办清单` + `active.md`。
|
||||
> **推进顺序(用户裁定)= 先产图、后改代码**:素材尺寸是实测值,容器(立绘盒 / 区高 / 血条位)依实测定,避免二次返工。
|
||||
> **上游**:讨论批已落籍 master `4359445`(art-bible v3.7/v3.11、character-design v1.8/v1.9、battle.md 区表、`tools/pixelize_candidates.py` 的 `STANDEE_TIER_H`)。本文只负责「把文档承诺变成盘上事实」。
|
||||
> **起草**:2026-10-07;T0 时点 master = `4359445`(已并入并行会话推进)。
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标与完成定义
|
||||
|
||||
### 1.1 一句话目标
|
||||
|
||||
把八敌站桩立绘从「全敌共用 48 档」换成**按生物体型逐键定档(源高 36–94、显示 ×2 整数 = 72–188)**,并把 B 区站桩排版换成**方案二**(演出区占 1/3 屏、立绘落台、血条+状态/名字行落底排全场一线),最终过**整屏样张人闸**。
|
||||
|
||||
### 1.2 完成定义(出口判定清单;按新立的条款验收标注纪律分三档)
|
||||
|
||||
| # | 判定项 | 验收方式 |
|
||||
|---|---|---|
|
||||
| C1 | 八敌源档高逐键 == `STANDEE_TIER_H`(36/38/46/58/62/74/90/94),主角 48 | ←机检:脚本读 PNG 尺寸逐键断言 |
|
||||
| C2 | 每张新档色数 ≤32、无新增非整数倍缩放痕迹、描边亮度达暖白族档(主角例外档单列) | ←机检:`standee_asset_check` 升级后跑 |
|
||||
| C3 | 新档拷贝进 `game/assets/art/character/character_enemy_<键>.png` 且 `.import` 同步;原 48 档归档 | ←机检:文件存在 + md5 对拍 |
|
||||
| C4 | B 区 252→270、C/D 548→530;**扫雷盘 438×438 与格边长零改动** | ←机检:`ui_struct_probe` 断言值随改 + 棋盘格尺寸断言零漂移 |
|
||||
| C5 | 站桩内容矩形 ⊆ 舞台矩形(内缩 8px)、底缘距舞台底 ≥8px | ←机检:⑥standee 断言族随批扩展 |
|
||||
| C6 | 血条 + 状态/名字行落底排、全场血条对齐一线 | ←机检:新增断言(血条 y 逐站桩相等,容差 1px) |
|
||||
| C7 | 大体档(drider 90 / duergar_king 94)头部探出盒顶进入光柱区、不裁切内容主体 | ←目检:样张看头部是否自然压进光柱、血条仍落底 |
|
||||
| C8 | 意图徽标不溢出盒顶(弹入峰值 ×1.6 后仍在界内) | ←机检:探针按动画峰值矩形断言 |
|
||||
| C9 | 八敌同屏一眼分得开(地精最小 72px ↔ 石君王 188px) | ←目检:整屏样张 |
|
||||
| D1 | 数字/名行/徽标对比度 ≥4.5:1(承迭代 16 `ui_contrast_probe`) | ←机检:既有探针零新增红 |
|
||||
| D2 | 玩家可感知「演出区变大了、怪物大小有差别了」 | ←方向性:人闸目检 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 现状事实(T0 代码级考证 · 2026-10-07 实查)
|
||||
|
||||
| 事实 | 位置 | 值 |
|
||||
|---|---|---|
|
||||
| B 区高度 | `ui_assembler.gd:22` / `battle_stage_view.gd:44` | **252**(`custom_minimum_size=(0,252)`) |
|
||||
| C/D 两列 | `ui_assembler.gd:26` | **548** |
|
||||
| 站桩盒宽 | `battle_stage_view.gd:26` / `standee_body.gd:29` | `box = Vector2(150, 176)` |
|
||||
| **立绘盒净高** | `standee_body.gd:231-234` | `176 − 44 − 36 = ` **96px** |
|
||||
| 立绘缩放 | `standee_body.gd:237` | 固定 `scale = (2.0, 2.0)`、NEAREST |
|
||||
| 立绘定位 | `standee_body.gd:238` | **盒内居中**(方案二要改底锚落台) |
|
||||
| 脚底余量 | `standee_body.gd:27` | `STANDEE_FOOT_MARGIN = 12`;名行基线 `box.y-1-12` |
|
||||
| 意图徽标 | `standee_body.gd:475` + `:194-197` | 绘制 y=86;`_intent_scale` 峰值 **1.6**(另有 1.26/1.22 变体) |
|
||||
| 站桩结构断言 | `ui_struct_probe.gd:235-256` | 内容矩形 ⊆ **252px** 舞台(内缩 8px)+ 底缘 ≥8px |
|
||||
| 现役素材 | `game/assets/art/character/character_enemy_<键>.png` | 八张,**48 档** |
|
||||
| 重产源 | `artwork/remote-gen-2026-09-26/<键>/pixel-1.png` | 八敌齐全(含 `hero-ref`) |
|
||||
|
||||
### 2.1 待算清的三笔账(T0 必答,答案决定任务卡能否成立)
|
||||
|
||||
1. **盒高账(硬约束)**:新档最大显示高 = 94×2 = **188px**,而立绘盒净高只有 96px。B 区抬到 270 后,可用 = 270 − 顶部轮次指示行 − 底部结算明细带(24 摘要 / 84 结算期)− 血条状态名行(约 30)。**188 + 30 是否塞得下、84 结算期态要不要改覆盖层**——这笔账没算清之前不动代码。
|
||||
2. **84px 明细带账**:`BattleLogView` 的 24/84 两态与 176 的盒如何共存(现 252 − 176 = 76,装不下 84)——需实查是压缩盒还是覆盖层。
|
||||
3. **探顶账(P1 已裁甲,只剩量值待算)**:已考证 `_svp_container` 为 FULL_RECT + 1:1 + **无 clip** → 溢出即可渲染,**无需 clip 逻辑**。C0 只需算清 **N = 溢出上限**:受顶部中央轮次·阶段指示的横向遮挡约束(大体档在右侧敌位,须用真图复算 x 区间),暂按 ≤32px 量级,并复算最高档 94×2=188 与盒净高的差值。
|
||||
|
||||
---
|
||||
|
||||
## 3. 范围边界(🔴 不可越界)
|
||||
|
||||
- **不动玩法与数值**:零核心/数据层改动,MC 零跑(纯呈现批,diff=0 实证,同迭代 16 口径)。
|
||||
- **不动棋盘**:扫雷盘 438×438、格边长、迷雾口径零改动(压缩全部由面板空档吸收)。
|
||||
- **不动主角档**:主角维持 48(定档已锁),本批只重产八敌。
|
||||
- **不动棋盘小人**:32×32 派生不随本批(重产归后续「棋盘小人重出批」)。
|
||||
- **不新增色值**:新档色数 ≤32 且色板不增色(§4.1 增量纪律双层门)。
|
||||
- **非本批**:站桩帧动画(Alpha 定版闸前)、3349 草稿整理、口号条款机检化——各自有闸,不并入。
|
||||
|
||||
---
|
||||
|
||||
## 4. 设计契约(🔴 触碰 = L3 停机)
|
||||
|
||||
1. **整数倍缩放**:显示一律 ×2 NEAREST,禁非整数倍(圣经 §8.2)。
|
||||
2. **高定宽随**:只定高度整数倍档、宽度随源图宽高比,禁统一方框强拉(v3.6 教训)。
|
||||
3. **定值单点**:档位数值权威 = 圣经 §8.2 / `STANDEE_TIER_H`,代码不得硬编码第二份数字。
|
||||
4. **素材不入 git**:产物拷回 `game/assets/art/` 并同步 `.import`;过程稿归档(`artwork/` + 择机对象存储),**worktree 产图必须拷回主区,否则分支一清即丢**。
|
||||
5. **派生管线锁死**:`pixel-1` 紧裁 → 等比缩至档高 → `dom_block_resize`;**禁走 `pixelfixer recon`、禁重跑 `remove_bg`**(recon 会把同色大块抹成一坨,2026-10-06 实测)。
|
||||
6. **零新素材外的零改动**:本批不新增除八敌立绘与舞台排版以外的任何素材。
|
||||
|
||||
---
|
||||
|
||||
## 5. 任务卡(分批执行;每批独立闸)
|
||||
|
||||
### 批 A · 素材重产(先做,产出实测尺寸)
|
||||
|
||||
| 卡 | 内容 | 产出 | 闸 |
|
||||
|---|---|---|---|
|
||||
| A0 | 基线:记录八敌现役 48 档尺寸/色数;确认八份 `pixel-1` 源在盘 | 基线表 | — |
|
||||
| A1 | 按 `STANDEE_TIER_H` 跑 `build_standee48()` 重产八敌 | 八张新档 + 尺寸/色数读数 | C1/C2 |
|
||||
| A2 | 九人同图对照总图(八敌 + 主角,真实相对体量) | 对照总图 | 目检 |
|
||||
| A3 | 拷回主区 `game/assets/art/character/` + `.import` 同步 + 旧档归档 | 盘上落位 | C3 |
|
||||
|
||||
> A 批不碰任何 `.gd`。若 A2 目检发现某档偏糊 → **只改 `STANDEE_TIER_H` 重跑**(本批最便宜的返工点,这正是「先产图」的意义)。
|
||||
|
||||
### 批 B · 工具闸(把纪律变成代码)
|
||||
|
||||
| 卡 | 内容 | 闸 |
|
||||
|---|---|---|
|
||||
| B1 | `standee_asset_check.py` 硬闸升级:按 §8.2 **逐键校验档高**(现「宽 1–75」虚设区间退役)+ 色数 ≤32 + 非整数倍痕迹 + 描边亮度 | 负向验证(喂 48 档应红) |
|
||||
| B2 | 色板检查器(48 上限 + 近色 ≥8/255) | 跑现役素材零误报 |
|
||||
| B3 | 路径核对器(悬空/退役命名即报) | 首跑读数 |
|
||||
|
||||
### 批 C · 引擎实装(拿到实测尺寸后才动)
|
||||
|
||||
| 卡 | 内容 | 依赖 |
|
||||
|---|---|---|
|
||||
| C0 | **T0 盒高账实算**(§2.1 三笔账)+ 定探顶方案 | 批 A 实测尺寸 |
|
||||
| C1 | `ui_assembler` B 252→270、C/D 548→530 | C0 |
|
||||
| C2 | `standee_body` 立绘盒抬高 + 居中改底锚落台 | C0 |
|
||||
| C3 | 血条 + 状态/名字行落底排、全场血条对齐一线 | C2 |
|
||||
| C4 | 大体档**允许向上溢出盒顶 N px**(不裁切;N 由 C0 实算,与光柱无关)+ 意图徽标改位(探顶档压胸) | C2 |
|
||||
| C5 | 探针断言族:`ui_struct_probe` 252→270、⑥standee 扩展(血条一线 / 名行不压盒 / 探顶不出血条 / 意图峰值不溢出) | C1-C4 |
|
||||
|
||||
### 批 D · 样张人闸(唯一必经人审)
|
||||
|
||||
| 卡 | 内容 |
|
||||
|---|---|
|
||||
| D1 | 整屏样张一屏(方案二排版真图) |
|
||||
| D2 | 人闸材料包(目检清单 + 代拍板追认单)+ 出口报告 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 验证闸
|
||||
|
||||
- **轻闸(每卡)**:`run_smoke` 全量 + `probe_gate`(含 click)+ `ui_struct_probe` + `ui_contrast_probe`。
|
||||
- **重闸(批末)**:轻闸 + `run_all` 全套 + doc 三闸(对基线零新增)+ 熵增闸 + **MC 零跑**(零数值改动,同迭代 16 口径)+ 素材机检(B 批三件)。
|
||||
- **人闸**:D 批整屏样张目检,用户亲口确认才算通过。
|
||||
|
||||
---
|
||||
|
||||
## 7. 裁决归档(P1–P3 已全裁 · 2026-10-07 用户拍板)
|
||||
|
||||
**P1 · 大体档探顶怎么落 ✅ 裁甲**
|
||||
- **甲(采纳)**:盒按最高档抬,**允许向上溢出盒顶 N px**,不裁切。
|
||||
- **口径修正(同批定)**:溢出判定**不得绑定光柱**——表述改为「允许向上溢出盒顶 N px,N 由 C0 实算,与背景/光柱无关」。现行溢出区恰为临时光柱氛围层(`battle_stage_view.gd:55-63`),正式舞台背景插画到位后该层退役/吸收,**判定不变、换背景零返工**。
|
||||
- **技术面(已考证)**:`_svp_container` 为 FULL_RECT + `stretch=true` 1:1 + **无 clip**,世界坐标系铺满舞台高度 → 甲案实现即「不裁切」,无需任何 clip 逻辑;光柱为世界层之下的兄弟 Control,立绘自然盖住它。
|
||||
- **约束**:横向不得压到顶部中央轮次·阶段指示;溢出上限由 C0 用真图复算 x 区间定(暂按 ≤32px 量级)。
|
||||
- 乙:真 `clip` 裁掉头部——**淘汰:会切掉石君王王冠,违反 §5.1 剪影完整**。
|
||||
- 丙:大体档降倍率(×1.5)——**淘汰:非整数倍违反契约 1。**
|
||||
|
||||
**P2 · 结算期 84px 明细带与 188px 立绘共存 ✅ 裁甲**
|
||||
- **甲(采纳)**:明细带结算期态改**覆盖层**,不挤压站桩盒。
|
||||
- 乙:结算期态压缩立绘盒——**淘汰:会造成站桩跳动(减动效纪律)**。
|
||||
- 丙:84 → 改小——需用户另裁数值,越权本批。
|
||||
|
||||
**P3 · 棋盘小人是否顺带重出 ✅ 裁甲**
|
||||
- **甲(采纳)**:**不随本批**,保持 32×32,重出另行立项(依赖 = 本批派生管线先验证)。
|
||||
- 乙:顺带重出——本批体积超软时间盒,且混料不利于归因。
|
||||
|
||||
> **P1–P3 已全裁 ⇒ U0 开工令已具备**(用户 2026-10-07 逐项确认)。A 段可发令。
|
||||
|
||||
---
|
||||
|
||||
## 8. 批次工作流十三条对照(合规自证)
|
||||
|
||||
| 条 | 本批落实 |
|
||||
|---|---|
|
||||
| 1 先检索后提问 | 已查在册记忆(pixelfixer 坑、档位语义)+ 正主文档(§8.2) |
|
||||
| 2 任务书全列备选案 | §7 三裁点各列全案含淘汰依据 |
|
||||
| 3 用户发开工令才动手 | **待 U0**(P1-P3 裁决后) |
|
||||
| 4 独立 worktree + 拷导入缓存 | 复用 `D:/code/g-plan2-standee-tier`;新 worktree 先拷 `.godot/` 与字体 `.import` |
|
||||
| 5 改码前定基线三查 | 冒烟 / 单测套数 / 探针读数(A0 记录;涉呈现无模拟锚) |
|
||||
| 6 涉数值先采改前读数 | **不适用**(零数值改动 = 零 MC) |
|
||||
| 7 新功能必配新测试 | C5 探针断言族 + B 批三件脚本机检 |
|
||||
| 8 验收改动先行声明 | §1.2 完成定义表 + §6 闸序列(含 252→270 随改) |
|
||||
| 9 批末四闸全绿才合并 | §6(素材批以「素材机检 + 探针 + 冒烟」替代 MC 对拍) |
|
||||
| 10 合并后主区全量复跑 | 批末在主区复跑全套 |
|
||||
| 11 会话收口落记 | active.md 快照 + 台账 |
|
||||
| 12 实机目检归用户 | D 批人闸 |
|
||||
| 13 —— | 批 A/B/C/D 每段独立提交,段末合一次 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 异常分级
|
||||
|
||||
L1 自救(一次重试)→ L2 记录继续(连续 3 次同红灯升级)→ L3 停机写报告等用户(触碰 §4 契约任一)。
|
||||
|
||||
---
|
||||
|
||||
## 10. 风险与遗留
|
||||
|
||||
1. **盒高账可能推翻方案二的 270**:若 188 + 血条 + 明细带算下来 > 270,需回到用户重裁(要么再抬 B 区、要么把最高档从 94 降到 ~84)。这是本批最大的单点风险,故排在 C0。
|
||||
2. **worktree 素材丢失风险**:A3 拷贝回主区是硬步骤(素材不入 git),漏做即丢。
|
||||
3. **并行会话冲突**:主区有在飞会话(iter17-enemy / uialign),合并采取「分支内先并入 master、再 ff 主区」,不直动主区脏件。
|
||||
4. **遗留**:站桩帧动画、3349 草稿整理、口号条款机检化、另两个「0 张」缺口(19 徽章 / 6 纹带)各自有闸,不并入本批。
|
||||
5. **关联新登记(2026-10-07 用户点名)**:**战斗区背景图替换**(B 区舞台插画 `stage/stage_bg.png` + 临时光柱退役)已作为独立待办登记进 `06-待办清单`。**建议开工顺序 = 本批 C0 盒高账定案后再出背景图**,避免 B 区高度/构图二次返工;本批 P1 甲案的溢出判定已与光柱解耦,二者互不阻塞。
|
||||
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""B2 色板检查器(圣经 §8.3①挂点实现 · 立绘定档批 2026-10-07)。
|
||||
|
||||
⚠⚠ 口径纪律(2026-10-07 实跑后订正,**勿改回**)——两处极易写错:
|
||||
|
||||
1. **48 色上限不是「每张 PNG 的色数」**。§4.1 的「全作色板硬上限 48 色」指
|
||||
**设计色板 token**(UI 语义色/墨色/材质色那套),不是像素画的独立色数。
|
||||
像素画单张另有**32 色冻结**口径,由 standee_asset_check 管(像素域)。
|
||||
初版把 48 套到每张 PNG 上⇒ 12 张全红(误报率 100%),已作废。
|
||||
本器改为:单张色数**只报读数不判红**;48 只在 --tokens 模式下校验色板表。
|
||||
|
||||
2. **近色 ≥8/255 是「新色入板双门」,不是存量两两互查**。§4.1 原文:
|
||||
「**新色**入板须同时过两道门……②与既有任一色的 RGB 三通道差 ≥8/255」。
|
||||
它管的是**新增色 vs 既有色板**。对存量色两两互查会把 AI 生成的明暗渐变
|
||||
全部打成近色(实测 drider 22 组 / 巨蜘蛛 82 组)⇒ 噪声淹没真问题。
|
||||
本器改为:近色**只对新增色集**判(新增色 vs 基线色板)。
|
||||
|
||||
另:必须排除全透明像素 (0,0,0,0)(同standee_asset_check 的坑)。
|
||||
|
||||
用法:
|
||||
# 主用法:扫目录,新增色相对 --baseline 判定
|
||||
python tools/palette_check.py <目录> --baseline <基线目录>
|
||||
# 无基线:只出读数(单张色数/ 近色对计数),不判红
|
||||
python tools/palette_check.py <目录>
|
||||
退出码: 0 通过 / 1 有红灯(仅新增色违规或超单张上限时)
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
from PIL import Image
|
||||
|
||||
# §4.1 硬上限(**设计色板 token 口径**,非像素画单张色数)
|
||||
TOKEN_MAX = 48
|
||||
NEAR_TOL = 8 # §4.1 新色双门:与既有任一色三通道差 ≥8/255
|
||||
# 像素画单张色数(像素域32 色冻结)——由 standee_asset_check 执法,
|
||||
# 本器只作读数提示,避免两处口径打架
|
||||
PIXEL_COLOR_SOFT_MAX = 32
|
||||
|
||||
|
||||
def palette_of(path):
|
||||
"""返回 (不透明像素唯一色集合, 像素数)。排除全透明。"""
|
||||
im = Image.open(path).convert("RGBA")
|
||||
px = im.load()
|
||||
w, h = im.size
|
||||
cols = set()
|
||||
n = 0
|
||||
for y in range(h):
|
||||
for x in range(w):
|
||||
c = px[x, y]
|
||||
if c[3] == 0:
|
||||
continue
|
||||
cols.add(c[:3])
|
||||
n += 1
|
||||
return cols, n
|
||||
|
||||
|
||||
def nearest_to(col, pool, tol):
|
||||
"""返回 col 在 pool 中最近的色及其差值(差 < tol 算近色)。"""
|
||||
best, bd = None, 999
|
||||
for c in pool:
|
||||
d = max(abs(col[k] - c[k]) for k in range(3))
|
||||
if d < bd:
|
||||
best, bd = c, d
|
||||
return best, bd
|
||||
|
||||
|
||||
def hexs(c):
|
||||
return "#%02X%02X%02X" % c
|
||||
|
||||
|
||||
def scan(d, baseline_cols, report_only):
|
||||
files = []
|
||||
for dirpath, _, names in os.walk(d):
|
||||
for fn in sorted(names):
|
||||
if fn.lower().endswith(".png"):
|
||||
files.append(os.path.join(dirpath, fn))
|
||||
files.sort()
|
||||
print("=== %s(%d 张 PNG)===" % (d, len(files)))
|
||||
n_fail = 0
|
||||
all_new = set()
|
||||
for p in files:
|
||||
cols, npx = palette_of(p)
|
||||
rel = os.path.relpath(p, d)
|
||||
notes = []
|
||||
msgs = []
|
||||
|
||||
over = len(cols) > PIXEL_COLOR_SOFT_MAX
|
||||
notes.append("色%d%s" % (len(cols), "(>32 像素域冻结)" if over else ""))
|
||||
|
||||
new = set()
|
||||
if baseline_cols is not None:
|
||||
new = cols - baseline_cols
|
||||
if new:
|
||||
# §4.1 新色双门②:新增色须与既有任一色差 ≥8/255
|
||||
bad = []
|
||||
for c in sorted(new):
|
||||
near, d3 = nearest_to(c, baseline_cols, 999)
|
||||
if d3 < NEAR_TOL:
|
||||
bad.append((c, near, d3))
|
||||
all_new |= new
|
||||
notes.append("新增%d" % len(new))
|
||||
for c, near, d3 in bad[:5]:
|
||||
msgs.append("新增色 %s 与既有 %s 三通道差 %d < %d"
|
||||
"(§4.1 新色双门②,须走换色合并)"
|
||||
% (hexs(c), hexs(near), d3, NEAR_TOL))
|
||||
if len(bad) > 5:
|
||||
msgs.append("…… 另有 %d 个新增色同样不过门" % (len(bad) - 5))
|
||||
else:
|
||||
notes.append("新增0")
|
||||
|
||||
line = "FAIL " if msgs else ("WARN " if (report_only and over) else "PASS ")
|
||||
print("%s %-46s %s" % (line, rel, " ".join(notes)))
|
||||
for m in msgs:
|
||||
print(" └─ %s" % m)
|
||||
n_fail += 1 if msgs else 0
|
||||
print("小计:%d 张,%d 张有红灯\n" % (len(files), n_fail))
|
||||
return n_fail, len(files), all_new
|
||||
|
||||
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
baseline = args[args.index("--baseline") + 1] if "--baseline" in args else None
|
||||
dirs = [a for a in args if not a.startswith("--")
|
||||
and os.path.isdir(a) and a != baseline]
|
||||
|
||||
if not dirs:
|
||||
print(__doc__)
|
||||
sys.exit(2)
|
||||
|
||||
baseline_cols = None
|
||||
if baseline:
|
||||
baseline_cols = set()
|
||||
for dirpath, _, names in os.walk(baseline):
|
||||
for fn in names:
|
||||
if fn.lower().endswith(".png"):
|
||||
cols, _ = palette_of(os.path.join(dirpath, fn))
|
||||
baseline_cols |= cols
|
||||
print("基线色板:%s,唯一色 %d" % (baseline, len(baseline_cols)))
|
||||
|
||||
total_fail = total_files = 0
|
||||
total_new = set()
|
||||
report_only = baseline_cols is None
|
||||
for d in dirs:
|
||||
f, n, new = scan(d, baseline_cols, report_only)
|
||||
total_fail += f
|
||||
total_files += n
|
||||
total_new |= new
|
||||
print("色板机检完成:%d 张 PNG,%d 张有红灯,累计新增色 %d"
|
||||
% (total_files, total_fail, len(total_new)))
|
||||
if report_only:
|
||||
print("提示:未给 --baseline ⇒ 本次为只读模式(不判红)。"
|
||||
"『色数>32』标 WARN 属像素域提示,最终执法在 standee_asset_check。")
|
||||
sys.exit(1 if total_fail else 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,242 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""B3 路径核对器(圣经 §8.3② 挂点实现 · 立绘定档批 2026-10-07)。
|
||||
|
||||
职责:扫描 asset-path-map.md 声明的全部路径 + 代码侧素材常量,
|
||||
报「悬空(声明存在但盘上无)/ 退役未清(仍引用已退役命名)」。
|
||||
|
||||
为什么需要(2026-10-06 实证三处悬空):素材不入 git,路径错了不会报错,
|
||||
只会在实机静默回退(UiKit.load_tex 的 exists 守卫)⇒ 肉眼难发现。
|
||||
|
||||
三层校验:
|
||||
L1 目录级 asset-path-map §1 声明的路径存在性(candidates 按需创建豁免)
|
||||
L2 文件级 §3 game/assets/art 语义子目录现役清单逐件存在性
|
||||
L3 代码级 grep 代码里的 res://assets/art 引用,核对盘上是否存在
|
||||
+ 检出已知退役命名(board_floor/board_wall/pillar_dungeon_*)
|
||||
|
||||
用法:
|
||||
python tools/path_check.py [--repo <仓库根>] [--code <代码根>]
|
||||
退出码: 0 通过 / 1 有红灯
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
# asset-path-map §1 目录分工总表(逐条对应文档,勿复写第二份事实源)
|
||||
DECLARED_DIRS = [
|
||||
# (路径, 角色, 按需创建豁免)
|
||||
("design/art/candidates", "设计侧源档(档案库,游戏禁引用)", True),
|
||||
("game/assets/art", "运行时素材唯一落地处", False),
|
||||
("game/assets/ui/icons", "UI 图标(唯一入 git 素材目录)", False),
|
||||
("artwork/mockups", "混合样张/评审产物", False),
|
||||
]
|
||||
|
||||
# asset-path-map §3 game/assets/art 语义子目录
|
||||
DECLARED_SUBDIRS = ["character", "fx", "board", "ui"]
|
||||
|
||||
# §3 现役清单(文件名按 §8.3 域键式)
|
||||
ACTIVE_FILES = [
|
||||
"character/character_hero_idle.png",
|
||||
"character/character_hero_walk.png",
|
||||
"character/character_hero_portrait.png",
|
||||
"fx/shovel_swing_f0.png",
|
||||
"fx/shovel_swing_f1.png",
|
||||
"fx/shovel_swing_f2.png",
|
||||
"board/flag_seal.png",
|
||||
]
|
||||
# 立绘八敌按数据表键生成(键集=STANDEE_TIER_H,见 standee_asset_check)
|
||||
ENEMY_KEYS = ("bugbear", "drider", "duergar", "duergar_king", "giant_spider",
|
||||
"goblin", "hook_horror", "ogre_chief")
|
||||
ACTIVE_FILES += ["character/character_enemy_%s.png" % k for k in ENEMY_KEYS]
|
||||
|
||||
# asset-path-map v3.9 已退役命名(检出即红)
|
||||
RETIRED_PATTERNS = [
|
||||
(re.compile(r"board_floor"), "board_floor 命名已退役(→terrain_floor_<board_type>_<n>)"),
|
||||
(re.compile(r"board_wall"), "board_wall 命名已退役"),
|
||||
(re.compile(r"pillar_dungeon"), "pillar_dungeon_* 命名已退役"),
|
||||
(re.compile(r"production/mockups"), "production/mockups 为废路径(→artwork/mockups)"),
|
||||
]
|
||||
|
||||
# 路径末尾要允许 printf 转换符(%s/%d/%0Nd)——否则正则会在 '%' 处截断,
|
||||
# 拿到 "res://assets/art/board/terrain_" 这种半截串,既不像模板也不像真实
|
||||
# 路径,两边都判错。初版即栽在此处(2 处假悬空),现让 %s/%d 一并吃掉。
|
||||
RES_RE = re.compile(r"res://assets/art/[A-Za-z0-9_/\.\-%]+")
|
||||
# ⚠ 路径模板(printf 式)不是可解析的真实路径——常量里存的是
|
||||
# "res://assets/art/board/terrain_%s_%d.png" 这类格式串,盘上当然没有
|
||||
# 字面同名文件。初版未识别⇒ 假悬空。识别到 % 转换符即跳过(模板有独立的
|
||||
# 运行时守卫与 test 覆盖,不在本器执法面)。
|
||||
FMT_MARKERS = ("%s", "%d", "%0", "{")
|
||||
|
||||
|
||||
def is_path_template(ref):
|
||||
return any(m in ref for m in FMT_MARKERS)
|
||||
|
||||
|
||||
def main():
|
||||
argv = sys.argv[1:]
|
||||
repo = "."
|
||||
code = "game"
|
||||
if "--repo" in argv:
|
||||
repo = argv[argv.index("--repo") + 1]
|
||||
if "--code" in argv:
|
||||
code = argv[argv.index("--code") + 1]
|
||||
|
||||
problems = []
|
||||
notes = []
|
||||
|
||||
# ⚠ worktree 素材环境判定(素材不入 git ⇒ worktree 素材靠人工拷贝同步,
|
||||
# 常见三种态,须区分否则满屏假红):
|
||||
# full —— 主区形态,art 下素材齐全,全量校验
|
||||
# partial —— worktree 常态:character/ 被拷进来了(跑测试三件套惯例),
|
||||
# fx/board/ui 没拷 ⇒ 缺的那些是「未同步」不是「悬空」
|
||||
# empty —— art 下 PNG 总数为 0,素材整体未同步
|
||||
# 只有 full 态才把缺失判红灯;partial/empty 判 SKIP 并提示同步。
|
||||
artdir = os.path.join(repo, "game", "assets", "art")
|
||||
present = [s for s in DECLARED_SUBDIRS
|
||||
if os.path.isdir(os.path.join(artdir, s))]
|
||||
png_total = sum(1 for dp, _, ns in os.walk(artdir)
|
||||
for n in ns if n.lower().endswith(".png"))
|
||||
if len(present) == len(DECLARED_SUBDIRS):
|
||||
env = "full"
|
||||
elif png_total == 0:
|
||||
env = "empty"
|
||||
else:
|
||||
env = "partial"
|
||||
synced = env != "full"
|
||||
if synced:
|
||||
notes.append("素材环境 = **%s**(子目录就位 %d/%d,PNG 共 %d)—— "
|
||||
"worktree 素材靠人工拷贝同步,缺项属未同步非悬空"
|
||||
% ({"partial": "部分同步", "empty": "空"}[env],
|
||||
len(present), len(DECLARED_SUBDIRS), png_total))
|
||||
notes.append("缺失子目录:%s(如需完整校验请对**主区**跑本器)"
|
||||
% ("、".join(s for s in DECLARED_SUBDIRS
|
||||
if s not in present) or "无"))
|
||||
else:
|
||||
notes.append("素材环境 = 完整(主区形态),全量校验")
|
||||
|
||||
print("=== L1 目录级(asset-path-map §1)===")
|
||||
for rel, role, exempt in DECLARED_DIRS:
|
||||
p = os.path.join(repo, rel)
|
||||
ok = os.path.isdir(p)
|
||||
if ok:
|
||||
print("OK %-30s %s" % (rel, role))
|
||||
elif exempt:
|
||||
print("SKIP %-30s 按需创建豁免(文档已注非作废)" % rel)
|
||||
elif synced and rel.startswith(("game/", "artwork/")):
|
||||
print("SKIP %-30s 素材未同步豁免 —— %s" % (rel, role))
|
||||
else:
|
||||
print("FAIL %-30s 悬空:声明存在但盘上无 —— %s" % (rel, role))
|
||||
problems.append("目录悬空: " + rel)
|
||||
|
||||
print("\n=== L2 文件级(asset-path-map §3 现役清单)===")
|
||||
for rel in ACTIVE_FILES:
|
||||
p = os.path.join(repo, "game", "assets", "art", rel)
|
||||
sub = rel.split("/")[0]
|
||||
if os.path.isfile(p):
|
||||
print("OK %s" % rel)
|
||||
elif synced:
|
||||
print("SKIP %-44s 素材未同步豁免" % rel)
|
||||
else:
|
||||
print("FAIL %-44s 悬空(现役清单声明但盘上无)" % rel)
|
||||
problems.append("文件悬空: " + rel)
|
||||
for sub in DECLARED_SUBDIRS:
|
||||
p = os.path.join(artdir, sub)
|
||||
if not os.path.isdir(p):
|
||||
if synced:
|
||||
print("SKIP 子目录 %-40s 素材未同步豁免" % sub)
|
||||
else:
|
||||
print("FAIL 子目录 %-40s 悬空" % sub)
|
||||
problems.append("子目录悬空: " + sub)
|
||||
|
||||
print("\n=== L3 代码级 res:// 引用核对 ===")
|
||||
# ⚠ 口径:Godot 的 res:// 根 = 项目目录 game/(project.godot 所在处),
|
||||
# 不是仓库根。所以 res://assets/art/x.png → <repo>/game/assets/art/x.png。
|
||||
# 2026-10-07 初版误按仓库根解析 ⇒ 全部引用假悬空,已修。
|
||||
refs = {}
|
||||
for dirpath, dirnames, names in os.walk(os.path.join(repo, code)):
|
||||
dirnames[:] = [d for d in dirnames
|
||||
if d not in (".git", ".godot", "import", "node_modules")]
|
||||
for fn in names:
|
||||
if not fn.endswith((".gd", ".tscn", ".tres")):
|
||||
continue
|
||||
fp = os.path.join(dirpath, fn)
|
||||
try:
|
||||
txt = open(fp, "r", encoding="utf-8", errors="ignore").read()
|
||||
except OSError:
|
||||
continue
|
||||
for m in RES_RE.findall(txt):
|
||||
refs.setdefault(m, []).append(os.path.relpath(fp, repo))
|
||||
if not refs:
|
||||
print("(代码侧无 res://assets/art 硬引用——符合 §2 第4步禁 preload 纪律)")
|
||||
templates = []
|
||||
for ref, where in sorted(refs.items()):
|
||||
if is_path_template(ref):
|
||||
templates.append((ref, where))
|
||||
continue
|
||||
p = os.path.join(repo, "game", *ref[len("res://"):].split("/"))
|
||||
if os.path.exists(p):
|
||||
print("OK %-52s ← %d 处" % (ref, len(where)))
|
||||
elif synced:
|
||||
print("SKIP %-52s 无素材环境豁免 ← %s" % (ref, where[0]))
|
||||
else:
|
||||
print("FAIL %-52s 悬空 ← %s" % (ref, ", ".join(where[:3])))
|
||||
problems.append("代码引用悬空: " + ref)
|
||||
if templates:
|
||||
print("SKIP 路径模板 %d 条(printf 格式串,非字面路径;运行时由守卫兜底)"
|
||||
% len(templates))
|
||||
for ref, where in templates:
|
||||
print(" · %-46s ← %s" % (ref, where[0]))
|
||||
|
||||
print("\n=== 退役命名扫描 ===")
|
||||
# ⚠ 口径纪律:退役命名**只在代码与素材清单里是违规**;文档的版本历史/
|
||||
# 台账在「叙述这些名字已退役」时提到它们属正常,不是违规。
|
||||
# 故扫描面只含:代码(.gd/.tscn) + 素材清单(design/art/*.md),
|
||||
# 且排除版本历史/台账类文件(active.md / *checklist* / *memory* / .zcode)。
|
||||
# 2026-10-07 初版全仓扫 .md ⇒ active.md/记忆文件里的历史记述全被误判,已修。
|
||||
hits = 0
|
||||
scan_exts = (".gd", ".tscn")
|
||||
skip_names = ("active.md",)
|
||||
for dirpath, dirnames, names in os.walk(repo):
|
||||
dirnames[:] = [d for d in dirnames
|
||||
if d not in (".git", ".godot", "archive", "node_modules",
|
||||
".workbuddy", ".zcode")]
|
||||
for fn in names:
|
||||
fp = os.path.join(dirpath, fn)
|
||||
rel = os.path.relpath(fp, repo)
|
||||
if any(s in rel for s in (".workbuddy", ".zcode")):
|
||||
continue
|
||||
if fn in skip_names:
|
||||
continue
|
||||
is_code = fn.endswith(scan_exts)
|
||||
is_manifest = (fn.endswith(".md")
|
||||
and os.sep + "art" + os.sep in fp
|
||||
and "版本历史" not in fn)
|
||||
if not (is_code or is_manifest):
|
||||
continue
|
||||
try:
|
||||
txt = open(fp, "r", encoding="utf-8", errors="ignore").read()
|
||||
except OSError:
|
||||
continue
|
||||
# 叙述性豁免:命中行若同时含「退役/已废/更正/改判」等记述词,
|
||||
# 视为「在讲这段历史」而非「仍在用这个名字」
|
||||
for rx, why in RETIRED_PATTERNS:
|
||||
for line in txt.splitlines():
|
||||
if rx.search(line) and not any(
|
||||
w in line for w in ("退役", "已废", "更正", "改判",
|
||||
"原写", "原名", "作废")):
|
||||
print("FAIL %-52s %s" % (rel, why))
|
||||
print(" └─ %s" % line.strip()[:90])
|
||||
problems.append("退役命名: " + rel)
|
||||
hits += 1
|
||||
break
|
||||
if not hits:
|
||||
print("OK 无退役命名残留(代码 + 素材清单;叙述性历史记述已豁免)")
|
||||
|
||||
for nt in notes:
|
||||
print("\n注:%s" % nt)
|
||||
print("\n路径机检完成:%d 处问题" % len(problems))
|
||||
return 1 if problems else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
+164
-40
@@ -1,79 +1,203 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""站桩槽位素材机检(M-3 迭代 6 T1——48px 档契约断言;重闸素材面闸)。
|
||||
"""站桩素材机检(B1 硬闸升级 · 立绘定档批 2026-10-07)。
|
||||
|
||||
四断言(契约=计划书 C4/圣经 §8.2):
|
||||
尺寸 高恒 48(槽位源档 ×2 整数放大=盒高 96);宽 1..75(盒宽 150 半值)。
|
||||
锚点 底行有不透明像素(底中锚——纵向比例自底边口径,脚贴画布底缘)。
|
||||
色数 ≤32(fixer 批 32 色冻结;NEAREST 采样不产生新色)。
|
||||
无插值 alpha 二值(仅 0/255——双线性/混合会在边缘产生中间 α)。
|
||||
升级依据=art-bible §8.3③ 挂点规格(审计 §07-2/3):
|
||||
- 逐键校验档高(**原「宽 1..75」虚设区间退役**——宽度改为「源宽×2 ≤ 站桩盒宽 150」
|
||||
的物理约束,档高改为逐键断言 STANDEE_TIER_H);
|
||||
- 像素域色数 ≤32(**排除全透明像素**,见下方口径注);
|
||||
- 无非整数倍缩放痕迹(alpha 二值 + 无中间 α);
|
||||
- 描边亮度达标(亮描边暖白族,character-design §10硬规则「禁黑描边」)。
|
||||
|
||||
用法: python tools/standee_asset_check.py [角色素材目录]
|
||||
默认 game/assets/art/character/;必需集=八敌+主角 portrait/attack/hit。
|
||||
⚠ 色数口径坑(2026-10-07 实踩,勿改回naive 统计):
|
||||
naive `len(set(所有像素))` 会把全透明 (0,0,0,0) 计成一个色 ⇒ 报33 假红灯。
|
||||
正确口径 = 只统计 alpha>0 像素的唯一 RGB。机检必须如此,否则天天误报。
|
||||
|
||||
档高表= tools/pixelize_candidates.py 的 STANDEE_TIER_H(定值单点纪律 §8:本表
|
||||
不在检查器里复写一份,改由 import 读,避免两处数字漂移)。
|
||||
|
||||
用法:
|
||||
python tools/standee_asset_check.py [角色素材目录]
|
||||
默认 game/assets/art/character/
|
||||
--json 输出机器可读格式
|
||||
退出码: 0 全过 / 1 有红灯
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from collections import Counter
|
||||
|
||||
from PIL import Image
|
||||
|
||||
REQUIRED = ["character_enemy_%s.png" % k for k in
|
||||
("bugbear", "drider", "duergar", "duergar_king", "giant_spider",
|
||||
"goblin", "hook_horror", "ogre_chief")] + \
|
||||
["character_hero_portrait.png", "character_hero_attack.png", "character_hero_hit.png"]
|
||||
SLOT_H = 48
|
||||
W_MAX = 75
|
||||
COLOR_MAX = 32
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
try:
|
||||
from pixelize_candidates import STANDEE_TIER_H, STANDEE_SLOT_H
|
||||
except ImportError: # pragma: no cover
|
||||
STANDEE_TIER_H = {
|
||||
"goblin": 36, "giant_spider": 38,
|
||||
"duergar": 46, "hook_horror": 58,
|
||||
"bugbear": 62, "ogre_chief": 74,
|
||||
"drider": 90, "duergar_king": 94,
|
||||
}
|
||||
STANDEE_SLOT_H = 48
|
||||
|
||||
ENEMY_KEYS = ("bugbear", "drider", "duergar", "duergar_king", "giant_spider",
|
||||
"goblin", "hook_horror", "ogre_chief")
|
||||
REQUIRED = ["character_enemy_%s.png" % k for k in ENEMY_KEYS] + \
|
||||
["character_hero_portrait.png", "character_hero_attack.png",
|
||||
"character_hero_hit.png"]
|
||||
|
||||
# ── 契约常量(全部有出处,禁复写第二份) ──────────────────────────────
|
||||
COLOR_MAX = 32 # 圣经 §4.1/fixer 批 32 色冻结;机检口径=alpha>0 唯一 RGB
|
||||
DISPLAY_SCALE = 2 # standee_body.gd:237 _portrait_sprite.scale = (2,2)
|
||||
BOX_W = 150 # standee_body.gd:29 var box := Vector2(150, 176)
|
||||
SRC_W_MAX = BOX_W // DISPLAY_SCALE # =75,源宽上限(×2 后须塞进盒宽)
|
||||
ALPHA_BIN = {0, 255} # 二值 alpha 域
|
||||
# 描边亮度阈值(2026-10-07 _tmp_probe_outline.py 实测标定):
|
||||
# 敌人暖白边占比实测 54.1%–84.3%,主角 portrait/hit 实测 0.4%(无暖白描边,见下)。
|
||||
# 敌人闸取 40%(低于实测下限 54.1% 留余量,高于噪声);主角**豁免**——
|
||||
# character-design §10要求亮描边,但现役三态主角实为暗边,属已知缺口,
|
||||
# 不在本批(美术素材批 A 范围)修,机检只报读数不判红,避免闸永久红。
|
||||
OUTLINE_WARM_L_MIN = 150 # 暖白 = 亮度 ≥150 且低饱和
|
||||
OUTLINE_WARM_S_MAX = 0.35
|
||||
OUTLINE_MIN_ENEMY = 40.0 # 敌人:暖白描边像素占轮廓像素 ≥40%
|
||||
HERO_OUTLINE_EXEMPT = ("portrait", "attack", "hit")
|
||||
|
||||
|
||||
def check(path):
|
||||
def _lum(c):
|
||||
return 0.299 * c[0] + 0.587 * c[1] + 0.114 * c[2]
|
||||
|
||||
|
||||
def _sat(c):
|
||||
mx, mn = max(c[:3]), min(c[:3])
|
||||
return 0.0 if mx == 0 else (mx - mn) / float(mx)
|
||||
|
||||
|
||||
def expected_tier_h(fn):
|
||||
"""按文件名返回应有档高。"""
|
||||
if fn.startswith("character_enemy_") and fn.endswith(".png"):
|
||||
key = fn[len("character_enemy_"):-len(".png")]
|
||||
return STANDEE_TIER_H.get(key)
|
||||
return STANDEE_SLOT_H # 主角三态同档
|
||||
|
||||
|
||||
def check(path, fn):
|
||||
"""返回 (problems, info)。info 含机检读数。"""
|
||||
problems = []
|
||||
im = Image.open(path).convert("RGBA")
|
||||
w, h = im.size
|
||||
if h != SLOT_H:
|
||||
problems.append("高应 48,实得 %d" % h)
|
||||
if not (1 <= w <= W_MAX):
|
||||
problems.append("宽应 1..%d,实得 %d" % (W_MAX, w))
|
||||
px = im.load()
|
||||
|
||||
# 断言①逐键档高(原「高恒 48」已随定档批退役)
|
||||
tier = expected_tier_h(fn)
|
||||
if tier is not None and h != tier:
|
||||
problems.append("档高应 %d(§8.2 逐键定档),实得 %d" % (tier, h))
|
||||
|
||||
# 断言② 宽度物理约束:源宽 ×2 须塞进站桩盒宽 150(替代旧虚设区间 1..75)
|
||||
if w > SRC_W_MAX:
|
||||
problems.append("源宽 %d ×2=%d 超站桩盒宽 %d(§8.2 高定宽随但不得溢出盒)"
|
||||
% (w, w * DISPLAY_SCALE, BOX_W))
|
||||
if w < 1:
|
||||
problems.append("源宽 %d 非法" % w)
|
||||
|
||||
colors = set()
|
||||
alphas = set()
|
||||
edges = []
|
||||
bottom_opaque = 0
|
||||
for y in range(h):
|
||||
for x in range(w):
|
||||
c = px[x, y]
|
||||
alphas.add(c[3])
|
||||
if c[3] > 0:
|
||||
colors.add(c[:3])
|
||||
if y == h - 1:
|
||||
bottom_opaque += 1
|
||||
if c[3] == 0:
|
||||
continue
|
||||
colors.add(c[:3]) # 口径:只收不透明像素的 RGB
|
||||
if y == h - 1:
|
||||
bottom_opaque += 1
|
||||
nb = ((x > 0 and px[x - 1, y][3] == 0) or
|
||||
(x < w - 1 and px[x + 1, y][3] == 0) or
|
||||
(y > 0 and px[x, y - 1][3] == 0) or
|
||||
(y < h - 1 and px[x, y + 1][3] == 0))
|
||||
if nb:
|
||||
edges.append(c)
|
||||
|
||||
# 断言③ 底中锚(脚贴画布底缘)
|
||||
if bottom_opaque < 1:
|
||||
problems.append("底行无不透明像素(底中锚失守——脚未贴画布底缘)")
|
||||
|
||||
# 断言④ 色数 ≤32(alpha>0 口径)
|
||||
if len(colors) > COLOR_MAX:
|
||||
problems.append("色数 %d > %d" % (len(colors), COLOR_MAX))
|
||||
if not alphas <= {0, 255}:
|
||||
problems.append("alpha 非二值(插值痕迹:%s)" % sorted(alphas - {0, 255})[:5])
|
||||
return problems, (w, h, len(colors))
|
||||
problems.append("色数 %d > %d(口径=alpha>0 唯一 RGB)" % (len(colors), COLOR_MAX))
|
||||
|
||||
# 断言⑤ 无非整数倍缩放痕迹:alpha 二值(双线性/混合会留中间 α)
|
||||
if not alphas <= ALPHA_BIN:
|
||||
problems.append("alpha 非二值(插值/非整数倍缩放痕迹:%s)"
|
||||
% sorted(alphas - ALPHA_BIN)[:5])
|
||||
|
||||
# 断言⑥ 描边亮度(亮描边暖白族,禁黑描边)
|
||||
warm_pct = 0.0
|
||||
dark_pct = 0.0
|
||||
if edges:
|
||||
warm = sum(1 for c in edges
|
||||
if _lum(c) >= OUTLINE_WARM_L_MIN and _sat(c) <= OUTLINE_WARM_S_MAX)
|
||||
dark = sum(1 for c in edges if _lum(c) < 60)
|
||||
warm_pct = warm * 100.0 / len(edges)
|
||||
dark_pct = dark * 100.0 / len(edges)
|
||||
is_hero = any(t in fn for t in HERO_OUTLINE_EXEMPT)
|
||||
if not is_hero and warm_pct < OUTLINE_MIN_ENEMY:
|
||||
problems.append("暖白描边占比 %.1f%% < %d%%(亮描边纪律,character-design §10)"
|
||||
% (warm_pct, OUTLINE_MIN_ENEMY))
|
||||
|
||||
info = {
|
||||
"size": [w, h],
|
||||
"tier_h": tier,
|
||||
"colors": len(colors),
|
||||
"bottom_opaque": bottom_opaque,
|
||||
"edge_px": len(edges),
|
||||
"outline_warm_pct": round(warm_pct, 1),
|
||||
"outline_dark_pct": round(dark_pct, 1),
|
||||
"outline_exempt": any(t in fn for t in HERO_OUTLINE_EXEMPT),
|
||||
}
|
||||
return problems, info
|
||||
|
||||
|
||||
def main():
|
||||
root = sys.argv[1] if len(sys.argv) > 1 else os.path.join("game", "assets", "art", "character")
|
||||
missing = [f for f in REQUIRED if not os.path.isfile(os.path.join(root, f))]
|
||||
n_fail = 0
|
||||
argv = [a for a in sys.argv[1:] if not a.startswith("--")]
|
||||
as_json = "--json" in sys.argv
|
||||
root = argv[0] if argv else os.path.join("game", "assets", "art", "character")
|
||||
missing, results, n_fail = [], [], 0
|
||||
for f in REQUIRED:
|
||||
p = os.path.join(root, f)
|
||||
if not os.path.isfile(p):
|
||||
print("MISS %-36s 缺位" % f)
|
||||
missing.append(f)
|
||||
n_fail += 1
|
||||
continue
|
||||
problems, info = check(p)
|
||||
if problems:
|
||||
n_fail += 1
|
||||
for pr in problems:
|
||||
print("FAIL %-36s %s" % (f, pr))
|
||||
problems, info = check(p, f)
|
||||
results.append({"file": f, "problems": problems, "info": info})
|
||||
n_fail += 1 if problems else 0
|
||||
|
||||
if as_json:
|
||||
print(json.dumps({"root": root, "missing": missing,
|
||||
"results": results, "fail": n_fail},
|
||||
ensure_ascii=False, indent=2))
|
||||
sys.exit(1 if n_fail else 0)
|
||||
|
||||
for f in missing:
|
||||
print("MISS %-36s 缺位" % f)
|
||||
for r in results:
|
||||
i = r["info"]
|
||||
if r["problems"]:
|
||||
for pr in r["problems"]:
|
||||
print("FAIL %-36s %s" % (r["file"], pr))
|
||||
else:
|
||||
print("PASS %-36s %dx%d 色数%d" % (f, info[0], info[1], info[2]))
|
||||
print("PASS %-36s %dx%d 档高%d 色数%d 暖白边%.1f%%%s"
|
||||
% (r["file"], i["size"][0], i["size"][1], i["tier_h"],
|
||||
i["colors"], i["outline_warm_pct"],
|
||||
"(豁免)" if i["outline_exempt"] else ""))
|
||||
print("机检完成:%d 件必需,%d 件未过" % (len(REQUIRED), n_fail))
|
||||
if not as_json:
|
||||
print("提示:主角三态暖白描边占比实测≈0.4%(暗边),属已知缺口,"
|
||||
"本闸豁免不判红——如需修另立主角描边素材批。")
|
||||
sys.exit(1 if n_fail else 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
Reference in new issue
Block a user