1
0

Umsetzung von M1

This commit is contained in:
2026-04-20 10:11:19 +02:00
parent cd6e5221aa
commit b5044f62a9
59 changed files with 5891 additions and 884 deletions
+86 -56
View File
@@ -1,18 +1,28 @@
---
model: sonnet
---
# AP05 Befundmodell mit Spec-/Diagnose-Trennung
> **Meilenstein:** M1
> **Vorgänger:** AP03, AP04 ✅
> **Nachfolger:** AP06, AP07, AP09
> **Grundlage:** `docs/specs/technik-und-architektur.md` v5, §§ „Ergebnis- und Befundmodell", „Befundarten", „Gültigkeitsentscheidung und Exit-Codes"
> **Entscheidungsprotokoll:** `docs/arbeitspakete/m1/E00-entscheidungsprotokoll.md`
## 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.
Der bestehende Typ `de.gecheckt.asv.validation.model.ValidationResult` wird nicht geändert — er wird in AP09 eingefroren.
## Voraussetzungen
- AP03 (Paketstruktur)
- AP03 (Paketstruktur vorhanden)
- AP04 (Logging-Adapter)
## Scope IN
Folgende Typen im Paket `de.gecheckt.asv.domain.finding` (oder ähnliches Unterpaket von `domain`):
Folgende Typen im Paket `de.gecheckt.asv.domain.finding`:
### `Severity` (Enum)
- `ERROR`
@@ -21,88 +31,108 @@ Folgende Typen im Paket `de.gecheckt.asv.domain.finding` (oder ähnliches Unterp
### `FindingKind` (Enum)
- `SPEC` — Befund ist Teil des Spec-Urteils, beeinflusst `Verdict`
- `DIAGNOSTIC` — zusätzliche Weiteranalyse, beeinflusst `Verdict` **nicht**
- `DIAGNOSTIC` — zusätzliche Weiteranalyse, beeinflusst `Verdict` **niemals**
### `FindingLayer` (Enum)
- `ARTIFACT` — äußeres Artefakt / Dateiebene
- `TECHNICAL_STRUCTURE` — Service-Segmente, KKS, Transport
- `DOMAIN_MODEL` — kanonisches Fachmodell (ASVREC/ASVFEH)
### `Finding` (Record)
### `Finding` (Record oder unveränderliche Klasse)
Alle Pflichtfelder laut `technik-und-architektur.md` §„Befundarten":
```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
String ruleId, // interne Regel-ID, nullable
String officialErrorCode, // offizieller Spec-Fehlercode, nullable
String segmentType, // z.B. "UNB", nullable
Integer segmentIndex, // nullable
String fieldId, // z.B. "UNB_0020", nullable
String rawValue, // Rohwert, nullable
Integer position, // Byte-/Zeichenposition, nullable
String messageReference, // UNH 0062 bei Nachrichtenbezug, nullable
String germanMessage // deutscher Befundtext, nicht nullable
) {}
```
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".**
Records mit vielen optionalen Feldern sind unschön — als Alternative ist eine reguläre unveränderliche Klasse mit Builder erlaubt, solange alle Felder vorhanden sind.
### `Verdict` (Enum)
- `VALID` — keine Spec-ERROR-Befunde
- `INVALID` — mindestens ein Spec-ERROR-Befund
- `OPERATIONAL_ERROR` — Bedienfehler (Exit-Code 2)
- `VALID` — keine SPEC-ERROR-Befunde
- `INVALID` — mindestens ein SPEC-ERROR-Befund
- `OPERATIONAL_ERROR` — Bedienfehler (Exit-Code 2), wird in AP08 genutzt
### `ValidationReport` (Klasse)
- unveränderlich
- enthält:
- `List<Finding> findings` (alle Befunde, SPEC und DIAGNOSTIC gemischt, Reihenfolge erhalten)
- Methode `Verdict computeVerdict()` — berücksichtigt **nur** `kind == SPEC` und `severity == ERROR`
- Methode `List<Finding> specFindings()` — filtert auf `kind == SPEC`
- Methode `List<Finding> 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.
### `ValidationReport` (unveränderliche Klasse)
### 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
```java
public final class ValidationReport {
// Metadaten
String fileName;
Instant timestamp;
// Befunde
List<Finding> findings; // unveränderlich
// Kern-Methoden
Verdict computeVerdict(); // NUR SPEC+ERROR zählt
boolean hasSpecErrors();
List<Finding> specFindings();
List<Finding> diagnosticFindings();
// Factory für Bedienfehler (AP08)
static ValidationReport operationalError(String fileName, String ruleId, String message);
}
```
**Invariante:** `computeVerdict()` berücksichtigt **ausschließlich** Findings mit `kind == SPEC` und `severity == ERROR`. Ein `DIAGNOSTIC`-ERROR darf das Verdict **niemals** auf `INVALID` setzen. Dies ist per Unit-Test abzusichern.
### Unit-Tests (Mindestanforderung)
1. Leerer Report → `Verdict.VALID`
2. Ein SPEC-ERROR → `Verdict.INVALID`
3. **Ein DIAGNOSTIC-ERROR → `Verdict.VALID`** (dieser Test ist kritisch und muss explizit vorhanden sein)
4. SPEC-WARNING → `Verdict.VALID` (nur ERROR zählt)
5. `specFindings()` / `diagnosticFindings()` filtern korrekt
6. `findings`-Liste ist nicht von außen modifizierbar
7. `operationalError(...)``Verdict.OPERATIONAL_ERROR`
## 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)
- Integration des neuen Modells in den bestehenden Lauf (AP06)
- Löschen oder Umbenennen der alten `ValidationResult`-Klasse (AP09)
- Berichtserzeugung, Textrendering, Konsolenausgabe (AP07)
- Architekturtest (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
1. Paket `de.gecheckt.asv.domain.finding` anlegen
2. Enums `Severity`, `FindingKind`, `FindingLayer` implementieren
3. `Finding` implementieren
4. `Verdict` implementieren
5. `ValidationReport` implementieren
6. Unit-Tests schreiben — mindestens die sieben oben genannten
7. `mvn clean verify` grün bekommen
8. 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
- [ ] Paket `domain.finding` enthält alle genannten Typen
- [ ] **Test „DIAGNOSTIC-ERROR ergibt VALID" ist grün** und im Bericht explizit genannt
- [ ] `ValidationReport.findings` ist unveränderlich (Test vorhanden)
- [ ] Alle Metadatenfelder aus `technik-und-architektur.md` §„Befundarten" sind im `Finding`-Typ vorhanden
- [ ] `operationalError(...)` Factory-Methode existiert
- [ ] Keine Änderung an `ValidationResult` (Altmodell)
- [ ] `mvn clean verify` grün
- [ ] Abschlussbericht unter `docs/arbeitspakete/m1/berichte/AP05-bericht.md`
## 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.
- Zwei parallele Ergebnistypen (`ValidationResult` alt, `ValidationReport` neu) sind bis AP09 Absicht.
- Das Befundmodell ist bewusst eine **flache Liste** mit Metadaten, keine Hierarchie. Die hierarchische Berichtserzeugung kommt in M9.
## Bericht
`docs/arbeitspakete/m1/berichte/AP05-bericht.md` nach `templates/ap-bericht.md`.
`docs/arbeitspakete/m1/berichte/AP05-bericht.md` nach `docs/arbeitspakete/m1/templates/ap-bericht.md`.