diff --git a/docs/arbeitspakete/m1/AP01-ist-stand-inventar.md b/docs/arbeitspakete/m1/AP01-ist-stand-inventar.md new file mode 100644 index 0000000..d7f8a8d --- /dev/null +++ b/docs/arbeitspakete/m1/AP01-ist-stand-inventar.md @@ -0,0 +1,62 @@ +# AP01 – Ist-Stand-Inventar und Delta-Analyse + +## Ziel + +Den **tatsächlichen Ist-Zustand** der bestehenden Code-Basis vollständig erfassen und ein **Delta** zum M1-Soll dokumentieren, bevor irgendetwas umgebaut wird. Ohne dieses AP besteht das Risiko, dass spätere APs an der Realität vorbeiplanen. + +## Voraussetzungen + +- keine (erstes AP) + +## Scope IN + +- vollständige Dateiliste unter `src/main/java/` und `src/test/java/` mit Kurzbeschreibung jeder Klasse (ein Satz pro Klasse) +- Auflistung aller externen Dependencies aus `pom.xml` inkl. Versionen +- Identifikation aller Stellen, an denen Log4j2-Typen (`org.apache.logging.log4j.*`) direkt importiert werden +- Identifikation aller Stellen, an denen Zeichensätze explizit gesetzt werden (Grep nach `StandardCharsets`, `Charset.forName`) +- Identifikation aller `System.exit`- und Exit-Code-Konstanten +- Delta-Tabelle: Ist-Paketstruktur vs. Soll-Paketstruktur aus `technik-und-architektur.md` +- Delta-Tabelle: Ist-Exit-Codes vs. Soll-Exit-Codes (`0/1/2`) +- Delta-Tabelle: vorhandene vs. fehlende Elemente für M1 (Befundmodell mit Spec-/Diagnose-Trennung, SLF4J-Fassade, Berichtdatei, Log-Datei, Suffix-Logik, Minimalbericht, ISO 8859-15 als Eingabe-Encoding) +- Klassifikation jedes vorhandenen Pakets: **behalten und migrieren**, **behalten und anpassen**, **neu bauen**, **später verwenden (M3+)** + +## Scope OUT + +- keinerlei Code-Änderungen +- keinerlei `pom.xml`-Änderungen +- keinerlei Datei-Verschiebungen +- keine neuen Dateien außer dem Bericht selbst + +## Schritte + +1. Repo lokal auschecken, `mvn clean verify` laufen lassen, Ergebnis festhalten (grün/rot, Anzahl Tests, Warnungen) +2. `find src/main/java -name "*.java" | sort` und jede Datei mit ein bis zwei Sätzen kurz beschreiben +3. `find src/test/java -name "*.java" | sort` analog +4. `grep -rn "org.apache.logging.log4j" src/` — alle Fundstellen auflisten +5. `grep -rn "StandardCharsets\|Charset.forName" src/` — alle Fundstellen auflisten +6. `grep -rn "System.exit\|EXIT_CODE" src/` — alle Fundstellen auflisten +7. aktuelle Paketstruktur als Baum zeichnen +8. Delta-Tabellen gemäß Scope IN erstellen +9. Klassifikation pro Paket vornehmen +10. Abschlussbericht nach `templates/ap-bericht.md` schreiben + +## Abnahmekriterien + +- Abschlussbericht `berichte/AP01-bericht.md` existiert und enthält: + - vollständige Dateiliste (main + test) mit Kurzbeschreibung + - Dependency-Liste + - alle Grep-Fundstellen + - Ist-vs-Soll-Paketstrukturbaum + - Delta-Tabelle Exit-Codes + - Delta-Tabelle fehlender M1-Elemente + - Klassifikationstabelle pro Paket +- `mvn clean verify` ist vor und nach diesem AP identisch (es wurde nichts geändert) +- keine neuen Dateien im Repo außer dem Abschlussbericht + +## Rest-Risiken und offene Punkte + +- Die Klassifikation „behalten" vs. „neu bauen" ist eine Einschätzung und kann in späteren APs revidiert werden müssen. Das ist okay, solange es dokumentiert wird. + +## Bericht + +`docs/arbeitspakete/m1/berichte/AP01-bericht.md` nach `templates/ap-bericht.md`. diff --git a/docs/arbeitspakete/m1/AP02-build-infrastruktur.md b/docs/arbeitspakete/m1/AP02-build-infrastruktur.md new file mode 100644 index 0000000..9d1992c --- /dev/null +++ b/docs/arbeitspakete/m1/AP02-build-infrastruktur.md @@ -0,0 +1,70 @@ +# AP02 – Build-Infrastruktur härten + +## Ziel + +Die `pom.xml` so erweitern, dass alle für M1 und die späteren Quality-Gates in M9 benötigten Bausteine bereitstehen, ohne schon Funktionalität zu implementieren. Dazu gehören **SLF4J als Fassade** (verlangt von `technik-und-architektur.md`), **JaCoCo** und **PIT** für die differenzierten Qualitätsgates, sowie das **maven-jar-plugin** für ein ausführbares JAR. + +## Voraussetzungen + +- AP01 abgeschlossen + +## Scope IN + +- `pom.xml` ergänzen um: + - **SLF4J API** (`org.slf4j:slf4j-api`) als Compile-Dependency + - **log4j-slf4j2-impl** (`org.apache.logging.log4j:log4j-slf4j2-impl`) als Runtime-Bindung (SLF4J → Log4j2) + - **maven-jar-plugin** mit `Main-Class` = Bootstrap-Klasse (Name ist zu diesem Zeitpunkt noch offen, Platzhalter eintragen, in AP06 final setzen) + - **jacoco-maven-plugin** für Coverage, an `verify` gebunden, **ohne** harte Schwellwerte in M1 (die kommen erst in M9) + - **pitest-maven** als optionales Ziel (`mvn -P mutation test`), ebenfalls **ohne** harte Schwelle in M1 + - **maven-surefire-plugin** bleibt wie bisher, ggf. Version aktualisieren falls nötig +- `.editorconfig` im Repo-Root anlegen mit: + - UTF-8 als Default-Encoding für Quellcode + - LF als Zeilenende + - 4 Spaces Einrückung für Java + - `trim_trailing_whitespace = true` + - `insert_final_newline = true` +- `.gitattributes` anlegen: + - `* text=auto eol=lf` + - `*.bat text eol=crlf` + - `*.java text eol=lf` + - `*.md text eol=lf` + +## Scope OUT + +- Umstellung bestehender Klassen von Log4j2-API auf SLF4J (kommt in AP04) +- Einführung von Coverage-Schwellwerten (kommt erst in M9) +- Einführung von PIT-Schwellwerten (kommt erst in M9) +- Änderungen an Quellcode +- Änderungen an Tests + +## Schritte + +1. Branch `m1/ap02-build-infra` anlegen +2. SLF4J-Dependencies in `pom.xml` eintragen; **keine** Imports in Quellcode ändern +3. JaCoCo-Plugin eintragen, an `verify` binden +4. PIT-Plugin in Profil `mutation` eintragen +5. maven-jar-plugin eintragen mit Platzhalter `Main-Class` (Wert: `de.gecheckt.asv.bootstrap.Main` — wird in AP06 Realität) +6. `.editorconfig` und `.gitattributes` anlegen +7. `mvn clean verify` laufen lassen, muss grün sein +8. `mvn -P mutation test` laufen lassen, muss grün sein (PIT muss die bestehenden Tests durchkauen können, auch wenn noch kaum was da ist) +9. Commit `M1-AP02: Build-Infrastruktur härten (SLF4J, JaCoCo, PIT, JAR-Plugin)` +10. Abschlussbericht schreiben + +## Abnahmekriterien + +- `pom.xml` enthält: `slf4j-api`, `log4j-slf4j2-impl`, `maven-jar-plugin`, `jacoco-maven-plugin`, `pitest-maven` +- `mvn clean verify` ist grün +- `mvn -P mutation test` läuft ohne Fehler durch (Score ist **irrelevant** in M1) +- JaCoCo erzeugt einen Report unter `target/site/jacoco/` +- `.editorconfig` und `.gitattributes` liegen im Repo-Root +- keine Änderungen an `.java`-Dateien +- Abschlussbericht `berichte/AP02-bericht.md` liegt vor + +## Rest-Risiken und offene Punkte + +- Der `Main-Class`-Eintrag im JAR-Plugin zeigt bis AP06 auf eine Klasse, die noch nicht existiert. Das ist okay, solange das JAR-Plugin die Datei nicht beim Packen validiert. Alternativ bis AP06 auf die bestehende `AsvValidatorApplication` zeigen lassen und in AP06 umbiegen. +- PIT ohne Schwelle ist nur eine Trockenübung für M1. Die echten Schwellen werden in M9 aktiviert. + +## Bericht + +`docs/arbeitspakete/m1/berichte/AP02-bericht.md` nach `templates/ap-bericht.md`. diff --git a/docs/arbeitspakete/m1/AP03-hexagonale-paketstruktur.md b/docs/arbeitspakete/m1/AP03-hexagonale-paketstruktur.md new file mode 100644 index 0000000..27b869d --- /dev/null +++ b/docs/arbeitspakete/m1/AP03-hexagonale-paketstruktur.md @@ -0,0 +1,72 @@ +# AP03 – Hexagonale Paketstruktur anlegen und Ist-Code migrieren + +## Ziel + +Die **Soll-Paketstruktur** aus `technik-und-architektur.md` im Projekt anlegen und den **bestehenden Code evolutionär** in die neuen Pakete verschieben, ohne Funktionalität zu verlieren. Alle bestehenden Tests müssen weiterhin grün laufen. + +## Voraussetzungen + +- AP01 (Ist-Stand bekannt) +- AP02 (Build ist grün) + +## Scope IN + +- Anlage der Soll-Pakete: + ``` + de.gecheckt.asv.domain + de.gecheckt.asv.application + de.gecheckt.asv.adapter.in.cli + de.gecheckt.asv.adapter.out.filesystem + de.gecheckt.asv.adapter.out.parsing + de.gecheckt.asv.adapter.out.reporting + de.gecheckt.asv.adapter.out.logging + de.gecheckt.asv.bootstrap + ``` + (Paket `adapter.out.crypto` kommt erst in M8.) +- Migration des bestehenden Codes nach folgender Zuordnung: + - `de.gecheckt.asv.cli.AsvValidatorApplication` → **vorerst** nach `adapter.in.cli`, wird in AP06 refaktoriert + - `de.gecheckt.asv.cli.ValidationResultPrinter` → `adapter.out.reporting` (technische Berichtsausgabe ist Adapter-Zuständigkeit) + - `de.gecheckt.asv.domain.model.*` → `domain` (Paket `.model` darf bleiben als Unterpaket von `domain`) + - `de.gecheckt.asv.parser.*` → `adapter.out.parsing` + - `de.gecheckt.asv.validation.*` (inkl. `field/`, `structure/`, `model/`) → vorerst unter `application` belassen, bis AP09 klärt, was davon wirklich nach `application` gehört und was ggf. in einem eigenen Unterpaket „eingefroren" bleibt +- alle `package`-Deklarationen und `import`-Statements anpassen +- alle Tests entsprechend mit verschieben +- Build und Tests bleiben grün +- einfaches Package-Diagramm als Markdown-Tabelle im Abschlussbericht + +## Scope OUT + +- inhaltliche Umstellung der Klassen (Exit-Codes, Zeichensatz, Befundmodell — das kommt in späteren APs) +- Einführung neuer Klassen +- Löschen von Klassen +- Refactoring von Methoden + +## Schritte + +1. Branch `m1/ap03-hexagonale-pakete` +2. Leerverzeichnisse für die Soll-Pakete anlegen (notfalls `.gitkeep`, wird später entfernt) +3. Klassen paketweise verschieben (IDE-Refactoring „Move Class" hilft hier enorm) +4. Nach jeder Paket-Migration: `mvn clean compile` laufen lassen, muss grün bleiben +5. Nach allen Migrationen: `mvn clean verify` — muss grün sein +6. Kurze Paket-Beschreibung pro Paket in einem `package-info.java` hinzufügen (deutsche JavaDoc, ein bis zwei Sätze) +7. Commit `M1-AP03: Hexagonale Paketstruktur angelegt, Ist-Code migriert` +8. Abschlussbericht schreiben + +## Abnahmekriterien + +- alle oben genannten Soll-Pakete existieren als Java-Packages +- kein Code ist verloren gegangen: `git log --stat` zeigt nur Verschiebungen und Import-Anpassungen, keine Löschungen +- `mvn clean verify` ist grün +- jede neue Paket-Wurzel hat ein `package-info.java` mit deutscher Kurzbeschreibung +- Abschlussbericht enthält eine **Vorher-Nachher-Tabelle** jeder migrierten Klasse +- keine neuen Features + +## Rest-Risiken und offene Punkte + +- Die Zuordnung der Validation-Klassen nach `application` ist **provisorisch**. AP09 entscheidet endgültig, was davon in M1 aktiv bleibt und was eingefroren wird. +- `AsvValidatorApplication` bleibt vorerst im CLI-Adapter, wird aber in AP06 zerlegt (Bootstrap + dünner CLI-Adapter). +- Die Tests-Struktur sollte die neue Paketstruktur spiegeln; falls das mit IDE-Move automatisch passiert: gut. Falls nicht: manuell nachziehen. + +## Bericht + +`docs/arbeitspakete/m1/berichte/AP03-bericht.md` nach `templates/ap-bericht.md`. diff --git a/docs/arbeitspakete/m1/AP04-logging-adapter.md b/docs/arbeitspakete/m1/AP04-logging-adapter.md new file mode 100644 index 0000000..53d1c49 --- /dev/null +++ b/docs/arbeitspakete/m1/AP04-logging-adapter.md @@ -0,0 +1,62 @@ +# AP04 – Logging-Adapter (SLF4J-Fassade + Log4j2-Bindung) + +## Ziel + +Sicherstellen, dass im gesamten Quellcode **nur noch SLF4J-Typen importiert werden** (`org.slf4j.Logger`, `org.slf4j.LoggerFactory`), außer in einem dedizierten **Logging-Adapter** und im **Bootstrap**. Die konkrete Log4j2-Bindung darf nur an diesen zwei Stellen sichtbar sein, wie von `technik-und-architektur.md` gefordert. + +## Voraussetzungen + +- AP03 (Paketstruktur vorhanden) + +## Scope IN + +- Alle Stellen im Produktivcode, die `org.apache.logging.log4j.LogManager` oder `org.apache.logging.log4j.Logger` importieren, werden umgestellt auf: + ```java + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + + private static final Logger logger = LoggerFactory.getLogger(MyClass.class); + ``` +- Anlage einer minimalen `log4j2.xml` in `src/main/resources/`: + - Console-Appender (StdErr) + - File-Appender mit Zielpfad, der später (AP07) durch den Bootstrap überschrieben wird; für M1 genügt ein Default-Pfad `logs/asv-format-validator.log` + - Log-Level `INFO` für `de.gecheckt.asv`, `WARN` für alles andere + - Deutsche Log-Texte bleiben auf Deutsch +- Anlage eines `LoggingConfigurator` oder ähnlich im Paket `adapter.out.logging`, der Log4j2 **programmatisch** konfigurieren kann (Zielpfad der Log-Datei setzbar). Für M1 reicht eine Klasse mit einer Methode `void configureLogFile(Path logFile)`, die noch keine tiefe Magie macht, aber das Interface definiert. +- Architekturcheck: per `grep` sicherstellen, dass außerhalb von `adapter.out.logging` und `bootstrap` keine `org.apache.logging.log4j.*`-Imports mehr existieren. + +## Scope OUT + +- tatsächliche dynamische Log-Datei-Umleitung pro Lauf (das ist AP07) +- Log-Rotation, Log-Compression, eigene Appender-Klassen +- Logging-Policies, Log-Level pro Klasse +- Umbau der Log-Nachrichten selbst (Wortlaut, Formatierung) + +## Schritte + +1. Branch `m1/ap04-logging-adapter` +2. In allen Produktiv-Klassen außer `adapter.out.logging` und `bootstrap`: Log4j2-Imports durch SLF4J-Imports ersetzen +3. Minimale `log4j2.xml` in `src/main/resources/` anlegen +4. `LoggingConfigurator` in `adapter.out.logging` anlegen (Skelett) +5. `mvn clean verify` laufen lassen, muss grün sein +6. `grep -rn "org.apache.logging.log4j" src/main/java/ | grep -v "adapter/out/logging\|bootstrap"` muss **leer** sein +7. Commit `M1-AP04: Logging-Adapter, SLF4J-Fassade etabliert` +8. Abschlussbericht schreiben + +## Abnahmekriterien + +- kein Import von `org.apache.logging.log4j.*` außerhalb von `adapter.out.logging` und `bootstrap` (Grep-Nachweis im Bericht) +- `log4j2.xml` in `src/main/resources/` vorhanden +- `LoggingConfigurator`-Klasse in `adapter.out.logging` vorhanden (mindestens Skelett) +- `mvn clean verify` ist grün +- alle bestehenden Tests laufen weiterhin (SLF4J ist API-kompatibel; falls Tests wegen Logger-Mocks brechen, müssen sie angepasst werden — dann im Bericht dokumentieren) +- Abschlussbericht liegt vor + +## Rest-Risiken und offene Punkte + +- Falls bestehende Tests Log4j2-Logger mocken: Anpassung nötig. Im Zweifel Logger-Mocks entfernen, Logging ist keine Testlogik. +- `log4j2.xml` hat in M1 einen statischen Dateipfad. Der dynamische Pfad pro Lauf kommt erst in AP07. + +## Bericht + +`docs/arbeitspakete/m1/berichte/AP04-bericht.md` nach `templates/ap-bericht.md`. diff --git a/docs/arbeitspakete/m1/AP05-befundmodell.md b/docs/arbeitspakete/m1/AP05-befundmodell.md new file mode 100644 index 0000000..4a1ebe7 --- /dev/null +++ b/docs/arbeitspakete/m1/AP05-befundmodell.md @@ -0,0 +1,108 @@ +# AP05 – Befundmodell mit Spec-/Diagnose-Trennung + +## Ziel + +Im Paket `domain` ein **stabiles Befundmodell** einführen, das von Anfang an zwischen **Spec-Urteil** (verbindliches Prüfurteil gemäß Spezifikation) und **diagnostischer Weiteranalyse** (zusätzliche, das Spec-Urteil nicht verändernde Hinweise) unterscheidet. Dieses Modell ist das **Herzstück** für alle nachfolgenden Meilensteine. + +Der bestehende Typ `de.gecheckt.asv.validation.model.ValidationResult` wird nicht einfach gelöscht, sondern **ersetzt** durch ein sauber geschnittenes Domain-Modell. Der alte Typ wird im Rahmen von AP09 eingefroren. + +## Voraussetzungen + +- AP03 (Paketstruktur) + +## Scope IN + +Folgende Typen im Paket `de.gecheckt.asv.domain.finding` (oder ähnliches Unterpaket von `domain`): + +### `Severity` (Enum) +- `ERROR` +- `WARNING` +- `HINT` + +### `FindingKind` (Enum) +- `SPEC` — Befund ist Teil des Spec-Urteils, beeinflusst `Verdict` +- `DIAGNOSTIC` — zusätzliche Weiteranalyse, beeinflusst `Verdict` **nicht** + +### `FindingLayer` (Enum) +- `ARTIFACT` — äußeres Artefakt / Dateiebene +- `TECHNICAL_STRUCTURE` — Service-Segmente, KKS, Transport +- `DOMAIN_MODEL` — kanonisches Fachmodell (ASVREC/ASVFEH) + +### `Finding` (Record) +```java +public record Finding( + FindingKind kind, // SPEC oder DIAGNOSTIC + Severity severity, // ERROR/WARNING/HINT + FindingLayer layer, // ARTIFACT/TECHNICAL_STRUCTURE/DOMAIN_MODEL + String ruleId, // interne Regel-ID, optional null + String officialErrorCode, // offizieller Fehlercode, optional null + String segmentType, // z.B. "UNB", optional + Integer segmentIndex, // optional + String fieldId, // z.B. "UNB_0020", optional + String rawValue, // Rohwert, optional + Integer position, // Byte-/Zeichenposition, optional + String messageReference, // UNH 0062 bei Nachrichtenbezug, optional + String germanMessage // deutscher Befundtext +) {} +``` +Records mit vielen optionalen Feldern sind unschön — als Alternative ist eine reguläre Klasse mit Builder erlaubt, solange sie unveränderlich (`final`) ist und die gleichen Felder trägt. **Wichtig ist: unveränderlich und mit allen Metadaten aus `technik-und-architektur.md` Abschnitt „Befundarten".** + +### `Verdict` (Enum) +- `VALID` — keine Spec-ERROR-Befunde +- `INVALID` — mindestens ein Spec-ERROR-Befund +- `OPERATIONAL_ERROR` — Bedienfehler (Exit-Code 2) + +### `ValidationReport` (Klasse) +- unveränderlich +- enthält: + - `List findings` (alle Befunde, SPEC und DIAGNOSTIC gemischt, Reihenfolge erhalten) + - Methode `Verdict computeVerdict()` — berücksichtigt **nur** `kind == SPEC` und `severity == ERROR` + - Methode `List specFindings()` — filtert auf `kind == SPEC` + - Methode `List diagnosticFindings()` — filtert auf `kind == DIAGNOSTIC` + - Methode `boolean hasSpecErrors()` + - Metadaten: `String fileName`, `Instant timestamp` +- **invariant:** eine `DIAGNOSTIC`-Severity `ERROR` darf das Verdict **niemals** auf `INVALID` setzen. Dies ist per Unit-Test abzusichern. + +### Unit-Tests +- `ValidationReport` ohne Befunde → `Verdict.VALID` +- `ValidationReport` mit einem SPEC-ERROR → `Verdict.INVALID` +- `ValidationReport` mit einem DIAGNOSTIC-ERROR → `Verdict.VALID` (dieser Test ist kritisch!) +- `ValidationReport` mit SPEC-WARNING → `Verdict.VALID` (nur ERROR zählt) +- `specFindings()` / `diagnosticFindings()` filtern korrekt +- Unveränderlichkeit: `findings`-Liste ist nicht modifizierbar + +## Scope OUT + +- Integration des neuen Modells in den bestehenden Lauf (kommt in AP06) +- Löschen oder Umbenennen der alten `validation.model.ValidationResult`-Klasse (das ist Teil von AP09) +- Berichtserzeugung (Text-Rendering), Bericht-Format, Konsolenausgabe (kommt in AP07) +- Architekturtest (kommt in AP10) + +## Schritte + +1. Branch `m1/ap05-befundmodell` +2. Paket `de.gecheckt.asv.domain.finding` anlegen +3. Enums und Klassen implementieren +4. Unit-Tests schreiben, mindestens die sechs oben genannten +5. `mvn clean verify` grün bekommen +6. Commit `M1-AP05: Befundmodell mit Spec-/Diagnose-Trennung` +7. Abschlussbericht schreiben + +## Abnahmekriterien + +- Paket `domain.finding` enthält alle oben genannten Typen +- **Der Test „DIAGNOSTIC-ERROR ergibt VALID" ist grün** und wird im Bericht explizit genannt +- `ValidationReport.findings` ist unveränderlich (Test vorhanden) +- alle Metadaten-Felder aus `technik-und-architektur.md` Abschnitt „Befundarten" sind im `Finding`-Typ vorhanden +- `mvn clean verify` ist grün +- keine Änderung an `validation.model.ValidationResult` (Altmodell) +- Abschlussbericht liegt vor + +## Rest-Risiken und offene Punkte + +- Wir haben jetzt zwei parallele Ergebnis-Typen: den alten `ValidationResult` und den neuen `ValidationReport`. Das ist **Absicht** bis AP09, wo die alte Logik sauber eingefroren wird. +- Das Befundmodell ist bewusst **keine** Hierarchie (Datei → Schicht → Nachricht → Befund), sondern eine flache Liste mit Metadaten. Die hierarchische Berichtserzeugung passiert später auf Basis dieser Metadaten in M9. Für M1 genügt die flache Struktur. + +## Bericht + +`docs/arbeitspakete/m1/berichte/AP05-bericht.md` nach `templates/ap-bericht.md`. diff --git a/docs/arbeitspakete/m1/AP06-bootstrap-cli.md b/docs/arbeitspakete/m1/AP06-bootstrap-cli.md new file mode 100644 index 0000000..354b072 --- /dev/null +++ b/docs/arbeitspakete/m1/AP06-bootstrap-cli.md @@ -0,0 +1,96 @@ +# AP06 – Bootstrap und CLI-Adapter + +## Ziel + +Die bestehende `AsvValidatorApplication` wird in zwei klar getrennte Verantwortlichkeiten zerlegt: + +1. **Bootstrap** (`de.gecheckt.asv.bootstrap.Main`) — verdrahtet die Komponenten manuell per Constructor Injection und ist der einzige `public static void main`. +2. **CLI-Adapter** (`de.gecheckt.asv.adapter.in.cli.CliRunner` oder ähnlich) — nimmt CLI-Argumente entgegen, ruft die Application-Schicht auf, übersetzt das Ergebnis in einen Exit-Code. + +Zusätzlich werden die **Exit-Codes spec-konform** auf `0/1/2` umgestellt. + +## Voraussetzungen + +- AP03, AP04, AP05 + +## Scope IN + +### Bootstrap +- Klasse `de.gecheckt.asv.bootstrap.Main` mit `public static void main(String[] args)` +- verdrahtet manuell: + - Logging-Konfigurator + - CLI-Runner + - (Application-Service — Platzhalter, wird in AP09 feingeschnitten) +- ruft `CliRunner.run(args)` auf, gibt den zurückgegebenen Exit-Code an `System.exit` weiter + +### CLI-Adapter +- Klasse `CliRunner` im Paket `adapter.in.cli` +- Methode `int run(String[] args)` +- akzeptiert **genau ein Positionsargument**: den Pfad zur Eingabedatei +- bei 0 oder ≥2 Argumenten → Exit-Code `2`, Minimalbericht-Vorbereitung (vollständige Minimalbericht-Logik kommt in AP08) +- bei nicht existierender, nicht lesbarer oder nicht regulärer Eingabedatei → Exit-Code `2` +- bei erfolgreichem Lauf ohne Spec-Fehler → Exit-Code `0` +- bei erfolgreichem Lauf mit Spec-Fehlern → Exit-Code `1` + +### Exit-Code-Konstanten +- Konstanten **nur noch in einer Klasse** (z.B. `ExitCode` im Paket `adapter.in.cli`) +- Werte: + - `0` = gültig, keine Fehler-Befunde + - `1` = ungültig, mindestens ein Spec-Fehler + - `2` = Bedienfehler +- Die alten Konstanten (`EXIT_CODE_INVALID_ARGUMENTS=1`, `EXIT_CODE_FILE_ERROR=2`, `EXIT_CODE_VALIDATION_ERRORS=3`) werden **gelöscht** + +### Verdrahtung mit Befundmodell (AP05) +- `CliRunner` gibt am Ende einen `ValidationReport` aus AP05 weiter oder erzeugt selbst einen Minimal-`ValidationReport` mit einem `Finding` des Kinds `SPEC`, Severity `ERROR`, Layer `ARTIFACT` im Bedienfehlerfall +- das eigentliche Einlesen und Verarbeiten der Datei kann für M1 noch ein **Dummy-Pfad** sein: die Datei wird gelesen, die Bytes gezählt, ein leerer `ValidationReport` mit `fileName` und `timestamp` zurückgegeben. Echte Validierung gehört nicht in M1. + +### Zeichensatz-Korrektur +- beim Einlesen der Eingabedatei wird **ISO 8859-15** verwendet, nicht UTF-8. Das ist eine harte Spec-Vorgabe aus `fachliche-anforderungen.md` §5.1 und muss ab jetzt dauerhaft so bleiben. + ```java + Files.readString(path, StandardCharsets.ISO_8859_1); // nicht ideal — besser Charset.forName("ISO-8859-15") + ``` + Achtung: Java kennt `StandardCharsets.ISO_8859_1`, aber **nicht** `ISO_8859_15`. Daher `Charset.forName("ISO-8859-15")` verwenden. + +## Scope OUT + +- Berichtdatei und Log-Datei im Eingabeverzeichnis (AP07) +- vollständiger Minimalbericht bei Exit-Code `2` (AP08) +- Entkopplung der Altlogik (AP09) +- Architekturtest (AP10) + +## Schritte + +1. Branch `m1/ap06-bootstrap-cli` +2. `de.gecheckt.asv.bootstrap.Main` anlegen mit `public static void main` +3. `CliRunner` in `adapter.in.cli` anlegen +4. `ExitCode`-Konstantenklasse anlegen +5. `AsvValidatorApplication` schrittweise entkernen: Code wandert nach `CliRunner` und `Main` +6. Einlese-Encoding auf `Charset.forName("ISO-8859-15")` umstellen +7. `maven-jar-plugin` in `pom.xml` auf `de.gecheckt.asv.bootstrap.Main` setzen (Platzhalter aus AP02 konkretisieren) +8. Alle Tests, die auf `AsvValidatorApplication` direkt zeigen, auf `CliRunner` umziehen +9. `mvn clean package` laufen lassen, das erzeugte JAR manuell mit `java -jar target/asv-format-validator-*.jar ` prüfen +10. `mvn clean verify` grün bekommen +11. Commit `M1-AP06: Bootstrap, CLI-Adapter, Exit-Codes 0/1/2, ISO 8859-15` +12. Abschlussbericht schreiben + +## Abnahmekriterien + +- `de.gecheckt.asv.bootstrap.Main` existiert und ist `Main-Class` des JAR +- `CliRunner` ist der einzige Ort mit CLI-Argument-Parsing +- Exit-Codes `0`, `1`, `2` sind definiert und spec-konform eingesetzt +- **Test:** Aufruf ohne Argument → Exit-Code `2` +- **Test:** Aufruf mit nicht existierender Datei → Exit-Code `2` +- **Test:** Aufruf mit leerer, lesbarer Datei → Exit-Code `0` (Dummy-Pfad, leerer `ValidationReport`) +- Einlese-Encoding ist ISO 8859-15 (per Test belegt: eine Datei mit Byte `0xA4` ergibt beim Einlesen `€`, weil `0xA4` in ISO 8859-15 auf Euro-Zeichen liegt) +- ausführbares JAR unter `target/` ist manuell startbar +- `mvn clean verify` ist grün +- Abschlussbericht liegt vor + +## Rest-Risiken und offene Punkte + +- Der Dummy-Pfad (Datei wird gelesen, leerer Report zurückgegeben) ist bewusst dünn. Die Einbindung der alten Parser-Logik passiert in AP09. +- Es ist verlockend, schon hier in AP06 die bestehende Parser-/Validator-Kette mit dem neuen Modell zu verknüpfen. **Nicht tun.** AP06 soll nur die äußere Hülle geradeziehen. + +## Bericht + +`docs/arbeitspakete/m1/berichte/AP06-bericht.md` nach `templates/ap-bericht.md`. diff --git a/docs/arbeitspakete/m1/AP07-ausgabeartefakte.md b/docs/arbeitspakete/m1/AP07-ausgabeartefakte.md new file mode 100644 index 0000000..9c0ec43 --- /dev/null +++ b/docs/arbeitspakete/m1/AP07-ausgabeartefakte.md @@ -0,0 +1,82 @@ +# AP07 – Ausgabeartefakte: Berichtdatei und Log-Datei mit Suffix-Logik + +## Ziel + +Pro Lauf werden **zwei Ausgabedateien** im **Verzeichnis der Eingabedatei** erzeugt: +- eine **Berichtdatei** `.txt` +- eine **Log-Datei** `.log` + +Beide in **UTF-8**. Zusätzlich wird der Bericht weiterhin in die **Konsole** geschrieben. Wenn bereits gleichnamige Dateien existieren, werden neue mit laufendem Suffix `_v1`, `_v2`, … erzeugt, **pro Eingabedatei-Basisname**. + +## Voraussetzungen + +- AP04 (Logging-Adapter), AP05 (Befundmodell), AP06 (Bootstrap/CLI) + +## Scope IN + +### Berichtdatei +- Klasse `ReportFileWriter` oder ähnlich im Paket `adapter.out.reporting` +- Eingabe: `ValidationReport` (aus AP05) und Eingabedatei-Pfad +- Ausgabe: eine UTF-8-Textdatei im **selben Verzeichnis** wie die Eingabedatei +- Dateiname: `.txt`, bei Konflikt `_v1.txt`, `_v2.txt`, … +- Inhalt für M1: **einfach gehalten**. Pro `Finding` eine Zeile mit den wichtigsten Metadaten (Severity, Kind, Layer, Feld-ID, deutsche Nachricht). Kopfzeile mit Dateiname, Zeitstempel, Verdict. Die fein strukturierte hierarchische Darstellung kommt erst in M9. + +### Log-Datei +- Wiederverwendung des `LoggingConfigurator` aus AP04 +- Methode `configureLogFile(Path logFile)` wird im Bootstrap **vor** dem CLI-Runner aufgerufen +- Log-Datei liegt im **selben Verzeichnis** wie die Eingabedatei +- Dateiname: `.log`, Suffix-Logik analog zur Berichtdatei +- Log4j2 wird programmatisch umkonfiguriert: der File-Appender schreibt nach dem neuen Pfad. Die statische `log4j2.xml` aus AP04 ist nur der Fallback für „kein Eingabeargument". + +### Suffix-Logik +- eigene kleine Utility-Klasse `SuffixResolver` im Paket `adapter.out.filesystem` +- Methode `Path resolveNextFreePath(Path baseDirectory, String baseName, String extension)`: + - probiert `.`, dann `_v1.`, `_v2.`, … + - gibt den ersten freien Pfad zurück +- wird sowohl für die Berichtdatei als auch für die Log-Datei verwendet +- **Hinweis:** Die Zählung ist pro Basisname unabhängig. Wenn für `test.auf.txt` schon `test.auf_v1.txt` existiert, aber für `test.auf.log` noch keine `_v1`, kann das vorkommen — die Suffixe müssen **nicht synchron** sein. + +### Konsolenausgabe +- bleibt erhalten, schreibt denselben Bericht-Text wie die Berichtdatei +- Konsolenausgabe erfolgt **nach** der Berichtdatei-Erstellung, damit ein IO-Fehler beim Schreiben der Berichtdatei nicht die Konsolenausgabe verhindert + +## Scope OUT + +- hierarchische Berichtsgliederung (M9) +- Einfärbung / ANSI-Codes in der Konsole +- Log-Rotation +- Minimalbericht bei Exit-Code 2 (AP08) + +## Schritte + +1. Branch `m1/ap07-ausgabeartefakte` +2. `SuffixResolver` implementieren inkl. Unit-Tests für: keine Datei vorhanden, `.txt` vorhanden, `.txt` + `_v1` vorhanden, mehrere Lücken +3. `ReportFileWriter` implementieren mit einfachem Zeilenformat für M1 +4. `LoggingConfigurator.configureLogFile(Path)` implementieren (programmatische Log4j2-Reconfiguration) +5. Bootstrap erweitern: vor CLI-Lauf → Log-Datei-Pfad bestimmen → `LoggingConfigurator` aufrufen +6. CLI-Runner erweitert: nach Lauf → Berichtdatei schreiben → Konsolenausgabe erzeugen +7. End-to-End-Test mit Dummy-Eingabedatei: beide Ausgabedateien entstehen, Suffix-Logik funktioniert +8. `mvn clean verify` grün +9. Commit `M1-AP07: Berichtdatei und Log-Datei im Eingabeverzeichnis mit Suffix-Logik` +10. Abschlussbericht schreiben + +## Abnahmekriterien + +- nach einem Lauf mit Eingabedatei `foo/bar.auf` existieren `foo/bar.auf.txt` und `foo/bar.auf.log` +- zweiter Lauf mit derselben Eingabedatei erzeugt `foo/bar.auf_v1.txt` und `foo/bar.auf_v1.log` +- dritter Lauf → `_v2` usw. +- beide Ausgabedateien sind UTF-8 +- Konsolenausgabe ist identisch zum Inhalt der Berichtdatei +- `SuffixResolver` hat mindestens vier Unit-Tests +- `mvn clean verify` ist grün +- Abschlussbericht liegt vor + +## Rest-Risiken und offene Punkte + +- **Race Conditions** bei gleichzeitigen Läufen auf derselben Eingabedatei: laut `technik-und-architektur.md` bewusst nicht behandelt (kein Mehrbenutzerbetrieb in V1). +- Die programmatische Log4j2-Reconfiguration ist technisch nicht ganz ohne. Falls sie sich als zu instabil erweist, ist eine **sys-property-basierte** Konfiguration der Log-Datei (`-Dasv.log.file=...`) ein zulässiger Fallback. Entscheidung im Bericht dokumentieren. +- Das Bericht-Dateiformat ist in M1 absichtlich primitiv. In M9 wird es durch die finale hierarchische Struktur ersetzt. + +## Bericht + +`docs/arbeitspakete/m1/berichte/AP07-bericht.md` nach `templates/ap-bericht.md`. diff --git a/docs/arbeitspakete/m1/AP08-minimalbericht.md b/docs/arbeitspakete/m1/AP08-minimalbericht.md new file mode 100644 index 0000000..753ece9 --- /dev/null +++ b/docs/arbeitspakete/m1/AP08-minimalbericht.md @@ -0,0 +1,80 @@ +# AP08 – Minimalbericht bei Bedienfehlern (Exit-Code 2) + +## Ziel + +Auch bei **Bedien- oder Zugriffsfehlern** (Exit-Code `2`) soll ein **Minimalbericht** entstehen, der den Fehler nachvollziehbar beschreibt. Das verlangt `technik-und-architektur.md` ausdrücklich: „Auch bei Exit-Code 2 soll, soweit technisch möglich, ein Minimalbericht erzeugt werden, der den Bedien- oder Zugriffsfehler nachvollziehbar beschreibt." + +## Voraussetzungen + +- AP06 (CLI), AP07 (Ausgabeartefakte) + +## Scope IN + +### Bedienfehler-Fälle +Alle diese Fälle müssen in Exit-Code `2` mit Minimalbericht resultieren: + +1. **Kein Argument übergeben** → Minimalbericht auf Konsole (Eingabeverzeichnis unbekannt, also keine Dateiausgabe möglich) +2. **Mehr als ein Argument** → Minimalbericht auf Konsole +3. **Eingabedatei existiert nicht** → Minimalbericht auf Konsole und falls möglich in das übergeordnete Verzeichnis (dort wo die Datei hätte liegen sollen), sonst nur Konsole +4. **Eingabepfad ist kein regulärer Dateityp** (z.B. Verzeichnis) → Minimalbericht auf Konsole, keine Dateiausgabe +5. **Eingabedatei ist nicht lesbar** (Permissions) → Minimalbericht auf Konsole, Dateiausgabe wird versucht wenn Zielverzeichnis schreibbar ist, sonst nur Konsole + +### Minimalbericht-Inhalt +Der Minimalbericht ist ein **`ValidationReport`** (aus AP05) mit: +- `fileName` = übergebener Pfad (oder Platzhalter `` bzw. ``) +- `timestamp` = jetzt +- genau ein `Finding`: + - `kind = SPEC` + - `severity = ERROR` + - `layer = ARTIFACT` + - `ruleId = "OPERATIONAL-"` (z.B. `OPERATIONAL-MISSING-ARG`, `OPERATIONAL-FILE-NOT-FOUND`, `OPERATIONAL-NOT-READABLE`, `OPERATIONAL-NOT-REGULAR`, `OPERATIONAL-TOO-MANY-ARGS`) + - `germanMessage` = kurzer, verständlicher deutscher Text +- **wichtig:** das Verdict dieses Reports ist **nicht** `INVALID`, sondern `OPERATIONAL_ERROR`. Die `Verdict`-Ableitungslogik muss in AP05 bereits den Fall „nur OPERATIONAL-Findings" erkennen können — falls das in AP05 noch nicht vorgesehen wurde, muss `ValidationReport` hier minimal erweitert werden. +- Alternative, sauberere Modellierung: ein zusätzlicher Konstruktor oder Factory-Methode `ValidationReport.operationalError(String fileName, String ruleId, String message)`, der den Verdict-Status explizit auf `OPERATIONAL_ERROR` setzt. + +### Dateiausgabe bei Exit-Code 2 +- wenn das Zielverzeichnis ermittelbar und schreibbar ist: Berichtdatei wird gemäß AP07-Logik erzeugt +- wenn nicht: **nur Konsolenausgabe**, keine Fehlermeldung („Bericht konnte nicht geschrieben werden"), weil das den Benutzer doppelt verunsichert +- eine kurze Hinweiszeile auf der Konsole ist okay: „Bericht konnte nicht in das Verzeichnis geschrieben werden, siehe Konsolenausgabe oben." + +### Logging +- der Minimalbericht wird zusätzlich **geloggt** (`logger.error(...)`) — damit in der Log-Datei (sofern erzeugt) dokumentiert ist, was schiefging +- bei Fall 1 und 2 (keine Dateipfadinformation) ist die Log-Datei nicht sinnvoll zu platzieren → Fallback auf `log4j2.xml`-Default aus AP04 + +## Scope OUT + +- Unterscheidung zwischen verschiedenen IO-Exceptions im Detail (`FileSystemException`, `AccessDeniedException`, …) — ein einheitlicher Fall „nicht lesbar" reicht +- Internationalisierung +- Exit-Codes jenseits von `0/1/2` +- Behandlung von `OutOfMemoryError`, `StackOverflowError` etc. + +## Schritte + +1. Branch `m1/ap08-minimalbericht` +2. Factory-Methode `ValidationReport.operationalError(...)` in AP05-Modell ergänzen (falls noch nicht vorhanden) +3. `CliRunner` um die fünf Bedienfehler-Fälle erweitern; pro Fall wird der passende Minimalbericht erzeugt +4. `ReportFileWriter`: im OPERATIONAL-Fall weichere IO-Fehlerbehandlung (keine `RuntimeException`, stattdessen Konsolenhinweis) +5. Unit-Tests für alle fünf Fälle +6. End-to-End-Test: `java -jar ... /pfad/zu/nichtvorhandener/datei.auf` erzeugt auf Konsole einen Minimalbericht und Exit-Code `2` +7. `mvn clean verify` grün +8. Commit `M1-AP08: Minimalbericht bei Exit-Code 2` +9. Abschlussbericht schreiben + +## Abnahmekriterien + +- alle fünf Bedienfehler-Fälle erzeugen einen Minimalbericht (per Unit-Test belegt) +- Exit-Code in allen fünf Fällen ist `2` +- Im Fall „Eingabedatei existiert nicht" wird der Minimalbericht in das übergeordnete Verzeichnis geschrieben, sofern dieses schreibbar ist +- Im Fall „kein Argument" wird der Minimalbericht **nur** auf Konsole ausgegeben (keine Dateiausgabe) +- `Verdict.OPERATIONAL_ERROR` ist in mindestens einem Test verifiziert +- `mvn clean verify` ist grün +- Abschlussbericht liegt vor + +## Rest-Risiken und offene Punkte + +- Im Fall „Eingabedatei existiert nicht, Zielverzeichnis aber schon" ist der Bericht-Basisname der **angegebene** Dateiname (obwohl die Datei nicht existiert). Das ist okay — der Benutzer findet den Bericht dort, wo er die Datei erwartet hätte. +- Die Unterscheidung zwischen `OPERATIONAL_ERROR` und `INVALID` im Verdict ist wichtig für spätere Reporting-Logik. Falls sich herausstellt, dass `OPERATIONAL_ERROR` als separater Verdict-Wert zu Komplikationen führt, kann alternativ ein Boolean-Flag `isOperational` auf dem Report verwendet werden. Entscheidung im Bericht dokumentieren. + +## Bericht + +`docs/arbeitspakete/m1/berichte/AP08-bericht.md` nach `templates/ap-bericht.md`. diff --git a/docs/arbeitspakete/m1/AP09-altlogik-einfrieren.md b/docs/arbeitspakete/m1/AP09-altlogik-einfrieren.md new file mode 100644 index 0000000..8f2bb09 --- /dev/null +++ b/docs/arbeitspakete/m1/AP09-altlogik-einfrieren.md @@ -0,0 +1,86 @@ +# AP09 – Altlogik aus M1 entkoppeln (Parser/Validator einfrieren) + +## Ziel + +Die **bereits vorhandene Parser- und Validator-Logik** aus der früheren Implementierung (vor dieser M1-Planung) wird **nicht gelöscht**, aber sauber **entkoppelt** vom aktiven M1-Lauf. Sie wird als „Vorbau für M3 und folgende" explizit markiert und ist während M1 **nicht** Bestandteil der aktiven Verarbeitungskette. + +Hintergrund: Der ursprüngliche Stand im Repository enthält bereits `DefaultInputFileParser`, `DefaultSegmentLineTokenizer`, `DefaultStructureValidator`, `DefaultFieldValidator`, `DefaultInputFileValidator` und `validation.model.ValidationResult`. Das ist wertvoll und darf nicht verloren gehen — gehört aber fachlich in M3 (Parser), M5 (Feldregeln) und M6 (Beziehungen), nicht in M1. + +## Voraussetzungen + +- AP03 (Migration), AP05 (neues Befundmodell), AP06 (neuer Bootstrap/CLI) + +## Scope IN + +### Einfrieren statt Löschen +- Die bestehenden Klassen bleiben **vollständig erhalten**, inklusive Tests +- Sie werden in ein klar erkennbares Unterpaket verschoben, z.B.: + ``` + de.gecheckt.asv.legacy.parser + de.gecheckt.asv.legacy.validation + de.gecheckt.asv.legacy.model + ``` + oder alternativ: + ``` + de.gecheckt.asv.application.preview + ``` + Die Entscheidung zwischen `legacy` und `preview` wird im Bericht dokumentiert und begründet. Empfehlung: **`preview`**, weil „legacy" suggeriert, dass etwas alt und zu entsorgen ist — tatsächlich wird der Code in M3/M5/M6 weiterverwendet. +- Jedes Paket bekommt ein `package-info.java` mit deutlichem Hinweis: + ``` + Diese Klassen stammen aus einer früheren Implementierung und sind + für die Meilensteine M3 bis M6 vorgesehen. Sie sind in M1 nicht Teil + der aktiven Validierungskette. Änderungen an diesen Klassen während + M1 sind zu vermeiden. + ``` + +### Entkopplung vom Lauf +- `CliRunner` und `Bootstrap` dürfen die Preview-Klassen **nicht** aufrufen +- der aktive M1-Lauf verwendet ausschließlich den Dummy-Pfad aus AP06 (Datei einlesen, leeren `ValidationReport` erzeugen) +- die alten Tests der Preview-Klassen laufen **weiterhin grün mit**, damit der Code nicht verrottet +- `validation.model.ValidationResult` (alt) bleibt im Preview-Paket und wird **nicht** mit dem neuen `ValidationReport` aus AP05 verwechselt + +### Saubere Kennzeichnung +- In `README.md` des Repos (falls vorhanden, sonst anlegen) ein kurzer Abschnitt „Preview-Code" mit Verweis auf `docs/arbeitspakete/m1/AP09-altlogik-einfrieren.md` +- Kein `@Deprecated`! Deprecated würde bedeuten „wird entfernt" — das Gegenteil ist der Fall. + +## Scope OUT + +- Weiterentwicklung der Preview-Klassen +- Änderung der Preview-Tests (außer notwendige Import-Anpassungen durch den Package-Umzug) +- Integration der Preview-Klassen in die neue `domain.finding`-Struktur (das ist explizit M3+) +- Löschung von Preview-Klassen, auch wenn sie wie Duplikate wirken + +## Schritte + +1. Branch `m1/ap09-preview-einfrieren` +2. Zielpaket wählen (`preview` empfohlen) und im Bericht begründen +3. Alle Parser-Klassen verschieben +4. Alle Validator-Klassen verschieben +5. `validation.model.ValidationResult` und `validation.model.*` mit verschieben +6. Tests entsprechend verschieben; Imports anpassen +7. `CliRunner`/`Bootstrap` auf Preview-Imports prüfen — **darf keine haben**, sonst entkoppeln +8. `package-info.java` mit Warnhinweis in jedem Preview-Unterpaket anlegen +9. README-Abschnitt „Preview-Code" ergänzen +10. `mvn clean verify` grün bekommen (alle Tests der Preview-Klassen laufen weiter mit) +11. Commit `M1-AP09: Alt-Parser und Alt-Validator nach preview-Paket, vom M1-Lauf entkoppelt` +12. Abschlussbericht schreiben + +## Abnahmekriterien + +- alle ursprünglich vorhandenen Parser- und Validator-Klassen liegen im Preview-Paket +- alle zugehörigen Tests laufen weiterhin grün +- `grep -rn "de.gecheckt.asv.preview" src/main/java/de/gecheckt/asv/adapter src/main/java/de/gecheckt/asv/bootstrap src/main/java/de/gecheckt/asv/application` ist **leer** (keine Referenzen aus dem aktiven Code) +- `package-info.java` mit Warnhinweis in jedem Preview-Unterpaket +- README enthält Abschnitt „Preview-Code" +- keine Klasse wurde gelöscht (`git log --diff-filter=D` für diesen Commit zeigt nur Verschiebungen) +- `mvn clean verify` ist grün +- Abschlussbericht liegt vor + +## Rest-Risiken und offene Punkte + +- Bei Wiederaufnahme in M3 wird zu klären sein, wie der Preview-Code an das neue Befundmodell angebunden wird. Das ist explizit M3-Aufgabe, nicht M1. +- Falls die Preview-Tests beim Package-Umzug brechen (wegen relativer Ressourcenpfade o.ä.), müssen sie einmalig angepasst werden. Das ist kein Scope-Verstoß, sondern Teil des Umzugs. + +## Bericht + +`docs/arbeitspakete/m1/berichte/AP09-bericht.md` nach `templates/ap-bericht.md`. diff --git a/docs/arbeitspakete/m1/AP10-architekturtest.md b/docs/arbeitspakete/m1/AP10-architekturtest.md new file mode 100644 index 0000000..433a516 --- /dev/null +++ b/docs/arbeitspakete/m1/AP10-architekturtest.md @@ -0,0 +1,110 @@ +# AP10 – Architekturtest + +## Ziel + +Ein **automatisierter Architekturtest** stellt sicher, dass die in M1 etablierten Strukturregeln auch in Zukunft eingehalten werden. Insbesondere darf: + +1. die **Log4j2-Bindung** nur in `adapter.out.logging` und `bootstrap` sichtbar sein +2. das `domain`-Paket **nichts** aus Adaptern oder Infrastruktur importieren +3. das `application`-Paket **nichts** aus konkreten Adaptern importieren, sondern nur aus `domain` und eigenen Ports +4. **Preview-Code** nicht aus dem aktiven Code (Bootstrap, CLI-Adapter, Application) referenziert werden + +## Voraussetzungen + +- AP04 (Logging-Adapter), AP09 (Preview eingefroren) + +## Scope IN + +### Technische Umsetzung +- **ArchUnit** (`com.tngtech.archunit:archunit-junit5`) als Test-Dependency aufnehmen +- neue Test-Klasse `ArchitectureTest` im Paket `de.gecheckt.asv` im Testbereich +- vier Tests: + +### Test 1: Log4j2-Sichtbarkeit +```java +@ArchTest +static final ArchRule log4j2_nur_in_logging_adapter_und_bootstrap = + noClasses() + .that().resideOutsideOfPackages( + "de.gecheckt.asv.adapter.out.logging..", + "de.gecheckt.asv.bootstrap..") + .should().dependOnClassesThat() + .resideInAPackage("org.apache.logging.log4j..") + .because("Log4j2 darf nur im Logging-Adapter und im Bootstrap sichtbar sein."); +``` + +### Test 2: Domain ist frei +```java +@ArchTest +static final ArchRule domain_hat_keine_adapter_abhaengigkeit = + noClasses() + .that().resideInAPackage("de.gecheckt.asv.domain..") + .should().dependOnClassesThat() + .resideInAnyPackage( + "de.gecheckt.asv.adapter..", + "de.gecheckt.asv.bootstrap..", + "de.gecheckt.asv.preview.."); +``` + +### Test 3: Application ist frei von konkreten Adaptern +```java +@ArchTest +static final ArchRule application_kennt_keine_adapter_implementierungen = + noClasses() + .that().resideInAPackage("de.gecheckt.asv.application..") + .should().dependOnClassesThat() + .resideInAnyPackage( + "de.gecheckt.asv.adapter..", + "de.gecheckt.asv.bootstrap.."); +``` + +### Test 4: Preview wird nicht referenziert +```java +@ArchTest +static final ArchRule preview_wird_nicht_aus_aktivem_code_referenziert = + noClasses() + .that().resideInAnyPackage( + "de.gecheckt.asv.adapter..", + "de.gecheckt.asv.application..", + "de.gecheckt.asv.bootstrap..", + "de.gecheckt.asv.domain..") + .should().dependOnClassesThat() + .resideInAPackage("de.gecheckt.asv.preview..") + .because("Preview-Code ist aus M1-Sicht eingefroren und wird erst ab M3 aktiv verwendet."); +``` + +### Zusätzlich: Paketstruktur-Check +- Prüfen, dass die Soll-Pakete aus `technik-und-architektur.md` tatsächlich existieren (als ArchUnit-Regel oder einfacher Dateisystem-Test) + +## Scope OUT + +- komplexere Regeln wie „keine zyklischen Abhängigkeiten zwischen Paketen" — wäre schön, ist aber für M1 zu weitgehend +- Regeln zu Klassenbenennung +- Regeln zu `public`-Sichtbarkeit +- Tests für Preview-internen Aufbau + +## Schritte + +1. Branch `m1/ap10-architekturtest` +2. ArchUnit in `pom.xml` als Test-Dependency aufnehmen +3. `ArchitectureTest`-Klasse im Testbereich anlegen +4. Die vier Regeln implementieren +5. `mvn clean verify` laufen lassen — die Tests müssen **grün** sein. Falls rot: **das heißt, eine frühere M1-Phase hat die Regel verletzt**. Die Verletzung muss gefunden und behoben werden (kein Entschärfen der Regel!). +6. Commit `M1-AP10: Architekturtest für Log4j2-Sichtbarkeit, Paketabhängigkeiten, Preview-Isolation` +7. Abschlussbericht schreiben + +## Abnahmekriterien + +- ArchUnit ist als Test-Dependency eingebunden +- vier Architektur-Regeln sind implementiert und grün +- `mvn clean verify` ist grün +- Abschlussbericht liegt vor und dokumentiert, ob beim ersten Lauf Regeln rot waren und wenn ja, wie sie behoben wurden + +## Rest-Risiken und offene Punkte + +- ArchUnit hat beim ersten Einsatz manchmal Überraschungen mit transitiven Abhängigkeiten (Regel greift auch auf Framework-Klassen, die nicht gemeint waren). In dem Fall: Regel präzisieren, **nicht** ausschalten. +- Die Regel „Log4j2-Sichtbarkeit" schließt auch den Bootstrap mit ein. Wenn der Bootstrap später (M8) Krypto-Typen referenziert, müssen analoge Regeln ergänzt werden — aber das ist M8-Thema. + +## Bericht + +`docs/arbeitspakete/m1/berichte/AP10-bericht.md` nach `templates/ap-bericht.md`. diff --git a/docs/arbeitspakete/m1/AP11-m1-abnahme.md b/docs/arbeitspakete/m1/AP11-m1-abnahme.md new file mode 100644 index 0000000..7a767ef --- /dev/null +++ b/docs/arbeitspakete/m1/AP11-m1-abnahme.md @@ -0,0 +1,92 @@ +# AP11 – M1-Abnahme + +## Ziel + +Der letzte Schritt in M1: Alles wird gegen die Meilenstein-Abnahmekriterien aus `docs/specs/meilensteine.md` v3 **geprüft**, ein **End-to-End-Lauf** mit einer Minimal-Eingabedatei wird durchgeführt, und alle AP-Berichte werden in einem **konsolidierten M1-Abschlussbericht** zusammengeführt. + +## Voraussetzungen + +- AP01 bis AP10 abgeschlossen und grün +- alle AP-Berichte liegen in `docs/arbeitspakete/m1/berichte/` vor + +## Scope IN + +### End-to-End-Lauf +1. **Minimaldatei erstellen**: eine einfache Dummy-Textdatei im ISO-8859-15-Encoding, z.B. `test-artefakte/m1/minimal.txt` mit ein paar Zeilen Inhalt. Keine echten ASV-Daten, kein gültiges EDIFACT — dies ist nur ein Lauftest, kein Fachtest. +2. **JAR bauen**: `mvn clean package` +3. **Lauf 1**: `java -jar target/asv-format-validator-0.0.1-SNAPSHOT.jar test-artefakte/m1/minimal.txt` + - **Erwartung:** Exit-Code `0` (Dummy-Pfad, leerer Report), Berichtdatei `minimal.txt.txt` und Log-Datei `minimal.txt.log` entstehen, Konsolenausgabe vorhanden +4. **Lauf 2**: identischer Aufruf + - **Erwartung:** `minimal.txt_v1.txt` und `minimal.txt_v1.log` entstehen +5. **Lauf 3**: `java -jar ... nicht-vorhanden.txt` + - **Erwartung:** Exit-Code `2`, Minimalbericht auf Konsole, gegebenenfalls Berichtdatei im übergeordneten Verzeichnis wenn schreibbar +6. **Lauf 4**: `java -jar ...` (ohne Argument) + - **Erwartung:** Exit-Code `2`, Minimalbericht **nur** auf Konsole +7. **Lauf 5**: `java -jar ... datei1.txt datei2.txt` + - **Erwartung:** Exit-Code `2`, Minimalbericht auf Konsole + +Alle fünf Läufe werden im M1-Abschlussbericht dokumentiert (Befehl, Exit-Code, relevante Ausgabe). + +### Meilenstein-Abnahmeprüfung +Jeder Abnahmepunkt aus `docs/specs/meilensteine.md` v3 Abschnitt „Abnahme von M1" wird mit einem konkreten Nachweis verknüpft: + +| M1-Abnahmekriterium | Nachweis | Status | +|---|---|---| +| Anwendung ist als JAR unter Windows mit Java 21 startbar | Lauf 1, JAR-Pfad | ✅ | +| falsches oder fehlendes Argument → Exit-Code `2` mit Minimalbericht | Lauf 3, 4, 5 | ✅ | +| Bericht- und Log-Datei werden im Eingabeverzeichnis mit korrekter Suffix-Logik erzeugt | Lauf 1 + Lauf 2 | ✅ | +| Log4j2-Bindung ist außerhalb von Bootstrap und Logging-Adapter nicht sichtbar | Architekturtest AP10, Test 1 | ✅ | +| Befundmodell unterscheidet Spec-Urteil und diagnostische Weiteranalyse | Unit-Test AP05 | ✅ | +| Build und Tests sind grün | `mvn clean verify` | ✅ | + +### M1-Abschlussbericht +- Datei: `docs/arbeitspakete/m1/berichte/M1-abschlussbericht.md` +- Inhalt: + - **Zusammenfassung**: Was ist M1 geworden, in zwei Absätzen + - **AP-Übersicht**: Tabelle mit allen 11 APs, Status, Commit-Hashes, Abschlussdatum + - **Meilenstein-Abnahmetabelle** (siehe oben) + - **End-to-End-Protokoll**: die fünf Läufe mit Befehl, Exit-Code, Zusammenfassung der Ausgabe + - **Quality-Metriken** (Coverage, Testanzahl — **keine harten Gates in M1**, nur Informationswert) + - **Rest-Risiken und übertragene Punkte** aus allen AP-Berichten konsolidiert + - **Empfehlungen für M2**: Was sollte M2 beachten? Was ist aus M1-Sicht offen geblieben? + - **Commit-Graph-Snapshot**: `git log --oneline --graph main` für den M1-Zeitraum +- Freigabe-Vermerk am Ende: „M1 ist abnahmebereit" oder „M1 ist mit folgenden Einschränkungen abnahmebereit: ..." + +### Tagging +- Git-Tag `m1-done` auf dem letzten AP11-Commit setzen +- Tag-Message: „Meilenstein 1 abgeschlossen, siehe docs/arbeitspakete/m1/berichte/M1-abschlussbericht.md" + +## Scope OUT + +- Vorgriffe auf M2-Themen (Dateinamensschemata, globale Rahmenregeln, ISO-8859-15 über Dateinamen hinaus — außer dem Einlese-Encoding aus AP06, das bleibt) +- Release-Builds, Signierung, Publizierung +- Externe Reviews (die kommen vom Rezensenten der Arbeitspakete, nicht aus diesem AP) + +## Schritte + +1. Branch `m1/ap11-abnahme` +2. Test-Artefakt `test-artefakte/m1/minimal.txt` anlegen (ISO-8859-15, 3–5 Zeilen Dummy-Inhalt) +3. `mvn clean package` ausführen +4. Die fünf Läufe durchführen und protokollieren +5. Konsolidierten M1-Abschlussbericht schreiben +6. `mvn clean verify` ein letztes Mal laufen lassen +7. Commit `M1-AP11: M1-Abnahme, End-to-End-Protokoll, konsolidierter Abschlussbericht` +8. Git-Tag `m1-done` setzen: `git tag -a m1-done -m "Meilenstein 1 abgeschlossen"` + +## Abnahmekriterien + +- `test-artefakte/m1/minimal.txt` existiert +- alle fünf Läufe sind protokolliert +- M1-Abschlussbericht existiert und enthält alle oben genannten Abschnitte +- Meilenstein-Abnahmetabelle ist vollständig und jede Zeile hat einen konkreten Nachweis +- `mvn clean verify` ist grün +- Git-Tag `m1-done` ist gesetzt +- der Freigabe-Vermerk am Ende des Abschlussberichts ist explizit + +## Rest-Risiken und offene Punkte + +- Dieser AP ist ein reines Zusammenfassungs-AP. Wenn hier Abnahmekriterien nicht erfüllt sind, zeigt das, dass ein früheres AP unvollständig war. In dem Fall: **zurück zum betroffenen AP**, nachbessern, dann AP11 wiederholen. Keine Abkürzungen. + +## Bericht + +`docs/arbeitspakete/m1/berichte/AP11-bericht.md` nach `templates/ap-bericht.md` **zusätzlich** zum konsolidierten `M1-abschlussbericht.md`. diff --git a/docs/arbeitspakete/m1/README.md b/docs/arbeitspakete/m1/README.md new file mode 100644 index 0000000..cc1ec3a --- /dev/null +++ b/docs/arbeitspakete/m1/README.md @@ -0,0 +1,83 @@ +# M1 – Arbeitspakete (Übersicht) + +> **Bezug:** Meilenstein 1 aus `docs/specs/meilensteine.md` v3 +> **Ziel:** tragfähiger technischer Sockel mit Logging-Adapter und Befundmodell (Spec-/Diagnose-Trennung); noch keine ASV-Fachvalidierung +> **Ist-Zustand:** Repo enthält bereits eine frühere, schichtenbasierte Implementierung mit Parser-, Validator- und Feldlogik (Commit `32d50ec` vom 27.03.2026). Diese muss erhalten, aber ins hexagonale Zielbild überführt werden. +> **Vorgehen:** **evolutionär, nicht in einem Wurf.** Jedes Arbeitspaket endet in einem grünen, stabilen Zwischenstand. + +## Leitprinzipien für alle M1-Arbeitspakete + +1. **So viel wie möglich aus dem Ist-Stand erhalten und refactoren**, nicht wegwerfen. Insbesondere Parser, Tokenizer und Validator-Gerüst sind wertvoll und gehören später in `adapter.out.parsing` bzw. `application`. +2. **Jedes Arbeitspaket endet mit einem Bericht** (`berichte/AP-MX-XX.md`) nach dem Schema in `templates/ap-bericht.md`. +3. **Jedes Arbeitspaket endet grün:** `mvn clean verify` muss durchlaufen. Build, Compile, Tests. +4. **Keine Fachvalidierung in M1.** Wer versucht, schon EDIFACT-Strukturprüfungen o.ä. einzubauen, verletzt den Scope. Bestehende Fachvalidierung darf erhalten bleiben, aber sie wird in M1 **nicht weiterentwickelt**. +5. **Commit-Strategie:** ein Commit pro Arbeitspaket, Commit-Message `M1-APxx: `. +6. **Reviewbarkeit:** Der Bericht pro Arbeitspaket muss so präzise sein, dass ein unabhängiger Rezensent ohne Rückfragen prüfen kann, ob alles korrekt und in-scope umgesetzt wurde. + +## Arbeitspaket-Folge + +| AP | Titel | Hauptnutzen | Abhängigkeit | +|---|---|---|---| +| **AP01** | Ist-Stand-Inventar und Delta-Analyse | dokumentierter Ausgangspunkt, keine Überraschungen später | — | +| **AP02** | Build-Infrastruktur härten: SLF4J, JaCoCo, PIT, maven-jar-plugin, .editorconfig | `pom.xml` ist M1-tauglich, Quality-Gates messbar vorbereitet | AP01 | +| **AP03** | Hexagonale Paketstruktur anlegen und Ist-Code migrieren | Soll-Paketstruktur steht, bestehender Code ist eingeordnet, nichts geht kaputt | AP02 | +| **AP04** | Logging-Adapter (SLF4J-Fassade + Log4j2-Bindung) | Log4j2-Imports sind nur noch im Logging-Adapter und im Bootstrap sichtbar | AP03 | +| **AP05** | Befundmodell mit Spec-/Diagnose-Trennung (Domain) | `Finding`, `Severity`, `Verdict`, Metadata-Felder, strikt getrennt | AP03 | +| **AP06** | Bootstrap und CLI-Adapter: ein Positionsargument, Exit-Codes 0/1/2 | Exit-Codes sind spec-konform, Bootstrap verdrahtet manuell | AP05 | +| **AP07** | Ausgabeartefakte: Berichtdatei und Log-Datei im Eingabeverzeichnis mit Suffix-Logik | `.txt`/`.log` werden erzeugt, Suffix `_v1/_v2/...` funktioniert, UTF-8 | AP06 | +| **AP08** | Minimalbericht bei Exit-Code 2 (Bedienfehler) | auch bei fehlendem/falschem Argument oder nicht lesbarer Datei entsteht ein nachvollziehbarer Bericht | AP07 | +| **AP09** | Altlogik aus M1 entkoppeln: Parser/Validator in Adapter-/Application-Schicht eingefroren | bestehende Parser-/Validator-Logik ist erhalten, aber explizit als „Vorbau für M3+" markiert und nicht aktiv in den M1-Lauf verdrahtet | AP06 | +| **AP10** | Architekturtest: Log4j2-Sichtbarkeit, Paketabhängigkeiten, M1-Abnahme | ArchUnit-Test oder einfacher Klassenpfad-Scan stellt sicher, dass die Regeln eingehalten werden | AP04, AP09 | +| **AP11** | M1-Abnahme: grüner End-to-End-Lauf mit Minimaldatei, alle AP-Berichte konsolidiert | Meilenstein abgeschlossen, Übergabe an M2 möglich | alle vorigen | + +## Verzeichnisstruktur (im Repo anzulegen) + +``` +docs/ + arbeitspakete/ + m1/ + README.md (diese Datei) + templates/ + ap-bericht.md (Berichtsvorlage) + AP01-ist-stand-inventar.md + AP02-build-infrastruktur.md + AP03-hexagonale-paketstruktur.md + AP04-logging-adapter.md + AP05-befundmodell.md + AP06-bootstrap-cli.md + AP07-ausgabeartefakte.md + AP08-minimalbericht.md + AP09-altlogik-einfrieren.md + AP10-architekturtest.md + AP11-m1-abnahme.md + berichte/ + AP01-bericht.md (nach Abschluss) + AP02-bericht.md + ... +``` + +## Grobumfang pro AP + +Jedes Arbeitspaket hat eine eigene Datei mit: +- **Ziel** (was soll erreicht werden) +- **Voraussetzungen** (welche APs müssen abgeschlossen sein) +- **Scope IN** (was explizit Teil dieses APs ist) +- **Scope OUT** (was explizit NICHT Teil dieses APs ist) +- **Schritte** (konkrete Handlungsanleitung) +- **Abnahmekriterien** (messbar, reviewbar) +- **Rest-Risiken und offene Punkte** (was kann schiefgehen, was bleibt offen) +- **Berichtsschablone** (Hinweis, den Abschlussbericht nach `templates/ap-bericht.md` anzulegen) + +## Definition of Done für den gesamten M1 + +Ein M1 ist abgenommen, wenn: + +- alle 11 Arbeitspakete grün abgeschlossen sind +- für jedes Arbeitspaket ein Abschlussbericht in `docs/arbeitspakete/m1/berichte/` existiert +- die Anwendung als ausführbares JAR vorliegt und mit `java -jar asv-format-validator.jar ` startbar ist +- die Exit-Codes 0/1/2 spec-konform sind +- Bericht- und Log-Datei im Eingabeverzeichnis erzeugt werden +- Log4j2-Typen außerhalb von Bootstrap und Logging-Adapter nicht mehr importiert werden (per Architekturtest nachweisbar) +- Befundmodell trennt Spec-Urteil und diagnostische Weiteranalyse +- `mvn clean verify` ist grün +- M1-Abnahmebericht (`AP11-bericht.md`) fasst alles zusammen diff --git a/docs/arbeitspakete/m1/templates/ap-bericht.md b/docs/arbeitspakete/m1/templates/ap-bericht.md new file mode 100644 index 0000000..fa9c7b7 --- /dev/null +++ b/docs/arbeitspakete/m1/templates/ap-bericht.md @@ -0,0 +1,66 @@ +# Abschlussbericht Arbeitspaket AP-XX- + +> **Bezug:** `docs/arbeitspakete/m1/APxx-.md` +> **Bearbeiter:** +> **Datum:** +> **Commit(s):** +> **Status:** ✅ abgeschlossen / ⚠️ abgeschlossen mit Einschränkungen / 🔴 abgebrochen + +## 1. Zusammenfassung + +Ein bis zwei Sätze: Was wurde gemacht? + +## 2. Umgesetzte Änderungen + +Konkrete Aufzählung der tatsächlich durchgeführten Änderungen. Wenn möglich mit Dateipfaden und kurzer Begründung. + +- `pfad/zur/datei` – was geändert wurde und warum +- … + +## 3. Scope-Treue + +| Scope-Punkt aus dem Arbeitspaket | Erfüllt? | Bemerkung | +|---|---|---| +| Punkt 1 | ✅ / ⚠️ / ❌ | … | +| Punkt 2 | ✅ / ⚠️ / ❌ | … | + +**Wurde der Scope eingehalten?** Ja / Nein / teilweise (begründen) + +**Wurden Dinge außerhalb des Scopes gemacht?** Falls ja, welche und warum? + +## 4. Abnahmekriterien + +| Abnahmekriterium aus dem Arbeitspaket | Erfüllt? | Nachweis | +|---|---|---| +| Kriterium 1 | ✅ / ⚠️ / ❌ | z.B. Testname, Commit-Hash, Log-Ausschnitt | +| … | | | + +## 5. Build- und Teststatus + +- `mvn clean verify`: ✅ grün / 🔴 rot +- Anzahl Tests: N (davon M neu hinzugefügt) +- Coverage (falls bereits messbar): domain = X %, application = Y %, … +- Warnungen beim Build: keine / siehe unten + +## 6. Rest-Risiken und offene Punkte + +Was kann noch schiefgehen? Was wurde bewusst nicht gelöst und in ein späteres Arbeitspaket geschoben? + +- Risiko 1: … +- Offener Punkt 1: … + +## 7. Empfehlungen für Folge-Arbeitspakete + +Was sollte das nächste AP beachten? Gibt es Lessons Learned? + +## 8. Reviewer-Checkliste + +Der Rezensent prüft damit die korrekte Umsetzung: + +- [ ] Alle im Arbeitspaket genannten Scope-IN-Punkte sind nachweislich umgesetzt +- [ ] Keine Scope-OUT-Punkte wurden angefasst +- [ ] Abnahmekriterien sind mit konkreten Nachweisen belegt (Tests, Dateipfade, Commits) +- [ ] `mvn clean verify` ist grün +- [ ] Der Commit für dieses AP hat eine sprechende Message (`M1-APxx: ...`) +- [ ] Keine Regeln der Grunddokumente (Spec, Fachliche, Technik) wurden verletzt +- [ ] Rest-Risiken sind ehrlich dokumentiert