Responsive Gui - partially Workflow #61
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "develop"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Backend: - normalization_engine.py (200 Zeilen): Synonym-Mapping, 5 Statuswerte * normalize_decision_signal(): Kaskade (exact → case → synonym → invalid) * apply_synonym_mapping(): DB-basierte Synonyme (case-insensitive) * normalize_all_signals(): Batch-Processing gegen Katalog * load_question_catalog(): Lädt normalization_rules aus DB - workflow_executor.py (440 Zeilen): Sequenzielle Workflow-Ausführung * execute_workflow(): Traversiert DAG in topologischer Reihenfolge * execute_node(): Führt analysis nodes aus (start/end = no-op) * aggregate_results(): Kombiniert analysis_core + normalized_signals * save_execution_state(): Persistiert in workflow_executions - workflow_models.py: Erweitert um Phase 2 Models * SignalStatus Enum (valid, normalized, unclear, invalid, not_decidable) * NormalizedSignal (question_type, raw_value, normalized_value, status) * NodeExecutionState (node_id, status, analysis_core, normalized_signals) * ExecutionResult (execution_id, workflow_id, status, node_states, aggregated_result) - workflow_engine.py: Neue Funktion get_execution_order() * Flattened topological sort für sequenzielle Execution * Phase 7: Wird zu levels (parallele Execution) - prompt_executor.py: execute_workflow_prompt() Implementierung * Ruft workflow_executor.execute_workflow() auf * Konvertiert ExecutionResult zu API-Response - routers/workflows.py (230 Zeilen): Workflow Execution API * POST /api/workflows/{id}/execute (mit enable_debug) * GET /api/workflows/executions/{id} (lädt gespeicherten State) * GET /api/workflows (listet alle aktiven Workflows) * GET /api/workflows/{id} (lädt einzelnen Workflow mit Graph) - main.py: Router-Registrierung (workflows.router) Tests: - test_phase2_normalization.py (17 Tests): Alle Normalisierungs-Szenarien * Exact match, case-insensitive, synonym mapping, invalid, whitespace * Batch-Normalisierung, not_in_catalog, mixed validity - test_phase2_workflow_executor.py (10 Tests): Executor + Aggregation * aggregate_results mit verschiedenen Konstellationen * execute_node für start/end/analysis/unknown * Integration mit question_augmenter + result_container_parser Alle 27 Unit-Tests bestanden. version: 0.9k (backend) module: workflow 0.3.0 Konzept: .claude/task/Workflow_engine_prompting_engine/anforderungsanalyse_umsetzungsplan.md (Phase 2)Backend: - logic_evaluator.py (NEU, 307 Zeilen): Deterministischer Logic Evaluator - Vergleichsoperatoren: EQ, NEQ, IN, NOT_IN, GT, LT, GTE, LTE, CONTAINS - Logische Operatoren: AND, OR, NOT mit Verschachtelung - Resolve signal references (node_id.question_type) - Error handling für UNCLEAR/INVALID/NOT_DECIDABLE Signale - workflow_executor.py (ERWEITERT): - execute_logic_node(): Bedingungen evaluieren, Pfade aktivieren/deaktivieren - execute_workflow(): BFS-Traversierung mit Edge-Activation statt Sequential - _apply_fallback(): 4 Fallback-Strategien (CONSERVATIVE_SKIP, DEFAULT_PATH, UNCERTAINTY_PATH, DOCUMENT_ONLY) - _has_active_incoming_edge(): Prüft ob Node erreichbar ist - _get_edges_by_label(): Findet then/else/uncertainty Pfade - workflow_models.py (ERWEITERT): - LogicOperator.CONTAINS hinzugefügt - version.py: 0.9k → 0.9l, workflow 0.3.0 → 0.4.0 Tests: - test_phase3_logic_evaluator.py (NEU): 20 Unit Tests (alle passing) - Comparison operators (EQ, NEQ, IN, GT, LT, CONTAINS) - Logical operators (AND, OR, NOT) - Nested expressions - Error handling (missing refs, UNCLEAR/INVALID signals) - test_phase2_workflow_executor.py (AKTUALISIERT): 11 Tests (alle passing) - execute_node() graph parameter hinzugefügt (Phase 3 requirement) - test_execute_node_unknown_type: logic → join (logic jetzt implementiert) - test_phase3_workflow_branching.py (NEU): Integration Tests vorbereitet - Erfordert vollständige DB-Mock-Strategie (wird in E2E-Test nachgeholt) Phase 2 Backward Compatibility: ✅ Alle Phase 2 Tests bestehen weiterhin Konzept: .claude/task/Workflow_engine_prompting_engine/konzept_workflow_engine_konsolidated.md Anforderungsanalyse: .claude/task/Workflow_engine_prompting_engine/phase3_anforderungsanalyse.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>Behebt 5 kritische Bugs die Editor unbenutzbar machten: BUG-01: Config Panel - Close Button hinzugefügt (×) - User war im Config Panel "gefangen" - Jetzt: Click × zum Deselektieren BUG-02: Save UX - Validierungs-Feedback verbessert - Speichern-Button zeigt Lock-Icon (🔒) bei Fehlern - Tooltip erklärt warum Speichern blockiert ist - Error-Message mit Hinweis auf Validierung BUG-03: Analysis Node - Prompt-Auswahl implementiert - Dropdown zum Auswählen von Basis-Prompts - Lädt verfügbare Prompts via API - Zeigt gewählten Prompt-Namen an BUG-04: Label-Input - UX verbessert - Header zeigt "Node-Konfiguration" (nicht Label) - Input hat Placeholder und Hilfetext - "Änderungen automatisch übernommen" Hinweis BUG-05: Admin Page - "Neuer Workflow" Button - Button neben "+ Neuer Prompt" - Navigiert zu /workflow-editor/new - Workflow-Filter im Type-Filter hinzugefügt Tested: Manuell durch User (alle Bugs bestätigt gefixt) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>Debug Logs Added: - useEffect: Log ID validation and loadWorkflow calls - loadWorkflow: Log API response, graph_data, deserialization results - handleNodeUpdate: Log updates and resulting node state - handleSave: Log serialization, API calls, navigation Bug Fixes: - useEffect: Add !isNaN(parseInt(id)) check to prevent /api/prompts/NaN calls - Prompt selection: String conversion for value prop (Number vs String mismatch) - <select value={String(selectedNode.data.prompt_id)}> - <option value={String(prompt.id)}> - onChange: find with String(p.id) === promptId Issues to Debug: - Why does useEffect run with id=undefined after navigate? - Why does loadWorkflow not populate nodes/edges? - Why does prompt selection not persist? Next Step: User tests with Browser Console open, reports logsCritical Bug Fixes: 1. Prompt IDs are UUIDs (strings), NOT numbers 2. parseInt(UUID) produces wrong results: - parseInt("3b4d7d64-...") = 3 (truncates at first non-digit) - parseInt("aa291dde-...") = NaN 3. This caused: - Prompt selection: saved as NaN instead of UUID - Load workflow: GET /api/prompts/3 instead of /api/prompts/3b4d7d64-... - 405 Method Not Allowed errors Changes: - useEffect: loadWorkflow(id) instead of loadWorkflow(parseInt(id)) - Prompt onChange: prompt_id: promptId (string) instead of parseInt(promptId) - Removed NaN check (unnecessary for UUID strings) Root Cause: Backend uses UUID primary keys, frontend assumed integer IDs Testing: Console logs still active for verificationCritical Backend Bug: - Frontend calls api.getPrompt(id) → GET /api/prompts/{uuid} - Backend had NO endpoint for single prompt retrieval by ID - Result: 405 Method Not Allowed Backend Endpoints Before: ✓ GET /api/prompts - List all ✓ POST /api/prompts - Create ✓ PUT /api/prompts/{id} - Update ✗ GET /api/prompts/{id} - MISSING! Backend Endpoints After: ✓ GET /api/prompts - List all ✓ GET /api/prompts/{id} - Get single (NEW) ✓ POST /api/prompts - Create ✓ PUT /api/prompts/{id} - Update Implementation: - Added get_prompt(prompt_id: str) function - Returns single prompt by UUID - 404 if not found - Requires auth (admin or user) This fixes: - Workflow loading after save (loadWorkflow calls getPrompt) - Workflow editing from admin list (Edit button calls getPrompt) - All 405 Method Not Allowed errors Root Cause: Backend was incomplete, missing basic CRUD read-by-id endpointBug: - Analysis nodes showed "Prompt #7edc6d6b-6cd5..." in canvas - After re-selecting prompt, showed readable name "Pipeline: Ernährungs-Analyse" - After loading workflow, showed UUID again Root Cause: - Serializer saved only prompt_id, not prompt_name - Deserializer expected prompt_name but got null - AnalysisNode fallback logic: data.prompt_name || `Prompt #{prompt_id}` - Result: Showed UUID as fallback Fix: - workflowSerializer.js line 25: Added prompt_name to serialization - Now saves both prompt_id AND prompt_name in graph_data - On load: prompt_name is restored → AnalysisNode shows readable name Testing: - Create workflow with analysis node + prompt selection - Save → Canvas should show "Pipeline: Körper-Analyse" (not UUID) - Reload → Canvas should still show readable name (not UUID)Backend: - workflow_models.py: EndNodeOutputMode enum (AUTO, TEMPLATE) - workflow_executor.py: execute_end_node() with Jinja2 rendering - Template Context: {{node_id.analysis_core}}, {{node_id.decision_signals.key}} - Conditional Rendering: {% if node_id %} for optional paths - AUTO Mode: Backward compatible (concatenates all analyses) - TEMPLATE Mode: Custom Jinja2 templates with placeholders Features: - Access node results: {{node_id.analysis_core}} - Access signals: {{node_id.decision_signals.relevanz}} - Optional paths: {% if node_id %}...{% endif %} - Default values: {{node_id|default("N/A")}} Version: 0.9n Module: workflow 0.6.0 Konzept: konzept_workflow_engine_konsolidated.md (Section 11) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>