diff --git a/TASK_REVIEW.md b/TASK_REVIEW.md new file mode 100644 index 0000000..a615586 --- /dev/null +++ b/TASK_REVIEW.md @@ -0,0 +1,91 @@ +# 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 + +1. **Jamulix-Crawl:** Nur 1 Seite gecrawlt (M1 + M2). Bei `check` → alle anderen URLs als "fehlend" gemeldet. +2. **Parallele Scans:** Kein File-Lock → Cron-Job + manueller Aufruf können Snapshots korrupt machen. +3. **Dependency-Updates:** Keine Obergrenzen in `requirements.txt` → potentielles Breaking Change bei `requests` v3.x oder `beautifulsoup4` v5.x. +4. **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 + +1. **Fix M1:** `jamulix.de/config.yaml` → `"/"` aus `exclude_paths` entfernen. +2. **Fix M2:** `scanner/crawler.py` Zeile 10-16 → Seed-URLs durch `should_crawl()` filtern. +3. **Add Lock:** `scanner/__main__.py` → File-Lock vor `cmd_scan` (`fcntl.flock` oder `portalocker`). +4. **Add Tests:** `tests/test_main.py` → Integrationstests für `cmd_scan`, `cmd_check`, `_worst_level`. +5. **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__.py` nur 10% + +**Empfehlung:** M1 + M2 fixen → dann **PASS**.