rules(规则审阅落地批): 十条评审意见落地——呈报四问/文件头缩窄/禁词表冻结/lean死条文退役/日期批注清除/AGENTS瘦身/分域闸口径/状态栏纯化
- AGENTS.md: 呈报六问改读后自检四问;文件头红线删行数上限与白名单;日期批注清除;回执五况细则挪 process-conventions §3.10;流水线闸过时状态句改事实句 - process-conventions: §1.2 非迭代批改按改动域跑闸;§3.10 承接五况;两处日期批注清除;§2 表格凭据落点改现状清单 - code-conventions: §1.4.1 重写(删 8 行上限/两类白名单/90 文件清偿义务);§2.1 联动;两处日期批注清除 - test-conventions: 三处日期批注清除(三处实证日期属证据保留) - doc-conventions: §1 lean 死条文删除;§4 词表冻结条款;§12.1 重写(状态行只写状态词;现状=关联文档清单;删括号凭据全部条款);三处日期批注清除;§5 重复词修复 - 术语表: 用语规范节加词表冻结句 - 06-待办清单: 11 条带括号状态行迁移(括号证据移入现状关联文档清单;待裁决说明并入现状;每条状态行只留状态词) - tools/audit_file_headers.py: 删 R1 行数上限(R0 载体/R2 日期/R3 变更叙事保留) - tools/gdd_lint.py: R2 表格占比判据与 R2_EXEMPT 整体退役(lean 解读对象已亡,只产存量噪音) - tools/doc_term_audit.py: 词表冻结注释 - tools/pipeline_gate.py: 状态栏括号凭据核对废止,新增状态行禁括号判据(点名病因短路);闭合证据改现状正文核对(卡片路径磁盘存在性+交叉核、文档路径+版本、art-bible+版本) - game/tests/static_scan.sh: S10 注释同步 变异验证(test-conventions §6):pipeline_gate 注入括号→状态行含括号内容红 exit1;删正文卡片路径→正文缺卡片路径+交叉核红 exit1;audit_file_headers 注入变更叙事→R2/R3 红 exit1、头注 12 行纯说明→0 红(上限停用实证)。坑册新增:未提交工作区禁 git checkout 变异还原(会连带回滚在途改动),须备份文件法。 全批净变化 +155/−146(12 文件)。
This commit is contained in:
1 parent
880ee91b20
commit
811f988032
12 files changed
+155
-146
No files matched your search
@@ -3,9 +3,8 @@
|
||||
"""audit_file_headers.py — 文件头机器闸(code-conventions §1.4.1)。
|
||||
|
||||
文件头 = .gd 文件顶部连续注释区:连续的空行或 # 注释行,首个非注释代码行止。
|
||||
本脚本只实现机械可判子集(两类白名单的人判面见规范正文):
|
||||
本脚本只实现机械可判子集(2026-10-20 缩窄:行数上限 R1 与类别白名单已停用):
|
||||
R0 载体:头注非空时首行必须以 `##` 文档注释开头;
|
||||
R1 行数上限:头注注释行(非空)> 8 行;
|
||||
R2 日期:头注出现日期模式(2026-09-12 / 2026年9月 一类)——日期只属于 git log 与迭代报告;
|
||||
R3 变更叙事词:「迭代N / 本迭代」、批次叙事复合词(本批/拆件批/改造批……)、「迁移到/改名为」
|
||||
一类变更经过。清单从紧防误伤:「结算批」等玩法机制词不在黑名单;
|
||||
@@ -20,8 +19,6 @@ from pathlib import Path
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
SCAN_DIRS = ["game/core", "game/data", "game/presentation"]
|
||||
|
||||
MAX_HEADER_LINES = 8
|
||||
|
||||
DATE_PAT = re.compile(r"\d{4}\s*[-/.年]\s*\d{1,2}")
|
||||
NARRATIVE_PATS = [
|
||||
(re.compile(r"迭代\s*\d|本迭代"), "变更叙事「迭代N」"),
|
||||
@@ -52,9 +49,6 @@ def audit_path(path):
|
||||
rows = header_lines(text)
|
||||
if rows and not rows[0][1].lstrip().startswith("##"):
|
||||
hits.append((rows[0][0], "R0 头注必须以 ## 文档注释开头"))
|
||||
if len(rows) > MAX_HEADER_LINES:
|
||||
hits.append((rows[0][0], "R1 头注 %d 行 > 上限 %d 行(区间 %d-%d 行)"
|
||||
% (len(rows), MAX_HEADER_LINES, rows[0][0], rows[-1][0])))
|
||||
for lineno, line in rows:
|
||||
if DATE_PAT.search(line):
|
||||
hits.append((lineno, "R2 头注日期"))
|
||||
@@ -77,7 +71,7 @@ def main():
|
||||
if violations:
|
||||
print("[audit_file_headers] FAIL: 文件头存量 %d 处(存量按 code-conventions §1.4.1 白名单清偿)" % violations)
|
||||
return 1
|
||||
print("[audit_file_headers] ok: 头注 ≤8 行且零黑名单命中")
|
||||
print("[audit_file_headers] ok: 头注零黑名单命中(R0 载体/R2 日期/R3 变更叙事)")
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ RETIRED_TERMS = [
|
||||
("雾格", "2026-09-14", "(雾格移除)", "不做清单"),
|
||||
("兄弟精", "2026-09-26", "L2 熊地精(bugbear 复用)", "变体名未经批准退役批——用户质问查证后全仓清除"),
|
||||
# —— 用语规范(2026-10-15 用户令):权威=design/gdd/术语表.md「用语规范」A 表,机器闸吸收 ——
|
||||
# 词表冻结:本节禁再新增词条;扩表唯一入口=用户实读反馈并经用户裁决,由非迭代批写入,agent 禁自行增词
|
||||
# (doc-conventions §4「词表冻结」)。
|
||||
# 注意:「随批」「台账」两词本身是上方行级白名单信号(行内出现即归留档类),对其扫描会自豁免,
|
||||
# 故不列入;「收口」「在飞」等照常扫描。术语表「用语规范」节已加入节级豁免(词表自身不命中)。
|
||||
("对标", "2026-10-15", "参照", "用语规范 A 表(STC 1.7)"),
|
||||
|
||||
+7
-29
@@ -9,7 +9,6 @@ r"""gdd_lint.py — GDD lean 格式门禁
|
||||
|
||||
规则(口径权威 = design/engineering/doc-conventions.md 第 5–6 节文档骨架与结构纪律):
|
||||
R1 散文段落 ≤ 240 字(代码块/表格/列表/引用不计)
|
||||
R2 表格字符占比(词条表分域豁免,见 R2_EXEMPT 注)
|
||||
R3 正文禁止修订注记:~~删除线~~、"作废"、括号内"日期+评审/修订/拍板/裁决/核销"
|
||||
(登记处/清单按 RULE_EXEMPT 分域豁免)
|
||||
R4 禁止变更记录节:出现「版本历史/修订记录/变更记录/修改记录/更新记录/更新日志」标题即红
|
||||
@@ -31,29 +30,18 @@ import sys
|
||||
from pathlib import Path
|
||||
|
||||
MAX_PARA = 240
|
||||
# 2026-09-14 放宽 60→30:lean 改革后的新模板(参考 analysis/design 两件套)允许
|
||||
# 短段落与编号人话规则——防铺开的职责改由 R1(段 ≤240 字)与 R9(节点 ≤80 行)承担,
|
||||
# R2 降为兜底下限(防纯散文文档)。
|
||||
MIN_TABLE_RATIO = 30
|
||||
# R2 表格占比判据已停用(2026-10-20 规则审阅批):lean 体系退役后其解读对象已不存在,
|
||||
# 分域豁免越加越多、只产存量噪音(af94ce97 指纹刷新为证),判据与 R2_EXEMPT 一并拆除。
|
||||
MAX_PAREN_SPAN = 80
|
||||
|
||||
# 规则分域(2026-10-03 用户裁「测试要快/要准」优化批):R1/R2 的体裁前提是「规范文」
|
||||
# (短段+表格化);登记处/清单/概念文的自然形态就是长条目与叙事散文,硬套=自 2026-09-20
|
||||
# 规则分域(2026-10-03 用户裁「测试要快/要准」优化批):R1 的体裁前提是「规范文」
|
||||
# (短段+表格化);登记处/清单的自然形态就是长条目与叙事散文,硬套=自 2026-09-20
|
||||
# 上线起 8/8 常红零过滤价值(test-perf-report-2026-10-02 §6.2 实证)。R3/R7 不豁免——
|
||||
# 「provenance 出正文」对一切体裁有效;R4 变更记录节禁令自 2026-10-19 起对一切体裁有效。
|
||||
R1_EXEMPT = {
|
||||
"06-待办清单.md", # 全项目待办登记处:现状/状态/方案长条目为体裁
|
||||
"07-体验验证清单.md", # 体验验证读数清单:同上
|
||||
}
|
||||
R2_EXEMPT = {
|
||||
"01-核心循环.md", # 循环概念文:叙事散文为体裁
|
||||
"03-内容规模.md", # 规模框架文:多维档位靠散文交代,结构表只有一张
|
||||
"04-美术音频方向.md", # 美术方向文:同上
|
||||
"05-不做清单.md", # 清单文:条目散文为体裁
|
||||
"06-待办清单.md",
|
||||
"07-体验验证清单.md",
|
||||
"术语表.md", # 词条表:表格为主体形态,表格占比高是体裁本身
|
||||
}
|
||||
# 规则粒度分域豁免(2026-10-15 用户令「清单类文件与术语表不做 GDD 规范性检查」)。
|
||||
# 原则:**按规则豁免,不按文件拉黑**——体裁规则(R3/R5/R7)对登记处/清单/词条表
|
||||
# 不适用,但机械可判的完整性规则(R4/R6/R8/R9/R11)一律不豁免,真缺陷不得藏起来。
|
||||
@@ -201,17 +189,7 @@ def lint_file(path):
|
||||
if len(p) > MAX_PARA:
|
||||
issues.append(f"R1 散文段 {len(p)} 字(>{MAX_PARA}): {p[:50]}…")
|
||||
|
||||
# R2 表格占比(概念/方向/清单文分域豁免,见 R2_EXEMPT 注)
|
||||
code_chars = sum(len(l) for l in code_lines)
|
||||
table_chars = sum(len(l) for l in text.splitlines() if l.strip().startswith("|"))
|
||||
total = max(len(text) - code_chars, 1)
|
||||
ratio = int(100 * table_chars / total)
|
||||
if fname in R2_EXEMPT:
|
||||
infos.append(f"表格占比 {ratio}%(R2 分域豁免)")
|
||||
elif ratio < MIN_TABLE_RATIO:
|
||||
issues.append(f"R2 表格占比 {ratio}%(<{MIN_TABLE_RATIO}%)")
|
||||
else:
|
||||
infos.append(f"表格占比 {ratio}%")
|
||||
# R2 表格占比已停用(见文件头注释)。
|
||||
|
||||
# R3 修订注记(代码块豁免;登记处/清单按 RULE_EXEMPT 豁免——变更记录节已整体禁设,无豁免域)
|
||||
body_no_code = "\n".join(l for l in text.splitlines() if l not in code_lines)
|
||||
@@ -307,7 +285,7 @@ def lint_file(path):
|
||||
issues.append(f"R7 最长括号跨度 {longest_span} 字(>{MAX_PAREN_SPAN})——疑似审计注记挤进正文")
|
||||
infos.append(f"最长括号跨度 {longest_span} 字")
|
||||
|
||||
return {"file": str(path), "issues": issues, "infos": infos, "table_ratio": ratio}
|
||||
return {"file": str(path), "issues": issues, "infos": infos}
|
||||
|
||||
|
||||
def main():
|
||||
@@ -347,7 +325,7 @@ def main():
|
||||
else:
|
||||
for r in results:
|
||||
mark = "❌ FAIL" if r["issues"] else "✅ PASS"
|
||||
print(f"\n{mark} {r['file']} (表格占比 {r['table_ratio']}%)")
|
||||
print(f"\n{mark} {r['file']}")
|
||||
for i in r["infos"]:
|
||||
print(f" · {i}")
|
||||
for issue in r["issues"]:
|
||||
|
||||
+71
-41
@@ -119,8 +119,12 @@ def check_title(title, line, issues, where):
|
||||
return face
|
||||
|
||||
|
||||
def check_segment(word, creds, line, issues, where, root):
|
||||
"""判据 3 的单段校验。返回 (合法状态词|None, 已写卡路径|None, 已编迭代号|None)。"""
|
||||
def check_segment(word, line, issues, where):
|
||||
"""判据 3 的单段校验。返回 (合法状态词|None, 已编迭代号|None)。
|
||||
|
||||
2026-10-20 状态栏纯化批:状态行只写状态词(§12.1),括号凭据已废止——
|
||||
闭合证据改到现状关联文档清单核对(check_todo 内),本函数只认状态词本身。
|
||||
"""
|
||||
def red(name, msg):
|
||||
issues.append((where, line, name, msg))
|
||||
|
||||
@@ -128,40 +132,24 @@ def check_segment(word, creds, line, issues, where, root):
|
||||
base = "已编迭代" if word.startswith("已编迭代") else word
|
||||
if im is None and base == "已编迭代":
|
||||
red("状态词非法", "「%s」缺迭代号(须「已编迭代 N」)" % word)
|
||||
return None, None, None
|
||||
return None, None
|
||||
if base not in STATUS_WORDS:
|
||||
red("状态词非法", "「%s」不在合法状态词白名单" % word)
|
||||
return None, None, None
|
||||
cred_text = ";".join(creds)
|
||||
if base in ("文档设计已闭合", "已写入"):
|
||||
if not (VER_RE.search(cred_text) and ("/" in cred_text or ".md" in cred_text)):
|
||||
red("凭据缺失", "「%s」须带括号落点凭据(文档路径+版本号形态)" % base)
|
||||
elif base == "美术设计已闭合":
|
||||
if not ("art-bible" in cred_text.lower() and VER_RE.search(cred_text)):
|
||||
red("凭据缺失", "「美术设计已闭合」凭据须含 art-bible 路径+版本号")
|
||||
elif base == "已写卡":
|
||||
rp = None
|
||||
for c in creds:
|
||||
m = RESEARCH_RE.search(c)
|
||||
if m:
|
||||
rp = m.group(0)
|
||||
break
|
||||
if rp is None:
|
||||
red("凭据缺失", "「已写卡」括号内须为 reports/ 下的需求卡片路径")
|
||||
elif not (root / rp).is_file():
|
||||
red("卡片路径不存在", "已写卡路径 %s 相对仓库根不存在" % rp)
|
||||
return base, rp, None
|
||||
red("状态词非法", "「%s」不在合法状态词白名单" % base)
|
||||
return None, None
|
||||
if im is not None:
|
||||
return base, None, int(im.group(1))
|
||||
return base, None, None
|
||||
return base, int(im.group(1))
|
||||
return base, None
|
||||
|
||||
|
||||
def check_status(raw, line, face, issues, where, root):
|
||||
"""判据 3+状态段累积制(§12.1)+特批/备选。返回 (状态词列表, 已写卡路径列表, 已编迭代号|None)。
|
||||
def check_status(raw, line, face, issues, where):
|
||||
"""判据 3+状态段累积制(§12.1)+特批/备选。返回 (状态词列表, 已编迭代号|None)。
|
||||
|
||||
累积制:按+切段后段数不限,逐段各自合法;再查两条结构约束——
|
||||
下游段(待写卡/已写卡/已编迭代)在场时上游闭合段必须在场(带日期特批可豁免);
|
||||
双轨设计阶段(无下游段)必须恰两段且一文档一美术。
|
||||
状态行只写状态词(§12.1):去掉特批标记与(备选)后缀后,残留任何括号即红——
|
||||
证据写现状关联文档清单,由 check_todo 到正文核对;此处点名病因后短路,
|
||||
不再产出碎片「状态词非法」误导红。
|
||||
"""
|
||||
content = raw.strip()
|
||||
m = re.match(r"^\*\*(.+)\*\*$", content)
|
||||
@@ -175,28 +163,28 @@ def check_status(raw, line, face, issues, where, root):
|
||||
issues.append((where, line, "特批标记", "〔用户特批〕缺日期(带 YYYY-MM-DD 才放行跳轨)"))
|
||||
content = APPROVAL_RE.sub("", content)
|
||||
content = content.replace("(备选)", "").replace("(备选)", "").strip()
|
||||
if re.search(r"[(())]", content):
|
||||
issues.append((where, line, "状态行含括号内容",
|
||||
"括号里的信息(路径/版本/说明)写进现状关联文档清单,状态行只留状态词(§12.1)"))
|
||||
return [], None
|
||||
segs = [s.strip() for s in content.split("+") if s.strip()]
|
||||
if not segs:
|
||||
issues.append((where, line, "状态词非法", "状态行内容为空"))
|
||||
return [], [], None
|
||||
words, cards, iter_no = [], [], None
|
||||
return [], None
|
||||
words, iter_no = [], None
|
||||
for seg in segs:
|
||||
creds = CRED_RE.findall(seg)
|
||||
word = CRED_RE.sub("", seg).strip()
|
||||
w, rp, it = check_segment(word, creds, line, issues, where, root)
|
||||
w, it = check_segment(seg, line, issues, where)
|
||||
if w:
|
||||
words.append(w)
|
||||
if rp:
|
||||
cards.append(rp)
|
||||
if it is not None:
|
||||
iter_no = it
|
||||
downstream = [w for w in words if w in DOWNSTREAM_WORDS]
|
||||
if downstream and face in PRESENCE_FACES and not dated_approval:
|
||||
need = []
|
||||
if face in ("文档轨", "双轨") and "文档设计已闭合" not in words:
|
||||
need.append("文档设计已闭合(凭据)")
|
||||
need.append("文档设计已闭合")
|
||||
if face in ("美术轨", "双轨") and "美术设计已闭合" not in words:
|
||||
need.append("美术设计已闭合(凭据)")
|
||||
need.append("美术设计已闭合")
|
||||
if need:
|
||||
issues.append((where, line, "在场约束",
|
||||
"下游段(%s)在场但缺上游闭合段 %s(带日期特批可豁免)"
|
||||
@@ -208,11 +196,16 @@ def check_status(raw, line, face, issues, where, root):
|
||||
issues.append((where, line, "双轨段数",
|
||||
"设计面=双轨设计阶段须恰两段且一文档一美术(现 %d 段:文档轨 %d、美术轨 %d)"
|
||||
% (len(segs), n_doc, n_art)))
|
||||
return words, cards, iter_no
|
||||
return words, iter_no
|
||||
|
||||
|
||||
def check_todo(text, issues, where, root):
|
||||
"""06 全部判据。返回交叉核链(已编迭代条目 → (行号, 迭代号, 卡片路径|None))。"""
|
||||
"""06 全部判据。返回交叉核链(已编迭代条目 → (行号, 迭代号, 卡片路径|None))。
|
||||
|
||||
2026-10-20 状态栏纯化批:闭合类状态词的证据核对从状态栏括号改到现状关联文档
|
||||
清单(§12.1「状态行只写状态词」)——已写卡对 reports/ 卡片路径+磁盘存在性,
|
||||
文档轨闭合/已写入对 design/ 路径+版本号,美术轨闭合对 art-bible+版本号。
|
||||
"""
|
||||
entries = parse_todo(text)
|
||||
links = []
|
||||
if not entries:
|
||||
@@ -233,8 +226,45 @@ def check_todo(text, issues, where, root):
|
||||
issues.append((where, line, "属性缺失", "条目缺「**%s**」属性" % req))
|
||||
if "状态" not in attrs:
|
||||
continue
|
||||
words, cards, iter_no = check_status(
|
||||
attrs["状态"], attr_line["状态"], face, issues, where, root)
|
||||
words, iter_no = check_status(
|
||||
attrs["状态"], attr_line["状态"], face, issues, where)
|
||||
# 现状属性全文(含清单续行):证据核对只看现状,其他属性不算数
|
||||
xian_lines, in_xian = [], False
|
||||
for ln, raw in e["body"]:
|
||||
m = ATTR_LINE_RE.match(raw.strip())
|
||||
if m:
|
||||
in_xian = m.group(1) == "现状"
|
||||
if in_xian:
|
||||
xian_lines.append(m.group(2))
|
||||
elif in_xian:
|
||||
xian_lines.append(raw)
|
||||
xian = "\n".join(xian_lines)
|
||||
xline = attr_line.get("现状", line)
|
||||
# 证据核对一:已写卡 → 现状清单须有卡片路径,逐条验磁盘存在
|
||||
cards = []
|
||||
if "已写卡" in words:
|
||||
cards = RESEARCH_RE.findall(xian)
|
||||
if not cards:
|
||||
issues.append((where, xline, "正文缺卡片路径",
|
||||
"状态段「已写卡」在场,但现状关联文档清单里没有 "
|
||||
"reports/需求卡片-*.md 路径(§12.1:证据写正文)"))
|
||||
else:
|
||||
for rp in cards:
|
||||
if not (root / rp).is_file():
|
||||
issues.append((where, line, "卡片路径不存在",
|
||||
"现状清单里的卡片路径 %s 相对仓库根不存在" % rp))
|
||||
# 证据核对二:文档轨闭合/反哺已写入 → 现状清单须有文档路径+版本号
|
||||
# (06 正文里的指针是相对路径,形如 systems/… 或 design/…,只认 .md 收尾+版本号)
|
||||
if "文档设计已闭合" in words or "已写入" in words:
|
||||
if not (re.search(r"[^\s ,,()()]+\.md", xian) and VER_RE.search(xian)):
|
||||
issues.append((where, xline, "正文缺设计定稿指针",
|
||||
"状态段含文档轨闭合词,但现状清单里没有带版本号的文档路径(§12.1:证据写正文)"))
|
||||
# 证据核对三:美术轨闭合 → 现状清单须有 art-bible 版本凭据
|
||||
if "美术设计已闭合" in words:
|
||||
if not ("art-bible" in xian.lower() and VER_RE.search(xian)):
|
||||
issues.append((where, xline, "正文缺美术凭据",
|
||||
"状态段「美术设计已闭合」在场,但现状清单里没有 "
|
||||
"art-bible 版本凭据(§12.1:证据写正文)"))
|
||||
need_gap = any(w in GAP_REQUIRED for w in words)
|
||||
if need_gap and "缺口" not in attrs:
|
||||
issues.append((where, line, "缺口属性",
|
||||
|
||||
Reference in new issue
Block a user