Files
breakpilot-compliance/ai-compliance-sdk/internal/iace/tech_file_generator_fallback.go
Sharang Parnerkar 3f1444541f refactor(go/iace): split tech_file_generator, hazard_patterns, models, completeness
Split 4 oversized files (503-679 LOC each) into focused units all under 500 LOC:
- tech_file_generator.go → +_prompts, +_prompt_builder, +_fallback
- hazard_patterns_extended.go → +_extended2.go (HP074-HP102 extracted)
- models.go → +_entities.go, +_api.go (enums / DB entities / API types)
- completeness.go → +_gates.go (gate definitions extracted)

All files remain in package iace. Zero behavior changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 10:03:44 +02:00

142 lines
4.7 KiB
Go

package iace
import (
"fmt"
"strings"
)
// ============================================================================
// Fallback content (when LLM is unavailable)
// ============================================================================
func buildFallbackContent(sctx *SectionGenerationContext, sectionType string) string {
var b strings.Builder
b.WriteString("[Automatisch generiert — LLM nicht verfuegbar]\n\n")
sectionTitle := sectionDisplayName(sectionType)
b.WriteString(fmt.Sprintf("# %s\n\n", sectionTitle))
b.WriteString(fmt.Sprintf("**Maschine:** %s (%s)\n", sctx.Project.MachineName, sctx.Project.MachineType))
b.WriteString(fmt.Sprintf("**Hersteller:** %s\n", sctx.Project.Manufacturer))
if sctx.Project.Description != "" {
b.WriteString(fmt.Sprintf("**Beschreibung:** %s\n", sctx.Project.Description))
}
b.WriteString("\n")
// Section-specific data summaries
switch sectionType {
case SectionComponentList, SectionGeneralDescription, SectionDesignSpecifications:
if len(sctx.Components) > 0 {
b.WriteString("## Komponenten\n\n")
b.WriteString(fmt.Sprintf("Anzahl: %d\n\n", len(sctx.Components)))
for _, c := range sctx.Components {
safety := ""
if c.IsSafetyRelevant {
safety = " [SICHERHEITSRELEVANT]"
}
b.WriteString(fmt.Sprintf("- %s (Typ: %s)%s\n", c.Name, string(c.ComponentType), safety))
}
b.WriteString("\n")
}
case SectionRiskAssessmentReport, SectionHazardLogCombined:
b.WriteString("## Risikoueberblick\n\n")
b.WriteString(fmt.Sprintf("Anzahl Gefaehrdungen: %d\n\n", len(sctx.Hazards)))
riskCounts := countRiskLevels(sctx)
for level, count := range riskCounts {
b.WriteString(fmt.Sprintf("- %s: %d\n", level, count))
}
b.WriteString("\n")
for _, h := range sctx.Hazards {
b.WriteString(fmt.Sprintf("- **%s** (%s) — Status: %s\n", h.Name, h.Category, string(h.Status)))
}
b.WriteString("\n")
case SectionMitigationReport:
design, protective, info := groupMitigations(sctx)
total := len(design) + len(protective) + len(info)
b.WriteString("## Massnahmenueberblick\n\n")
b.WriteString(fmt.Sprintf("Gesamt: %d Massnahmen\n", total))
b.WriteString(fmt.Sprintf("- Design: %d\n- Schutzmassnahmen: %d\n- Benutzerinformation: %d\n\n", len(design), len(protective), len(info)))
writeFallbackMitigationList(&b, "Design", design)
writeFallbackMitigationList(&b, "Schutzmassnahmen", protective)
writeFallbackMitigationList(&b, "Benutzerinformation", info)
case SectionClassificationReport:
if len(sctx.Classifications) > 0 {
b.WriteString("## Klassifizierungen\n\n")
for _, c := range sctx.Classifications {
b.WriteString(fmt.Sprintf("- **%s:** %s (Risiko: %s)\n",
string(c.Regulation), c.ClassificationResult, string(c.RiskLevel)))
}
b.WriteString("\n")
}
case SectionEvidenceIndex:
b.WriteString("## Nachweisverzeichnis\n\n")
b.WriteString(fmt.Sprintf("Anzahl Nachweise: %d\n\n", len(sctx.Evidence)))
for _, e := range sctx.Evidence {
desc := e.Description
if desc == "" {
desc = "(keine Beschreibung)"
}
b.WriteString(fmt.Sprintf("- %s — %s\n", e.FileName, desc))
}
b.WriteString("\n")
default:
// Generic fallback data summary
b.WriteString(fmt.Sprintf("- Komponenten: %d\n", len(sctx.Components)))
b.WriteString(fmt.Sprintf("- Gefaehrdungen: %d\n", len(sctx.Hazards)))
b.WriteString(fmt.Sprintf("- Klassifizierungen: %d\n", len(sctx.Classifications)))
b.WriteString(fmt.Sprintf("- Nachweise: %d\n", len(sctx.Evidence)))
b.WriteString("\n")
}
b.WriteString("---\n")
b.WriteString("*Dieser Abschnitt wurde ohne LLM-Unterstuetzung erstellt und enthaelt nur eine Datenuebersicht. Bitte erneut generieren, wenn der LLM-Service verfuegbar ist.*\n")
return b.String()
}
func writeFallbackMitigationList(b *strings.Builder, title string, measures []Mitigation) {
if len(measures) == 0 {
return
}
b.WriteString(fmt.Sprintf("### %s\n\n", title))
for _, m := range measures {
b.WriteString(fmt.Sprintf("- %s [%s]\n", m.Name, string(m.Status)))
}
b.WriteString("\n")
}
// ============================================================================
// Utility helpers
// ============================================================================
func countRiskLevels(sctx *SectionGenerationContext) map[string]int {
counts := make(map[string]int)
for _, h := range sctx.Hazards {
if assessments, ok := sctx.Assessments[h.ID]; ok && len(assessments) > 0 {
latest := assessments[len(assessments)-1]
counts[string(latest.RiskLevel)]++
}
}
return counts
}
func acceptableLabel(isAcceptable bool) string {
if isAcceptable {
return "[AKZEPTABEL]"
}
return "[NICHT AKZEPTABEL]"
}
func truncateForPrompt(text string, maxLen int) string {
if len(text) <= maxLen {
return text
}
return text[:maxLen] + "..."
}