docs: Archive stale docs and create Atomizer-HQ agent documentation
Archive Management: - Moved RALPH_LOOP, CANVAS, and dashboard implementation plans to archive/review/ for CEO review - Moved completed restructuring plan and protocol v1 to archive/historical/ - Moved old session summaries to archive/review/ New HQ Documentation (docs/hq/): - README.md: Overview of Atomizer-HQ multi-agent optimization team - PROJECT_STRUCTURE.md: Standard KB-integrated project layout with Hydrotech reference - KB_CONVENTIONS.md: Knowledge Base accumulation principles with generation tracking - AGENT_WORKFLOWS.md: Project lifecycle phases and agent handoffs (OP_09 integration) - STUDY_CONVENTIONS.md: Technical study execution standards and atomizer_spec.json format Index Update: - Reorganized docs/00_INDEX.md with HQ docs prominent - Updated structure to reflect new agent-focused organization - Maintained core documentation access for engineers No files deleted, only moved to appropriate archive locations.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,297 +0,0 @@
|
||||
# Study Interview Mode - Implementation TODO
|
||||
|
||||
**Created**: 2026-01-02
|
||||
**Source**: [ATOMIZER_STUDY_INTERVIEW_MODE_IMPLEMENTATION_PLAN.md](ATOMIZER_STUDY_INTERVIEW_MODE_IMPLEMENTATION_PLAN.md)
|
||||
**Status**: COMPLETE - All Tasks Done
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This document tracks the Interview Mode implementation. **All core components have been implemented and tests pass (129/129).**
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Foundation - COMPLETE
|
||||
|
||||
### 1.1 Directory Structure Setup
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
**Files Created**:
|
||||
```
|
||||
optimization_engine/interview/
|
||||
├── __init__.py
|
||||
├── study_interview.py
|
||||
├── question_engine.py
|
||||
├── interview_state.py
|
||||
├── interview_presenter.py
|
||||
├── interview_intelligence.py
|
||||
├── engineering_validator.py
|
||||
├── study_blueprint.py
|
||||
└── schemas/
|
||||
├── interview_questions.json
|
||||
├── materials_database.json
|
||||
└── anti_patterns.json
|
||||
|
||||
tests/interview/
|
||||
├── __init__.py
|
||||
├── test_interview_state.py
|
||||
├── test_question_engine.py
|
||||
├── test_interview_presenter.py
|
||||
├── test_engineering_validator.py
|
||||
├── test_study_blueprint.py
|
||||
└── test_study_interview.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1.2 InterviewState Dataclass
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Implemented in `interview_state.py`:
|
||||
- InterviewState dataclass with all fields
|
||||
- JSON serialization (to_json(), from_json())
|
||||
- InterviewPhase enum with transitions
|
||||
- Helper methods: is_complete(), progress_percentage(), add_warning(), etc.
|
||||
- AnsweredQuestion and LogEntry dataclasses
|
||||
|
||||
---
|
||||
|
||||
### 1.3 InterviewStateManager
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Implemented in `interview_state.py`:
|
||||
- Directory creation (.interview/, .interview/backups/)
|
||||
- Atomic save with backup rotation
|
||||
- Lock file mechanism
|
||||
- Log file appending (INTERVIEW_LOG.md)
|
||||
- History tracking
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Question Engine - COMPLETE
|
||||
|
||||
### 2.1 Question Schema
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Created `schemas/interview_questions.json`:
|
||||
- 17 questions across 7 categories
|
||||
- Conditional logic definitions
|
||||
- Dynamic option population support
|
||||
- Engineering guidance per question
|
||||
|
||||
---
|
||||
|
||||
### 2.2 QuestionEngine
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Implemented in `question_engine.py`:
|
||||
- Schema loading and parsing
|
||||
- Conditional evaluation (and/or/not/equals/contains/introspection_has)
|
||||
- Dynamic option population from introspection
|
||||
- Answer validation
|
||||
- Category ordering
|
||||
|
||||
---
|
||||
|
||||
### 2.3 Interview Presenters
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Implemented in `interview_presenter.py`:
|
||||
- InterviewPresenter abstract base class
|
||||
- ClaudePresenter (markdown formatting)
|
||||
- DashboardPresenter (JSON events)
|
||||
- CLIPresenter (plain text)
|
||||
- Response parsing for all question types
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Intelligence Layer - COMPLETE
|
||||
|
||||
### 3.1 ExtractorMapper
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Implemented in `interview_intelligence.py`:
|
||||
- GOAL_MAP for goal-to-extractor mapping
|
||||
- Support for all extractors E1-E10
|
||||
- Auto-assignment based on optimization goal
|
||||
|
||||
---
|
||||
|
||||
### 3.2 Materials Database
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Created `schemas/materials_database.json`:
|
||||
- 12 common engineering materials
|
||||
- Properties: yield stress, ultimate stress, density, modulus
|
||||
- Safety factors by application
|
||||
- Fuzzy name matching implemented
|
||||
|
||||
---
|
||||
|
||||
### 3.3 Anti-Pattern Detector
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Created `schemas/anti_patterns.json` and implemented in `engineering_validator.py`:
|
||||
- 12 anti-pattern definitions
|
||||
- Severity levels (error, warning, info)
|
||||
- Fix suggestions
|
||||
- Pattern detection logic
|
||||
|
||||
---
|
||||
|
||||
### 3.4 Engineering Validator
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Implemented in `engineering_validator.py`:
|
||||
- MaterialsDatabase class with fuzzy matching
|
||||
- AntiPatternDetector class
|
||||
- EngineeringValidator combining both
|
||||
- Constraint validation (stress, displacement, frequency)
|
||||
- Bounds suggestion
|
||||
|
||||
---
|
||||
|
||||
### 3.5 Interview Intelligence
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Implemented in `interview_intelligence.py`:
|
||||
- Complexity determination (simple/moderate/complex)
|
||||
- Question estimation
|
||||
- Recommended settings generation
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Blueprint & Generation - COMPLETE
|
||||
|
||||
### 4.1 StudyBlueprint
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Implemented in `study_blueprint.py`:
|
||||
- DesignVariable, Objective, Constraint dataclasses
|
||||
- StudyBlueprint with all configuration
|
||||
- to_config_json() for optimization_config.json format
|
||||
- to_markdown() for summary display
|
||||
- Validation methods
|
||||
|
||||
---
|
||||
|
||||
### 4.2 BlueprintBuilder
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Implemented in `study_blueprint.py`:
|
||||
- from_interview_state() method
|
||||
- Automatic extractor assignment
|
||||
- Trial count calculation
|
||||
- Sampler selection
|
||||
|
||||
---
|
||||
|
||||
### 4.3 StudyInterviewEngine
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Implemented in `study_interview.py`:
|
||||
- Main orchestrator class
|
||||
- start_interview() with resume support
|
||||
- get_first_question() / process_answer() flow
|
||||
- Warning acknowledgment
|
||||
- Blueprint generation and modification
|
||||
- State persistence
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Integration - COMPLETE
|
||||
|
||||
### 5.1 Skill File
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Created `.claude/skills/modules/study-interview-mode.md`:
|
||||
- Usage documentation
|
||||
- Example conversation
|
||||
- Integration guide
|
||||
|
||||
---
|
||||
|
||||
### 5.2 Protocol Updates
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Completed:
|
||||
- [x] Update OP_01_CREATE_STUDY.md with interview phase
|
||||
- [x] Update 00_BOOTSTRAP.md task routing
|
||||
- [x] Update CLAUDE.md with interview instructions
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Testing - COMPLETE
|
||||
|
||||
### 6.1 Unit Tests
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
All tests pass: **129/129**
|
||||
|
||||
Test files created:
|
||||
- test_interview_state.py (23 tests)
|
||||
- test_question_engine.py (20 tests)
|
||||
- test_interview_presenter.py (16 tests)
|
||||
- test_engineering_validator.py (32 tests)
|
||||
- test_study_blueprint.py (22 tests)
|
||||
- test_study_interview.py (16 tests)
|
||||
|
||||
---
|
||||
|
||||
### 6.2 Integration Tests
|
||||
**Status**: `[x]` COMPLETE
|
||||
|
||||
Integration tests in test_study_interview.py:
|
||||
- Full interview flow
|
||||
- Resume functionality
|
||||
- Blueprint generation
|
||||
- Warning handling
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Phase | Status | Completion |
|
||||
|-------|--------|------------|
|
||||
| 1. Foundation | COMPLETE | 100% |
|
||||
| 2. Question Engine | COMPLETE | 100% |
|
||||
| 3. Intelligence | COMPLETE | 100% |
|
||||
| 4. Blueprint | COMPLETE | 100% |
|
||||
| 5. Integration | COMPLETE | 100% |
|
||||
| 6. Testing | COMPLETE | 100% |
|
||||
|
||||
**Overall**: 100% Complete
|
||||
|
||||
**All Tasks Done**:
|
||||
- [x] All 129 tests passing
|
||||
- [x] All protocol updates complete
|
||||
- [x] Skill file created
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
```python
|
||||
from optimization_engine.interview import StudyInterviewEngine
|
||||
|
||||
# Create engine
|
||||
engine = StudyInterviewEngine(study_path)
|
||||
|
||||
# Start interview
|
||||
session = engine.start_interview("my_study", introspection=introspection_data)
|
||||
|
||||
# Get first question
|
||||
action = engine.get_first_question()
|
||||
print(action.message)
|
||||
|
||||
# Process answers in loop
|
||||
while action.action_type == "ask_question":
|
||||
user_response = input()
|
||||
action = engine.process_answer(user_response)
|
||||
|
||||
# When complete
|
||||
if action.action_type == "show_summary":
|
||||
blueprint = action.blueprint
|
||||
config = blueprint.to_config_json()
|
||||
```
|
||||
@@ -1,312 +0,0 @@
|
||||
# Canvas Deep Fix Investigation
|
||||
|
||||
**Date**: January 16, 2026
|
||||
**Status**: ✅ IMPLEMENTATION COMPLETE
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Four critical issues have been identified that are blocking Canvas functionality:
|
||||
|
||||
| # | Issue | Root Cause | Severity |
|
||||
|---|-------|------------|----------|
|
||||
| 1 | Claude Chat Not Working | `asyncio.create_subprocess_exec` fails on Windows | CRITICAL |
|
||||
| 2 | Expressions Can't Connect to Model | ModelNode has `inputs={0}` - no input handle | CRITICAL |
|
||||
| 3 | File Browser Only Shows Studies | Web API can't access OS file system | HIGH |
|
||||
| 4 | Introspection is Fake | Only reads config files, not actual NX models | HIGH |
|
||||
|
||||
---
|
||||
|
||||
## Issue 1: Claude Chat NotImplementedError
|
||||
|
||||
### Root Cause
|
||||
```python
|
||||
# session_manager.py line 138
|
||||
process = await asyncio.create_subprocess_exec(...)
|
||||
```
|
||||
|
||||
On Windows, `asyncio.create_subprocess_exec` raises `NotImplementedError` because Windows doesn't support the ProactorEventLoop subprocess methods the same way Unix does.
|
||||
|
||||
### Evidence
|
||||
```
|
||||
Traceback:
|
||||
File "session_manager.py", line 138, in create_session
|
||||
process = await asyncio.create_subprocess_exec(
|
||||
File "asyncio\subprocess.py", line 218, in create_subprocess_exec
|
||||
File "asyncio\base_events.py", line 498, in _make_subprocess_transport
|
||||
raise NotImplementedError
|
||||
NotImplementedError
|
||||
```
|
||||
|
||||
### Solution
|
||||
Replace async subprocess with synchronous subprocess + ThreadPoolExecutor:
|
||||
|
||||
```python
|
||||
import subprocess
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
executor = ThreadPoolExecutor(max_workers=4)
|
||||
|
||||
async def create_session(...):
|
||||
# Instead of asyncio.create_subprocess_exec
|
||||
loop = asyncio.get_event_loop()
|
||||
process = await loop.run_in_executor(
|
||||
executor,
|
||||
lambda: subprocess.Popen(
|
||||
["claude", "--print", ...],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
cwd=str(ATOMIZER_ROOT),
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
**OR** - Simpler approach: Skip session-based subprocess entirely, use HTTP streaming for chat:
|
||||
|
||||
The `/api/claude/chat/stream` endpoint already works (it uses `claude_cli_agent.py` which runs Claude one-shot). The WebSocket session approach is over-engineered for the use case.
|
||||
|
||||
### Fix Strategy
|
||||
1. Make `create_session` return a "virtual" session (no subprocess)
|
||||
2. Route all messages through HTTP streaming endpoint
|
||||
3. Keep conversation history in `ConversationStore` database
|
||||
4. WebSocket just wraps the HTTP streaming calls
|
||||
|
||||
---
|
||||
|
||||
## Issue 2: Expressions Can't Connect to Model
|
||||
|
||||
### Root Cause
|
||||
|
||||
**ModelNode.tsx:**
|
||||
```tsx
|
||||
<BaseNode {...props} icon={...} iconColor="text-blue-400" inputs={0}>
|
||||
```
|
||||
`inputs={0}` means Model has **NO input handle** - nothing can connect TO it!
|
||||
|
||||
**DesignVarNode.tsx:**
|
||||
```tsx
|
||||
<BaseNode {...props} icon={...} iconColor="text-emerald-400">
|
||||
```
|
||||
Uses defaults (`inputs=1, outputs=1`) but DesignVar should have:
|
||||
- `inputs=0` (it's a source node)
|
||||
- `outputs=1` (connects to Model)
|
||||
|
||||
### Visual Problem
|
||||
```
|
||||
Current (WRONG):
|
||||
DesignVar ←─ Model ──→ Solver
|
||||
↑ ↓
|
||||
(has input) (has output only)
|
||||
|
||||
Should be:
|
||||
DesignVar ──→ Model ──→ Solver
|
||||
↓ ↑↓
|
||||
(output) (input & output)
|
||||
```
|
||||
|
||||
### Fix Required
|
||||
|
||||
**ModelNode.tsx** - Add input handle:
|
||||
```tsx
|
||||
<BaseNode {...props} icon={...} iconColor="text-blue-400" inputs={1} outputs={1}>
|
||||
```
|
||||
|
||||
**DesignVarNode.tsx** - Remove input handle:
|
||||
```tsx
|
||||
<BaseNode {...props} icon={...} iconColor="text-emerald-400" inputs={0} outputs={1}>
|
||||
```
|
||||
|
||||
**SurrogateNode.tsx** - Should be terminal (no output):
|
||||
```tsx
|
||||
<BaseNode {...props} icon={...} iconColor="text-pink-400" inputs={1} outputs={0}>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Issue 3: File Browser Only Shows Studies Folder
|
||||
|
||||
### Root Cause
|
||||
The current `FileBrowser.tsx` uses fetch to `/api/files/list` which only lists files within the `studies/` directory. The user wants:
|
||||
|
||||
1. Native OS file picker to select files from ANYWHERE
|
||||
2. Import selected files into the study folder
|
||||
3. Copy all related files (.prt, .sim, .fem, _i.prt, etc.)
|
||||
|
||||
### Web Browser Limitation
|
||||
Browsers can't access the local file system directly for security. Options:
|
||||
|
||||
**Option A: File System Access API** (Chrome/Edge only)
|
||||
```typescript
|
||||
const handle = await window.showOpenFilePicker({
|
||||
types: [{ description: 'NX Files', accept: { '*/*': ['.sim', '.prt', '.fem'] } }]
|
||||
});
|
||||
const file = await handle.getFile();
|
||||
// Upload to backend
|
||||
```
|
||||
|
||||
**Option B: Traditional File Input**
|
||||
```tsx
|
||||
<input type="file" accept=".sim,.prt,.fem,.afem" onChange={handleFileUpload} />
|
||||
```
|
||||
Then upload to backend which saves to study folder.
|
||||
|
||||
**Option C: Backend Path Input + Validation**
|
||||
User enters full Windows path (e.g., `C:\NX_Models\bracket.prt`), backend validates and copies.
|
||||
|
||||
### Recommended Solution
|
||||
Combine B + C:
|
||||
1. File input for direct upload (drag & drop)
|
||||
2. Path input for network drives/existing paths
|
||||
3. Backend endpoint to copy/import files
|
||||
|
||||
---
|
||||
|
||||
## Issue 4: Introspection is Fake
|
||||
|
||||
### Root Cause
|
||||
Current `nx_introspection.py` does NOT actually read NX files. It only:
|
||||
- Reads `optimization_config.json` for existing design variables
|
||||
- Infers expressions based on folder names ("mirror" → suggest mirror expressions)
|
||||
- Guesses solver type from file names
|
||||
|
||||
### What Real Introspection Needs
|
||||
|
||||
**For .prt files (NX Part):**
|
||||
- Use NX Open API to read expressions
|
||||
- Get expression names, values, units, formulas
|
||||
- Requires NX to be installed and licensed
|
||||
|
||||
**For .sim files (Simulation):**
|
||||
- Parse XML-like structure or use NX Open
|
||||
- Get solver type, boundary conditions, loads
|
||||
- Identify linked .fem and .prt files
|
||||
|
||||
**For .fem files (FEM):**
|
||||
- Get mesh statistics (nodes, elements)
|
||||
- Material properties
|
||||
- Element types used
|
||||
|
||||
**For .op2 files (Results):**
|
||||
- Use PyNastran to read binary results
|
||||
- Extract displacement, stress, frequency data
|
||||
- Get node/element IDs for specific extractions
|
||||
|
||||
### Implementation Approach
|
||||
|
||||
**Phase 1: File Discovery (no NX needed)**
|
||||
```python
|
||||
def discover_related_files(sim_path: Path) -> List[Dict]:
|
||||
"""Find all related files by naming convention"""
|
||||
# model_sim1.sim → model.prt, model_fem1.fem, model_fem1_i.prt
|
||||
```
|
||||
|
||||
**Phase 2: Config-based Expression Discovery**
|
||||
```python
|
||||
def discover_expressions_from_config(study_dir: Path) -> List[Dict]:
|
||||
"""Read optimization_config.json for design variables"""
|
||||
```
|
||||
|
||||
**Phase 3: NX Open Integration (requires NX)**
|
||||
```python
|
||||
def introspect_with_nx_open(prt_path: Path) -> Dict:
|
||||
"""Use NX Open API to read actual expressions"""
|
||||
# This requires NX to be running
|
||||
# Use the existing nx_journals/ infrastructure
|
||||
```
|
||||
|
||||
**Phase 4: OP2 Result Analysis (PyNastran)**
|
||||
```python
|
||||
def analyze_op2_results(op2_path: Path) -> Dict:
|
||||
"""Read OP2 file to discover available result types"""
|
||||
from pyNastran.op2.op2 import OP2
|
||||
op2 = OP2()
|
||||
op2.read_op2(str(op2_path))
|
||||
# Return available subcases, result types, etc.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: Fix Claude Chat (CRITICAL - 30 min)
|
||||
1. Modify `create_session` to not spawn subprocess
|
||||
2. Keep session metadata in database only
|
||||
3. Route all messages through HTTP streaming
|
||||
4. WebSocket wraps HTTP calls
|
||||
|
||||
### Phase 2: Fix Node Handles (CRITICAL - 15 min)
|
||||
1. Update `ModelNode.tsx`: `inputs={1}`
|
||||
2. Update `DesignVarNode.tsx`: `inputs={0}, outputs={1}`
|
||||
3. Update `SurrogateNode.tsx`: `outputs={0}`
|
||||
4. Test connections work correctly
|
||||
|
||||
### Phase 3: Native File Import (HIGH - 45 min)
|
||||
1. Add file upload input to FileBrowser
|
||||
2. Create backend `/api/files/upload` endpoint
|
||||
3. Add path input with validation
|
||||
4. Create `/api/files/import` for path-based import
|
||||
5. Copy all related files to study folder
|
||||
|
||||
### Phase 4: Real Introspection Service (HIGH - 2 hours)
|
||||
1. File discovery by naming convention
|
||||
2. OP2 analysis with PyNastran
|
||||
3. NX Open integration (optional, requires NX running)
|
||||
4. Return comprehensive file metadata
|
||||
|
||||
### Phase 5: Integration Testing (30 min)
|
||||
1. Test complete workflow: Select model → Introspect → Add Design Vars → Connect → Execute
|
||||
2. Fix any remaining issues
|
||||
|
||||
---
|
||||
|
||||
## Files to Modify
|
||||
|
||||
### Backend
|
||||
- `session_manager.py` - Fix Windows subprocess issue
|
||||
- `files.py` - Add upload/import endpoints
|
||||
- `nx_introspection.py` - Real introspection logic
|
||||
|
||||
### Frontend
|
||||
- `ModelNode.tsx` - Add input handle
|
||||
- `DesignVarNode.tsx` - Remove input, keep output
|
||||
- `SurrogateNode.tsx` - Remove output
|
||||
- `FileBrowser.tsx` - Add file upload, path input
|
||||
- `IntrospectionPanel.tsx` - Display real introspection data
|
||||
|
||||
---
|
||||
|
||||
## Estimated Total Time: 4-5 hours
|
||||
|
||||
---
|
||||
|
||||
## Implementation Summary (Completed)
|
||||
|
||||
### Phase 1: Claude Chat Windows Fix ✅
|
||||
**File**: `atomizer-dashboard/backend/api/services/session_manager.py`
|
||||
- Replaced `asyncio.create_subprocess_exec` with `subprocess.Popen`
|
||||
- Used `ThreadPoolExecutor` with `run_in_executor()` for async compatibility
|
||||
- Made sessions stateless (no persistent subprocess)
|
||||
- Each message handled via one-shot CLI call with 5-minute timeout
|
||||
|
||||
### Phase 2: Node Handles ✅
|
||||
**Files**:
|
||||
- `ModelNode.tsx`: Changed `inputs={0}` to `inputs={1}` (now accepts connections)
|
||||
- `DesignVarNode.tsx`: Added `inputs={0} outputs={1}` (source node)
|
||||
|
||||
### Phase 3: Native File Import ✅
|
||||
**Files**:
|
||||
- `files.py`: Added `/validate-path`, `/import-from-path`, `/upload` endpoints
|
||||
- `FileBrowser.tsx`: Complete rewrite with 3 tabs:
|
||||
- Browse Studies (existing)
|
||||
- Import Path (paste Windows path, validate, import related files)
|
||||
- Upload Files (drag & drop)
|
||||
|
||||
### Phase 4: Real NX Introspection ✅
|
||||
**File**: `atomizer-dashboard/backend/api/services/nx_introspection.py`
|
||||
- Added PyNastran OP2 parsing (displacements, eigenvectors, stress)
|
||||
- BDF/DAT file analysis (mass, grid count, element counts, solver type)
|
||||
- Study database queries for expression discovery
|
||||
- Related file discovery by naming convention
|
||||
- Result file discovery with trial folder detection
|
||||
@@ -1,438 +0,0 @@
|
||||
# Canvas Builder Robustness & Enhancement Plan
|
||||
|
||||
**Created**: January 21, 2026
|
||||
**Branch**: `feature/studio-enhancement`
|
||||
**Status**: Planning
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This plan addresses critical issues and enhancements to make the Canvas Builder robust and production-ready:
|
||||
|
||||
1. **Panel Management** - Panels (Introspection, Config, Chat) disappear unexpectedly
|
||||
2. **Pre-run Validation** - No validation before starting optimization
|
||||
3. **Error Handling** - Poor feedback when things go wrong
|
||||
4. **Live Updates** - Polling is inefficient; need WebSocket
|
||||
5. **Visualization** - No convergence charts or progress indicators
|
||||
6. **Testing** - No automated tests for critical flows
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Panel Management System (HIGH PRIORITY)
|
||||
|
||||
### Problem
|
||||
- IntrospectionPanel disappears when user clicks elsewhere on canvas
|
||||
- Panel state is lost (e.g., introspection results, expanded sections)
|
||||
- No way to have multiple panels open simultaneously
|
||||
- Chat panel and Config panel are mutually exclusive
|
||||
|
||||
### Root Cause
|
||||
```typescript
|
||||
// Current: Local state in ModelNodeConfig (NodeConfigPanelV2.tsx:275)
|
||||
const [showIntrospection, setShowIntrospection] = useState(false);
|
||||
|
||||
// When selectedNodeId changes, ModelNodeConfig unmounts, losing state
|
||||
```
|
||||
|
||||
### Solution: Centralized Panel Store
|
||||
|
||||
Create `usePanelStore.ts` - a Zustand store for panel management:
|
||||
|
||||
```typescript
|
||||
// atomizer-dashboard/frontend/src/hooks/usePanelStore.ts
|
||||
|
||||
interface PanelState {
|
||||
// Panel visibility
|
||||
panels: {
|
||||
introspection: { open: boolean; filePath?: string; data?: IntrospectionResult };
|
||||
config: { open: boolean; nodeId?: string };
|
||||
chat: { open: boolean; powerMode: boolean };
|
||||
validation: { open: boolean; errors?: ValidationError[] };
|
||||
results: { open: boolean; trialId?: number };
|
||||
};
|
||||
|
||||
// Actions
|
||||
openPanel: (panel: PanelName, data?: any) => void;
|
||||
closePanel: (panel: PanelName) => void;
|
||||
togglePanel: (panel: PanelName) => void;
|
||||
|
||||
// Panel data persistence
|
||||
setIntrospectionData: (data: IntrospectionResult) => void;
|
||||
clearIntrospectionData: () => void;
|
||||
}
|
||||
```
|
||||
|
||||
### Implementation Tasks
|
||||
|
||||
| Task | File | Description |
|
||||
|------|------|-------------|
|
||||
| 1.1 | `usePanelStore.ts` | Create Zustand store for panel state |
|
||||
| 1.2 | `PanelContainer.tsx` | Create container that renders open panels |
|
||||
| 1.3 | `IntrospectionPanel.tsx` | Refactor to use store instead of local state |
|
||||
| 1.4 | `NodeConfigPanelV2.tsx` | Remove local panel state, use store |
|
||||
| 1.5 | `CanvasView.tsx` | Integrate PanelContainer, remove chat panel logic |
|
||||
| 1.6 | `SpecRenderer.tsx` | Add panel trigger buttons (introspect, validate) |
|
||||
|
||||
### UI Changes
|
||||
|
||||
**Before:**
|
||||
```
|
||||
[Canvas] [Config Panel OR Chat Panel]
|
||||
↑ mutually exclusive
|
||||
```
|
||||
|
||||
**After:**
|
||||
```
|
||||
[Canvas] [Right Panel Area]
|
||||
├── Config Panel (pinnable)
|
||||
├── Chat Panel (collapsible)
|
||||
└── Floating Panels:
|
||||
├── Introspection (draggable, persistent)
|
||||
├── Validation Results
|
||||
└── Trial Details
|
||||
```
|
||||
|
||||
### Panel Behaviors
|
||||
|
||||
| Panel | Trigger | Persistence | Position |
|
||||
|-------|---------|-------------|----------|
|
||||
| **Config** | Node click | While node selected | Right sidebar |
|
||||
| **Chat** | Toggle button | Always available | Right sidebar (below config) |
|
||||
| **Introspection** | "Introspect" button | Until explicitly closed | Floating, draggable |
|
||||
| **Validation** | "Validate" or pre-run | Until fixed or dismissed | Floating |
|
||||
| **Results** | Click on result badge | Until dismissed | Floating |
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Pre-run Validation (HIGH PRIORITY)
|
||||
|
||||
### Problem
|
||||
- User can click "Run" with incomplete spec
|
||||
- No feedback about missing extractors, objectives, or connections
|
||||
- Optimization fails silently or with cryptic errors
|
||||
|
||||
### Solution: Validation Pipeline
|
||||
|
||||
```typescript
|
||||
// Types of validation
|
||||
interface ValidationResult {
|
||||
valid: boolean;
|
||||
errors: ValidationError[]; // Must fix before running
|
||||
warnings: ValidationWarning[]; // Can proceed but risky
|
||||
}
|
||||
|
||||
interface ValidationError {
|
||||
code: string;
|
||||
severity: 'error' | 'warning';
|
||||
path: string; // e.g., "objectives[0]"
|
||||
message: string;
|
||||
suggestion?: string;
|
||||
autoFix?: () => void;
|
||||
}
|
||||
```
|
||||
|
||||
### Validation Rules
|
||||
|
||||
| Rule | Severity | Message |
|
||||
|------|----------|---------|
|
||||
| No design variables | Error | "Add at least one design variable" |
|
||||
| No objectives | Error | "Add at least one objective" |
|
||||
| Objective not connected to extractor | Error | "Objective '{name}' has no source extractor" |
|
||||
| Extractor type not set | Error | "Extractor '{name}' needs a type selected" |
|
||||
| Design var bounds invalid | Error | "Min must be less than max for '{name}'" |
|
||||
| No model file | Error | "No simulation file configured" |
|
||||
| Custom extractor no code | Warning | "Custom extractor '{name}' has no code" |
|
||||
| High trial count (>500) | Warning | "Large budget may take hours to complete" |
|
||||
| Single trial | Warning | "Only 1 trial - results won't be meaningful" |
|
||||
|
||||
### Implementation Tasks
|
||||
|
||||
| Task | File | Description |
|
||||
|------|------|-------------|
|
||||
| 2.1 | `validation/specValidator.ts` | Client-side validation rules |
|
||||
| 2.2 | `ValidationPanel.tsx` | Display validation results |
|
||||
| 2.3 | `SpecRenderer.tsx` | Add "Validate" button, pre-run check |
|
||||
| 2.4 | `api/routes/spec.py` | Server-side validation endpoint |
|
||||
| 2.5 | `useSpecStore.ts` | Add `validate()` action |
|
||||
|
||||
### UI Flow
|
||||
|
||||
```
|
||||
User clicks "Run Optimization"
|
||||
↓
|
||||
[Validate Spec] ──failed──→ [Show ValidationPanel]
|
||||
↓ passed │
|
||||
[Confirm Dialog] │
|
||||
↓ confirmed │
|
||||
[Start Optimization] ←── fix ─────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Error Handling & Recovery (HIGH PRIORITY)
|
||||
|
||||
### Problem
|
||||
- NX crashes don't show useful feedback
|
||||
- Solver failures leave user confused
|
||||
- No way to resume after errors
|
||||
|
||||
### Solution: Error Classification & Display
|
||||
|
||||
```typescript
|
||||
interface OptimizationError {
|
||||
type: 'nx_crash' | 'solver_fail' | 'extractor_error' | 'config_error' | 'system_error';
|
||||
trial?: number;
|
||||
message: string;
|
||||
details?: string;
|
||||
recoverable: boolean;
|
||||
suggestions: string[];
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling Strategy
|
||||
|
||||
| Error Type | Display | Recovery |
|
||||
|------------|---------|----------|
|
||||
| NX Crash | Toast + Error Panel | Retry trial, skip trial |
|
||||
| Solver Failure | Badge on trial | Mark infeasible, continue |
|
||||
| Extractor Error | Log + badge | Use NaN, continue |
|
||||
| Config Error | Block run | Show validation panel |
|
||||
| System Error | Full modal | Restart optimization |
|
||||
|
||||
### Implementation Tasks
|
||||
|
||||
| Task | File | Description |
|
||||
|------|------|-------------|
|
||||
| 3.1 | `ErrorBoundary.tsx` | Wrap canvas in error boundary |
|
||||
| 3.2 | `ErrorPanel.tsx` | Detailed error display with suggestions |
|
||||
| 3.3 | `optimization.py` | Enhanced error responses with type/recovery |
|
||||
| 3.4 | `SpecRenderer.tsx` | Error state handling, retry buttons |
|
||||
| 3.5 | `useOptimizationStatus.ts` | Hook for status polling with error handling |
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Live Updates via WebSocket (MEDIUM PRIORITY)
|
||||
|
||||
### Problem
|
||||
- Current polling (3s) is inefficient and has latency
|
||||
- Missed updates between polls
|
||||
- No real-time progress indication
|
||||
|
||||
### Solution: WebSocket for Trial Updates
|
||||
|
||||
```typescript
|
||||
// WebSocket events
|
||||
interface TrialStartEvent {
|
||||
type: 'trial_start';
|
||||
trial_number: number;
|
||||
params: Record<string, number>;
|
||||
}
|
||||
|
||||
interface TrialCompleteEvent {
|
||||
type: 'trial_complete';
|
||||
trial_number: number;
|
||||
objectives: Record<string, number>;
|
||||
is_best: boolean;
|
||||
is_feasible: boolean;
|
||||
}
|
||||
|
||||
interface OptimizationCompleteEvent {
|
||||
type: 'optimization_complete';
|
||||
best_trial: number;
|
||||
total_trials: number;
|
||||
}
|
||||
```
|
||||
|
||||
### Implementation Tasks
|
||||
|
||||
| Task | File | Description |
|
||||
|------|------|-------------|
|
||||
| 4.1 | `websocket.py` | Add optimization events to WS |
|
||||
| 4.2 | `run_optimization.py` | Emit events during optimization |
|
||||
| 4.3 | `useOptimizationWebSocket.ts` | Hook for WS subscription |
|
||||
| 4.4 | `SpecRenderer.tsx` | Use WS instead of polling |
|
||||
| 4.5 | `ResultBadge.tsx` | Animate on new results |
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Convergence Visualization (MEDIUM PRIORITY)
|
||||
|
||||
### Problem
|
||||
- No visual feedback on optimization progress
|
||||
- Can't tell if converging or stuck
|
||||
- No Pareto front visualization for multi-objective
|
||||
|
||||
### Solution: Embedded Charts
|
||||
|
||||
### Components
|
||||
|
||||
| Component | Description |
|
||||
|-----------|-------------|
|
||||
| `ConvergenceSparkline` | Tiny chart in ObjectiveNode showing trend |
|
||||
| `ProgressRing` | Circular progress in header (trials/total) |
|
||||
| `ConvergenceChart` | Full chart in Results panel |
|
||||
| `ParetoPlot` | 2D Pareto front for multi-objective |
|
||||
|
||||
### Implementation Tasks
|
||||
|
||||
| Task | File | Description |
|
||||
|------|------|-------------|
|
||||
| 5.1 | `ConvergenceSparkline.tsx` | SVG sparkline component |
|
||||
| 5.2 | `ObjectiveNode.tsx` | Integrate sparkline |
|
||||
| 5.3 | `ProgressRing.tsx` | Circular progress indicator |
|
||||
| 5.4 | `ConvergenceChart.tsx` | Full chart with Recharts |
|
||||
| 5.5 | `ResultsPanel.tsx` | Panel showing detailed results |
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: End-to-End Testing (MEDIUM PRIORITY)
|
||||
|
||||
### Problem
|
||||
- No automated tests for canvas operations
|
||||
- Manual testing is time-consuming and error-prone
|
||||
- Regressions go unnoticed
|
||||
|
||||
### Solution: Playwright E2E Tests
|
||||
|
||||
### Test Scenarios
|
||||
|
||||
| Test | Steps | Assertions |
|
||||
|------|-------|------------|
|
||||
| Load study | Navigate to /canvas/{id} | Spec loads, nodes render |
|
||||
| Add design var | Drag from palette | Node appears, spec updates |
|
||||
| Connect nodes | Drag edge | Edge renders, spec has edge |
|
||||
| Edit node | Click node, change value | Value persists, API called |
|
||||
| Run validation | Click validate | Errors shown for incomplete |
|
||||
| Start optimization | Complete spec, click run | Status shows running |
|
||||
| View results | Wait for trial | Badge shows value |
|
||||
| Stop optimization | Click stop | Status shows stopped |
|
||||
|
||||
### Implementation Tasks
|
||||
|
||||
| Task | File | Description |
|
||||
|------|------|-------------|
|
||||
| 6.1 | `e2e/canvas.spec.ts` | Basic canvas operations |
|
||||
| 6.2 | `e2e/optimization.spec.ts` | Run/stop/status flow |
|
||||
| 6.3 | `e2e/panels.spec.ts` | Panel open/close/persist |
|
||||
| 6.4 | `playwright.config.ts` | Configure Playwright |
|
||||
| 6.5 | `CI workflow` | Run tests in GitHub Actions |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Order
|
||||
|
||||
```
|
||||
Week 1:
|
||||
├── Phase 1: Panel Management (critical UX fix)
|
||||
│ ├── Day 1-2: usePanelStore + PanelContainer
|
||||
│ └── Day 3-4: Refactor existing panels
|
||||
│
|
||||
├── Phase 2: Validation (prevent user errors)
|
||||
│ └── Day 5: Validation rules + UI
|
||||
|
||||
Week 2:
|
||||
├── Phase 3: Error Handling
|
||||
│ ├── Day 1-2: Error types + ErrorPanel
|
||||
│ └── Day 3: Integration with optimization flow
|
||||
│
|
||||
├── Phase 4: WebSocket Updates
|
||||
│ └── Day 4-5: WS events + frontend hook
|
||||
|
||||
Week 3:
|
||||
├── Phase 5: Visualization
|
||||
│ ├── Day 1-2: Sparklines
|
||||
│ └── Day 3: Progress indicators
|
||||
│
|
||||
├── Phase 6: Testing
|
||||
│ └── Day 4-5: Playwright setup + core tests
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Wins (Can Do Now)
|
||||
|
||||
These can be implemented immediately with minimal changes:
|
||||
|
||||
1. **Persist introspection data in localStorage**
|
||||
- Cache introspection results
|
||||
- Restore on panel reopen
|
||||
|
||||
2. **Add loading states to all buttons**
|
||||
- Disable during operations
|
||||
- Show spinners
|
||||
|
||||
3. **Add confirmation dialogs**
|
||||
- Before stopping optimization
|
||||
- Before clearing canvas
|
||||
|
||||
4. **Improve error messages**
|
||||
- Parse NX error logs
|
||||
- Show actionable suggestions
|
||||
|
||||
---
|
||||
|
||||
## Files to Create/Modify
|
||||
|
||||
### New Files
|
||||
```
|
||||
atomizer-dashboard/frontend/src/
|
||||
├── hooks/
|
||||
│ ├── usePanelStore.ts
|
||||
│ └── useOptimizationWebSocket.ts
|
||||
├── components/canvas/
|
||||
│ ├── PanelContainer.tsx
|
||||
│ ├── panels/
|
||||
│ │ ├── ValidationPanel.tsx
|
||||
│ │ ├── ErrorPanel.tsx
|
||||
│ │ └── ResultsPanel.tsx
|
||||
│ └── visualization/
|
||||
│ ├── ConvergenceSparkline.tsx
|
||||
│ ├── ProgressRing.tsx
|
||||
│ └── ConvergenceChart.tsx
|
||||
└── lib/
|
||||
└── validation/
|
||||
└── specValidator.ts
|
||||
|
||||
e2e/
|
||||
├── canvas.spec.ts
|
||||
├── optimization.spec.ts
|
||||
└── panels.spec.ts
|
||||
```
|
||||
|
||||
### Modified Files
|
||||
```
|
||||
atomizer-dashboard/frontend/src/
|
||||
├── pages/CanvasView.tsx
|
||||
├── components/canvas/SpecRenderer.tsx
|
||||
├── components/canvas/panels/IntrospectionPanel.tsx
|
||||
├── components/canvas/panels/NodeConfigPanelV2.tsx
|
||||
├── components/canvas/nodes/ObjectiveNode.tsx
|
||||
└── hooks/useSpecStore.ts
|
||||
|
||||
atomizer-dashboard/backend/api/
|
||||
├── routes/optimization.py
|
||||
├── routes/spec.py
|
||||
└── websocket.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
| Phase | Success Metric |
|
||||
|-------|----------------|
|
||||
| 1 | Introspection panel persists across node selections |
|
||||
| 2 | Invalid spec shows clear error before run |
|
||||
| 3 | NX errors display with recovery options |
|
||||
| 4 | Results update within 500ms of trial completion |
|
||||
| 5 | Convergence trend visible on objective nodes |
|
||||
| 6 | All E2E tests pass in CI |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Review this plan
|
||||
2. Start with Phase 1 (Panel Management) - fixes your immediate issue
|
||||
3. Implement incrementally, commit after each phase
|
||||
@@ -1,445 +0,0 @@
|
||||
# Canvas UX Improvements - Master Plan
|
||||
|
||||
**Created:** January 2026
|
||||
**Status:** Planning
|
||||
**Branch:** `feature/studio-enhancement`
|
||||
|
||||
## Overview
|
||||
|
||||
This plan addresses three major UX issues in the Canvas Builder:
|
||||
|
||||
1. **Resizable Panels** - Right pane (chat/config) is fixed at 384px, cannot be adjusted
|
||||
2. **Disabled Palette Items** - Model, Solver, Algorithm, Surrogate are grayed out and not draggable
|
||||
3. **Solver Type Selection** - Solver node should allow selection of solver type (NX Nastran, Python, etc.)
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: Resizable Panels
|
||||
|
||||
### Current State
|
||||
- Left sidebar: Fixed 240px (expanded) or 56px (collapsed)
|
||||
- Right panel (Chat/Config): Fixed 384px
|
||||
- Canvas: Takes remaining space
|
||||
|
||||
### Requirements
|
||||
- Users should be able to drag panel edges to resize
|
||||
- Minimum/maximum constraints for usability
|
||||
- Persist panel sizes in localStorage
|
||||
- Smooth resize with proper cursor feedback
|
||||
|
||||
### Implementation
|
||||
|
||||
#### 7.1 Create Resizable Panel Hook
|
||||
```typescript
|
||||
// hooks/useResizablePanel.ts
|
||||
interface ResizablePanelState {
|
||||
width: number;
|
||||
isDragging: boolean;
|
||||
startDrag: (e: React.MouseEvent) => void;
|
||||
}
|
||||
|
||||
function useResizablePanel(
|
||||
key: string,
|
||||
defaultWidth: number,
|
||||
minWidth: number,
|
||||
maxWidth: number
|
||||
): ResizablePanelState
|
||||
```
|
||||
|
||||
#### 7.2 Update CanvasView Layout
|
||||
- Wrap left sidebar with resizer
|
||||
- Wrap right panel with resizer
|
||||
- Add visual drag handles (thin border that highlights on hover)
|
||||
- Add cursor: col-resize on hover
|
||||
|
||||
#### 7.3 Files to Modify
|
||||
| File | Changes |
|
||||
|------|---------|
|
||||
| `hooks/useResizablePanel.ts` | NEW - Resize hook with localStorage persistence |
|
||||
| `pages/CanvasView.tsx` | Add resizers to left/right panels |
|
||||
| `components/canvas/ResizeHandle.tsx` | NEW - Visual resize handle component |
|
||||
|
||||
#### 7.4 Constraints
|
||||
| Panel | Min | Default | Max |
|
||||
|-------|-----|---------|-----|
|
||||
| Left (Palette/Files) | 200px | 240px | 400px |
|
||||
| Right (Chat/Config) | 280px | 384px | 600px |
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: Enable All Palette Items
|
||||
|
||||
### Current State
|
||||
- Model, Solver, Algorithm, Surrogate are marked `canAdd: false`
|
||||
- They appear grayed out with "Auto-created" text
|
||||
- Users cannot drag them to canvas
|
||||
|
||||
### Problem Analysis
|
||||
These nodes were marked as "synthetic" because they're derived from:
|
||||
- **Model**: From `spec.model.sim.path`
|
||||
- **Solver**: From model's solution type
|
||||
- **Algorithm**: From `spec.optimization.algorithm`
|
||||
- **Surrogate**: From `spec.optimization.surrogate`
|
||||
|
||||
However, users need to:
|
||||
1. Add a Model node when creating a new study from scratch
|
||||
2. Configure the Solver type
|
||||
3. Choose an Algorithm
|
||||
4. Enable/configure Surrogate
|
||||
|
||||
### Solution: Make All Items Draggable
|
||||
|
||||
#### 8.1 Update NodePalette
|
||||
```typescript
|
||||
// All items should be draggable
|
||||
export const PALETTE_ITEMS: PaletteItem[] = [
|
||||
{
|
||||
type: 'model',
|
||||
label: 'Model',
|
||||
canAdd: true, // Changed from false
|
||||
description: 'NX/FEM model file',
|
||||
},
|
||||
{
|
||||
type: 'solver',
|
||||
label: 'Solver',
|
||||
canAdd: true, // Changed from false
|
||||
description: 'Analysis solver',
|
||||
},
|
||||
// ... etc
|
||||
];
|
||||
```
|
||||
|
||||
#### 8.2 Handle "Singleton" Nodes
|
||||
Some nodes should only exist once on the canvas:
|
||||
- Model (only one model per study)
|
||||
- Solver (one solver)
|
||||
- Algorithm (one algorithm config)
|
||||
- Surrogate (optional, one)
|
||||
|
||||
When user drags a singleton that already exists:
|
||||
- Option A: Show warning toast "Model already exists"
|
||||
- Option B: Select the existing node instead of creating new
|
||||
- **Recommended**: Option B (select existing)
|
||||
|
||||
#### 8.3 Update SpecRenderer Drop Handler
|
||||
```typescript
|
||||
const onDrop = useCallback(async (event: DragEvent) => {
|
||||
const type = event.dataTransfer.getData('application/reactflow');
|
||||
|
||||
// Check if singleton already exists
|
||||
const SINGLETON_TYPES = ['model', 'solver', 'algorithm', 'surrogate'];
|
||||
if (SINGLETON_TYPES.includes(type)) {
|
||||
const existingNode = nodes.find(n => n.type === type);
|
||||
if (existingNode) {
|
||||
selectNode(existingNode.id);
|
||||
showNotification(`${type} already exists - selected it`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new node...
|
||||
}, [...]);
|
||||
```
|
||||
|
||||
#### 8.4 Default Data for New Node Types
|
||||
```typescript
|
||||
function getDefaultNodeData(type: NodeType, position) {
|
||||
switch (type) {
|
||||
case 'model':
|
||||
return {
|
||||
name: 'Model',
|
||||
sim: { path: '', solver: 'nastran' },
|
||||
canvas_position: position,
|
||||
};
|
||||
case 'solver':
|
||||
return {
|
||||
name: 'Solver',
|
||||
type: 'nxnastran', // Default solver
|
||||
solution_type: 'SOL101',
|
||||
canvas_position: position,
|
||||
};
|
||||
case 'algorithm':
|
||||
return {
|
||||
name: 'Algorithm',
|
||||
type: 'TPE',
|
||||
budget: { max_trials: 100 },
|
||||
canvas_position: position,
|
||||
};
|
||||
case 'surrogate':
|
||||
return {
|
||||
name: 'Surrogate',
|
||||
enabled: false,
|
||||
model_type: 'MLP',
|
||||
min_trials: 20,
|
||||
canvas_position: position,
|
||||
};
|
||||
// ... existing cases
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 8.5 Files to Modify
|
||||
| File | Changes |
|
||||
|------|---------|
|
||||
| `components/canvas/palette/NodePalette.tsx` | Set `canAdd: true` for all items |
|
||||
| `components/canvas/SpecRenderer.tsx` | Handle singleton logic in onDrop |
|
||||
| `lib/spec/converter.ts` | Ensure synthetic nodes have proper IDs |
|
||||
| `hooks/useSpecStore.ts` | Add model/solver/algorithm to addNode support |
|
||||
|
||||
---
|
||||
|
||||
## Phase 9: Solver Type Selection
|
||||
|
||||
### Current State
|
||||
- Solver node shows auto-detected solution type (SOL101, etc.)
|
||||
- No ability to change solver engine or configure it
|
||||
|
||||
### Requirements
|
||||
1. Allow selection of solver engine type
|
||||
2. Configure solution type
|
||||
3. Support future solver types
|
||||
|
||||
### Solver Types to Support
|
||||
|
||||
| Solver | Description | Status |
|
||||
|--------|-------------|--------|
|
||||
| `nxnastran` | NX Nastran (built-in) | Current |
|
||||
| `mscnastran` | MSC Nastran (external) | Future |
|
||||
| `python` | Python-based solver | Future |
|
||||
| `abaqus` | Abaqus (via Python API) | Future |
|
||||
| `ansys` | ANSYS (via Python API) | Future |
|
||||
|
||||
### Solution Types per Solver
|
||||
|
||||
**NX Nastran / MSC Nastran:**
|
||||
- SOL101 - Linear Static
|
||||
- SOL103 - Normal Modes
|
||||
- SOL105 - Buckling
|
||||
- SOL106 - Nonlinear Static
|
||||
- SOL111 - Frequency Response
|
||||
- SOL112 - Transient Response
|
||||
- SOL200 - Design Optimization
|
||||
|
||||
**Python Solver:**
|
||||
- Custom (user-defined)
|
||||
|
||||
### Schema Updates
|
||||
|
||||
#### 9.1 Update AtomizerSpec Types
|
||||
```typescript
|
||||
// types/atomizer-spec.ts
|
||||
|
||||
export type SolverEngine =
|
||||
| 'nxnastran'
|
||||
| 'mscnastran'
|
||||
| 'python'
|
||||
| 'abaqus'
|
||||
| 'ansys';
|
||||
|
||||
export type NastranSolutionType =
|
||||
| 'SOL101'
|
||||
| 'SOL103'
|
||||
| 'SOL105'
|
||||
| 'SOL106'
|
||||
| 'SOL111'
|
||||
| 'SOL112'
|
||||
| 'SOL200';
|
||||
|
||||
export interface SolverConfig {
|
||||
/** Solver engine type */
|
||||
engine: SolverEngine;
|
||||
|
||||
/** Solution type (for Nastran) */
|
||||
solution_type?: NastranSolutionType;
|
||||
|
||||
/** Custom solver script path (for Python solver) */
|
||||
script_path?: string;
|
||||
|
||||
/** Additional solver options */
|
||||
options?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface Model {
|
||||
sim?: {
|
||||
path: string;
|
||||
solver: SolverConfig; // Changed from just 'nastran' string
|
||||
};
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 9.2 Update SolverNode Component
|
||||
```typescript
|
||||
// components/canvas/nodes/SolverNode.tsx
|
||||
|
||||
function SolverNodeComponent(props: NodeProps<SolverNodeData>) {
|
||||
const { data } = props;
|
||||
|
||||
return (
|
||||
<BaseNode {...props} icon={<Cpu size={16} />} iconColor="text-violet-400">
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-sm font-medium">{data.engine || 'nxnastran'}</span>
|
||||
<span className="text-xs text-dark-400">
|
||||
{data.solution_type || 'Auto-detect'}
|
||||
</span>
|
||||
</div>
|
||||
</BaseNode>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### 9.3 Solver Configuration Panel
|
||||
Add to `NodeConfigPanelV2.tsx`:
|
||||
|
||||
```typescript
|
||||
function SolverNodeConfig({ spec }: SpecConfigProps) {
|
||||
const { patchSpec } = useSpecStore();
|
||||
const solver = spec.model?.sim?.solver || { engine: 'nxnastran' };
|
||||
|
||||
const handleEngineChange = (engine: SolverEngine) => {
|
||||
patchSpec('model.sim.solver.engine', engine);
|
||||
};
|
||||
|
||||
const handleSolutionTypeChange = (type: NastranSolutionType) => {
|
||||
patchSpec('model.sim.solver.solution_type', type);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<label className={labelClass}>Solver Engine</label>
|
||||
<select
|
||||
value={solver.engine}
|
||||
onChange={(e) => handleEngineChange(e.target.value as SolverEngine)}
|
||||
className={selectClass}
|
||||
>
|
||||
<option value="nxnastran">NX Nastran</option>
|
||||
<option value="mscnastran">MSC Nastran</option>
|
||||
<option value="python">Python Script</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{(solver.engine === 'nxnastran' || solver.engine === 'mscnastran') && (
|
||||
<div>
|
||||
<label className={labelClass}>Solution Type</label>
|
||||
<select
|
||||
value={solver.solution_type || ''}
|
||||
onChange={(e) => handleSolutionTypeChange(e.target.value as NastranSolutionType)}
|
||||
className={selectClass}
|
||||
>
|
||||
<option value="">Auto-detect from model</option>
|
||||
<option value="SOL101">SOL101 - Linear Static</option>
|
||||
<option value="SOL103">SOL103 - Normal Modes</option>
|
||||
<option value="SOL105">SOL105 - Buckling</option>
|
||||
<option value="SOL106">SOL106 - Nonlinear Static</option>
|
||||
<option value="SOL111">SOL111 - Frequency Response</option>
|
||||
<option value="SOL112">SOL112 - Transient Response</option>
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{solver.engine === 'python' && (
|
||||
<div>
|
||||
<label className={labelClass}>Solver Script</label>
|
||||
<input
|
||||
type="text"
|
||||
value={solver.script_path || ''}
|
||||
onChange={(e) => patchSpec('model.sim.solver.script_path', e.target.value)}
|
||||
placeholder="/path/to/solver.py"
|
||||
className={inputClass}
|
||||
/>
|
||||
<p className="text-xs text-dark-500 mt-1">
|
||||
Python script that runs the analysis
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### 9.4 Files to Modify
|
||||
| File | Changes |
|
||||
|------|---------|
|
||||
| `types/atomizer-spec.ts` | Add SolverEngine, SolverConfig types |
|
||||
| `components/canvas/nodes/SolverNode.tsx` | Show engine and solution type |
|
||||
| `components/canvas/panels/NodeConfigPanelV2.tsx` | Add SolverNodeConfig |
|
||||
| `lib/canvas/schema.ts` | Update SolverNodeData |
|
||||
| Backend: `config/spec_models.py` | Add SolverConfig Pydantic model |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Order
|
||||
|
||||
| Phase | Effort | Priority | Dependencies |
|
||||
|-------|--------|----------|--------------|
|
||||
| **7.1** Resizable Panel Hook | 2h | High | None |
|
||||
| **7.2** CanvasView Resizers | 2h | High | 7.1 |
|
||||
| **8.1** Enable Palette Items | 1h | High | None |
|
||||
| **8.2** Singleton Logic | 2h | High | 8.1 |
|
||||
| **8.3** Default Node Data | 1h | High | 8.2 |
|
||||
| **9.1** Schema Updates | 2h | Medium | None |
|
||||
| **9.2** SolverNode UI | 1h | Medium | 9.1 |
|
||||
| **9.3** Solver Config Panel | 2h | Medium | 9.1, 9.2 |
|
||||
|
||||
**Total Estimated Effort:** ~13 hours
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
### Phase 7 (Resizable Panels)
|
||||
- [ ] Left panel can be resized between 200-400px
|
||||
- [ ] Right panel can be resized between 280-600px
|
||||
- [ ] Resize handles show cursor feedback
|
||||
- [ ] Panel sizes persist across page reload
|
||||
- [ ] Double-click on handle resets to default
|
||||
|
||||
### Phase 8 (Enable Palette Items)
|
||||
- [ ] All 8 node types are draggable from palette
|
||||
- [ ] Dragging singleton to canvas with existing node selects existing
|
||||
- [ ] Toast notification explains the behavior
|
||||
- [ ] New studies can start with empty canvas and add Model first
|
||||
|
||||
### Phase 9 (Solver Selection)
|
||||
- [ ] Solver node shows engine type (nxnastran, python, etc.)
|
||||
- [ ] Clicking solver node opens config panel
|
||||
- [ ] Can select solver engine from dropdown
|
||||
- [ ] Nastran solvers show solution type dropdown
|
||||
- [ ] Python solver shows script path input
|
||||
- [ ] Changes persist to atomizer_spec.json
|
||||
|
||||
---
|
||||
|
||||
## Future Considerations
|
||||
|
||||
### Additional Solver Support
|
||||
- ANSYS integration via pyANSYS
|
||||
- Abaqus integration via abaqus-python
|
||||
- OpenFOAM for CFD
|
||||
- Custom Python solvers with standardized interface
|
||||
|
||||
### Multi-Solver Workflows
|
||||
- Support for chained solvers (thermal → structural)
|
||||
- Co-simulation workflows
|
||||
- Parallel solver execution
|
||||
|
||||
### Algorithm Node Enhancement
|
||||
- Similar to Solver, allow algorithm selection
|
||||
- Show algorithm-specific parameters
|
||||
- Support custom algorithms
|
||||
|
||||
---
|
||||
|
||||
## Commit Strategy
|
||||
|
||||
```bash
|
||||
# Phase 7
|
||||
git commit -m "feat: Add resizable panels to canvas view"
|
||||
|
||||
# Phase 8
|
||||
git commit -m "feat: Enable all palette items with singleton handling"
|
||||
|
||||
# Phase 9
|
||||
git commit -m "feat: Add solver type selection and configuration"
|
||||
```
|
||||
@@ -1,737 +0,0 @@
|
||||
# Claude + Canvas Integration V2
|
||||
|
||||
## The Vision
|
||||
|
||||
**Side-by-side LLM + Canvas** where:
|
||||
1. **Claude talks → Canvas updates in real-time** (user sees nodes appear/change)
|
||||
2. **User tweaks Canvas → Claude sees changes** (bi-directional sync)
|
||||
3. **Full Claude Code-level power** through the dashboard chat
|
||||
4. **Interview-driven study creation** entirely through chat
|
||||
|
||||
The user can:
|
||||
- Describe what they want in natural language
|
||||
- Watch the canvas build itself
|
||||
- Make quick manual tweaks
|
||||
- Continue the conversation with Claude seeing their changes
|
||||
- Have Claude execute protocols, create files, run optimizations
|
||||
|
||||
---
|
||||
|
||||
## Current State vs Target
|
||||
|
||||
### What We Have Now
|
||||
|
||||
```
|
||||
┌──────────────────┐ ┌──────────────────┐
|
||||
│ Chat Panel │ │ Canvas │
|
||||
│ (Power Mode) │ │ (SpecRenderer) │
|
||||
├──────────────────┤ ├──────────────────┤
|
||||
│ - Anthropic API │ │ - Loads spec │
|
||||
│ - Write tools │ │ - User edits │
|
||||
│ - spec_modified │--->│ - Auto-refresh │
|
||||
│ events │ │ on event │
|
||||
└──────────────────┘ └──────────────────┘
|
||||
│ │
|
||||
│ No real-time │
|
||||
│ canvas state │
|
||||
│ in Claude context │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
**Gaps:**
|
||||
1. Claude doesn't see current canvas state in real-time
|
||||
2. No interview engine for guided study creation
|
||||
3. Limited tool set (no file ops, no protocol execution)
|
||||
4. No streaming for tool calls
|
||||
5. Mode switching requires reconnection
|
||||
|
||||
### What We Want
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────────────────────┐
|
||||
│ ATOMIZER DASHBOARD │
|
||||
├────────────────────────────┬──────────────────────────────────────┤
|
||||
│ │ │
|
||||
│ CHAT PANEL │ CANVAS │
|
||||
│ (Atomizer Assistant) │ (SpecRenderer) │
|
||||
│ │ │
|
||||
│ ┌──────────────────────┐ │ ┌────────────────────────────────┐ │
|
||||
│ │ "Create a bracket │ │ │ │ │
|
||||
│ │ optimization with │ │ │ [DV: thickness] │ │
|
||||
│ │ mass and stiffness" │ │ │ │ │ │
|
||||
│ └──────────────────────┘ │ │ ▼ │ │
|
||||
│ │ │ │ [Model Node] │ │
|
||||
│ ▼ │ │ │ │ │
|
||||
│ ┌──────────────────────┐ │ │ ▼ │ │
|
||||
│ │ 🔧 Adding thickness │ │ │ [Ext: mass]──>[Obj: min] │ │
|
||||
│ │ 🔧 Adding mass ext │◄─┼──┤ [Ext: disp]──>[Obj: min] │ │
|
||||
│ │ 🔧 Adding objective │ │ │ │ │
|
||||
│ │ │ │ │ (nodes appear in real-time) │ │
|
||||
│ │ ✓ Study configured! │ │ │ │ │
|
||||
│ └──────────────────────┘ │ └────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────────────────┐ │ User can click any node to edit │
|
||||
│ │ Claude sees the │ │ Claude sees user's edits │
|
||||
│ │ canvas state and │◄─┼──────────────────────────────────────│
|
||||
│ │ user's manual edits │ │ │
|
||||
│ └──────────────────────┘ │ │
|
||||
└────────────────────────────┴──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### 1. WebSocket Hub (Bi-directional Sync)
|
||||
|
||||
```
|
||||
┌─────────────────────┐
|
||||
│ WebSocket Hub │
|
||||
│ (Single Connection)│
|
||||
└─────────┬───────────┘
|
||||
│
|
||||
┌────────────────────┼────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Chat Panel │ │ Canvas │ │ Spec Store │
|
||||
│ │ │ │ │ │
|
||||
│ - Send messages │ │ - User edits │ │ - Single source │
|
||||
│ - Receive text │ │ - Node add/del │ │ of truth │
|
||||
│ - See tool calls│ │ - Edge changes │ │ - Validates │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
|
||||
Message Types:
|
||||
Client → Server:
|
||||
{ type: "message", content: "..." } # Chat message
|
||||
{ type: "canvas_edit", patch: {...} } # User made canvas change
|
||||
{ type: "set_study", study_id: "..." } # Switch study
|
||||
{ type: "ping" } # Heartbeat
|
||||
|
||||
Server → Client:
|
||||
{ type: "text", content: "...", done: false } # Streaming text
|
||||
{ type: "tool_start", tool: "...", input: {...} }
|
||||
{ type: "tool_result", tool: "...", result: "..." }
|
||||
{ type: "spec_updated", spec: {...} } # Full spec after change
|
||||
{ type: "canvas_patch", patch: {...} } # Incremental update
|
||||
{ type: "done" } # Response complete
|
||||
{ type: "pong" } # Heartbeat response
|
||||
```
|
||||
|
||||
### 2. Enhanced Claude Agent
|
||||
|
||||
The `AtomizerClaudeAgent` needs to be more like **Claude Code**:
|
||||
|
||||
```python
|
||||
class AtomizerClaudeAgent:
|
||||
"""Full-power Claude agent with Claude Code-like capabilities"""
|
||||
|
||||
def __init__(self, study_id: Optional[str] = None):
|
||||
self.client = anthropic.Anthropic()
|
||||
self.study_id = study_id
|
||||
self.spec_store = SpecStore(study_id) # Real-time spec access
|
||||
self.interview_state = None # For guided creation
|
||||
self.tools = self._define_full_tools()
|
||||
|
||||
async def chat_stream(
|
||||
self,
|
||||
message: str,
|
||||
conversation: List[Dict],
|
||||
canvas_state: Optional[Dict] = None # Current canvas from frontend
|
||||
) -> AsyncGenerator[Dict, None]:
|
||||
"""Stream responses with tool calls"""
|
||||
|
||||
# Build context with current canvas state
|
||||
system = self._build_system_prompt(canvas_state)
|
||||
|
||||
# Stream the response
|
||||
with self.client.messages.stream(
|
||||
model="claude-sonnet-4-20250514",
|
||||
max_tokens=8192,
|
||||
system=system,
|
||||
messages=conversation + [{"role": "user", "content": message}],
|
||||
tools=self.tools
|
||||
) as stream:
|
||||
for event in stream:
|
||||
if event.type == "content_block_delta":
|
||||
if event.delta.type == "text_delta":
|
||||
yield {"type": "text", "content": event.delta.text}
|
||||
|
||||
elif event.type == "content_block_start":
|
||||
if event.content_block.type == "tool_use":
|
||||
yield {
|
||||
"type": "tool_start",
|
||||
"tool": event.content_block.name,
|
||||
"input": {} # Will be completed
|
||||
}
|
||||
|
||||
# Handle tool calls after stream
|
||||
response = stream.get_final_message()
|
||||
for block in response.content:
|
||||
if block.type == "tool_use":
|
||||
result = await self._execute_tool(block.name, block.input)
|
||||
yield {
|
||||
"type": "tool_result",
|
||||
"tool": block.name,
|
||||
"result": result["result"],
|
||||
"spec_changed": result.get("spec_changed", False)
|
||||
}
|
||||
|
||||
# If spec changed, send the updated spec
|
||||
if result.get("spec_changed"):
|
||||
yield {
|
||||
"type": "spec_updated",
|
||||
"spec": self.spec_store.get_dict()
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Full Tool Set
|
||||
|
||||
Claude needs more tools to match Claude Code power:
|
||||
|
||||
```python
|
||||
FULL_TOOLS = [
|
||||
# === READ TOOLS ===
|
||||
"read_study_config", # Read atomizer_spec.json
|
||||
"query_trials", # Query optimization database
|
||||
"list_studies", # List available studies
|
||||
"read_file", # Read any file in study
|
||||
"list_files", # List files in study directory
|
||||
"read_nx_expressions", # Get NX model expressions
|
||||
|
||||
# === WRITE TOOLS (Spec Modification) ===
|
||||
"add_design_variable", # Add DV to spec
|
||||
"add_extractor", # Add extractor (built-in or custom)
|
||||
"add_objective", # Add objective
|
||||
"add_constraint", # Add constraint
|
||||
"update_spec_field", # Update any spec field by path
|
||||
"remove_node", # Remove any node by ID
|
||||
"update_canvas_layout", # Reposition nodes for better layout
|
||||
|
||||
# === STUDY MANAGEMENT ===
|
||||
"create_study", # Create new study directory + spec
|
||||
"clone_study", # Clone existing study
|
||||
"validate_spec", # Validate current spec
|
||||
"migrate_config", # Migrate legacy config to spec v2
|
||||
|
||||
# === OPTIMIZATION CONTROL ===
|
||||
"start_optimization", # Start optimization run
|
||||
"stop_optimization", # Stop running optimization
|
||||
"get_optimization_status",# Check if running, trial count
|
||||
|
||||
# === FILE OPERATIONS ===
|
||||
"write_file", # Write file to study directory
|
||||
"create_directory", # Create directory in study
|
||||
|
||||
# === NX INTEGRATION ===
|
||||
"introspect_model", # Get model info (expressions, features)
|
||||
"suggest_design_vars", # AI-suggest design variables from model
|
||||
|
||||
# === INTERVIEW/GUIDED CREATION ===
|
||||
"start_interview", # Begin guided study creation
|
||||
"process_answer", # Process user's interview answer
|
||||
"get_interview_state", # Get current interview progress
|
||||
]
|
||||
```
|
||||
|
||||
### 4. Interview Engine Integration
|
||||
|
||||
The interview happens **through chat**, not a separate UI:
|
||||
|
||||
```python
|
||||
class InterviewEngine:
|
||||
"""Guided study creation through conversation"""
|
||||
|
||||
PHASES = [
|
||||
("model", "Let's set up your model. What's the path to your NX simulation file?"),
|
||||
("objectives", "What do you want to optimize? (e.g., minimize mass, minimize displacement)"),
|
||||
("design_vars", "Which parameters can I vary? I can suggest some based on your model."),
|
||||
("constraints", "Any constraints to respect? (e.g., max stress, min frequency)"),
|
||||
("method", "I recommend {method} for this problem. Should I configure it?"),
|
||||
("review", "Here's the complete configuration. Ready to create the study?"),
|
||||
]
|
||||
|
||||
def __init__(self, spec_store: SpecStore):
|
||||
self.spec_store = spec_store
|
||||
self.current_phase = 0
|
||||
self.collected_data = {}
|
||||
|
||||
def get_current_question(self) -> str:
|
||||
phase_name, question = self.PHASES[self.current_phase]
|
||||
# Customize question based on collected data
|
||||
if phase_name == "method":
|
||||
method = self._recommend_method()
|
||||
question = question.format(method=method)
|
||||
return question
|
||||
|
||||
def process_answer(self, answer: str) -> Dict:
|
||||
"""Process answer and build spec incrementally"""
|
||||
phase_name, _ = self.PHASES[self.current_phase]
|
||||
|
||||
# Extract structured data from answer
|
||||
extracted = self._extract_for_phase(phase_name, answer)
|
||||
self.collected_data[phase_name] = extracted
|
||||
|
||||
# Update spec with extracted data
|
||||
spec_update = self._apply_to_spec(phase_name, extracted)
|
||||
|
||||
# Advance to next phase
|
||||
self.current_phase += 1
|
||||
|
||||
return {
|
||||
"phase": phase_name,
|
||||
"extracted": extracted,
|
||||
"spec_update": spec_update,
|
||||
"next_question": self.get_current_question() if self.current_phase < len(self.PHASES) else None,
|
||||
"complete": self.current_phase >= len(self.PHASES)
|
||||
}
|
||||
```
|
||||
|
||||
Claude uses the interview through tools:
|
||||
|
||||
```python
|
||||
async def _tool_start_interview(self, params: Dict) -> str:
|
||||
"""Start guided study creation"""
|
||||
self.interview_state = InterviewEngine(self.spec_store)
|
||||
return {
|
||||
"status": "started",
|
||||
"first_question": self.interview_state.get_current_question()
|
||||
}
|
||||
|
||||
async def _tool_process_answer(self, params: Dict) -> str:
|
||||
"""Process user's answer in interview"""
|
||||
if not self.interview_state:
|
||||
return {"error": "No interview in progress"}
|
||||
|
||||
result = self.interview_state.process_answer(params["answer"])
|
||||
|
||||
if result["spec_update"]:
|
||||
# Spec was updated - this will trigger canvas update
|
||||
return {
|
||||
"status": "updated",
|
||||
"spec_changed": True,
|
||||
"next_question": result["next_question"],
|
||||
"complete": result["complete"]
|
||||
}
|
||||
|
||||
return result
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Frontend Implementation
|
||||
|
||||
### 1. Unified WebSocket Hook
|
||||
|
||||
```typescript
|
||||
// hooks/useAtomizerSocket.ts
|
||||
export function useAtomizerSocket(studyId: string | undefined) {
|
||||
const [spec, setSpec] = useState<AtomizerSpec | null>(null);
|
||||
const [messages, setMessages] = useState<ChatMessage[]>([]);
|
||||
const [isThinking, setIsThinking] = useState(false);
|
||||
const [currentTool, setCurrentTool] = useState<string | null>(null);
|
||||
|
||||
const ws = useRef<WebSocket | null>(null);
|
||||
|
||||
// Single WebSocket connection for everything
|
||||
useEffect(() => {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const host = import.meta.env.DEV ? 'localhost:8001' : window.location.host;
|
||||
ws.current = new WebSocket(`${protocol}//${host}/api/atomizer/ws`);
|
||||
|
||||
ws.current.onmessage = (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
|
||||
switch (data.type) {
|
||||
case 'text':
|
||||
// Streaming text from Claude
|
||||
setMessages(prev => {
|
||||
const last = prev[prev.length - 1];
|
||||
if (last?.role === 'assistant' && !last.complete) {
|
||||
return [...prev.slice(0, -1), {
|
||||
...last,
|
||||
content: last.content + data.content
|
||||
}];
|
||||
}
|
||||
return [...prev, {
|
||||
id: Date.now().toString(),
|
||||
role: 'assistant',
|
||||
content: data.content,
|
||||
complete: false
|
||||
}];
|
||||
});
|
||||
break;
|
||||
|
||||
case 'tool_start':
|
||||
setCurrentTool(data.tool);
|
||||
// Add tool indicator to chat
|
||||
setMessages(prev => [...prev, {
|
||||
id: Date.now().toString(),
|
||||
role: 'tool',
|
||||
tool: data.tool,
|
||||
status: 'running'
|
||||
}]);
|
||||
break;
|
||||
|
||||
case 'tool_result':
|
||||
setCurrentTool(null);
|
||||
// Update tool message with result
|
||||
setMessages(prev => prev.map(m =>
|
||||
m.role === 'tool' && m.tool === data.tool && m.status === 'running'
|
||||
? { ...m, status: 'complete', result: data.result }
|
||||
: m
|
||||
));
|
||||
break;
|
||||
|
||||
case 'spec_updated':
|
||||
// Canvas gets the new spec - this is the magic!
|
||||
setSpec(data.spec);
|
||||
break;
|
||||
|
||||
case 'done':
|
||||
setIsThinking(false);
|
||||
// Mark last message as complete
|
||||
setMessages(prev => prev.map((m, i) =>
|
||||
i === prev.length - 1 ? { ...m, complete: true } : m
|
||||
));
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// Set study context
|
||||
if (studyId) {
|
||||
ws.current.onopen = () => {
|
||||
ws.current?.send(JSON.stringify({
|
||||
type: 'set_study',
|
||||
study_id: studyId
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
return () => ws.current?.close();
|
||||
}, [studyId]);
|
||||
|
||||
// Send message
|
||||
const sendMessage = useCallback((content: string) => {
|
||||
if (!ws.current) return;
|
||||
|
||||
setIsThinking(true);
|
||||
setMessages(prev => [...prev, {
|
||||
id: Date.now().toString(),
|
||||
role: 'user',
|
||||
content
|
||||
}]);
|
||||
|
||||
ws.current.send(JSON.stringify({
|
||||
type: 'message',
|
||||
content
|
||||
}));
|
||||
}, []);
|
||||
|
||||
// Notify Claude about canvas edits
|
||||
const notifyCanvasEdit = useCallback((patch: any) => {
|
||||
ws.current?.send(JSON.stringify({
|
||||
type: 'canvas_edit',
|
||||
patch
|
||||
}));
|
||||
}, []);
|
||||
|
||||
return {
|
||||
spec,
|
||||
messages,
|
||||
isThinking,
|
||||
currentTool,
|
||||
sendMessage,
|
||||
notifyCanvasEdit
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Integrated Canvas View
|
||||
|
||||
```typescript
|
||||
// pages/CanvasView.tsx (revised)
|
||||
export function CanvasView() {
|
||||
const { '*': studyId } = useParams();
|
||||
|
||||
// Single hook manages everything
|
||||
const {
|
||||
spec,
|
||||
messages,
|
||||
isThinking,
|
||||
currentTool,
|
||||
sendMessage,
|
||||
notifyCanvasEdit
|
||||
} = useAtomizerSocket(studyId);
|
||||
|
||||
// When user edits canvas, notify Claude
|
||||
const handleSpecChange = useCallback((newSpec: AtomizerSpec) => {
|
||||
// This is called by SpecRenderer when user makes edits
|
||||
notifyCanvasEdit({
|
||||
type: 'spec_replace',
|
||||
spec: newSpec
|
||||
});
|
||||
}, [notifyCanvasEdit]);
|
||||
|
||||
return (
|
||||
<div className="h-screen flex">
|
||||
{/* Canvas - receives spec from WebSocket */}
|
||||
<div className="flex-1">
|
||||
<SpecRenderer
|
||||
spec={spec}
|
||||
onChange={handleSpecChange} // User edits flow back
|
||||
highlightNode={currentTool ? getAffectedNode(currentTool) : undefined}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Chat Panel */}
|
||||
<div className="w-96 border-l">
|
||||
<ChatPanel
|
||||
messages={messages}
|
||||
isThinking={isThinking}
|
||||
currentTool={currentTool}
|
||||
onSend={sendMessage}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Visual Feedback for Tool Calls
|
||||
|
||||
When Claude calls a tool, the canvas shows visual feedback:
|
||||
|
||||
```typescript
|
||||
// components/canvas/SpecRenderer.tsx
|
||||
function SpecRenderer({ spec, highlightNode, onChange }) {
|
||||
// When a tool is targeting a node, highlight it
|
||||
const getNodeStyle = (nodeId: string) => {
|
||||
if (highlightNode === nodeId) {
|
||||
return {
|
||||
boxShadow: '0 0 0 3px #f59e0b', // Amber glow
|
||||
animation: 'pulse 1s infinite'
|
||||
};
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
// When new nodes are added, animate them
|
||||
const [newNodes, setNewNodes] = useState<Set<string>>(new Set());
|
||||
|
||||
useEffect(() => {
|
||||
if (spec) {
|
||||
const currentIds = new Set([
|
||||
...spec.design_variables.map(d => d.id),
|
||||
...spec.extractors.map(e => e.id),
|
||||
...spec.objectives.map(o => o.id),
|
||||
...spec.constraints.map(c => c.id)
|
||||
]);
|
||||
|
||||
// Find truly new nodes
|
||||
const added = [...currentIds].filter(id => !prevIds.current.has(id));
|
||||
if (added.length > 0) {
|
||||
setNewNodes(new Set(added));
|
||||
setTimeout(() => setNewNodes(new Set()), 1000); // Clear animation
|
||||
}
|
||||
prevIds.current = currentIds;
|
||||
}
|
||||
}, [spec]);
|
||||
|
||||
// Render with animations
|
||||
return (
|
||||
<ReactFlow nodes={nodes.map(n => ({
|
||||
...n,
|
||||
style: {
|
||||
...getNodeStyle(n.id),
|
||||
...(newNodes.has(n.id) ? { animation: 'slideIn 0.5s ease-out' } : {})
|
||||
}
|
||||
}))} />
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## User Experience Flow
|
||||
|
||||
### Flow 1: Create Study Through Chat
|
||||
|
||||
```
|
||||
User: "Create a bracket optimization. I want to minimize mass while keeping
|
||||
stress below 200 MPa. The thickness can vary from 2mm to 10mm."
|
||||
|
||||
Claude: [Internal: Parse intent, no interview needed - user gave full spec]
|
||||
|
||||
🔧 Creating study "bracket_optimization"...
|
||||
🔧 Adding design variable: thickness [2mm - 10mm]
|
||||
🔧 Adding extractor: mass (BDF mass extraction)
|
||||
🔧 Adding extractor: max_stress (von Mises stress)
|
||||
🔧 Adding objective: minimize mass
|
||||
🔧 Adding constraint: stress <= 200 MPa
|
||||
|
||||
✓ Study created! I've configured:
|
||||
- 1 design variable (thickness)
|
||||
- 2 extractors (mass, stress)
|
||||
- 1 objective (minimize mass)
|
||||
- 1 constraint (max stress)
|
||||
|
||||
The canvas shows your optimization setup. You can:
|
||||
- Click any node to adjust settings
|
||||
- Ask me to add more variables or constraints
|
||||
- Say "run" to start optimization
|
||||
|
||||
[Canvas shows: DV→Model→Extractors→Objectives/Constraints, all connected]
|
||||
```
|
||||
|
||||
### Flow 2: Interview-Guided Creation
|
||||
|
||||
```
|
||||
User: "Help me set up a new optimization"
|
||||
|
||||
Claude: Let's set up your optimization step by step.
|
||||
|
||||
First, what's the path to your NX simulation file?
|
||||
(You can drag & drop or type the path)
|
||||
|
||||
User: "studies/M1_Mirror/model.sim"
|
||||
|
||||
Claude: 🔧 Loading model...
|
||||
[tool: introspect_model]
|
||||
|
||||
Found your model! It has 15 expressions. I noticed these look like
|
||||
good design variables:
|
||||
- rib_thickness (current: 8mm)
|
||||
- mirror_depth (current: 50mm)
|
||||
- support_angle (current: 45°)
|
||||
|
||||
What are you trying to optimize?
|
||||
- Minimize mass?
|
||||
- Minimize wavefront error (WFE)?
|
||||
- Both? (I can set up multi-objective)
|
||||
|
||||
[Canvas shows: Model node appears]
|
||||
|
||||
User: "minimize WFE and mass"
|
||||
|
||||
Claude: 🔧 Adding Zernike WFE extractor
|
||||
🔧 Adding mass extractor
|
||||
🔧 Adding objectives (NSGA-II multi-objective)
|
||||
|
||||
Got it - multi-objective optimization for WFE and mass.
|
||||
|
||||
Which parameters should I vary?
|
||||
I suggest: rib_thickness, mirror_depth, support_angle
|
||||
|
||||
[Canvas shows: Model→WFE Extractor→Obj, Model→Mass Extractor→Obj]
|
||||
|
||||
User: "Yes, use those, but keep support_angle fixed"
|
||||
|
||||
Claude: 🔧 Adding design variable: rib_thickness [4mm - 16mm]
|
||||
🔧 Adding design variable: mirror_depth [30mm - 80mm]
|
||||
|
||||
Perfect. Any constraints?
|
||||
- Maximum mass?
|
||||
- Maximum stress?
|
||||
- Minimum frequency?
|
||||
|
||||
[Canvas shows: 2 DVs connected to Model]
|
||||
|
||||
User: "max stress 150 MPa"
|
||||
|
||||
Claude: 🔧 Adding stress extractor
|
||||
🔧 Adding constraint: stress <= 150 MPa
|
||||
|
||||
✓ Configuration complete! Ready to optimize?
|
||||
|
||||
[Canvas shows: Full optimization flow]
|
||||
```
|
||||
|
||||
### Flow 3: User Edits Canvas, Claude Sees
|
||||
|
||||
```
|
||||
[User clicks thickness DV node, changes max from 10mm to 15mm]
|
||||
|
||||
[WebSocket sends: { type: "canvas_edit", patch: { path: "design_variables.0.bounds.max", value: 15 } }]
|
||||
|
||||
Claude: [Receives canvas edit notification in context]
|
||||
|
||||
User: "Is this range reasonable?"
|
||||
|
||||
Claude: I see you changed thickness max to 15mm. That's quite thick for a
|
||||
bracket - typical ranges are 2-10mm.
|
||||
|
||||
With 15mm max, you might see:
|
||||
- Higher mass designs explored
|
||||
- Potentially better stiffness
|
||||
- Longer optimization time (larger search space)
|
||||
|
||||
Want me to adjust or keep it?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: Unified WebSocket (1 week)
|
||||
|
||||
1. **Backend**: Create `/api/atomizer/ws` endpoint
|
||||
- Single connection for chat + spec sync
|
||||
- Streaming response support
|
||||
- Canvas edit notifications
|
||||
|
||||
2. **Frontend**: Create `useAtomizerSocket` hook
|
||||
- Replaces `useChat` + `useSpecWebSocket`
|
||||
- Single source of truth for spec state
|
||||
|
||||
3. **Integration**: Wire SpecRenderer to socket
|
||||
- Receive spec updates from Claude's tools
|
||||
- Send edit notifications back
|
||||
|
||||
### Phase 2: Enhanced Tools (1 week)
|
||||
|
||||
1. Add remaining write tools
|
||||
2. Implement `introspect_model` for NX expression discovery
|
||||
3. Add `create_study` for new study creation
|
||||
4. Add file operation tools
|
||||
|
||||
### Phase 3: Interview Engine (1 week)
|
||||
|
||||
1. Implement `InterviewEngine` class
|
||||
2. Add interview tools to Claude
|
||||
3. Test guided creation flow
|
||||
4. Add smart defaults and recommendations
|
||||
|
||||
### Phase 4: Polish (1 week)
|
||||
|
||||
1. Visual feedback for tool calls
|
||||
2. Node highlight during modification
|
||||
3. Animation for new nodes
|
||||
4. Error recovery and reconnection
|
||||
5. Performance optimization
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
1. **Creation Time**: User can create complete study in <3 minutes through chat
|
||||
2. **Edit Latency**: Canvas updates within 200ms of Claude's tool call
|
||||
3. **Sync Reliability**: 100% of user edits reflected in Claude's context
|
||||
4. **Interview Success**: 90% of studies created through interview are valid
|
||||
|
||||
---
|
||||
|
||||
## Key Differences from Current Implementation
|
||||
|
||||
| Current | Target |
|
||||
|---------|--------|
|
||||
| Separate chat/canvas WebSockets | Single unified WebSocket |
|
||||
| Claude doesn't see canvas state | Real-time canvas state in context |
|
||||
| Manual spec refresh | Automatic spec push on changes |
|
||||
| No interview engine | Guided creation through chat |
|
||||
| Limited tools | Full Claude Code-like tool set |
|
||||
| Mode switching breaks connection | Seamless power mode |
|
||||
|
||||
---
|
||||
|
||||
*This is the architecture that makes Atomizer truly powerful - where Claude and Canvas work together as one system.*
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,502 +0,0 @@
|
||||
# Dashboard Chat Architecture - Task List
|
||||
|
||||
**For**: Ralph Loop Execution
|
||||
**Plan Document**: [DASHBOARD_CHAT_ARCHITECTURE.md](./DASHBOARD_CHAT_ARCHITECTURE.md)
|
||||
**Created**: 2025-01-08
|
||||
|
||||
---
|
||||
|
||||
## Execution Order
|
||||
|
||||
Execute phases in order. Within each phase, tasks can be parallelized where noted.
|
||||
|
||||
---
|
||||
|
||||
## PHASE 1: MCP Server Foundation
|
||||
|
||||
**Goal**: Create Atomizer MCP server that exposes tools to Claude
|
||||
|
||||
### P1.1 - Create MCP Server Scaffold [BLOCKING]
|
||||
|
||||
**Description**: Set up the MCP server project structure
|
||||
|
||||
**Files to create**:
|
||||
- `mcp-server/atomizer-tools/package.json`
|
||||
- `mcp-server/atomizer-tools/tsconfig.json`
|
||||
- `mcp-server/atomizer-tools/src/index.ts`
|
||||
- `mcp-server/atomizer-tools/src/utils/paths.ts`
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] `npm install` succeeds
|
||||
- [ ] `npm run build` succeeds
|
||||
- [ ] Server starts without errors
|
||||
|
||||
**Reference**: See DASHBOARD_CHAT_ARCHITECTURE.md section "Phase 1: MCP Server Foundation"
|
||||
|
||||
---
|
||||
|
||||
### P1.2 - Implement Study Tools [CAN PARALLELIZE with P1.3-P1.6]
|
||||
|
||||
**Description**: Create tools for study management
|
||||
|
||||
**File**: `mcp-server/atomizer-tools/src/tools/study.ts`
|
||||
|
||||
**Tools to implement**:
|
||||
1. `list_studies` - List all available studies with status
|
||||
2. `get_study_status` - Get detailed status of a study
|
||||
3. `create_study` - Create study from natural language description
|
||||
|
||||
**Dependencies**: P1.1
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] list_studies returns array of {name, status, trials}
|
||||
- [ ] get_study_status returns config + results summary
|
||||
- [ ] create_study calls Python StudyCreator
|
||||
|
||||
---
|
||||
|
||||
### P1.3 - Implement Optimization Tools [CAN PARALLELIZE]
|
||||
|
||||
**Description**: Create tools for running optimizations
|
||||
|
||||
**File**: `mcp-server/atomizer-tools/src/tools/optimization.ts`
|
||||
|
||||
**Tools to implement**:
|
||||
1. `run_optimization` - Start optimization for a study
|
||||
2. `stop_optimization` - Stop running optimization
|
||||
3. `get_optimization_status` - Get current optimization state
|
||||
|
||||
**Dependencies**: P1.1
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] run_optimization spawns Python process
|
||||
- [ ] stop_optimization terminates gracefully
|
||||
- [ ] get_optimization_status reads from DB
|
||||
|
||||
---
|
||||
|
||||
### P1.4 - Implement Analysis Tools [CAN PARALLELIZE]
|
||||
|
||||
**Description**: Create tools for analyzing results
|
||||
|
||||
**File**: `mcp-server/atomizer-tools/src/tools/analysis.ts`
|
||||
|
||||
**Tools to implement**:
|
||||
1. `get_trial_data` - Query trials with filters
|
||||
2. `analyze_convergence` - Convergence analysis
|
||||
3. `compare_trials` - Compare multiple trials
|
||||
4. `get_best_design` - Get best design found
|
||||
|
||||
**Dependencies**: P1.1
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] get_trial_data supports: all, best, pareto, recent, failed
|
||||
- [ ] analyze_convergence returns trend metrics
|
||||
- [ ] compare_trials returns comparison table
|
||||
|
||||
---
|
||||
|
||||
### P1.5 - Implement Reporting Tools [CAN PARALLELIZE]
|
||||
|
||||
**Description**: Create tools for generating reports
|
||||
|
||||
**File**: `mcp-server/atomizer-tools/src/tools/reporting.ts`
|
||||
|
||||
**Tools to implement**:
|
||||
1. `generate_report` - Generate markdown report
|
||||
2. `export_data` - Export results to CSV/JSON
|
||||
|
||||
**Dependencies**: P1.1
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] generate_report creates valid markdown
|
||||
- [ ] export_data creates valid CSV/JSON files
|
||||
|
||||
---
|
||||
|
||||
### P1.6 - Implement Physics Tools [CAN PARALLELIZE]
|
||||
|
||||
**Description**: Create tools for FEA explanations
|
||||
|
||||
**File**: `mcp-server/atomizer-tools/src/tools/physics.ts`
|
||||
|
||||
**Tools to implement**:
|
||||
1. `explain_physics` - Explain FEA concepts
|
||||
2. `recommend_method` - Recommend optimization method
|
||||
3. `query_extractors` - List available extractors
|
||||
|
||||
**Dependencies**: P1.1
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] explain_physics uses Atomizer context
|
||||
- [ ] recommend_method considers objectives/DVs
|
||||
|
||||
---
|
||||
|
||||
### P1.7 - Implement Admin Tools (Power Mode) [AFTER P1.2-P1.6]
|
||||
|
||||
**Description**: Create tools for power mode (code modification)
|
||||
|
||||
**File**: `mcp-server/atomizer-tools/src/tools/admin.ts`
|
||||
|
||||
**Tools to implement**:
|
||||
1. `edit_file` - Edit file in codebase
|
||||
2. `create_file` - Create new file
|
||||
3. `create_extractor` - Create new physics extractor
|
||||
4. `run_shell_command` - Run arbitrary shell command
|
||||
5. `search_codebase` - Search files
|
||||
|
||||
**Dependencies**: P1.2-P1.6 (understand patterns first)
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] edit_file validates old_content exists
|
||||
- [ ] create_extractor follows template
|
||||
- [ ] run_shell_command captures output
|
||||
|
||||
**SECURITY**: These tools ONLY available when ATOMIZER_MODE=power
|
||||
|
||||
---
|
||||
|
||||
### P1.8 - Build and Register MCP Server [BLOCKING]
|
||||
|
||||
**Description**: Build server and update Claude config
|
||||
|
||||
**Steps**:
|
||||
1. `cd mcp-server/atomizer-tools && npm run build`
|
||||
2. Update `.claude/settings.local.json` with MCP config
|
||||
3. Test with `claude --mcp-config`
|
||||
|
||||
**Dependencies**: P1.1-P1.7
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] Server builds without errors
|
||||
- [ ] Claude can list tools
|
||||
- [ ] Tools execute correctly
|
||||
|
||||
---
|
||||
|
||||
## PHASE 2: Backend Session Manager
|
||||
|
||||
**Goal**: Manage persistent Claude sessions with MCP
|
||||
|
||||
### P2.1 - Create Conversation Store [BLOCKING]
|
||||
|
||||
**Description**: SQLite persistence for conversations
|
||||
|
||||
**File**: `atomizer-dashboard/backend/api/services/conversation_store.py`
|
||||
|
||||
**Features**:
|
||||
- Sessions table (id, mode, study_id, timestamps)
|
||||
- Messages table (id, session_id, role, content, tool_calls, timestamp)
|
||||
- CRUD operations
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] Database schema created on init
|
||||
- [ ] add_message stores correctly
|
||||
- [ ] get_history returns chronological messages
|
||||
|
||||
---
|
||||
|
||||
### P2.2 - Create Context Builder [CAN PARALLELIZE with P2.1]
|
||||
|
||||
**Description**: Build context prompts for Claude
|
||||
|
||||
**File**: `atomizer-dashboard/backend/api/services/context_builder.py`
|
||||
|
||||
**Features**:
|
||||
- Base context (identity, capabilities)
|
||||
- Study context (config, results)
|
||||
- Mode instructions (user vs power)
|
||||
- Conversation history injection
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] User mode context restricts capabilities
|
||||
- [ ] Power mode context enables all tools
|
||||
- [ ] Study context includes config + status
|
||||
|
||||
---
|
||||
|
||||
### P2.3 - Create Session Manager [AFTER P2.1, P2.2]
|
||||
|
||||
**Description**: Manage Claude Code subprocess sessions
|
||||
|
||||
**File**: `atomizer-dashboard/backend/api/services/session_manager.py`
|
||||
|
||||
**Features**:
|
||||
- Create session (spawn Claude subprocess)
|
||||
- Send message (stdin/stdout communication)
|
||||
- Stream response (async generator)
|
||||
- Switch mode (restart with new config)
|
||||
- Cleanup stale sessions
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] Sessions persist across messages
|
||||
- [ ] Mode switching works
|
||||
- [ ] Cleanup runs periodically
|
||||
|
||||
---
|
||||
|
||||
### P2.4 - Update API Routes [AFTER P2.3]
|
||||
|
||||
**Description**: Add new Claude API endpoints
|
||||
|
||||
**File**: `atomizer-dashboard/backend/api/routes/claude.py`
|
||||
|
||||
**Endpoints**:
|
||||
- `POST /sessions` - Create/resume session
|
||||
- `POST /sessions/{id}/mode` - Switch mode
|
||||
- `WS /sessions/{id}/ws` - WebSocket for chat
|
||||
- Keep legacy endpoints for backwards compatibility
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] Session creation returns session_id
|
||||
- [ ] WebSocket streams responses
|
||||
- [ ] Mode switch requires confirmation
|
||||
|
||||
---
|
||||
|
||||
### P2.5 - Update Main Entry Point [AFTER P2.4]
|
||||
|
||||
**Description**: Initialize session manager on startup
|
||||
|
||||
**File**: `atomizer-dashboard/backend/main.py`
|
||||
|
||||
**Changes**:
|
||||
- Add lifespan handler
|
||||
- Start session manager on startup
|
||||
- Stop session manager on shutdown
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] Manager starts with server
|
||||
- [ ] Manager stops cleanly
|
||||
|
||||
---
|
||||
|
||||
## PHASE 3: Frontend Updates
|
||||
|
||||
**Goal**: Update React UI for new chat system
|
||||
|
||||
### P3.1 - Create Mode Toggle Component [CAN PARALLELIZE]
|
||||
|
||||
**Description**: User/Power mode switcher
|
||||
|
||||
**File**: `atomizer-dashboard/frontend/src/components/chat/ModeToggle.tsx`
|
||||
|
||||
**Features**:
|
||||
- Toggle buttons for User/Power mode
|
||||
- Confirmation modal for Power mode
|
||||
- Visual indication of current mode
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] User mode is default
|
||||
- [ ] Power mode requires confirmation
|
||||
- [ ] Visual feedback on mode change
|
||||
|
||||
---
|
||||
|
||||
### P3.2 - Create Tool Call Card Component [CAN PARALLELIZE]
|
||||
|
||||
**Description**: Display tool calls in messages
|
||||
|
||||
**File**: `atomizer-dashboard/frontend/src/components/chat/ToolCallCard.tsx`
|
||||
|
||||
**Features**:
|
||||
- Expandable card showing tool name
|
||||
- Arguments display
|
||||
- Result display (success/error)
|
||||
- Loading state
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] Shows tool name and status
|
||||
- [ ] Expandable to show details
|
||||
- [ ] Error states displayed clearly
|
||||
|
||||
---
|
||||
|
||||
### P3.3 - Update useChat Hook [AFTER P3.1, P3.2]
|
||||
|
||||
**Description**: WebSocket-based chat with sessions
|
||||
|
||||
**File**: `atomizer-dashboard/frontend/src/hooks/useChat.ts`
|
||||
|
||||
**Changes**:
|
||||
- Session creation on mount
|
||||
- WebSocket connection management
|
||||
- Tool call handling in messages
|
||||
- Mode switching
|
||||
- Reconnection logic
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] Session created on mount
|
||||
- [ ] WebSocket connects and streams
|
||||
- [ ] Tool calls rendered in messages
|
||||
- [ ] Mode switch triggers reconnect
|
||||
|
||||
---
|
||||
|
||||
### P3.4 - Update ChatMessage Component [CAN PARALLELIZE with P3.3]
|
||||
|
||||
**Description**: Support tool calls in messages
|
||||
|
||||
**File**: `atomizer-dashboard/frontend/src/components/chat/ChatMessage.tsx`
|
||||
|
||||
**Changes**:
|
||||
- Import and render ToolCallCard
|
||||
- Update Message interface for toolCalls
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] Tool calls render inline
|
||||
- [ ] Markdown still works
|
||||
- [ ] Streaming cursor shows
|
||||
|
||||
---
|
||||
|
||||
### P3.5 - Update ChatPane Component [AFTER P3.3, P3.4]
|
||||
|
||||
**Description**: Integrate new components
|
||||
|
||||
**File**: `atomizer-dashboard/frontend/src/components/chat/ChatPane.tsx`
|
||||
|
||||
**Changes**:
|
||||
- Add ModeToggle to header
|
||||
- Show connection status
|
||||
- Power mode indicator bar
|
||||
- Pass mode to useChat
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] Mode toggle visible
|
||||
- [ ] Connection status shows
|
||||
- [ ] Power mode has warning bar
|
||||
|
||||
---
|
||||
|
||||
### P3.6 - Update Component Exports [AFTER P3.1-P3.5]
|
||||
|
||||
**Description**: Export new components
|
||||
|
||||
**File**: `atomizer-dashboard/frontend/src/components/chat/index.ts`
|
||||
|
||||
**Changes**:
|
||||
- Export ModeToggle
|
||||
- Export ToolCallCard
|
||||
|
||||
---
|
||||
|
||||
## PHASE 4: Integration & Testing
|
||||
|
||||
**Goal**: Ensure everything works together
|
||||
|
||||
### P4.1 - Integration Test: User Mode [AFTER P1-P3]
|
||||
|
||||
**Test cases**:
|
||||
- [ ] Create new session
|
||||
- [ ] Send message, receive response
|
||||
- [ ] Tool call: list_studies
|
||||
- [ ] Tool call: get_study_status
|
||||
- [ ] Tool call: create_study
|
||||
- [ ] Session persists across page refresh
|
||||
|
||||
---
|
||||
|
||||
### P4.2 - Integration Test: Power Mode [AFTER P4.1]
|
||||
|
||||
**Test cases**:
|
||||
- [ ] Switch to power mode
|
||||
- [ ] Tool call: edit_file
|
||||
- [ ] Tool call: create_extractor
|
||||
- [ ] Tool call: run_shell_command
|
||||
- [ ] Verify changes in filesystem
|
||||
|
||||
---
|
||||
|
||||
### P4.3 - Integration Test: Study Context [AFTER P4.1]
|
||||
|
||||
**Test cases**:
|
||||
- [ ] Navigate to study
|
||||
- [ ] Chat knows study context
|
||||
- [ ] Tool calls use study context
|
||||
- [ ] Context updates on study change
|
||||
|
||||
---
|
||||
|
||||
### P4.4 - Performance Testing [AFTER P4.1-P4.3]
|
||||
|
||||
**Test cases**:
|
||||
- [ ] Response streaming is smooth
|
||||
- [ ] No memory leaks in sessions
|
||||
- [ ] Cleanup works for stale sessions
|
||||
- [ ] Multiple concurrent sessions
|
||||
|
||||
---
|
||||
|
||||
### P4.5 - Documentation Update [AFTER P4.1-P4.4]
|
||||
|
||||
**Files to update**:
|
||||
- [ ] README.md - Add chat architecture section
|
||||
- [ ] CLAUDE.md - Reference new MCP tools
|
||||
- [ ] Add user guide for chat modes
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference: File Map
|
||||
|
||||
```
|
||||
CREATE:
|
||||
├── mcp-server/atomizer-tools/
|
||||
│ ├── package.json
|
||||
│ ├── tsconfig.json
|
||||
│ └── src/
|
||||
│ ├── index.ts
|
||||
│ ├── tools/
|
||||
│ │ ├── study.ts
|
||||
│ │ ├── optimization.ts
|
||||
│ │ ├── analysis.ts
|
||||
│ │ ├── reporting.ts
|
||||
│ │ ├── physics.ts
|
||||
│ │ └── admin.ts
|
||||
│ └── utils/
|
||||
│ └── paths.ts
|
||||
│
|
||||
├── atomizer-dashboard/backend/api/services/
|
||||
│ ├── conversation_store.py
|
||||
│ ├── context_builder.py
|
||||
│ └── session_manager.py
|
||||
│
|
||||
└── atomizer-dashboard/frontend/src/components/chat/
|
||||
├── ModeToggle.tsx
|
||||
└── ToolCallCard.tsx
|
||||
|
||||
UPDATE:
|
||||
├── atomizer-dashboard/backend/api/routes/claude.py
|
||||
├── atomizer-dashboard/backend/main.py
|
||||
├── atomizer-dashboard/frontend/src/hooks/useChat.ts
|
||||
├── atomizer-dashboard/frontend/src/components/chat/ChatMessage.tsx
|
||||
├── atomizer-dashboard/frontend/src/components/chat/ChatPane.tsx
|
||||
└── atomizer-dashboard/frontend/src/components/chat/index.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Estimated Effort
|
||||
|
||||
| Phase | Tasks | Estimated Hours |
|
||||
|-------|-------|-----------------|
|
||||
| Phase 1 | 8 | 6-8 |
|
||||
| Phase 2 | 5 | 4-6 |
|
||||
| Phase 3 | 6 | 4-5 |
|
||||
| Phase 4 | 5 | 3-4 |
|
||||
| **Total** | **24** | **17-23** |
|
||||
|
||||
---
|
||||
|
||||
## Notes for Ralph Loop
|
||||
|
||||
1. **Read the full plan first**: `docs/plans/DASHBOARD_CHAT_ARCHITECTURE.md`
|
||||
2. **Execute in order**: Phase 1 → Phase 2 → Phase 3 → Phase 4
|
||||
3. **Parallelize where noted**: Tasks marked "CAN PARALLELIZE" can run concurrently
|
||||
4. **Test incrementally**: Each phase should be tested before moving on
|
||||
5. **Commit after each phase**: Keep changes atomic and reversible
|
||||
|
||||
---
|
||||
|
||||
*Task List Version: 1.0*
|
||||
@@ -1,693 +0,0 @@
|
||||
# Dashboard Claude Code Integration Plan
|
||||
|
||||
**Date**: January 16, 2026
|
||||
**Status**: 🟢 IMPLEMENTED
|
||||
**Priority**: CRITICAL
|
||||
**Implemented**: January 16, 2026
|
||||
|
||||
---
|
||||
|
||||
## Problem Statement
|
||||
|
||||
The dashboard chat assistant is **fundamentally underpowered** compared to Claude Code CLI. Users expect the same level of intelligence, proactivity, and capability when interacting with the dashboard as they get from the terminal.
|
||||
|
||||
### Current Experience (Terminal - Claude Code CLI)
|
||||
```
|
||||
User: "Add 10 new design variables to the M1 mirror study"
|
||||
|
||||
Claude Code:
|
||||
1. Reads optimization_config.json
|
||||
2. Understands the current structure
|
||||
3. Adds 10 variables with intelligent defaults
|
||||
4. ACTUALLY MODIFIES the file
|
||||
5. Shows the diff
|
||||
6. Can immediately run/test
|
||||
```
|
||||
|
||||
### Current Experience (Dashboard Chat)
|
||||
```
|
||||
User: "Add 10 new design variables"
|
||||
|
||||
Dashboard Chat:
|
||||
1. Calls MCP tool canvas_add_node
|
||||
2. Returns JSON instruction
|
||||
3. Frontend SHOULD apply it but doesn't
|
||||
4. Nothing visible happens
|
||||
5. User frustrated
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Root Cause Analysis
|
||||
|
||||
### Issue 1: MCP Tools Don't Actually Modify Anything
|
||||
|
||||
The current MCP tools (`canvas_add_node`, etc.) just return instructions like:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"modification": {
|
||||
"action": "add_node",
|
||||
"nodeType": "designVar",
|
||||
"data": {...}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The **frontend is supposed to receive and apply these**, but:
|
||||
- WebSocket message handling may not process tool results
|
||||
- No automatic application of modifications
|
||||
- User sees "success" message but nothing changes
|
||||
|
||||
### Issue 2: Claude API vs Claude Code CLI
|
||||
|
||||
| Capability | Claude API (Dashboard) | Claude Code CLI (Terminal) |
|
||||
|------------|------------------------|---------------------------|
|
||||
| Read files | Via MCP tool | Native |
|
||||
| Write files | Via MCP tool (limited) | Native |
|
||||
| Run commands | Via MCP tool (limited) | Native |
|
||||
| Edit in place | NO | YES |
|
||||
| Git operations | NO | YES |
|
||||
| Multi-step reasoning | Limited | Full |
|
||||
| Tool chaining | Awkward | Natural |
|
||||
| Context window | 200k | Unlimited (summarization) |
|
||||
|
||||
### Issue 3: Model Capability Gap
|
||||
|
||||
Dashboard uses Claude API (likely Sonnet or Haiku for cost). Terminal uses **Opus 4.5** with full Claude Code capabilities.
|
||||
|
||||
---
|
||||
|
||||
## Proposed Solution: Claude Code CLI Backend
|
||||
|
||||
Instead of MCP tools calling Python scripts, **spawn actual Claude Code CLI sessions** in the backend that have full power.
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ DASHBOARD FRONTEND │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Canvas Builder │ Chat Panel │ Study Views │ Results │
|
||||
└────────┬────────────────┬─────────────────────────────────────┬─┘
|
||||
│ │ │
|
||||
│ WebSocket │ REST API │
|
||||
▼ ▼ │
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ BACKEND (FastAPI) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ CLAUDE CODE SESSION MANAGER │ │
|
||||
│ │ │ │
|
||||
│ │ - Spawns claude CLI processes │ │
|
||||
│ │ - Maintains conversation context │ │
|
||||
│ │ - Streams output back to frontend │ │
|
||||
│ │ - Has FULL Atomizer codebase access │ │
|
||||
│ │ - Uses Opus 4.5 model │ │
|
||||
│ │ - Can edit files, run commands, modify studies │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ ATOMIZER CODEBASE │ │
|
||||
│ │ │ │
|
||||
│ │ studies/ optimization_engine/ │ │
|
||||
│ │ M1_Mirror/ extractors/ │ │
|
||||
│ │ optimization_config.json runner.py │ │
|
||||
│ │ run_optimization.py ... │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Key Changes
|
||||
|
||||
1. **Backend spawns Claude Code CLI** instead of calling Claude API
|
||||
2. **Full file system access** - Claude can read/write any file
|
||||
3. **Full command execution** - Run Python, git, npm, etc.
|
||||
4. **Opus 4.5 model** - Same intelligence as terminal
|
||||
5. **Stream output** - Real-time feedback to user
|
||||
6. **Canvas sync** - After Claude modifies files, canvas reloads from config
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: Claude Code CLI Session Manager
|
||||
|
||||
**File**: `atomizer-dashboard/backend/api/services/claude_code_session.py`
|
||||
|
||||
```python
|
||||
"""
|
||||
Claude Code CLI Session Manager
|
||||
|
||||
Spawns actual Claude Code CLI processes with full Atomizer access.
|
||||
This gives dashboard users the same power as terminal users.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import AsyncGenerator, Dict, List, Optional
|
||||
|
||||
ATOMIZER_ROOT = Path(__file__).parent.parent.parent.parent.parent
|
||||
|
||||
class ClaudeCodeSession:
|
||||
"""
|
||||
Manages a Claude Code CLI session.
|
||||
|
||||
Unlike MCP tools, this spawns the actual claude CLI which has:
|
||||
- Full file system access
|
||||
- Full command execution
|
||||
- Opus 4.5 model
|
||||
- All Claude Code capabilities
|
||||
"""
|
||||
|
||||
def __init__(self, session_id: str, study_id: Optional[str] = None):
|
||||
self.session_id = session_id
|
||||
self.study_id = study_id
|
||||
self.canvas_state: Optional[Dict] = None # Current canvas state from frontend
|
||||
self.working_dir = ATOMIZER_ROOT
|
||||
if study_id:
|
||||
study_path = ATOMIZER_ROOT / "studies" / study_id
|
||||
if study_path.exists():
|
||||
self.working_dir = study_path
|
||||
|
||||
def set_canvas_state(self, canvas_state: Dict):
|
||||
"""Update canvas state from frontend"""
|
||||
self.canvas_state = canvas_state
|
||||
|
||||
async def send_message(self, message: str) -> AsyncGenerator[str, None]:
|
||||
"""
|
||||
Send message to Claude Code CLI and stream response.
|
||||
|
||||
Uses claude CLI with:
|
||||
- --print for output
|
||||
- --dangerously-skip-permissions for full access (controlled environment)
|
||||
- Runs from Atomizer root to get CLAUDE.md context automatically
|
||||
- Study-specific context injected into prompt
|
||||
"""
|
||||
# Build study-specific context
|
||||
study_context = self._build_study_context() if self.study_id else ""
|
||||
|
||||
# The user's message with study context prepended
|
||||
full_message = f"""## Current Study Context
|
||||
{study_context}
|
||||
|
||||
## User Request
|
||||
{message}
|
||||
|
||||
Remember: You have FULL power to edit files. Make the actual changes, don't just describe them."""
|
||||
|
||||
# Write prompt to a temp file (better than stdin for complex prompts)
|
||||
prompt_file = ATOMIZER_ROOT / f".claude-prompt-{self.session_id}.md"
|
||||
prompt_file.write_text(full_message)
|
||||
|
||||
try:
|
||||
# Spawn claude CLI from ATOMIZER_ROOT so it picks up CLAUDE.md
|
||||
# This gives it full Atomizer context automatically
|
||||
process = await asyncio.create_subprocess_exec(
|
||||
"claude",
|
||||
"--print",
|
||||
"--dangerously-skip-permissions", # Full access in controlled env
|
||||
"-p", str(prompt_file), # Read prompt from file
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
cwd=str(ATOMIZER_ROOT), # Run from root to get CLAUDE.md
|
||||
env={
|
||||
**os.environ,
|
||||
"ATOMIZER_STUDY": self.study_id or "",
|
||||
"ATOMIZER_STUDY_PATH": str(self.working_dir),
|
||||
}
|
||||
)
|
||||
|
||||
# Stream output
|
||||
stdout, stderr = await process.communicate()
|
||||
|
||||
if stdout:
|
||||
yield stdout.decode()
|
||||
if stderr and process.returncode != 0:
|
||||
yield f"\n[Error]: {stderr.decode()}"
|
||||
|
||||
finally:
|
||||
# Clean up prompt file
|
||||
if prompt_file.exists():
|
||||
prompt_file.unlink()
|
||||
|
||||
def _build_system_prompt(self) -> str:
|
||||
"""Build Atomizer-aware system prompt with full context"""
|
||||
|
||||
# Load CLAUDE.md for Atomizer system instructions
|
||||
claude_md_path = ATOMIZER_ROOT / "CLAUDE.md"
|
||||
claude_md_content = ""
|
||||
if claude_md_path.exists():
|
||||
claude_md_content = claude_md_path.read_text()
|
||||
|
||||
# Load study-specific context
|
||||
study_context = ""
|
||||
if self.study_id:
|
||||
study_context = self._build_study_context()
|
||||
|
||||
prompt = f"""# Atomizer Dashboard Assistant
|
||||
|
||||
You are running as the Atomizer Dashboard Assistant with FULL Claude Code CLI capabilities.
|
||||
You have the same power as a terminal Claude Code session.
|
||||
|
||||
## Atomizer System Instructions
|
||||
{claude_md_content[:8000]} # Truncate if too long
|
||||
|
||||
## Your Capabilities
|
||||
|
||||
You can and MUST:
|
||||
- Read and EDIT any file in the codebase
|
||||
- Modify optimization_config.json directly
|
||||
- Update run_optimization.py
|
||||
- Run Python scripts
|
||||
- Execute git commands
|
||||
- Create new studies
|
||||
- Modify existing studies
|
||||
|
||||
When the user asks to add design variables, objectives, or other config changes:
|
||||
1. Read the current config file
|
||||
2. Make the actual modifications using Edit tool
|
||||
3. Save the file
|
||||
4. Report what you changed with a diff
|
||||
|
||||
DO NOT just return instructions - ACTUALLY MAKE THE CHANGES.
|
||||
|
||||
## Current Context
|
||||
|
||||
**Atomizer Root**: {ATOMIZER_ROOT}
|
||||
**Working Directory**: {self.working_dir}
|
||||
|
||||
{study_context}
|
||||
|
||||
## Important Paths
|
||||
|
||||
- Studies: {ATOMIZER_ROOT / 'studies'}
|
||||
- Extractors: {ATOMIZER_ROOT / 'optimization_engine' / 'extractors'}
|
||||
- Protocols: {ATOMIZER_ROOT / 'docs' / 'protocols'}
|
||||
|
||||
## After Making Changes
|
||||
|
||||
After modifying any study files:
|
||||
1. Confirm the changes were saved
|
||||
2. Show the relevant diff
|
||||
3. The dashboard canvas will auto-refresh to reflect your changes
|
||||
"""
|
||||
return prompt
|
||||
|
||||
def _build_study_context(self) -> str:
|
||||
"""Build detailed context for the active study"""
|
||||
context = f"## Active Study: {self.study_id}\n\n"
|
||||
|
||||
# Find and read optimization_config.json
|
||||
config_path = self.working_dir / "1_setup" / "optimization_config.json"
|
||||
if not config_path.exists():
|
||||
config_path = self.working_dir / "optimization_config.json"
|
||||
|
||||
if config_path.exists():
|
||||
import json
|
||||
try:
|
||||
config = json.loads(config_path.read_text())
|
||||
context += f"**Config File**: `{config_path}`\n\n"
|
||||
|
||||
# Design variables summary
|
||||
dvs = config.get("design_variables", [])
|
||||
if dvs:
|
||||
context += "### Design Variables\n\n"
|
||||
context += "| Name | Min | Max | Baseline | Unit |\n"
|
||||
context += "|------|-----|-----|----------|------|\n"
|
||||
for dv in dvs[:15]:
|
||||
name = dv.get("name", dv.get("expression_name", "?"))
|
||||
min_v = dv.get("min", dv.get("lower", "?"))
|
||||
max_v = dv.get("max", dv.get("upper", "?"))
|
||||
baseline = dv.get("baseline", "-")
|
||||
unit = dv.get("units", dv.get("unit", "-"))
|
||||
context += f"| {name} | {min_v} | {max_v} | {baseline} | {unit} |\n"
|
||||
if len(dvs) > 15:
|
||||
context += f"\n*... and {len(dvs) - 15} more*\n"
|
||||
context += "\n"
|
||||
|
||||
# Objectives
|
||||
objs = config.get("objectives", [])
|
||||
if objs:
|
||||
context += "### Objectives\n\n"
|
||||
for obj in objs:
|
||||
name = obj.get("name", "?")
|
||||
direction = obj.get("direction", "minimize")
|
||||
weight = obj.get("weight", 1)
|
||||
context += f"- **{name}**: {direction} (weight: {weight})\n"
|
||||
context += "\n"
|
||||
|
||||
# Extraction method (for Zernike)
|
||||
ext_method = config.get("extraction_method", {})
|
||||
if ext_method:
|
||||
context += "### Extraction Method\n\n"
|
||||
context += f"- Type: {ext_method.get('type', '?')}\n"
|
||||
context += f"- Class: {ext_method.get('class', '?')}\n"
|
||||
if ext_method.get("inner_radius"):
|
||||
context += f"- Inner Radius: {ext_method.get('inner_radius')}\n"
|
||||
context += "\n"
|
||||
|
||||
# Zernike settings
|
||||
zernike = config.get("zernike_settings", {})
|
||||
if zernike:
|
||||
context += "### Zernike Settings\n\n"
|
||||
context += f"- Modes: {zernike.get('n_modes', '?')}\n"
|
||||
context += f"- Filter Low Orders: {zernike.get('filter_low_orders', '?')}\n"
|
||||
context += f"- Subcases: {zernike.get('subcases', [])}\n"
|
||||
context += "\n"
|
||||
|
||||
# Algorithm
|
||||
method = config.get("method", config.get("optimization", {}).get("sampler", "TPE"))
|
||||
max_trials = config.get("max_trials", config.get("optimization", {}).get("n_trials", 100))
|
||||
context += f"### Algorithm\n\n"
|
||||
context += f"- Method: {method}\n"
|
||||
context += f"- Max Trials: {max_trials}\n\n"
|
||||
|
||||
except Exception as e:
|
||||
context += f"*Error reading config: {e}*\n\n"
|
||||
else:
|
||||
context += "*No optimization_config.json found*\n\n"
|
||||
|
||||
# Check for run_optimization.py
|
||||
run_opt_path = self.working_dir / "run_optimization.py"
|
||||
if run_opt_path.exists():
|
||||
context += f"**Run Script**: `{run_opt_path}` (exists)\n\n"
|
||||
|
||||
# Check results
|
||||
db_path = self.working_dir / "3_results" / "study.db"
|
||||
if db_path.exists():
|
||||
context += "**Results Database**: exists\n"
|
||||
# Could query trial count here
|
||||
else:
|
||||
context += "**Results Database**: not found (no optimization run yet)\n"
|
||||
|
||||
return context
|
||||
```
|
||||
|
||||
### Phase 2: WebSocket Handler for Claude Code
|
||||
|
||||
**File**: `atomizer-dashboard/backend/api/routes/claude_code.py`
|
||||
|
||||
```python
|
||||
"""
|
||||
Claude Code WebSocket Routes
|
||||
|
||||
Provides WebSocket endpoint that connects to actual Claude Code CLI.
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
|
||||
from api.services.claude_code_session import ClaudeCodeSession
|
||||
import uuid
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
# Active sessions
|
||||
sessions: Dict[str, ClaudeCodeSession] = {}
|
||||
|
||||
@router.websocket("/ws/{study_id}")
|
||||
async def claude_code_websocket(websocket: WebSocket, study_id: str = None):
|
||||
"""
|
||||
WebSocket for full Claude Code CLI access.
|
||||
|
||||
This gives dashboard users the SAME power as terminal users.
|
||||
"""
|
||||
await websocket.accept()
|
||||
|
||||
session_id = str(uuid.uuid4())[:8]
|
||||
session = ClaudeCodeSession(session_id, study_id)
|
||||
sessions[session_id] = session
|
||||
|
||||
try:
|
||||
while True:
|
||||
data = await websocket.receive_json()
|
||||
|
||||
if data.get("type") == "message":
|
||||
content = data.get("content", "")
|
||||
|
||||
# Stream response from Claude Code CLI
|
||||
async for chunk in session.send_message(content):
|
||||
await websocket.send_json({
|
||||
"type": "text",
|
||||
"content": chunk,
|
||||
})
|
||||
|
||||
await websocket.send_json({"type": "done"})
|
||||
|
||||
# After response, trigger canvas refresh
|
||||
await websocket.send_json({
|
||||
"type": "refresh_canvas",
|
||||
"study_id": study_id,
|
||||
})
|
||||
|
||||
except WebSocketDisconnect:
|
||||
sessions.pop(session_id, None)
|
||||
```
|
||||
|
||||
### Phase 3: Frontend - Use Claude Code Endpoint
|
||||
|
||||
**File**: `atomizer-dashboard/frontend/src/hooks/useClaudeCode.ts`
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Hook for Claude Code CLI integration
|
||||
*
|
||||
* Connects to backend that spawns actual Claude Code CLI processes.
|
||||
* This gives full power: file editing, command execution, etc.
|
||||
*/
|
||||
|
||||
export function useClaudeCode(studyId?: string) {
|
||||
const [messages, setMessages] = useState<Message[]>([]);
|
||||
const [isThinking, setIsThinking] = useState(false);
|
||||
const wsRef = useRef<WebSocket | null>(null);
|
||||
|
||||
// Reload canvas after Claude makes changes
|
||||
const { loadFromConfig } = useCanvasStore();
|
||||
|
||||
useEffect(() => {
|
||||
// Connect to Claude Code WebSocket
|
||||
const ws = new WebSocket(`ws://${location.host}/api/claude-code/ws/${studyId || ''}`);
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
|
||||
if (data.type === 'text') {
|
||||
// Stream Claude's response
|
||||
appendToLastMessage(data.content);
|
||||
}
|
||||
else if (data.type === 'done') {
|
||||
setIsThinking(false);
|
||||
}
|
||||
else if (data.type === 'refresh_canvas') {
|
||||
// Claude made file changes - reload canvas from config
|
||||
reloadCanvasFromStudy(data.study_id);
|
||||
}
|
||||
};
|
||||
|
||||
wsRef.current = ws;
|
||||
return () => ws.close();
|
||||
}, [studyId]);
|
||||
|
||||
const sendMessage = async (content: string) => {
|
||||
setIsThinking(true);
|
||||
addMessage({ role: 'user', content });
|
||||
addMessage({ role: 'assistant', content: '', isStreaming: true });
|
||||
|
||||
wsRef.current?.send(JSON.stringify({
|
||||
type: 'message',
|
||||
content,
|
||||
}));
|
||||
};
|
||||
|
||||
return { messages, isThinking, sendMessage };
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 4: Canvas Auto-Refresh
|
||||
|
||||
When Claude modifies `optimization_config.json`, the canvas should automatically reload:
|
||||
|
||||
```typescript
|
||||
// In AtomizerCanvas.tsx or useCanvasChat.ts
|
||||
|
||||
const reloadCanvasFromStudy = async (studyId: string) => {
|
||||
// Fetch fresh config from backend
|
||||
const response = await fetch(`/api/studies/${studyId}/config`);
|
||||
const config = await response.json();
|
||||
|
||||
// Reload canvas
|
||||
loadFromConfig(config);
|
||||
|
||||
// Notify user
|
||||
showNotification('Canvas updated with Claude\'s changes');
|
||||
};
|
||||
```
|
||||
|
||||
### Phase 5: Smart Prompting for Canvas Context
|
||||
|
||||
When user sends a message from canvas view, include canvas state:
|
||||
|
||||
```typescript
|
||||
const sendCanvasMessage = (userMessage: string) => {
|
||||
const canvasContext = generateCanvasMarkdown();
|
||||
|
||||
const enrichedMessage = `
|
||||
## Current Canvas State
|
||||
${canvasContext}
|
||||
|
||||
## User Request
|
||||
${userMessage}
|
||||
|
||||
When making changes, modify the actual optimization_config.json file.
|
||||
After changes, the canvas will auto-refresh.
|
||||
`;
|
||||
|
||||
sendMessage(enrichedMessage);
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Expected Behavior After Implementation
|
||||
|
||||
### Example 1: Add Design Variables
|
||||
```
|
||||
User: "Add 10 new design variables for hole diameters, range 5-25mm"
|
||||
|
||||
Claude Code (in dashboard):
|
||||
1. Reads studies/M1_Mirror/.../optimization_config.json
|
||||
2. Adds 10 entries to design_variables array:
|
||||
- hole_diameter_1: [5, 25] mm
|
||||
- hole_diameter_2: [5, 25] mm
|
||||
- ... (10 total)
|
||||
3. WRITES the file
|
||||
4. Reports: "Added 10 design variables to optimization_config.json"
|
||||
5. Frontend receives "refresh_canvas" signal
|
||||
6. Canvas reloads and shows 10 new nodes
|
||||
7. User sees actual changes
|
||||
```
|
||||
|
||||
### Example 2: Modify Optimization
|
||||
```
|
||||
User: "Change the algorithm to CMA-ES with 500 trials and add a stress constraint < 200 MPa"
|
||||
|
||||
Claude Code (in dashboard):
|
||||
1. Reads config
|
||||
2. Changes method: "TPE" -> "CMA-ES"
|
||||
3. Changes max_trials: 100 -> 500
|
||||
4. Adds constraint: {name: "stress_limit", operator: "<=", value: 200, unit: "MPa"}
|
||||
5. WRITES the file
|
||||
6. Reports changes
|
||||
7. Canvas refreshes with updated algorithm node and new constraint node
|
||||
```
|
||||
|
||||
### Example 3: Complex Multi-File Changes
|
||||
```
|
||||
User: "Add a new Zernike extractor for the secondary mirror and connect it to a new objective"
|
||||
|
||||
Claude Code (in dashboard):
|
||||
1. Reads config
|
||||
2. Adds extractor to extractors array
|
||||
3. Adds objective connected to extractor
|
||||
4. If needed, modifies run_optimization.py to import new extractor
|
||||
5. WRITES all modified files
|
||||
6. Canvas refreshes with new extractor and objective nodes, properly connected
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
### Phase 1: Backend Claude Code Session
|
||||
- [x] Create `claude_code_session.py` with session manager
|
||||
- [x] Implement `send_message()` with CLI spawning
|
||||
- [x] Build Atomizer-aware system prompt
|
||||
- [x] Handle study context (working directory)
|
||||
- [x] Stream output properly
|
||||
|
||||
### Phase 2: WebSocket Route
|
||||
- [x] Create `/api/claude-code/ws/{study_id}` endpoint
|
||||
- [x] Handle message routing
|
||||
- [x] Implement `refresh_canvas` signal
|
||||
- [x] Session cleanup on disconnect
|
||||
|
||||
### Phase 3: Frontend Hook
|
||||
- [x] Create `useClaudeCode.ts` hook
|
||||
- [x] Connect to Claude Code WebSocket
|
||||
- [x] Handle streaming responses
|
||||
- [x] Handle canvas refresh signals
|
||||
|
||||
### Phase 4: Canvas Auto-Refresh
|
||||
- [x] Add `reloadCanvasFromStudy()` function
|
||||
- [x] Wire refresh signal to canvas store
|
||||
- [x] Add loading state during refresh
|
||||
- [x] Show notification on refresh (system message)
|
||||
|
||||
### Phase 5: Chat Panel Integration
|
||||
- [x] Update ChatPanel to use `useClaudeCode`
|
||||
- [x] Include canvas context in messages
|
||||
- [x] Add "Claude Code" indicator in UI (mode toggle)
|
||||
- [x] Show when Claude is editing files
|
||||
|
||||
### Phase 6: Testing
|
||||
- [ ] Test adding design variables
|
||||
- [ ] Test modifying objectives
|
||||
- [ ] Test complex multi-file changes
|
||||
- [ ] Test canvas refresh after changes
|
||||
- [ ] Test error handling
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### Files Created/Modified
|
||||
|
||||
**Backend:**
|
||||
- `atomizer-dashboard/backend/api/services/claude_code_session.py` - New session manager
|
||||
- `atomizer-dashboard/backend/api/routes/claude_code.py` - New WebSocket routes
|
||||
- `atomizer-dashboard/backend/api/main.py` - Added claude_code router
|
||||
|
||||
**Frontend:**
|
||||
- `atomizer-dashboard/frontend/src/hooks/useClaudeCode.ts` - New hook for Claude Code CLI
|
||||
- `atomizer-dashboard/frontend/src/components/canvas/AtomizerCanvas.tsx` - Added mode toggle
|
||||
- `atomizer-dashboard/frontend/src/components/chat/ChatMessage.tsx` - Added system message support
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
Claude Code CLI with `--dangerously-skip-permissions` has full system access. Mitigations:
|
||||
|
||||
1. **Sandboxed environment**: Dashboard runs on user's machine, not public server
|
||||
2. **Study-scoped working directory**: Claude starts in study folder
|
||||
3. **Audit logging**: Log all file modifications
|
||||
4. **User confirmation**: Option to require approval for destructive operations
|
||||
|
||||
---
|
||||
|
||||
## Cost Considerations
|
||||
|
||||
Using Opus 4.5 via Claude Code CLI is more expensive than Sonnet API. Options:
|
||||
|
||||
1. **Default to Sonnet, upgrade on request**: "Use full power mode" button
|
||||
2. **Per-session token budget**: Warn user when approaching limit
|
||||
3. **Cache common operations**: Pre-generate responses for common tasks
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
1. **Parity with terminal**: Dashboard chat can do everything Claude Code CLI can
|
||||
2. **Real modifications**: Files actually change, not just instructions
|
||||
3. **Canvas sync**: Canvas reflects file changes immediately
|
||||
4. **Intelligent defaults**: Claude makes smart choices without asking clarifying questions
|
||||
5. **Proactive behavior**: Claude anticipates needs and handles edge cases
|
||||
|
||||
---
|
||||
|
||||
*This document to be implemented by Claude Code CLI*
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,637 +0,0 @@
|
||||
# Dashboard Intake & AtomizerSpec Integration Plan
|
||||
|
||||
**Version**: 1.0
|
||||
**Author**: Atomizer Team
|
||||
**Date**: January 22, 2026
|
||||
**Status**: APPROVED FOR IMPLEMENTATION
|
||||
**Dependencies**: ATOMIZER_UX_SYSTEM.md, UNIFIED_CONFIGURATION_ARCHITECTURE.md
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This plan implements visual study creation in the Atomizer Dashboard, with `atomizer_spec.json` as the **single source of truth** for all study configuration. Engineers can:
|
||||
|
||||
1. **Drop files** into the dashboard to create a new study
|
||||
2. **See introspection results** inline (expressions, mass, solver type)
|
||||
3. **Open Canvas** for detailed configuration (one-click from create card)
|
||||
4. **Generate README with Claude** (intelligent, not template-based)
|
||||
5. **Run baseline solve** with real-time progress via WebSocket
|
||||
6. **Finalize** to move study from inbox to studies folder
|
||||
|
||||
**Key Principle**: Every operation reads from or writes to `atomizer_spec.json`. Nothing bypasses the spec.
|
||||
|
||||
---
|
||||
|
||||
## 1. Architecture Overview
|
||||
|
||||
### 1.1 AtomizerSpec as Central Data Hub
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ATOMIZER_SPEC.JSON - CENTRAL DATA HUB │
|
||||
├─────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ INPUTS (write to spec) SPEC OUTPUTS (read spec) │
|
||||
│ ┌──────────────────┐ ┌──────────┐ ┌──────────────────┐ │
|
||||
│ │ File Upload │ │ │ │ Canvas Builder │ │
|
||||
│ │ Introspection │ ────────→ │ atomizer │ ────────→ │ Dashboard Views │ │
|
||||
│ │ Claude Interview │ │ _spec │ │ Optimization Run │ │
|
||||
│ │ Canvas Edits │ │ .json │ │ README Generator │ │
|
||||
│ │ Manual Edit │ │ │ │ Report Generator │ │
|
||||
│ └──────────────────┘ └──────────┘ └──────────────────┘ │
|
||||
│ │ │
|
||||
│ │ validates against │
|
||||
│ ↓ │
|
||||
│ ┌──────────────────┐ │
|
||||
│ │ atomizer_spec │ │
|
||||
│ │ _v2.json │ │
|
||||
│ │ (JSON Schema) │ │
|
||||
│ └──────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.2 Study Creation Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ STUDY CREATION FLOW │
|
||||
├─────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. DROP FILES 2. INTROSPECT 3. CLAUDE README 4. FINALIZE │
|
||||
│ ┌────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │
|
||||
│ │ .sim .prt │ → │ Expressions │ → │ Analyzes │ → │ Baseline │ │
|
||||
│ │ .fem _i.prt│ │ Mass props │ │ context+model│ │ solve │ │
|
||||
│ │ goals.md │ │ Solver type │ │ Writes full │ │ Update │ │
|
||||
│ └────────────┘ └──────────────┘ │ README.md │ │ README │ │
|
||||
│ │ │ └──────────────┘ │ Archive │ │
|
||||
│ ↓ ↓ │ │ inbox │ │
|
||||
│ Creates initial Updates spec Claude skill └──────────┘ │
|
||||
│ atomizer_spec.json with introspection for study docs │ │
|
||||
│ status="draft" status="introspected" ↓ │
|
||||
│ studies/ │
|
||||
│ {topic}/ │
|
||||
│ {name}/ │
|
||||
└─────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.3 Spec Status State Machine
|
||||
|
||||
```
|
||||
draft → introspected → configured → validated → ready → running → completed
|
||||
│ │ │ │ │ │ │
|
||||
│ │ │ │ │ │ └─ optimization done
|
||||
│ │ │ │ │ └─ optimization started
|
||||
│ │ │ │ └─ can start optimization
|
||||
│ │ │ └─ baseline solve done
|
||||
│ │ └─ DVs, objectives, constraints set (Claude or Canvas)
|
||||
│ └─ introspection done
|
||||
└─ files uploaded, minimal spec created
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. AtomizerSpec Schema Extensions
|
||||
|
||||
### 2.1 New Fields in SpecMeta
|
||||
|
||||
Add to `optimization_engine/config/spec_models.py`:
|
||||
|
||||
```python
|
||||
class SpecStatus(str, Enum):
|
||||
"""Study lifecycle status."""
|
||||
DRAFT = "draft"
|
||||
INTROSPECTED = "introspected"
|
||||
CONFIGURED = "configured"
|
||||
VALIDATED = "validated"
|
||||
READY = "ready"
|
||||
RUNNING = "running"
|
||||
COMPLETED = "completed"
|
||||
FAILED = "failed"
|
||||
|
||||
|
||||
class SpecCreatedBy(str, Enum):
|
||||
"""Who/what created the spec."""
|
||||
CANVAS = "canvas"
|
||||
CLAUDE = "claude"
|
||||
API = "api"
|
||||
MIGRATION = "migration"
|
||||
MANUAL = "manual"
|
||||
DASHBOARD_INTAKE = "dashboard_intake" # NEW
|
||||
|
||||
|
||||
class SpecMeta(BaseModel):
|
||||
"""Metadata about the spec."""
|
||||
version: str = Field(..., pattern=r"^2\.\d+$")
|
||||
study_name: str
|
||||
created: Optional[datetime] = None
|
||||
modified: Optional[datetime] = None
|
||||
created_by: Optional[SpecCreatedBy] = None
|
||||
modified_by: Optional[str] = None
|
||||
status: SpecStatus = SpecStatus.DRAFT # NEW
|
||||
topic: Optional[str] = None # NEW - folder grouping
|
||||
```
|
||||
|
||||
### 2.2 IntrospectionData Model
|
||||
|
||||
New model for storing introspection results in the spec:
|
||||
|
||||
```python
|
||||
class ExpressionInfo(BaseModel):
|
||||
"""Information about an NX expression."""
|
||||
name: str
|
||||
value: Optional[float] = None
|
||||
units: Optional[str] = None
|
||||
formula: Optional[str] = None
|
||||
is_candidate: bool = False
|
||||
confidence: float = 0.0 # 0.0 to 1.0
|
||||
|
||||
|
||||
class BaselineData(BaseModel):
|
||||
"""Results from baseline FEA solve."""
|
||||
timestamp: datetime
|
||||
solve_time_seconds: float
|
||||
mass_kg: Optional[float] = None
|
||||
max_displacement_mm: Optional[float] = None
|
||||
max_stress_mpa: Optional[float] = None
|
||||
success: bool = True
|
||||
error: Optional[str] = None
|
||||
|
||||
|
||||
class IntrospectionData(BaseModel):
|
||||
"""Model introspection results."""
|
||||
timestamp: datetime
|
||||
solver_type: Optional[str] = None
|
||||
mass_kg: Optional[float] = None
|
||||
volume_mm3: Optional[float] = None
|
||||
expressions: List[ExpressionInfo] = []
|
||||
baseline: Optional[BaselineData] = None
|
||||
warnings: List[str] = []
|
||||
```
|
||||
|
||||
### 2.3 Extended ModelConfig
|
||||
|
||||
```python
|
||||
class ModelConfig(BaseModel):
|
||||
"""Model file configuration."""
|
||||
sim: Optional[SimFile] = None
|
||||
fem: Optional[str] = None
|
||||
prt: Optional[str] = None
|
||||
idealized_prt: Optional[str] = None # NEW - critical for mesh updating
|
||||
introspection: Optional[IntrospectionData] = None # NEW
|
||||
```
|
||||
|
||||
### 2.4 JSON Schema Updates
|
||||
|
||||
Add to `optimization_engine/schemas/atomizer_spec_v2.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"definitions": {
|
||||
"SpecMeta": {
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["draft", "introspected", "configured", "validated", "ready", "running", "completed", "failed"],
|
||||
"default": "draft"
|
||||
},
|
||||
"topic": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-Za-z0-9_]+$",
|
||||
"description": "Topic folder for grouping related studies"
|
||||
}
|
||||
}
|
||||
},
|
||||
"IntrospectionData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"timestamp": { "type": "string", "format": "date-time" },
|
||||
"solver_type": { "type": "string" },
|
||||
"mass_kg": { "type": "number" },
|
||||
"volume_mm3": { "type": "number" },
|
||||
"expressions": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/ExpressionInfo" }
|
||||
},
|
||||
"baseline": { "$ref": "#/definitions/BaselineData" },
|
||||
"warnings": { "type": "array", "items": { "type": "string" } }
|
||||
}
|
||||
},
|
||||
"ExpressionInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": { "type": "string" },
|
||||
"value": { "type": "number" },
|
||||
"units": { "type": "string" },
|
||||
"formula": { "type": "string" },
|
||||
"is_candidate": { "type": "boolean", "default": false },
|
||||
"confidence": { "type": "number", "minimum": 0, "maximum": 1 }
|
||||
},
|
||||
"required": ["name"]
|
||||
},
|
||||
"BaselineData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"timestamp": { "type": "string", "format": "date-time" },
|
||||
"solve_time_seconds": { "type": "number" },
|
||||
"mass_kg": { "type": "number" },
|
||||
"max_displacement_mm": { "type": "number" },
|
||||
"max_stress_mpa": { "type": "number" },
|
||||
"success": { "type": "boolean", "default": true },
|
||||
"error": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Backend Implementation
|
||||
|
||||
### 3.1 New File: `backend/api/routes/intake.py`
|
||||
|
||||
Core intake API endpoints:
|
||||
|
||||
| Endpoint | Method | Purpose | Status After |
|
||||
|----------|--------|---------|--------------|
|
||||
| `/api/intake/create` | POST | Create inbox folder with initial spec | draft |
|
||||
| `/api/intake/introspect` | POST | Run NX introspection, update spec | introspected |
|
||||
| `/api/intake/readme/generate` | POST | Claude generates README + config suggestions | configured |
|
||||
| `/api/intake/finalize` | POST | Baseline solve, move to studies folder | validated/ready |
|
||||
| `/api/intake/list` | GET | List inbox folders with status | - |
|
||||
| `/api/intake/topics` | GET | List existing topic folders | - |
|
||||
|
||||
**Key Implementation Details:**
|
||||
|
||||
1. **Create** - Creates folder structure + minimal `atomizer_spec.json`
|
||||
2. **Introspect** - Runs NX introspection, updates spec with expressions, mass, solver type
|
||||
3. **Generate README** - Calls Claude with spec + goals.md, returns README + suggested config
|
||||
4. **Finalize** - Full workflow: copy files, baseline solve (optional), move to studies, archive inbox
|
||||
|
||||
### 3.2 New File: `backend/api/services/spec_manager.py`
|
||||
|
||||
Centralized spec operations:
|
||||
|
||||
```python
|
||||
class SpecManager:
|
||||
"""Single source of truth for spec operations."""
|
||||
|
||||
def load(self) -> dict
|
||||
def save(self, spec: dict) -> None
|
||||
def update_status(self, status: str, modified_by: str) -> dict
|
||||
def add_introspection(self, data: dict) -> dict
|
||||
def get_status(self) -> str
|
||||
def exists(self) -> bool
|
||||
```
|
||||
|
||||
### 3.3 New File: `backend/api/services/claude_readme.py`
|
||||
|
||||
Claude-powered README generation:
|
||||
|
||||
- Loads skill from `.claude/skills/modules/study-readme-generator.md`
|
||||
- Builds prompt with spec + goals
|
||||
- Returns README content + suggested DVs/objectives/constraints
|
||||
- Uses Claude API (claude-sonnet-4-20250514)
|
||||
|
||||
### 3.4 WebSocket for Finalization Progress
|
||||
|
||||
The `/api/intake/finalize` endpoint will support WebSocket for real-time progress:
|
||||
|
||||
```typescript
|
||||
// Progress steps
|
||||
const steps = [
|
||||
'Creating study folder',
|
||||
'Copying model files',
|
||||
'Running introspection',
|
||||
'Running baseline solve',
|
||||
'Extracting baseline results',
|
||||
'Generating README with Claude',
|
||||
'Moving to studies folder',
|
||||
'Archiving inbox'
|
||||
];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Frontend Implementation
|
||||
|
||||
### 4.1 Component Structure
|
||||
|
||||
```
|
||||
frontend/src/components/home/
|
||||
├── CreateStudyCard.tsx # Main study creation UI
|
||||
├── IntrospectionResults.tsx # Display introspection data
|
||||
├── TopicSelector.tsx # Topic dropdown + new topic input
|
||||
├── StudyFilesPanel.tsx # File display in preview
|
||||
└── index.ts # Exports
|
||||
|
||||
frontend/src/components/common/
|
||||
└── ProgressModal.tsx # Finalization progress display
|
||||
```
|
||||
|
||||
### 4.2 CreateStudyCard States
|
||||
|
||||
```typescript
|
||||
type CardState =
|
||||
| 'empty' // No files, just showing dropzone
|
||||
| 'staged' // Files selected, ready to upload
|
||||
| 'uploading' // Uploading files to inbox
|
||||
| 'introspecting' // Running introspection
|
||||
| 'ready' // Introspection done, can finalize or open canvas
|
||||
| 'finalizing' // Running finalization
|
||||
| 'complete'; // Study created, showing success
|
||||
```
|
||||
|
||||
### 4.3 CreateStudyCard UI
|
||||
|
||||
```
|
||||
╔═══════════════════════════════════════════════════════════════╗
|
||||
║ + Create New Study [Open Canvas] ║
|
||||
╠═══════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ Study Name ║
|
||||
║ ┌─────────────────────────────────────────────────────────┐ ║
|
||||
║ │ bracket_optimization_v1 │ ║
|
||||
║ └─────────────────────────────────────────────────────────┘ ║
|
||||
║ ║
|
||||
║ Topic ║
|
||||
║ ┌─────────────────────────────────────────────────────────┐ ║
|
||||
║ │ M1_Mirror ▼ │ ║
|
||||
║ └─────────────────────────────────────────────────────────┘ ║
|
||||
║ ○ Brackets ○ M1_Mirror ○ Support_Arms ● + New Topic ║
|
||||
║ ║
|
||||
║ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ ║
|
||||
║ │ 📁 Drop model files here │ ║
|
||||
║ │ .sim .prt .fem _i.prt │ ║
|
||||
║ │ or click to browse │ ║
|
||||
║ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ ║
|
||||
║ ║
|
||||
║ Files [Clear] ║
|
||||
║ ┌─────────────────────────────────────────────────────────┐ ║
|
||||
║ │ ✓ bracket_sim1.sim 1.2 MB │ ║
|
||||
║ │ ✓ bracket.prt 3.4 MB │ ║
|
||||
║ │ ✓ bracket_fem1.fem 2.1 MB │ ║
|
||||
║ │ ✓ bracket_fem1_i.prt 0.8 MB ← Idealized! │ ║
|
||||
║ └─────────────────────────────────────────────────────────┘ ║
|
||||
║ ║
|
||||
║ ▼ Model Information ✓ Ready ║
|
||||
║ ┌─────────────────────────────────────────────────────────┐ ║
|
||||
║ │ Solver: NX Nastran │ ║
|
||||
║ │ Estimated Mass: 2.34 kg │ ║
|
||||
║ │ │ ║
|
||||
║ │ Design Variable Candidates (5 found): │ ║
|
||||
║ │ ★ rib_thickness = 5.0 mm [2.5 - 10.0] │ ║
|
||||
║ │ ★ web_height = 20.0 mm [10.0 - 40.0] │ ║
|
||||
║ │ ★ flange_width = 15.0 mm [7.5 - 30.0] │ ║
|
||||
║ └─────────────────────────────────────────────────────────┘ ║
|
||||
║ ║
|
||||
║ ┌─────────────────────────────────────────────────────────┐ ║
|
||||
║ │ ☑ Run baseline solve (recommended for accurate values) │ ║
|
||||
║ │ ☑ Generate README with Claude │ ║
|
||||
║ └─────────────────────────────────────────────────────────┘ ║
|
||||
║ ║
|
||||
║ [ Finalize Study ] [ Open Canvas → ] ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
### 4.4 ProgressModal UI
|
||||
|
||||
```
|
||||
╔════════════════════════════════════════════════════════════════╗
|
||||
║ Creating Study [X] ║
|
||||
╠════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ bracket_optimization_v1 ║
|
||||
║ Topic: M1_Mirror ║
|
||||
║ ║
|
||||
║ ┌──────────────────────────────────────────────────────────┐ ║
|
||||
║ │ │ ║
|
||||
║ │ ✓ Creating study folder 0.5s │ ║
|
||||
║ │ ✓ Copying model files 1.2s │ ║
|
||||
║ │ ✓ Running introspection 3.4s │ ║
|
||||
║ │ ● Running baseline solve... │ ║
|
||||
║ │ ├─ Updating parameters │ ║
|
||||
║ │ ├─ Meshing... │ ║
|
||||
║ │ └─ Solving (iteration 2/5) │ ║
|
||||
║ │ ○ Extracting baseline results │ ║
|
||||
║ │ ○ Generating README with Claude │ ║
|
||||
║ │ ○ Moving to studies folder │ ║
|
||||
║ │ ○ Archiving inbox │ ║
|
||||
║ │ │ ║
|
||||
║ └──────────────────────────────────────────────────────────┘ ║
|
||||
║ ║
|
||||
║ [━━━━━━━━━━━━━━━━░░░░░░░░░░░░░░░░░░░] 42% ║
|
||||
║ ║
|
||||
║ Estimated time remaining: ~45 seconds ║
|
||||
║ ║
|
||||
╚════════════════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
### 4.5 StudyFilesPanel (in Preview)
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────┐
|
||||
│ 📁 Model Files (4) [+ Add] [↗] │
|
||||
├────────────────────────────────────────────────────────────────┤
|
||||
│ 📦 bracket_sim1.sim 1.2 MB Simulation │
|
||||
│ 📐 bracket.prt 3.4 MB Geometry │
|
||||
│ 🔷 bracket_fem1.fem 2.1 MB FEM │
|
||||
│ 🔶 bracket_fem1_i.prt 0.8 MB Idealized Part │
|
||||
└────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Claude Skill for README Generation
|
||||
|
||||
### 5.1 Skill Location
|
||||
|
||||
`.claude/skills/modules/study-readme-generator.md`
|
||||
|
||||
### 5.2 Skill Purpose
|
||||
|
||||
Claude analyzes the AtomizerSpec and generates:
|
||||
1. **Comprehensive README.md** - Not a template, but intelligent documentation
|
||||
2. **Suggested design variables** - Based on introspection candidates
|
||||
3. **Suggested objectives** - Based on goals.md or reasonable defaults
|
||||
4. **Suggested extractors** - Mapped to objectives
|
||||
5. **Suggested constraints** - If mentioned in goals
|
||||
|
||||
### 5.3 README Structure
|
||||
|
||||
1. **Title & Overview** - Study name, description, quick stats
|
||||
2. **Optimization Goals** - Primary objective, constraints summary
|
||||
3. **Model Information** - Solver, baseline mass, warnings
|
||||
4. **Design Variables** - Table with baseline, bounds, units
|
||||
5. **Extractors & Objectives** - Physics extraction mapping
|
||||
6. **Constraints** - Limits and thresholds
|
||||
7. **Recommended Approach** - Algorithm, trial budget
|
||||
8. **Files** - Model file listing
|
||||
|
||||
---
|
||||
|
||||
## 6. Home Page Integration
|
||||
|
||||
### 6.1 Layout
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ [Logo] [Canvas Builder] [Refresh] │
|
||||
├──────────────────────────────────────────────────────────────────┤
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Studies │ │ Running │ │ Trials │ │ Best │ │
|
||||
│ │ 15 │ │ 2 │ │ 1,234 │ │ 2.34e-3 │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
├─────────────────────────────┬────────────────────────────────────┤
|
||||
│ ┌─────────────────────────┐ │ Study Preview │
|
||||
│ │ + Create New Study │ │ ┌────────────────────────────────┐ │
|
||||
│ │ │ │ │ 📁 Model Files (4) [+] │ │
|
||||
│ │ [CreateStudyCard] │ │ │ (StudyFilesPanel) │ │
|
||||
│ │ │ │ └────────────────────────────────┘ │
|
||||
│ └─────────────────────────┘ │ │
|
||||
│ │ README.md │
|
||||
│ Studies (15) │ (MarkdownRenderer) │
|
||||
│ ▶ M1_Mirror (5) │ │
|
||||
│ ▶ Brackets (3) │ │
|
||||
│ ▼ Other (2) │ │
|
||||
│ └─ test_study ● Running │ │
|
||||
└─────────────────────────────┴────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. File Changes Summary
|
||||
|
||||
| File | Action | Est. Lines |
|
||||
|------|--------|------------|
|
||||
| **Backend** | | |
|
||||
| `backend/api/routes/intake.py` | CREATE | ~350 |
|
||||
| `backend/api/services/spec_manager.py` | CREATE | ~80 |
|
||||
| `backend/api/services/claude_readme.py` | CREATE | ~150 |
|
||||
| `backend/api/main.py` | MODIFY | +5 |
|
||||
| **Schema/Models** | | |
|
||||
| `optimization_engine/config/spec_models.py` | MODIFY | +60 |
|
||||
| `optimization_engine/schemas/atomizer_spec_v2.json` | MODIFY | +50 |
|
||||
| **Frontend** | | |
|
||||
| `frontend/src/components/home/CreateStudyCard.tsx` | CREATE | ~400 |
|
||||
| `frontend/src/components/home/IntrospectionResults.tsx` | CREATE | ~120 |
|
||||
| `frontend/src/components/home/TopicSelector.tsx` | CREATE | ~80 |
|
||||
| `frontend/src/components/home/StudyFilesPanel.tsx` | CREATE | ~100 |
|
||||
| `frontend/src/components/common/ProgressModal.tsx` | CREATE | ~150 |
|
||||
| `frontend/src/pages/Home.tsx` | MODIFY | +80 |
|
||||
| `frontend/src/api/client.ts` | MODIFY | +100 |
|
||||
| `frontend/src/types/atomizer-spec.ts` | MODIFY | +40 |
|
||||
| **Skills** | | |
|
||||
| `.claude/skills/modules/study-readme-generator.md` | CREATE | ~120 |
|
||||
|
||||
**Total: ~1,885 lines**
|
||||
|
||||
---
|
||||
|
||||
## 8. Implementation Order
|
||||
|
||||
### Phase 1: Backend Foundation (Day 1)
|
||||
1. Update `spec_models.py` with new fields (status, IntrospectionData)
|
||||
2. Update JSON schema
|
||||
3. Create `spec_manager.py` service
|
||||
4. Create `intake.py` routes (create, introspect, list, topics)
|
||||
5. Register in `main.py`
|
||||
6. Test with curl/Postman
|
||||
|
||||
### Phase 2: Claude Integration (Day 1-2)
|
||||
1. Create `study-readme-generator.md` skill
|
||||
2. Create `claude_readme.py` service
|
||||
3. Add `/readme/generate` endpoint
|
||||
4. Test README generation
|
||||
|
||||
### Phase 3: Frontend Components (Day 2-3)
|
||||
1. Add TypeScript types
|
||||
2. Add API client methods
|
||||
3. Create `TopicSelector` component
|
||||
4. Create `IntrospectionResults` component
|
||||
5. Create `ProgressModal` component
|
||||
6. Create `CreateStudyCard` component
|
||||
7. Create `StudyFilesPanel` component
|
||||
|
||||
### Phase 4: Home Page Integration (Day 3)
|
||||
1. Modify `Home.tsx` layout
|
||||
2. Integrate `CreateStudyCard` above study list
|
||||
3. Add `StudyFilesPanel` to study preview
|
||||
4. Test full flow
|
||||
|
||||
### Phase 5: Finalization & WebSocket (Day 4)
|
||||
1. Implement `/finalize` endpoint with baseline solve
|
||||
2. Add WebSocket progress updates
|
||||
3. Implement inbox archiving
|
||||
4. End-to-end testing
|
||||
5. Documentation updates
|
||||
|
||||
---
|
||||
|
||||
## 9. Validation Gate Integration
|
||||
|
||||
The Validation Gate runs 2-3 test trials before full optimization to catch:
|
||||
- Mesh not updating (identical results)
|
||||
- Extractor failures
|
||||
- Constraint evaluation errors
|
||||
|
||||
**Integration point**: After study is finalized, before optimization starts, a "Validate" button appears in the study preview that runs the gate.
|
||||
|
||||
---
|
||||
|
||||
## 10. Success Criteria
|
||||
|
||||
- [ ] User can create study by dropping files in dashboard
|
||||
- [ ] Introspection runs automatically after upload
|
||||
- [ ] Introspection results show inline with design candidates highlighted
|
||||
- [ ] "Open Canvas" button works, loading spec into canvas
|
||||
- [ ] Claude generates comprehensive README from spec + goals
|
||||
- [ ] Baseline solve runs with WebSocket progress display
|
||||
- [ ] Study moves to correct topic folder
|
||||
- [ ] Inbox folder is archived after success
|
||||
- [ ] `atomizer_spec.json` is the ONLY configuration file used
|
||||
- [ ] Spec status updates correctly through workflow
|
||||
- [ ] Canvas can load and edit spec from inbox (pre-finalization)
|
||||
|
||||
---
|
||||
|
||||
## 11. Error Handling
|
||||
|
||||
### Baseline Solve Failure
|
||||
If baseline solve fails:
|
||||
- Still create the study
|
||||
- Set `spec.meta.status = "configured"` (not "validated")
|
||||
- Store error in `spec.model.introspection.baseline.error`
|
||||
- README notes baseline was attempted but failed
|
||||
- User can retry baseline later or proceed without it
|
||||
|
||||
### Missing Idealized Part
|
||||
If `*_i.prt` is not found:
|
||||
- Add CRITICAL warning to introspection
|
||||
- Highlight in UI with warning icon
|
||||
- Still allow study creation (user may add later)
|
||||
- README includes warning about mesh not updating
|
||||
|
||||
### Introspection Failure
|
||||
If NX introspection fails:
|
||||
- Store error in spec
|
||||
- Allow manual configuration via Canvas
|
||||
- User can retry introspection after fixing issues
|
||||
|
||||
---
|
||||
|
||||
## 12. Future Enhancements (Out of Scope)
|
||||
|
||||
- PDF extraction with Claude Vision
|
||||
- Image analysis for sketches in context/
|
||||
- Batch study creation (multiple studies at once)
|
||||
- Study templates from existing studies
|
||||
- Auto-retry failed baseline with different parameters
|
||||
|
||||
---
|
||||
|
||||
*Document created: January 22, 2026*
|
||||
*Approved for implementation*
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,553 +0,0 @@
|
||||
# RALPH LOOP: Canvas-Study Synchronization Overhaul
|
||||
|
||||
**Date**: January 16, 2026
|
||||
**Status**: 🟢 COMPLETED
|
||||
**Priority**: CRITICAL
|
||||
**Completion Date**: January 16, 2026
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The Canvas Builder and actual optimization studies are fundamentally disconnected. When a user loads a study, the canvas doesn't reflect the true optimization pipeline. Claude chat has zero awareness of the canvas state, making it useless for canvas-based interactions.
|
||||
|
||||
---
|
||||
|
||||
## Part 1: Problem Analysis
|
||||
|
||||
### 1.1 Core Issues Identified
|
||||
|
||||
| # | Issue | Severity | Impact |
|
||||
|---|-------|----------|--------|
|
||||
| 1 | **Canvas doesn't match optimization_config.json schema** | CRITICAL | Canvas nodes don't represent actual extractors, objectives, constraints |
|
||||
| 2 | **Missing data flow representation** | CRITICAL | No visualization of: displacement → Zernike → WFE pipeline |
|
||||
| 3 | **Claude has no canvas context** | CRITICAL | Can't help modify canvas because it doesn't know current state |
|
||||
| 4 | **Study loader is incomplete** | HIGH | Loading a study doesn't populate all nodes correctly |
|
||||
| 5 | **Canvas exporter is broken/missing** | HIGH | Can't generate valid optimization_config.json from canvas |
|
||||
| 6 | **No extractor node types** | HIGH | E1-E10 extractors not represented as proper nodes |
|
||||
| 7 | **No output/result node types** | MEDIUM | Missing nodes for WFE, mass, stress outputs |
|
||||
| 8 | **No validation against real schema** | MEDIUM | Canvas allows invalid configurations |
|
||||
|
||||
### 1.2 Real M1 Mirror Optimization Pipeline (What Canvas Should Show)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ M1 MIRROR OPTIMIZATION │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ INPUTS (Design Variables) │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ flatback_ │ │ rib_height │ │ rib_width │ │ fillet_ │ │
|
||||
│ │ thickness │ │ [25-60mm] │ │ [4-12mm] │ │ radius │ │
|
||||
│ │ [15-45mm] │ │ │ │ │ │ [2-10mm] │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ └────────────────┴────────────────┴────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ MODEL + SOLVER │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ m1_mirror_sim1.sim → NX Nastran SOL101 (Static) │ │
|
||||
│ │ Updates: geometry.prt → idealized_i.prt → fem1.fem │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ EXTRACTORS (Post-Processing) │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ E5: CAD Mass │ │ E8: Zernike │ │ E1: Max Disp │ │ E3: Max │ │
|
||||
│ │ (expression) │ │ from OP2 │ │ (optional) │ │ Stress │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ │ ▼ │ │ │
|
||||
│ │ ┌───────────────────────┐ │ │ │
|
||||
│ │ │ Zernike Processing │ │ │ │
|
||||
│ │ │ - Fit coefficients │ │ │ │
|
||||
│ │ │ - Calculate WFE_40_20 │ │ │ │
|
||||
│ │ │ - Calculate RMS │ │ │ │
|
||||
│ │ └───────────┬───────────┘ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ ▼ ▼ ▼ ▼ │
|
||||
│ OBJECTIVES & CONSTRAINTS │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ MINIMIZE │ │ MINIMIZE │ │ CONSTRAINT │ │
|
||||
│ │ mass_kg │ │ wfe_40_20 │ │ stress < 200 │ │
|
||||
│ │ weight: 1.0 │ │ weight: 10.0 │ │ MPa │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.3 What optimization_config.json Actually Contains
|
||||
|
||||
```json
|
||||
{
|
||||
"study_name": "m1_mirror_flatback_lateral",
|
||||
"description": "M1 Mirror optimization",
|
||||
|
||||
"design_variables": [
|
||||
{"name": "flatback_thickness", "min": 15, "max": 45, "unit": "mm"},
|
||||
{"name": "rib_height", "min": 25, "max": 60, "unit": "mm"},
|
||||
{"name": "rib_width", "min": 4, "max": 12, "unit": "mm"},
|
||||
{"name": "fillet_radius", "min": 2, "max": 10, "unit": "mm"}
|
||||
],
|
||||
|
||||
"model": {
|
||||
"sim_file": "1_model/m1_mirror_sim1.sim",
|
||||
"prt_file": "1_model/m1_mirror.prt",
|
||||
"fem_file": "1_model/m1_mirror_fem1.fem",
|
||||
"idealized_file": "1_model/m1_mirror_fem1_i.prt"
|
||||
},
|
||||
|
||||
"solver": {
|
||||
"type": "SOL101",
|
||||
"timeout_minutes": 30
|
||||
},
|
||||
|
||||
"extractors": [
|
||||
{
|
||||
"id": "E5",
|
||||
"name": "mass_extractor",
|
||||
"type": "cad_mass",
|
||||
"expression_name": "total_mass",
|
||||
"output_name": "mass_kg"
|
||||
},
|
||||
{
|
||||
"id": "E8",
|
||||
"name": "zernike_extractor",
|
||||
"type": "zernike_op2",
|
||||
"subcase": 1,
|
||||
"node_set": "mirror_surface",
|
||||
"terms": [40, 20],
|
||||
"output_name": "wfe_40_20"
|
||||
}
|
||||
],
|
||||
|
||||
"objectives": [
|
||||
{"name": "mass_kg", "direction": "minimize", "weight": 1.0},
|
||||
{"name": "wfe_40_20", "direction": "minimize", "weight": 10.0}
|
||||
],
|
||||
|
||||
"constraints": [
|
||||
{"name": "max_stress", "operator": "<=", "value": 200, "unit": "MPa"}
|
||||
],
|
||||
|
||||
"algorithm": {
|
||||
"method": "NSGA-II",
|
||||
"max_trials": 200,
|
||||
"population_size": 40
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 1.4 Current Canvas Schema (INCOMPLETE)
|
||||
|
||||
The current canvas has these node types:
|
||||
- `model` - File path only, no solver integration
|
||||
- `solver` - Just solver type, no connection to model
|
||||
- `designVar` - Expression name and bounds only
|
||||
- `algorithm` - Method and max trials
|
||||
- `extractor` - Just extractor ID, no configuration
|
||||
- `objective` - Name, direction, weight
|
||||
- `constraint` - Name, operator, value
|
||||
- `surrogate` - Neural surrogate toggle
|
||||
|
||||
**MISSING:**
|
||||
- Proper extractor configuration (subcase, node set, terms)
|
||||
- Data flow connections (extractor output → objective input)
|
||||
- Model file relationships (sim → fem → prt → idealized)
|
||||
- Zernike-specific processing nodes
|
||||
- Output mapping (which extractor feeds which objective)
|
||||
|
||||
---
|
||||
|
||||
## Part 2: Claude Context Problem
|
||||
|
||||
### 2.1 Current State
|
||||
|
||||
When user opens canvas and chats with Claude:
|
||||
1. Claude receives NO information about:
|
||||
- Current canvas nodes
|
||||
- Current canvas edges (connections)
|
||||
- Current study context
|
||||
- Current configuration state
|
||||
|
||||
2. Claude can only:
|
||||
- Answer generic questions
|
||||
- Use MCP tools for study queries
|
||||
- NOT modify the canvas directly
|
||||
|
||||
### 2.2 Required Claude Capabilities
|
||||
|
||||
Claude needs to:
|
||||
1. **See current canvas state** - All nodes, edges, configurations
|
||||
2. **Modify canvas** - Add/remove/update nodes via API
|
||||
3. **Validate changes** - Check if configuration is valid
|
||||
4. **Generate config** - Export canvas to optimization_config.json
|
||||
5. **Load studies** - Import optimization_config.json to canvas
|
||||
|
||||
---
|
||||
|
||||
## Part 3: Solution Architecture
|
||||
|
||||
### 3.1 Enhanced Canvas Schema
|
||||
|
||||
```typescript
|
||||
// New comprehensive node types
|
||||
type NodeType =
|
||||
| 'model' // NX model with all file references
|
||||
| 'solver' // Solver configuration
|
||||
| 'designVar' // Design variable (expression)
|
||||
| 'extractor' // Physics extractor with full config
|
||||
| 'processor' // Data processor (Zernike fitting, etc.)
|
||||
| 'objective' // Optimization objective
|
||||
| 'constraint' // Constraint definition
|
||||
| 'algorithm' // Optimization algorithm
|
||||
| 'surrogate' // Neural surrogate
|
||||
| 'output' // Final output metric
|
||||
|
||||
// Enhanced extractor node
|
||||
interface ExtractorNodeData {
|
||||
type: 'extractor';
|
||||
extractorId: 'E1' | 'E2' | 'E3' | 'E4' | 'E5' | 'E8' | 'E9' | 'E10';
|
||||
extractorName: string;
|
||||
|
||||
// E1/E3 specific
|
||||
subcase?: number;
|
||||
nodeId?: number;
|
||||
elementId?: number;
|
||||
|
||||
// E8 Zernike specific
|
||||
zernikeTerms?: number[];
|
||||
nodeSet?: string;
|
||||
referenceRadius?: number;
|
||||
|
||||
// E5 Mass specific
|
||||
expressionName?: string;
|
||||
|
||||
// Output mapping
|
||||
outputName: string; // Name of the output variable
|
||||
}
|
||||
|
||||
// Enhanced model node
|
||||
interface ModelNodeData {
|
||||
type: 'model';
|
||||
simFile: string;
|
||||
prtFile: string;
|
||||
femFile: string;
|
||||
idealizedFile?: string;
|
||||
|
||||
// Discovered info
|
||||
expressions?: Array<{name: string; value: number; unit: string}>;
|
||||
meshInfo?: {nodes: number; elements: number};
|
||||
}
|
||||
|
||||
// Data processor node (for Zernike fitting, etc.)
|
||||
interface ProcessorNodeData {
|
||||
type: 'processor';
|
||||
processorType: 'zernike_fit' | 'relative_calc' | 'rms_calc' | 'custom';
|
||||
|
||||
// Inputs (connected from extractors)
|
||||
inputMapping: Record<string, string>;
|
||||
|
||||
// Processing config
|
||||
config: Record<string, any>;
|
||||
|
||||
// Outputs
|
||||
outputNames: string[];
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 Canvas-Config Synchronization
|
||||
|
||||
```typescript
|
||||
// Canvas State Manager - shared between frontend and Claude
|
||||
class CanvasStateManager {
|
||||
// Current state
|
||||
nodes: CanvasNode[];
|
||||
edges: CanvasEdge[];
|
||||
studyId: string | null;
|
||||
|
||||
// Load from optimization_config.json
|
||||
async loadFromConfig(configPath: string): Promise<void>;
|
||||
|
||||
// Export to optimization_config.json
|
||||
async exportToConfig(): Promise<OptimizationConfig>;
|
||||
|
||||
// Validation
|
||||
validate(): ValidationResult;
|
||||
|
||||
// Claude API
|
||||
toClaudeContext(): string; // Markdown summary for Claude
|
||||
|
||||
// Modification API (for Claude)
|
||||
addNode(type: NodeType, data: NodeData): string;
|
||||
updateNode(nodeId: string, data: Partial<NodeData>): void;
|
||||
removeNode(nodeId: string): void;
|
||||
addEdge(source: string, target: string): string;
|
||||
removeEdge(edgeId: string): void;
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 Claude Context Injection
|
||||
|
||||
When Claude receives a message in canvas mode:
|
||||
|
||||
```markdown
|
||||
## Current Canvas State
|
||||
|
||||
**Study**: m1_mirror_flatback_lateral
|
||||
**Status**: Configured (valid)
|
||||
|
||||
### Design Variables (4)
|
||||
| Name | Min | Max | Unit |
|
||||
|------|-----|-----|------|
|
||||
| flatback_thickness | 15 | 45 | mm |
|
||||
| rib_height | 25 | 60 | mm |
|
||||
| rib_width | 4 | 12 | mm |
|
||||
| fillet_radius | 2 | 10 | mm |
|
||||
|
||||
### Model
|
||||
- **Sim File**: 1_model/m1_mirror_sim1.sim
|
||||
- **Solver**: SOL101 (Static)
|
||||
|
||||
### Extractors (2)
|
||||
1. E5: CAD Mass → mass_kg
|
||||
2. E8: Zernike OP2 → wfe_40_20 (terms: 40, 20)
|
||||
|
||||
### Objectives (2)
|
||||
1. MINIMIZE mass_kg (weight: 1.0)
|
||||
2. MINIMIZE wfe_40_20 (weight: 10.0)
|
||||
|
||||
### Constraints (1)
|
||||
1. max_stress <= 200 MPa
|
||||
|
||||
### Algorithm
|
||||
- Method: NSGA-II
|
||||
- Max Trials: 200
|
||||
|
||||
---
|
||||
User can ask to modify any of the above. Use canvas_* tools to make changes.
|
||||
```
|
||||
|
||||
### 3.4 New MCP Tools for Canvas
|
||||
|
||||
```typescript
|
||||
// New tools Claude can use
|
||||
const canvasTools = {
|
||||
// Read current state
|
||||
canvas_get_state: () => CanvasState,
|
||||
|
||||
// Modify nodes
|
||||
canvas_add_design_var: (name: string, min: number, max: number, unit: string) => NodeId,
|
||||
canvas_update_design_var: (nodeId: string, updates: Partial<DesignVarData>) => void,
|
||||
canvas_remove_node: (nodeId: string) => void,
|
||||
|
||||
// Add extractors
|
||||
canvas_add_extractor: (type: ExtractorType, config: ExtractorConfig) => NodeId,
|
||||
|
||||
// Add objectives/constraints
|
||||
canvas_add_objective: (name: string, direction: 'minimize' | 'maximize', weight: number) => NodeId,
|
||||
canvas_add_constraint: (name: string, operator: string, value: number) => NodeId,
|
||||
|
||||
// Connections
|
||||
canvas_connect: (sourceId: string, targetId: string) => EdgeId,
|
||||
canvas_disconnect: (edgeId: string) => void,
|
||||
|
||||
// Validation & Export
|
||||
canvas_validate: () => ValidationResult,
|
||||
canvas_export_config: () => OptimizationConfig,
|
||||
canvas_apply_to_study: (studyPath: string) => void,
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Part 4: Implementation Plan
|
||||
|
||||
### Phase 1: Schema & Store Enhancement (Priority: CRITICAL)
|
||||
|
||||
**Files to modify:**
|
||||
- `frontend/src/lib/canvas/schema.ts` - Enhanced node types
|
||||
- `frontend/src/hooks/useCanvasStore.ts` - State management
|
||||
- `frontend/src/lib/canvas/configSync.ts` - NEW: Config sync utilities
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Define complete ExtractorNodeData with all E1-E10 configs
|
||||
- [ ] Define ProcessorNodeData for Zernike processing
|
||||
- [ ] Define complete ModelNodeData with all file references
|
||||
- [ ] Add output mapping to all extractors
|
||||
- [ ] Create validation functions
|
||||
|
||||
### Phase 2: Study Loader Enhancement (Priority: CRITICAL)
|
||||
|
||||
**Files to modify:**
|
||||
- `frontend/src/lib/canvas/studyLoader.ts` - NEW: Full study loading
|
||||
- `backend/api/routes/canvas.py` - NEW: Canvas API endpoints
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Parse optimization_config.json completely
|
||||
- [ ] Create nodes for ALL config elements
|
||||
- [ ] Create edges for data flow
|
||||
- [ ] Handle Zernike-specific extractors
|
||||
- [ ] Handle nested processor configurations
|
||||
|
||||
### Phase 3: Canvas Exporter (Priority: HIGH)
|
||||
|
||||
**Files to create:**
|
||||
- `frontend/src/lib/canvas/configExporter.ts` - Export to config
|
||||
- `backend/api/routes/canvas.py` - Save config endpoint
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Convert canvas nodes to optimization_config.json
|
||||
- [ ] Validate exported config
|
||||
- [ ] Handle edge-to-dependency mapping
|
||||
- [ ] Write to study folder
|
||||
|
||||
### Phase 4: Claude Context Integration (Priority: CRITICAL)
|
||||
|
||||
**Files to modify:**
|
||||
- `backend/api/services/context_builder.py` - Add canvas context
|
||||
- `backend/api/routes/claude.py` - Include canvas state in prompt
|
||||
- `frontend/src/components/chat/ChatPanel.tsx` - Send canvas state
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Generate markdown summary of canvas state
|
||||
- [ ] Include in every Claude message
|
||||
- [ ] Update context on canvas changes
|
||||
- [ ] Add canvas modification instructions
|
||||
|
||||
### Phase 5: MCP Canvas Tools (Priority: HIGH)
|
||||
|
||||
**Files to create:**
|
||||
- `mcp-server/atomizer-tools/src/canvas-tools.ts` - Canvas modification tools
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Implement canvas_get_state
|
||||
- [ ] Implement canvas_add_* tools
|
||||
- [ ] Implement canvas_update_* tools
|
||||
- [ ] Implement canvas_remove_node
|
||||
- [ ] Implement canvas_connect/disconnect
|
||||
- [ ] Implement canvas_validate
|
||||
- [ ] Implement canvas_export_config
|
||||
|
||||
### Phase 6: UI Node Enhancements (Priority: MEDIUM)
|
||||
|
||||
**Files to modify:**
|
||||
- `frontend/src/components/canvas/nodes/ExtractorNode.tsx` - Full config display
|
||||
- `frontend/src/components/canvas/panels/NodeConfigPanel.tsx` - All config options
|
||||
|
||||
**Tasks:**
|
||||
- [ ] Show extractor configuration in node
|
||||
- [ ] Show output mapping
|
||||
- [ ] Show data flow direction
|
||||
- [ ] Add quick-edit for common settings
|
||||
|
||||
---
|
||||
|
||||
## Part 5: Immediate Actions
|
||||
|
||||
### Action 1: Read actual optimization_config.json from M1 mirror
|
||||
```bash
|
||||
Read studies/M1_Mirror/m1_mirror_flatback_lateral/optimization_config.json
|
||||
```
|
||||
|
||||
### Action 2: Read current run_optimization.py to understand pipeline
|
||||
```bash
|
||||
Read studies/M1_Mirror/m1_mirror_flatback_lateral/run_optimization.py
|
||||
```
|
||||
|
||||
### Action 3: Compare with canvas schema
|
||||
```bash
|
||||
Read atomizer-dashboard/frontend/src/lib/canvas/schema.ts
|
||||
```
|
||||
|
||||
### Action 4: Check current study loading logic
|
||||
```bash
|
||||
Find and read study loading code in useCanvasStore
|
||||
```
|
||||
|
||||
### Action 5: Check Claude context builder
|
||||
```bash
|
||||
Read atomizer-dashboard/backend/api/services/context_builder.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Part 6: Success Criteria
|
||||
|
||||
1. **Loading M1 Mirror study shows ALL nodes**:
|
||||
- 4 design variables with correct bounds
|
||||
- Model node with all file references
|
||||
- Solver node (SOL101)
|
||||
- E5 Mass extractor with expression name
|
||||
- E8 Zernike extractor with terms [40, 20]
|
||||
- 2 objectives (mass, wfe)
|
||||
- Proper edge connections
|
||||
|
||||
2. **Claude knows canvas state**:
|
||||
- User says "add hole_diameter" → Claude immediately adds it
|
||||
- No clarifying questions about which study
|
||||
- Validates against current config
|
||||
|
||||
3. **Canvas exports valid config**:
|
||||
- Click "Export" → generates optimization_config.json
|
||||
- Config is valid and runnable
|
||||
- Matches what run_optimization.py expects
|
||||
|
||||
4. **Bidirectional sync**:
|
||||
- Edit canvas → config updates
|
||||
- Edit config file → canvas updates (on reload)
|
||||
|
||||
---
|
||||
|
||||
## Tracking
|
||||
|
||||
| Phase | Status | Notes |
|
||||
|-------|--------|-------|
|
||||
| Phase 1: Schema | 🟢 COMPLETE | Enhanced ExtractorNodeData, DesignVarNodeData, AlgorithmNodeData with ZernikeConfig, baseline, penalty weights |
|
||||
| Phase 2: Loader | 🟢 COMPLETE | Fixed OptimizationConfig to use min/max, added extraction_method, zernike_settings parsing |
|
||||
| Phase 3: Exporter | 🟡 Partial | loadFromConfig now creates proper nodes from real configs |
|
||||
| Phase 4: Claude Context | 🟢 COMPLETE | context_builder.py now has _canvas_context(), useChat passes canvas state |
|
||||
| Phase 5: MCP Tools | 🟢 COMPLETE | Added canvas_add_node, canvas_update_node, canvas_remove_node, canvas_connect_nodes |
|
||||
| Phase 6: UI | 🟡 Partial | useCanvasChat syncs canvas state, applyModification handles Claude responses |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Summary
|
||||
|
||||
### Files Modified
|
||||
|
||||
**Frontend:**
|
||||
- `src/lib/canvas/schema.ts` - Enhanced node data types (ZernikeConfig, baseline, penalty weights)
|
||||
- `src/hooks/useCanvasStore.ts` - Fixed OptimizationConfig interface (min/max), enhanced loadFromConfig
|
||||
- `src/hooks/useChat.ts` - Added CanvasState, updateCanvasState, passes canvas to backend
|
||||
- `src/hooks/useCanvasChat.ts` - Syncs canvas state, applyModification for Claude modifications
|
||||
|
||||
**Backend:**
|
||||
- `api/services/context_builder.py` - Added _canvas_context() method with full canvas serialization
|
||||
- `api/services/session_manager.py` - send_message now accepts canvas_state parameter
|
||||
- `api/routes/claude.py` - WebSocket handler accepts set_canvas messages, passes to session
|
||||
|
||||
**MCP Server:**
|
||||
- `src/tools/canvas.ts` - Added canvas_add_node, canvas_update_node, canvas_remove_node, canvas_connect_nodes
|
||||
|
||||
### Key Changes
|
||||
|
||||
1. **Canvas-Config Interface Fixed**:
|
||||
- Uses `min/max` instead of `lower/upper`
|
||||
- Supports `extraction_method` and `zernike_settings`
|
||||
- Handles `baseline`, `units`, `enabled`, `notes` for design vars
|
||||
|
||||
2. **Claude Context Injection**:
|
||||
- Full canvas state passed with every message
|
||||
- Tables for design vars, objectives, extractors
|
||||
- Instructions for canvas modification tools
|
||||
|
||||
3. **Canvas Modification Tools**:
|
||||
- Claude can add design variables with `canvas_add_node`
|
||||
- Claude can update weights/bounds with `canvas_update_node`
|
||||
- Frontend applies modifications via `applyModification()`
|
||||
|
||||
---
|
||||
|
||||
*Document completed January 16, 2026*
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,239 +0,0 @@
|
||||
# Atomizer Dashboard V2 - Implementation Status
|
||||
|
||||
**Last Updated:** January 14, 2026
|
||||
**Status:** COMPLETE
|
||||
|
||||
---
|
||||
|
||||
## Implementation Audit Summary
|
||||
|
||||
All phases of the Atomizer Dashboard V2 have been implemented.
|
||||
|
||||
### Phase 0: MCP Chat Foundation - COMPLETE
|
||||
|
||||
| Component | Files | Lines | Status |
|
||||
|-----------|-------|-------|--------|
|
||||
| MCP Server | `mcp-server/atomizer-tools/src/` | 579+ | COMPLETE |
|
||||
| Backend Services | `backend/api/services/` | 1,897 | COMPLETE |
|
||||
| Frontend Chat | `frontend/src/components/chat/` | 6 files | COMPLETE |
|
||||
|
||||
**MCP Tools Implemented:**
|
||||
- `list_studies` - List all studies
|
||||
- `get_study_status` - Study details
|
||||
- `create_study` - Create from description
|
||||
- `run_optimization` - Start optimization
|
||||
- `stop_optimization` - Stop optimization
|
||||
- `get_trial_data` - Query trials
|
||||
- `analyze_convergence` - Convergence metrics
|
||||
- `compare_trials` - Side-by-side comparison
|
||||
- `get_best_design` - Best design details
|
||||
- `generate_report` - Markdown reports
|
||||
- `export_data` - CSV/JSON export
|
||||
- `explain_physics` - FEA concepts
|
||||
- `recommend_method` - Algorithm recommendation
|
||||
- `query_extractors` - Extractor list
|
||||
|
||||
### Phase 1: Canvas with React Flow - COMPLETE
|
||||
|
||||
| Component | Location | Status |
|
||||
|-----------|----------|--------|
|
||||
| Schema | `frontend/src/lib/canvas/schema.ts` | COMPLETE |
|
||||
| Intent Serializer | `frontend/src/lib/canvas/intent.ts` | COMPLETE |
|
||||
| Validation | `frontend/src/lib/canvas/validation.ts` | COMPLETE |
|
||||
| Templates | `frontend/src/lib/canvas/templates.ts` | COMPLETE |
|
||||
| Canvas Store | `frontend/src/hooks/useCanvasStore.ts` | COMPLETE |
|
||||
| Main Canvas | `frontend/src/components/canvas/AtomizerCanvas.tsx` | COMPLETE |
|
||||
|
||||
**Node Types (8):**
|
||||
- ModelNode, SolverNode, DesignVarNode, ExtractorNode
|
||||
- ObjectiveNode, ConstraintNode, AlgorithmNode, SurrogateNode
|
||||
|
||||
**Panels (6):**
|
||||
- NodeConfigPanel, ValidationPanel, ExecuteDialog
|
||||
- ChatPanel, ConfigImporter, TemplateSelector
|
||||
|
||||
### Phase 2: LLM Intelligence Layer - COMPLETE
|
||||
|
||||
| Component | Location | Status |
|
||||
|-----------|----------|--------|
|
||||
| Canvas Chat Hook | `frontend/src/hooks/useCanvasChat.ts` | COMPLETE |
|
||||
| Canvas MCP Tools | `mcp-server/atomizer-tools/src/tools/canvas.ts` | COMPLETE |
|
||||
|
||||
**Canvas Tools:**
|
||||
- `validate_canvas_intent` - Validate graph before execution
|
||||
- `execute_canvas_intent` - Create study + optionally run
|
||||
- `interpret_canvas_intent` - Get recommendations
|
||||
|
||||
### Phase 3: Bidirectional Sync - COMPLETE
|
||||
|
||||
| Feature | Status |
|
||||
|---------|--------|
|
||||
| Session persistence | COMPLETE (SQLite) |
|
||||
| Context builder | COMPLETE |
|
||||
| Canvas ↔ Chat bridge | COMPLETE |
|
||||
| Study context loading | COMPLETE |
|
||||
|
||||
### Phase 4: Templates & Polish - COMPLETE
|
||||
|
||||
| Feature | Status |
|
||||
|---------|--------|
|
||||
| Template selector | COMPLETE |
|
||||
| Config importer | COMPLETE |
|
||||
| Route: /canvas | COMPLETE |
|
||||
|
||||
---
|
||||
|
||||
## File Inventory
|
||||
|
||||
### MCP Server (`mcp-server/atomizer-tools/`)
|
||||
```
|
||||
src/
|
||||
├── index.ts # Server entry (imports canvasTools)
|
||||
├── tools/
|
||||
│ ├── study.ts # Study management
|
||||
│ ├── optimization.ts # Optimization control
|
||||
│ ├── analysis.ts # Analysis tools
|
||||
│ ├── reporting.ts # Report generation
|
||||
│ ├── physics.ts # Physics explanations
|
||||
│ ├── canvas.ts # Canvas intent tools
|
||||
│ └── admin.ts # Power mode tools
|
||||
└── utils/
|
||||
└── paths.ts # Path utilities
|
||||
```
|
||||
|
||||
### Backend Services (`atomizer-dashboard/backend/api/services/`)
|
||||
```
|
||||
__init__.py
|
||||
claude_agent.py # Full Claude API integration (722 lines)
|
||||
claude_cli_agent.py # CLI-based agent (202 lines)
|
||||
conversation_store.py # SQLite persistence (295 lines)
|
||||
session_manager.py # Session lifecycle (425 lines)
|
||||
context_builder.py # Context assembly (246 lines)
|
||||
```
|
||||
|
||||
### Frontend Canvas (`atomizer-dashboard/frontend/src/components/canvas/`)
|
||||
```
|
||||
AtomizerCanvas.tsx # Main canvas component
|
||||
nodes/
|
||||
├── index.ts # Node type registry
|
||||
├── BaseNode.tsx
|
||||
├── ModelNode.tsx
|
||||
├── SolverNode.tsx
|
||||
├── DesignVarNode.tsx
|
||||
├── ExtractorNode.tsx
|
||||
├── ObjectiveNode.tsx
|
||||
├── ConstraintNode.tsx
|
||||
├── AlgorithmNode.tsx
|
||||
└── SurrogateNode.tsx
|
||||
panels/
|
||||
├── NodeConfigPanel.tsx
|
||||
├── ValidationPanel.tsx
|
||||
├── ExecuteDialog.tsx
|
||||
├── ChatPanel.tsx
|
||||
├── ConfigImporter.tsx
|
||||
└── TemplateSelector.tsx
|
||||
palette/
|
||||
└── NodePalette.tsx
|
||||
```
|
||||
|
||||
### Canvas Library (`atomizer-dashboard/frontend/src/lib/canvas/`)
|
||||
```
|
||||
schema.ts # Type definitions
|
||||
intent.ts # Serialization (174 lines)
|
||||
validation.ts # Graph validation
|
||||
templates.ts # Workflow templates
|
||||
index.ts # Exports
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
To verify the implementation:
|
||||
|
||||
### 1. Build MCP Server
|
||||
```bash
|
||||
cd mcp-server/atomizer-tools
|
||||
npm run build
|
||||
# Expected: Compiles without errors
|
||||
```
|
||||
|
||||
### 2. Start MCP Server
|
||||
```bash
|
||||
npm run dev
|
||||
# Expected: "Atomizer MCP Server running in user mode"
|
||||
```
|
||||
|
||||
### 3. Build Frontend
|
||||
```bash
|
||||
cd atomizer-dashboard/frontend
|
||||
npm run build
|
||||
# Expected: Compiles without errors
|
||||
```
|
||||
|
||||
### 4. Start Dashboard
|
||||
```bash
|
||||
npm run dev
|
||||
# Expected: Vite dev server starts
|
||||
```
|
||||
|
||||
### 5. Browser Tests
|
||||
- [ ] Navigate to `/canvas`
|
||||
- [ ] Drag nodes from palette
|
||||
- [ ] Connect nodes with edges
|
||||
- [ ] Configure node properties
|
||||
- [ ] Click "Validate"
|
||||
- [ ] Click "Execute with Claude"
|
||||
- [ ] Chat panel responds
|
||||
|
||||
---
|
||||
|
||||
## What's Next?
|
||||
|
||||
The Dashboard V2 implementation is complete. Remaining work falls into:
|
||||
|
||||
### Integration Testing
|
||||
- End-to-end flow: Canvas → Intent → Claude → Study Creation → Optimization
|
||||
- WebSocket stability under load
|
||||
- Session recovery after browser refresh
|
||||
|
||||
### Documentation
|
||||
- Update ATOMIZER_PODCAST_BRIEFING.md (already done)
|
||||
- Add user guide for Canvas interface
|
||||
- Update README with new features
|
||||
|
||||
### Optional Enhancements (Future)
|
||||
- Phase 5: Tauri Desktop (see master plan)
|
||||
- More workflow templates
|
||||
- Advanced constraint types
|
||||
- Real-time optimization progress on canvas
|
||||
|
||||
---
|
||||
|
||||
## Original Ralph Loop Prompt (Archived)
|
||||
|
||||
The original autonomous development prompt is no longer needed since all phases are complete. The prompt below is kept for reference only.
|
||||
|
||||
<details>
|
||||
<summary>Click to expand archived prompt</summary>
|
||||
|
||||
```
|
||||
[Original prompt content - now obsolete]
|
||||
|
||||
All phases (0-4) have been implemented. The Canvas feature with React Flow
|
||||
is fully functional with:
|
||||
- 8 node types
|
||||
- Drag-drop from palette
|
||||
- Node configuration panels
|
||||
- Graph validation
|
||||
- Intent JSON serialization
|
||||
- MCP tool integration
|
||||
- Claude chat integration
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
*Implementation completed via autonomous Claude Code sessions.*
|
||||
*Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>*
|
||||
@@ -1,546 +0,0 @@
|
||||
# Atomizer Massive Restructuring Plan
|
||||
|
||||
**Created:** 2026-01-06
|
||||
**Purpose:** Comprehensive TODO list for Ralph mode execution with skip permissions
|
||||
**Status:** COMPLETED (2026-01-07)
|
||||
|
||||
---
|
||||
|
||||
## Progress Summary
|
||||
|
||||
**All Phases Completed:**
|
||||
- [x] Phase 1: Safe Cleanup
|
||||
- [x] Phase 2: Documentation (OP_08, protocol numbering, cheatsheet)
|
||||
- [x] Phase 3: Code Organization (surrogates consolidation, tests directory)
|
||||
- [x] Phase 4: Dependency Management (pyproject.toml cleanup)
|
||||
- [x] Phase 5: Study Organization (archived V1-V8 studies)
|
||||
- [x] Phase 6: Documentation Polish (README, LAC, plans)
|
||||
- [x] Final Push: Pushed to both origin and github remotes
|
||||
|
||||
---
|
||||
|
||||
## RALPH MODE TODO LIST
|
||||
|
||||
### PHASE 2 (Remaining - Documentation)
|
||||
|
||||
#### 2.8 Add OP_08 to 01_CHEATSHEET.md
|
||||
```
|
||||
File: .claude/skills/01_CHEATSHEET.md
|
||||
Action: Add row to "I want to..." table after OP_07 entry (around line 33)
|
||||
|
||||
Add this line:
|
||||
| **Generate report** | **OP_08** | `python -m optimization_engine.reporting.report_generator <study>` |
|
||||
|
||||
Also add a section around line 280:
|
||||
## Report Generation (OP_08)
|
||||
|
||||
### Quick Commands
|
||||
| Task | Command |
|
||||
|------|---------|
|
||||
| Generate markdown report | `python -m optimization_engine.reporting.markdown_report <study>` |
|
||||
| Generate HTML visualization | `python tools/zernike_html_generator.py <study>` |
|
||||
|
||||
**Full details**: `docs/protocols/operations/OP_08_GENERATE_REPORT.md`
|
||||
```
|
||||
|
||||
#### 2.9 SKIP (Already verified V3.0 Bootstrap has no circular refs)
|
||||
|
||||
#### 2.10 Commit Phase 2 Changes
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
git add -A
|
||||
git commit -m "$(cat <<'EOF'
|
||||
docs: Consolidate documentation and fix protocol numbering
|
||||
|
||||
- Rename SYS_16_STUDY_INSIGHTS -> SYS_17_STUDY_INSIGHTS
|
||||
- Rename SYS_17_CONTEXT_ENGINEERING -> SYS_18_CONTEXT_ENGINEERING
|
||||
- Promote Bootstrap V3.0 (Context Engineering) as default
|
||||
- Create knowledge_base/playbook.json for ACE framework
|
||||
- Add OP_08 (Generate Report) to all routing tables
|
||||
- Add SYS_16-18 to all protocol tables
|
||||
- Update docs/protocols/README.md version 1.1
|
||||
- Update CLAUDE.md with new protocols
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### PHASE 3: Code Organization
|
||||
|
||||
#### 3.1 Move ensemble_surrogate.py
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
git mv optimization_engine/surrogates/ensemble_surrogate.py optimization_engine/processors/surrogates/ensemble_surrogate.py
|
||||
```
|
||||
|
||||
#### 3.2 Update processors/surrogates/__init__.py
|
||||
```
|
||||
File: optimization_engine/processors/surrogates/__init__.py
|
||||
Action: Add to __getattr__ function and __all__ list:
|
||||
|
||||
In __getattr__, add these elif blocks:
|
||||
elif name == 'EnsembleSurrogate':
|
||||
from .ensemble_surrogate import EnsembleSurrogate
|
||||
return EnsembleSurrogate
|
||||
elif name == 'OODDetector':
|
||||
from .ensemble_surrogate import OODDetector
|
||||
return OODDetector
|
||||
elif name == 'create_and_train_ensemble':
|
||||
from .ensemble_surrogate import create_and_train_ensemble
|
||||
return create_and_train_ensemble
|
||||
|
||||
In __all__, add:
|
||||
'EnsembleSurrogate',
|
||||
'OODDetector',
|
||||
'create_and_train_ensemble',
|
||||
```
|
||||
|
||||
#### 3.3 Add deprecation shim to surrogates/__init__.py
|
||||
```
|
||||
File: optimization_engine/surrogates/__init__.py
|
||||
Replace contents with:
|
||||
|
||||
"""
|
||||
DEPRECATED: This module has been moved to optimization_engine.processors.surrogates
|
||||
|
||||
Please update your imports:
|
||||
from optimization_engine.processors.surrogates import EnsembleSurrogate
|
||||
|
||||
This module will be removed in a future version.
|
||||
"""
|
||||
|
||||
import warnings
|
||||
|
||||
warnings.warn(
|
||||
"optimization_engine.surrogates is deprecated. "
|
||||
"Use optimization_engine.processors.surrogates instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2
|
||||
)
|
||||
|
||||
# Redirect imports
|
||||
from optimization_engine.processors.surrogates import (
|
||||
EnsembleSurrogate,
|
||||
OODDetector,
|
||||
create_and_train_ensemble
|
||||
)
|
||||
|
||||
__all__ = ['EnsembleSurrogate', 'OODDetector', 'create_and_train_ensemble']
|
||||
```
|
||||
|
||||
#### 3.4 Check future/ imports
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
grep -r "from optimization_engine.future" --include="*.py" | grep -v "future/" | head -20
|
||||
```
|
||||
Analyze output and decide which modules need to move out of future/
|
||||
|
||||
#### 3.5 Move workflow_decomposer.py (if imported by production code)
|
||||
If grep shows imports from config/ or core/:
|
||||
```bash
|
||||
git mv optimization_engine/future/workflow_decomposer.py optimization_engine/config/workflow_decomposer.py
|
||||
# Update imports in capability_matcher.py and any other files
|
||||
```
|
||||
|
||||
#### 3.6 Create tests/ directory structure
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
mkdir -p tests/unit/gnn tests/unit/extractors tests/integration tests/fixtures/sample_data
|
||||
```
|
||||
|
||||
#### 3.7 Move test files from archive/test_scripts/
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
git mv archive/test_scripts/test_neural_surrogate.py tests/unit/
|
||||
git mv archive/test_scripts/test_nn_surrogate.py tests/unit/
|
||||
git mv archive/test_scripts/test_parametric_surrogate.py tests/unit/
|
||||
git mv archive/test_scripts/test_adaptive_characterization.py tests/unit/
|
||||
git mv archive/test_scripts/test_training_data_export.py tests/unit/
|
||||
git mv optimization_engine/gnn/test_*.py tests/unit/gnn/ 2>/dev/null || true
|
||||
git mv optimization_engine/extractors/test_phase3_extractors.py tests/unit/extractors/ 2>/dev/null || true
|
||||
```
|
||||
|
||||
#### 3.8 Create tests/conftest.py
|
||||
```
|
||||
File: tests/conftest.py
|
||||
Content:
|
||||
"""
|
||||
Pytest configuration and shared fixtures for Atomizer tests.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
@pytest.fixture
|
||||
def sample_study_dir(tmp_path):
|
||||
"""Create a temporary study directory structure."""
|
||||
study = tmp_path / "test_study"
|
||||
(study / "1_setup").mkdir(parents=True)
|
||||
(study / "2_iterations").mkdir()
|
||||
(study / "3_results").mkdir()
|
||||
return study
|
||||
|
||||
@pytest.fixture
|
||||
def sample_config():
|
||||
"""Sample optimization config for testing."""
|
||||
return {
|
||||
"study_name": "test_study",
|
||||
"design_variables": [
|
||||
{"name": "param1", "lower": 0, "upper": 10, "type": "continuous"}
|
||||
],
|
||||
"objectives": [
|
||||
{"name": "minimize_mass", "direction": "minimize"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.9 Rename bracket_displacement_maximizing/results to 3_results
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
# Check if results/ exists first
|
||||
if [ -d "studies/bracket_displacement_maximizing/results" ]; then
|
||||
git mv studies/bracket_displacement_maximizing/results studies/bracket_displacement_maximizing/3_results
|
||||
fi
|
||||
```
|
||||
|
||||
#### 3.10 Rename Drone_Gimbal/2_results to 3_results
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
# Check if 2_results/ exists first
|
||||
if [ -d "studies/Drone_Gimbal/2_results" ]; then
|
||||
git mv studies/Drone_Gimbal/2_results studies/Drone_Gimbal/3_results
|
||||
fi
|
||||
```
|
||||
|
||||
#### 3.11 Commit Phase 3 Changes
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
git add -A
|
||||
git commit -m "$(cat <<'EOF'
|
||||
refactor: Reorganize code structure and create tests directory
|
||||
|
||||
- Consolidate surrogates module to processors/surrogates/
|
||||
- Add deprecation shim for old import path
|
||||
- Create tests/ directory with pytest structure
|
||||
- Move test files from archive/test_scripts/
|
||||
- Standardize study folder naming (3_results/)
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### PHASE 4: Dependency Management
|
||||
|
||||
#### 4.1-4.2 Add neural and gnn optional deps to pyproject.toml
|
||||
```
|
||||
File: pyproject.toml
|
||||
After the [project.optional-dependencies] section, add:
|
||||
|
||||
neural = [
|
||||
"torch>=2.0.0",
|
||||
"torch-geometric>=2.3.0",
|
||||
"tensorboard>=2.13.0",
|
||||
]
|
||||
|
||||
gnn = [
|
||||
"torch>=2.0.0",
|
||||
"torch-geometric>=2.3.0",
|
||||
]
|
||||
|
||||
all = ["atomizer[neural,gnn,dev,dashboard]"]
|
||||
```
|
||||
|
||||
#### 4.3 Remove mcp optional deps
|
||||
```
|
||||
File: pyproject.toml
|
||||
Delete this section:
|
||||
|
||||
mcp = [
|
||||
"mcp>=0.1.0",
|
||||
]
|
||||
```
|
||||
|
||||
#### 4.4 Remove mcp_server from packages.find
|
||||
```
|
||||
File: pyproject.toml
|
||||
Change:
|
||||
include = ["mcp_server*", "optimization_engine*", "nx_journals*"]
|
||||
To:
|
||||
include = ["optimization_engine*", "nx_journals*"]
|
||||
```
|
||||
|
||||
#### 4.5 Commit Phase 4 Changes
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
git add pyproject.toml
|
||||
git commit -m "$(cat <<'EOF'
|
||||
build: Add optional dependency groups and clean up pyproject.toml
|
||||
|
||||
- Add neural optional group (torch, torch-geometric, tensorboard)
|
||||
- Add gnn optional group (torch, torch-geometric)
|
||||
- Add all optional group for convenience
|
||||
- Remove mcp optional group (not implemented)
|
||||
- Remove mcp_server from packages.find (not implemented)
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### PHASE 5: Study Organization
|
||||
|
||||
#### 5.1 Create archive directory
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
mkdir -p studies/M1_Mirror/_archive
|
||||
```
|
||||
|
||||
#### 5.2 Move V1-V8 cost_reduction studies
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer/studies/M1_Mirror
|
||||
# Move cost_reduction V2-V8 (V1 doesn't exist as base is just "cost_reduction")
|
||||
for v in V2 V3 V4 V5 V6 V7 V8; do
|
||||
if [ -d "m1_mirror_cost_reduction_$v" ]; then
|
||||
mv "m1_mirror_cost_reduction_$v" _archive/
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
#### 5.3 Move V1-V8 flat_back studies
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer/studies/M1_Mirror
|
||||
# Move flat_back V1-V8 (note: V2 may not exist)
|
||||
for v in V1 V3 V4 V5 V6 V7 V8; do
|
||||
if [ -d "m1_mirror_cost_reduction_flat_back_$v" ]; then
|
||||
mv "m1_mirror_cost_reduction_flat_back_$v" _archive/
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
#### 5.4 Create MANIFEST.md
|
||||
```
|
||||
File: studies/M1_Mirror/_archive/MANIFEST.md
|
||||
Content:
|
||||
|
||||
# M1 Mirror Archived Studies
|
||||
|
||||
**Archived:** 2026-01-06
|
||||
**Reason:** Repository cleanup - keeping only V9+ studies active
|
||||
|
||||
## Archived Studies
|
||||
|
||||
### Cost Reduction Series
|
||||
| Study | Trials | Best WS | Notes |
|
||||
|-------|--------|---------|-------|
|
||||
| V2 | TBD | TBD | Early exploration |
|
||||
| V3 | TBD | TBD | - |
|
||||
| V4 | TBD | TBD | - |
|
||||
| V5 | TBD | TBD | - |
|
||||
| V6 | TBD | TBD | - |
|
||||
| V7 | TBD | TBD | - |
|
||||
| V8 | TBD | TBD | - |
|
||||
|
||||
### Cost Reduction Flat Back Series
|
||||
| Study | Trials | Best WS | Notes |
|
||||
|-------|--------|---------|-------|
|
||||
| V1 | TBD | TBD | Initial flat back design |
|
||||
| V3 | TBD | TBD | V2 was skipped |
|
||||
| V4 | TBD | TBD | - |
|
||||
| V5 | TBD | TBD | - |
|
||||
| V6 | TBD | TBD | - |
|
||||
| V7 | TBD | TBD | - |
|
||||
| V8 | TBD | TBD | - |
|
||||
|
||||
## Restoration Instructions
|
||||
|
||||
To restore a study:
|
||||
1. Move from _archive/ to parent directory
|
||||
2. Verify database integrity: `sqlite3 3_results/study.db ".tables"`
|
||||
3. Check optimization_config.json exists
|
||||
```
|
||||
|
||||
#### 5.5 Commit Phase 5 Changes
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
git add -A
|
||||
git commit -m "$(cat <<'EOF'
|
||||
chore: Archive old M1_Mirror studies (V1-V8)
|
||||
|
||||
- Create studies/M1_Mirror/_archive/ directory
|
||||
- Move cost_reduction V2-V8 to archive
|
||||
- Move flat_back V1-V8 to archive
|
||||
- Create MANIFEST.md documenting archived studies
|
||||
- Keep V9+ studies active for reference
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### PHASE 6: Documentation Polish
|
||||
|
||||
#### 6.1 Update README.md with LLM section
|
||||
```
|
||||
File: README.md
|
||||
Add this section after the main description:
|
||||
|
||||
## For AI Assistants
|
||||
|
||||
Atomizer is designed for LLM-first interaction. Key resources:
|
||||
|
||||
- **[CLAUDE.md](CLAUDE.md)** - System instructions for Claude Code
|
||||
- **[.claude/skills/](/.claude/skills/)** - LLM skill modules
|
||||
- **[docs/protocols/](docs/protocols/)** - Protocol Operating System
|
||||
|
||||
### Knowledge Base (LAC)
|
||||
|
||||
The Learning Atomizer Core (`knowledge_base/lac/`) accumulates optimization knowledge:
|
||||
- `session_insights/` - Learnings from past sessions
|
||||
- `optimization_memory/` - Optimization outcomes by geometry type
|
||||
- `playbook.json` - ACE framework knowledge store
|
||||
|
||||
For detailed AI interaction guidance, see CLAUDE.md.
|
||||
```
|
||||
|
||||
#### 6.2-6.4 Create optimization_memory JSONL files
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
mkdir -p knowledge_base/lac/optimization_memory
|
||||
```
|
||||
|
||||
```
|
||||
File: knowledge_base/lac/optimization_memory/bracket.jsonl
|
||||
Content (one JSON per line):
|
||||
{"geometry_type": "bracket", "study_name": "example", "method": "TPE", "objectives": ["mass"], "trials": 0, "converged": false, "notes": "Schema file - replace with real data"}
|
||||
```
|
||||
|
||||
```
|
||||
File: knowledge_base/lac/optimization_memory/beam.jsonl
|
||||
Content:
|
||||
{"geometry_type": "beam", "study_name": "example", "method": "TPE", "objectives": ["mass"], "trials": 0, "converged": false, "notes": "Schema file - replace with real data"}
|
||||
```
|
||||
|
||||
```
|
||||
File: knowledge_base/lac/optimization_memory/mirror.jsonl
|
||||
Content:
|
||||
{"geometry_type": "mirror", "study_name": "m1_mirror_adaptive_V14", "method": "IMSO", "objectives": ["wfe_40_20", "mass_kg"], "trials": 100, "converged": true, "notes": "SAT v3 achieved WS=205.58"}
|
||||
```
|
||||
|
||||
#### 6.5 Move implementation plans to docs/plans
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
git mv .claude/skills/modules/DYNAMIC_RESPONSE_IMPLEMENTATION_PLAN.md docs/plans/
|
||||
git mv .claude/skills/modules/OPTIMIZATION_ENGINE_MIGRATION_PLAN.md docs/plans/
|
||||
git mv .claude/skills/modules/atomizer_fast_solver_technologies.md docs/plans/
|
||||
```
|
||||
|
||||
#### 6.6 Final consistency verification
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
# Verify protocol files exist
|
||||
ls docs/protocols/operations/OP_0*.md
|
||||
ls docs/protocols/system/SYS_1*.md
|
||||
|
||||
# Verify imports work
|
||||
python -c "import optimization_engine; print('OK')"
|
||||
|
||||
# Verify no broken references
|
||||
grep -r "SYS_16_STUDY" . --include="*.md" | head -5 # Should be empty
|
||||
grep -r "SYS_17_CONTEXT" . --include="*.md" | head -5 # Should be empty
|
||||
|
||||
# Count todos completed
|
||||
echo "Verification complete"
|
||||
```
|
||||
|
||||
#### 6.7 Commit Phase 6 Changes
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
git add -A
|
||||
git commit -m "$(cat <<'EOF'
|
||||
docs: Final documentation polish and consistency fixes
|
||||
|
||||
- Update README.md with LLM assistant section
|
||||
- Create optimization_memory JSONL structure
|
||||
- Move implementation plans from skills/modules to docs/plans
|
||||
- Verify all protocol references are consistent
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### FINAL: Push to Both Remotes
|
||||
|
||||
```bash
|
||||
cd c:\Users\antoi\Atomizer
|
||||
git push origin main
|
||||
git push github main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Files Modified in This Restructuring
|
||||
|
||||
**Documentation (Phase 2):**
|
||||
- `docs/protocols/README.md` - Updated protocol listings
|
||||
- `docs/protocols/system/SYS_17_STUDY_INSIGHTS.md` - Renamed from SYS_16
|
||||
- `docs/protocols/system/SYS_18_CONTEXT_ENGINEERING.md` - Renamed from SYS_17
|
||||
- `CLAUDE.md` - Updated routing tables
|
||||
- `.claude/skills/00_BOOTSTRAP.md` - Replaced with V3.0
|
||||
- `.claude/skills/01_CHEATSHEET.md` - Added OP_08
|
||||
- `knowledge_base/playbook.json` - Created
|
||||
|
||||
**Code (Phase 3):**
|
||||
- `optimization_engine/processors/surrogates/__init__.py` - Added exports
|
||||
- `optimization_engine/surrogates/__init__.py` - Deprecation shim
|
||||
- `tests/conftest.py` - Created
|
||||
|
||||
**Dependencies (Phase 4):**
|
||||
- `pyproject.toml` - Updated optional groups
|
||||
|
||||
**Studies (Phase 5):**
|
||||
- `studies/M1_Mirror/_archive/` - Created with V1-V8 studies
|
||||
|
||||
**Final Polish (Phase 6):**
|
||||
- `README.md` - Added LLM section
|
||||
- `knowledge_base/lac/optimization_memory/` - Created structure
|
||||
- `docs/plans/` - Moved implementation plans
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria Checklist
|
||||
|
||||
- [x] All imports work: `python -c "import optimization_engine"` - VERIFIED
|
||||
- [x] No SYS_16 duplication (only SELF_AWARE_TURBO) - VERIFIED
|
||||
- [x] Bootstrap V3.0 is active version - VERIFIED
|
||||
- [x] OP_08 discoverable in all routing tables - ADDED
|
||||
- [x] Tests directory exists with conftest.py - CREATED
|
||||
- [x] All changes pushed to both remotes - PUSHED
|
||||
@@ -1,495 +0,0 @@
|
||||
# Unified Configuration Architecture - Execution Plan
|
||||
|
||||
**Project**: AtomizerSpec v2.0 Implementation
|
||||
**Reference Document**: `docs/plans/UNIFIED_CONFIGURATION_ARCHITECTURE.md`
|
||||
**Schema Definition**: `optimization_engine/schemas/atomizer_spec_v2.json`
|
||||
**Status**: Ready for Implementation
|
||||
|
||||
---
|
||||
|
||||
## Project Overview
|
||||
|
||||
Transform Atomizer's fragmented configuration system into a unified architecture where:
|
||||
- One JSON schema (AtomizerSpec v2.0) is the single source of truth
|
||||
- Canvas, Backend, Claude, and Optimization Engine all use the same spec
|
||||
- Real-time WebSocket sync keeps all clients updated
|
||||
- Claude can dynamically modify specs and add custom functions
|
||||
|
||||
---
|
||||
|
||||
## Phase Structure
|
||||
|
||||
| Phase | Name | Duration | Focus |
|
||||
|-------|------|----------|-------|
|
||||
| 1 | Foundation | Week 1-3 | Backend SpecManager, REST API, Migration |
|
||||
| 2 | Frontend | Week 4-6 | SpecRenderer, WebSocket Sync, Store |
|
||||
| 3 | Claude Integration | Week 7-9 | MCP Tools, Custom Functions |
|
||||
| 4 | Polish & Testing | Week 10-12 | Migration, Testing, Documentation |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Order (Critical Path)
|
||||
|
||||
```
|
||||
1. Schema & Types (P1.1-P1.3)
|
||||
└── 2. SpecManager Service (P1.4-P1.7)
|
||||
└── 3. REST Endpoints (P1.8-P1.12)
|
||||
├── 4. Migration Script (P1.13-P1.16)
|
||||
└── 5. Frontend Store (P2.1-P2.4)
|
||||
└── 6. SpecRenderer (P2.5-P2.10)
|
||||
└── 7. WebSocket Sync (P2.11-P2.15)
|
||||
└── 8. MCP Tools (P3.1-P3.8)
|
||||
└── 9. Custom Functions (P3.9-P3.14)
|
||||
└── 10. Testing & Polish (P4.1-P4.12)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PHASE 1: Foundation (Backend)
|
||||
|
||||
### P1.1 - Create TypeScript types from JSON Schema
|
||||
- **File**: `atomizer-dashboard/frontend/src/types/atomizer-spec.ts`
|
||||
- **Action**: Generate TypeScript interfaces matching `atomizer_spec_v2.json`
|
||||
- **Reference**: Schema at `optimization_engine/schemas/atomizer_spec_v2.json`
|
||||
- **Acceptance**: Types compile, cover all schema definitions
|
||||
|
||||
### P1.2 - Create Python Pydantic models from JSON Schema
|
||||
- **File**: `optimization_engine/config/spec_models.py`
|
||||
- **Action**: Create Pydantic models for AtomizerSpec validation
|
||||
- **Reference**: Schema at `optimization_engine/schemas/atomizer_spec_v2.json`
|
||||
- **Acceptance**: Models validate example specs correctly
|
||||
|
||||
### P1.3 - Create spec validation utility
|
||||
- **File**: `optimization_engine/config/spec_validator.py`
|
||||
- **Action**: JSON Schema validation + semantic validation (bounds, references)
|
||||
- **Dependencies**: P1.2
|
||||
- **Acceptance**: Validates good specs, rejects invalid with clear errors
|
||||
|
||||
### P1.4 - Create SpecManager core class
|
||||
- **File**: `atomizer-dashboard/backend/api/services/spec_manager.py`
|
||||
- **Action**: Implement `load()`, `save()`, `_validate()`, `_compute_hash()`
|
||||
- **Reference**: Design in UNIFIED_CONFIGURATION_ARCHITECTURE.md Section 5.1
|
||||
- **Dependencies**: P1.3
|
||||
- **Acceptance**: Can load/save/validate atomizer_spec.json files
|
||||
|
||||
### P1.5 - Add SpecManager patch functionality
|
||||
- **File**: `atomizer-dashboard/backend/api/services/spec_manager.py`
|
||||
- **Action**: Implement `patch()` method for JSONPath-style updates
|
||||
- **Dependencies**: P1.4
|
||||
- **Acceptance**: Can update nested fields with conflict detection
|
||||
|
||||
### P1.6 - Add SpecManager node operations
|
||||
- **File**: `atomizer-dashboard/backend/api/services/spec_manager.py`
|
||||
- **Action**: Implement `add_node()`, `remove_node()`, `_generate_id()`, `_auto_position()`
|
||||
- **Dependencies**: P1.5
|
||||
- **Acceptance**: Can add/remove design vars, extractors, objectives, constraints
|
||||
|
||||
### P1.7 - Add SpecManager custom function support
|
||||
- **File**: `atomizer-dashboard/backend/api/services/spec_manager.py`
|
||||
- **Action**: Implement `add_custom_function()` with Python syntax validation
|
||||
- **Dependencies**: P1.6
|
||||
- **Acceptance**: Can add custom extractors with validated Python code
|
||||
|
||||
### P1.8 - Create spec REST router
|
||||
- **File**: `atomizer-dashboard/backend/api/routes/spec.py`
|
||||
- **Action**: Create FastAPI router for spec endpoints
|
||||
- **Dependencies**: P1.7
|
||||
- **Acceptance**: Router imports and mounts correctly
|
||||
|
||||
### P1.9 - Implement GET /studies/{study_id}/spec
|
||||
- **File**: `atomizer-dashboard/backend/api/routes/spec.py`
|
||||
- **Action**: Return full AtomizerSpec for a study
|
||||
- **Dependencies**: P1.8
|
||||
- **Acceptance**: Returns valid spec JSON, 404 for missing studies
|
||||
|
||||
### P1.10 - Implement PUT /studies/{study_id}/spec
|
||||
- **File**: `atomizer-dashboard/backend/api/routes/spec.py`
|
||||
- **Action**: Replace entire spec with validation
|
||||
- **Dependencies**: P1.9
|
||||
- **Acceptance**: Validates, saves, returns new hash
|
||||
|
||||
### P1.11 - Implement PATCH /studies/{study_id}/spec
|
||||
- **File**: `atomizer-dashboard/backend/api/routes/spec.py`
|
||||
- **Action**: Partial update with JSONPath
|
||||
- **Dependencies**: P1.10
|
||||
- **Acceptance**: Updates specific fields, broadcasts change
|
||||
|
||||
### P1.12 - Implement POST /studies/{study_id}/spec/validate
|
||||
- **File**: `atomizer-dashboard/backend/api/routes/spec.py`
|
||||
- **Action**: Validate spec and return detailed report
|
||||
- **Dependencies**: P1.11
|
||||
- **Acceptance**: Returns errors, warnings, summary
|
||||
|
||||
### P1.13 - Create config migration base
|
||||
- **File**: `optimization_engine/config/migrator.py`
|
||||
- **Action**: Create SpecMigrator class with field mapping
|
||||
- **Reference**: Design in UNIFIED_CONFIGURATION_ARCHITECTURE.md Section 8
|
||||
- **Acceptance**: Class structure ready for migration logic
|
||||
|
||||
### P1.14 - Implement design variable migration
|
||||
- **File**: `optimization_engine/config/migrator.py`
|
||||
- **Action**: Migrate `bounds[]` → `bounds.min/max`, `parameter` → `expression_name`
|
||||
- **Dependencies**: P1.13
|
||||
- **Acceptance**: All DV formats convert correctly
|
||||
|
||||
### P1.15 - Implement objective/constraint migration
|
||||
- **File**: `optimization_engine/config/migrator.py`
|
||||
- **Action**: Migrate `goal` → `direction`, extraction configs to new format
|
||||
- **Dependencies**: P1.14
|
||||
- **Acceptance**: Objectives and constraints convert correctly
|
||||
|
||||
### P1.16 - Implement full config migration
|
||||
- **File**: `optimization_engine/config/migrator.py`
|
||||
- **Action**: Complete migration including canvas positions, extractors inference
|
||||
- **Dependencies**: P1.15
|
||||
- **Acceptance**: Can migrate any existing optimization_config.json to AtomizerSpec
|
||||
|
||||
### P1.17 - Create migration CLI tool
|
||||
- **File**: `tools/migrate_to_spec_v2.py`
|
||||
- **Action**: CLI for batch migration with dry-run support
|
||||
- **Dependencies**: P1.16
|
||||
- **Acceptance**: `python tools/migrate_to_spec_v2.py --dry-run studies/*`
|
||||
|
||||
---
|
||||
|
||||
## PHASE 2: Frontend Integration
|
||||
|
||||
### P2.1 - Create useSpecStore hook
|
||||
- **File**: `atomizer-dashboard/frontend/src/hooks/useSpecStore.ts`
|
||||
- **Action**: Zustand store for AtomizerSpec state management
|
||||
- **Dependencies**: P1.1
|
||||
- **Acceptance**: Store holds spec, provides typed accessors
|
||||
|
||||
### P2.2 - Add spec loading to useSpecStore
|
||||
- **File**: `atomizer-dashboard/frontend/src/hooks/useSpecStore.ts`
|
||||
- **Action**: Implement `loadSpec(studyId)` fetching from API
|
||||
- **Dependencies**: P2.1, P1.9
|
||||
- **Acceptance**: Loads spec from backend, updates store
|
||||
|
||||
### P2.3 - Add spec modification to useSpecStore
|
||||
- **File**: `atomizer-dashboard/frontend/src/hooks/useSpecStore.ts`
|
||||
- **Action**: Implement `patchSpec()`, `addNode()`, `removeNode()` calling API
|
||||
- **Dependencies**: P2.2, P1.11
|
||||
- **Acceptance**: Modifications persist to backend
|
||||
|
||||
### P2.4 - Add optimistic updates to useSpecStore
|
||||
- **File**: `atomizer-dashboard/frontend/src/hooks/useSpecStore.ts`
|
||||
- **Action**: Update local state immediately, rollback on error
|
||||
- **Dependencies**: P2.3
|
||||
- **Acceptance**: UI feels instant, handles errors gracefully
|
||||
|
||||
### P2.5 - Create specToNodes converter
|
||||
- **File**: `atomizer-dashboard/frontend/src/lib/spec/converter.ts`
|
||||
- **Action**: Convert AtomizerSpec to ReactFlow nodes array
|
||||
- **Reference**: Design in UNIFIED_CONFIGURATION_ARCHITECTURE.md Section 5.2
|
||||
- **Dependencies**: P1.1
|
||||
- **Acceptance**: All node types render correctly
|
||||
|
||||
### P2.6 - Create specToEdges converter
|
||||
- **File**: `atomizer-dashboard/frontend/src/lib/spec/converter.ts`
|
||||
- **Action**: Convert spec.canvas.edges to ReactFlow edges
|
||||
- **Dependencies**: P2.5
|
||||
- **Acceptance**: All connections render correctly
|
||||
|
||||
### P2.7 - Create SpecRenderer component
|
||||
- **File**: `atomizer-dashboard/frontend/src/components/canvas/SpecRenderer.tsx`
|
||||
- **Action**: ReactFlow component that renders from useSpecStore
|
||||
- **Dependencies**: P2.5, P2.6, P2.4
|
||||
- **Acceptance**: Canvas displays spec correctly
|
||||
|
||||
### P2.8 - Wire node editing to spec updates
|
||||
- **File**: `atomizer-dashboard/frontend/src/components/canvas/SpecRenderer.tsx`
|
||||
- **Action**: Node data changes call useSpecStore.patchSpec()
|
||||
- **Dependencies**: P2.7
|
||||
- **Acceptance**: Editing node properties persists to spec
|
||||
|
||||
### P2.9 - Wire node position to spec updates
|
||||
- **File**: `atomizer-dashboard/frontend/src/components/canvas/SpecRenderer.tsx`
|
||||
- **Action**: Drag-drop updates canvas_position in spec
|
||||
- **Dependencies**: P2.8
|
||||
- **Acceptance**: Layout persists across reloads
|
||||
|
||||
### P2.10 - Update node panels for full spec fields
|
||||
- **Files**: `atomizer-dashboard/frontend/src/components/canvas/panels/*.tsx`
|
||||
- **Action**: Update all node config panels to show/edit full spec fields
|
||||
- **Dependencies**: P2.8
|
||||
- **Acceptance**: All spec fields are editable in UI
|
||||
|
||||
### P2.11 - Create WebSocket connection hook
|
||||
- **File**: `atomizer-dashboard/frontend/src/hooks/useSpecSync.ts`
|
||||
- **Action**: WebSocket connection to `/api/studies/{id}/sync`
|
||||
- **Dependencies**: P2.4
|
||||
- **Acceptance**: Connects, handles reconnection
|
||||
|
||||
### P2.12 - Create WebSocket backend endpoint
|
||||
- **File**: `atomizer-dashboard/backend/api/routes/spec.py`
|
||||
- **Action**: WebSocket endpoint for spec sync
|
||||
- **Dependencies**: P1.12
|
||||
- **Acceptance**: Accepts connections, tracks subscribers
|
||||
|
||||
### P2.13 - Implement spec_updated broadcast
|
||||
- **File**: `atomizer-dashboard/backend/api/services/spec_manager.py`
|
||||
- **Action**: SpecManager broadcasts to all subscribers on save
|
||||
- **Dependencies**: P2.12
|
||||
- **Acceptance**: All connected clients receive updates
|
||||
|
||||
### P2.14 - Handle spec_updated in frontend
|
||||
- **File**: `atomizer-dashboard/frontend/src/hooks/useSpecSync.ts`
|
||||
- **Action**: On spec_updated message, refresh spec from store
|
||||
- **Dependencies**: P2.11, P2.13
|
||||
- **Acceptance**: Changes from other clients appear in real-time
|
||||
|
||||
### P2.15 - Add conflict detection
|
||||
- **File**: `atomizer-dashboard/frontend/src/hooks/useSpecStore.ts`
|
||||
- **Action**: Compare hashes, warn on conflict, offer merge/overwrite
|
||||
- **Dependencies**: P2.14
|
||||
- **Acceptance**: Concurrent edits don't silently overwrite
|
||||
|
||||
### P2.16 - Replace CanvasView with SpecRenderer
|
||||
- **File**: `atomizer-dashboard/frontend/src/pages/CanvasView.tsx`
|
||||
- **Action**: Switch from useCanvasStore to useSpecStore + SpecRenderer
|
||||
- **Dependencies**: P2.10, P2.15
|
||||
- **Acceptance**: Canvas page uses new spec-based system
|
||||
|
||||
---
|
||||
|
||||
## PHASE 3: Claude Integration
|
||||
|
||||
### P3.1 - Create spec_get MCP tool
|
||||
- **File**: `mcp-server/atomizer-tools/src/tools/spec_tools.ts`
|
||||
- **Action**: Tool to retrieve full AtomizerSpec
|
||||
- **Reference**: Design in UNIFIED_CONFIGURATION_ARCHITECTURE.md Section 5.3
|
||||
- **Dependencies**: P1.9
|
||||
- **Acceptance**: Claude can read spec via MCP
|
||||
|
||||
### P3.2 - Create spec_modify MCP tool
|
||||
- **File**: `mcp-server/atomizer-tools/src/tools/spec_tools.ts`
|
||||
- **Action**: Tool to apply modifications (set, add, remove operations)
|
||||
- **Dependencies**: P3.1, P1.11
|
||||
- **Acceptance**: Claude can modify spec fields
|
||||
|
||||
### P3.3 - Create spec_add_node MCP tool
|
||||
- **File**: `mcp-server/atomizer-tools/src/tools/spec_tools.ts`
|
||||
- **Action**: Tool to add design vars, extractors, objectives, constraints
|
||||
- **Dependencies**: P3.2
|
||||
- **Acceptance**: Claude can add nodes to canvas
|
||||
|
||||
### P3.4 - Create spec_remove_node MCP tool
|
||||
- **File**: `mcp-server/atomizer-tools/src/tools/spec_tools.ts`
|
||||
- **Action**: Tool to remove nodes (with edge cleanup)
|
||||
- **Dependencies**: P3.3
|
||||
- **Acceptance**: Claude can remove nodes
|
||||
|
||||
### P3.5 - Create spec_validate MCP tool
|
||||
- **File**: `mcp-server/atomizer-tools/src/tools/spec_tools.ts`
|
||||
- **Action**: Tool to validate spec and return report
|
||||
- **Dependencies**: P1.12
|
||||
- **Acceptance**: Claude can check spec validity
|
||||
|
||||
### P3.6 - Create spec_add_custom_extractor MCP tool
|
||||
- **File**: `mcp-server/atomizer-tools/src/tools/spec_tools.ts`
|
||||
- **Action**: Tool to add custom Python functions as extractors
|
||||
- **Dependencies**: P1.7, P3.3
|
||||
- **Acceptance**: Claude can add custom extraction logic
|
||||
|
||||
### P3.7 - Register spec tools in MCP server
|
||||
- **File**: `mcp-server/atomizer-tools/src/index.ts`
|
||||
- **Action**: Import and register all spec_* tools
|
||||
- **Dependencies**: P3.1-P3.6
|
||||
- **Acceptance**: Tools appear in MCP tool list
|
||||
|
||||
### P3.8 - Update ContextBuilder for spec awareness
|
||||
- **File**: `atomizer-dashboard/backend/api/services/context_builder.py`
|
||||
- **Action**: Include spec summary in Claude context, mention spec tools
|
||||
- **Dependencies**: P3.7
|
||||
- **Acceptance**: Claude knows about spec tools in context
|
||||
|
||||
### P3.9 - Create custom extractor runtime loader
|
||||
- **File**: `optimization_engine/extractors/custom_loader.py`
|
||||
- **Action**: Dynamically load and execute custom functions from spec
|
||||
- **Dependencies**: P1.7
|
||||
- **Acceptance**: Custom functions execute during optimization
|
||||
|
||||
### P3.10 - Integrate custom extractors into optimization runner
|
||||
- **File**: `optimization_engine/core/runner.py`
|
||||
- **Action**: Check spec for custom extractors, load and use them
|
||||
- **Dependencies**: P3.9
|
||||
- **Acceptance**: Optimization uses custom extractors defined in spec
|
||||
|
||||
### P3.11 - Add custom extractor node type to canvas
|
||||
- **File**: `atomizer-dashboard/frontend/src/components/canvas/nodes/CustomExtractorNode.tsx`
|
||||
- **Action**: New node type showing custom function with code preview
|
||||
- **Dependencies**: P2.10
|
||||
- **Acceptance**: Custom extractors display distinctly in canvas
|
||||
|
||||
### P3.12 - Add code editor for custom extractors
|
||||
- **File**: `atomizer-dashboard/frontend/src/components/canvas/panels/CustomExtractorPanel.tsx`
|
||||
- **Action**: Monaco editor for viewing/editing custom Python code
|
||||
- **Dependencies**: P3.11
|
||||
- **Acceptance**: Users can view and edit custom function code
|
||||
|
||||
### P3.13 - Create spec_create_from_description MCP tool
|
||||
- **File**: `mcp-server/atomizer-tools/src/tools/spec_tools.ts`
|
||||
- **Action**: Tool to create new spec from natural language + model path
|
||||
- **Dependencies**: P3.6, P1.16
|
||||
- **Acceptance**: Claude can create studies from descriptions
|
||||
|
||||
### P3.14 - Update Claude prompts for spec workflow
|
||||
- **File**: `atomizer-dashboard/backend/api/services/context_builder.py`
|
||||
- **Action**: Update system prompts to guide Claude on using spec tools
|
||||
- **Dependencies**: P3.13
|
||||
- **Acceptance**: Claude naturally uses spec tools for modifications
|
||||
|
||||
---
|
||||
|
||||
## PHASE 4: Polish & Testing
|
||||
|
||||
### P4.1 - Migrate m1_mirror studies
|
||||
- **Action**: Run migration on all m1_mirror_* studies
|
||||
- **Dependencies**: P1.17
|
||||
- **Acceptance**: All studies have valid atomizer_spec.json
|
||||
|
||||
### P4.2 - Migrate drone_gimbal study
|
||||
- **Action**: Run migration on drone_gimbal study
|
||||
- **Dependencies**: P1.17
|
||||
- **Acceptance**: Study has valid atomizer_spec.json
|
||||
|
||||
### P4.3 - Migrate all remaining studies
|
||||
- **Action**: Run migration on all studies in studies/
|
||||
- **Dependencies**: P4.1, P4.2
|
||||
- **Acceptance**: All studies migrated, validated
|
||||
|
||||
### P4.4 - Create spec unit tests
|
||||
- **File**: `tests/test_spec_manager.py`
|
||||
- **Action**: Unit tests for SpecManager operations
|
||||
- **Dependencies**: P1.7
|
||||
- **Acceptance**: All SpecManager methods tested
|
||||
|
||||
### P4.5 - Create spec API integration tests
|
||||
- **File**: `tests/test_spec_api.py`
|
||||
- **Action**: Integration tests for REST endpoints
|
||||
- **Dependencies**: P1.12
|
||||
- **Acceptance**: All endpoints tested
|
||||
|
||||
### P4.6 - Create migration tests
|
||||
- **File**: `tests/test_migrator.py`
|
||||
- **Action**: Test migration with various config formats
|
||||
- **Dependencies**: P1.16
|
||||
- **Acceptance**: All config variants migrate correctly
|
||||
|
||||
### P4.7 - Create frontend component tests
|
||||
- **File**: `atomizer-dashboard/frontend/src/__tests__/SpecRenderer.test.tsx`
|
||||
- **Action**: Test SpecRenderer with various specs
|
||||
- **Dependencies**: P2.16
|
||||
- **Acceptance**: Canvas renders correctly for all spec types
|
||||
|
||||
### P4.8 - Create WebSocket sync tests
|
||||
- **File**: `tests/test_spec_sync.py`
|
||||
- **Action**: Test real-time sync between multiple clients
|
||||
- **Dependencies**: P2.15
|
||||
- **Acceptance**: Changes propagate correctly
|
||||
|
||||
### P4.9 - Create MCP tools tests
|
||||
- **File**: `mcp-server/atomizer-tools/src/__tests__/spec_tools.test.ts`
|
||||
- **Action**: Test all spec_* MCP tools
|
||||
- **Dependencies**: P3.7
|
||||
- **Acceptance**: All tools work correctly
|
||||
|
||||
### P4.10 - End-to-end testing
|
||||
- **Action**: Full workflow test: create study in canvas, modify via Claude, run optimization
|
||||
- **Dependencies**: P4.1-P4.9
|
||||
- **Acceptance**: Complete workflow works
|
||||
|
||||
### P4.11 - Update documentation
|
||||
- **Files**: `docs/04_USER_GUIDES/CANVAS.md`, `docs/04_USER_GUIDES/DASHBOARD.md`
|
||||
- **Action**: Document new spec-based workflow
|
||||
- **Dependencies**: P4.10
|
||||
- **Acceptance**: Documentation reflects new system
|
||||
|
||||
### P4.12 - Update CLAUDE.md
|
||||
- **File**: `CLAUDE.md`
|
||||
- **Action**: Add spec tools documentation, update context loading
|
||||
- **Dependencies**: P4.11
|
||||
- **Acceptance**: Claude Code sessions know about spec system
|
||||
|
||||
---
|
||||
|
||||
## File Summary
|
||||
|
||||
### New Files to Create
|
||||
|
||||
| File | Phase | Purpose |
|
||||
|------|-------|---------|
|
||||
| `atomizer-dashboard/frontend/src/types/atomizer-spec.ts` | P1 | TypeScript types |
|
||||
| `optimization_engine/config/spec_models.py` | P1 | Pydantic models |
|
||||
| `optimization_engine/config/spec_validator.py` | P1 | Validation logic |
|
||||
| `atomizer-dashboard/backend/api/services/spec_manager.py` | P1 | Core spec service |
|
||||
| `atomizer-dashboard/backend/api/routes/spec.py` | P1 | REST endpoints |
|
||||
| `optimization_engine/config/migrator.py` | P1 | Config migration |
|
||||
| `tools/migrate_to_spec_v2.py` | P1 | Migration CLI |
|
||||
| `atomizer-dashboard/frontend/src/hooks/useSpecStore.ts` | P2 | Spec state store |
|
||||
| `atomizer-dashboard/frontend/src/hooks/useSpecSync.ts` | P2 | WebSocket sync |
|
||||
| `atomizer-dashboard/frontend/src/lib/spec/converter.ts` | P2 | Spec ↔ ReactFlow |
|
||||
| `atomizer-dashboard/frontend/src/components/canvas/SpecRenderer.tsx` | P2 | New canvas component |
|
||||
| `mcp-server/atomizer-tools/src/tools/spec_tools.ts` | P3 | MCP tools |
|
||||
| `optimization_engine/extractors/custom_loader.py` | P3 | Custom function loader |
|
||||
| `atomizer-dashboard/frontend/src/components/canvas/nodes/CustomExtractorNode.tsx` | P3 | Custom node type |
|
||||
| `atomizer-dashboard/frontend/src/components/canvas/panels/CustomExtractorPanel.tsx` | P3 | Code editor panel |
|
||||
|
||||
### Files to Modify
|
||||
|
||||
| File | Phase | Changes |
|
||||
|------|-------|---------|
|
||||
| `atomizer-dashboard/backend/api/main.py` | P1 | Mount spec router |
|
||||
| `mcp-server/atomizer-tools/src/index.ts` | P3 | Register spec tools |
|
||||
| `atomizer-dashboard/backend/api/services/context_builder.py` | P3 | Update Claude context |
|
||||
| `optimization_engine/core/runner.py` | P3 | Custom extractor support |
|
||||
| `atomizer-dashboard/frontend/src/pages/CanvasView.tsx` | P2 | Use SpecRenderer |
|
||||
| `CLAUDE.md` | P4 | Document spec system |
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
### Phase 1 Complete When:
|
||||
- [ ] SpecManager can load/save/validate specs
|
||||
- [ ] All REST endpoints return correct responses
|
||||
- [ ] Migration tool converts existing configs
|
||||
|
||||
### Phase 2 Complete When:
|
||||
- [ ] Canvas renders from AtomizerSpec
|
||||
- [ ] Edits persist to spec file
|
||||
- [ ] WebSocket sync works between clients
|
||||
|
||||
### Phase 3 Complete When:
|
||||
- [ ] Claude can read and modify specs via MCP
|
||||
- [ ] Custom extractors work in optimization
|
||||
- [ ] Claude can create studies from descriptions
|
||||
|
||||
### Phase 4 Complete When:
|
||||
- [ ] All existing studies migrated
|
||||
- [ ] All tests pass
|
||||
- [ ] Documentation updated
|
||||
|
||||
---
|
||||
|
||||
## Risk Mitigation
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| Existing studies break | Migration tool with dry-run, keep old configs as backup |
|
||||
| WebSocket complexity | Start with polling, add WebSocket as enhancement |
|
||||
| Custom code security | Sandbox execution, syntax validation, no imports |
|
||||
| Performance with large specs | Lazy loading, incremental updates |
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**Master Design**: `docs/plans/UNIFIED_CONFIGURATION_ARCHITECTURE.md`
|
||||
**Schema**: `optimization_engine/schemas/atomizer_spec_v2.json`
|
||||
**This Plan**: `docs/plans/UNIFIED_CONFIG_EXECUTION_PLAN.md`
|
||||
|
||||
---
|
||||
|
||||
*Execute tasks in order. Each task has clear acceptance criteria. Reference the master design document for detailed specifications.*
|
||||
@@ -1,286 +0,0 @@
|
||||
# Ralph Loop Prompt: AtomizerSpec v2.0 Implementation
|
||||
|
||||
**Copy this prompt to start the autonomous implementation loop.**
|
||||
|
||||
---
|
||||
|
||||
## Claude CLI Command
|
||||
|
||||
```bash
|
||||
claude --dangerously-skip-permissions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Initial Prompt (Copy This)
|
||||
|
||||
```
|
||||
You are implementing the AtomizerSpec v2.0 Unified Configuration Architecture for Atomizer.
|
||||
|
||||
## Project Context
|
||||
|
||||
Read these documents before starting:
|
||||
1. `docs/plans/UNIFIED_CONFIGURATION_ARCHITECTURE.md` - Master design document with architecture, schemas, and component designs
|
||||
2. `docs/plans/UNIFIED_CONFIG_EXECUTION_PLAN.md` - Detailed task list with 50+ tasks across 4 phases
|
||||
3. `optimization_engine/schemas/atomizer_spec_v2.json` - The JSON Schema definition
|
||||
|
||||
## Your Mission
|
||||
|
||||
Implement the AtomizerSpec v2.0 system following the execution plan. Work through tasks in order (P1.1 → P1.2 → ... → P4.12).
|
||||
|
||||
## Rules
|
||||
|
||||
1. **Follow the plan**: Execute tasks in the order specified in UNIFIED_CONFIG_EXECUTION_PLAN.md
|
||||
2. **Check dependencies**: Don't start a task until its dependencies are complete
|
||||
3. **Use TodoWrite**: Track all tasks, mark in_progress when starting, completed when done
|
||||
4. **Test as you go**: Verify each task meets its acceptance criteria before moving on
|
||||
5. **Commit regularly**: Commit after completing each logical group of tasks (e.g., after P1.7, after P1.12)
|
||||
6. **Reference the design**: The master document has code examples - use them
|
||||
7. **Ask if blocked**: If you encounter a blocker, explain what's wrong and what you need
|
||||
|
||||
## Starting Point
|
||||
|
||||
1. Read the three reference documents listed above
|
||||
2. Load the current task list into TodoWrite
|
||||
3. Start with P1.1 (Create TypeScript types from JSON Schema)
|
||||
4. Work through each task, marking completion as you go
|
||||
|
||||
## Commit Message Format
|
||||
|
||||
Use conventional commits:
|
||||
- `feat(spec): Add SpecManager core class (P1.4)`
|
||||
- `feat(spec-api): Implement GET /studies/{id}/spec (P1.9)`
|
||||
- `feat(frontend): Create useSpecStore hook (P2.1)`
|
||||
- `test(spec): Add SpecManager unit tests (P4.4)`
|
||||
|
||||
## Progress Tracking
|
||||
|
||||
After completing each phase, summarize:
|
||||
- Tasks completed
|
||||
- Files created/modified
|
||||
- Any deviations from plan
|
||||
- Blockers encountered
|
||||
|
||||
Begin by reading the reference documents and loading tasks into TodoWrite.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Continuation Prompt (When Resuming)
|
||||
|
||||
```
|
||||
Continue implementing the AtomizerSpec v2.0 system.
|
||||
|
||||
Reference documents:
|
||||
- `docs/plans/UNIFIED_CONFIGURATION_ARCHITECTURE.md` - Master design
|
||||
- `docs/plans/UNIFIED_CONFIG_EXECUTION_PLAN.md` - Task list
|
||||
|
||||
Check where we left off:
|
||||
1. Read the current todo list
|
||||
2. Find the last completed task
|
||||
3. Continue with the next task in sequence
|
||||
|
||||
If you need context on what was done, check recent git commits.
|
||||
|
||||
Resume implementation.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase-Specific Prompts
|
||||
|
||||
### Start Phase 1 (Foundation)
|
||||
```
|
||||
Begin Phase 1 of AtomizerSpec implementation - Foundation/Backend.
|
||||
|
||||
Reference: `docs/plans/UNIFIED_CONFIG_EXECUTION_PLAN.md` section "PHASE 1: Foundation"
|
||||
|
||||
Tasks P1.1 through P1.17 focus on:
|
||||
- TypeScript and Python types from JSON Schema
|
||||
- SpecManager service (load, save, validate, patch, nodes)
|
||||
- REST API endpoints
|
||||
- Migration tool
|
||||
|
||||
Start with P1.1: Create TypeScript types from the JSON Schema at `optimization_engine/schemas/atomizer_spec_v2.json`.
|
||||
|
||||
Work through each task in order, tracking with TodoWrite.
|
||||
```
|
||||
|
||||
### Start Phase 2 (Frontend)
|
||||
```
|
||||
Begin Phase 2 of AtomizerSpec implementation - Frontend Integration.
|
||||
|
||||
Reference: `docs/plans/UNIFIED_CONFIG_EXECUTION_PLAN.md` section "PHASE 2: Frontend Integration"
|
||||
|
||||
Tasks P2.1 through P2.16 focus on:
|
||||
- useSpecStore hook (Zustand state management)
|
||||
- Spec ↔ ReactFlow conversion
|
||||
- SpecRenderer component
|
||||
- WebSocket real-time sync
|
||||
- Replacing old canvas with spec-based canvas
|
||||
|
||||
Prerequisites: Phase 1 must be complete (P1.1-P1.17).
|
||||
|
||||
Start with P2.1: Create useSpecStore hook.
|
||||
|
||||
Work through each task in order, tracking with TodoWrite.
|
||||
```
|
||||
|
||||
### Start Phase 3 (Claude Integration)
|
||||
```
|
||||
Begin Phase 3 of AtomizerSpec implementation - Claude Integration.
|
||||
|
||||
Reference: `docs/plans/UNIFIED_CONFIG_EXECUTION_PLAN.md` section "PHASE 3: Claude Integration"
|
||||
|
||||
Tasks P3.1 through P3.14 focus on:
|
||||
- MCP tools for spec operations (spec_get, spec_modify, spec_add_node, etc.)
|
||||
- Custom extractor support (add Python functions via Claude)
|
||||
- Runtime loading of custom functions
|
||||
- Natural language study creation
|
||||
|
||||
Prerequisites: Phases 1 and 2 must be complete.
|
||||
|
||||
Start with P3.1: Create spec_get MCP tool.
|
||||
|
||||
Work through each task in order, tracking with TodoWrite.
|
||||
```
|
||||
|
||||
### Start Phase 4 (Polish & Testing)
|
||||
```
|
||||
Begin Phase 4 of AtomizerSpec implementation - Polish & Testing.
|
||||
|
||||
Reference: `docs/plans/UNIFIED_CONFIG_EXECUTION_PLAN.md` section "PHASE 4: Polish & Testing"
|
||||
|
||||
Tasks P4.1 through P4.12 focus on:
|
||||
- Migrating all existing studies to AtomizerSpec v2
|
||||
- Unit tests, integration tests, e2e tests
|
||||
- Documentation updates
|
||||
|
||||
Prerequisites: Phases 1, 2, and 3 must be complete.
|
||||
|
||||
Start with P4.1: Migrate m1_mirror studies.
|
||||
|
||||
Work through each task in order, tracking with TodoWrite.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting Prompts
|
||||
|
||||
### If Stuck on a Task
|
||||
```
|
||||
I'm blocked on task [TASK_ID].
|
||||
|
||||
The issue is: [describe the problem]
|
||||
|
||||
What I've tried: [list attempts]
|
||||
|
||||
Please help me resolve this so I can continue with the execution plan.
|
||||
```
|
||||
|
||||
### If Tests Fail
|
||||
```
|
||||
Tests are failing for [component].
|
||||
|
||||
Error: [paste error]
|
||||
|
||||
This is blocking task [TASK_ID]. Help me fix the tests so I can mark the task complete.
|
||||
```
|
||||
|
||||
### If Design Needs Clarification
|
||||
```
|
||||
Task [TASK_ID] requires [specific thing] but the design document doesn't specify [what's unclear].
|
||||
|
||||
Options I see:
|
||||
1. [option A]
|
||||
2. [option B]
|
||||
|
||||
Which approach should I take? Or should I update the design document?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Full Task List for TodoWrite
|
||||
|
||||
Copy this to initialize the todo list:
|
||||
|
||||
```
|
||||
P1.1 - Create TypeScript types from JSON Schema
|
||||
P1.2 - Create Python Pydantic models from JSON Schema
|
||||
P1.3 - Create spec validation utility
|
||||
P1.4 - Create SpecManager core class
|
||||
P1.5 - Add SpecManager patch functionality
|
||||
P1.6 - Add SpecManager node operations
|
||||
P1.7 - Add SpecManager custom function support
|
||||
P1.8 - Create spec REST router
|
||||
P1.9 - Implement GET /studies/{study_id}/spec
|
||||
P1.10 - Implement PUT /studies/{study_id}/spec
|
||||
P1.11 - Implement PATCH /studies/{study_id}/spec
|
||||
P1.12 - Implement POST /studies/{study_id}/spec/validate
|
||||
P1.13 - Create config migration base
|
||||
P1.14 - Implement design variable migration
|
||||
P1.15 - Implement objective/constraint migration
|
||||
P1.16 - Implement full config migration
|
||||
P1.17 - Create migration CLI tool
|
||||
P2.1 - Create useSpecStore hook
|
||||
P2.2 - Add spec loading to useSpecStore
|
||||
P2.3 - Add spec modification to useSpecStore
|
||||
P2.4 - Add optimistic updates to useSpecStore
|
||||
P2.5 - Create specToNodes converter
|
||||
P2.6 - Create specToEdges converter
|
||||
P2.7 - Create SpecRenderer component
|
||||
P2.8 - Wire node editing to spec updates
|
||||
P2.9 - Wire node position to spec updates
|
||||
P2.10 - Update node panels for full spec fields
|
||||
P2.11 - Create WebSocket connection hook
|
||||
P2.12 - Create WebSocket backend endpoint
|
||||
P2.13 - Implement spec_updated broadcast
|
||||
P2.14 - Handle spec_updated in frontend
|
||||
P2.15 - Add conflict detection
|
||||
P2.16 - Replace CanvasView with SpecRenderer
|
||||
P3.1 - Create spec_get MCP tool
|
||||
P3.2 - Create spec_modify MCP tool
|
||||
P3.3 - Create spec_add_node MCP tool
|
||||
P3.4 - Create spec_remove_node MCP tool
|
||||
P3.5 - Create spec_validate MCP tool
|
||||
P3.6 - Create spec_add_custom_extractor MCP tool
|
||||
P3.7 - Register spec tools in MCP server
|
||||
P3.8 - Update ContextBuilder for spec awareness
|
||||
P3.9 - Create custom extractor runtime loader
|
||||
P3.10 - Integrate custom extractors into optimization runner
|
||||
P3.11 - Add custom extractor node type to canvas
|
||||
P3.12 - Add code editor for custom extractors
|
||||
P3.13 - Create spec_create_from_description MCP tool
|
||||
P3.14 - Update Claude prompts for spec workflow
|
||||
P4.1 - Migrate m1_mirror studies
|
||||
P4.2 - Migrate drone_gimbal study
|
||||
P4.3 - Migrate all remaining studies
|
||||
P4.4 - Create spec unit tests
|
||||
P4.5 - Create spec API integration tests
|
||||
P4.6 - Create migration tests
|
||||
P4.7 - Create frontend component tests
|
||||
P4.8 - Create WebSocket sync tests
|
||||
P4.9 - Create MCP tools tests
|
||||
P4.10 - End-to-end testing
|
||||
P4.11 - Update documentation
|
||||
P4.12 - Update CLAUDE.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Expected Outcomes
|
||||
|
||||
After successful completion:
|
||||
|
||||
1. **Single Source of Truth**: `atomizer_spec.json` used everywhere
|
||||
2. **Bidirectional Sync**: Canvas ↔ Spec with no data loss
|
||||
3. **Real-time Updates**: WebSocket keeps all clients in sync
|
||||
4. **Claude Integration**: Claude can read/modify/create specs via MCP
|
||||
5. **Custom Functions**: Users can add Python extractors through UI/Claude
|
||||
6. **All Studies Migrated**: Existing configs converted to v2 format
|
||||
7. **Full Test Coverage**: Unit, integration, and e2e tests passing
|
||||
8. **Updated Documentation**: User guides reflect new workflow
|
||||
|
||||
---
|
||||
|
||||
*This prompt file enables autonomous implementation of the AtomizerSpec v2.0 system using the Ralph Loop pattern.*
|
||||
Reference in New Issue
Block a user