feat: Add panel management, validation, and error handling to canvas

Phase 1 - Panel Management System:
- Create usePanelStore.ts for centralized panel state management
- Add PanelContainer.tsx for draggable floating panels
- Create FloatingIntrospectionPanel.tsx (persistent, doesn't disappear on node click)
- Create ResultsPanel.tsx for trial result details
- Refactor NodeConfigPanelV2 to use panel store for introspection
- Integrate PanelContainer into CanvasView

Phase 2 - Pre-run Validation:
- Create specValidator.ts with comprehensive validation rules
- Add ValidationPanel (enhanced version with error navigation)
- Add Validate button to SpecRenderer with status indicator
- Block run if validation fails
- Check for: design vars, objectives, extractors, bounds, connections

Phase 3 - Error Handling & Recovery:
- Create ErrorPanel.tsx for displaying optimization errors
- Add error classification (nx_crash, solver_fail, extractor_error, etc.)
- Add recovery suggestions based on error type
- Update status endpoint to return error info
- Add _get_study_error_info helper to check error_status.json and DB
- Integrate error detection into status polling

Documentation:
- Add CANVAS_ROBUSTNESS_PLAN.md with full implementation plan
This commit is contained in:
2026-01-21 21:35:31 -05:00
parent e1c59a51c1
commit c224b16ac3
12 changed files with 2853 additions and 29 deletions

View File

@@ -1,6 +1,6 @@
import { useState, useEffect, useCallback } from 'react';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { ClipboardList, Download, Trash2, Layers, Home, ChevronRight, Save, RefreshCw, Zap, MessageSquare, X, Folder, SlidersHorizontal, Undo2, Redo2 } from 'lucide-react';
import { ClipboardList, Download, Trash2, Layers, Home, ChevronRight, Save, RefreshCw, Zap, MessageSquare, X, Folder, SlidersHorizontal, Undo2, Redo2, CheckCircle } from 'lucide-react';
import { AtomizerCanvas } from '../components/canvas/AtomizerCanvas';
import { SpecRenderer } from '../components/canvas/SpecRenderer';
import { NodePalette } from '../components/canvas/palette/NodePalette';
@@ -10,8 +10,10 @@ import { ConfigImporter } from '../components/canvas/panels/ConfigImporter';
import { NodeConfigPanel } from '../components/canvas/panels/NodeConfigPanel';
import { NodeConfigPanelV2 } from '../components/canvas/panels/NodeConfigPanelV2';
import { ChatPanel } from '../components/canvas/panels/ChatPanel';
import { PanelContainer } from '../components/canvas/panels/PanelContainer';
import { useCanvasStore } from '../hooks/useCanvasStore';
import { useSpecStore, useSpec, useSpecLoading, useSpecIsDirty, useSelectedNodeId } from '../hooks/useSpecStore';
import { usePanelStore } from '../hooks/usePanelStore';
import { useSpecUndoRedo, useUndoRedoKeyboard } from '../hooks/useSpecUndoRedo';
import { useStudy } from '../context/StudyContext';
import { useChat } from '../hooks/useChat';
@@ -556,6 +558,9 @@ export function CanvasView() {
onImport={handleImport}
/>
{/* Floating Panels (Introspection, Validation, Error, Results) */}
{useSpecMode && <PanelContainer />}
{/* Notification Toast */}
{notification && (
<div