M8 komplett umgesetzt

This commit is contained in:
2026-04-08 16:30:13 +02:00
parent a3f47ba560
commit d61316c699
21 changed files with 2377 additions and 89 deletions
@@ -85,30 +85,6 @@ public class AiRequestComposer {
Objects.requireNonNull(promptContent, "promptContent must not be null");
Objects.requireNonNull(documentText, "documentText must not be null");
// The complete request text is composed in a fixed, deterministic order:
// 1. Prompt content (instruction)
// 2. Newline separator
// 3. Prompt identifier marker (for traceability)
// 4. Newline separator
// 5. Document text section marker
// 6. Newline separator
// 7. Document text content
// 8. Newline separator
// 9. Response format specification (JSON-only with required fields)
//
// This order is fixed so that another implementation knows exactly where
// each part is positioned and what to expect.
StringBuilder requestBuilder = new StringBuilder();
requestBuilder.append(promptContent);
requestBuilder.append("\n");
requestBuilder.append("--- Prompt-ID: ").append(promptIdentifier.identifier()).append(" ---");
requestBuilder.append("\n");
requestBuilder.append("--- Document Text ---");
requestBuilder.append("\n");
requestBuilder.append(documentText);
requestBuilder.append("\n");
appendJsonResponseFormat(requestBuilder);
// Record the exact character count of the document text that was included.
// This is the length of the document text (not the complete request).
int sentCharacterCount = documentText.length();
@@ -393,10 +393,10 @@ public class DefaultBatchRunProcessingUseCase implements BatchRunProcessingUseCa
private void logProcessingOutcome(SourceDocumentCandidate candidate, DocumentProcessingOutcome outcome) {
switch (outcome) {
case de.gecheckt.pdf.umbenenner.domain.model.PreCheckFailed failed ->
logger.info("Pre-checks FAILED for '{}': {} (Deterministic content error).",
logger.info("Pre-checks failed for '{}': {} (deterministic content error).",
candidate.uniqueIdentifier(), failed.failureReasonDescription());
case de.gecheckt.pdf.umbenenner.domain.model.TechnicalDocumentError technicalError ->
logger.warn("Processing FAILED for '{}': {} (Technical error retryable).",
logger.warn("Processing failed for '{}': {} (transient technical error retryable).",
candidate.uniqueIdentifier(), technicalError.errorMessage());
case de.gecheckt.pdf.umbenenner.domain.model.NamingProposalReady ready ->
logger.info("AI naming proposal ready for '{}': title='{}', date={}.",
@@ -404,10 +404,10 @@ public class DefaultBatchRunProcessingUseCase implements BatchRunProcessingUseCa
ready.proposal().validatedTitle(),
ready.proposal().resolvedDate());
case de.gecheckt.pdf.umbenenner.domain.model.AiTechnicalFailure aiTechnical ->
logger.warn("AI technical failure for '{}': {} (Transient retryable).",
logger.warn("AI invocation failed for '{}': {} (transient technical error retryable).",
candidate.uniqueIdentifier(), aiTechnical.errorMessage());
case de.gecheckt.pdf.umbenenner.domain.model.AiFunctionalFailure aiFunctional ->
logger.info("AI functional failure for '{}': {} (Deterministic content error).",
logger.info("AI naming failed for '{}': {} (deterministic content error).",
candidate.uniqueIdentifier(), aiFunctional.errorMessage());
default -> { /* other outcomes are handled elsewhere */ }
}