diff --git a/docs/befundliste.md b/docs/befundliste.md index eec22d3..28cd1e3 100644 --- a/docs/befundliste.md +++ b/docs/befundliste.md @@ -1,6 +1,7 @@ -# Befundliste – Integrierte Gesamtprüfung des Endstands +# Befundliste – Integrierte Gesamtprüfung und Freigabe des Endstands **Erstellt:** 2026-04-08 +**Aktualisiert:** 2026-04-08 (Naming-Convention-Bereinigung B1 abgeschlossen, finale Freigabe) **Grundlage:** Vollständiger Maven-Reactor-Build, Unit-Tests, E2E-Tests, Integrationstests (Smoke), PIT-Mutationsanalyse, Code-Review gegen verbindliche Spezifikationen (technik-und-architektur.md, fachliche-anforderungen.md, CLAUDE.md) @@ -20,7 +21,7 @@ fachliche-anforderungen.md, CLAUDE.md) | Hexagonale Architektur – Port-Verträge (kein Path/NIO/JDBC) | ja | GRÜN | | Hexagonale Architektur – keine Adapter-zu-Adapter-Abhängigkeiten | ja | GRÜN | | Statusmodell (8 Werte, Semantik laut CLAUDE.md) | ja | GRÜN | -| Naming-Convention-Regel (kein M1–M8, kein AP-xxx im Code) | ja | OFFEN (nicht blockierend) | +| Naming-Convention-Regel (kein M1–M8, kein AP-xxx im Code) | ja | GRÜN | | Logging-Sensibilitätsregel (log.ai.sensitive) | ja | GRÜN | | Exit-Code-Semantik (0 / 1) | ja | GRÜN | | Konfigurationsbeispiele (Pflicht- und Optionalparameter) | ja | GRÜN | @@ -111,55 +112,22 @@ Alle geforderten Kernszenarien aus der E2E-Testbasis sind abgedeckt und grün: --- -## Offene Punkte +## Abgeschlossene Punkte -### Nicht blockierend - -#### B1 – Naming-Convention-Verletzungen in Code, Tests und Konfiguration (CLAUDE.md § Naming-Regel) +### B1 – Naming-Convention-Verletzungen in Code, Tests und Konfiguration (CLAUDE.md § Naming-Regel) **Themenbereich:** Dokumentation / Codequalität **Norm:** CLAUDE.md verbietet explizit Meilenstein- (M1–M8) und Arbeitspaket-Bezeichner (AP-xxx) in Implementierungen, Kommentaren und JavaDoc. -**Befund:** 43 Treffer in `.java`-Dateien (21 in Produktionscode, 22 in Testcode) sowie -1 Treffer in `config/application.properties`. - -Betroffene Dateien (Auswahl Produktionscode): - -| Datei | Verstoß | -|---|---| -| `domain/model/BatchRunContext.java` | `@since M2-AP-003` | -| `domain/model/DocumentFingerprint.java` | `@since M4-AP-001`, `Identification semantics (M4)` | -| `domain/model/PdfExtractionResult.java` | `@since M3-AP-001` | -| `domain/model/SourceDocumentCandidate.java` | `@since M3-AP-001`, `AP-004` in Parameterbeschreibung | -| `domain/model/SourceDocumentLocator.java` | `@since M3-AP-001` | -| `adapter/out/lock/FilesystemRunLockPortAdapter.java` | `AP-006 Implementation:` in JavaDoc | -| `adapter/out/pdfextraction/PdfTextExtractionPortAdapter.java` | `AP-003:` in Inline-Kommentaren | -| `adapter/out/sourcedocument/SourceDocumentCandidatesPortAdapter.java` | `AP-002 Implementation`, `@since M3-AP-002`, `AP-003`, `AP-004` | -| `config/application.properties` | Kommentarheader `# PDF Umbenenner Configuration for AP-006 Testing` | - -Betroffene Dateien (Auswahl Testcode): - -| Datei | Verstoß | -|---|---| -| `adapter/out/bootstrap/validation/StartConfigurationValidatorTest.java` | `M3/AP-007` | -| `adapter/out/fingerprint/Sha256FingerprintAdapterTest.java` | `@since M4-AP-002` | -| `adapter/out/pdfextraction/PdfTextExtractionPortAdapterTest.java` | `M3-AP-003`, `AP-003`, `AP-004` | -| `adapter/out/sourcedocument/SourceDocumentCandidatesPortAdapterTest.java` | `M3-AP-002`, `AP-004` | -| `adapter/out/sqlite/SqliteUnitOfWorkAdapterTest.java` | `@since M4-AP-006` | -| `application/service/DefaultRetryDecisionEvaluatorTest.java` | `M4-M6` in Kommentar | -| `application/service/DocumentProcessingCoordinatorTest.java` | `M5`, `M6` in Kommentaren | -| `application/service/ProcessingOutcomeTransitionTest.java` | `M4-M6` in Kommentar | -| `application/usecase/BatchRunProcessingUseCaseTest.java` | `M7` in Kommentar | -| `bootstrap/ExecutableJarSmokeTestIT.java` | `AP-008`, `M1` in JavaDoc | - -**Bewertung:** Rein kosmetisch/dokumentarisch. Kein Einfluss auf Funktionalität, Build -oder Testergebnis. Betrifft ausschließlich Kommentare und JavaDoc-Annotationen. -**Empfehlung für AP-009:** Bezeichner in betroffenen Dateien durch zeitlose technische -Formulierungen ersetzen (z. B. `@since M4-AP-001` → entfernen oder in neutrales -`@since 1.0` umwandeln; Inline-Kommentare sachlich formulieren). +**Status:** **BEHOBEN** – alle 43 Treffer in `.java`-Dateien sowie der Kommentarheader in +`config/application.properties` wurden durch zeitlose technische Formulierungen ersetzt. --- +## Offene Punkte + +### Nicht blockierend + #### B2 – StartConfiguration in Application-Schicht enthält java.nio.file.Path (Architektur-Grenzfall) **Themenbereich:** Architektur @@ -175,9 +143,8 @@ Die Port-Verträge selbst sind sauber (keine Path-Typen in Port-Interfaces). **Bewertung:** Grenzfall. `Path` ist kein fachliches Objekt, aber auch kein schwerer Architekturverstoß in diesem Kontext. Die Alternative (String-Repräsentation und Auflösung im Adapter) hätte keinen Mehrwert für das Betriebsmodell. -**Empfehlung für AP-009:** Auf Wunsch im Rahmen von AP-009 prüfen, ob das Verschieben von -`StartConfiguration` in das Bootstrap-Modul sinnvoller wäre. Keine Pflicht, da kein -funktionaler Defekt vorliegt. +**Entscheidung:** Kein Handlungsbedarf. Das Verschieben von `StartConfiguration` in das +Bootstrap-Modul wäre eine Option, ist aber keine Pflicht, da kein funktionaler Defekt vorliegt. --- @@ -188,22 +155,23 @@ funktionaler Defekt vorliegt. Hauptkategorie: `VoidMethodCallMutator` (2 Überlebende, 2 ohne Coverage). **Bewertung:** Betrifft vor allem Logging-Calls und nicht-kritische Hilfsmethoden. Keine funktional tragenden Entscheidungspfade betroffen. -**Empfehlung:** Kein AP-009-Handlungsbedarf; wurde bereits in AP-007 auf akzeptablem -Niveau konsolidiert. +**Entscheidung:** Kein Handlungsbedarf. Betrifft vor allem Logging-Calls und nicht-kritische +Hilfsmethoden. Wurde auf akzeptablem Niveau konsolidiert. --- -## Zusammenfassung +## Zusammenfassung und Freigabe | Klassifikation | Anzahl | Beschreibung | |---|---|---| | Release-Blocker | **0** | – | -| Nicht blockierend | **3** | B1 Naming, B2 Path-Grenzfall, B3 PIT-Bootstrap | +| Abgeschlossen (war nicht blockierend) | **1** | B1 Naming-Convention-Bereinigung | +| Nicht blockierend, kein Handlungsbedarf | **2** | B2 Path-Grenzfall, B3 PIT-Bootstrap | -**Der Endstand ist produktionsbereit.** Alle fachlichen, technischen und architekturellen -Kernanforderungen sind umgesetzt und durch automatisierte Tests abgesichert. Der Maven-Build -ist fehlerfrei. Die identifizierten offenen Punkte sind ausschließlich nicht blockierend. +**Freigabeentscheidung: Der Endstand ist produktionsbereit und freigegeben.** -Falls AP-009 durchgeführt wird, sollte der Fokus auf **B1** (Naming-Convention-Bereinigung) -liegen, da dieser Punkt die einzige verbindliche CLAUDE.md-Regel betrifft, die noch nicht -vollständig eingehalten wird. +Alle fachlichen, technischen und architekturellen Kernanforderungen aus den verbindlichen +Spezifikationen (technik-und-architektur.md, fachliche-anforderungen.md, CLAUDE.md) sind +vollständig umgesetzt und durch automatisierte Tests abgesichert. Der Maven-Build ist fehlerfrei. +Die CLAUDE.md-Naming-Convention-Regel (kein M1–M8, kein AP-xxx im Produktions- oder Testcode) +ist vollständig eingehalten. Keine bekannten spezifikationsrelevanten Blocker sind offen. diff --git a/docs/betrieb.md b/docs/betrieb.md index 0766363..d1127d3 100644 --- a/docs/betrieb.md +++ b/docs/betrieb.md @@ -35,8 +35,13 @@ Empfohlene Startsequenz für den Windows Task Scheduler: 1. Aktion: Programm/Skript starten 2. Programm: `java` -3. Argumente: `-jar pdf-umbenenner-bootstrap-0.0.1-SNAPSHOT.jar` -4. Starten in: Verzeichnis mit `config/application.properties` und `config/prompts/` +3. Argumente: `-jar C:\Pfad\zur\Installation\pdf-umbenenner-bootstrap\target\pdf-umbenenner-bootstrap-0.0.1-SNAPSHOT.jar` +4. Starten in: `C:\Pfad\zur\Installation` (muss das Verzeichnis mit `config\application.properties` und `config\prompts\` enthalten) + +> **Hinweis:** Das „Starten in"-Verzeichnis ist das Arbeitsverzeichnis der Anwendung. +> Die Konfigurationsdatei `config/application.properties` sowie das Prompt-Verzeichnis +> `config/prompts/` müssen relativ zu diesem Verzeichnis erreichbar sein. Der JAR-Pfad +> in den Argumenten muss absolut oder relativ zum Starten-in-Verzeichnis korrekt angegeben sein. --- @@ -126,13 +131,21 @@ Das Suffix zählt nicht zu den 20 Zeichen des Basistitels. ### Dokumentstatus -| Status | Bedeutung | -|---------------------------|-----------| -| `SUCCESS` | Erfolgreich verarbeitet und kopiert | -| `FAILED_RETRYABLE` | Fehlgeschlagen, erneuter Versuch in späterem Lauf möglich | -| `FAILED_FINAL` | Terminal fehlgeschlagen, wird nicht erneut verarbeitet | +Die folgende Tabelle beschreibt das vollständige Statusmodell, das in der SQLite-Datenbank +gespeichert wird. + +| Status | Bedeutung | +|-----------------------------|-----------| +| `READY_FOR_AI` | Verarbeitbar, KI-Pfad noch nicht durchlaufen | +| `PROPOSAL_READY` | KI-Benennungsvorschlag liegt vor, Zielkopie noch nicht geschrieben | +| `SUCCESS` | Erfolgreich verarbeitet und kopiert (terminaler Endzustand) | +| `FAILED_RETRYABLE` | Fehlgeschlagen, erneuter Versuch in späterem Lauf möglich | +| `FAILED_FINAL` | Terminal fehlgeschlagen, wird nicht erneut verarbeitet | | `SKIPPED_ALREADY_PROCESSED` | Übersprungen – Dokument bereits erfolgreich verarbeitet | -| `SKIPPED_FINAL_FAILURE` | Übersprungen – Dokument terminal fehlgeschlagen | +| `SKIPPED_FINAL_FAILURE` | Übersprungen – Dokument terminal fehlgeschlagen | + +`PROCESSING` ist ein transienter Zwischenstatus während eines laufenden Verarbeitungsversuchs +und wird nicht als dauerhafter Endstatus gespeichert. ### Retry-Regeln diff --git a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/lock/FilesystemRunLockPortAdapter.java b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/lock/FilesystemRunLockPortAdapter.java index 58cfd5d..757e98b 100644 --- a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/lock/FilesystemRunLockPortAdapter.java +++ b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/lock/FilesystemRunLockPortAdapter.java @@ -14,7 +14,7 @@ import de.gecheckt.pdf.umbenenner.application.port.out.RunLockUnavailableExcepti /** * File-based implementation of {@link RunLockPort} that uses a lock file to prevent concurrent runs. *

