merge master(改动四类与两层模型)+手工合四文件:格式换代与新状态词并轨

This commit is contained in:
DKChan committed 2026-10-25 07:44:25 +08:00
commit c550654896
10 files changed
+440 -933

No files matched your search

+13 -21
View File
@@ -3,13 +3,7 @@
r"""pipeline_gate.py — 工作流程流水线闸(待办清单条目状态机+roadmap 迭代总表+需求卡片口径+一次交叉核)。
职责:机检待办清单条目(标题元数据与可选优先级档名/四属性齐备与旧属性名防回潮/状态词白名单/
改动面四档白名单/条件凭据/工程形态证据指认/状态段累积制/特批/零命中)与 roadmap 迭代总表(六列/状态四形态/卡片与报告存在性/编入时间与预计周期的
历史行「—」豁免/周期三条线(<5 与 >20 判红、超 10 须带日期特批标记)/单元格白名单/零命中);「已编迭代↔已写卡段↔迭代行
卡片列」交叉核只此一处。2026-10-18 卡片冲突修订批补两条卡片机检:C1 关联文档同步面的
文档义务口径(生效 2026-10-17)、C2 设计事实源声明(生效 2026-10-18)——两条都按文件名
日期只追新规生效日之后的卡,旧卡属 git 历史留档不回头改。2026-10-21 验收闭合批补 C3:
改动—验收对照表的结构检查(生效 2026-10-21)——只查节/列/行/必填格非空,不判断覆盖真假;
覆盖真假由独立验收审计判。
改动面四档白名单/条件凭据/无设计线段条目的证据指认/状态段累积制/特批/零命中)与 roadmap 迭代总表(六列/状态五形态/卡片与报告存在性/编入时间与预计周期的
约束:每红项一行「文件:行号 判据名 一句白话说明」,exit 0=全绿 / 1=有红 / 2=输入件缺失;
卡片与报告存在性相对 --repo-root 解析(缺省=本文件上两级);待办清单与 roadmap 均已为新格式
(2026-10-18 数据整改批),本闸已注册进 tools/run_all_gates.sh 文档域(08c 流水线闸)。
@@ -29,7 +23,7 @@ SURFACE_WORDS = ("文档", "美术素材", "游戏代码", "工具代码")
STATUS_WORDS = (
"待文档设计", "文档设计中", "文档设计已闭合",
"待美术设计", "美术设计中", "美术设计已闭合",
"待写卡", "已写卡", "已编迭代", "待裁决", "已写入",
"待写卡", "已写卡", "已编迭代", "待裁决", "已写入", "待执行",
)
# 这些状态 = 设计未闭合,条目必须带「**缺口**」属性;其余状态不得带
GAP_REQUIRED = ("待文档设计", "文档设计中", "待美术设计", "美术设计中")
@@ -38,6 +32,7 @@ DOWNSTREAM_WORDS = ("待写卡", "已写卡", "已编迭代")
DOC_DESIGN_WORDS = ("待文档设计", "文档设计中", "文档设计已闭合")
ART_DESIGN_WORDS = ("待美术设计", "美术设计中", "美术设计已闭合")
DESIGN_WORDS = DOC_DESIGN_WORDS + ART_DESIGN_WORDS
FANBU_WORDS = ("待裁决", "已写入") # 反哺点专条用词,不走设计线也不走下游序列
# 工程形态条目的证据指认形态:审计报告路径/文件:行号址/「证据=」句/审计 P 编号
EVIDENCE_RE = re.compile(r"reports/\S+|[\w/.\-]+:\d{2,}|证据\s*[==]|审计\s*P\d")
ROADMAP_HEADER = ("迭代代号", "状态", "需求卡片", "编入时间", "预计周期", "实现报告")
@@ -73,7 +68,7 @@ SURFACE_SEP_RE = re.compile(r"+|\+")
HEADING_RE = re.compile(r"^(#{1,4})\s+")
SEP_ROW_RE = re.compile(r"^\|[\s\-|:]+$")
STATUS_COL_RE = re.compile(
r"^(待开工|进行中|已完成\(\d{4}-\d{2}-\d{2}\)|已终止\(\d{4}-\d{2}-\d{2}\))$")
r"^(待开工|冻结待凑批|进行中|已完成\(\d{4}-\d{2}-\d{2}\)|已终止\(\d{4}-\d{2}-\d{2}\))$")
PERIOD_RE = re.compile(r"^≈(\d+(?:\.\d+)?)\s*个工作日$")
ITER_CODE_COL_RE = re.compile(r"^迭代\s*(\d+)")
@@ -189,7 +184,6 @@ def check_status(raw, line, issues, where):
words.append(w)
if it is not None:
iter_no = it
downstream = [w for w in words if w in DOWNSTREAM_WORDS]
# 同一设计线只留最新一段:并现两段说明推进时忘了收旧段,或把另一条线的段
# 误写进本线条目;跨条设计线的未闭合依赖(如文档线已闭合写卡、美术线仍待设计)合法。
for track, name in ((DOC_DESIGN_WORDS, "文档线"), (ART_DESIGN_WORDS, "美术线")):
@@ -197,9 +191,6 @@ def check_status(raw, line, issues, where):
if len(hit) > 1:
issues.append((where, line, "设计线段并现",
"%s同时出现 %s(同线只留最新一段,§12.1)" % (name, "、".join(hit))))
if not downstream and not any(w in DESIGN_WORDS for w in words) and "待裁决" not in words and "已写入" not in words:
issues.append((where, line, "状态词非法",
"状态行既无设计线段、也不在下游序列、也不是反哺点用词"))
return words, iter_no
@@ -291,12 +282,13 @@ def check_todo(text, issues, where, root):
issues.append((where, live_line, "正文缺美术凭据",
"状态段「美术设计已闭合」在场,但实况清单里没有 "
"art-bible 版本凭据(§12.1:证据写正文)"))
# 工程形态证据指认:整行无设计段且已进下游段 → 实况必须给得出证据
# 无设计线段条目的证据指认:需求性工程条目(待写卡及以后)与直改类条目(待执行)
# 都跳过设计线,实况必须给得出证据;反哺点专条不在此列。
if (words and not any(w in DESIGN_WORDS for w in words)
and any(w in DOWNSTREAM_WORDS for w in words)
and not any(w in FANBU_WORDS for w in words)
and not EVIDENCE_RE.search(live)):
issues.append((where, live_line, "工程形态缺证据指认",
"状态无设计段且已进下游段=工程形态条目,实况须指认证据"
issues.append((where, live_line, "无设计线段缺证据指认",
"状态整行无设计线段(需求性工程条目或直改类条目),实况须指认证据"
"(reports/ 路径/文件:行号址/「证据=」句/审计 P 编号,§12.1)"))
need_gap = any(w in GAP_REQUIRED for w in words)
if need_gap and "缺口" not in attrs:
@@ -362,7 +354,7 @@ def check_iter_table(block, issues, where, root):
status_n = norm_parens(status)
if not STATUS_COL_RE.match(status_n):
issues.append((where, ln, "总表状态列",
"「%s」不在四形态(待开工/进行中/已完成(YYYY-MM-DD)/已终止(YYYY-MM-DD))" % status))
"「%s」不在五形态(待开工/冻结待凑批/进行中/已完成(YYYY-MM-DD)/已终止(YYYY-MM-DD))" % status))
# 需求卡片列:路径逐卡查存在性;退役保留字与历史行「—」(无卡片制时期)豁免
if norm_parens(cards) not in (norm_parens(RESERVED_RETIRED), "—"):
for part in CARD_SEP_RE.split(cards):
@@ -372,7 +364,7 @@ def check_iter_table(block, issues, where, root):
"需求卡片列 %s 相对仓库根不存在" % part))
if date != "—" and not re.fullmatch(r"\d{4}-\d{2}-\d{2}", date):
issues.append((where, ln, "编入时间", "「%s」须为 YYYY-MM-DD(历史迭代不可考填「—」)" % date))
# 预计周期:≈N 个工作日(估时中值精确值);<5/>20 硬判红(特批标记不放行);10<x≤20 须格内带日期特批标记(§12.2/§12.4);历史行「—」跳过
# 预计周期:≈N 个工作日(估时中值精确值);>20 硬判红(特批不放行);10<x≤20 须格内带日期特批标记(§12.2/§12.4);<5 ⇒ 行状态须为「冻结待凑批」(2026-10-25 两层模型:卡片无门槛、迭代层冻结线);历史行「—」跳过
per_marks = APPROVAL_RE.findall(period)
per_core = APPROVAL_RE.sub("", period).strip()
pm = None if per_core == "—" else PERIOD_RE.match(per_core)
@@ -381,9 +373,9 @@ def check_iter_table(block, issues, where, root):
"「%s」须为「≈N 个工作日」形态(精确值不取整;历史迭代不可考填「—」)" % period))
elif pm is not None:
wd = float(pm.group(1))
if wd < 5:
if wd < 5 and "冻结待凑批" not in status:
issues.append((where, ln, "预计周期",
"「%s」低于 5 个工作日硬下限,不得编入" % period))
"「%s」低于 5 个工作日且未处「冻结待凑批」态——小卡可编入,迭代总量不足须冻结待凑批" % period))
elif wd > 20:
issues.append((where, ln, "预计周期",
"「%s」超过 20 个工作日硬上限,特批标记不放行,须拆批" % period))