From 7493aebca86c3b67bf32c7440e9d0e275b579c64 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Wed, 21 Oct 2026 05:51:17 +0800 Subject: [PATCH] =?UTF-8?q?chore(=E6=96=87=E6=A1=A3=E7=BC=BA=E9=99=B7?= =?UTF-8?q?=E8=AE=A2=E6=AD=A3=E4=B8=8E=E6=9C=BA=E6=A3=80=E8=A1=A5=E4=BB=B6?= =?UTF-8?q?):=20=E5=9B=9B=E4=BB=BD=E6=A0=B9=E6=96=87=E4=BB=B6=E7=94=A8?= =?UTF-8?q?=E8=AF=8D=E4=B8=8E=E6=AD=BB=E6=8C=87=E8=AE=A2=E6=AD=A3=EF=BC=8B?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=BC=95=E7=94=A8=E5=8F=AF=E6=A0=B8=E6=9C=BA?= =?UTF-8?q?=E6=A3=80=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修文档缺陷四处:AGENTS.md「收口」×2、「不得」×3 换白话;roadmap.md:87「对拍」「标旗」换代; reports/README.md 指向已迁移的 design/gdd/06-待办清单.md 改指仓库根;待办清单 iter19 遗留第⑦项 前半「数据配置.md:223 历史行死指」实查核销(该文件版本史行已随禁写变更记录规约消亡,现 212 行)。 补机检:tools/doc_ref_audit.py 核文档内「文件:行号」指针的目标存在性与行界,带扫描面为空与 引用数为零双自检;双向变异证据——注入不存在路径 EXIT=1、注入超界行号 EXIT=1、还原 EXIT=0。 doc_term 扫描面扩到四份根文件:扩面前实测这批文件自身含 3 处用语表废止词,先改现实再扩面, 扩面后「疑似现行」0、注入「完美排雷」见红 EXIT=1、还原 EXIT=0。 08d 引用可核暂不注册进闸壳:建档须改 game/tests/.gates/baseline.json,触 game/ 即要求代码域全量测试, 文档域批按测试两入口铁规零跑——注册欠账已登记待办清单。内容锚核对实测 81 处出 58 条未命中(约七成噪声), 按建议级交付不判红。文档域闸全绿。 --- AGENTS.md | 10 +- design/gdd/01-核心循环.md | 1 + reports/README.md | 2 +- roadmap.md | 2 +- tools/doc_ref_audit.py | 219 ++++++++++++++++++++++++++++++++++++++ tools/doc_term_audit.py | 10 +- tools/run_all_gates.sh | 3 + 待办清单.md | 19 +++- 8 files changed, 254 insertions(+), 12 deletions(-) create mode 100644 tools/doc_ref_audit.py diff --git a/AGENTS.md b/AGENTS.md index 2735d352..8d747e33 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -31,7 +31,7 @@ - `artwork/` — 在途图像素材唯一工作区(文档归文档/在途图归一处/终稿归游戏);整目录不入 git(.gitignore 强制),收口归档 `archive/` - `game/assets/art/` — 已验收终稿(入包被游戏加载);`game/` — 游戏工程本体(代码 + smoke/ 冒烟 + tests/ 单元集成) - `sim-data/` — 机器读数据产物;数据件不入 git(入库例外 = README+analyze.py+growth_model.py);MC 锚与读数常驻留盘,无数值调整禁重跑 -- `tools/` — python 工具脚本;`archive/` — 收口归档 zip(gitignored) +- `tools/` — python 工具脚本;`archive/` — 批次完结归档 zip(gitignored) - `reports/` — 过程件容器:**需求卡片**(写卡段产出,实现批的输入合同)+迭代批产出物(实现报告/代拍板追认单/GDD 反哺点清单);**实现批唯一可写目录**,只放 .md,不是事实源(细则见 `reports/README.md`) - 根目录:`README.md`(纯指路牌:设计/流程/当前位/待办四个链接,零规则重述)、`roadmap.md`(里程碑+迭代总表六列+顶部「当前位」节=现在做什么)、`待办清单.md`(流水线唯一登记处,条目级待办与状态)、`体验验证清单.md`(需真人试玩才能下结论的验证项)、`stage.txt`/`review-mode.txt`(运行开关);仓库根禁止再设会话状态文件(细则见 doc-conventions 第 10 节) @@ -56,22 +56,22 @@ - **仓库根禁止设会话状态文件**(`active.md` 已废除)——现状看 roadmap「当前位」,待办看待办清单,过程看 git 提交信息,产出物看 `reports/`;任何文档禁止另设「当前状态快照」节,两处记同一件事必然漂移(细则见 doc-conventions 第 10 节) - 测试执行两入口铁规——只有迭代 loop 开发与用户点名两个触发入口;其余会话零测试,需测试支撑先请示并注明未跑测 - 交付前验收 = 跑 `tools/run_all_gates.sh` **按改动域**全绿(唯一入口、唯一闸清单、唯一域划分,禁在文档另列);合回 master 由 worktree-guard 按 diff 推域校验回执强制(process-conventions §3) -- **两类批**——**迭代批**(代码实现,`/iter` 发射):**禁写 `design/` 整个目录与两份根流程清单(`待办清单.md`/`体验验证清单.md`)**(含新增/修改/删除),设计文档对它只读、是写测试与实现代码的输入依据;两份流程清单的条目状态只由流水线各段推进,实现批不得顺手改;产出物只准写 `reports/`;批末只跑代码域闸。**非迭代批**(工具/规则/文档改动):不占 roadmap 迭代号,按改动域跑闸。文档内容的落地走五段流水线相应段(文档设计段入口=doc-design 技能;登记条目格式由流水线闸强制) +- **两类批**——**迭代批**(代码实现,`/iter` 发射):**禁写 `design/` 整个目录与两份根流程清单(`待办清单.md`/`体验验证清单.md`)**(含新增/修改/删除),设计文档对它只读、是写测试与实现代码的输入依据;两份流程清单的条目状态只由流水线各段推进,实现批禁止顺手改;产出物只准写 `reports/`;批末只跑代码域闸。**非迭代批**(工具/规则/文档改动):不占 roadmap 迭代号,按改动域跑闸。文档内容的落地走五段流水线相应段(文档设计段入口=doc-design 技能;登记条目格式由流水线闸强制) - 五段流水线铁律——一切工作按「登记 → 文档设计/美术设计 → 写需求卡片 → 迭代编排 → 实现」推进,段间不自动流转、每段转进由用户发令;编入迭代的卡片必须设计闭合+零待裁点,流水线闸 `tools/pipeline_gate.py` 强制(已注册进 run_all_gates.sh 文档域);实现段零裁断——卡片没写清=上游缺陷,停该卡退回上游,禁内联求裁(process-conventions §2,格式与状态机=doc-conventions §12) - MC/模拟:无数值改动零跑;档位硬闸见 `sim-data/README.md`「MC 采集档位表」,一档只能由用户发起 - 闸机轮次纪律:新码先孤立验证 → 出红只跑红件最小单元 → 长批先最小参数试车 → 开工扫坑册(process-conventions §6) - 变异验证——新增/改写验收函数必须变异变红才算验收成立;无变异红记录只写「已实现,拦截能力未证」(test-conventions §6) -- **验收闭合**——每个需求点与每个行为改动都要有从真实入口进入的验收断言,撤销该改动能让对应断言变红;禁删断言/放宽阈值换绿;合回前独立验收审计未过不得合并(细则=test-conventions §9+iter 技能第 5 步) +- **验收闭合**——每个需求点与每个行为改动都要有从真实入口进入的验收断言,撤销该改动能让对应断言变红;禁删断言/放宽阈值换绿;合回前独立验收审计未过则禁止合并(细则=test-conventions §9+iter 技能第 5 步) - 规则评估——没在真实任务上评估过的规则修订,不算完成。 - 中间产物吸收即死——结论先吸收进权威文档、未决先迁待办清单,文件即删且永不提交(doc-conventions 第 11 节) - **禁写变更记录**——文档与代码文件内一律禁设「版本历史/修订记录/变更记录/修改记录/更新记录/更新日志」节或表格,禁写「本版改了哪些条款」式逐版本叙述与 `# 2026-xx-xx 缺陷修批——` 式行内修订注记;沿革只进 git commit log。版本号可作文档现行身份标记留在文首状态行与正文引用中(doc-conventions 第 5 节,机检闸 gdd_lint R4 反转拦截) - 用语红线——一切对用户输出禁自造黑话,需要作者解释的词必须展开成完整白话句(doc-conventions 第 4 节三形态表) - 呈报四问(读后自检制)——向用户首次完整呈报一件事(需求/缺陷/方案/结论)时,写完先自查:读者只读这一段,能否不看原文答出——① 现状差在哪:现在是什么、缺什么;② 你建议做什么:做完预期什么效果、会动到哪些面;③ 为什么选这个做法:考虑过、放弃过哪些别的路;④ 做完怎么验证:哪些还有把握不足。哪问答不出就补哪问,禁靠加小标题凑数;三句话能说清的小件合并为三句:现状一句、建议与验证一句、没把握的一句;后续追问与推进不必重跑全框架 -- 真人检测只登记不阻塞——登记进体验验证清单/实现报告即完成义务,禁以等目检为停工理由或收口前置 +- 真人检测只登记不阻塞——登记进体验验证清单/实现报告即完成义务,禁以等目检为停工理由或当作合回的前置条件 - 文件头 = `##` 文档注释,介绍本模块是什么;禁写变更叙事(改动史查 git log);禁文档反向链接(code-conventions §1.4.1) - 数值单一事实源——玩法数值只存 `data/tables/`(.tres)经 ConfigDB 单点读取;禁数值字面量与自建 `load()` 表路径 - RNG 单点——禁 `randomize()`/自建 RandomNumberGenerator,随机只经 `RngService` 统一流 - 架构事实唯一源——架构事实只认 `design/engineering/architecture/architecture.md`;禁立第二架构文档或决策文档体系,历史决策记录只进 git commit log - Core 层零 UI 依赖——完整战斗必须可 `--headless --script` 跑通;fail-fast——数据校验错误一律致命中止,无软回退 -- spec-AC 一致性——规约与验收标准不得在同一输入上给出不同答案;评审隔离——`/design-review` 必须独立会话跑(与 `/design-system` 隔离) +- spec-AC 一致性——规约与验收标准禁止在同一输入上给出不同答案;评审隔离——`/design-review` 必须独立会话跑(与 `/design-system` 隔离) - 像素结构件——先抄后造、验收写成像素级判据、±1px 坐标推导(process-conventions 第 7 节) diff --git a/design/gdd/01-核心循环.md b/design/gdd/01-核心循环.md index 124f3178..eab7ea80 100644 --- a/design/gdd/01-核心循环.md +++ b/design/gdd/01-核心循环.md @@ -160,3 +160,4 @@ **获取概率提升**是元进度/营地的合法提升轴(可提升=奇物高档位出现率/秘宝解锁进度/地图 T3/T4 权重),但**不动保底**——保底是承诺不是概率,禁止任何概率件改变 T3「每板必有回复」类承诺。 **专长 rarity 语义约束**:Boss 三选一候选按档配比或加权抽取,使罕见度对出现率生效(字段双脱钩修复——此前 rarity 不影响抽选也不稳代表幅度);具体配比归调参批。 + diff --git a/reports/README.md b/reports/README.md index 15e1e379..3216da5c 100644 --- a/reports/README.md +++ b/reports/README.md @@ -18,7 +18,7 @@ - **不放设计结论。** 本目录的文件是"待处理的申请单",不是事实源。反哺点由你在会话中讨论定稿后, 另开文档批写进 `design/`,写完即可删除本目录对应条目。 - **不放图。** 图像白名单不含本目录,放了会被熵增闸判红。 -- **不放进度状态。** 现在做什么看根 `roadmap.md` 顶部「当前位」节,待办与待裁看 `design/gdd/06-待办清单.md`(2026-10-18 用户裁:根目录会话状态文件已废除,本目录也不许兼做状态记录)。 +- **不放进度状态。** 现在做什么看根 `roadmap.md` 顶部「当前位」节,待办与待裁看仓库根 `待办清单.md`(2026-10-18 用户裁:根目录会话状态文件已废除,本目录也不许兼做状态记录)。 ## 生命周期 diff --git a/roadmap.md b/roadmap.md index 12e50979..8fbe34cf 100644 --- a/roadmap.md +++ b/roadmap.md @@ -84,7 +84,7 @@ > **迭代粒度界定(对齐敏捷迭代/Sprint)**:一个迭代 = 一句迭代目标 + **3–8 个更改任务** + 一份计划书 loop + 一次合并登记,交付一个可验证增量(≈一次迭代交付)。单交付物不成迭代——并入相邻迭代当任务卡;用户输入闸未解的任务不进迭代(留待办清单当 backlog,解闸后编入下一个迭代);**迭代周期 ≈ 一周左右**(2026-10-11 用户裁定——原「软时间盒 ≤3 个工作日,超限即切迭代」系 3abb3bd2 成文时自造、用户从未立过此规,就此废弃)。**里程碑 = 2–4 个迭代的发布级目标 + 出口验收闸(≈Release)**。 > 1. **计划书**(`.zcode/plans/<迭代名>-loop-plan-<日期>.md`):迭代目标与完成定义 / 现状事实(代码级,开工自行复核)/ 设计契约(违反即返工,标 🔴 触碰=L3 停机)/ 范围边界 / 任务卡 T0..Tn(逐卡估时)/ 验证闸 / 异常分级 / 代拍板白名单。 -2. **T0 开工**:建 worktree + 基线复读记档(冒烟/探针/三闸/MC 对拍基准)+ `git status` 归属核对(并行遗留只标旗不碰)。 +2. **T0 开工**:建 worktree + 基线复读记档(冒烟/探针/三闸/MC 与基线数据逐项比对基准)+ `git status` 归属核对(并行遗留只登记不触碰)。 3. **循环骨架**:一轮 = 一个任务卡——读卡 → 对事实源 → 实装 → 轻闸全绿 → 提交(代拍板随 commit 记录)→ 状态记录追加(查撞号)→ 下一轮。单 worktree 多点提交一次合并;轮内禁开第二个 worktree;基线每轮开工时点重测;断点续跑 = `git log` 对任务卡定轮次 + 重跑当轮轻闸。 4. **轻闸**(每轮必跑,headless):`tools/run_all_gates.sh --quick`(迭代中段自检档)。 5. **重闸**(批末 Tn):`tools/run_all_gates.sh` **按本批改动域跑**(触及 `game/` → `--code`,这是代码域唯一触发;不触及 `game/` 的一切路径 → `--docs`;一次改动同批混触两域 → 不带参数全量),所选域全绿——闸件清单、顺序与域划分只在该脚本里定义,本文件与 AGENTS.md/规约均不另列;改闸件自身(`tools/` 下机检脚本与闸壳)不占合回全量,质量义务=落批时的变异验证;涉核心的 MC 与基线逐位比对、素材批的机检断言另行。 diff --git a/tools/doc_ref_audit.py b/tools/doc_ref_audit.py new file mode 100644 index 00000000..3e400913 --- /dev/null +++ b/tools/doc_ref_audit.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python3 +r"""doc_ref_audit.py — 文档内代码引用可核检查(机检) + +职责:现行文档里凡写「某文件:第几行」,就该指得动。本工具核两件事: + ①路径可解析——目标文件在 git 受控文件清单里存在; + ②行号在界内——引用的行号不超过目标文件的实际行数。 +动机:条目与规约常写 `board_view.gd:737` 这类指针,代码前进后行号漂移、文件迁移改名, +账面就与现实脱节而无人知(2026-10-21 迭代 32 收尾时实测抓到两例)。 + +扫描面:`design/` 现行文档树 + 四份根文件(`待办清单.md`/`体验验证清单.md`/`roadmap.md`/`AGENTS.md`)。 +排除面:`reports/` 与 `design/research/`——两处是中间文档暂存地(doc-conventions 第 11 节), +入内文件按「吸收即死」退役,历史件不回溯改,故不入本闸判据。 + +自检二道(防假绿):扫描文件数为零 ⇒ FAIL;抽取到的引用数为零 ⇒ FAIL。 +(正则被改写失手或路径写错时,检查会静默空转并报绿——与 static_scan 各段同规。) + +判据分两档: + 红(判 FAIL)=路径不存在/行号超界; + 建议(只报告)=同名文件有多条路径需要人工定位/`--anchors` 的内容锚没在目标行附近找到。 + +用法: + python tools/doc_ref_audit.py # 全扫,报告模式 + python tools/doc_ref_audit.py --strict # 有红项时 exit 1(供门禁) + python tools/doc_ref_audit.py --anchors # 追加内容锚核对(只报告,不判红) + python tools/doc_ref_audit.py ... # 只扫指定文件 +exit:0=全绿 / 1=有红项(--strict)/ 2=扫描面异常(目录缺失) +""" +import argparse +import io +import os +import re +import subprocess +import sys +from pathlib import Path + +REPO = Path(__file__).resolve().parents[1] + +SCAN_DIRS = ["design"] +SCAN_EXCLUDE_DIRS = ["design/research"] +ROOT_FILES = ["待办清单.md", "体验验证清单.md", "roadmap.md", "AGENTS.md"] + +# 引用形态:路径或文件名 + 扩展名 + 半/全角冒号 + 行号。反引号可包在中间或外面, +# 因此先抓到扩展名为止,冒号允许紧跟或在反引号之后。 +REF_RE = re.compile( + r"([\w./一-鿿-]+\.(?:gd|tres|sh|py|json|md|cfg|yml|yaml|txt|png|html))" + r"[`”』」]?\s*[::]\s*(\d+)" +) +# 内容锚:同一行内的反引号片段或「」内文本,取长度 ≥4 的第一个非引用片段 +ANCHOR_RE = re.compile(r"`([^`\n]{4,60})`|「([^」\n]{4,60})」") +ANCHOR_WINDOW = 12 +# 留档信号(与 doc_term_audit 同口径):同句带日期或退役/注销类说明时,指向已不存在的路径 +# 属历史叙述而非现行指针,降为建议级报出、不判红。 +ARCHIVE_RE = re.compile( + r"\d{4}-\d{2}-\d{2}|退役|注销|已删|已废除|已废|废除|作废|历史|原名|改名|迁入|迁到|移到|迁至" +) + + +def tracked_files(): + out = subprocess.run( + ["git", "-c", "core.quotepath=false", "-C", str(REPO), "ls-files"], + capture_output=True, text=True, encoding="utf-8", errors="ignore", + ) + if out.returncode != 0: + return None + return {l.strip().strip('"').replace("\\", "/") for l in out.stdout.splitlines() if l.strip()} + + +def collect_docs(explicit): + if explicit: + return [p for p in explicit if Path(p).is_file()] + paths = [] + for d in SCAN_DIRS: + root = REPO / d + if not root.is_dir(): + return None + for p in sorted(root.rglob("*.md")): + rel = p.relative_to(REPO).as_posix() + if any(rel.startswith(x + "/") for x in SCAN_EXCLUDE_DIRS): + continue + paths.append(rel) + for f in ROOT_FILES: + if (REPO / f).is_file(): + paths.append(f) + return paths + + +def resolve(name, doc_rel, index, bybase): + """返回 (命中路径列表, 解析方式)。方式=exact / ambiguous / none。""" + name = name.strip("./") + if "/" in name: + for cand in ( + os.path.normpath(os.path.join(os.path.dirname(doc_rel), name)).replace("\\", "/"), + os.path.normpath(name).replace("\\", "/"), + ): + if cand in index: + return [cand], "exact" + return [], "none" + cands = sorted(bybase.get(name, [])) + if not cands: + return [], "none" + if len(cands) == 1: + return cands, "exact" + return cands, "ambiguous" + + +def line_count(path, cache): + if path not in cache: + try: + cache[path] = len(io.open(REPO / path, encoding="utf-8", errors="ignore").read().splitlines()) + except OSError: + cache[path] = 0 + return cache[path] + + +def anchor_of(line, name): + """取同句里可当内容锚的片段:反引号或「」内、长度 ≥4、且自身不是文件路径。""" + for m in ANCHOR_RE.finditer(line): + frag = (m.group(1) or m.group(2)).strip() + if name.split("/")[-1] in frag: + continue + if re.search(r"\.(gd|tres|sh|py|json|md|yaml|yml|html|png)$", frag): + continue + if re.fullmatch(r"[\d:~\-]+", frag): + continue + return frag + return None + + +def check(doc_rel, index, bybase, cache, anchors=False): + reds, advises = [], [] + text = io.open(REPO / doc_rel, encoding="utf-8", errors="ignore").read() + for ln, line in enumerate(text.splitlines(), 1): + for m in REF_RE.finditer(line): + name = m.group(1).lstrip("①②③④⑤⑥⑦⑧⑨⑩〔[[((「」·、。,,;;") + num = int(m.group(2)) + hits, how = resolve(name, doc_rel, index, bybase) + if how == "none": + if ARCHIVE_RE.search(line): + advises.append("%s:%d 引用已退役件 指 `%s`——同句带日期或退役/注销类说明,按留档处理" % (doc_rel, ln, name)) + else: + reds.append("%s:%d 引用可核/路径不存在 文档指 `%s`,git 受控文件清单里没有这件" % (doc_rel, ln, name)) + continue + if how == "ambiguous": + advises.append("%s:%d 同名多路径 指 `%s`——命中 %d 件(%s),需写全路径" % ( + doc_rel, ln, name, len(hits), ", ".join(hits[:3]))) + target = hits[0] + total = line_count(target, cache) + if num > total: + if ARCHIVE_RE.search(line): + advises.append("%s:%d 行号已越界(留档句) 指 `%s:%d`,目标现 %d 行——同句带退役/日期说明" % ( + doc_rel, ln, name, num, total)) + else: + reds.append("%s:%d 引用可核/行号超界 指 `%s:%d`,目标文件现只有 %d 行" % (doc_rel, ln, name, num, total)) + continue + if anchors: + frag = anchor_of(line, name) + if frag: + lines = io.open(REPO / target, encoding="utf-8", errors="ignore").read().splitlines() + lo, hi = max(0, num - 1 - ANCHOR_WINDOW), min(len(lines), num + ANCHOR_WINDOW) + window = "\n".join(lines[lo:hi]) + if frag not in window: + advises.append("%s:%d 内容锚未命中 指 `%s:%d`,同句片段「%s」不在该线 ±%d 行内" % ( + doc_rel, ln, os.path.basename(name), num, frag[:28], ANCHOR_WINDOW)) + return reds, advises + + +def main(): + ap = argparse.ArgumentParser(description="文档内代码引用可核检查") + ap.add_argument("files", nargs="*", help="指定文件;缺省扫 design/ 现行树+四份根文件") + ap.add_argument("--strict", action="store_true", help="有红项时 exit 1") + ap.add_argument("--anchors", action="store_true", help="追加内容锚核对(只报告)") + args = ap.parse_args() + + index = tracked_files() + if index is None: + print("引用可核 FAIL:git ls-files 取不到受控文件清单(扫描面异常)") + return 2 + docs = collect_docs(args.files) + if docs is None: + print("引用可核 FAIL:扫描目录缺失(design/ 不在位)") + return 2 + if not docs: + print("引用可核 FAIL:扫描面为空——路径写错导致的静默假绿") + return 1 + + bybase = {} + for p in index: + bybase.setdefault(p.rsplit("/", 1)[-1], []).append(p) + + cache, all_reds, all_adv = {}, [], [] + total_refs = 0 + for doc in docs: + reds, adv = check(doc, index, bybase, cache, anchors=args.anchors) + total_refs += doc_ref_count(doc) + all_reds += reds + all_adv += adv + if total_refs == 0: + print("引用可核 FAIL:抽取到的引用数为零——正则或扫描面失手,属假绿防线") + return 1 + + for r in all_reds: + print(r) + print("── 引用可核:扫描 %d 件文档 · 抽取引用 %d 处 · 红项 %d · 建议 %d" % ( + len(docs), total_refs, len(all_reds), len(all_adv))) + if all_adv: + for a in all_adv[:25]: + print(" (建议)" + a) + if len(all_adv) > 25: + print(" (建议)…另有 %d 条" % (len(all_adv) - 25)) + return 1 if (args.strict and all_reds) else 0 + + +def doc_ref_count(doc_rel): + text = io.open(REPO / doc_rel, encoding="utf-8", errors="ignore").read() + return sum(len(REF_RE.findall(l)) for l in text.splitlines()) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/doc_term_audit.py b/tools/doc_term_audit.py index 9ba0c203..3d5c8a8e 100644 --- a/tools/doc_term_audit.py +++ b/tools/doc_term_audit.py @@ -14,8 +14,9 @@ r"""doc_term_audit.py — GDD 退役术语扫描(半自动) python tools/doc_term_audit.py ... # 只扫指定文件 python tools/doc_term_audit.py --json # 机器可读 -口径:扫 design/gdd/ 与 design/art/ 两处文档域(2026-10-21 迭代 32 卡①反哺批扩面 art, -用户裁)——design/research(历史提案)、docs/(样例)与 production/ 不在扫描域; +口径:扫 design/gdd/ 与 design/art/ 两处文档域 + 四份根文件(`待办清单.md`/`体验验证清单.md`/ +`roadmap.md`/`AGENTS.md`,2026-10-21 迭代 32 卡①反哺批扩面,用户裁;根文件同属现行文本) +——design/research(历史提案)与 reports/(中间文档)不在扫描域; 词表扩充 = 改 RETIRED_TERMS(受 doc-conventions §4 词表冻结约束:唯一入口=用户实读反馈并经用户裁决)。 """ import argparse @@ -71,6 +72,10 @@ RETIRED_TERMS = [ ] DEFAULT_DIRS = ["design/gdd", "design/art"] +# 根规则与流程文件同属现行文本,2026-10-21 迭代 32 反哺批复测后纳入扫描面: +# 当日实测这批文件自身含 3 处用语表废止词(roadmap 的「对拍」「标旗」、AGENTS 的「收口」×2), +# 随同批订正后判红归零才扩面——先改现实、再让闸盯住现实,避免带红扩面。 +DEFAULT_FILES = ["待办清单.md", "体验验证清单.md", "roadmap.md", "AGENTS.md"] # 用语规范 A 表补充词专项补扫:随批/台账 两词本身是上方行级白名单信号(行内出现即归 # 留档类),主扫描对它们自豁免;本通道只做节外残留的专项报告,供后续触碰批清偿。 @@ -191,6 +196,7 @@ def main(): for d in DEFAULT_DIRS: paths += sorted(Path(d).rglob("*.md")) paths += sorted(Path(d).rglob("*.yaml")) + paths += [Path(f) for f in DEFAULT_FILES] paths = [p for p in paths if Path(p).exists()] findings = scan(paths) + scan_supplement(paths) diff --git a/tools/run_all_gates.sh b/tools/run_all_gates.sh index bd416d97..f094ab44 100644 --- a/tools/run_all_gates.sh +++ b/tools/run_all_gates.sh @@ -185,6 +185,9 @@ 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" --strict # ── 8c. 流水线闸(待办清单条目状态机+roadmap 迭代总表+一次交叉核,判据=doc-conventions §12)── gate "08c 流水线闸" "pipeline.log" "$PY" "$REPO/tools/pipeline_gate.py" +# 8d 引用可核(tools/doc_ref_audit.py,2026-10-21 交付)暂不注册:新闸件无基线记录必判「闸况变化」拦回执, +# 而建档要改 game/tests/.gates/baseline.json——触 game/ 即要求代码域全量测试(process-conventions §3.10 推域口径), +# 文档域批按测试两入口铁规零跑游戏测试。注册与建档随下一个触 game/ 的批次一并做(待办清单在册)。 fi # ── 6c. 回放确定性对拍(条件闸件;属代码域)── if in_domain code; then diff --git a/待办清单.md b/待办清单.md index a4185f2c..9e924cfd 100644 --- a/待办清单.md +++ b/待办清单.md @@ -513,9 +513,9 @@ 4. **迷雾对三关扩对**(iter19 卡②遗留):素材不入 git 致三关逐关 floor avg 实查受限,ui_contrast 迷雾测点现按在册单值 #453020;素材入库或授权读素材后,以 tools 脚本算三关逐关 avg→最亮者核合成(最坏情况判据契约 7 完整化)。**归属**:对比度探针面(前置=素材可读授权) 5. **字面量墨收测前置**(iter19 卡②遗留):bcard 属性描述/类型脚注/✓章/primary_button 字四处内联 Color8 无常量形态,收测需先在 ui_kit 立常量(呈现批顺路件,改 ui_kit 越当批面)。**归属**:呈现优化批(ui_kit 常量面) 6. **TG_* 装饰带非文字判据**(iter19 卡②遗留):卡顶类型色带为 8px Bayer 抖动装饰带(DitherBand),非文字;如需机检化(WCAG 1.4.11 非文字 3:1)另立探针段裁决。**归属**:对比度探针扩展段 -7. **数据配置.md:223 历史行死指 + 商店房截图纳屏**(iter19 卡①遗留):前者=v0.4 版本史行 backtick 指已退役探针(doc_link advisory 级不 FAIL,历史行不改写原则下留观,如需清零可下批 prose 化+补退役行);后者=商店房截图纳屏留后续呈现批(考证结论在 shot_probe 头注)。**归属**:文档卫生批/呈现批 +7. **商店房截图纳屏**(iter19 卡①遗留):商店房截图纳屏留后续呈现批(考证结论在 shot_probe 头注)。本项原并列的「`数据配置.md:223` 历史行死指」半句已于 2026-10-21 实查核销——禁写变更记录规约生效后该文件的版本史行整段已不存在(现全文 212 行,文内零版本史行),被指对象随之消亡。**归属**:呈现批 -**归属**:①熵增闸白名单 ②冒险结构/战斗开场参数面 ③⑤呈现优化批 ④⑥对比度探针面/扩展段 ⑦文档卫生批/呈现批——逐项见现状清单 +**归属**:①熵增闸白名单 ②冒险结构/战斗开场参数面 ③⑤呈现优化批 ④⑥对比度探针面/扩展段 ⑦呈现批——逐项见现状清单 **状态**:待写卡(备选) @@ -713,7 +713,7 @@ #### `game/` 域文档两处措辞订正欠账(2026-10-21 登记,来源=批次移交,设计面=工程直入) -**现状**:两处 `game/` 内文本与现实不符,改 `game/` 任何路径都会触发代码域全量测试(2026-10-20 用户裁「零代码批不改该行、登记欠账」),故不入本写入批:①`game/tests/static_scan.sh:100` S11 注释仍称「完美排雷」不在退役词对照表里——2026-10-21 起该词已入表(术语表退役词对照行在册),注释与 `:122` 追加行按「S11 权威=术语表解析」口径可一并订正;②`game/tests/README.md:58` 记「manifest 已登记实跑 26 套件」——迭代 32 卡② 后现况为 35 套件(含 counter_prefix_fatal 负面套件),以 `run_all.gd` 现况为准更新。 +**现状**:两处 `game/` 内文本与现实不符,改 `game/` 任何路径都会触发代码域全量测试(2026-10-20 用户裁「零代码批不改该行、登记欠账」),故不入本写入批:①`game/tests/static_scan.sh:100` S11 注释仍称「完美排雷」不在退役词对照表里——2026-10-21 起该词已入表(术语表退役词对照行在册),注释与 `:122` 追加行按「S11 权威=术语表解析」口径可一并订正;②`game/tests/README.md:58` 记「manifest 已登记实跑 26 套件」——迭代 32 卡② 后现况为 35 套件(含 counter_prefix_fatal 负面套件),以 `run_all.gd` 现况为准更新。同文件另两处 `design/qa/` 死指已另有在册条目(本清单「game/tests/README 分级表证据落点行仍指 design/qa/」),本条不重复登记。 **归属**:`game/tests/`(代码域,随下一个触碰 game/ 的批次顺带清) @@ -721,6 +721,16 @@ --- +#### 引用可核闸注册与建档欠账(2026-10-21 登记,来源=会话提及,设计面=工程直入) + +**现状**:新机检件 `tools/doc_ref_audit.py`(文档内「文件:行号」指针的存在性与行界核对,件头注即判据)已于 2026-10-21 交付并双向验证——注入不存在路径 EXIT=1、注入超界行号 EXIT=1、扫描面为空自判 FAIL、还原 EXIT=0(当日实测:63 件文档/81 处引用/红项 0/建议 6)。它**尚未注册进 `tools/run_all_gates.sh` 文档域**,原因=注册要把绿记录写进 `game/tests/.gates/baseline.json`(先例见 8f66ae15 之 08c 与 e8b6751b 之 06b),而改 `game/` 下任何路径都要求代码域回执、即跑全量游戏测试,文档域批按测试两入口铁规零跑(2026-10-20 用户裁「不为边际正确性付跑测成本」)。同批附带交付:`tools/doc_term_audit.py` 扫描面已扩到四份根文件(待办清单/体验验证清单/roadmap/AGENTS),扩面实测「疑似现行」0 处、变异注入见红 EXIT=1 还原 EXIT=0。内容锚核对(`--anchors`)实测 81 处引用出 58 条未命中,噪声约七成,按建议级交付不判红,待真实批次积累后再定是否收紧。 + +**归属**:`tools/run_all_gates.sh` 注册行+`game/tests/.gates/baseline.json` 建档(代码域批次顺带) + +**状态**:待写卡 + +--- + #### 迭代 32 移交项一——奇物门票三处玩家文案待定性后传导(2026-10-21 登记,来源=批次移交,设计面=文档轨) **现状**:「门票(专长门票)→专长凭证」已在 [术语表](design/gdd/术语表.md) 「退役词对照」在册;迭代 32 卡① 清了 `game/` 注释面的 36 处,但下列三处是**数据值与玩家可见文案**、属 奇物/专长 归类表述,需文档侧先定性才动,故本批只移交不改:①`game/data/tables/shop.tres:86` `"display_name": "奇物门票"`;②③`game/presentation/curio_interact_controller.gd:165`/`:166` 交互文案「奇物门票/选定即开一次奇物三选一」。代码闸拦不到它们——S11 只取注释面(.gd 取 # 后、.tres 取 ; 后),数据值与 UI 文案不在其扫描语义内。关联文档:[奇物](design/gdd/systems/冒险循环/奇物.md)(归类口径 owner,现行版本以文首状态行为准)。用户 2026-10-21 裁=与本清单「2026-10-18 冒记案遗留待裁两项」第②项(资源成员判据句)同源,待该项裁决后走传导批。 @@ -742,3 +752,6 @@ **归属**:design/gdd/ 各件(机制表述面)+ design/gdd/术语表.md(口径与除外注) **状态**:待文档设计 + + +