4.3 KiB
Senior QA Review — Integrity Scanner
Urteil: PASS WITH CONCERNS
✅ Bestanden (8/8)
| Check | Ergebnis | Befehl/Evidenz |
|---|---|---|
| Module-Import | 11/11 ✅ | python3 -c "import scanner.*" — alle OK |
| Tests | 266/266 grün (2.95s) ✅ | pytest tests/ -v |
| CLI | 14 Subcommands, --help funktioniert ✅ |
python3 -m scanner --help |
| Pipeline-Check | Crawler → Extractor → Baseline → Differ → Scoring ✅ | python3 -c "from scanner.differ import compare_snapshots" |
Echter Check (bredelar.info) |
🟢 Score 0, 46 Seiten geprüft ✅ | python3 -m scanner --config bredelar.info/config.yaml check |
| Report-Generierung | JSON + Markdown ✅ | bredelar.info/reports/20260614_171847/report.md |
| KI-Analyse | OpenRouter primary + localhost Fallback, hash-gegated ✅ | _openrouter_chat() graceful degradation |
| Dependencies | requests 2.32, bs4 4.13, lxml 5.4, PyYAML 6.0, pytest 8.3 ✅ | requirements.txt erfüllt |
🔴 Blocker (0)
Keine.
🟡 Major (2) — unverändert vom letzten Review
M1: exclude_paths=["/"] bei jamulix.de blockt ALLE Pfade
Datei: jamulix.de/config.yaml (Zeile 28-30)
Befehl: python3 -c "from scanner.crawler import should_crawl; print(should_crawl('https://jamulix.de/podcasts/episode-1', 'jamulix.de', [], ('/hackernews/', '/'), ('/podcasts/',)))" → False
Reproduktion: exclude_paths=['/'] + p.path.startswith('/') → jeder Pfad wird blockiert. Baseline hat nur 1 Seite.
Fix: "/" aus exclude_paths entfernen ODER Logik ändern: exakte Pfad-Treffer prüfen (p.path == "/"), nicht startswith.
M2: Seed-URL umgeht should_crawl-Filter
Datei: scanner/crawler.py (Zeile 10-16)
Befehl: grep -n "should_crawl" scanner/crawler.py → nur Zeile 264, 281 (Sitemap + Link-Extraktion), nicht Zeile 11-16 (Seed-Queue)
Reproduktion: Bei jamulix.de wird /podcasts/ direkt gecrawlt, obwohl should_crawl() es als False bewerten würde.
Fix: Seed-URLs durch should_crawl() filtern.
🔵 Minor (4) — unverändert vom letzten Review
| Issue | Datei | Risiko |
|---|---|---|
Mi1: Test-Coverage für __main__.py nur 10% |
tests/ |
Integrations-Logik kaum getestet |
Mi2: Keine Versions-Pins in requirements.txt |
requirements.txt |
Breaking Changes bei Updates |
| Mi3: Kein File-Lock für parallele Scans | scanner/__main__.py |
Cron-Job + manueller Aufruf kollidieren |
Mi4: refresh_catalog() ohne Lock |
scanner/ai_analyzer.py |
Race Condition bei parallelen Scans |
📊 Fehlende Tests (Coverage < 40%)
| Modul | Coverage | Fehlend |
|---|---|---|
__main__.py |
10% | cmd_scan, cmd_check, _worst_level, Report-Pipeline |
crawler.py |
28% | Live-Crawl, Sitemap-Parsing, Seed-URL-Logik |
config.py |
28% | resolve_paths(), Config-Merge |
report.py |
37% | Markdown-Rendering, JSON-Export |
⚠️ Produktionsrisiken
- Jamulix-Crawl: Nur 1 Seite gecrawlt (M1 + M2). Bei
check→ alle anderen URLs als "fehlend" gemeldet. - Parallele Scans: Kein File-Lock → Cron-Job + manueller Aufruf können Snapshots korrupt machen.
- Dependency-Updates: Keine Obergrenzen in
requirements.txt→ potentielles Breaking Change beirequestsv3.x oderbeautifulsoup4v5.x. - OpenRouter-Rate-Limits: Im Produktivbetrieb ohne KI-Cache → viele API-Calls. Circuit-Breaker hilft, aber bei 46 Seiten × 2000 Zeichen = ~92k Zeichen pro Scan.
🔧 Konkrete Fix-Aufträge an den Coder
- Fix M1:
jamulix.de/config.yaml→"/"ausexclude_pathsentfernen. - Fix M2:
scanner/crawler.pyZeile 10-16 → Seed-URLs durchshould_crawl()filtern. - Add Lock:
scanner/__main__.py→ File-Lock vorcmd_scan(fcntl.flockoderportalocker). - Add Tests:
tests/test_main.py→ Integrationstests fürcmd_scan,cmd_check,_worst_level. - Pin Versions:
requirements.txt→ Obergrenzen hinzufügen (z.B.requests>=2.31,<3.0).
Fazit
Das Projekt funktioniert und ist produktionsreif für bredelar.info (46 Seiten, alle Checks grün). Die Hauptprobleme sind:
- Jamulix-Crawl nur 1 Seite (Konfigurations-Bug + Code-Bug)
- Test-Coverage für
__main__.pynur 10%
Empfehlung: M1 + M2 fixen → dann PASS.