@@ -13,20 +13,29 @@ Future metrics (e.g., audio coverage, state-graph coverage) will follow the same
1313
1414```
1515.
16+ ├── Cargo.toml # Rust manifest (maturin builds the extension)
17+ ├── pyproject.toml # Project metadata, maturin build backend
1618├── src/
1719│ ├── main.py # CLI entry point (Typer)
20+ │ ├── lib.rs # PyO3 module entry point (Rust)
21+ │ ├── bktree.rs # BK-tree<u64> with POPCNT Hamming distance
22+ │ ├── unionfind.rs # Flat Vec-based union-find
23+ │ ├── monitor.rs # CoverageTracker (BK-tree + UnionFind combined)
1824│ └── gamecov/
1925│ ├── __init__.py # Public API re-exports
26+ │ ├── _gamecov_core.pyi # Type stub for Rust extension
2027│ ├── cov_base.py # Abstract protocols: CoverageItem, Coverage, CoverageMonitor
2128│ ├── frame.py # Frame dataclass (PIL Image wrapper with average-hash)
2229│ ├── dedup.py # Deduplication algorithms (pHash, SSIM [deprecated])
23- │ ├── frame_cov.py # FrameCoverage, FrameMonitor, BKFrameMonitor, BK-tree, UnionFind
30+ │ ├── frame_cov.py # FrameCoverage, FrameMonitor, BKFrameMonitor, RustBKFrameMonitor, BK-tree, UnionFind
2431│ ├── loader.py # MP4 loading: bulk, lazy (generator), last-n
2532│ ├── writer.py # MP4 writing: imageio and OpenCV backends
2633│ ├── stitch.py # Panorama stitching of unique frames
2734│ ├── generator.py # Hypothesis strategies for property-based testing
2835│ ├── env.py # Runtime config (RADIUS env var)
2936│ └── py.typed # PEP 561 marker
37+ ├── rust-tests/
38+ │ └── prop_tests.rs # Rust proptest property-based tests
3039├── tests/
3140│ ├── test_generators.py # Frame/FrameList generation strategies
3241│ ├── test_dedup.py # Dedup monotonicity properties
@@ -35,19 +44,34 @@ Future metrics (e.g., audio coverage, state-graph coverage) will follow the same
3544│ ├── test_load_write_assets.py# Differential tests across loaders on real videos
3645│ ├── test_monotone.py # Coverage monotonicity (FrameMonitor & BKFrameMonitor)
3746│ ├── test_BK_frame_monitor.py # Differential: FrameMonitor vs BKFrameMonitor
47+ │ ├── test_rust_frame_monitor.py # Differential & monotonicity: BKFrameMonitor vs RustBKFrameMonitor
3848│ └── test_monotone_smb.py # Real-world monotonicity on SMB dataset
49+ ├── benchmarks/
50+ │ ├── conftest.py # Session-scoped fixtures (pre-generated FrameCoverage)
51+ │ └── test_bench_monitor.py # Python vs Rust monitor throughput benchmarks
3952├── assets/
4053│ ├── videos/ # Small sample MP4s for integration tests
4154│ └── smb/ # Super Smash Bros recordings for stress tests
4255├── docs/
4356│ └── design.md # Architecture and design documentation
44- ├── pyproject .toml # Project metadata, dependencies, tool configs
45- ├── .pre-commit-config.yaml # Pre-commit hooks
46- ├── .github/workflows/ # CI: pytest, mypy, ruff, pylint
57+ ├── rustfmt .toml # Rust formatting config
58+ ├── .pre-commit-config.yaml # Pre-commit hooks (Python + Rust)
59+ ├── .github/workflows/ # CI: pytest, mypy, ruff, pylint, rust (fmt/clippy/test)
4760├── AGENTS.md # This file
4861└── README.md # Human-facing documentation
4962```
5063
64+ ### Rust extension (gamecov-core)
65+
66+ The Rust extension is built as part of the package via maturin. The compiled
67+ module is installed as ` gamecov._gamecov_core ` and provides high-performance
68+ replacements for the BK-tree, union-find, and coverage tracker.
69+
70+ Build the package (includes Rust compilation): ` uv sync ` or ` pip install . `
71+ Run Rust tests independently: ` cargo test `
72+ Check Rust formatting: ` cargo fmt --all -- --check `
73+ Run Rust linting: ` cargo clippy --all-targets --all-features -- -D warnings `
74+
5175## Design
5276
5377See [ docs/design.md] ( docs/design.md ) for the coverage framework architecture, frame coverage pipeline, BK-tree optimization, and loading strategies.
@@ -59,7 +83,7 @@ See [docs/design.md](docs/design.md) for the coverage framework architecture, fr
5983| ` cov_base.py ` | ` CoverageItem ` , ` Coverage[T] ` , ` CoverageMonitor[T] ` protocols/ABC |
6084| ` frame.py ` | ` Frame ` dataclass (PIL Image + average-hash) |
6185| ` dedup.py ` | ` is_dup() ` , ` dedup_unique_frames() ` , ` dedup_unique_hashes() ` , ` ssim_dedup() ` [ deprecated] |
62- | ` frame_cov.py ` | ` FrameCoverage ` , ` FrameMonitor ` , ` BKFrameMonitor ` , ` get_frame_cov() ` , ` _UnionFind ` , ` _BKTree ` |
86+ | ` frame_cov.py ` | ` FrameCoverage ` , ` FrameMonitor ` , ` BKFrameMonitor ` , ` RustBKFrameMonitor ` , ` get_frame_cov() ` , ` _UnionFind ` , ` _BKTree ` |
6387| ` loader.py ` | ` load_mp4() ` , ` load_mp4_lazy() ` , ` load_mp4_last_n() ` |
6488| ` writer.py ` | ` write_mp4() ` , ` write_mp4_cv2() ` |
6589| ` stitch.py ` | ` stitch_images() ` (panorama via AffineStitcher) |
@@ -80,7 +104,8 @@ See [docs/design.md](docs/design.md) for the coverage framework architecture, fr
80104| ` opencv-python ` | Color conversion, video writing, image processing |
81105| ` scikit-image ` | SSIM metric (deprecated path) |
82106| ` stitching ` | Panorama stitching via OpenCV features |
83- | ` numpy ` , ` numba ` | Numerical arrays, optional JIT acceleration |
107+ | ` numpy ` | Numerical arrays |
108+ | ` gamecov._gamecov_core ` | Built-in Rust extension: BK-tree, union-find, coverage tracker (PyO3/maturin) |
84109| ` returns ` | Functional ` Result ` type for error handling |
85110| ` deprecated ` | ` @deprecated ` decorator |
86111| ` typer-slim ` | CLI framework |
@@ -93,6 +118,7 @@ See [docs/design.md](docs/design.md) for the coverage framework architecture, fr
93118| ` mypy ` | Static type checking (strict mode, returns plugin) |
94119| ` ruff ` | Linting and formatting |
95120| ` pre-commit ` | Pre-commit hook runner |
121+ | ` pytest-benchmark ` | Performance benchmarking (Python vs Rust) |
96122| ` pytest-xdist ` | Parallel test execution (` -n auto ` ) |
97123| ` pytest-cov ` | Coverage reporting |
98124| ` pytest-profiling ` | Performance profiling |
@@ -110,6 +136,7 @@ uv run pytest -n auto
110136- ** Integration** (real assets): ` test_load_n.py ` , ` test_load_write_assets.py `
111137- ** Monotonicity** : ` test_monotone.py ` (random data), ` test_monotone_smb.py ` (real SMB recordings)
112138- ** Differential** : ` test_BK_frame_monitor.py ` (FrameMonitor vs BKFrameMonitor produce identical results)
139+ - ** Rust backend** : ` test_rust_frame_monitor.py ` (differential Python vs Rust, order-independence, monotonicity)
113140
114141Some tests require assets in ` assets/videos/ ` or ` assets/smb/ ` and will skip if missing.
115142
@@ -118,6 +145,24 @@ Some tests require assets in `assets/videos/` or `assets/smb/` and will skip if
118145- ` RADIUS ` — Hamming distance threshold (default ` 5 ` ).
119146- ` N_MAX ` — Maximum number of recordings to process in monotonicity tests (default ` 100 ` ).
120147
148+ ## Benchmarks
149+
150+ ``` bash
151+ # Run benchmarks (disabled by default during normal test runs)
152+ uv run pytest benchmarks/ --benchmark-enable
153+
154+ # Group output by backend for side-by-side comparison
155+ uv run pytest benchmarks/ --benchmark-enable --benchmark-group-by=param:backend
156+
157+ # Save results for later comparison
158+ uv run pytest benchmarks/ --benchmark-enable --benchmark-save=baseline
159+ uv run pytest benchmarks/ --benchmark-enable --benchmark-compare=baseline
160+ ```
161+
162+ Benchmarks live in ` benchmarks/ ` and are excluded from the normal test suite.
163+ They compare ` BKFrameMonitor ` (Python) vs ` RustBKFrameMonitor ` (Rust) throughput
164+ at the monitor level (` add_cov ` /` is_seen ` operations).
165+
121166## Development
122167
123168- Before start working, refresh your knowledge from contents in ` .agents ` first.
@@ -129,7 +174,8 @@ Some tests require assets in `assets/videos/` or `assets/smb/` and will skip if
129174 Local variables' types are optional as long as the types can be easily inferred.
130175- Use f-strings for string interpolation.
131176- Use ` TypedDict ` , ` Literal ` , ` Protocol ` , and ` TypeVar ` from ` typing ` module when appropriate.
132- - Always run ` mypy ` , and ` ruff ` to ensure code quality after updating code in ` src/ ` .
177+ - Always run ` mypy ` and ` ruff ` to ensure code quality after updating Python code in ` src/ ` .
178+ - Always run ` cargo fmt ` , ` cargo clippy -- -D warnings ` , and ` cargo test ` after updating Rust code in ` src/ ` .
133179- Never commit changes or create PRs. Suggest commit messages to the human developer for review after your changes to the codebase.
134180- Always use ` typer ` to handle CLI commands.
135181
0 commit comments