#!/usr/bin/env python3 """审计现有干预文件和当前规则的贴合度。 这个脚本用于回答两个问题: 1. 现有单句精确干预/正则干预文件自身是否存在明显格式问题。 2. 当前 label-master 校验、type_match_agent 下发表和历史数据是否匹配。 它不会修改任何文件,只输出 JSON 摘要和少量样例。 """ from __future__ import annotations import argparse import re from collections import Counter, defaultdict from pathlib import Path from typing import Any from intervention_common import ( DEFAULT_EXACT_SOURCE, DEFAULT_REGEX_SOURCE, build_source_summary, domain_compatible, infer_configured_dispatch_domain, json_dumps, load_exact_records, load_label_validator, load_regex_records, ) def sample_append(bucket: list[dict[str, Any]], item: dict[str, Any], limit: int) -> None: if len(bucket) < limit: bucket.append(item) def validate_unique_targets(targets: set[str]) -> dict[str, dict[str, Any]]: validator = load_label_validator() return {target: validator.validate(target) for target in sorted(targets)} def audit_exact_records(summary: dict[str, Any], target_results: dict[str, dict[str, Any]], sample_limit: int) -> dict[str, Any]: records = load_exact_records(Path(summary["source_files"]["exact"])) empty_fields = Counter() target_invalid = Counter() configured_mismatch = Counter() duplicate_keys: dict[tuple[str, str], list[Any]] = defaultdict(list) samples = { "empty_fields": [], "invalid_targets": [], "configured_domain_mismatch": [], "conflicts": [], } for record in records: if not record.device: empty_fields["device"] += 1 if not record.query: empty_fields["query"] += 1 if not record.target: empty_fields["target"] += 1 if not record.dispatch_domain: empty_fields["dispatch_domain"] += 1 if any(not value for value in (record.device, record.query, record.target, record.dispatch_domain)): sample_append(samples["empty_fields"], record.__dict__, sample_limit) result = target_results.get(record.target) if result and not result.get("valid"): target_invalid[record.target] += 1 sample_append( samples["invalid_targets"], { "line_no": record.line_no, "target": record.target, "errors": result.get("errors", []), }, sample_limit, ) configured = infer_configured_dispatch_domain(record.target, record.device, summary) if configured and not domain_compatible(record.dispatch_domain, configured["dispatch_domain"]): configured_mismatch[configured["matched_key"]] += 1 sample_append( samples["configured_domain_mismatch"], { "line_no": record.line_no, "device": record.device, "query": record.query, "target": record.target, "dispatch_domain": record.dispatch_domain, "configured": configured, }, sample_limit, ) duplicate_keys[(record.device, record.query)].append(record) conflicts = [] duplicate_count = 0 for (device, query), items in duplicate_keys.items(): if len(items) <= 1: continue duplicate_count += len(items) variants = {(item.target, item.dispatch_domain) for item in items} if len(variants) > 1: conflict = { "device": device, "query": query, "lines": [item.line_no for item in items[:10]], "variants": sorted([{"target": target, "dispatch_domain": domain} for target, domain in variants], key=str), } conflicts.append(conflict) sample_append(samples["conflicts"], conflict, sample_limit) return { "total": len(records), "empty_fields": dict(empty_fields), "invalid_target_total": sum(target_invalid.values()), "invalid_target_top": dict(target_invalid.most_common(20)), "configured_domain_mismatch_total": sum(configured_mismatch.values()), "configured_domain_mismatch_top": dict(configured_mismatch.most_common(20)), "duplicate_row_count_by_device_query": duplicate_count, "conflict_key_count": len(conflicts), "samples": samples, } def audit_regex_records(target_results: dict[str, dict[str, Any]], summary: dict[str, Any], sample_limit: int) -> dict[str, Any]: records = load_regex_records(Path(summary["source_files"]["regex"])) empty_fields = Counter() regex_errors = Counter() anchor_warnings = 0 missing_query_fragment = 0 target_invalid = Counter() duplicate_keys: dict[tuple[str, str], list[Any]] = defaultdict(list) samples = { "empty_fields": [], "regex_errors": [], "missing_query_fragment": [], "invalid_targets": [], "conflicts": [], } for record in records: if not record.device: empty_fields["device"] += 1 if not record.pattern: empty_fields["pattern"] += 1 if not record.target: empty_fields["target"] += 1 if any(not value for value in (record.device, record.pattern, record.target)): sample_append(samples["empty_fields"], record.__dict__, sample_limit) if record.pattern: try: re.compile(record.pattern) except re.error as exc: regex_errors[str(exc)] += 1 sample_append( samples["regex_errors"], {"line_no": record.line_no, "pattern": record.pattern, "error": str(exc)}, sample_limit, ) if "query#" not in record.pattern: missing_query_fragment += 1 sample_append(samples["missing_query_fragment"], record.__dict__, sample_limit) if not record.pattern.startswith("^") or not record.pattern.endswith("$"): anchor_warnings += 1 result = target_results.get(record.target) if result and not result.get("valid"): target_invalid[record.target] += 1 sample_append( samples["invalid_targets"], { "line_no": record.line_no, "target": record.target, "errors": result.get("errors", []), }, sample_limit, ) duplicate_keys[(record.device, record.pattern)].append(record) conflicts = [] duplicate_count = 0 for (device, pattern), items in duplicate_keys.items(): if len(items) <= 1: continue duplicate_count += len(items) variants = {item.target for item in items} if len(variants) > 1: conflict = { "device": device, "pattern": pattern, "lines": [item.line_no for item in items[:10]], "variants": sorted(variants), } conflicts.append(conflict) sample_append(samples["conflicts"], conflict, sample_limit) return { "total": len(records), "empty_fields": dict(empty_fields), "regex_error_total": sum(regex_errors.values()), "regex_error_top": dict(regex_errors.most_common(20)), "missing_query_fragment": missing_query_fragment, "anchor_warning_count": anchor_warnings, "invalid_target_total": sum(target_invalid.values()), "invalid_target_top": dict(target_invalid.most_common(20)), "duplicate_row_count_by_device_pattern": duplicate_count, "conflict_key_count": len(conflicts), "samples": samples, } def main() -> int: parser = argparse.ArgumentParser(description="审计现有干预文件") parser.add_argument("--exact-source", default=str(DEFAULT_EXACT_SOURCE), help="单句精确干预 TSV 路径") parser.add_argument("--regex-source", default=str(DEFAULT_REGEX_SOURCE), help="正则干预 TSV 路径") parser.add_argument("--sample-limit", type=int, default=5, help="每类问题最多输出样例数") args = parser.parse_args() summary = build_source_summary(Path(args.exact_source), Path(args.regex_source)) exact_records = load_exact_records(Path(args.exact_source)) regex_records = load_regex_records(Path(args.regex_source)) target_results = validate_unique_targets({record.target for record in exact_records + regex_records if record.target}) payload = { "source_files": summary["source_files"], "devices": summary["devices"], "counts": summary["counts"], "target_validation": { "unique_targets": len(target_results), "valid_unique_targets": sum(1 for item in target_results.values() if item.get("valid")), "invalid_unique_targets": sum(1 for item in target_results.values() if not item.get("valid")), }, "exact": audit_exact_records(summary, target_results, args.sample_limit), "regex": audit_regex_records(target_results, summary, args.sample_limit), } print(json_dumps(payload)) has_hard_errors = bool(payload["exact"]["empty_fields"] or payload["regex"]["regex_error_total"]) return 1 if has_hard_errors else 0 if __name__ == "__main__": raise SystemExit(main())