vigil-codeintel 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vigil_codeintel-0.1.0.dist-info/METADATA +780 -0
- vigil_codeintel-0.1.0.dist-info/RECORD +131 -0
- vigil_codeintel-0.1.0.dist-info/WHEEL +5 -0
- vigil_codeintel-0.1.0.dist-info/entry_points.txt +3 -0
- vigil_codeintel-0.1.0.dist-info/licenses/LICENSE +21 -0
- vigil_codeintel-0.1.0.dist-info/top_level.txt +3 -0
- vigil_forensic/__init__.py +224 -0
- vigil_forensic/_git_utils.py +178 -0
- vigil_forensic/_shared.py +510 -0
- vigil_forensic/_stubs.py +156 -0
- vigil_forensic/gate_checks/__init__.py +1 -0
- vigil_forensic/gate_checks/_ast_helpers.py +629 -0
- vigil_forensic/gate_checks/_deployment_detector.py +573 -0
- vigil_forensic/gate_checks/atomic_write_checks.py +1143 -0
- vigil_forensic/gate_checks/authority_checks.py +95 -0
- vigil_forensic/gate_checks/boundary_breach_checks.py +202 -0
- vigil_forensic/gate_checks/broad_except_checks.py +301 -0
- vigil_forensic/gate_checks/broad_except_hidden_sentinel_checks.py +365 -0
- vigil_forensic/gate_checks/common.py +253 -0
- vigil_forensic/gate_checks/config_safety_checks.py +704 -0
- vigil_forensic/gate_checks/config_ssot_checks.py +78 -0
- vigil_forensic/gate_checks/conflict_checks.py +193 -0
- vigil_forensic/gate_checks/context_fallback_checks.py +697 -0
- vigil_forensic/gate_checks/context_health_checks.py +289 -0
- vigil_forensic/gate_checks/contract_shape_drift_checks.py +459 -0
- vigil_forensic/gate_checks/dirty_baseline_check.py +274 -0
- vigil_forensic/gate_checks/duplication_checks.py +387 -0
- vigil_forensic/gate_checks/embedded_string_checks.py +123 -0
- vigil_forensic/gate_checks/empty_output_checks.py +87 -0
- vigil_forensic/gate_checks/encoding_checks.py +847 -0
- vigil_forensic/gate_checks/export_completeness_checks.py +156 -0
- vigil_forensic/gate_checks/fallback_checks.py +41 -0
- vigil_forensic/gate_checks/file_proliferation_checks.py +171 -0
- vigil_forensic/gate_checks/fix_without_test_checks.py +69 -0
- vigil_forensic/gate_checks/forensic_cluster_runners/__init__.py +9 -0
- vigil_forensic/gate_checks/forensic_cluster_runners/_helpers.py +71 -0
- vigil_forensic/gate_checks/forensic_cluster_runners/advanced_checks.py +322 -0
- vigil_forensic/gate_checks/forensic_cluster_runners/core.py +273 -0
- vigil_forensic/gate_checks/forensic_cluster_runners/integrity_checks.py +203 -0
- vigil_forensic/gate_checks/forensic_cluster_runners/quality_checks.py +666 -0
- vigil_forensic/gate_checks/forensic_clusters/__init__.py +193 -0
- vigil_forensic/gate_checks/forensic_clusters/allowlist.py +426 -0
- vigil_forensic/gate_checks/forensic_clusters/allowlist_writer.py +302 -0
- vigil_forensic/gate_checks/forensic_clusters/api_protocol.py +231 -0
- vigil_forensic/gate_checks/forensic_clusters/async_quality.py +1156 -0
- vigil_forensic/gate_checks/forensic_clusters/code_style.py +808 -0
- vigil_forensic/gate_checks/forensic_clusters/core.py +319 -0
- vigil_forensic/gate_checks/forensic_clusters/data_quality.py +763 -0
- vigil_forensic/gate_checks/forensic_clusters/dead_code.py +480 -0
- vigil_forensic/gate_checks/forensic_clusters/edit_mutation.py +842 -0
- vigil_forensic/gate_checks/forensic_clusters/exception_boundary.py +240 -0
- vigil_forensic/gate_checks/forensic_clusters/legacy_debt.py +556 -0
- vigil_forensic/gate_checks/forensic_clusters/static_analysis.py +834 -0
- vigil_forensic/gate_checks/forensic_clusters/structural_quality.py +298 -0
- vigil_forensic/gate_checks/god_object_zones_checks.py +173 -0
- vigil_forensic/gate_checks/hallucination_checks.py +566 -0
- vigil_forensic/gate_checks/hunter_artifact_completeness_check.py +139 -0
- vigil_forensic/gate_checks/implementation_overfit_checks.py +380 -0
- vigil_forensic/gate_checks/import_integrity_checks.py +233 -0
- vigil_forensic/gate_checks/imports_in_function_checks.py +283 -0
- vigil_forensic/gate_checks/ml_checks.py +318 -0
- vigil_forensic/gate_checks/performance_checks.py +106 -0
- vigil_forensic/gate_checks/project_specific_runner.py +691 -0
- vigil_forensic/gate_checks/provider_capability_checks.py +73 -0
- vigil_forensic/gate_checks/refactor_completeness_checks.py +274 -0
- vigil_forensic/gate_checks/reliability_checks.py +389 -0
- vigil_forensic/gate_checks/reporting_checks.py +55 -0
- vigil_forensic/gate_checks/runtime_behavior_checks.py +220 -0
- vigil_forensic/gate_checks/security_injection_checks.py +332 -0
- vigil_forensic/gate_checks/semantic_intent_checks.py +139 -0
- vigil_forensic/gate_checks/size_complexity_checks.py +336 -0
- vigil_forensic/gate_checks/stuck_feature_flag_checks.py +354 -0
- vigil_forensic/gate_checks/syntax_validity_checks.py +217 -0
- vigil_forensic/gate_checks/temporal_freshness_checks.py +79 -0
- vigil_forensic/gate_checks/test_quality_checks.py +946 -0
- vigil_forensic/gate_checks/testing_checks.py +149 -0
- vigil_forensic/gate_checks/toctou_checks.py +367 -0
- vigil_forensic/gate_checks/type_checking_checks.py +316 -0
- vigil_forensic/gate_models.py +392 -0
- vigil_forensic/gate_packs/__init__.py +1 -0
- vigil_forensic/gate_packs/universal.py +179 -0
- vigil_forensic/gate_profile.json +31 -0
- vigil_forensic/gate_registry.py +21 -0
- vigil_forensic/language_profiles.py +219 -0
- vigil_forensic/meta_findings.py +207 -0
- vigil_forensic/self_audit.py +725 -0
- vigil_forensic/source_analysis.py +175 -0
- vigil_mapper/__init__.py +103 -0
- vigil_mapper/_ast_helpers_minimal.py +229 -0
- vigil_mapper/_extract_imports_impl.py +123 -0
- vigil_mapper/_file_count_guard.py +129 -0
- vigil_mapper/_git_utils.py +178 -0
- vigil_mapper/_runtime_ast.py +438 -0
- vigil_mapper/_runtime_dispatch.py +137 -0
- vigil_mapper/_seed_helpers.py +82 -0
- vigil_mapper/authority_builder.py +1102 -0
- vigil_mapper/cli_entry.py +731 -0
- vigil_mapper/conflict_builder.py +818 -0
- vigil_mapper/data_contract_builder.py +446 -0
- vigil_mapper/findings_builder.py +716 -0
- vigil_mapper/fingerprint.py +53 -0
- vigil_mapper/hotspot_builder.py +539 -0
- vigil_mapper/map_common.py +449 -0
- vigil_mapper/map_errors.py +55 -0
- vigil_mapper/map_models.py +431 -0
- vigil_mapper/map_models_ext.py +206 -0
- vigil_mapper/map_models_findings.py +130 -0
- vigil_mapper/map_storage.py +455 -0
- vigil_mapper/parse_cache.py +795 -0
- vigil_mapper/refactor_boundary_builder.py +266 -0
- vigil_mapper/runtime_builder.py +527 -0
- vigil_mapper/runtime_tracer.py +243 -0
- vigil_mapper/runtime_tracer_entry.py +199 -0
- vigil_mapper/semantic_diff.py +71 -0
- vigil_mapper/source_adapters/__init__.py +109 -0
- vigil_mapper/source_adapters/_base.py +264 -0
- vigil_mapper/source_adapters/_ir.py +156 -0
- vigil_mapper/source_adapters/_lexer.py +309 -0
- vigil_mapper/source_adapters/_patterns.py +212 -0
- vigil_mapper/source_adapters/_treesitter.py +182 -0
- vigil_mapper/source_adapters/go.py +553 -0
- vigil_mapper/source_adapters/java.py +541 -0
- vigil_mapper/source_adapters/javascript.py +626 -0
- vigil_mapper/source_adapters/python.py +325 -0
- vigil_mapper/source_adapters/typescript.py +749 -0
- vigil_mapper/structural_builder.py +586 -0
- vigil_mcp/__init__.py +1 -0
- vigil_mcp/_jobs.py +587 -0
- vigil_mcp/_paths.py +93 -0
- vigil_mcp/forensic_server.py +419 -0
- vigil_mcp/map_server.py +452 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
from vigil_forensic._shared import EvidenceReference, GateCategory, GateImpact, GateSeverity
|
|
6
|
+
from vigil_forensic.gate_models import PostExecGateContext
|
|
7
|
+
from .common import build_check_result, build_finding, iter_touched_snapshots
|
|
8
|
+
import logging
|
|
9
|
+
_log = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
# Config keys that must be read via the canonical config path, not env vars directly.
|
|
12
|
+
_ENV_BYPASS_KEYS = {"VIGIL_PORT", "CONTROL_PLANE_PORT", "VIGIL_DB_PATH"}
|
|
13
|
+
|
|
14
|
+
# Files that are legitimately allowed to read these env vars (e.g. the canonical config resolver itself).
|
|
15
|
+
_ALLOWED_ENV_READERS = {"config.py", "settings.py", "config_loader.py", "vigil_config.py"}
|
|
16
|
+
|
|
17
|
+
# Matches os.environ.get( or getenv( followed (anywhere on the same line) by a known key.
|
|
18
|
+
_ENV_PATTERN = re.compile(r'(?:os\.environ\.get\s*\(|getenv\s*\()')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def run_config_ssot_checks(ctx: PostExecGateContext):
|
|
22
|
+
findings = []
|
|
23
|
+
profile = ctx.repo_profile
|
|
24
|
+
if profile is None:
|
|
25
|
+
return build_check_result(check_id="config_ssot", category=GateCategory.CONFIG_SSOT)
|
|
26
|
+
for snapshot in iter_touched_snapshots(ctx):
|
|
27
|
+
if not snapshot.exists:
|
|
28
|
+
continue
|
|
29
|
+
# -- existing check: canonical literal owners --
|
|
30
|
+
for literal, owners in profile.canonical_literal_owners.items():
|
|
31
|
+
if literal not in snapshot.text:
|
|
32
|
+
continue
|
|
33
|
+
if snapshot.path in owners:
|
|
34
|
+
continue
|
|
35
|
+
findings.append(
|
|
36
|
+
build_finding(
|
|
37
|
+
check_id="config_ssot.literal_owner",
|
|
38
|
+
category=GateCategory.CONFIG_SSOT,
|
|
39
|
+
title="Touched code bypasses a canonical config owner",
|
|
40
|
+
severity=GateSeverity.HIGH,
|
|
41
|
+
impact=GateImpact.REVISE,
|
|
42
|
+
summary=f"Literal '{literal}' appears in {snapshot.path}, but canonical owner paths are {', '.join(owners[:3])}.",
|
|
43
|
+
recommendation="Move or reference the invariant from its canonical owner instead of duplicating the literal.",
|
|
44
|
+
evidence=[EvidenceReference(kind="file", path=snapshot.path, detail=literal)],
|
|
45
|
+
|
|
46
|
+
repair_kind='fix_contract',
|
|
47
|
+
executor_action='Fix contract violation',
|
|
48
|
+
proof_required='Contract respected',
|
|
49
|
+
allowlist_allowed=False,
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
# -- new check: env var bypass of known config keys --
|
|
53
|
+
filename = snapshot.path.split("/")[-1].split("\\")[-1]
|
|
54
|
+
if filename not in _ALLOWED_ENV_READERS:
|
|
55
|
+
for lineno, line in enumerate(snapshot.text.splitlines(), start=1):
|
|
56
|
+
if not _ENV_PATTERN.search(line):
|
|
57
|
+
continue
|
|
58
|
+
matched_key = next((k for k in _ENV_BYPASS_KEYS if k in line), None)
|
|
59
|
+
if matched_key is None:
|
|
60
|
+
continue
|
|
61
|
+
findings.append(
|
|
62
|
+
build_finding(
|
|
63
|
+
check_id="config_ssot.env_bypass",
|
|
64
|
+
category=GateCategory.CONFIG_SSOT,
|
|
65
|
+
title="Config value accessed via environment variable bypass",
|
|
66
|
+
severity=GateSeverity.MEDIUM,
|
|
67
|
+
impact=GateImpact.REVISE,
|
|
68
|
+
summary="Config value accessed via environment variable bypass instead of canonical config path",
|
|
69
|
+
recommendation=f"Read '{matched_key}' through the canonical config resolver, not directly via os.environ/getenv.",
|
|
70
|
+
evidence=[EvidenceReference(kind="file", path=snapshot.path, detail=f"line {lineno}: {line.strip()}")],
|
|
71
|
+
|
|
72
|
+
repair_kind='fix_contract',
|
|
73
|
+
executor_action='Fix contract violation',
|
|
74
|
+
proof_required='Contract respected',
|
|
75
|
+
allowlist_allowed=False,
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
return build_check_result(check_id="config_ssot", category=GateCategory.CONFIG_SSOT, findings=findings)
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"""Unresolved high-conflict touch forensic gate (Finding 6.6).
|
|
2
|
+
|
|
3
|
+
conflict_touch: detect when a PR touches files flagged in the conflict map
|
|
4
|
+
as unresolved and with severity high or critical.
|
|
5
|
+
|
|
6
|
+
Primary path: use ctx.maps.conflict when hydrated.
|
|
7
|
+
Fallback: read .cortex/maps/50_conflict_map.json from disk (legacy callers).
|
|
8
|
+
|
|
9
|
+
Fail-open: map missing, unreadable, or malformed -> return empty findings.
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
import logging
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
from vigil_forensic._shared import EvidenceReference, GateCategory, GateImpact, GateSeverity
|
|
19
|
+
from vigil_forensic.gate_models import PostExecGateContext
|
|
20
|
+
|
|
21
|
+
_CATEGORY = GateCategory.CONTRACT
|
|
22
|
+
from .common import build_check_result, build_finding, normalize_path
|
|
23
|
+
|
|
24
|
+
_log = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
_MAP_REL_PATH = ".cortex/maps/50_conflict_map.json"
|
|
27
|
+
|
|
28
|
+
_HIGH_SEVERITIES = frozenset({"high", "critical"})
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# ---------------------------------------------------------------------------
|
|
32
|
+
# Internal helpers
|
|
33
|
+
# ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _load_conflicts(project_dir: Path) -> list[dict[str, Any]] | None:
|
|
37
|
+
"""Load conflict entries from the map file.
|
|
38
|
+
|
|
39
|
+
Returns a list of conflict dicts on success, or None on any failure
|
|
40
|
+
(missing file, JSON error, unexpected top-level shape).
|
|
41
|
+
"""
|
|
42
|
+
map_path = project_dir / _MAP_REL_PATH
|
|
43
|
+
try:
|
|
44
|
+
raw = map_path.read_text(encoding="utf-8")
|
|
45
|
+
except OSError as exc:
|
|
46
|
+
_log.debug("conflict_touch: map not found at %s: %s", map_path, exc)
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
data = json.loads(raw)
|
|
51
|
+
except json.JSONDecodeError as exc:
|
|
52
|
+
_log.debug("conflict_touch: map JSON malformed: %s", exc)
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
if not isinstance(data, dict):
|
|
56
|
+
_log.debug("conflict_touch: map root is not a dict")
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
conflicts_raw = data.get("conflicts")
|
|
60
|
+
if not isinstance(conflicts_raw, list):
|
|
61
|
+
_log.debug("conflict_touch: map has no 'conflicts' list")
|
|
62
|
+
return None
|
|
63
|
+
|
|
64
|
+
return [c for c in conflicts_raw if isinstance(c, dict)]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _entry_from_conflict(c: Any) -> dict[str, Any]:
|
|
68
|
+
"""Convert a ConflictEntry dataclass instance to the dict format used internally.
|
|
69
|
+
|
|
70
|
+
ConflictEntry uses ``conflict_status`` (open/in_progress/resolved) rather than
|
|
71
|
+
a boolean ``resolved`` field. Map to the dict shape that _build_high_conflict_files
|
|
72
|
+
expects: ``resolved`` = True only when conflict_status == "resolved".
|
|
73
|
+
"""
|
|
74
|
+
conflict_status = str(getattr(c, "conflict_status", "open") or "open").lower()
|
|
75
|
+
# Gather files from ``sources`` tuples (JSON strings containing {"file": ...} dicts)
|
|
76
|
+
# and from the subject field as a best-effort path hint.
|
|
77
|
+
import json as _json
|
|
78
|
+
files: list[str] = []
|
|
79
|
+
for src_raw in (getattr(c, "sources", ()) or ()):
|
|
80
|
+
try:
|
|
81
|
+
src = _json.loads(src_raw) if isinstance(src_raw, str) else src_raw
|
|
82
|
+
if isinstance(src, dict):
|
|
83
|
+
# Sources may carry a "file" key
|
|
84
|
+
if "file" in src:
|
|
85
|
+
files.append(str(src["file"]))
|
|
86
|
+
except _json.JSONDecodeError as exc:
|
|
87
|
+
_log.debug("conflict_checks: skipping malformed source JSON %r: %s", src_raw, exc)
|
|
88
|
+
# Fallback safe here: one unparseable source string doesn't affect other sources
|
|
89
|
+
# Evidence strings may also contain file paths
|
|
90
|
+
for ev in (getattr(c, "evidence", ()) or ()):
|
|
91
|
+
ev_str = str(ev)
|
|
92
|
+
if ev_str and ("/" in ev_str or "\\" in ev_str) and not ev_str.startswith("{"):
|
|
93
|
+
files.append(ev_str)
|
|
94
|
+
return {
|
|
95
|
+
"files": files,
|
|
96
|
+
"severity": str(getattr(c, "severity", "medium") or "medium"),
|
|
97
|
+
"resolved": conflict_status == "resolved",
|
|
98
|
+
"summary": str(getattr(c, "subject", "") or ""),
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _build_high_conflict_files(conflicts: list[dict[str, Any]]) -> set[str]:
|
|
103
|
+
"""Return the set of file paths that are unresolved AND high/critical severity."""
|
|
104
|
+
result: set[str] = set()
|
|
105
|
+
for entry in conflicts:
|
|
106
|
+
resolved = entry.get("resolved", True)
|
|
107
|
+
if resolved:
|
|
108
|
+
continue
|
|
109
|
+
severity = str(entry.get("severity", "")).lower()
|
|
110
|
+
if severity not in _HIGH_SEVERITIES:
|
|
111
|
+
continue
|
|
112
|
+
files_raw = entry.get("files")
|
|
113
|
+
if isinstance(files_raw, list):
|
|
114
|
+
for f in files_raw:
|
|
115
|
+
if f:
|
|
116
|
+
result.add(normalize_path(str(f)))
|
|
117
|
+
return result
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
# ---------------------------------------------------------------------------
|
|
121
|
+
# Public gate function
|
|
122
|
+
# ---------------------------------------------------------------------------
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def run_conflict_touch_checks(ctx: PostExecGateContext):
|
|
126
|
+
"""Emit a finding for every changed file that is an unresolved high/critical conflict.
|
|
127
|
+
|
|
128
|
+
Primary path: use ctx.maps.conflict when hydrated and not missing.
|
|
129
|
+
Fallback: read map JSON file from disk (legacy callers / maps not loaded).
|
|
130
|
+
|
|
131
|
+
Fail-open: if the map is missing or malformed, return empty findings.
|
|
132
|
+
"""
|
|
133
|
+
# --- Primary: ctx.maps ---------------------------------------------------
|
|
134
|
+
conflicts: list[dict[str, Any]] | None = None
|
|
135
|
+
if ctx.maps is not None and not getattr(ctx.maps, "missing", False):
|
|
136
|
+
cm = getattr(ctx.maps, "conflict", None)
|
|
137
|
+
if cm:
|
|
138
|
+
conflicts = [_entry_from_conflict(c) for c in cm]
|
|
139
|
+
_log.debug("conflict_touch: using %d entries from ctx.maps", len(conflicts))
|
|
140
|
+
|
|
141
|
+
# --- Fallback: file read --------------------------------------------------
|
|
142
|
+
if conflicts is None:
|
|
143
|
+
conflicts = _load_conflicts(ctx.project_dir)
|
|
144
|
+
|
|
145
|
+
if conflicts is None:
|
|
146
|
+
return build_check_result(
|
|
147
|
+
check_id="conflict_touch",
|
|
148
|
+
category=_CATEGORY,
|
|
149
|
+
notes=["conflict_touch: map missing or malformed -- skipped (fail-open)"],
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
high_conflict_files = _build_high_conflict_files(conflicts)
|
|
153
|
+
|
|
154
|
+
findings = []
|
|
155
|
+
for raw_path in ctx.changed_files_observed:
|
|
156
|
+
normalized = normalize_path(raw_path)
|
|
157
|
+
if normalized in high_conflict_files:
|
|
158
|
+
findings.append(
|
|
159
|
+
build_finding(
|
|
160
|
+
check_id="conflict_touch.unresolved_high_conflict",
|
|
161
|
+
category=_CATEGORY,
|
|
162
|
+
title="Changed file has an unresolved high-severity conflict",
|
|
163
|
+
severity=GateSeverity.MEDIUM,
|
|
164
|
+
impact=GateImpact.REVISE,
|
|
165
|
+
summary=(
|
|
166
|
+
f"File '{normalized}' was changed and is flagged in the conflict map "
|
|
167
|
+
f"as unresolved with high or critical severity."
|
|
168
|
+
),
|
|
169
|
+
recommendation=(
|
|
170
|
+
"Resolve the conflict recorded in the conflict map before landing "
|
|
171
|
+
f"this change, or update {_MAP_REL_PATH} if the conflict was "
|
|
172
|
+
"already addressed."
|
|
173
|
+
),
|
|
174
|
+
evidence=[
|
|
175
|
+
EvidenceReference(
|
|
176
|
+
kind="changed_file",
|
|
177
|
+
path=normalized,
|
|
178
|
+
detail="unresolved high/critical conflict in conflict map",
|
|
179
|
+
)
|
|
180
|
+
],
|
|
181
|
+
|
|
182
|
+
repair_kind='fix_contract',
|
|
183
|
+
executor_action='Fix conflict',
|
|
184
|
+
proof_required='No conflict',
|
|
185
|
+
allowlist_allowed=False,
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return build_check_result(
|
|
190
|
+
check_id="conflict_touch",
|
|
191
|
+
category=_CATEGORY,
|
|
192
|
+
findings=findings,
|
|
193
|
+
)
|