feat: Add Studio UI, intake system, and extractor improvements
Dashboard: - Add Studio page with drag-drop model upload and Claude chat - Add intake system for study creation workflow - Improve session manager and context builder - Add intake API routes and frontend components Optimization Engine: - Add CLI module for command-line operations - Add intake module for study preprocessing - Add validation module with gate checks - Improve Zernike extractor documentation - Update spec models with better validation - Enhance solve_simulation robustness Documentation: - Add ATOMIZER_STUDIO.md planning doc - Add ATOMIZER_UX_SYSTEM.md for UX patterns - Update extractor library docs - Add study-readme-generator skill Tools: - Add test scripts for extraction validation - Add Zernike recentering test Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
144
docs/plans/ATOMIZER_STUDIO.md
Normal file
144
docs/plans/ATOMIZER_STUDIO.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# Atomizer Studio - Technical Implementation Plan
|
||||
|
||||
**Version**: 1.0
|
||||
**Date**: January 24, 2026
|
||||
**Status**: In Progress
|
||||
**Author**: Atomizer Team
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive Summary
|
||||
|
||||
**Atomizer Studio** is a unified, drag-and-drop study creation environment that consolidates file management, visual configuration (Canvas), and AI assistance into a single real-time workspace. It replaces the legacy wizard-based approach with a modern "Studio" experience.
|
||||
|
||||
### Core Principles
|
||||
|
||||
| Principle | Implementation |
|
||||
|-----------|----------------|
|
||||
| **Drag & Drop First** | No wizards, no forms. Drop files, see results. |
|
||||
| **AI-Native** | Claude sees everything: files, parameters, goals. It proposes, you approve. |
|
||||
| **Zero Commitment** | Work in "Draft Mode" until ready. Nothing is permanent until "Build". |
|
||||
|
||||
---
|
||||
|
||||
## 2. Architecture
|
||||
|
||||
### 2.1 The Draft Workflow
|
||||
|
||||
```
|
||||
User Opens /studio
|
||||
│
|
||||
▼
|
||||
POST /intake/draft ──► Creates studies/_inbox/draft_{id}/
|
||||
│
|
||||
▼
|
||||
User Drops Files ──► Auto-Introspection ──► Parameters Discovered
|
||||
│
|
||||
▼
|
||||
AI Reads Context ──► Proposes Configuration ──► Canvas Updates
|
||||
│
|
||||
▼
|
||||
User Clicks BUILD ──► Finalize ──► studies/{topic}/{name}/
|
||||
```
|
||||
|
||||
### 2.2 Interface Layout
|
||||
|
||||
```
|
||||
┌───────────────────┬───────────────────────────────────────────────┬───────────────────┐
|
||||
│ RESOURCES (Left) │ CANVAS (Center) │ ASSISTANT (Right) │
|
||||
├───────────────────┼───────────────────────────────────────────────┼───────────────────┤
|
||||
│ ▼ DROP ZONE │ │ │
|
||||
│ [Drag files] │ ┌───────┐ ┌────────┐ ┌─────────┐ │ "I see you want │
|
||||
│ │ │ Model ├─────►│ Solver ├─────►│ Extract │ │ to minimize │
|
||||
│ ▼ MODEL FILES │ └───────┘ └────────┘ └────┬────┘ │ mass. Adding │
|
||||
│ • bracket.sim │ │ │ objective..." │
|
||||
│ • bracket.prt │ ┌────▼────┐ │ │
|
||||
│ │ │ Objectiv│ │ [Apply Changes] │
|
||||
│ ▼ PARAMETERS │ └─────────┘ │ │
|
||||
│ • thickness │ │ │
|
||||
│ • rib_count │ AtomizerSpec v2.0 │ │
|
||||
│ │ (Draft Mode) │ │
|
||||
│ ▼ CONTEXT │ │ │
|
||||
│ • goals.pdf │ │ [ Chat Input... ] │
|
||||
├───────────────────┼───────────────────────────────────────────────┼───────────────────┤
|
||||
│ [ Reset Draft ] │ [ Validate ] [ BUILD STUDY ] │ │
|
||||
└───────────────────┴───────────────────────────────────────────────┴───────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Implementation Phases
|
||||
|
||||
### Phase 1: Backend API Enhancements
|
||||
- `POST /intake/draft` - Create anonymous draft
|
||||
- `GET /intake/{id}/context/content` - Extract text from uploaded files
|
||||
- Enhanced `POST /intake/{id}/finalize` with rename support
|
||||
|
||||
### Phase 2: Frontend Studio Shell
|
||||
- `/studio` route with 3-column layout
|
||||
- DropZone component with file categorization
|
||||
- Integrated Canvas in draft mode
|
||||
- Parameter discovery panel
|
||||
|
||||
### Phase 3: AI Integration
|
||||
- Context-aware chat system
|
||||
- Spec modification via Claude
|
||||
- Real-time canvas updates
|
||||
|
||||
### Phase 4: Polish & Testing
|
||||
- Full DevLoop testing
|
||||
- Edge case handling
|
||||
- UX polish and animations
|
||||
|
||||
---
|
||||
|
||||
## 4. File Structure
|
||||
|
||||
```
|
||||
atomizer-dashboard/
|
||||
├── frontend/src/
|
||||
│ ├── pages/
|
||||
│ │ └── Studio.tsx
|
||||
│ ├── components/
|
||||
│ │ └── studio/
|
||||
│ │ ├── StudioLayout.tsx
|
||||
│ │ ├── ResourcePanel.tsx
|
||||
│ │ ├── StudioCanvas.tsx
|
||||
│ │ ├── StudioChat.tsx
|
||||
│ │ ├── DropZone.tsx
|
||||
│ │ ├── ParameterList.tsx
|
||||
│ │ ├── ContextFileList.tsx
|
||||
│ │ └── BuildDialog.tsx
|
||||
│ └── hooks/
|
||||
│ └── useDraft.ts
|
||||
├── backend/api/
|
||||
│ └── routes/
|
||||
│ └── intake.py (enhanced)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. API Endpoints
|
||||
|
||||
### New Endpoints
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/intake/draft` | POST | Create anonymous draft study |
|
||||
| `/intake/{id}/context/content` | GET | Extract text from context files |
|
||||
|
||||
### Enhanced Endpoints
|
||||
|
||||
| Endpoint | Change |
|
||||
|----------|--------|
|
||||
| `/intake/{id}/finalize` | Added `new_name` parameter for rename |
|
||||
|
||||
---
|
||||
|
||||
## 6. Status
|
||||
|
||||
- [x] Plan documented
|
||||
- [ ] Phase 1: Backend
|
||||
- [ ] Phase 2: Frontend Shell
|
||||
- [ ] Phase 3: AI Integration
|
||||
- [ ] Phase 4: Testing & Polish
|
||||
1191
docs/plans/ATOMIZER_UX_SYSTEM.md
Normal file
1191
docs/plans/ATOMIZER_UX_SYSTEM.md
Normal file
File diff suppressed because it is too large
Load Diff
637
docs/plans/DASHBOARD_INTAKE_ATOMIZERSPEC_INTEGRATION.md
Normal file
637
docs/plans/DASHBOARD_INTAKE_ATOMIZERSPEC_INTEGRATION.md
Normal file
@@ -0,0 +1,637 @@
|
||||
# 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*
|
||||
@@ -110,31 +110,48 @@ frequency = result['frequency'] # Hz
|
||||
```python
|
||||
from optimization_engine.extractors.extract_von_mises_stress import extract_solid_stress
|
||||
|
||||
# For shell elements (CQUAD4, CTRIA3)
|
||||
result = extract_solid_stress(op2_file, subcase=1, element_type='cquad4')
|
||||
# RECOMMENDED: Check ALL solid element types (returns max across all)
|
||||
result = extract_solid_stress(op2_file, subcase=1)
|
||||
|
||||
# For solid elements (CTETRA, CHEXA)
|
||||
result = extract_solid_stress(op2_file, subcase=1, element_type='ctetra')
|
||||
# Or specify single element type
|
||||
result = extract_solid_stress(op2_file, subcase=1, element_type='chexa')
|
||||
|
||||
# Returns: {
|
||||
# 'max_von_mises': float, # MPa
|
||||
# 'max_stress_element': int
|
||||
# 'max_von_mises': float, # MPa (auto-converted from kPa)
|
||||
# 'max_stress_element': int,
|
||||
# 'element_type': str, # e.g., 'CHEXA', 'CTETRA'
|
||||
# 'units': 'MPa'
|
||||
# }
|
||||
|
||||
max_stress = result['max_von_mises'] # MPa
|
||||
```
|
||||
|
||||
**IMPORTANT (Updated 2026-01-22):**
|
||||
- By default, checks ALL solid types: CTETRA, CHEXA, CPENTA, CPYRAM
|
||||
- CHEXA elements often have highest stress (not CTETRA!)
|
||||
- Auto-converts from kPa to MPa (NX kg-mm-s unit system outputs kPa)
|
||||
- Returns Elemental Nodal stress (peak), not Elemental Centroid (averaged)
|
||||
|
||||
### E4: BDF Mass Extraction
|
||||
|
||||
**Module**: `optimization_engine.extractors.bdf_mass_extractor`
|
||||
**Module**: `optimization_engine.extractors.extract_mass_from_bdf`
|
||||
|
||||
```python
|
||||
from optimization_engine.extractors.bdf_mass_extractor import extract_mass_from_bdf
|
||||
from optimization_engine.extractors import extract_mass_from_bdf
|
||||
|
||||
mass_kg = extract_mass_from_bdf(str(bdf_file)) # kg
|
||||
result = extract_mass_from_bdf(bdf_file)
|
||||
# Returns: {
|
||||
# 'total_mass': float, # kg (primary key)
|
||||
# 'mass_kg': float, # kg
|
||||
# 'mass_g': float, # grams
|
||||
# 'cg': [x, y, z], # center of gravity
|
||||
# 'num_elements': int
|
||||
# }
|
||||
|
||||
mass_kg = result['mass_kg'] # kg
|
||||
```
|
||||
|
||||
**Note**: Reads mass directly from BDF/DAT file material and element definitions.
|
||||
**Note**: Uses `BDFMassExtractor` internally. Reads mass from element geometry and material density in BDF/DAT file. NX kg-mm-s unit system - mass is directly in kg.
|
||||
|
||||
### E5: CAD Expression Mass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user