Files
regelwerk/improvements_implementation_plan.md
grok-botandCommandCodeBot e669e15e75 docs: add improvement implementation plan (Phase A-F)
Detailed plan for 15 improvements across 6 phases covering
security, stability, robustness, testability, modernization, and build.

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
2026-06-13 08:55:12 +02:00

15 KiB
Raw Permalink Blame History

Regelwerk — Implementierungsplan für DeepSeek V4 Flash

Ziel: 15 Verbesserungen in 6 Phasen. Jede Änderung ist atomar, verifizierbar und einzeln commitbar. Wichtig: Keine Änderung ohne vorheriges gitnexus_impact. Nach jedem Commit: Build + Tests + gitnexus_detect_changes.


Phase A — Sicherheit (3 Änderungen)

A1. Dangling Pointer in regelmaschine.cpp beheben

Datei: src/core/regelmaschine.cpp

Vorher:

MSMem fallMem("regelFall FallMem", 1024*1024);
gFallMemObject = &fallMem;

Nachher:

gFallMemObject = new MSMem("regelFall FallMem", 1024*1024);

Entsprechend am Ende der Funktion: Kein delete (Ownership liegt beim Global, wie gPersistParamMemObject).

Ablauf:

  1. gitnexus_impact({target: "gFallMemObject", direction: "upstream"}) — alle Zugriffsstellen identifizieren
  2. gitnexus_impact({target: "regelFaelle", direction: "upstream"}) — Caller prüfen
  3. src/core/regelmaschine.cpp öffnen, Zeile mit MSMem fallMem(...) suchen
  4. MSMem fallMem(...) durch gFallMemObject = new MSMem(...) ersetzen
  5. Alle folgenden &fallMem-Referenzen durch gFallMemObject ersetzen
  6. Build: cmake --build build -j$(sysctl -n hw.logicalcpu)
  7. Tests: ctest --test-dir build --output-on-failure
  8. Integrationstest: ./build/tests/integration_test
  9. Address Sanitizer: cmake -B build-asan -G Ninja -DBUILD_TESTS=ON -DCMAKE_CXX_FLAGS="-fsanitize=address" && cmake --build build-asan && ./build-asan/tests/integration_test
  10. gitnexus_detect_changes()
  11. Commit: fix: dangling pointer gFallMemObject → heap allocation

A2. Thread-sichere Singleton-Initialisierung

Datei: src/core/initrw.cpp

Vorher:

static bool fInit = false;
if(fInit)
    return true;
fInit = true;
// ~40 mapXxx = makeMap(...)

Nachher:

#include <mutex>

static std::once_flag initFlag;
bool alreadyDone = false;
std::call_once(initFlag, [&]() {
    alreadyDone = true;
    // ~40 mapXxx = makeMap(...)
});
if(alreadyDone) return true;

Oder einfacher: fInit durch std::atomic<bool> ersetzen und den Check+Set mit exchange machen.

Ablauf:

  1. gitnexus_impact({target: "initRegelwerk", direction: "upstream"})
  2. src/core/initrw.cpp öffnen, #include <mutex> hinzufügen
  3. static bool fInit = false → static std::atomic<bool> fInit{false}
  4. if(fInit) return true; → if(fInit.load(std::memory_order_acquire)) return true;
  5. fInit = true; → fInit.store(true, std::memory_order_release);
  6. Build + Tests + Integrationstest
  7. gitnexus_detect_changes()
  8. Commit: fix: thread-safe initialization via std::atomic<bool>

A3. strcpy-Audit — kritische Stellen entschärfen

Betroffene Dateien (priorisiert):

Datei Zeile Änderung
src/domain/class_regelbegruendung.cpp 25 strcpy(dst, src) → strncpy(dst, src, sizeof(dst)-1); dst[sizeof(dst)-1]='\0'
src/domain/class_leistungwert.cpp 40 strcpy(buf, val) → strncpy(buf, val, sizeof(buf)-1); buf[sizeof(buf)-1]='\0'
src/rw_actions/op_datum_selektor.hpp 22 strcpy(opdatum_, val) → sichern
src/rw_actions/setze_alpha_extension.hpp 33 strcpy(gop, lst→gop()) → sichern

Ablauf:

  1. gitnexus_impact({target: "class_regelbegruendung", direction: "upstream"}) für jede betroffene Klasse
  2. Jede Datei einzeln bearbeiten
  3. Vor jeder Änderung: Größe des Ziel-Puffers ermitteln (sizeof(buf) oder Member-Deklaration prüfen)
  4. strcpy(dst, src) → strncpy(dst, src, sizeof(dst)-1); dst[sizeof(dst)-1] = '\0';
  5. Nach jeder Datei: Build + Tests
  6. gitnexus_detect_changes()
  7. Commit pro Datei: fix: replace strcpy with strncpy in <filename>

