并master(fix-ci-red-20261106批+精英专属池批): README能力行冲突并集(master营地五窗真输入化行+本批3行); 待办「卡片复核报告文件口径」条目删除——其不一致由本批复核凭据换代全数解掉(闸C6/doc-conventions/两技能件已对齐复核记录节即凭据); 读数: 流水线闸PASS(33条目·卡片口径4张全过)

This commit is contained in:
DKChan committed 2026-11-07 00:11:40 +08:00
commit 8bee626138
121 files changed
+1646 -52

No files matched your search

+70 -3
View File
@@ -14,9 +14,14 @@ r"""capability_audit.py — 能力清单、覆盖域表与 GDD 纯度机检(
tests//probe/)有 `func 方法(`,或该方法名能在 reports/需求卡片*.md 中找到(计划入口同 D 口径);两头都无=红。
F 覆盖域表:systems 每篇一行;状态∈{已覆盖,部分覆盖,未覆盖};非未覆盖行的「能力行」非空且每项都能
对上能力表里的行名;部分/未覆盖行的缺口非空且指待办清单。
G 判据出处随测注记(test-conventions §8.3):game/tests/** 与 game/probe/** 内每个验证函数
(函数体含 check(/check_quiet(/_problems.append(/push_error( 判定调用,定义行与 _check( 前缀除外)
须带 ≥1 条 `# oracle: <design/相对路径>:<行号> <判据一句>` 注记;指针指向存在的设计文档行且不出
design/ 全域。扫描面=game/tests/**+game/probe/**(sim/ 不进——测量面直构惯例)。
条件闸行豁免(代表用例含「条件闸」字样)不参与 D/E。
自检四道(防扫描面空转假绿):系统文档数、能力行数、manifest 套件数、覆盖表行数任一为零 ⇒ exit 2。
自检五道(防扫描面空转假绿):系统文档数、能力行数、manifest 套件数、覆盖表行数、判据注记扫描面文件数
任一为零 ⇒ exit 2。
用法:
python tools/capability_audit.py # 报告模式(红项只打印,不改退出码)
@@ -332,6 +337,67 @@ def check_coverage(cov_tables, names):
red(README.relative_to(REPO), 1, "覆盖域表", "%s 未在覆盖域表登记" % doc)
ORACLE_RE = re.compile(r"^#\s*oracle:\s*(\S+\.md):(\d+)\s+\S")
VERDICT_RE = re.compile(r"(?<![_\w])check(?:_quiet)?\(|_problems\.append\(|push_error\(")
ORACLE_FUNC_RE = re.compile(r"^(?:static\s+)?func\s+([A-Za-z_]\w*)")
def check_oracle_markers():
"""判据出处随测注记机检(G 道):验证函数须带 # oracle 注记,指针可核。"""
files = sorted((REPO / "game" / "tests").rglob("*.gd")) + sorted((REPO / "game" / "probe").glob("*.gd"))
files = [p for p in files if p.name != "test_kit.gd" and p.name != "run_all.gd"]
if not files:
selfcheck.append("判据出处注记扫描面零文件")
return 0, 0
marked = flagged = 0
for p in files:
rel = p.relative_to(REPO).as_posix()
lines = read(p).splitlines()
starts = []
for i, ln in enumerate(lines):
m = ORACLE_FUNC_RE.match(ln)
if m:
starts.append((m.group(1), i))
ranges = []
for j, (name, s0) in enumerate(starts):
e0 = (starts[j + 1][1] - 1) if j + 1 < len(starts) else len(lines) - 1
ranges.append((name, s0, e0))
for name, s0, e0 in ranges:
body = lines[s0:e0 + 1]
has_verdict = False
for ln in body:
st = ln.strip()
if st.startswith("func ") or st.startswith("#"):
continue # 定义行与注释行不作判定调用计
code = st.split("#")[0]
if VERDICT_RE.search(code):
has_verdict = True
break
if not has_verdict:
continue
oks = []
for ln in body:
st = ln.strip()
if st.startswith("#"):
m = ORACLE_RE.match(st)
if m:
oks.append(m)
if not oks:
red(rel, s0 + 1, "判据出处注记", "验证函数 %s 缺 # oracle 注记" % name)
flagged += 1
continue
marked += 1
for m in oks:
relp, no = m.group(1), int(m.group(2))
if not relp.replace("\\", "/").startswith("design/"):
red(rel, s0 + 1, "判据出处注记", "%s 指针越出 design/ 全域:%s" % (name, relp))
continue
tp = REPO / relp
if not tp.is_file() or not (1 <= no <= len(read(tp).splitlines())):
red(rel, s0 + 1, "判据出处注记", "%s 指针不可核:%s:%d(文件缺失或行号越界)" % (name, relp, no))
return marked, flagged
def main():
# GBK 控制台兜底(红项明细含 ✗ 等非 GBK 字符,编码崩=红项被吞不可见)
for stream in (sys.stdout, sys.stderr):
@@ -355,15 +421,16 @@ def main():
names, referenced = check_capability_rows(cap_tables, suites, funcs, cards_corpus())
missing_suites = check_suite_coverage(suites, referenced)
check_coverage(cov_tables, names)
oracle_marked, oracle_flagged = check_oracle_markers()
if selfcheck:
print("capability_audit 扫描面异常:")
for s in selfcheck:
print(" ! " + s)
print("| ── 能力审计:系统文档 %d 篇 · 能力行 %d · 套件 %d · 覆盖域表 %d 行 · 链断套件 %d · 红项 %d"
print("| ── 能力审计:系统文档 %d 篇 · 能力行 %d · 套件 %d · 覆盖域表 %d 行 · 链断套件 %d · oracle 注记函数 %d · 红项 %d"
% (len(system_docs()), len(names), len(suites),
sum(len(r) for _, r in cov_tables), len(missing_suites), len(reds)))
sum(len(r) for _, r in cov_tables), len(missing_suites), oracle_marked, len(reds)))
for path, line, check, msg in reds:
print(" ✗ [%s] %s:%d %s" % (check, path, line, msg))
if selfcheck: