3838 "work-plan" : ["标题" , "制定背景" , "总体要求" , "工作目标" , "主要任务" , "实施步骤" , "保障措施" ],
3939}
4040
41+ # 合法子型:结构与标准模板不同的真实写法(见对应 spec.md 撰写思路)。命中「签名」即视为
42+ # 该子型,放过标准模板章节缺失、改为提示,避免拿制式年报、公布式决定等去校验时误报缺章节。
43+ # 签名为 headings(须出现的标题集,子集匹配)或 phrase(正文标志短语)。
44+ SUBTYPE_SIGNATURES : dict [str , list [tuple [str , dict ]]] = {
45+ "report" : [("制式/年度报告" , {"headings" : {"总体情况" }})],
46+ "decision" : [("公布式决定" , {"phrase" : "现予公布" })],
47+ "order" : [("公布令" , {"phrase" : "现予公布" })],
48+ }
49+
50+
4151# 各文种常见结尾用语(与 prompts/core/drafting-thinking.md、style.md 一致)。
4252# 只收录有明确套语的文种;用于成稿结尾用语核对,提示性、不作硬错误。
4353ENDING_PHRASES = {
@@ -221,6 +231,16 @@ def check_format_redlines(content: str) -> list[str]:
221231 return warnings
222232
223233
234+ def match_subtype (doc_type : str , content : str , headings : set [str ]) -> str | None :
235+ """命中合法子型签名时返回子型名,否则 None;用于放过标准模板章节缺失。"""
236+ for name , signature in SUBTYPE_SIGNATURES .get (doc_type , []):
237+ if "headings" in signature and signature ["headings" ] <= headings :
238+ return name
239+ if "phrase" in signature and signature ["phrase" ] in content :
240+ return name
241+ return None
242+
243+
224244def audit_unsourced_specifics (content : str ) -> list [str ]:
225245 """0 幻觉审计:列出成稿里非占位的具体值(文号/日期/百分比/金额/数量),供逐项核对来源。"""
226246 findings : list [str ] = []
@@ -252,11 +272,18 @@ def main() -> int:
252272 missing = [section for section in REQUIRED_SECTIONS [args .doc_type ] if section not in headings ]
253273 structure_warnings = check_heading_structure (content )
254274
275+ subtype = None
255276 if missing :
256- print (f"[ERROR] { args .file } 缺少以下章节:" )
257- for section in missing :
258- print (f"- { section } " )
259- return 1
277+ subtype = match_subtype (args .doc_type , content , headings )
278+ if subtype is None :
279+ print (f"[ERROR] { args .file } 缺少以下章节:" )
280+ for section in missing :
281+ print (f"- { section } " )
282+ return 1
283+ print (
284+ f"[INFO] { args .file } 识别为「{ subtype } 」子型,标准模板章节"
285+ f"(缺 { '、' .join (missing )} )不强制,见 { args .doc_type } 的 spec.md 撰写思路。"
286+ )
260287
261288 if structure_warnings and args .strict_structure :
262289 print (f"[ERROR] { args .file } 层级结构存在以下问题:" )
@@ -271,7 +298,8 @@ def main() -> int:
271298 + check_title_punctuation (content )
272299 )
273300
274- print (f"[OK] { args .file } 章节完整,类型:{ args .doc_type } " )
301+ status = f"按「{ subtype } 」子型校验通过" if subtype else "章节完整"
302+ print (f"[OK] { args .file } { status } ,类型:{ args .doc_type } " )
275303 if structure_warnings :
276304 print ("[WARN] 检测到以下层级结构提醒:" )
277305 for item in structure_warnings :
0 commit comments