工程(流水线闸): 验收对照表加「能力行」列——2026-10-29 起生效,既有名回核 game/tests/README.md 能力表
check_ledger 增第七列:每行写 既有:<能力名> 或 新增:<能力名>(分号可多段)。既有名须在能力表首列可查,新增放行(新能力行由写卡段落表,test-conventions §8.9 滞后一迭代)。日期门控对齐 BINDING_RULE_DATE 同构:文件名日期早于 2026-10-29 的旧卡不回头改。自测四况通过(既有命中/新增放行/既有不存在红/格式错红/缺列红/旧卡免检)。req-card 与 iter 两技能本地件同批同步(不进 git):对照表改七格、写卡段增删能力行并刷最后验证批次、实现批禁写 README。
This commit is contained in:
1 parent
ae3c99e34e
commit
f32634446e
1 file changed
+52
-2
+52
-2
@@ -55,6 +55,9 @@ LEDGER_PROOF_MARKS = ("撤销", "证明")
|
||||
BINDING_RULE_DATE = (2026, 10, 28) # req-card §8:换代为判据绑定面列,撤销/变异证明列同日禁列
|
||||
BANNED_PROOF_MARKS = ("撤销证明", "变异证明")
|
||||
AUDIT_MARK = "验收审计"
|
||||
CAP_ROW_RULE_DATE = (2026, 10, 29) # req-card §8:每行标能力归属(对齐 test-conventions §8.9 三层模型)
|
||||
CAP_ROW_RE = re.compile(r"^(既有|新增)\s*[::]\s*(.+)$")
|
||||
CAP_README = Path("game/tests/README.md")
|
||||
|
||||
DATE_RE = re.compile(r"\d{4}-\d{2}-\d{2}")
|
||||
VER_RE = re.compile(r"[vV]\d+(?:\.\d+)*")
|
||||
@@ -453,7 +456,30 @@ def card_date(path):
|
||||
return tuple(int(x) for x in found[-1].split("-"))
|
||||
|
||||
|
||||
def check_ledger(text, path, when, issues):
|
||||
def capability_names(root):
|
||||
"""game/tests/README.md 能力表首列行名集合;文件或表缺失返回空集(调用方据此判红)。"""
|
||||
p = root / CAP_README
|
||||
if not p.is_file():
|
||||
return set()
|
||||
names = set()
|
||||
header = None
|
||||
for raw in p.read_text(encoding="utf-8").splitlines():
|
||||
s = raw.strip()
|
||||
if not s.startswith("|"):
|
||||
header = None
|
||||
continue
|
||||
cells = row_cells(s)
|
||||
if header is None:
|
||||
header = cells
|
||||
continue
|
||||
if SEP_ROW_RE.match(s):
|
||||
continue
|
||||
if any("代表用例" in c for c in header) and cells:
|
||||
names.add(cells[0].strip("`").strip())
|
||||
return names
|
||||
|
||||
|
||||
def check_ledger(text, path, when, issues, root):
|
||||
"""C3 改动—验收对照表结构检查(生效 2026-10-21)。
|
||||
|
||||
只查:对照表节在不在、表头有没有五个必需列、有没有数据行、必填格空不空。
|
||||
@@ -517,6 +543,18 @@ def check_ledger(text, path, when, issues):
|
||||
return
|
||||
idx["证明"] = proof_hit
|
||||
|
||||
cap_hit = None
|
||||
cap_names = None
|
||||
if when >= CAP_ROW_RULE_DATE:
|
||||
cap_hit = next((k for k, cell in enumerate(header) if "能力行" in cell), None)
|
||||
if cap_hit is None:
|
||||
issues.append((str(path), header_line, "验收对照表缺列",
|
||||
"缺「能力行」列(2026-10-29 起:每行写 既有:<能力名> 或 "
|
||||
"新增:<能力名>,对齐能力清单)"))
|
||||
return
|
||||
idx["能力行"] = cap_hit
|
||||
cap_names = capability_names(root)
|
||||
|
||||
rows = 0
|
||||
for i in range(header_line, len(lines)):
|
||||
s = lines[i].strip()
|
||||
@@ -536,6 +574,18 @@ def check_ledger(text, path, when, issues):
|
||||
if k >= len(cells) or not cells[k].strip():
|
||||
issues.append((str(path), i + 1, "验收对照表空格",
|
||||
"「%s」列为空" % name))
|
||||
if cap_hit is not None:
|
||||
cap_cell = cells[cap_hit] if cap_hit < len(cells) else ""
|
||||
for seg in [x.strip() for x in re.split(r"[;;]", cap_cell) if x.strip()]:
|
||||
m = CAP_ROW_RE.match(seg)
|
||||
if not m:
|
||||
issues.append((str(path), i + 1, "能力行格式",
|
||||
"「能力行」格须写 既有:<能力名>/新增:<能力名>:%s"
|
||||
% seg[:24]))
|
||||
elif m.group(1) == "既有" and m.group(2).strip("`").strip() not in cap_names:
|
||||
issues.append((str(path), i + 1, "能力行不可核",
|
||||
"既有能力「%s」不在 game/tests/README.md 能力表"
|
||||
% m.group(2).strip("`").strip()[:24]))
|
||||
if rows == 0:
|
||||
issues.append((str(path), header_line, "验收对照表零行",
|
||||
"表内没有数据行"))
|
||||
@@ -569,7 +619,7 @@ def check_cards(root, issues):
|
||||
"须含「设计事实源」或「唯一事实源」声明句(req-card §2 三选一,"
|
||||
"GDD 节+版本号/样张+art-bible 版本/工程形态证据指认)"))
|
||||
if when >= LEDGER_RULE_DATE:
|
||||
check_ledger(text, path, when, issues)
|
||||
check_ledger(text, path, when, issues, root)
|
||||
if AUDIT_MARK not in text:
|
||||
issues.append((str(path), 1, "独立验收审计未声明",
|
||||
"须在卡内写明独立验收审计入口与报告文件(2026-10-21 起,"
|
||||
|
||||
Reference in new issue
Block a user