Skip to content

Commit a1c390b

Browse files
Sutaigneclaude
andcommitted
Real fix for hung user-folder scans: prune dep-caches BEFORE recursing (v4.1.4)
Brad ran v4.1.3 and AIVision was still hung. Diagnosis: the v4.1.1 fix applied the exclusion pattern AFTER Get-ChildItem -Recurse had already walked into node_modules / site-packages / .venv / etc. PowerShell's pipeline filter can't prune mid-recursion the way Python's os.walk can. Fix: new helper Get-PrunedFiles in forensic-common.ps1 that uses .NET DirectoryInfo.EnumerateDirectories with explicit name-pruning before descending. node_modules / site-packages / .venv / conda envs / etc. are skipped at the directory-traversal level — they're never enumerated. Applied to all 5 user-folder scanners that previously hung on dep caches: - Scan-AIVisionArtifacts (4 walks: onnx, exe+py, ino, requirements/pyproject) - Scan-LuaScripts - Scan-UserScriptContents - Scan-ObscuredFileNames - Scan-KnownHashes Verified end-to-end on Brad's machine (v3.1.3 had killed at 36s+ in AIVision and counting). Post-fix run: Scan-AIVisionArtifacts: 33.87s (completes; was unbounded) Scan-KnownHashes: 14.89s Scan-LuaScripts: 14.05s Scan-Downloads: 8.20s Scan-Drivers: 6.85s ...everything else < 5s TOTAL: 92.92s Still room to push AIVision lower (the .exe/.py walk + per-pattern keyword regex is the bulk), but it's no longer the hang case. Default pruned dir-name list lives in $Script:DefaultPrunedDirNames at the top of the helper so future scanners can opt in via Get-PrunedFiles instead of bare Get-ChildItem -Recurse. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 27e4344 commit a1c390b

3 files changed

Lines changed: 165 additions & 112 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ AlibiRigReport_*_visual.html
3333
*alibi-pc.summary
3434
*alibi-console.summary
3535
*alibi-loldb.json
36+
_test_*

HASHES.txt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@
33
# To verify a kit you received:
44
# 1. Download HASHES.txt from this repo at the matching tag.
55
# 2. In the kit folder, run: sha256sum -c HASHES.txt
6-
# (or, pure-Windows: Get-FileHash per file).
7-
# 3. Every line must report 'OK'. Mismatch = modified kit; don't trust the report.
86
#
9-
# Re-generated on each release.
10-
#
11-
# Format: <SHA256> <relative-path>
7+
# Re-generated on each release. Format: <SHA256> <relative-path>
128

139
# --- repo root: the runnable distribution ---
1410
314058db7beff3511bb59556f34b9d5dd35e7fdb54fc3dd6d7193b0f45e01a82 *Run scan.bat
@@ -21,7 +17,7 @@ da10d733a8628d518a9931693761f02645eb63d8278d08d9df7f8c1d7e53108f *scanner/consol
2117
8c3c8eaf9d99990de6e60a513dfb3f97f57eaa350c5fbfc1e22698a9a00bcc3d *scanner/console-rig-audit.ps1
2218
0b680b000ecc2b500bbde276aadac5a850a8dcbc11c8990f52a96e21a11b22a1 *scanner/console-run-check.bat
2319
065ef704012b8c3f410916e702165dc1fd197d586d852fc8473af735273b0d0b *scanner/console-setup-checklist.html
24-
2fd6b2c9d1d43fee58d303bcb27b3e5dde31c4b6c8d57e300ac5e6bf46f602e8 *scanner/forensic-common.ps1
20+
f023d3250bd536023ac13d86476bd30ad7b058d519e70d893a1df988ab204889 *scanner/forensic-common.ps1
2521
f697d59ff68523d3aa9ba3dd8dbd015659230a221c0c668b16a574e2f1156c4b *scanner/forensic-scan.ps1
2622
671c81e911af316569e92ce162cfee0bb5efaff9c8096942c9b7c102aa809f40 *scanner/generate-visual-companion-console.ps1
2723
659db814bc9ee87bda9506fa613780bc8e6da3a487866e040d46c8bac59fd957 *scanner/generate-visual-companion.ps1

scanner/forensic-common.ps1