Nicht anfassen: src/util/std_c_compat.hpp — nur dokumentieren, nicht ändern (wird von vielen Dateien benötigt).


Phase B — Stabilität (3 Änderungen)

B1. static → thread_local für Funktions-Caches

Datei: src/core/sys_vars.cpp

3 Stellen ändern:

  1. diagnosenErfuellt() — static ScheinPtrVector sScheine → thread_local ScheinPtrVector sScheine
  2. hatFK4012Quartal() — static ScheinPtrVector sScheine → thread_local ScheinPtrVector sScheine
  3. aktive_bht_datum_menge() — static std::vector<int> s_result → thread_local std::vector<int> s_result

Ablauf:

  1. src/core/sys_vars.cpp öffnen
  2. Drei static → thread_local ersetzen (einfaches Search & Replace)
  3. Build + Tests + Integrationstest
  4. Thread Sanitizer: cmake -B build-tsan -G Ninja -DBUILD_TESTS=ON -DCMAKE_CXX_FLAGS="-fsanitize=thread" && cmake --build build-tsan && ./build-tsan/tests/integration_test
  5. gitnexus_detect_changes()
  6. Commit: fix: function-local static caches → thread_local in sys_vars.cpp

B2. sRegelnAusfuehren atomar machen

Dateien: src/core/regelmaschine.hpp, src/core/regelmaschine.cpp

Ablauf:

  1. regelmaschine.hpp: #include <atomic> hinzufügen
  2. static bool sRegelnAusfuehren; → static std::atomic<bool> sRegelnAusfuehren{true};
  3. regelmaschine.cpp: Alle Zugriffe auf sRegelnAusfuehren prüfen:
    • Lesend: if(sRegelnAusfuehren) → if(sRegelnAusfuehren.load(std::memory_order_acquire))
    • Schreibend: sRegelnAusfuehren = val → sRegelnAusfuehren.store(val, std::memory_order_release)
  4. Build + Tests
  5. gitnexus_detect_changes()
  6. Commit: fix: sRegelnAusfuehren → std::atomic<bool>

B3. DLL-Interface mit Mutex schützen

Datei: src/core/rw_dll.cpp

Ablauf:

  1. gitnexus_impact({target: "xmlRegelWerk", direction: "upstream"}) — alle Caller
  2. gitnexus_impact({target: "RegelWerkFree", direction: "upstream"}) — alle Caller
  3. rw_dll.cpp öffnen, #include <mutex> hinzufügen
  4. File-scope: static std::mutex rwMutex; hinzufügen
  5. xmlRegelWerk(): Erste Zeile nach Variablen-Deklarationen → std::lock_guard<std::mutex> lock(rwMutex);
  6. RegelWerkFree(): Erste Zeile → std::lock_guard<std::mutex> lock(rwMutex);
  7. Build + Tests + Integrationstest
  8. gitnexus_detect_changes()
  9. Commit: fix: mutex guard for DLL interface functions

Phase C — Robustheit (2 Änderungen)

C1. Exception-Sicherheit — class_steuer.cpp:73

Datei: src/domain/class_steuer.cpp

Vorher:

catch(...) {
    Debug::logError("...");
}

Nachher:

catch(const std::exception& e) {
    Debug::logError(std::string("...") + e.what());
    return false;
}
catch(...) {
    Debug::logError("... unknown exception");
    return false;
}

Ablauf:

  1. gitnexus_impact({target: "class_steuer", direction: "upstream"})
  2. class_steuer.cpp öffnen, #include <exception> prüfen/ergänzen
  3. catch(...) durch die differenzierte Variante ersetzen
  4. Prüfen ob return false bereits vorhanden ist, sonst ergänzen
  5. Build + Tests
  6. gitnexus_detect_changes()
  7. Commit: fix: distinguish exception types in class_steuer.cpp

C2. ConfigUnion → std::variant

Datei: src/core/config.hpp (und alle Includer)

Vorher:

union ConfigUnion {
    char*   s;
    int     i;
    char    c;
    void*   p;
    double  d;
};

Nachher:

#include <variant>
using ConfigUnion = std::variant<char*, int, char, void*, double>;

Ablauf:

  1. gitnexus_impact({target: "ConfigUnion", direction: "upstream"}) — ALLE Zugriffsstellen finden (critical!)
  2. Alle Zugriffe auditieren: union.member → std::get<T>(variant)
    • .s → std::get<char*>(val) oder std::get<0>(val)
    • .i → std::get<int>(val) oder std::get<1>(val)
    • usw.
  3. Alle Zugriffe einzeln ersetzen
  4. Build — erwarte Compile-Fehler an Stellen mit .member-Zugriff, die übersehen wurden → fixen
  5. Tests
  6. gitnexus_detect_changes()
  7. Commit: refactor: ConfigUnion → std::variant

