Die drei echten Coverage-Lücken schließen: provenance_cmd, migrate_cmd, type_resolver #51

Open
opened 2026-09-04 17:18:44 +00:00 by torben · 0 comments
Owner

Ausgangslage

Abgespalten von #10, das die Messung eingerichtet und die Schwelle gesetzt hat. #10 friert den
erreichten Stand ein; dieses Issue ist die Arbeit, die er nicht ersetzt.

Die Coverage-Messung teilt ungedeckte Zeilen in drei Sorten, und nur die dritte ist
Arbeitsvorrat: dünne Typer-Wrapper (Logik liegt daneben und ist dort getestet), Code an der
Netz-/Dateisystem-Naht (interessante Hälfte über eine injizierbare Naht getestet) — und echte
Lücken
, wo ungedeckte Zeilen Logik sind, die niemand ausführt.

Die dritte Sorte, Stand CI-Lauf 163 (2026-09-04, Stack 4.7.1, Gesamt 87,0 %):

Modul Coverage Statements ungedeckt Bewegung seit Lauf 87
chemenu/commands/provenance_cmd.py 44,1 % 127 71 unverändert
chemenu/commands/migrate_cmd.py 64,6 % 198 70 gefallen von 71,1 %
chemenu/type_resolver.py 78,9 % 199 42 78,6 % → 78,9 %

Das ist die einzige der drei Listen, die sich nicht bewegt hat, während alles um sie herum
wuchs.
Zwischen Lauf 87 und Lauf 163 ist der gemessene Code um ein Viertel gewachsen und die
Suite um ein Drittel; provenance_cmd.py steht bei exakt denselben 44,1 %, und migrate_cmd.py
ist gefallen, weil das Modul gewachsen ist und die neuen Zeilen ungetestet ankamen.

Warum das mehr ist als eine Zahl