Lines changed: 162 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,84 @@ function Score-And-Add {
556556
}
557557
}
558558

559+
# ============================================================================
560+
# Get-PrunedFiles — fast recursive file walker that prunes dependency-cache
561+
# directories BEFORE descending. PowerShell's Get-ChildItem -Recurse can't
562+
# do this (any -Where applied to the pipeline runs after enumeration, so
563+
# node_modules / site-packages / .venv / etc. get fully walked before the
564+
# filter rejects results). This helper uses .NET DirectoryInfo enumeration
565+
# with explicit pruning, which is dramatically faster on ML-heavy / dev
566+
# machines.
567+
#
568+
# Returns System.IO.FileInfo objects — same shape as Get-ChildItem -File,
569+
# so callers can use .FullName, .Name, .Length, .CreationTime, .LastWriteTime,
570+
# .DirectoryName, .Extension, .BaseName interchangeably.
571+
# ============================================================================
572+
573+
$Script:DefaultPrunedDirNames = @(
574+
'node_modules', '.git', '.hg', '.svn', 'site-packages',
575+
'venv', '.venv', 'env', 'envs',
576+
'__pycache__', '.pytest_cache', '.mypy_cache', '.ruff_cache', '.tox',
577+
'anaconda3', 'miniconda3', 'conda',
578+
'.cache', '.npm', '.yarn',
579+
'.next', '.nuxt', '.cargo', '.rustup'
580+
)
581+
582+
function Get-PrunedFiles {
583+
[CmdletBinding()]
584+
param(
585+
[Parameter(Mandatory)][string]$Root,
586+
[string[]]$Extensions = $null, # e.g. @('.onnx') or @('.exe','.py')
587+
[int]$MaxDepth = 8,
588+
[int]$ResultCap = 0, # 0 = unlimited
589+
[string[]]$ExcludeDirNames = $null # $null = default dep-cache list
590+
)
591+
if (-not (Test-Path -LiteralPath $Root)) { return }
592+
593+
$excludes = if ($null -ne $ExcludeDirNames) { $ExcludeDirNames } else { $Script:DefaultPrunedDirNames }
594+
$excludeSet = @{}
595+
foreach ($n in $excludes) { $excludeSet[$n.ToLower()] = $true }
596+
597+
$extSet = $null
598+
if ($Extensions) {
599+
$extSet = @{}
600+
foreach ($e in $Extensions) {
601+
$k = if ($e.StartsWith('.')) { $e.ToLower() } else { '.' + $e.ToLower() }
602+
$extSet[$k] = $true
603+
}
604+
}
605+
606+
$results = [System.Collections.Generic.List[System.IO.FileInfo]]::new()
607+
$stack = [System.Collections.Generic.Stack[object]]::new()
608+
try {
609+
$stack.Push(@{ Dir = [System.IO.DirectoryInfo]::new($Root); Depth = 0 })
610+
} catch { return $results }
611+
612+
while ($stack.Count -gt 0) {
613+
$cur = $stack.Pop()
614+
$dir = $cur.Dir
615+
$depth = $cur.Depth
616+
617+
try {
618+
foreach ($f in $dir.EnumerateFiles()) {
619+
if ($extSet -and -not $extSet.ContainsKey($f.Extension.ToLower())) { continue }
620+
[void]$results.Add($f)
621+
if ($ResultCap -gt 0 -and $results.Count -ge $ResultCap) { return $results }
622+
}
623+
} catch {}
624+
625+
if ($depth -ge $MaxDepth) { continue }
626+
627+
try {
628+
foreach ($d in $dir.EnumerateDirectories()) {
629+
if ($excludeSet.ContainsKey($d.Name.ToLower())) { continue }
630+
$stack.Push(@{ Dir = $d; Depth = $depth + 1 })
631+
}
632+
} catch {}
633+
}
634+
return $results
635+
}
636+
559637
# ============================================================================
560638
# SCAN FUNCTIONS
561639
# ============================================================================
@@ -1109,17 +1187,15 @@ function Scan-UserScriptContents {
11091187
$scanRoots = $scanRoots | Where-Object { Test-Path $_ }
11101188

11111189
$scriptFiles = [System.Collections.Generic.List[object]]::new()
1190+
# v4.1.4: Get-PrunedFiles handles dep-cache pruning + multi-extension walk
1191+
# in one pass per root (faster than the prior per-extension loop).
1192+
$scriptExts = @('.bat','.cmd','.ps1','.vbs','.wsf','.psm1','.lua','.ahk')
11121193
foreach ($root in $scanRoots) {
1113-
foreach ($ext in @('*.bat','*.cmd','*.ps1','*.vbs','*.wsf','*.psm1','*.lua','*.ahk')) {
1114-
try {
1115-
Get-ChildItem $root -Recurse -File -Depth 8 -Filter $ext -ErrorAction SilentlyContinue |
1116-
Where-Object {
1117-
$_.Length -lt 10MB -and
1118-
($_.Name.ToLower() -notin $excludeNames) -and
1119-
(-not ($selfDir -and $_.DirectoryName.ToLower().StartsWith($selfDir)))
1120-
} |
1121-
ForEach-Object { [void]$scriptFiles.Add($_) }
1122-
} catch {}
1194+
foreach ($f in (Get-PrunedFiles -Root $root -Extensions $scriptExts -ResultCap 3000)) {
1195+
if ($f.Length -ge 10MB) { continue }
1196+
if ($f.Name.ToLower() -in $excludeNames) { continue }
1197+
if ($selfDir -and $f.DirectoryName.ToLower().StartsWith($selfDir)) { continue }
1198+
[void]$scriptFiles.Add($f)
11231199
}
11241200
}
11251201

@@ -1207,25 +1283,24 @@ function Scan-ObscuredFileNames {
12071283

12081284
$extWatchlist = @('.exe','.dll','.bat','.cmd','.ps1','.vbs','.lua','.ahk','.sys','.bin')
12091285

1286+
# v4.1.4: dep-cache prune. node_modules etc. would never be the place where
1287+
# someone hides a cheat under a hex-name; skipping these is detection-neutral.
12101288
foreach ($root in $roots) {
1211-
try {
1212-
Get-ChildItem $root -Recurse -File -Depth 8 -ErrorAction SilentlyContinue |
1213-
Where-Object { $extWatchlist -contains $_.Extension.ToLower() -and $_.Length -lt 100MB } |
1214-
ForEach-Object {
1215-
$name = $_.BaseName
1216-
$reason = ''
1217-
if ($name -match '^0x[0-9a-fA-F]+$') { $reason = "0x-prefix hex name ($name$($_.Extension))" }
1218-
elseif ($name -match '^[0-9a-fA-F]{8,}$' -and $name -match '[a-fA-F]') { $reason = "raw hex name ($name$($_.Extension))" }
1219-
elseif ($name -match '^\d{4,}$') { $reason = "pure-numeric name ($name$($_.Extension))" }
1220-
elseif ($name -match '^[a-zA-Z0-9]{1,2}$' -and $name -notin @('go','vc','7z','C','x')) { $reason = "ultra-short obscured name ($name$($_.Extension))" }
1221-
if ($reason) {
1222-
Add-Finding 'ObscuredNames' $_.FullName "Obscured filename: $reason" 'MEDIUM' 'dual-use' @{
1223-
FileName = $_.Name; FullPath = $_.FullName; Pattern = $reason
1224-
SizeBytes = $_.Length; LastWrite = $_.LastWriteTime.ToString('s')
1225-
}
1226-
}
1289+
foreach ($f in (Get-PrunedFiles -Root $root -Extensions $extWatchlist -ResultCap 4000)) {
1290+
if ($f.Length -ge 100MB) { continue }
1291+
$name = $f.BaseName
1292+
$reason = ''
1293+
if ($name -match '^0x[0-9a-fA-F]+$') { $reason = "0x-prefix hex name ($name$($f.Extension))" }
1294+
elseif ($name -match '^[0-9a-fA-F]{8,}$' -and $name -match '[a-fA-F]') { $reason = "raw hex name ($name$($f.Extension))" }
1295+
elseif ($name -match '^\d{4,}$') { $reason = "pure-numeric name ($name$($f.Extension))" }
1296+
elseif ($name -match '^[a-zA-Z0-9]{1,2}$' -and $name -notin @('go','vc','7z','C','x')) { $reason = "ultra-short obscured name ($name$($f.Extension))" }
1297+
if ($reason) {
1298+
Add-Finding 'ObscuredNames' $f.FullName "Obscured filename: $reason" 'MEDIUM' 'dual-use' @{
1299+
FileName = $f.Name; FullPath = $f.FullName; Pattern = $reason
1300+
SizeBytes = $f.Length; LastWrite = $f.LastWriteTime.ToString('s')
12271301
}
1228-
} catch {}
1302+
}
1303+
}
12291304
}
12301305
}
12311306

@@ -1301,14 +1376,13 @@ function Scan-KnownHashes {
13011376
}
13021377
$roots = $roots | Where-Object { Test-Path $_ }
13031378

1379+
# v4.1.4: dep-cache prune. Skips node_modules / site-packages / .venv etc.
1380+
# A real cheat-sample wouldn't be stashed inside an npm dependency tree.
13041381
$candidates = [System.Collections.Generic.List[object]]::new()
13051382
foreach ($root in $roots) {
1306-
foreach ($ext in @('*.exe','*.dll')) {
1307-
try {
1308-
Get-ChildItem $root -Recurse -File -Depth 8 -Filter $ext -ErrorAction SilentlyContinue |
1309-
Where-Object { $_.Length -lt 100MB -and $_.Length -gt 0 } |
1310-
ForEach-Object { [void]$candidates.Add($_) }
1311-
} catch {}
1383+
foreach ($f in (Get-PrunedFiles -Root $root -Extensions @('.exe','.dll') -ResultCap 2000)) {
1384+
if ($f.Length -le 0 -or $f.Length -ge 100MB) { continue }
1385+
[void]$candidates.Add($f)
13121386
}
13131387
}
13141388

@@ -1346,9 +1420,11 @@ function Scan-LuaScripts {
13461420
"$env:USERPROFILE\Projects", "$env:USERPROFILE\Games"
13471421
) | Where-Object { $_ -and (Test-Path $_) }
13481422

1423+
# v4.1.4: prune dep-cache dirs (node_modules / site-packages / .venv / etc.)
1424+
# before recursing — those routinely contain bundled .lua files (Neovim
1425+
# plugins, build-tool .lua scripts) that aren't real cheat scripts.
13491426
foreach ($root in $roots) {
1350-
Get-ChildItem $root -Recurse -File -Depth 8 -Filter '*.lua' -ErrorAction SilentlyContinue | ForEach-Object {
1351-
$file = $_
1427+
foreach ($file in (Get-PrunedFiles -Root $root -Extensions @('.lua') -ResultCap 1500)) {
13521428
$zone = Get-DownloadSourceUrl $file.FullName
13531429
$meta = @{
13541430
FileName = $file.Name
@@ -1368,20 +1444,20 @@ function Scan-LuaScripts {
13681444
if ($hit) {
13691445
$meta['Pattern'] = $hit
13701446
Add-Finding 'LuaScript' $file.FullName "[$hit] $($file.Name)" 'HIGH' 'cheat' $meta
1371-
return
1447+
continue
13721448
}
13731449

13741450
$hitC = Match-Keyword $lc $Keywords_High_Cheats
13751451
if ($hitC) {
13761452
$meta['Pattern'] = $hitC
13771453
Add-Finding 'LuaScript' $file.FullName "[$hitC] $($file.Name)" 'HIGH' 'cheat' $meta
1378-
return
1454+
continue
13791455
}
13801456
$hitI = Match-Keyword $lc $Keywords_High_Input
13811457
if ($hitI) {
13821458
$meta['Pattern'] = $hitI
13831459
Add-Finding 'LuaScript' $file.FullName "[$hitI] $($file.Name)" 'HIGH' 'input' $meta
1384-
return
1460+
continue
13851461
}
13861462

13871463
# No cheat or input-device keyword. Emit at INFO so the file is listed
@@ -1722,10 +1798,10 @@ function Scan-AIVisionArtifacts {
17221798
# — walking them was the single biggest contributor to AIVision wall time.
17231799
Write-Host ' [*] AI-vision aimbot artifacts (ONNX / YOLO / external HID)...' -ForegroundColor DarkGray
17241800

1725-
# Skip these directory NAMES (matched as path segments, case-insensitive).
1726-
# A real AI-aimbot constellation lives in a hand-organized user folder,
1727-
# not in a dependency cache. Skipping these is detection-neutral.
1728-
$excludePattern = '(?i)\\(node_modules|\.git|\.hg|\.svn|site-packages|\.venv|venv|env|envs|__pycache__|\.pytest_cache|\.mypy_cache|\.ruff_cache|\.tox|anaconda3|miniconda3|conda|\.cache|\.npm|\.yarn|\.next|\.nuxt|\.cargo|\.rustup|dist-info)\\'
1801+
# v4.1.4 perf: use Get-PrunedFiles which prunes node_modules / site-packages
1802+
# / .venv / conda envs / etc. BEFORE recursing into them. The previous
1803+
# v4.1.1 fix only filtered AFTER Get-ChildItem enumerated, which on
1804+
# ML-heavy machines still hung walking caches with 100k+ files inside.
17291805

17301806
$roots = @(
17311807
"$env:USERPROFILE\Documents", "$env:USERPROFILE\Desktop",
@@ -1739,81 +1815,61 @@ function Scan-AIVisionArtifacts {
17391815
$arduinoHits = [System.Collections.Generic.List[object]]::new()
17401816
$pyDepHits = [System.Collections.Generic.List[object]]::new()
17411817

1742-
# Hard caps on the .exe/.py walk in particular — ML-heavy users can have
1743-
# tens of thousands of Python scripts across virtualenvs. We don't need
1744-
# to scan them all to find a named-brand aimbot binary.
17451818
$exePyCapPerRoot = 800
17461819
$pyDepCapPerRoot = 150
17471820

17481821
foreach ($root in $roots) {
1749-
# ONNX models (YOLO weights). Cap recursion depth implicitly via cap on results.
1750-
try {
1751-
Get-ChildItem $root -Recurse -File -Depth 8 -Filter '*.onnx' -ErrorAction SilentlyContinue |
1752-
Where-Object { $_.FullName -notmatch $excludePattern } |
1753-
Select-Object -First 200 |
1754-
ForEach-Object { [void]$onnxFiles.Add($_) }
1755-
} catch {}
1822+
# ONNX models (YOLO weights).
1823+
foreach ($f in (Get-PrunedFiles -Root $root -Extensions @('.onnx') -ResultCap 200)) {
1824+
[void]$onnxFiles.Add($f)
1825+
}
17561826

17571827
# Named-brand executables (HIGH on their own).
1758-
try {
1759-
Get-ChildItem $root -Recurse -File -Depth 8 -Include '*.exe','*.py' -ErrorAction SilentlyContinue |
1760-
Where-Object { $_.FullName -notmatch $excludePattern -and $_.Length -lt 200MB } |
1761-
Select-Object -First $exePyCapPerRoot |
1762-
ForEach-Object {
1763-
$hit = Match-Keyword "$($_.Name) $($_.DirectoryName)" $VisionAimbot_AI_PC
1764-
if ($hit) {
1765-
$meta = @{
1766-
Pattern = $hit
1767-
FileName = $_.Name
1768-
FullPath = $_.FullName
1769-
SizeBytes = $_.Length
1770-
Created = $_.CreationTime.ToString('s')
1771-
LastWrite = $_.LastWriteTime.ToString('s')
1772-
}
1773-
Add-Finding 'AIVision' $_.FullName "[$hit] AI-vision aimbot executable: $($_.Name)" 'HIGH' 'cheat' $meta
1774-
[void]$brandHits.Add($_)
1775-
}
1828+
foreach ($f in (Get-PrunedFiles -Root $root -Extensions @('.exe','.py') -ResultCap $exePyCapPerRoot)) {
1829+
if ($f.Length -ge 200MB) { continue }
1830+
$hit = Match-Keyword "$($f.Name) $($f.DirectoryName)" $VisionAimbot_AI_PC
1831+
if ($hit) {
1832+
$meta = @{
1833+
Pattern = $hit
1834+
FileName = $f.Name
1835+
FullPath = $f.FullName
1836+
SizeBytes = $f.Length
1837+
Created = $f.CreationTime.ToString('s')
1838+
LastWrite = $f.LastWriteTime.ToString('s')
17761839
}
1777-
} catch {}
1840+
Add-Finding 'AIVision' $f.FullName "[$hit] AI-vision aimbot executable: $($f.Name)" 'HIGH' 'cheat' $meta
1841+
[void]$brandHits.Add($f)
1842+
}
1843+
}
17781844

1779-
# Arduino sketches with HID-descriptor patterns - dead giveaway when
1780-
# paired with the ONNX/Python side of the constellation.
1781-
try {
1782-
Get-ChildItem $root -Recurse -File -Depth 8 -Filter '*.ino' -ErrorAction SilentlyContinue |
1783-
Where-Object { $_.FullName -notmatch $excludePattern } |
1784-
Select-Object -First 100 |
1785-
ForEach-Object {
1786-
try {
1787-
$content = Get-Content $_.FullName -Raw -ErrorAction Stop
1788-
if ($content -match '(?i)(Mouse\.move|HID-Project|MouseAbsolute|Keyboard\.press.*Mouse)') {
1789-
[void]$arduinoHits.Add($_)
1790-
}
1791-
} catch {}
1845+
# Arduino sketches with HID-descriptor patterns.
1846+
foreach ($f in (Get-PrunedFiles -Root $root -Extensions @('.ino') -ResultCap 100)) {
1847+
try {
1848+
$content = Get-Content $f.FullName -Raw -ErrorAction Stop
1849+
if ($content -match '(?i)(Mouse\.move|HID-Project|MouseAbsolute|Keyboard\.press.*Mouse)') {
1850+
[void]$arduinoHits.Add($f)
17921851
}
1793-
} catch {}
1852+
} catch {}
1853+
}
17941854

1795-
# Python ML dependency markers - requirements.txt / pyproject.toml /
1796-
# site-packages dirs naming aimbot-typical libraries.
1797-
try {
1798-
Get-ChildItem $root -Recurse -File -Depth 8 -Include 'requirements.txt','pyproject.toml','*.cfg' -ErrorAction SilentlyContinue |
1799-
Where-Object { $_.FullName -notmatch $excludePattern } |
1800-
Select-Object -First $pyDepCapPerRoot |
1801-
ForEach-Object {
1802-
try {
1803-
$content = Get-Content $_.FullName -Raw -ErrorAction Stop
1804-
$combo = 0
1805-
if ($content -match '(?i)ultralytics') { $combo++ }
1806-
if ($content -match '(?i)\btorch\b') { $combo++ }
1807-
if ($content -match '(?i)\bmss\b') { $combo++ }
1808-
if ($content -match '(?i)pyautogui|pydirectinput|pynput') { $combo++ }
1809-
if ($content -match '(?i)opencv-python|cv2') { $combo++ }
1810-
if ($content -match '(?i)onnxruntime') { $combo++ }
1811-
if ($combo -ge 3) {
1812-
[void]$pyDepHits.Add(@{ File=$_; Score=$combo })
1813-
}
1814-
} catch {}
1855+
# Python ML dependency markers - requirements.txt / pyproject.toml / .cfg
1856+
foreach ($f in (Get-PrunedFiles -Root $root -Extensions @('.txt','.toml','.cfg') -ResultCap ($pyDepCapPerRoot * 3))) {
1857+
$n = $f.Name.ToLower()
1858+
if ($n -ne 'requirements.txt' -and $n -ne 'pyproject.toml' -and -not $n.EndsWith('.cfg')) { continue }
1859+
try {
1860+
$content = Get-Content $f.FullName -Raw -ErrorAction Stop
1861+
$combo = 0
1862+
if ($content -match '(?i)ultralytics') { $combo++ }
1863+
if ($content -match '(?i)\btorch\b') { $combo++ }
1864+
if ($content -match '(?i)\bmss\b') { $combo++ }
1865+
if ($content -match '(?i)pyautogui|pydirectinput|pynput') { $combo++ }
1866+
if ($content -match '(?i)opencv-python|cv2') { $combo++ }
1867+
if ($content -match '(?i)onnxruntime') { $combo++ }
1868+
if ($combo -ge 3) {
1869+
[void]$pyDepHits.Add(@{ File=$f; Score=$combo })
18151870
}
1816-
} catch {}
1871+
} catch {}
1872+
}
18171873
}
18181874

18191875
# Emit ONNX findings according to constellation rules.

0 commit comments

Comments
 (0)