Phase D — Testbarkeit (3 strategische Änderungen)

D1. Testabdeckung: Prädikate Batch 2

Neue Datei: tests/predicates_batch2_test.cpp

Struktur (Kopie von predicates_batch1_test.cpp):

#define CATCH_CONFIG_RUNNER
#include "catch2/catch_amalgamated.hpp"
#include "mock_leistung.hpp"
// Predicate-Headers includieren

TEST_CASE("GOP_Menge_Selector", "[predicates]") {
    // Test mit MockLeistung
}

Zu testende Prädikate (10 Stück):

  1. gop_menge_selector.hpp — GOP-Mengen-Prüfung
  2. ist_element_von.hpp — Set-Membership
  3. nicht_disjunkt.hpp — Nicht-Disjunktheit
  4. pruefe_patientenalter.hpp — Altersprüfung
  5. ist_op_datum.hpp — OP-Datum-Prüfung
  6. diagnosen_erfuellt.hpp — Diagnose-Prüfung
  7. le_hat_berechtigung.hpp — LE-Berechtigung
  8. kennzeichen_ist_element_von.hpp — Kennzeichen-Prüfung
  9. hat_datum.hpp — Datums-Prüfung
  10. ist_gueltiges_datum.hpp — Gültiges-Datum-Prüfung

Ablauf:

  1. predicates_batch1_test.cpp lesen — Pattern verstehen
  2. mock_leistung.hpp lesen — MockLeistung API verstehen
  3. Jeden Predicate-Header lesen — operator() Signatur + Parameter verstehen
  4. Test-Struktur: Pro Predicate mindestens 2 Test Cases (true + false)
  5. tests/CMakeLists.txt ergänzen: add_rw_catch_test(predicates_batch2_test)
  6. Build + ./build/tests/predicates_batch2_test
  7. gitnexus_detect_changes()
  8. Commit: test: predicates batch 2 — 10 standalone Prädikate

D2. Testabdeckung: Aktionen Batch 1

Neue Datei: tests/actions_batch1_test.cpp

Zu testende Aktionen (10 Stück):

  1. leistung_hinzu_dahinter.hpp — Leistung einfügen
  2. wertaenderung.hpp — Wertänderung
  3. proz_wertaenderung.hpp — Prozentuale Wertänderung
  4. umfaerbe.hpp — Umfärben
  5. taetigkeit_umsetzen.hpp — Tätigkeit umsetzen
  6. setze_lug.hpp — LUG setzen
  7. setze_lglug.hpp — LGLUG setzen
  8. gop_hinzusetzen.hpp — GOP hinzusetzen
  9. gop_menge_hinzu.hpp — GOP-Menge hinzu
  10. setze_alpha_extension.hpp — Alpha-Extension setzen

Ablauf:

  1. actions_test.cpp lesen — Pattern verstehen
  2. mock_leistung.hpp lesen — welche Setter/Methoden existieren für Aktionen
  3. Jeden Action-Header lesen — operator() Signatur verstehen
  4. Tests schreiben (pro Action: Setup → Ausführen → Assertions auf MockLeistung)
  5. tests/CMakeLists.txt ergänzen
  6. Build + ./build/tests/actions_batch1_test
  7. gitnexus_detect_changes()
  8. Commit: test: actions batch 1 — 10 standalone Aktionen

D3. Integrationstest für sb_meth-Familie

Neue Datei: tests/sb_meth_integration_test.cpp

Ansatz: XML-Testdaten → Patientenfall::newFromXML() → regelFall() → Ergebnis-XML → Assertions

Ablauf:

  1. integration_test.cpp lesen — Pattern verstehen (XML laden, Patient erstellen, Regelwerk ausführen)
  2. Test-XML-Dateien für SB20, SB34, SB46 erstellen (minimale Testszenarien)
  3. Tests schreiben: TEST_CASE("SB20 - basic", "[integration][sb]")
  4. Erwartete Ergebnisse im Ausgabe-XML prüfen (Leistung gestrichen, umgefärbt, etc.)
  5. tests/CMakeLists.txt ergänzen
  6. Build + ./build/tests/sb_meth_integration_test
  7. gitnexus_detect_changes()
  8. Commit: test: integration tests for SB methods

Phase E — Modernisierung (3 Bereiche)

E1. Makros in rw_macros.hpp ersetzen

Datei: src/core/rw_macros.hpp

