docs(验收闭合): 测试规范新增 §9 改动级验收闭合——每个需求点与行为改动都要真实入口断言+撤销证明,合回前独立验收审计
病根=测试规范 §5.2 只要求「每条清单条目至少一个自动断言」,没要求断言从改动的真实入口进入: 裸 EffectEngine 断言可替 BattleOrchestrator 接线,报告写「V1 绿」而 V1 断言并不存在。 - test-conventions §9(9.1–9.8):验收单位=行为改动;四层与真实入口;改动—验收对照表六列 双端对上(需求点正向、diff 反向、断言挂载测试侧);撤销证明(改既有行为回退变红、新增行为 变异变红);禁削弱测试;明确不要求 TDD;合回前独立验收审计;旧卡不回头改、开工前补齐 - process-conventions §3:第 7 条挂对照表、第 9 条补撤销证明、第 10 条合回前审计、新增第 16 条 - AGENTS.md 硬性红线新增「验收闭合」,与变异验证并列 - pipeline_gate 新增 C3:卡片须有对照表节、五个必需列、至少一行、必填格非空、全文声明验收审计; 只查结构不判语义(生效 2026-10-21,按卡片文件名日期追新) - reports/README 与 batch-closure 同步验收审计报告的落点与退役判据 - 待办清单登记「验收闭合规则——下一次迭代实测评估」,按规则评估红线等真实迭代检验
This commit is contained in:
1 parent
f103177471
commit
feaf01454a
6 files changed
+167
-8
No files matched your search
+91
-2
@@ -7,7 +7,9 @@ r"""pipeline_gate.py — 工作流程流水线闸(待办清单条目状态机
|
||||
历史行「—」豁免/周期≤2 周可特批豁免/单元格白名单/零命中);「已编迭代↔已写卡段↔迭代行
|
||||
卡片列」交叉核只此一处。2026-10-18 卡片冲突修订批补两条卡片机检:C1 关联文档同步面的
|
||||
文档义务口径(生效 2026-10-17)、C2 设计事实源声明(生效 2026-10-18)——两条都按文件名
|
||||
日期只追新规生效日之后的卡,旧卡属 git 历史留档不回头改。
|
||||
日期只追新规生效日之后的卡,旧卡属 git 历史留档不回头改。2026-10-21 验收闭合批补 C3:
|
||||
改动—验收对照表的结构检查(生效 2026-10-21)——只查节/列/行/必填格非空,不判断覆盖真假;
|
||||
覆盖真假由独立验收审计判。
|
||||
约束:每红项一行「文件:行号 判据名 一句白话说明」,exit 0=全绿 / 1=有红 / 2=输入件缺失;
|
||||
卡片与报告存在性相对 --repo-root 解析(缺省=本文件上两级);待办清单与 roadmap 均已为新格式
|
||||
(2026-10-18 数据整改批),本闸已注册进 tools/run_all_gates.sh 文档域(08c 流水线闸)。
|
||||
@@ -47,6 +49,12 @@ SOURCE_MARKS = ("设计事实源", "唯一事实源") # 两种合格写法,
|
||||
SYNC_HEADING_RE = re.compile(r"^#{2,3}\s*\d*\.?\s*关联文档同步面")
|
||||
BANNED_DOC_MARKS = ("design/", "../gdd/", "../registry/", "../research/", "../qa/",
|
||||
"../engineering/", "../ux/", "../art/", "roadmap.md", "AGENTS.md")
|
||||
# C3 改动—验收对照表(2026-10-21 验收闭合批,生效 2026-10-21)
|
||||
LEDGER_RULE_DATE = (2026, 10, 21)
|
||||
LEDGER_HEADING_RE = re.compile(r"^#{2,4}\s*.*(验收对照表|改动[—\-]验收)")
|
||||
LEDGER_REQUIRED = ("需求点", "改动", "验收测试", "真实入口")
|
||||
LEDGER_PROOF_MARKS = ("撤销", "变异", "证明")
|
||||
AUDIT_MARK = "验收审计"
|
||||
|
||||
DATE_RE = re.compile(r"\d{4}-\d{2}-\d{2}")
|
||||
VER_RE = re.compile(r"[vV]\d+(?:\.\d+)*")
|
||||
@@ -411,13 +419,88 @@ def card_date(path):
|
||||
return tuple(int(x) for x in found[-1].split("-"))
|
||||
|
||||
|
||||
def check_ledger(text, path, issues):
|
||||
"""C3 改动—验收对照表结构检查(生效 2026-10-21)。
|
||||
|
||||
只查:对照表节在不在、表头有没有五个必需列、有没有数据行、必填格空不空。
|
||||
不判断测试是否真的覆盖改动——那是独立验收审计的职责,机器闸不猜语义。
|
||||
"""
|
||||
lines = text.splitlines()
|
||||
start = None
|
||||
for i, raw in enumerate(lines):
|
||||
if LEDGER_HEADING_RE.match(raw.strip()):
|
||||
start = i
|
||||
break
|
||||
if start is None:
|
||||
issues.append((str(path), 1, "验收对照表缺失",
|
||||
"须含「改动—验收对照表」节(2026-10-21 起,req-card §8)"))
|
||||
return
|
||||
|
||||
header = None
|
||||
header_line = 0
|
||||
for i in range(start + 1, len(lines)):
|
||||
s = lines[i].strip()
|
||||
if s.startswith("#") and not LEDGER_HEADING_RE.match(s):
|
||||
break
|
||||
if s.startswith("|") and not SEP_ROW_RE.match(s):
|
||||
header = row_cells(s)
|
||||
header_line = i + 1
|
||||
break
|
||||
if header is None:
|
||||
issues.append((str(path), start + 1, "验收对照表缺表",
|
||||
"节内未找到表格"))
|
||||
return
|
||||
|
||||
idx = {}
|
||||
for name in LEDGER_REQUIRED:
|
||||
hit = next((k for k, cell in enumerate(header) if name in cell), None)
|
||||
if hit is None:
|
||||
issues.append((str(path), header_line, "验收对照表缺列",
|
||||
"缺「%s」列" % name))
|
||||
return
|
||||
idx[name] = hit
|
||||
proof_hit = next((k for k, cell in enumerate(header)
|
||||
if any(mark in cell for mark in LEDGER_PROOF_MARKS)), None)
|
||||
if proof_hit is None:
|
||||
issues.append((str(path), header_line, "验收对照表缺列",
|
||||
"缺「撤销或变异证明」列"))
|
||||
return
|
||||
idx["证明"] = proof_hit
|
||||
|
||||
rows = 0
|
||||
for i in range(header_line, len(lines)):
|
||||
s = lines[i].strip()
|
||||
if not s:
|
||||
continue
|
||||
if not s.startswith("|"):
|
||||
break
|
||||
if SEP_ROW_RE.match(s):
|
||||
continue
|
||||
cells = row_cells(s)
|
||||
if len(cells) < len(header):
|
||||
issues.append((str(path), i + 1, "验收对照表缺格",
|
||||
"列数少于表头(%d<%d)" % (len(cells), len(header))))
|
||||
continue
|
||||
rows += 1
|
||||
for name, k in idx.items():
|
||||
if k >= len(cells) or not cells[k].strip():
|
||||
issues.append((str(path), i + 1, "验收对照表空格",
|
||||
"「%s」列为空" % name))
|
||||
if rows == 0:
|
||||
issues.append((str(path), header_line, "验收对照表零行",
|
||||
"表内没有数据行"))
|
||||
|
||||
|
||||
def check_cards(root, issues):
|
||||
"""C1 文档义务口径(生效 2026-10-17)+C2 设计事实源声明(生效 2026-10-18)。
|
||||
"""C1 文档义务口径(生效 2026-10-17)+C2 设计事实源声明(生效 2026-10-18)
|
||||
+C3 改动—验收对照表结构(生效 2026-10-21)。
|
||||
|
||||
只检文件名日期达生效日的卡——更早的卡属已实现批次的历史留档,不回头改。
|
||||
C1 判据:「关联文档同步面」表内,目标格指向 design/ 或根规则文件、而义务格仍写
|
||||
「随批」者红(2026-10-17 req-card §6 改口径后,这类点只能列 reports/ 反哺点清单)。
|
||||
C2 判据:全文既无「设计事实源」也无「唯一事实源」者红(两种写法都与库内实态对齐)。
|
||||
C3 判据:有「改动—验收对照表」节;表头含需求点/改动/验收测试/真实入口/证明列;
|
||||
至少一行;必填格非空;全文含「验收审计」声明。语义覆盖不在此判。
|
||||
"""
|
||||
dirn = root / CARD_DIR
|
||||
if not dirn.is_dir():
|
||||
@@ -434,6 +517,12 @@ def check_cards(root, issues):
|
||||
issues.append((str(path), 1, "设计事实源缺失",
|
||||
"须含「设计事实源」或「唯一事实源」声明句(req-card §2 三选一,"
|
||||
"GDD 节+版本号/样张+art-bible 版本/工程直入证据指认)"))
|
||||
if when >= LEDGER_RULE_DATE:
|
||||
check_ledger(text, path, issues)
|
||||
if AUDIT_MARK not in text:
|
||||
issues.append((str(path), 1, "独立验收审计未声明",
|
||||
"须在卡内写明独立验收审计入口与报告文件(2026-10-21 起,"
|
||||
"test-conventions §9.7)"))
|
||||
if when < SYNC_RULE_DATE:
|
||||
continue
|
||||
in_sec = False
|
||||
|
||||
Reference in new issue
Block a user