pybinaryguard 1.0.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.
- pybinaryguard/__init__.py +78 -0
- pybinaryguard/__main__.py +7 -0
- pybinaryguard/_compat/__init__.py +0 -0
- pybinaryguard/agent/__init__.py +63 -0
- pybinaryguard/agent/guard.py +232 -0
- pybinaryguard/agent/recommender.py +283 -0
- pybinaryguard/agent/schema.py +200 -0
- pybinaryguard/agent/simulator.py +430 -0
- pybinaryguard/agent/tool_interface.py +474 -0
- pybinaryguard/analyzers/__init__.py +209 -0
- pybinaryguard/analyzers/base.py +40 -0
- pybinaryguard/analyzers/dependency_analyzer.py +336 -0
- pybinaryguard/analyzers/elf_analyzer.py +754 -0
- pybinaryguard/analyzers/symbol_analyzer.py +280 -0
- pybinaryguard/analyzers/wheel_analyzer.py +308 -0
- pybinaryguard/cli/__init__.py +5 -0
- pybinaryguard/cli/commands.py +414 -0
- pybinaryguard/cli/formatters.py +720 -0
- pybinaryguard/cli/main.py +250 -0
- pybinaryguard/diagnostics/__init__.py +13 -0
- pybinaryguard/diagnostics/explainer.py +356 -0
- pybinaryguard/diagnostics/findings.py +146 -0
- pybinaryguard/diagnostics/suggestions.py +508 -0
- pybinaryguard/frameworks/__init__.py +20 -0
- pybinaryguard/frameworks/onnxruntime.py +214 -0
- pybinaryguard/frameworks/pytorch.py +223 -0
- pybinaryguard/frameworks/tensorflow.py +266 -0
- pybinaryguard/frameworks/tensorrt.py +189 -0
- pybinaryguard/models/__init__.py +19 -0
- pybinaryguard/models/enums.py +102 -0
- pybinaryguard/models/finding.py +109 -0
- pybinaryguard/models/package.py +121 -0
- pybinaryguard/models/system.py +118 -0
- pybinaryguard/plugins/__init__.py +19 -0
- pybinaryguard/plugins/contrib/__init__.py +7 -0
- pybinaryguard/plugins/contrib/gstreamer.py +109 -0
- pybinaryguard/plugins/contrib/jetson.py +385 -0
- pybinaryguard/plugins/contrib/opencv.py +306 -0
- pybinaryguard/plugins/contrib/tensorrt.py +426 -0
- pybinaryguard/plugins/hooks.py +273 -0
- pybinaryguard/plugins/loader.py +190 -0
- pybinaryguard/predictor/__init__.py +23 -0
- pybinaryguard/predictor/dependency_graph.py +226 -0
- pybinaryguard/predictor/linker_simulator.py +161 -0
- pybinaryguard/predictor/predictor.py +144 -0
- pybinaryguard/predictor/resolver.py +282 -0
- pybinaryguard/probes/__init__.py +73 -0
- pybinaryguard/probes/base.py +45 -0
- pybinaryguard/probes/board_probe.py +248 -0
- pybinaryguard/probes/cpu_probe.py +176 -0
- pybinaryguard/probes/glibc_probe.py +215 -0
- pybinaryguard/probes/gpu_probe.py +430 -0
- pybinaryguard/probes/library_probe.py +132 -0
- pybinaryguard/probes/os_probe.py +227 -0
- pybinaryguard/probes/python_probe.py +135 -0
- pybinaryguard/probes/toolchain_probe.py +89 -0
- pybinaryguard/probes/venv_probe.py +111 -0
- pybinaryguard/profiles/__init__.py +12 -0
- pybinaryguard/profiles/engine.py +343 -0
- pybinaryguard/rules/__init__.py +24 -0
- pybinaryguard/rules/base.py +57 -0
- pybinaryguard/rules/builtin/__init__.py +136 -0
- pybinaryguard/rules/builtin/arch_rules.py +86 -0
- pybinaryguard/rules/builtin/board_profile_rules.py +282 -0
- pybinaryguard/rules/builtin/container_rules.py +170 -0
- pybinaryguard/rules/builtin/cpu_rules.py +204 -0
- pybinaryguard/rules/builtin/cuda_rules.py +760 -0
- pybinaryguard/rules/builtin/dependency_rules.py +278 -0
- pybinaryguard/rules/builtin/framework_rules.py +252 -0
- pybinaryguard/rules/builtin/glibc_rules.py +320 -0
- pybinaryguard/rules/builtin/numpy_rules.py +110 -0
- pybinaryguard/rules/builtin/predictive_rules.py +165 -0
- pybinaryguard/rules/builtin/python_abi_rules.py +259 -0
- pybinaryguard/rules/builtin/source_build_rules.py +150 -0
- pybinaryguard/rules/builtin/venv_rules.py +159 -0
- pybinaryguard/rules/engine.py +123 -0
- pybinaryguard/scanner.py +904 -0
- pybinaryguard/scoring/__init__.py +19 -0
- pybinaryguard/scoring/engine.py +416 -0
- pybinaryguard/snapshot/__init__.py +20 -0
- pybinaryguard/snapshot/generator.py +168 -0
- pybinaryguard/snapshot/lockfile.py +152 -0
- pybinaryguard/snapshot/verifier.py +315 -0
- pybinaryguard/validators/__init__.py +7 -0
- pybinaryguard/validators/import_validator.py +231 -0
- pybinaryguard-1.0.0.dist-info/METADATA +876 -0
- pybinaryguard-1.0.0.dist-info/RECORD +91 -0
- pybinaryguard-1.0.0.dist-info/WHEEL +5 -0
- pybinaryguard-1.0.0.dist-info/entry_points.txt +8 -0
- pybinaryguard-1.0.0.dist-info/licenses/LICENSE +21 -0
- pybinaryguard-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,876 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pybinaryguard
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Binary Compatibility Intelligence for Python — detect incompatibilities before they crash your program
|
|
5
|
+
Author-email: S P Pothihai Selvan <po@nuvai.dev>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Nuvai/pybinaryguard
|
|
8
|
+
Project-URL: Repository, https://github.com/Nuvai/pybinaryguard
|
|
9
|
+
Project-URL: Issues, https://github.com/Nuvai/pybinaryguard/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Nuvai/pybinaryguard/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: binary,compatibility,elf,glibc,cuda,diagnostics
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
|
+
Classifier: Topic :: System :: Systems Administration
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Provides-Extra: full
|
|
27
|
+
Requires-Dist: pyelftools>=0.29; extra == "full"
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
31
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
32
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
<p align="center">
|
|
36
|
+
<img src="https://img.shields.io/badge/python-3.9%2B-blue?style=for-the-badge&logo=python&logoColor=white" alt="Python 3.9+">
|
|
37
|
+
<img src="https://img.shields.io/badge/license-MIT-green?style=for-the-badge" alt="MIT License">
|
|
38
|
+
<img src="https://img.shields.io/badge/platform-linux-orange?style=for-the-badge&logo=linux&logoColor=white" alt="Linux">
|
|
39
|
+
<img src="https://img.shields.io/badge/version-1.0.0-purple?style=for-the-badge" alt="v1.0.0">
|
|
40
|
+
<img src="https://img.shields.io/badge/tests-505%20passing-brightgreen?style=for-the-badge" alt="505 Tests">
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
<h1 align="center">PyBinaryGuard</h1>
|
|
44
|
+
|
|
45
|
+
<p align="center">
|
|
46
|
+
<strong>Binary Compatibility Intelligence for Python</strong><br>
|
|
47
|
+
Detect incompatibilities <em>before</em> they crash your program.
|
|
48
|
+
</p>
|
|
49
|
+
|
|
50
|
+
<p align="center">
|
|
51
|
+
<a href="#quick-start">Quick Start</a> •
|
|
52
|
+
<a href="#why-pybinaryguard">Why?</a> •
|
|
53
|
+
<a href="#features">Features</a> •
|
|
54
|
+
<a href="#cli-usage">CLI</a> •
|
|
55
|
+
<a href="#python-api">Python API</a> •
|
|
56
|
+
<a href="#agent-sdk">Agent SDK</a> •
|
|
57
|
+
<a href="#architecture">Architecture</a>
|
|
58
|
+
</p>
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Origin Story
|
|
63
|
+
|
|
64
|
+
Back in college, I was working on real-time object detection on an **NVIDIA Jetson TX2** — computer vision, image processing, and ML models for live detection. I spent weeks writing the code. Tested the logic. Verified every layer, every weight, every preprocessing step. The code had **zero errors**.
|
|
65
|
+
|
|
66
|
+
Then I hit run.
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
Illegal instruction (core dumped)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
That's it. No traceback. No helpful message. Just — *"instruction unclear, core dumped."*
|
|
73
|
+
|
|
74
|
+
I stared at the screen. I checked the code again. **Nothing was wrong.** I rewrote parts of it. Same crash. I tried different package versions. Same crash. I searched Stack Overflow for hours. Nothing worked.
|
|
75
|
+
|
|
76
|
+
This went on for **days**. Every single day, the same cryptic error. I started questioning my own code, my understanding of Python, everything. It was pure rage.
|
|
77
|
+
|
|
78
|
+
Then one day I finally figured it out — it wasn't my code at all. The pip packages I installed were compiled for a different architecture. The CUDA toolkit version didn't match what PyTorch expected. The GLIBC on the Jetson was too old for the prebuilt wheels. The binaries simply didn't belong on that hardware.
|
|
79
|
+
|
|
80
|
+
**My code was perfect. The binaries were incompatible.**
|
|
81
|
+
|
|
82
|
+
And the worst part? There was no tool to tell me this. No `pip check` that catches binary mismatches. No scanner that says *"hey, this .so file needs GLIBC 2.34 but you only have 2.27."* Nothing.
|
|
83
|
+
|
|
84
|
+
I told myself: if I ever get the chance, I'll build the tool I wish I had during those sleepless nights on the Jetson. Something that looks at your system — your CPU, your GPU, your GLIBC, your CUDA — and tells you **what's actually wrong** before you waste another day blaming your own code.
|
|
85
|
+
|
|
86
|
+
That tool is **PyBinaryGuard**.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## The Problem
|
|
91
|
+
|
|
92
|
+
You install a Python package. Your code is correct. Your machine is fine. **It still crashes.**
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
ImportError: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.34' not found
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
Illegal instruction (core dumped)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
OSError: libcudart.so.12: cannot open shared object file
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
These aren't bugs in your code. They're **binary-level incompatibilities** between compiled C/C++ libraries inside Python packages and your system's hardware, OS, or drivers. No existing tool catches them before runtime.
|
|
107
|
+
|
|
108
|
+
**PyBinaryGuard does.**
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Why PyBinaryGuard?
|
|
113
|
+
|
|
114
|
+
| Tool | What it does | What it misses |
|
|
115
|
+
|------|-------------|----------------|
|
|
116
|
+
| `pip check` | Version conflicts | Binary/ABI compatibility |
|
|
117
|
+
| `ldd` | Shared library links | Python package context |
|
|
118
|
+
| `nvidia-smi` | GPU info | Cross-package CUDA conflicts |
|
|
119
|
+
| `file` | ELF metadata | Compatibility analysis |
|
|
120
|
+
| **PyBinaryGuard** | **All of the above, unified** | -- |
|
|
121
|
+
|
|
122
|
+
PyBinaryGuard is the **first tool** that correlates your Python version, CPU architecture, GLIBC version, CUDA toolkit, GPU compute capability, and installed package binaries into a single compatibility verdict.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Quick Start
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Clone and install
|
|
130
|
+
git clone https://github.com/vikash-nuvai/pybinaryguard.git
|
|
131
|
+
cd pybinaryguard
|
|
132
|
+
pip install -e .
|
|
133
|
+
|
|
134
|
+
# Run a full scan
|
|
135
|
+
pybinaryguard scan
|
|
136
|
+
|
|
137
|
+
# Check a specific package
|
|
138
|
+
pybinaryguard check torch
|
|
139
|
+
|
|
140
|
+
# Fast scan (metadata only, <1 second)
|
|
141
|
+
pybinaryguard scan --fast
|
|
142
|
+
|
|
143
|
+
# Deep scan (full symbol resolution + hash verification)
|
|
144
|
+
pybinaryguard scan --deep
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Features
|
|
150
|
+
|
|
151
|
+
### Core Scanner
|
|
152
|
+
- **System Profiling** -- Detects Python version, CPU architecture (x86_64/aarch64/armv7l), GLIBC version, CUDA toolkit, GPU compute capability, container environment
|
|
153
|
+
- **Binary Analysis** -- Inspects `.so` shared objects inside installed packages using ELF header parsing and symbol resolution
|
|
154
|
+
- **20+ Built-in Rules** -- Covers GLIBC version requirements, CUDA ABI mismatches, CPU instruction set conflicts, architecture mismatches, NumPy ABI breaks, container-specific issues, and more
|
|
155
|
+
- **Plugin System** -- Extensible with custom probes, analyzers, and rules for Jetson, TensorRT, OpenCV, GStreamer
|
|
156
|
+
|
|
157
|
+
### Health Scoring v2
|
|
158
|
+
Multi-dimensional weighted scoring across 4 categories:
|
|
159
|
+
|
|
160
|
+
| Category | Weight | What it measures |
|
|
161
|
+
|----------|--------|------------------|
|
|
162
|
+
| Binary Stability | 35% | GLIBC, ELF, ABI issues |
|
|
163
|
+
| GPU Compatibility | 30% | CUDA, compute capability, driver mismatches |
|
|
164
|
+
| Dependency Health | 25% | Version conflicts, missing libraries |
|
|
165
|
+
| Platform Risk | 10% | Architecture, container, OS-specific issues |
|
|
166
|
+
|
|
167
|
+
Weights auto-adjust based on your system (e.g., no GPU = GPU weight redistributed).
|
|
168
|
+
|
|
169
|
+
### Scan Modes
|
|
170
|
+
|
|
171
|
+
| Mode | Speed | Depth | Use case |
|
|
172
|
+
|------|-------|-------|----------|
|
|
173
|
+
| `--fast` | <1s | Metadata only, skips ELF analysis | CI pipelines, quick checks |
|
|
174
|
+
| *(default)* | ~3s | Full binary analysis | Development workflow |
|
|
175
|
+
| `--deep` | ~10s | Symbol resolution + SHA256 hashes | Security audits, production deploys |
|
|
176
|
+
|
|
177
|
+
### Board Profile Engine
|
|
178
|
+
Built-in support for embedded/edge platforms:
|
|
179
|
+
- **NVIDIA Jetson** (Nano, TX2, Xavier, Orin)
|
|
180
|
+
- **Raspberry Pi** (3B, 4B, 5, Zero 2W)
|
|
181
|
+
- Custom board profiles via plugin system
|
|
182
|
+
|
|
183
|
+
### AI Framework Inspection
|
|
184
|
+
Specialized checks for ML/AI stacks:
|
|
185
|
+
- PyTorch CUDA ABI compatibility
|
|
186
|
+
- PyTorch + TorchVision version matrix
|
|
187
|
+
- TensorFlow compute capability requirements
|
|
188
|
+
- TensorRT version compatibility
|
|
189
|
+
- ONNX Runtime execution provider validation
|
|
190
|
+
|
|
191
|
+
### Predictive Failure Engine
|
|
192
|
+
Predicts runtime failures before they happen:
|
|
193
|
+
- Import error prediction based on dependency chain analysis
|
|
194
|
+
- Unresolved symbol detection
|
|
195
|
+
- Cross-package ABI conflict detection
|
|
196
|
+
|
|
197
|
+
### Environment Snapshots
|
|
198
|
+
Lock and verify your binary environment:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Create a snapshot
|
|
202
|
+
pybinaryguard snapshot -o env.lock.json
|
|
203
|
+
|
|
204
|
+
# Verify against snapshot on another machine
|
|
205
|
+
pybinaryguard verify env.lock.json
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## CLI Usage
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
pybinaryguard <command> [options]
|
|
214
|
+
|
|
215
|
+
Commands:
|
|
216
|
+
scan Full environment scan
|
|
217
|
+
check <package> Check a specific package
|
|
218
|
+
profile Show system profile
|
|
219
|
+
doctor Interactive troubleshooting
|
|
220
|
+
inspect <file> Analyse a .whl or .so file
|
|
221
|
+
snapshot Create environment snapshot
|
|
222
|
+
verify <lockfile> Verify against snapshot
|
|
223
|
+
simulate <spec> Predict compatibility before install
|
|
224
|
+
export-tool-schema Export agent tool schema
|
|
225
|
+
|
|
226
|
+
Global Options:
|
|
227
|
+
--format {table,json,minimal} Output format (default: table)
|
|
228
|
+
--severity {critical,warning,info,all}
|
|
229
|
+
--fast / --deep Scan depth
|
|
230
|
+
--ci CI mode (minimal + strict exit codes)
|
|
231
|
+
--ignore RULE_ID [...] Rules to skip
|
|
232
|
+
--timeout SECONDS Max scan time (default: 30)
|
|
233
|
+
--no-color Disable coloured output
|
|
234
|
+
-v, --verbose Show technical details
|
|
235
|
+
-q, --quiet Critical findings only
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Exit Codes
|
|
239
|
+
|
|
240
|
+
| Code | Meaning |
|
|
241
|
+
|------|---------|
|
|
242
|
+
| 0 | All clear |
|
|
243
|
+
| 1 | Warnings found |
|
|
244
|
+
| 2 | Critical issues found |
|
|
245
|
+
| 3 | Scanner error |
|
|
246
|
+
|
|
247
|
+
### CI/CD Integration
|
|
248
|
+
|
|
249
|
+
```yaml
|
|
250
|
+
# GitHub Actions
|
|
251
|
+
- name: Binary compatibility check
|
|
252
|
+
run: |
|
|
253
|
+
pip install pybinaryguard
|
|
254
|
+
pybinaryguard scan --ci
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
```Dockerfile
|
|
258
|
+
# Docker health check
|
|
259
|
+
HEALTHCHECK CMD pybinaryguard scan --fast --ci || exit 1
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Python API
|
|
265
|
+
|
|
266
|
+
```python
|
|
267
|
+
import pybinaryguard
|
|
268
|
+
|
|
269
|
+
# Full environment scan
|
|
270
|
+
report = pybinaryguard.scan()
|
|
271
|
+
print(f"Health: {report.health_score}/100")
|
|
272
|
+
print(f"Issues: {report.total_findings}")
|
|
273
|
+
|
|
274
|
+
for finding in report.findings:
|
|
275
|
+
print(f"[{finding.severity}] {finding.rule_id}: {finding.message}")
|
|
276
|
+
if finding.suggestion:
|
|
277
|
+
print(f" Fix: {finding.suggestion}")
|
|
278
|
+
|
|
279
|
+
# Check a single package
|
|
280
|
+
findings = pybinaryguard.check("torch")
|
|
281
|
+
|
|
282
|
+
# Get system profile
|
|
283
|
+
profile = pybinaryguard.profile()
|
|
284
|
+
print(f"Python: {profile.python_version}")
|
|
285
|
+
print(f"GLIBC: {profile.glibc_version}")
|
|
286
|
+
print(f"Arch: {profile.architecture}")
|
|
287
|
+
print(f"CUDA: {profile.cuda_version}")
|
|
288
|
+
|
|
289
|
+
# Inspect a wheel file before installing
|
|
290
|
+
findings = pybinaryguard.inspect("torch-2.4.0-cp311-cp311-manylinux1_x86_64.whl")
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Agent SDK
|
|
296
|
+
|
|
297
|
+
PyBinaryGuard is **agent-native** -- designed for AI agents and automation pipelines to consume directly.
|
|
298
|
+
|
|
299
|
+
### Structured Output
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
from pybinaryguard.agent import scan, check, simulate_install, doctor
|
|
303
|
+
|
|
304
|
+
# Returns machine-readable ActionableReport
|
|
305
|
+
report = scan()
|
|
306
|
+
report.to_dict() # JSON-serializable
|
|
307
|
+
|
|
308
|
+
# Classified actions with safety levels
|
|
309
|
+
report.safe_actions # Auto-executable (e.g., pip install --upgrade)
|
|
310
|
+
report.review_actions # Needs human confirmation
|
|
311
|
+
report.dangerous_actions # Human-only (e.g., system library changes)
|
|
312
|
+
|
|
313
|
+
# Pre-install simulation
|
|
314
|
+
sim = simulate_install("torch==2.4.0+cu124")
|
|
315
|
+
sim.predicted_compatible # True/False
|
|
316
|
+
sim.confidence # 0.0-1.0
|
|
317
|
+
sim.blockers # List of blocking issues
|
|
318
|
+
|
|
319
|
+
# Error diagnosis
|
|
320
|
+
dx = doctor("GLIBC_2.34 not found")
|
|
321
|
+
dx.diagnosis # What went wrong
|
|
322
|
+
dx.fix_plan # Step-by-step fix
|
|
323
|
+
dx.auto_fix_safe # Can an agent fix this automatically?
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Tool Schema Export
|
|
327
|
+
|
|
328
|
+
Register PyBinaryGuard as a tool in any agent framework:
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
from pybinaryguard.agent import export_tool_schema
|
|
332
|
+
|
|
333
|
+
# OpenAI function calling format
|
|
334
|
+
schema = export_tool_schema(format="openai")
|
|
335
|
+
|
|
336
|
+
# MCP (Model Context Protocol) format
|
|
337
|
+
schema = export_tool_schema(format="mcp")
|
|
338
|
+
|
|
339
|
+
# Generic JSON Schema
|
|
340
|
+
schema = export_tool_schema(format="json_schema")
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
# CLI export
|
|
345
|
+
pybinaryguard export-tool-schema --schema-format openai
|
|
346
|
+
pybinaryguard export-tool-schema --schema-format mcp
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### One-Liner Agent Registration
|
|
350
|
+
|
|
351
|
+
```python
|
|
352
|
+
from pybinaryguard.agent import as_agent_tool
|
|
353
|
+
|
|
354
|
+
# Returns {schema: ..., handlers: {scan: fn, check: fn, ...}}
|
|
355
|
+
tool = as_agent_tool()
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Runtime Import Guard
|
|
359
|
+
|
|
360
|
+
Capture and diagnose import failures in real-time:
|
|
361
|
+
|
|
362
|
+
```python
|
|
363
|
+
from pybinaryguard.agent.guard import guarded_imports
|
|
364
|
+
|
|
365
|
+
with guarded_imports() as guard:
|
|
366
|
+
import torch # If this fails, guard captures structured diagnostics
|
|
367
|
+
|
|
368
|
+
for error in guard.captured_errors:
|
|
369
|
+
print(error["category"]) # e.g., "glibc_mismatch"
|
|
370
|
+
print(error["diagnosis"]) # Human-readable explanation
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## How It Works (UML Diagrams)
|
|
376
|
+
|
|
377
|
+
### Core Scan Pipeline
|
|
378
|
+
|
|
379
|
+
The entire library follows a 4-phase pipeline: **Probe → Analyze → Evaluate → Report**.
|
|
380
|
+
|
|
381
|
+
```mermaid
|
|
382
|
+
flowchart TB
|
|
383
|
+
subgraph INPUT["INPUT"]
|
|
384
|
+
USER["User / Agent / CI"]
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
subgraph PHASE1["PHASE 1: PROBE — Collect System Info"]
|
|
388
|
+
direction LR
|
|
389
|
+
PP["PythonProbe<br/>Python version, ABI"]
|
|
390
|
+
CP["CpuProbe<br/>Architecture, ISA"]
|
|
391
|
+
GP["GlibcProbe<br/>GLIBC version"]
|
|
392
|
+
GPU["GpuProbe<br/>CUDA, GPU, compute cap"]
|
|
393
|
+
OP["OsProbe<br/>OS, container detect"]
|
|
394
|
+
LP["LibraryProbe<br/>System shared libs"]
|
|
395
|
+
BP["BoardProbe<br/>Jetson, RPi detect"]
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
subgraph PROFILE["SystemProfile"]
|
|
399
|
+
SP["python_version<br/>architecture<br/>glibc_version<br/>cuda_version<br/>gpu_name<br/>compute_capability<br/>os_name<br/>is_container<br/>..."]
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
subgraph PHASE2["PHASE 2: ANALYZE — Inspect Package Binaries"]
|
|
403
|
+
direction LR
|
|
404
|
+
WA["WheelAnalyzer<br/>WHEEL metadata, tags"]
|
|
405
|
+
EA["ELF Analyzer<br/>Headers, symbols, DT_NEEDED"]
|
|
406
|
+
SA["SymbolAnalyzer<br/>Unresolved symbols"]
|
|
407
|
+
DA["DependencyAnalyzer<br/>Dependency chain"]
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
subgraph PACKAGES["PackageBinaryInfo[]"]
|
|
411
|
+
PKG["package_name<br/>shared_objects[]<br/>wheel_tags[]<br/>required_glibc<br/>target_architecture<br/>..."]
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
subgraph PHASE3["PHASE 3: EVALUATE — Run Compatibility Rules"]
|
|
415
|
+
direction LR
|
|
416
|
+
RE["RuleEngine"]
|
|
417
|
+
R1["GLIBC Rules"]
|
|
418
|
+
R2["CUDA Rules"]
|
|
419
|
+
R3["Arch Rules"]
|
|
420
|
+
R4["CPU Rules"]
|
|
421
|
+
R5["NumPy ABI Rules"]
|
|
422
|
+
R6["Container Rules"]
|
|
423
|
+
R7["Framework Rules<br/>PyTorch, TF, TRT, ONNX"]
|
|
424
|
+
R8["Board Rules<br/>Jetson, RPi"]
|
|
425
|
+
R9["Predictive Rules"]
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
subgraph FINDINGS["Finding[]"]
|
|
429
|
+
F["rule_id<br/>severity<br/>package<br/>message<br/>suggestion<br/>confidence"]
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
subgraph PHASE4["PHASE 4: REPORT — Score & Format"]
|
|
433
|
+
direction LR
|
|
434
|
+
HS["HealthScoreV2<br/>4-category weighted"]
|
|
435
|
+
FMT["Formatter<br/>Table / JSON / Minimal"]
|
|
436
|
+
AGENT["Agent SDK<br/>ActionRecommender"]
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
subgraph OUTPUT["OUTPUT"]
|
|
440
|
+
SR["ScanReport<br/>health_score: 73/100<br/>findings: [...]<br/>score_breakdown: {...}"]
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
USER -->|"scan() / check() / CLI"| PHASE1
|
|
444
|
+
PP & CP & GP & GPU & OP & LP & BP -->|"parallel threads"| PROFILE
|
|
445
|
+
PROFILE --> PHASE2
|
|
446
|
+
WA & EA & SA & DA -->|"per package"| PACKAGES
|
|
447
|
+
PROFILE --> PHASE3
|
|
448
|
+
PACKAGES --> PHASE3
|
|
449
|
+
RE --> R1 & R2 & R3 & R4 & R5 & R6 & R7 & R8 & R9
|
|
450
|
+
PHASE3 --> FINDINGS
|
|
451
|
+
FINDINGS --> PHASE4
|
|
452
|
+
HS & FMT & AGENT --> OUTPUT
|
|
453
|
+
OUTPUT --> USER
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Sequence Diagram — Full Scan Flow
|
|
457
|
+
|
|
458
|
+
Step-by-step execution when a user runs `pybinaryguard scan`:
|
|
459
|
+
|
|
460
|
+
```mermaid
|
|
461
|
+
sequenceDiagram
|
|
462
|
+
actor User
|
|
463
|
+
participant CLI as CLI (main.py)
|
|
464
|
+
participant CMD as Commands (commands.py)
|
|
465
|
+
participant Scanner
|
|
466
|
+
participant Probes as Probes (7 probes)
|
|
467
|
+
participant Analyzers as ELF/Wheel Analyzers
|
|
468
|
+
participant Rules as Rule Engine (20+ rules)
|
|
469
|
+
participant Scoring as HealthScoreV2
|
|
470
|
+
participant Formatter as Table/JSON Formatter
|
|
471
|
+
|
|
472
|
+
User->>CLI: pybinaryguard scan
|
|
473
|
+
CLI->>CMD: dispatch(args)
|
|
474
|
+
CMD->>Scanner: Scanner(scan_mode, ...).run()
|
|
475
|
+
|
|
476
|
+
Note over Scanner: PHASE 1: PROBE
|
|
477
|
+
Scanner->>Probes: run all probes (parallel threads)
|
|
478
|
+
Probes-->>Scanner: merged dict
|
|
479
|
+
Scanner->>Scanner: build SystemProfile
|
|
480
|
+
|
|
481
|
+
Note over Scanner: PHASE 2: ANALYZE
|
|
482
|
+
Scanner->>Scanner: walk site-packages dirs
|
|
483
|
+
loop Each package with .dist-info
|
|
484
|
+
Scanner->>Analyzers: parse WHEEL tags
|
|
485
|
+
alt STANDARD or DEEP mode
|
|
486
|
+
Scanner->>Analyzers: parse ELF headers (.so files)
|
|
487
|
+
Analyzers-->>Scanner: SharedObjectInfo[]
|
|
488
|
+
end
|
|
489
|
+
alt DEEP mode only
|
|
490
|
+
Scanner->>Scanner: compute SHA256 hashes
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
Scanner-->>Scanner: PackageBinaryInfo[]
|
|
494
|
+
|
|
495
|
+
Note over Scanner: PHASE 3: EVALUATE
|
|
496
|
+
Scanner->>Rules: RuleEngine.with_builtin_rules()
|
|
497
|
+
loop Each rule
|
|
498
|
+
Rules->>Rules: is_applicable(profile)?
|
|
499
|
+
alt applicable
|
|
500
|
+
Rules->>Rules: evaluate(profile, packages)
|
|
501
|
+
Rules-->>Scanner: Finding[]
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
Note over Scanner: PHASE 4: REPORT
|
|
506
|
+
Scanner->>Scoring: compute_health_score(findings)
|
|
507
|
+
Scoring-->>Scanner: ScoreBreakdown
|
|
508
|
+
Scanner->>Scanner: deduplicate, filter, sort
|
|
509
|
+
Scanner-->>CMD: ScanReport
|
|
510
|
+
|
|
511
|
+
CMD->>Formatter: format_scan(report, profile)
|
|
512
|
+
Formatter-->>CMD: formatted string
|
|
513
|
+
CMD-->>CLI: exit code (0/1/2)
|
|
514
|
+
CLI-->>User: printed output
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Health Scoring Model
|
|
518
|
+
|
|
519
|
+
How the multi-dimensional health score is calculated:
|
|
520
|
+
|
|
521
|
+
```mermaid
|
|
522
|
+
flowchart LR
|
|
523
|
+
subgraph FINDINGS["All Findings"]
|
|
524
|
+
F1["GLIBC_VERSION_MISMATCH<br/>severity: CRITICAL"]
|
|
525
|
+
F2["CUDA_MINOR_MISMATCH<br/>severity: WARNING"]
|
|
526
|
+
F3["NUMPY_ABI_MISMATCH<br/>severity: WARNING"]
|
|
527
|
+
F4["CONTAINER_GLIBC_OLD<br/>severity: INFO"]
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
subgraph CLASSIFY["Classify by Rule ID Prefix"]
|
|
531
|
+
C1["binary_stability<br/>GLIBC_, ARCH_, ELF_, ..."]
|
|
532
|
+
C2["gpu_compat<br/>CUDA_, PYTORCH_CUDA_, ..."]
|
|
533
|
+
C3["dependency_health<br/>NUMPY_ABI_, MISSING_, ..."]
|
|
534
|
+
C4["platform_risk<br/>CONTAINER_, BOARD_, ..."]
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
subgraph SCORE["Score Each Category"]
|
|
538
|
+
S1["Binary: 70/100<br/>weight: 0.35"]
|
|
539
|
+
S2["GPU: 90/100<br/>weight: 0.30"]
|
|
540
|
+
S3["Deps: 90/100<br/>weight: 0.25"]
|
|
541
|
+
S4["Platform: 98/100<br/>weight: 0.10"]
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
subgraph TOTAL["Weighted Total"]
|
|
545
|
+
T["70x0.35 + 90x0.30 + 90x0.25 + 98x0.10<br/>= 24.5 + 27.0 + 22.5 + 9.8<br/>= <strong>83.8 / 100</strong>"]
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
F1 --> C1
|
|
549
|
+
F2 --> C2
|
|
550
|
+
F3 --> C3
|
|
551
|
+
F4 --> C4
|
|
552
|
+
|
|
553
|
+
C1 --> S1
|
|
554
|
+
C2 --> S2
|
|
555
|
+
C3 --> S3
|
|
556
|
+
C4 --> S4
|
|
557
|
+
|
|
558
|
+
S1 & S2 & S3 & S4 --> T
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### Agent SDK Flow
|
|
562
|
+
|
|
563
|
+
How AI agents interact with PyBinaryGuard:
|
|
564
|
+
|
|
565
|
+
```mermaid
|
|
566
|
+
flowchart TB
|
|
567
|
+
subgraph AGENT["AI Agent (GPT, LangChain, AutoGen, CrewAI, etc.)"]
|
|
568
|
+
A1["1. Register tool via schema"]
|
|
569
|
+
A2["2. Call scan/check/simulate/doctor"]
|
|
570
|
+
A3["3. Read structured result"]
|
|
571
|
+
A4["4. Execute safe_actions automatically"]
|
|
572
|
+
A5["5. Ask human for review_actions"]
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
subgraph SDK["PyBinaryGuard Agent SDK"]
|
|
576
|
+
SCHEMA["export_tool_schema()<br/>OpenAI / MCP / JSON Schema"]
|
|
577
|
+
SCAN["scan() → ActionableReport"]
|
|
578
|
+
CHECK["check('torch') → AgentCheckResult"]
|
|
579
|
+
SIM["simulate_install('torch==2.4.0+cu124')<br/>→ AgentSimulateResult"]
|
|
580
|
+
DOC["doctor('GLIBC_2.34 not found')<br/>→ AgentDoctorResult"]
|
|
581
|
+
REC["ActionRecommender<br/>classify actions by safety"]
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
subgraph SAFETY["Action Safety Classification"]
|
|
585
|
+
SAFE["SAFE (auto-execute)<br/>pip install --upgrade numpy<br/>pip install torch==2.3.0"]
|
|
586
|
+
REVIEW["REVIEW (confirm first)<br/>pip install --force-reinstall ...<br/>pip install package[cuda12]"]
|
|
587
|
+
DANGER["DANGEROUS (human only)<br/>apt install libcuda1<br/>System library changes"]
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
A1 -->|"schema = export_tool_schema('openai')"| SCHEMA
|
|
591
|
+
A2 --> SCAN & CHECK & SIM & DOC
|
|
592
|
+
SCAN --> REC
|
|
593
|
+
REC --> SAFE & REVIEW & DANGER
|
|
594
|
+
SAFE --> A4
|
|
595
|
+
REVIEW --> A5
|
|
596
|
+
DANGER -->|"flag to human"| A5
|
|
597
|
+
A3 -->|"result.to_dict() → JSON"| A2
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### Scan Mode Comparison
|
|
601
|
+
|
|
602
|
+
```mermaid
|
|
603
|
+
flowchart LR
|
|
604
|
+
subgraph FAST["--fast (<1 second)"]
|
|
605
|
+
F1_["Read WHEEL metadata"]
|
|
606
|
+
F2_["Check .so file existence"]
|
|
607
|
+
F3_["Run metadata-only rules"]
|
|
608
|
+
F4_["Skip ELF parsing entirely"]
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
subgraph STD["default (~3 seconds)"]
|
|
612
|
+
S1_["Read WHEEL metadata"]
|
|
613
|
+
S2_["Parse ELF headers"]
|
|
614
|
+
S3_["Extract DT_NEEDED, symbols"]
|
|
615
|
+
S4_["Run ALL rules"]
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
subgraph DEEP["--deep (~10 seconds)"]
|
|
619
|
+
D1_["Read WHEEL metadata"]
|
|
620
|
+
D2_["Parse ELF headers"]
|
|
621
|
+
D3_["Full symbol resolution"]
|
|
622
|
+
D4_["SHA256 hash every .so"]
|
|
623
|
+
D5_["Run ALL rules"]
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
F1_ --> F2_ --> F3_ --> F4_
|
|
627
|
+
S1_ --> S2_ --> S3_ --> S4_
|
|
628
|
+
D1_ --> D2_ --> D3_ --> D4_ --> D5_
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
### Class Diagram — Core Data Model
|
|
632
|
+
|
|
633
|
+
```mermaid
|
|
634
|
+
classDiagram
|
|
635
|
+
class SystemProfile {
|
|
636
|
+
+str python_version
|
|
637
|
+
+str architecture
|
|
638
|
+
+str glibc_version
|
|
639
|
+
+str cuda_version
|
|
640
|
+
+str gpu_name
|
|
641
|
+
+float compute_capability
|
|
642
|
+
+str os_name
|
|
643
|
+
+bool is_container
|
|
644
|
+
+bool gpu_available
|
|
645
|
+
+bool is_embedded_board
|
|
646
|
+
+list site_packages_paths
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
class PackageBinaryInfo {
|
|
650
|
+
+str package_name
|
|
651
|
+
+str package_version
|
|
652
|
+
+str install_path
|
|
653
|
+
+list~SharedObjectInfo~ shared_objects
|
|
654
|
+
+list~WheelTag~ wheel_tags
|
|
655
|
+
+str required_glibc
|
|
656
|
+
+str target_architecture
|
|
657
|
+
+bool has_binaries
|
|
658
|
+
+bool is_pure_python
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
class SharedObjectInfo {
|
|
662
|
+
+str name
|
|
663
|
+
+str path
|
|
664
|
+
+str architecture
|
|
665
|
+
+str required_glibc
|
|
666
|
+
+list~str~ dt_needed
|
|
667
|
+
+str sha256
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
class Finding {
|
|
671
|
+
+str rule_id
|
|
672
|
+
+Severity severity
|
|
673
|
+
+str title
|
|
674
|
+
+str explanation
|
|
675
|
+
+str package
|
|
676
|
+
+str suggestion
|
|
677
|
+
+float confidence
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
class ScanReport {
|
|
681
|
+
+list~Finding~ findings
|
|
682
|
+
+int packages_scanned
|
|
683
|
+
+int total_packages
|
|
684
|
+
+float scan_duration_ms
|
|
685
|
+
+ScoreBreakdown score_breakdown
|
|
686
|
+
+int health_score
|
|
687
|
+
+str health_label
|
|
688
|
+
+int critical_count
|
|
689
|
+
+int warning_count
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
class ScoreBreakdown {
|
|
693
|
+
+float overall_score
|
|
694
|
+
+str overall_label
|
|
695
|
+
+dict categories
|
|
696
|
+
+int total_findings
|
|
697
|
+
+CategoryScore weakest_category
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
class CategoryScore {
|
|
701
|
+
+str name
|
|
702
|
+
+float score
|
|
703
|
+
+float weight
|
|
704
|
+
+float weighted_score
|
|
705
|
+
+str label
|
|
706
|
+
+list top_issues
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
class Rule {
|
|
710
|
+
<<abstract>>
|
|
711
|
+
+str rule_id
|
|
712
|
+
+Severity severity
|
|
713
|
+
+is_applicable(SystemProfile) bool
|
|
714
|
+
+evaluate(SystemProfile, list) list~Finding~
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
class Scanner {
|
|
718
|
+
+run() ScanReport
|
|
719
|
+
+check_package(str) list~Finding~
|
|
720
|
+
+get_profile() SystemProfile
|
|
721
|
+
+inspect_file(str) list~Finding~
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
Scanner --> SystemProfile : collects
|
|
725
|
+
Scanner --> PackageBinaryInfo : analyzes
|
|
726
|
+
Scanner --> Rule : evaluates
|
|
727
|
+
Rule --> Finding : produces
|
|
728
|
+
Scanner --> ScanReport : builds
|
|
729
|
+
ScanReport --> Finding : contains
|
|
730
|
+
ScanReport --> ScoreBreakdown : includes
|
|
731
|
+
ScoreBreakdown --> CategoryScore : has 4
|
|
732
|
+
PackageBinaryInfo --> SharedObjectInfo : contains
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
---
|
|
736
|
+
|
|
737
|
+
## Project Structure
|
|
738
|
+
|
|
739
|
+
```
|
|
740
|
+
pybinaryguard/
|
|
741
|
+
|
|
|
742
|
+
|-- pyproject.toml # Packaging config (PEP 621)
|
|
743
|
+
|-- README.md
|
|
744
|
+
|-- LICENSE
|
|
745
|
+
|-- CHANGELOG.md
|
|
746
|
+
|-- .gitignore
|
|
747
|
+
|
|
|
748
|
+
|-- src/
|
|
749
|
+
| +-- pybinaryguard/
|
|
750
|
+
| |-- __init__.py # Public API (scan, check, profile, inspect)
|
|
751
|
+
| |-- scanner.py # Core orchestrator
|
|
752
|
+
| |
|
|
753
|
+
| |-- models/ # Data structures
|
|
754
|
+
| | |-- system.py # SystemProfile dataclass
|
|
755
|
+
| | |-- finding.py # Finding, ScanReport
|
|
756
|
+
| | |-- package.py # PackageBinaryInfo, SharedObjectInfo
|
|
757
|
+
| | +-- enums.py # Severity, ScanMode
|
|
758
|
+
| |
|
|
759
|
+
| |-- probes/ # System information collectors
|
|
760
|
+
| | |-- os_probe.py # OS, GLIBC, container detection
|
|
761
|
+
| | |-- python_probe.py # Python version, ABI flags
|
|
762
|
+
| | |-- cpu_probe.py # Architecture, instruction sets
|
|
763
|
+
| | |-- gpu_probe.py # CUDA, GPU compute capability
|
|
764
|
+
| | |-- glibc_probe.py # GLIBC version detection
|
|
765
|
+
| | |-- library_probe.py # System shared library inventory
|
|
766
|
+
| | +-- board_probe.py # Embedded board detection (Jetson, RPi)
|
|
767
|
+
| |
|
|
768
|
+
| |-- analyzers/ # Package binary inspectors
|
|
769
|
+
| | |-- elf_analyzer.py # ELF header & symbol table parsing
|
|
770
|
+
| | |-- wheel_analyzer.py
|
|
771
|
+
| | |-- symbol_analyzer.py
|
|
772
|
+
| | +-- dependency_analyzer.py
|
|
773
|
+
| |
|
|
774
|
+
| |-- rules/ # Compatibility rule engine
|
|
775
|
+
| | |-- engine.py # Rule evaluation orchestrator
|
|
776
|
+
| | +-- builtin/ # 20+ built-in rules
|
|
777
|
+
| | |-- glibc_rules.py
|
|
778
|
+
| | |-- cuda_rules.py
|
|
779
|
+
| | |-- arch_rules.py
|
|
780
|
+
| | |-- cpu_rules.py
|
|
781
|
+
| | |-- numpy_rules.py
|
|
782
|
+
| | |-- container_rules.py
|
|
783
|
+
| | |-- python_abi_rules.py
|
|
784
|
+
| | |-- board_profile_rules.py
|
|
785
|
+
| | |-- framework_rules.py
|
|
786
|
+
| | +-- predictive_rules.py
|
|
787
|
+
| |
|
|
788
|
+
| |-- scoring/ # Health scoring v2
|
|
789
|
+
| | +-- engine.py # Multi-dimensional weighted scoring
|
|
790
|
+
| |
|
|
791
|
+
| |-- profiles/ # Board profile engine
|
|
792
|
+
| | +-- engine.py # Board detection & matching
|
|
793
|
+
| |
|
|
794
|
+
| |-- diagnostics/ # Error explanation
|
|
795
|
+
| | |-- findings.py
|
|
796
|
+
| | |-- explainer.py
|
|
797
|
+
| | +-- suggestions.py
|
|
798
|
+
| |
|
|
799
|
+
| |-- agent/ # Agent SDK
|
|
800
|
+
| | |-- tool_interface.py
|
|
801
|
+
| | |-- recommender.py
|
|
802
|
+
| | |-- schema.py # Tool schema export (OpenAI/MCP)
|
|
803
|
+
| | |-- simulator.py # Pre-install compatibility prediction
|
|
804
|
+
| | +-- guard.py # Runtime import guard
|
|
805
|
+
| |
|
|
806
|
+
| |-- plugins/ # Plugin system
|
|
807
|
+
| | |-- loader.py
|
|
808
|
+
| | |-- hooks.py
|
|
809
|
+
| | +-- contrib/ # Built-in plugins (Jetson, TensorRT, OpenCV, GStreamer)
|
|
810
|
+
| |
|
|
811
|
+
| +-- cli/ # Command-line interface
|
|
812
|
+
| |-- main.py # Argument parser
|
|
813
|
+
| |-- commands.py # Command handlers
|
|
814
|
+
| +-- formatters.py # Output formatting (table/json/minimal)
|
|
815
|
+
|
|
|
816
|
+
|-- tests/ # 450 tests
|
|
817
|
+
|-- docs/ # Documentation
|
|
818
|
+
+-- examples/ # Usage examples
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
### Design Principles
|
|
822
|
+
|
|
823
|
+
1. **Zero dependencies by default** -- Core functionality works with just the Python standard library. Optional `pyelftools` enables deep ELF analysis.
|
|
824
|
+
|
|
825
|
+
2. **Read-only** -- Never modifies your system, packages, or files. Safe to run anywhere.
|
|
826
|
+
|
|
827
|
+
3. **Offline-first** -- No network calls. All analysis runs locally. Works in air-gapped environments.
|
|
828
|
+
|
|
829
|
+
4. **Agent-native** -- Structured JSON-serializable outputs. Tool schema export. Safety-classified actions.
|
|
830
|
+
|
|
831
|
+
5. **Extensible** -- Plugin system for custom probes, analyzers, and rules via entry points.
|
|
832
|
+
|
|
833
|
+
---
|
|
834
|
+
|
|
835
|
+
## Supported Platforms
|
|
836
|
+
|
|
837
|
+
| Platform | Architecture | Status |
|
|
838
|
+
|----------|-------------|--------|
|
|
839
|
+
| Ubuntu 20.04+ | x86_64 | Fully supported |
|
|
840
|
+
| Ubuntu 20.04+ | aarch64 | Fully supported |
|
|
841
|
+
| Debian 11+ | x86_64 / aarch64 | Fully supported |
|
|
842
|
+
| RHEL / CentOS 8+ | x86_64 | Supported |
|
|
843
|
+
| Alpine (musl) | x86_64 | Supported |
|
|
844
|
+
| NVIDIA Jetson | aarch64 | Supported (board profiles) |
|
|
845
|
+
| Raspberry Pi OS | armv7l / aarch64 | Supported (board profiles) |
|
|
846
|
+
| Docker containers | any | Supported (auto-detected) |
|
|
847
|
+
|
|
848
|
+
---
|
|
849
|
+
|
|
850
|
+
## Testing
|
|
851
|
+
|
|
852
|
+
```bash
|
|
853
|
+
# Run all tests (450 tests)
|
|
854
|
+
python -m pytest tests/ -v
|
|
855
|
+
|
|
856
|
+
# Run with coverage
|
|
857
|
+
python -m pytest tests/ --cov=pybinaryguard --cov-report=term-missing
|
|
858
|
+
|
|
859
|
+
# Run specific test suites
|
|
860
|
+
python -m pytest tests/test_scoring.py -v # Health scoring
|
|
861
|
+
python -m pytest tests/test_scan_modes.py -v # Scan modes
|
|
862
|
+
python -m pytest tests/test_agent_sdk.py -v # Agent SDK
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
---
|
|
866
|
+
|
|
867
|
+
## Author
|
|
868
|
+
|
|
869
|
+
**S P Pothihai Selvan** (Po-nuvai)
|
|
870
|
+
Applied Research Scientist @ [Nuvai AI Solution Pvt Ltd](https://nuvai.dev)
|
|
871
|
+
|
|
872
|
+
---
|
|
873
|
+
|
|
874
|
+
## License
|
|
875
|
+
|
|
876
|
+
MIT License. See [LICENSE](LICENSE) for details.
|