54 lines
2.1 KiB
Python
54 lines
2.1 KiB
Python
from __future__ import annotations
|
|
|
|
from review_agent.models import FileSummaryBatch
|
|
from review_agent.regulatory_review.schemas import Finding
|
|
|
|
|
|
def run_completeness_check(batch: FileSummaryBatch, rule_set: dict) -> list[Finding]:
|
|
items = list(batch.items.order_by("file_index"))
|
|
findings: list[Finding] = []
|
|
for requirement in rule_set.get("requirements", []):
|
|
if requirement.get("type") not in {"required", "conditional", "recommended", "chapter", "directory"}:
|
|
continue
|
|
matched = [
|
|
item
|
|
for item in items
|
|
if _matches_item(
|
|
item.file_name,
|
|
item.relative_path,
|
|
item.directory_level,
|
|
[*requirement.get("file_keywords", []), *requirement.get("aliases", [])],
|
|
)
|
|
]
|
|
if matched:
|
|
continue
|
|
findings.append(
|
|
Finding(
|
|
rule_code=requirement["code"],
|
|
category=requirement.get("category", "completeness"),
|
|
severity=requirement.get("severity", "medium"),
|
|
title=f"缺少{_numbered_title(requirement)}",
|
|
detail=f"当前文件汇总批次未发现{_numbered_title(requirement)}。",
|
|
suggestion=requirement.get("suggestion", ""),
|
|
evidence={
|
|
"requirement_type": requirement.get("type"),
|
|
"matched_files": [],
|
|
"searched_keywords": requirement.get("file_keywords", []),
|
|
"searched_fields": ["file_name", "relative_path", "directory_level"],
|
|
},
|
|
)
|
|
)
|
|
return findings
|
|
|
|
|
|
def _matches_item(file_name: str, relative_path: str, directory_level: str, keywords: list[str]) -> bool:
|
|
haystack = f"{file_name} {relative_path} {directory_level}".lower()
|
|
return any(str(keyword).lower() in haystack for keyword in keywords)
|
|
|
|
|
|
def _numbered_title(requirement: dict) -> str:
|
|
attachment4_code = requirement.get("attachment4_code")
|
|
if not attachment4_code:
|
|
return requirement["title"]
|
|
return f"{attachment4_code}{requirement['title']}"
|