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:
2026-02-09 02:48:35 +00:00
parent 9541958eae
commit 8d9d55356c
34 changed files with 3651 additions and 69 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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()
```

View File

@@ -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

View File

@@ -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

View File

@@ -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"
```

View File

@@ -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

View File

@@ -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*

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>*

View File

@@ -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

View File

@@ -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.*

View File

@@ -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.*