Ersetzungen (schrittweise, je ein Commit):

  1. FOR/REP → for(size_t i = s; i < n; ++i) (direkt, kein std::views::iota wegen Compiler-Support)

    • gitnexus_impact({target: "FOR", direction: "upstream"}) → alle Verwendungen finden
    • Jede Verwendung einzeln ersetzen
    • Makro am Ende entfernen
  2. RW_ARRAYSIZE → std::size

    • gitnexus_impact({target: "RW_ARRAYSIZE", direction: "upstream"})
    • RW_ARRAYSIZE(arr) → std::size(arr) (benötigt #include <iterator>)
    • Makro entfernen
  3. LL → std::int64_t

    • gitnexus_impact({target: "LL", direction: "upstream"})
    • Alle LL-Verwendungen durch std::int64_t ersetzen
    • #include <cstdint> wo nötig
  4. ALL → direkte Iterator-Paare

    • Nicht ersetzen, sondern dokumentieren dass es deprecated ist
    • Zu viele Verwendungen für einen simplen Batch

Ablauf pro Makro:

  1. Impact-Analyse
  2. Alle Verwendungen ersetzen
  3. Build — Compile-Fehler an übersehenen Stellen fixen
  4. Tests
  5. Makro-Definition entfernen
  6. gitnexus_detect_changes()
  7. Commit

E2. Tote Perl-Tools löschen

Zu löschende Dateien:

tools/make.pl
tools/clean.pl
tools/test_rw.pl
tools/rw_mr.pl
tools/gen2list.pl
tools/idstring.pl

Ablauf:

  1. git rm tools/make.pl tools/clean.pl tools/test_rw.pl tools/rw_mr.pl tools/gen2list.pl tools/idstring.pl
  2. Build — sicherstellen dass nichts fehlschlägt (diese Tools sind nicht im Build)
  3. gitnexus_detect_changes()
  4. Commit: chore: remove dead Perl build tools (hpux, borland, sybase, svn era)

E3. Tote Konfigurationen und Plattform-Guards

Teil 1 — config/kvai.ini:

git rm config/kvai.ini

Teil 2 — src/util/debug.cpp _HPUX-Guards:

  1. Zeilen mit #ifdef _HPUX / #ifndef _HPUX / #endif identifizieren (~Zeilen 20, 445)
  2. _HPUX-Block komplett entfernen (Code zwischen #ifdef und #else/#endif)
  3. Build — sicherstellen dass nichts fehlschlägt

Teil 3 — src/util/debug.cpp __WIN32__-Guards:

  1. Prüfen ob Windows noch ein Target ist (CI baut nur Linux)
  2. Wenn nicht: __WIN32__-Block entfernen
  3. Wenn doch: so belassen

Teil 4 — src/aktsource_dummies/ leeres Verzeichnis:

rmdir src/aktsource_dummies

Ablauf:

  1. Jeweils einzeln ausführen
  2. Build nach jeder Änderung
  3. gitnexus_detect_changes()
  4. Commits: chore: remove dead HP-UX platform guards etc.

Phase F — Build (1 Änderung)

F1. Toten RW_DLL-Define entfernen

Dateien: CMakeLists.txt, src/core/rw_implementation.cpp

Ablauf:

  1. CMakeLists.txt: add_compile_definitions(RW_DLL) entfernen
  2. src/core/rw_implementation.cpp: #ifdef RW_DLL-Block + Code darin prüfen — wenn DLL-spezifisch und DLL nicht mehr gebaut wird → entfernen
  3. Build — wenn Compile-Fehler durch fehlende #ifdef RW_DLL-Definitionen → prüfen ob Code noch gebraucht wird
  4. Tests
  5. gitnexus_detect_changes()
  6. Commit: chore: remove dead RW_DLL define and guards

Verifikation nach jeder Phase

# In Projekt-Root ausführen:

# 1. Build
cmake -B build -G Ninja -DBUILD_TESTS=ON
cmake --build build -j$(sysctl -n hw.logicalcpu)

# 2. Alle Tests
ctest --test-dir build --output-on-failure

# 3. Integrationstest separat
./build/tests/integration_test

# 4. Statische Analyse
cppcheck --enable=all --inconclusive src/ 2>&1 | head -50

# 5. gitnexus_detect_changes()
npx gitnexus detect-changes

Checkliste pro Änderung

  • gitnexus_impact — Blast Radius verstanden, Risiko akzeptabel
  • Code-Änderung — nur das Nötigste, existierenden Stil respektieren
  • Build — cmake --build build erfolgreich
  • Tests — ctest --test-dir build --output-on-failure alle grün
  • Integrationstest — ./build/tests/integration_test erfolgreich
  • gitnexus_detect_changes — nur erwartete Symbole betroffen
  • Commit — ein Commit pro logischer Änderung, Sprache Deutsch

Geschätzte Gesamtanzahl Commits: ~20–25

Phase Commits
A 5 (A1=1, A2=1, A3=3)
B 3
C 2
D 3
E 8 (E1=4, E2=1, E3=3)
F 1