Zwei der drei Module tun Dinge, bei denen ein Fehler nicht als roter Test auffällt, sondern als
beschädigter Korpus:

  • migrate_cmd.py verändert kb/-Inhalte und schreibt .wikitool-kb.json fort. Der Präzedenzfall
    steht in #30: zwei datenzerstörende Bugs in upstream merge sind an grünem pytest,
    docs verify, instructions verify und grüner CI vorbeigelaufen, weil kein Test den Fall
    ausgeübt hat
    — nicht weil der getestete Fall schlecht geschrieben war. stack-dev Schritt 3
    führt genau diesen Fall als Kaveat zur „mechanisch abgedeckten" Phase. migrate_cmd.py ist
    dieselbe Sorte Code mit einem Drittel ungedeckter Zeilen.
  • provenance_cmd.py erzeugt kb/provenance.md, eine generierte Datei unter Invariante 1. Eine
    falsche Ausgabe hier ist nicht falsch aussehende Ausgabe, sondern eine Herkunftsangabe, der
    eine spätere Sitzung glaubt.
  • type_resolver.py entscheidet, welcher Typ und damit welches Verzeichnis für eine Seite gilt —
    die Frage, die AGENTS.md ausdrücklich dem Tool und nicht der Sitzung überlässt („Never pick a
    directory by hand").

Was zu tun ist

Nicht „Coverage auf X heben". Pro Modul die ungedeckten Zeilen durchgehen und entscheiden,
welche der drei Kategorien sie sind — die Aufteilung aus #10 gilt auch innerhalb eines Moduls,
und ein Teil dieser Zeilen wird sich als Wrapper oder als Naht herausstellen. Für den Rest
Tests, die den Fall ausüben, nicht die Zeile berühren.

  • provenance_cmd.py: ungedeckte Blöcke sind zusammenhängend (u. a. 127–169, 176–184), also
    vermutlich ganze Codepfade, nicht Fehlerzweige. Erst lesen, dann kategorisieren.
  • migrate_cmd.py: zuerst die Zeilen, die seit Lauf 87 dazugekommen sind — dort ist die
    Regression entstanden.
  • type_resolver.py: 42 Zeilen über viele kleine Blöcke verteilt; hier ist der Anteil echter
    Fehlerzweige vermutlich am höchsten.
  • Nach jedem Modul prüfen, ob die Untergrenze in tools/.coveragerc nachgezogen werden
    sollte. Nicht automatisch — die Schwelle ist ein Boden gegen Rückfall, kein Ziel, und
    sie mitzuziehen macht sie wieder zu der Zahl, die beim nächsten Wrapper gesenkt wird.

Vor dem ersten Test: instructions/dev/testing-conventions.md
— die Suite läuft gegen eine bewusst leere Maschine, und was die autouse-Fixture
hermetic_environment schon neutralisiert, muss ein Test nicht selbst herstellen.

Abgrenzung

Nicht in diesem Issue: die dünnen Wrapper (eval_cmd.py 36 %, types_cmd.py 40 %, search.py
49 %, cli.py 54 %, links_cmd.py 61 %). Niedrige Zahlen sind dort das Zeichen für einen guten
Schnitt. search.py ist der Musterfall: ungedeckt ist ausschließlich der Kommandokörper
(Zeilen 117–176), während die Backends unter chemenu/search/, die die Arbeit tun, zwischen
91 % und 98 % liegen.

Ebenfalls nicht: die echte Netzzeile in version.pys fetch_latest(). Die bleibt absichtlich
ungedeckt, dafür nimmt sie einen injizierbaren fetcher.

Version

Reine Testarbeit unter tools/chemenu/tests/ berührt das Version-Gate (^tools/) und braucht
damit einen PATCH-Bump, auch wenn sich am Verhalten nichts ändert. Wenn beim Testschreiben
ein echter Bug auffällt — der wahrscheinliche Ausgang bei migrate_cmd.py —, ist das der
eigentliche Ertrag dieses Issues und gehört in denselben Bump.

## Ausgangslage Abgespalten von #10, das die Messung eingerichtet und die Schwelle gesetzt hat. **#10 friert den erreichten Stand ein; dieses Issue ist die Arbeit, die er nicht ersetzt.** Die Coverage-Messung teilt ungedeckte Zeilen in drei Sorten, und nur die dritte ist Arbeitsvorrat: dünne Typer-Wrapper (Logik liegt daneben und ist dort getestet), Code an der Netz-/Dateisystem-Naht (interessante Hälfte über eine injizierbare Naht getestet) — und **echte Lücken**, wo ungedeckte Zeilen Logik sind, die niemand ausführt. Die dritte Sorte, Stand CI-Lauf 163 (2026-09-04, Stack 4.7.1, Gesamt 87,0 %): | Modul | Coverage | Statements | ungedeckt | Bewegung seit Lauf 87 | |---|---|---|---|---| | `chemenu/commands/provenance_cmd.py` | **44,1 %** | 127 | 71 | unverändert | | `chemenu/commands/migrate_cmd.py` | **64,6 %** | 198 | 70 | **gefallen** von 71,1 % | | `chemenu/type_resolver.py` | **78,9 %** | 199 | 42 | 78,6 % → 78,9 % | **Das ist die einzige der drei Listen, die sich nicht bewegt hat, während alles um sie herum wuchs.** Zwischen Lauf 87 und Lauf 163 ist der gemessene Code um ein Viertel gewachsen und die Suite um ein Drittel; `provenance_cmd.py` steht bei exakt denselben 44,1 %, und `migrate_cmd.py` ist gefallen, weil das Modul gewachsen ist und die neuen Zeilen ungetestet ankamen. ## Warum das mehr ist als eine Zahl Zwei der drei Module tun Dinge, bei denen ein Fehler nicht als roter Test auffällt, sondern als beschädigter Korpus: - `migrate_cmd.py` verändert `kb/`-Inhalte und schreibt `.wikitool-kb.json` fort. Der Präzedenzfall steht in #30: zwei datenzerstörende Bugs in `upstream merge` sind an grünem `pytest`, `docs verify`, `instructions verify` und grüner CI vorbeigelaufen, **weil kein Test den Fall ausgeübt hat** — nicht weil der getestete Fall schlecht geschrieben war. `stack-dev` Schritt 3 führt genau diesen Fall als Kaveat zur „mechanisch abgedeckten" Phase. `migrate_cmd.py` ist dieselbe Sorte Code mit einem Drittel ungedeckter Zeilen. - `provenance_cmd.py` erzeugt `kb/provenance.md`, eine generierte Datei unter Invariante 1. Eine falsche Ausgabe hier ist nicht falsch aussehende Ausgabe, sondern eine Herkunftsangabe, der eine spätere Sitzung glaubt. - `type_resolver.py` entscheidet, welcher Typ und damit welches Verzeichnis für eine Seite gilt — die Frage, die AGENTS.md ausdrücklich dem Tool und nicht der Sitzung überlässt („Never pick a directory by hand"). ## Was zu tun ist Nicht „Coverage auf X heben". Pro Modul die ungedeckten Zeilen durchgehen und **entscheiden**, welche der drei Kategorien sie sind — die Aufteilung aus #10 gilt auch innerhalb eines Moduls, und ein Teil dieser Zeilen wird sich als Wrapper oder als Naht herausstellen. Für den Rest Tests, die den Fall ausüben, nicht die Zeile berühren. - [ ] `provenance_cmd.py`: ungedeckte Blöcke sind zusammenhängend (u. a. 127–169, 176–184), also vermutlich ganze Codepfade, nicht Fehlerzweige. Erst lesen, dann kategorisieren. - [ ] `migrate_cmd.py`: zuerst die Zeilen, die seit Lauf 87 dazugekommen sind — dort ist die Regression entstanden. - [ ] `type_resolver.py`: 42 Zeilen über viele kleine Blöcke verteilt; hier ist der Anteil echter Fehlerzweige vermutlich am höchsten. - [ ] Nach jedem Modul prüfen, ob die Untergrenze in `tools/.coveragerc` nachgezogen werden sollte. **Nicht automatisch** — die Schwelle ist ein Boden gegen Rückfall, kein Ziel, und sie mitzuziehen macht sie wieder zu der Zahl, die beim nächsten Wrapper gesenkt wird. Vor dem ersten Test: [instructions/dev/testing-conventions.md](../src/branch/main/instructions/dev/testing-conventions.md) — die Suite läuft gegen eine bewusst leere Maschine, und was die autouse-Fixture `hermetic_environment` schon neutralisiert, muss ein Test nicht selbst herstellen. ## Abgrenzung Nicht in diesem Issue: die dünnen Wrapper (`eval_cmd.py` 36 %, `types_cmd.py` 40 %, `search.py` 49 %, `cli.py` 54 %, `links_cmd.py` 61 %). Niedrige Zahlen sind dort das Zeichen für einen guten Schnitt. `search.py` ist der Musterfall: ungedeckt ist ausschließlich der Kommandokörper (Zeilen 117–176), während die Backends unter `chemenu/search/`, die die Arbeit tun, zwischen 91 % und 98 % liegen. Ebenfalls nicht: die echte Netzzeile in `version.py`s `fetch_latest()`. Die bleibt absichtlich ungedeckt, dafür nimmt sie einen injizierbaren `fetcher`. ## Version Reine Testarbeit unter `tools/chemenu/tests/` berührt das Version-Gate (`^tools/`) und braucht damit einen **PATCH**-Bump, auch wenn sich am Verhalten nichts ändert. Wenn beim Testschreiben ein echter Bug auffällt — der wahrscheinliche Ausgang bei `migrate_cmd.py` —, ist das der eigentliche Ertrag dieses Issues und gehört in denselben Bump.
torben added the prio/plannedsize/Marea/processkind/build labels 2026-09-04 17:18:44 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: torben/chemenu#51