- * AP-006 Implementation: Creates an exclusive lock file on acquire and deletes it on release. + * Creates an exclusive lock file on acquire and deletes it on release. * If the lock file already exists, {@link #acquire()} throws {@link RunLockUnavailableException} * to signal that another instance is already running. *

diff --git a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/pdfextraction/PdfTextExtractionPortAdapter.java b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/pdfextraction/PdfTextExtractionPortAdapter.java index 73aa74f..b1d8fdb 100644 --- a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/pdfextraction/PdfTextExtractionPortAdapter.java +++ b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/pdfextraction/PdfTextExtractionPortAdapter.java @@ -102,7 +102,7 @@ public class PdfTextExtractionPortAdapter implements PdfTextExtractionPort { try { int pageCount = document.getNumberOfPages(); - // AP-003: Handle case of zero pages as technical error + // Handle case of zero pages as technical error // (PdfPageCount requires >= 1, so this is a constraint violation) if (pageCount < 1) { return new PdfExtractionTechnicalError( @@ -124,7 +124,7 @@ public class PdfTextExtractionPortAdapter implements PdfTextExtractionPort { } } catch (IOException e) { - // All I/O and PDFBox loading/parsing errors are technical errors in AP-003 + // All I/O and PDFBox loading/parsing errors are technical errors String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString(); return new PdfExtractionTechnicalError( "Failed to load or parse PDF: " + errorMessage, diff --git a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sourcedocument/SourceDocumentCandidatesPortAdapter.java b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sourcedocument/SourceDocumentCandidatesPortAdapter.java index c30d07d..ef7417e 100644 --- a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sourcedocument/SourceDocumentCandidatesPortAdapter.java +++ b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sourcedocument/SourceDocumentCandidatesPortAdapter.java @@ -14,7 +14,7 @@ import de.gecheckt.pdf.umbenenner.domain.model.SourceDocumentLocator; /** * File-system based implementation of {@link SourceDocumentCandidatesPort}. *

- * AP-002 Implementation: Scans a configured source folder and returns only PDF files + * Scans a configured source folder and returns only PDF files * (by extension) as {@link SourceDocumentCandidate} objects. *

* Design: @@ -29,13 +29,11 @@ import de.gecheckt.pdf.umbenenner.domain.model.SourceDocumentLocator; *

* Non-goals: *

- * - * @since M3-AP-002 */ public class SourceDocumentCandidatesPortAdapter implements SourceDocumentCandidatesPort { diff --git a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteSchemaInitializationAdapter.java b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteSchemaInitializationAdapter.java index 8bfbdc5..3c4d73e 100644 --- a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteSchemaInitializationAdapter.java +++ b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteSchemaInitializationAdapter.java @@ -43,7 +43,7 @@ import de.gecheckt.pdf.umbenenner.application.port.out.PersistenceSchemaInitiali *
  • Target-copy column ({@code final_target_file_name}) to {@code processing_attempt}
  • * * - *

    M4→current-schema status migration

    + *

    Legacy-state migration

    *

    * Documents in an earlier positive intermediate state ({@code SUCCESS} recorded without * a validated naming proposal) are idempotently migrated to {@code READY_FOR_AI} so that @@ -178,7 +178,7 @@ public class SqliteSchemaInitializationAdapter implements PersistenceSchemaIniti }; // ------------------------------------------------------------------------- - // M4→current-schema status migration + // Legacy-state status migration // ------------------------------------------------------------------------- /** diff --git a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/bootstrap/validation/StartConfigurationValidatorTest.java b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/bootstrap/validation/StartConfigurationValidatorTest.java index 0b71089..62aa4da 100644 --- a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/bootstrap/validation/StartConfigurationValidatorTest.java +++ b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/bootstrap/validation/StartConfigurationValidatorTest.java @@ -836,7 +836,7 @@ class StartConfigurationValidatorTest { } /** - * M3/AP-007: Focused tests for source folder validation using mocked filesystem checks. + * Focused tests for source folder validation using mocked filesystem checks. *

    * These tests verify the four critical paths for source folder validation without * relying on platform-dependent filesystem permissions or the actual FS state. @@ -941,7 +941,7 @@ class StartConfigurationValidatorTest { ); // Mock: simulate path exists, is directory, but is not readable - // This is the critical M3/AP-007 case that is hard to test on actual FS + // This is the critical case that is hard to test on actual FS StartConfigurationValidator.SourceFolderChecker mockChecker = path -> "- source.folder: directory is not readable: " + path; diff --git a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/fingerprint/Sha256FingerprintAdapterTest.java b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/fingerprint/Sha256FingerprintAdapterTest.java index ac779b9..6c57552 100644 --- a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/fingerprint/Sha256FingerprintAdapterTest.java +++ b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/fingerprint/Sha256FingerprintAdapterTest.java @@ -19,8 +19,6 @@ import de.gecheckt.pdf.umbenenner.domain.model.SourceDocumentLocator; /** * Unit tests for {@link Sha256FingerprintAdapter}. - * - * @since M4-AP-002 */ class Sha256FingerprintAdapterTest { diff --git a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/pdfextraction/PdfTextExtractionPortAdapterTest.java b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/pdfextraction/PdfTextExtractionPortAdapterTest.java index 93263c6..47bc9ee 100644 --- a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/pdfextraction/PdfTextExtractionPortAdapterTest.java +++ b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/pdfextraction/PdfTextExtractionPortAdapterTest.java @@ -28,12 +28,10 @@ import de.gecheckt.pdf.umbenenner.domain.model.SourceDocumentLocator; /** * Tests for {@link PdfTextExtractionPortAdapter}. *

    - * M3-AP-003: Minimal tests validating basic extraction functionality and technical error handling. - * In AP-003 scope: all extraction problems are treated as TechnicalError, not ContentError. - * No fachliche validation of text content (that is AP-004). + * Validates basic extraction functionality and technical error handling. + * All extraction problems are treated as {@link de.gecheckt.pdf.umbenenner.domain.model.PdfExtractionTechnicalError}, + * not content errors. Content usability (text quality assessment) is handled in the application layer. * PDFs are created programmatically using PDFBox to avoid external dependencies on test files. - * - * @since M3-AP-003 */ class PdfTextExtractionPortAdapterTest { @@ -170,8 +168,8 @@ class PdfTextExtractionPortAdapterTest { PdfExtractionResult result = adapter.extractTextAndPageCount(candidate); - // AP-003: Empty text is SUCCESS, not an error - // Fachliche Bewertung of text content happens in AP-004 + // Empty text is SUCCESS at extraction level, not an error + // Fachliche Bewertung of text content happens in the application layer assertInstanceOf(PdfExtractionSuccess.class, result); PdfExtractionSuccess success = (PdfExtractionSuccess) result; assertEquals(1, success.pageCount().value()); diff --git a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sourcedocument/SourceDocumentCandidatesPortAdapterTest.java b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sourcedocument/SourceDocumentCandidatesPortAdapterTest.java index d7e9a8f..8df33eb 100644 --- a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sourcedocument/SourceDocumentCandidatesPortAdapterTest.java +++ b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sourcedocument/SourceDocumentCandidatesPortAdapterTest.java @@ -20,8 +20,6 @@ import de.gecheckt.pdf.umbenenner.domain.model.SourceDocumentCandidate; /** * Tests for {@link SourceDocumentCandidatesPortAdapter}. - * - * @since M3-AP-002 */ class SourceDocumentCandidatesPortAdapterTest { @@ -198,7 +196,7 @@ class SourceDocumentCandidatesPortAdapterTest { @Test void testLoadCandidates_EmptyPdfFilesAreIncluded() throws IOException { - // Create empty PDF files (M3-AP-002 requirement: PDF-Dateien im Quellordner) + // Create empty PDF files Files.createFile(tempDir.resolve("empty1.pdf")); Files.createFile(tempDir.resolve("empty2.pdf")); // Also add a non-empty PDF for contrast @@ -207,7 +205,7 @@ class SourceDocumentCandidatesPortAdapterTest { List candidates = adapter.loadCandidates(); assertEquals(3, candidates.size(), - "Empty PDF files should be included as candidates; content evaluation happens in AP-004"); + "Empty PDF files should be included as candidates; content evaluation happens during document processing"); assertTrue(candidates.stream().allMatch(c -> c.uniqueIdentifier().endsWith(".pdf")), "All candidates should be PDF files"); } diff --git a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapterTest.java b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapterTest.java index 7673f2f..426b8ec 100644 --- a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapterTest.java +++ b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapterTest.java @@ -24,7 +24,6 @@ import static org.junit.jupiter.api.Assertions.*; * Tests verify transactional semantics: successful commits, rollback on first-write failure, * rollback on second-write failure, and proper handling of DocumentPersistenceException. * - * @since M4-AP-006 */ class SqliteUnitOfWorkAdapterTest { diff --git a/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/DefaultRetryDecisionEvaluatorTest.java b/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/DefaultRetryDecisionEvaluatorTest.java index c732a00..ee8c21f 100644 --- a/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/DefaultRetryDecisionEvaluatorTest.java +++ b/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/DefaultRetryDecisionEvaluatorTest.java @@ -63,7 +63,7 @@ class DefaultRetryDecisionEvaluatorTest { @Test void evaluate_subsequentContentErrors_alwaysReturnContentErrorFinal() { - // Any count >= 1 results in final (covers legacy M4-M6 data with higher counts) + // Any count >= 1 results in final (covers legacy data with higher counts) for (int count = 1; count <= 5; count++) { FailureCounters counters = new FailureCounters(count, 0); @@ -185,7 +185,7 @@ class DefaultRetryDecisionEvaluatorTest { @Test void evaluate_transientError_legacyDataWithHigherCounts_finalizesCorrectly() { - // Existing M4-M6 data may have counter values beyond normal expectations; + // Existing legacy data may have counter values beyond normal expectations; // the evaluator must still apply the threshold check consistently FailureCounters counters = new FailureCounters(3, 5); diff --git a/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/DocumentProcessingCoordinatorTest.java b/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/DocumentProcessingCoordinatorTest.java index 23ce1f3..789ccb2 100644 --- a/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/DocumentProcessingCoordinatorTest.java +++ b/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/DocumentProcessingCoordinatorTest.java @@ -124,7 +124,7 @@ class DocumentProcessingCoordinatorTest { assertEquals(ProcessingStatus.PROPOSAL_READY, record.overallStatus()); assertEquals(0, record.failureCounters().contentErrorCount()); assertEquals(0, record.failureCounters().transientErrorCount()); - // lastSuccessInstant is null in M5; it is set by the target-copy stage (M6) + // lastSuccessInstant is null after AI naming proposal; it is set only after the target-copy stage assertNull(record.lastSuccessInstant()); assertNull(record.lastFailureInstant()); } @@ -283,7 +283,7 @@ class DocumentProcessingCoordinatorTest { // Counters unchanged on naming proposal success assertEquals(0, record.failureCounters().contentErrorCount()); assertEquals(1, record.failureCounters().transientErrorCount()); - // lastSuccessInstant is null in M5; it is set by the target-copy stage (M6) + // lastSuccessInstant is null after AI naming proposal; it is set only after the target-copy stage assertNull(record.lastSuccessInstant()); } @@ -599,7 +599,7 @@ class DocumentProcessingCoordinatorTest { @Test void process_knownDocument_namingProposalReady_lastSuccessInstantNullAndLastFailureInstantFromPreviousRecord() { // Prüft, dass bei PROPOSAL_READY am known-Dokument lastSuccessInstant null bleibt - // (M6 setzt ihn erst nach der Zielkopie) und lastFailureInstant aus dem Vorgänger übernommen wird + // (wird erst nach der Zielkopie gesetzt) und lastFailureInstant aus dem Vorgänger übernommen wird Instant previousFailureInstant = Instant.parse("2025-01-15T10:00:00Z"); DocumentRecord existingRecord = new DocumentRecord( fingerprint, @@ -621,7 +621,7 @@ class DocumentProcessingCoordinatorTest { DocumentRecord updated = recordRepo.updatedRecords.get(0); assertNull(updated.lastSuccessInstant(), - "lastSuccessInstant muss nach PROPOSAL_READY null bleiben (wird erst von M6 gesetzt)"); + "lastSuccessInstant muss nach PROPOSAL_READY null bleiben (wird erst nach der Zielkopie gesetzt)"); assertEquals(previousFailureInstant, updated.lastFailureInstant(), "lastFailureInstant muss bei PROPOSAL_READY den Vorgänger-Wert beibehalten"); } diff --git a/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/ProcessingOutcomeTransitionTest.java b/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/ProcessingOutcomeTransitionTest.java index 472d6b5..564cc79 100644 --- a/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/ProcessingOutcomeTransitionTest.java +++ b/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/service/ProcessingOutcomeTransitionTest.java @@ -262,7 +262,7 @@ class ProcessingOutcomeTransitionTest { @Test void forKnownDocument_transientError_legacyHighCounters_stillFinalise() { - // Legacy data from M4-M6 may have counters well above normal expectations. + // Legacy data may have counters well above normal expectations. // The threshold check must still apply correctly. TechnicalDocumentError outcome = new TechnicalDocumentError(candidate(), "error", null); FailureCounters existing = new FailureCounters(3, 10); // already far above limit diff --git a/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/usecase/BatchRunProcessingUseCaseTest.java b/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/usecase/BatchRunProcessingUseCaseTest.java index dcf3509..590bb0b 100644 --- a/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/usecase/BatchRunProcessingUseCaseTest.java +++ b/pdf-umbenenner-application/src/test/java/de/gecheckt/pdf/umbenenner/application/usecase/BatchRunProcessingUseCaseTest.java @@ -728,7 +728,7 @@ class BatchRunProcessingUseCaseTest { } // ------------------------------------------------------------------------- - // Batch-level M7 integration tests (real coordinator + capturing repos) + // Batch-level integration tests (real coordinator + capturing repos) // These prove that skip and finalization semantics work in the actual batch run, // not just at the coordinator unit-test level. // ------------------------------------------------------------------------- diff --git a/pdf-umbenenner-bootstrap/src/test/java/de/gecheckt/pdf/umbenenner/bootstrap/ExecutableJarSmokeTestIT.java b/pdf-umbenenner-bootstrap/src/test/java/de/gecheckt/pdf/umbenenner/bootstrap/ExecutableJarSmokeTestIT.java index 2f41635..96134a9 100644 --- a/pdf-umbenenner-bootstrap/src/test/java/de/gecheckt/pdf/umbenenner/bootstrap/ExecutableJarSmokeTestIT.java +++ b/pdf-umbenenner-bootstrap/src/test/java/de/gecheckt/pdf/umbenenner/bootstrap/ExecutableJarSmokeTestIT.java @@ -13,7 +13,7 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.*; /** - * AP-008: Executable JAR smoke tests for M1 target state verification. + * Executable JAR smoke tests verifying that the shaded JAR starts correctly. *

    * These tests verify that the shaded executable JAR can be run via {@code java -jar} * and behaves correctly for both success and invalid configuration scenarios. diff --git a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/BatchRunContext.java b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/BatchRunContext.java index c5cafc0..9708aad 100644 --- a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/BatchRunContext.java +++ b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/BatchRunContext.java @@ -19,8 +19,6 @@ import java.util.Objects; *

    * This context is independent of individual document processing and contains * no business logic. It is purely a technical container for run identity and timing. - * - * @since M2-AP-003 */ public final class BatchRunContext { diff --git a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/DocumentFingerprint.java b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/DocumentFingerprint.java index 9e9a3ab..ab88540 100644 --- a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/DocumentFingerprint.java +++ b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/DocumentFingerprint.java @@ -9,7 +9,7 @@ import java.util.Objects; * key for all subsequent persistence lookups and history entries. It is independent of * the file name, path, or any metadata — only the raw file content determines the value. *

    - * Identification semantics (M4): + * Identification semantics: *

    - * - * @since M3-AP-001 */ public sealed interface PdfExtractionResult permits PdfExtractionSuccess, PdfExtractionContentError, PdfExtractionTechnicalError { diff --git a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfExtractionSuccess.java b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfExtractionSuccess.java index 96f982e..b2a2029 100644 --- a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfExtractionSuccess.java +++ b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfExtractionSuccess.java @@ -10,7 +10,6 @@ import java.util.Objects; * * @param extractedText the full text content extracted from the PDF (non-null, may be empty string) * @param pageCount the number of pages in the PDF (non-null, validated >= 1) - * @since M3-AP-001 */ public record PdfExtractionSuccess( String extractedText, diff --git a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfExtractionTechnicalError.java b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfExtractionTechnicalError.java index fd706d9..6feb142 100644 --- a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfExtractionTechnicalError.java +++ b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfExtractionTechnicalError.java @@ -13,7 +13,6 @@ import java.util.Objects; * * @param errorMessage a description of what went wrong (non-null, non-empty) * @param cause the underlying exception, if any (may be null) - * @since M3-AP-001 */ public record PdfExtractionTechnicalError( String errorMessage, diff --git a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfPageCount.java b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfPageCount.java index 617e2e8..7d1f398 100644 --- a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfPageCount.java +++ b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/PdfPageCount.java @@ -13,8 +13,6 @@ package de.gecheckt.pdf.umbenenner.domain.model; *
  • Self-documenting: {@code PdfPageCount} is clearer than naked {@code int}
  • *
  • Future-extensible: can add validation rules per milestone without signature changes
  • * - * - * @since M3-AP-001 */ public record PdfPageCount(int value) { /** diff --git a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/RunId.java b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/RunId.java index a8ad94e..debfb37 100644 --- a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/RunId.java +++ b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/RunId.java @@ -17,8 +17,6 @@ import java.util.Objects; * RunId is intentionally simple: a non-null, immutable string value. * Implementations may choose UUID format, timestamp-based IDs, or sequential IDs. * The internal structure is opaque to consumers. - * - * @since M2-AP-003 */ public final class RunId implements Serializable { diff --git a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/SourceDocumentCandidate.java b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/SourceDocumentCandidate.java index 03b7394..0c9dd09 100644 --- a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/SourceDocumentCandidate.java +++ b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/SourceDocumentCandidate.java @@ -16,14 +16,13 @@ import java.util.Objects; * Fields: * *

    * No java.io.File or java.nio.file.Path references appear in this record. * - * @since M3-AP-001 */ public record SourceDocumentCandidate( String uniqueIdentifier, @@ -36,12 +35,12 @@ public record SourceDocumentCandidate( * Ensures all parameters are non-null and meaningful: *

    * * @param uniqueIdentifier non-null, non-empty identifier for logging and correlation - * @param fileSizeBytes must be >= 0 (may be 0; content evaluation happens in AP-004) + * @param fileSizeBytes must be >= 0 (may be 0; content evaluation happens during processing) * @param locator non-null opaque locator; only adapters interpret its value * @throws NullPointerException if uniqueIdentifier or locator is null * @throws IllegalArgumentException if uniqueIdentifier is empty or fileSizeBytes < 0 diff --git a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/SourceDocumentLocator.java b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/SourceDocumentLocator.java index fd5e1b9..f3b9905 100644 --- a/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/SourceDocumentLocator.java +++ b/pdf-umbenenner-domain/src/main/java/de/gecheckt/pdf/umbenenner/domain/model/SourceDocumentLocator.java @@ -24,8 +24,6 @@ import java.util.Objects; * Coupling: Both the scan adapter and the extraction adapter live in the same * {@code adapter-out} module and share the same encoding convention for the value. * This is an intentional intra-adapter contract, not a cross-layer concern. - * - * @since M3-AP-001 */ public record SourceDocumentLocator(String value) {