2114ccd278
CI / Lint & Test (Python 3.13) (push) Failing after 2s
CI / Lint & Test (Python 3.14) (push) Failing after 1s
CI / Lint & Test (Python 3.12) (push) Failing after 2s
CI / DCO Check (push) Has been skipped
Scorecard supply-chain security / Scorecard analysis (push) Failing after 2s
150 lines
5.8 KiB
Markdown
150 lines
5.8 KiB
Markdown
# Contributing — Multilingual Batch Scanner
|
|
|
|
> For developers who want to set up, test, and extend this module.
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
python3 -m venv .venv
|
|
source .venv/bin/activate
|
|
pip install -e .
|
|
cp contrib/batch_scan/.env.example .env # edit with your API keys
|
|
```
|
|
|
|
Verify everything works:
|
|
```bash
|
|
python -m contrib.batch_scan.batch_scan ./tests/fixtures/ -f terminal --workers 8
|
|
```
|
|
|
|
---
|
|
|
|
## Project Map
|
|
|
|
```
|
|
contrib/batch_scan/
|
|
├── batch_scan.py # CLI entry + ThreadPoolExecutor (start here)
|
|
├── runner.py # graph.invoke() wrapper + 7 patches + pool wiring (core)
|
|
├── gap_fill.py # GapFillAnalyzer — LLM pass for 8 uncovered rules
|
|
├── api_pool.py # ApiKeyPool — multi-key scheduler + 429 backoff
|
|
├── detection.py # Unicode script-ratio language detection
|
|
├── annotation.py # Finding language-compatibility labels
|
|
├── discovery.py # Recursive SKILL.md finder
|
|
├── reports.py # Terminal / JSON / Markdown formatters
|
|
├── CONTRIBUTING.md # this file
|
|
│
|
|
├── docs/
|
|
│ ├── README.md # user guide — all commands, test commands, reviewer index
|
|
│ ├── DESIGN.md # architecture — concurrency, patches, dual-patch mechanism
|
|
│ ├── REVIEW_RESPONSE.md # PR #100 review response
|
|
│ └── archive/ # deep dives, history, future work, pitfalls
|
|
│
|
|
└── tests/
|
|
├── test_pool_wiring.py # smoke — 3-path pool verification
|
|
├── test_monkeypatch_invasiveness.py # thread isolation, scoping (14 tests)
|
|
├── test_monkeypatch_fragility.py # guard verification, deep deps (26 tests)
|
|
├── docs/
|
|
│ ├── TEST_DESIGN.md # WHY each suite was designed
|
|
│ ├── TEST_GUIDE.md # WHAT each file covers + run commands
|
|
│ └── BUGS_FOUND.md # 16 bugs found & fixed
|
|
└── tests-pro/
|
|
├── test_api_pool.py # 45 tests — acquire/release/backoff
|
|
├── test_gap_fill.py # 41 tests — JSON parsing, prompt building
|
|
├── test_runner_patches.py # 24 tests — context manager, patches
|
|
├── test_annotation.py # 10 tests — language compatibility
|
|
├── random_numbered.py # main entry point (seed=42)
|
|
└── mutation_max.py # 30-bug injection framework
|
|
```
|
|
|
|
---
|
|
|
|
## Running Tests
|
|
|
|
```bash
|
|
# All 164 tests
|
|
python contrib/batch_scan/tests/tests-pro/random_numbered.py # 120 unit (seed=42)
|
|
python contrib/batch_scan/tests/test_pool_wiring.py # 4 smoke checks
|
|
python contrib/batch_scan/tests/test_monkeypatch_invasiveness.py # 14 thematic
|
|
python contrib/batch_scan/tests/test_monkeypatch_fragility.py # 26 thematic
|
|
|
|
# Review-themed only
|
|
python -m unittest \
|
|
contrib.batch_scan.tests.test_monkeypatch_invasiveness \
|
|
contrib.batch_scan.tests.test_monkeypatch_fragility -v
|
|
python contrib/batch_scan/tests/test_pool_wiring.py
|
|
|
|
# Mutation test
|
|
python contrib/batch_scan/tests/tests-pro/mutation_max.py
|
|
|
|
# End-to-end (fixture suite)
|
|
python -m contrib.batch_scan.batch_scan ./tests/fixtures/ -f terminal --workers 8
|
|
python -m contrib.batch_scan.batch_scan ./tests/fixtures/ -f terminal --workers 8 --no-llm
|
|
```
|
|
|
|
**Three commands catch most regressions:**
|
|
```bash
|
|
python contrib/batch_scan/tests/tests-pro/random_numbered.py
|
|
python contrib/batch_scan/tests/test_pool_wiring.py
|
|
python -m contrib.batch_scan.batch_scan ./tests/fixtures/ -f terminal --workers 8
|
|
```
|
|
|
|
---
|
|
|
|
## Code Conventions
|
|
|
|
Match SkillSpector upstream exactly:
|
|
|
|
- **SPDX header** on every `.py` file
|
|
- `from __future__ import annotations` as first import
|
|
- Imports: stdlib → third-party → `skillspector.*` → relative (`.`)
|
|
- `| None` syntax (not `Optional[X]`)
|
|
- `frozenset` / `Final` for module-level constants (`UPPER_SNAKE_CASE`)
|
|
- Private helpers: `_lower_snake_case`
|
|
- `logger = get_logger(__name__)` in every module
|
|
- Comments explain **why**, not what
|
|
- Docstrings on all public functions and classes
|
|
|
|
---
|
|
|
|
## Commit Style
|
|
|
|
```
|
|
fix: wire ApiKeyPool into llm_analyzer_base graph path
|
|
feat: add multilingual batch scanner with parallel execution
|
|
docs: document dual-patch pool wiring fix
|
|
```
|
|
|
|
- Present-tense, imperative mood
|
|
- `Signed-off-by` trailer required (NVIDIA DCO)
|
|
- `Co-authored-by` trailer for joint work
|
|
|
|
---
|
|
|
|
## Key Design Points
|
|
|
|
Before modifying code, understand these three:
|
|
|
|
1. **Dual-patch pool wiring.** `set_api_pool()` patches both `llm_utils.get_chat_model` AND `llm_analyzer_base.get_chat_model`. The latter is necessary because `llm_analyzer_base` imports via `from ... import`, creating a local reference that single-module patching misses. See `docs/archive/PITFALLS.md`.
|
|
|
|
2. **Instance-attribute injection (not class-attribute).** Patch 1 writes `self.response_schema = None` to instance `__dict__`, not class `__dict__`. Python MRO finds instance attributes first. This is what makes patches thread-safe. Mutating the class attribute causes cross-thread races (this killed V1).
|
|
|
|
3. **Guard before apply.** `_verify_patch_targets()` checks all 7 patch assumptions before `_apply_patches()` runs. If upstream changes a signature or removes a dependency, the guard raises immediately — patches fail closed, never silently.
|
|
|
|
Full architecture: `docs/DESIGN.md`.
|
|
All pitfalls: `docs/archive/PITFALLS.md`.
|
|
|
|
---
|
|
|
|
## Where to Contribute
|
|
|
|
See `docs/archive/FUTURE_WORK.md` for 12 future directions with effort estimates. High-impact items:
|
|
- Checkpoint/resume (prevents data loss on large scans)
|
|
- Language detection expansion (9+ languages)
|
|
- SARIF output format
|
|
- Non-English ground-truth fixtures
|
|
|
|
---
|
|
|
|
**Next:** [docs/README.md](docs/README.md) — user guide · [docs/DESIGN.md](docs/DESIGN.md) — architecture · [docs/REVIEW_RESPONSE.md](docs/REVIEW_RESPONSE.md) — PR #100 review response
|