Files
Orchestrator/bahn/teamlandkarte-mcp/.kiro/specs/llm-competence-inference/tasks.md
T
ankn a5f8fb49ab Migrate all repos into monorepo context folders
Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
      Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
      Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)

Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
2026-06-30 20:39:52 +02:00

121 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Implementation Plan: LLM-Kompetenz-Inferenz Bugfix
## Übersicht
Explorativer Bugfix-Workflow: Zuerst den Bug durch Tests bestätigen, dann Preservation sicherstellen, anschließend den Fix implementieren und validieren. Die `infer_competences`-Methode wird in `VocabularyCache` ergänzt und an drei Stellen im `mcp_server.py` integriert.
## Tasks
- [x] 1. Bug-Condition Explorationstest schreiben
- **Property 1: Fault Condition** - Kompetenz-Inferenz liefert stets leere Liste
- **CRITICAL**: Dieser Test MUSS auf dem unfixierten Code FEHLSCHLAGEN das Fehlschlagen bestätigt den Bug
- **DO NOT** versuchen den Test oder den Code zu fixen wenn er fehlschlägt
- **NOTE**: Dieser Test kodiert das erwartete Verhalten er validiert den Fix wenn er nach der Implementierung besteht
- **GOAL**: Counterexamples aufdecken, die demonstrieren dass der Bug existiert
- **Scoped PBT Approach**: Property auf konkrete Fälle scopen: nicht-leerer Task-Text mit vorhandenen Kompetenzen in der DB
- Test-Datei: `tests/test_competence_inference_fault_pbt.py`
- Hypothesis-Strategie: `st.text(min_size=1)` für Task-Text, `st.lists(st.text(min_size=1), min_size=1, max_size=50)` für Kompetenzliste
- Mock `AzureOpenAIClient.chat_completion` so dass er gültiges JSON mit Kompetenzen zurückgibt
- Assertion: `infer_competences(task_text)` liefert eine nicht-leere Liste von bis zu 10 Tupeln `(name, confidence)` wobei jeder Name in der Kompetenzliste enthalten ist und `confidence` in [0.0, 1.0] liegt
- Test auf UNFIXIERTEM Code ausführen **ERWARTETES ERGEBNIS**: Test SCHLÄGT FEHL (bestätigt Bug)
- Counterexamples dokumentieren (z.B. "infer_competences('Python Backend') gibt [] zurück statt Kompetenzen")
- Task als abgeschlossen markieren wenn Test geschrieben, ausgeführt und Fehlschlag dokumentiert ist
- _Requirements: 1.1, 1.2, 1.3, 2.1, 2.2, 2.3_
- [x] 2. Preservation Property-Tests schreiben (VOR der Fix-Implementierung)
- **Property 2: Preservation** - Rollen-Inferenz und Leer-Eingaben unverändert
- **IMPORTANT**: Observation-First-Methodik befolgen
- Test-Datei: `tests/test_competence_inference_preservation_pbt.py`
- Beobachten: `infer_primary_role` liefert auf unfixiertem Code weiterhin eine Rolle mit Konfidenz
- Beobachten: Leerer Task-Text liefert auf unfixiertem Code `[]` (korrektes Verhalten)
- Beobachten: Leere Kompetenzliste in DB liefert auf unfixiertem Code `[]` (korrektes Verhalten)
- Property-Based Test 1: Für alle nicht-leeren Task-Texte liefert `infer_primary_role` weiterhin ein Tupel `(role_name, confidence)` oder `None` bei Fehler (aus Preservation Requirements)
- Property-Based Test 2: Für alle leeren Task-Texte (`st.just("")` oder `st.from_regex(r'^\s*$')`) liefert `infer_competences` stets `[]`
- Property-Based Test 3: Für leere Kompetenzliste in DB liefert `infer_competences` stets `[]`
- Tests auf UNFIXIERTEM Code ausführen **ERWARTETES ERGEBNIS**: Tests BESTEHEN (bestätigt Baseline-Verhalten)
- Task als abgeschlossen markieren wenn Tests geschrieben, ausgeführt und bestanden auf unfixiertem Code
- _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5_
- [x] 3. Fix für LLM-Kompetenz-Inferenz implementieren
- [x] 3.1 System-Prompt `_COMPETENCE_INFERENCE_SYSTEM_PROMPT` in `vocabulary.py` hinzufügen
- Modul-Level-Konstante analog zu `_ROLE_INFERENCE_SYSTEM_PROMPT`
- Prompt instruiert das LLM, aus einer Kompetenzliste bis zu 10 passende Kompetenzen für einen Task-Text auszuwählen
- Antwortformat: `{"competences": [{"name": "<name>", "confidence": <float>}]}`
- _Bug_Condition: isBugCondition(input) where task_text.strip() != "" AND len(competence_names) > 0 AND infer_competences(task_text) == []_
- _Expected_Behavior: Nicht-leere Liste von bis zu 10 (name, confidence)-Tupeln_
- _Requirements: 2.1, 2.2, 2.3_
- [x] 3.2 Methode `infer_competences` in `VocabularyCache` implementieren
- Signatur: `async def infer_competences(self, *, task_text: str, max_competences: int = 10) -> list[tuple[str, float]]`
- Kompetenzliste via `self._db.get_all_competence_names()` holen
- Bei leerer Liste oder leerem Text: `[]` zurückgeben
- LLM-Aufruf via `self._client.chat_completion(system, user)`
- JSON-Parsing, Validierung gegen DB-Kompetenzliste (nur bekannte Namen übernehmen)
- Bei Fehler (Exception, ungültiges JSON): leere Liste zurückgeben + Warning loggen
- _Bug_Condition: isBugCondition(input) where task_text.strip() != "" AND len(competence_names) > 0_
- _Expected_Behavior: expectedBehavior(result) = len(result) > 0 AND len(result) <= 10 AND all(name in competence_names for name, _ in result) AND all(0.0 <= conf <= 1.0 for _, conf in result)_
- _Preservation: Leerer Text → [], Leere DB → [], Fehler → [] + Warning_
- _Requirements: 2.1, 2.2, 2.3, 2.4, 2.5_
- [x] 3.3 LLM-Aufruf in `validate_task_requirements` integrieren
- Ersetze `inferred_comps: list[tuple[str, float]] = []` durch `inferred_comps = await vocab_cache.infer_competences(task_text=task_text)`
- _Bug_Condition: validate_task_requirements aufgerufen mit Task der beschriebenen Text hat_
- _Expected_Behavior: inferred_comps enthält bis zu 10 Kompetenzen mit Konfidenz_
- _Preservation: Rollen-Inferenz und DB-Skills bleiben unverändert_
- _Requirements: 2.1, 3.1, 3.2_
- [x] 3.4 LLM-Aufruf in `extract_requirements` integrieren
- Ersetze `inferred_competences: list[tuple[str, float]] = []` durch `inferred_competences = await vocab_cache.infer_competences(task_text=desc)`
- _Bug_Condition: extract_requirements aufgerufen mit nicht-leerem Text_
- _Expected_Behavior: inferred_competences enthält bis zu 10 Kompetenzen_
- _Requirements: 2.2_
- [x] 3.5 LLM-Aufruf in `find_matching_tasks` (Score-Modus) integrieren
- Ersetze den bestehenden `inferred_comp_names`-Block durch LLM-Inferenz mit Fallback auf DB-Skills
- `inferred_comp_tuples = await vocab_cache.infer_competences(task_text=full_text)`
- `inferred_comp_names = [name for name, _conf in inferred_comp_tuples]`
- Fallback: `if not inferred_comp_names: inferred_comp_names = [str(x) for x in (getattr(t, "skills", None) or []) if x]`
- _Bug_Condition: find_matching_tasks im Score-Modus mit Task der beschriebenen Text hat_
- _Expected_Behavior: inferred_comp_names enthält LLM-inferierte Kompetenzen für Scoring_
- _Preservation: LLM-Fulltext-Modus bleibt unverändert_
- _Requirements: 2.3, 3.3_
- [x] 3.6 Unit-Tests für `infer_competences` mit gemocktem LLM-Client
- Test gültige JSON-Antwort → korrekte Tupel-Liste
- Test leerer Task-Text → `[]`
- Test leere Kompetenzliste in DB → `[]`
- Test LLM-Fehler (Exception) → `[]` + Warning geloggt
- Test ungültige JSON-Antwort → `[]`
- Test Kompetenz-Namen die nicht in DB sind → werden herausgefiltert
- Test max_competences Begrenzung auf 10
- _Requirements: 2.1, 2.2, 2.3, 2.4, 2.5_
- [x] 3.7 Bug-Condition Explorationstest erneut ausführen Verifizieren dass er jetzt besteht
- **Property 1: Expected Behavior** - Kompetenz-Inferenz liefert Ergebnisse
- **IMPORTANT**: Den GLEICHEN Test aus Task 1 erneut ausführen KEINEN neuen Test schreiben
- Der Test aus Task 1 kodiert das erwartete Verhalten
- Wenn dieser Test besteht, bestätigt das dass das erwartete Verhalten erfüllt ist
- Bug-Condition Explorationstest aus Schritt 1 ausführen
- **ERWARTETES ERGEBNIS**: Test BESTEHT (bestätigt Bug ist behoben)
- _Requirements: 2.1, 2.2, 2.3_
- [x] 3.8 Preservation-Tests erneut ausführen Verifizieren dass sie weiterhin bestehen
- **Property 2: Preservation** - Rollen-Inferenz und Leer-Eingaben unverändert
- **IMPORTANT**: Die GLEICHEN Tests aus Task 2 erneut ausführen KEINE neuen Tests schreiben
- Preservation Property-Tests aus Schritt 2 ausführen
- **ERWARTETES ERGEBNIS**: Tests BESTEHEN (bestätigt keine Regressionen)
- Bestätigen dass alle Tests nach dem Fix weiterhin bestehen
- _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5_
- [x] 4. Checkpoint - Sicherstellen dass alle Tests bestehen
- Alle Tests ausführen und sicherstellen dass sie bestehen, bei Fragen den User konsultieren.
## Hinweise
- Property-Based Tests verwenden Hypothesis mit `@settings(max_examples=100)`.
- Unit- und Integrationstests verwenden `pytest` (Run-once, kein Watch-Modus); der `AzureOpenAIClient` wird stets gemockt.
- Die Implementierungssprache ist Python (bestehende Codebase).
- Tasks referenzieren explizit Anforderungen aus `bugfix.md` zur lückenlosen Nachverfolgbarkeit.
- Der Fix ist additiv: bestehende Funktionalität (Rollen-Inferenz, DB-Skills, LLM-Fulltext-Matching) bleibt unverändert.