""" 任务类型感知的证据门控 — V2 P0-1 修复。 替代 V1 无差别触发 AirXDB 的逻辑,根据任务特征差异化要求证据类型。 """ from __future__ import annotations import enum from dataclasses import dataclass class EvidenceClass(enum.Enum): GUI_REQUIRED = "gui_required" # 需要截图/GUI 操作验证 NETWORK_REQUIRED = "network_required" # 需要抓包/流量验证 STATIC_ANALYSIS = "static_analysis" # 需要静态分析 CODE_ONLY = "code_only" # 代码级验证即可 @dataclass class EvidenceGatePolicy: """基于任务特征的差异化证据要求。 关键词匹配 → 确定性分类,零额外 API 调用,可测试可覆盖。 用户可在 todo.md 中用 [no-xdb] / [no-ndb] 标记显式跳过。 """ GUI_INDICATORS: tuple[str, ...] = ( "gui", "ui", "render", "layout", "dialog", "osd", "overlay", "visual", "screenshot", "display", "widget", "pane", "toolbar", "settings_dialog", "canvas", "button", "window", "popup", "menu", "drm", "kms", "opengl", "vulkan", ) NETWORK_INDICATORS: tuple[str, ...] = ( "network", "rtsp", "http", "tcp", "udp", "tls", "dns", "proxy", "socket", "stream", "port", "packet", "pcap", "bandwidth", "latency", ) STATIC_ANALYSIS_INDICATORS: tuple[str, ...] = ( "cppcheck", "clang-tidy", "mypy", "ruff", "lint", "static analysis", "compile_commands", ) SKIP_MARKERS: tuple[str, ...] = ("[no-xdb]", "[no-ndb]", "[no-sdb]") def classify(self, task_text: str, task_id: str = "", skip_overrides: list[str] | None = None) -> EvidenceClass: text = task_text.lower() skips = set(skip_overrides or []) for marker in self.SKIP_MARKERS: if marker in text: skips.add(marker) has_gui = any(kw in text for kw in self.GUI_INDICATORS) has_net = any(kw in text for kw in self.NETWORK_INDICATORS) has_static = any(kw in text for kw in self.STATIC_ANALYSIS_INDICATORS) if has_gui and "[no-xdb]" not in skips: return EvidenceClass.GUI_REQUIRED if has_net and "[no-ndb]" not in skips: return EvidenceClass.NETWORK_REQUIRED if has_static and "[no-sdb]" not in skips: return EvidenceClass.STATIC_ANALYSIS return EvidenceClass.CODE_ONLY def required_evidence_for(self, evidence_class: EvidenceClass) -> list[str]: evidence_map = { EvidenceClass.GUI_REQUIRED: ["screenshot", "gui-operation-validation"], EvidenceClass.NETWORK_REQUIRED: ["packet-capture", "connectivity-verification"], EvidenceClass.STATIC_ANALYSIS: ["static-analysis-report"], EvidenceClass.CODE_ONLY: ["code-review", "test-results"], } return evidence_map.get(evidence_class, ["code-review"])