React 19 runtime migration complete, AI-assisted migration underway

This commit is contained in:
Richard Osborne
2025-12-20 23:32:50 +01:00
parent 7d307066d8
commit 03a464f6ff
22 changed files with 3081 additions and 145 deletions

View File

@@ -2,11 +2,207 @@
## [Unreleased]
### Session 11: MigrationWizard AI Integration Complete
#### 2024-12-20
**Completed:**
- **MigrationWizard.tsx** - Full AI integration with proper wiring:
- Added imports for MigratingStep, AiDecision, AIConfigPanel, AIConfig types
- Added action types: CONFIGURE_AI, AI_CONFIGURED, BACK_TO_REPORT, AI_DECISION
- Added reducer cases for all AI flow transitions
- Implemented handlers:
- `handleConfigureAi()` - Navigate to AI configuration screen
- `handleAiConfigured()` - Save AI config and return to report (transforms config with spent: 0)
- `handleBackToReport()` - Cancel AI config and return to report
- `handleAiDecision()` - Handle user decisions during AI migration
- `handlePauseMigration()` - Pause ongoing migration
- Added render cases:
- `configureAi` step - Renders AIConfigPanel with save/cancel callbacks
- Updated `report` step - Added onConfigureAi prop and aiEnabled flag
- Updated `migrating` step - Replaced ScanningStep with MigratingStep, includes AI decision handling
**Technical Details:**
- AIConfig transformation adds `spent: 0` to budget before passing to MigrationSessionManager
- AI configuration flow: Report → Configure AI → Report (with AI enabled) → Migrate
- MigratingStep receives progress, useAi flag, budget, and decision/pause callbacks
- All unused imports removed (AIBudget, AIPreferences were for type reference only)
- Handlers use console.log for Phase 3 orchestrator hookup points
**Integration Status:**
✅ UI components complete (MigratingStep, ReportStep, AIConfigPanel)
✅ State management wired (reducer actions, handlers)
✅ Render flow complete (all step cases implemented)
⏳ Backend orchestration (Phase 3 - AIMigrationOrchestrator integration)
**Files Modified:**
```
packages/noodl-editor/src/editor/src/views/migration/
└── MigrationWizard.tsx (Complete AI integration)
```
**Next Steps:**
- Phase 3: Wire AIMigrationOrchestrator into MigrationSession.startMigration()
- Add event listeners for budget approval dialogs
- Handle real-time migration progress updates
- End-to-end testing with actual Claude API
---
### Session 10: AI Integration into Wizard
#### 2024-12-20
**Added:**
- **MigratingStep Component** - Real-time AI migration progress display:
- `MigratingStep.tsx` - Component with budget tracking, progress display, and AI decision panels
- `MigratingStep.module.scss` - Styling with animations for budget warnings and component progress
- Features:
- Budget display with warning state when >80% spent
- Component-by-component progress tracking
- Activity log with color-coded entries (info/success/warning/error)
- AI decision panel for handling migration failures
- Pause migration functionality
**Updated:**
- **ReportStep.tsx** - Enabled AI configuration:
- Added `onConfigureAi` callback prop
- Added `aiEnabled` prop to track AI configuration state
- "Configure AI" button appears when issues exist and AI not yet configured
- "Migrate with AI" button enabled when AI is configured
- Updated AI prompt text from "Coming Soon" to "Available"
**Technical Implementation:**
- MigratingStep handles both AI and non-AI migration display
- Decision panel allows user choices: retry, skip, or get help
- Budget bar changes color (orange) when approaching limit
- Real-time log entries with sliding animations
- Integrates with existing AIBudget and MigrationProgress types
**Files Created:**
```
packages/noodl-editor/src/editor/src/views/migration/steps/
├── MigratingStep.tsx
└── MigratingStep.module.scss
```
**Files Modified:**
```
packages/noodl-editor/src/editor/src/views/migration/steps/
└── ReportStep.tsx (AI configuration support)
```
**Next Steps:**
- Wire MigratingStep into MigrationWizard.tsx
- Connect AI configuration flow (configureAi step)
- Handle migrating step with AI decision logic
- End-to-end testing
---
### Session 9: AI Migration Implementation
#### 2024-12-20
**Added:**
- **Complete AI-Assisted Migration System** - Full implementation of Session 4 from spec:
- Core AI infrastructure (5 files):
- `claudePrompts.ts` - System prompts and templates for guiding Claude migrations
- `keyStorage.ts` - Encrypted API key storage using Electron's safeStorage API
- `claudeClient.ts` - Anthropic API wrapper with cost tracking and response parsing
- `BudgetController.ts` - Spending limits and approval flow management
- `AIMigrationOrchestrator.ts` - Coordinates multi-component migrations with retry logic
- UI components (4 files):
- `AIConfigPanel.tsx` + `.module.scss` - First-time setup for API key, budget, and preferences
- `BudgetApprovalDialog.tsx` + `.module.scss` - Pause dialog for budget approval
**Technical Implementation:**
- **Claude Integration:**
- Model: `claude-sonnet-4-20250514`
- Pricing: $3/$15 per 1M tokens (input/output)
- Max tokens: 4096 for migrations, 2048 for help requests
- Response format: Structured JSON with success/changes/warnings/confidence
- **Budget Controls:**
- Default: $5 max per session, $1 pause increments
- Hard limits prevent budget overruns
- Real-time cost tracking and display
- User approval required at spending increments
- **Migration Flow:**
1. User configures API key + budget (one-time setup)
2. Wizard scans project → identifies components needing AI help
3. User reviews and approves estimated cost
4. AI migrates each component with up to 3 retry attempts
5. Babel syntax verification after each migration
6. Failed migrations get manual suggestions via "Get Help" option
- **Security:**
- API keys stored with OS-level encryption (safeStorage)
- Fallback to electron-store encryption
- Keys never sent to OpenNoodl servers
- All API calls go directly to Anthropic
- **Verification:**
- Babel parser checks syntax validity
- Forbidden pattern detection (componentWillMount, string refs, etc.)
- Confidence threshold enforcement (default: 0.7)
- User decision points for low-confidence migrations
**Files Created:**
```
packages/noodl-editor/src/editor/src/utils/migration/
├── claudePrompts.ts
├── keyStorage.ts
└── claudeClient.ts
packages/noodl-editor/src/editor/src/models/migration/
├── BudgetController.ts
└── AIMigrationOrchestrator.ts
packages/noodl-editor/src/editor/src/views/migration/
├── AIConfigPanel.tsx
├── AIConfigPanel.module.scss
├── BudgetApprovalDialog.tsx
└── BudgetApprovalDialog.module.scss
```
**Dependencies Added:**
- `@anthropic-ai/sdk` - Claude API client
- `@babel/parser` - Code syntax verification
**Next Steps:**
- Integration into MigrationSession.ts (orchestrate AI phase)
- Update ReportStep.tsx to enable AI configuration
- Add MigratingStep.tsx for real-time AI progress display
- Testing with real project migrations
---
### Session 8: Migration Marker Fix
#### 2024-12-15
**Fixed:**
- **Migrated Projects Still Showing as Legacy** (`MigrationSession.ts`):
- Root cause: `executeFinalizePhase()` was a placeholder with just `await this.simulateDelay(200)` and never updated project.json
- The runtime detection system checks for `runtimeVersion` or `migratedFrom` fields in project.json
@@ -23,6 +219,7 @@
- Migrated projects now correctly identified as React 19 in project list
**Technical Notes:**
- Runtime detection checks these fields in order:
1. `runtimeVersion` field (highest confidence)
2. `migratedFrom` field (indicates already migrated)
@@ -32,6 +229,7 @@
- Adding `runtimeVersion: "react19"` provides "high" confidence detection
**Files Modified:**
```
packages/noodl-editor/src/editor/src/models/migration/MigrationSession.ts
```
@@ -43,7 +241,9 @@ packages/noodl-editor/src/editor/src/models/migration/MigrationSession.ts
#### 2024-12-14
**Fixed:**
- **Text Color Invisible (Gray on Gray)** (All migration SCSS files):
- Root cause: SCSS files used non-existent CSS variables like `--theme-color-fg-1` and `--theme-color-secondary` for text
- `--theme-color-fg-1` doesn't exist in the theme - it's `--theme-color-fg-highlight`
- `--theme-color-secondary` is a dark teal color (`#005769`) meant for backgrounds, not text
@@ -54,6 +254,7 @@ packages/noodl-editor/src/editor/src/models/migration/MigrationSession.ts
- Text is now visible with proper contrast against dark backgrounds
- **Migration Does Not Create Project Folder** (`MigrationSession.ts`):
- Root cause: `executeCopyPhase()` was a placeholder that never actually copied files
- Implemented actual file copying using `@noodl/platform` filesystem API
- New `copyDirectoryRecursive()` method recursively copies all project files
@@ -67,6 +268,7 @@ packages/noodl-editor/src/editor/src/models/migration/MigrationSession.ts
- Shows success toast and updates project list
**Technical Notes:**
- Theme color variable naming conventions:
- `--theme-color-bg-*` for backgrounds (bg-1 through bg-4, darker to lighter)
- `--theme-color-fg-*` for foreground/text (fg-highlight, fg-default, fg-default-shy, fg-muted)
@@ -80,6 +282,7 @@ packages/noodl-editor/src/editor/src/models/migration/MigrationSession.ts
- `filesystem.writeFile(path, content)` - write file contents
**Files Modified:**
```
packages/noodl-editor/src/editor/src/models/migration/MigrationSession.ts
packages/noodl-editor/src/editor/src/views/projectsview.ts
@@ -98,7 +301,9 @@ packages/noodl-editor/src/editor/src/views/migration/components/WizardProgress.m
#### 2024-12-14
**Fixed:**
- **"Start Migration" Button Does Nothing** (`MigrationWizard.tsx`):
- Root cause: useReducer `state.session` was never initialized
- Component used two sources of truth:
1. `migrationSessionManager.getSession()` for rendering - worked fine
@@ -108,6 +313,7 @@ packages/noodl-editor/src/editor/src/views/migration/components/WizardProgress.m
- Button clicks now properly dispatch actions and update state
- **Switched from Modal to CoreBaseDialog** (`MigrationWizard.tsx`):
- Modal component was causing layout and interaction issues
- CoreBaseDialog is the pattern used by working dialogs like ConfirmDialog
- Changed import and component usage to use CoreBaseDialog directly
@@ -118,19 +324,22 @@ packages/noodl-editor/src/editor/src/views/migration/components/WizardProgress.m
- Renamed one to `currentSession` to avoid redeclaration error
**Technical Notes:**
- When using both an external manager AND useReducer, reducer state must be explicitly synchronized
- CoreBaseDialog is the preferred pattern for dialogs - simpler and more reliable than Modal
- Pattern for initializing reducer with async data:
```tsx
// In useEffect after async operation:
dispatch({ type: 'SET_SESSION', session: createdSession });
// In reducer:
case 'SET_SESSION':
return { ...state, session: action.session };
```
**Files Modified:**
```
packages/noodl-editor/src/editor/src/views/migration/MigrationWizard.tsx
```
@@ -142,13 +351,16 @@ packages/noodl-editor/src/editor/src/views/migration/MigrationWizard.tsx
#### 2024-12-14
**Fixed:**
- **Migration Wizard Buttons Not Clickable** (`BaseDialog.module.scss`):
- Root cause: The `::after` pseudo-element on `.VisibleDialog` was covering the entire dialog
- This overlay had no `pointer-events: none`, blocking all click events
- Added `pointer-events: none` to `::after` pseudo-element
- All buttons, icons, and interactive elements now work correctly
- **Migration Wizard Not Scrollable** (`MigrationWizard.module.scss`):
- Root cause: Missing proper flex layout and overflow settings
- Added `display: flex`, `flex-direction: column`, and `overflow: hidden` to `.MigrationWizard`
- Added `flex: 1`, `min-height: 0`, and `overflow-y: auto` to `.WizardContent`
@@ -165,6 +377,7 @@ packages/noodl-editor/src/editor/src/views/migration/MigrationWizard.tsx
- Text now has proper contrast against modal background
**Technical Notes:**
- BaseDialog uses a `::after` pseudo-element for background color rendering
- Without `pointer-events: none`, this pseudo covers content and blocks interaction
- Theme color variables follow pattern: `--theme-color-{semantic-name}`
@@ -172,6 +385,7 @@ packages/noodl-editor/src/editor/src/views/migration/MigrationWizard.tsx
- Flex containers need `min-height: 0` on children to allow proper shrinking/scrolling
**Files Modified:**
```
packages/noodl-core-ui/src/components/layout/BaseDialog/BaseDialog.module.scss
packages/noodl-editor/src/editor/src/views/migration/MigrationWizard.module.scss
@@ -190,19 +404,23 @@ packages/noodl-editor/src/editor/src/views/migration/steps/FailedStep.module.scs
#### 2024-12-14
**Fixed:**
- **EPIPE Error on Project Open** (`cloud-function-server.js`):
- Added `safeLog()` wrapper function that catches and ignores EPIPE errors
- EPIPE occurs when stdout pipe is broken (e.g., terminal closed)
- All console.log calls in cloud-function-server now use safeLog
- Prevents editor crash when output pipe becomes unavailable
- **Runtime Detection Defaulting** (`ProjectScanner.ts`):
- Changed fallback runtime version from `'unknown'` to `'react17'`
- Projects without explicit markers now correctly identified as legacy
- Ensures old Noodl projects trigger migration UI even without version flags
- Updated indicator message: "No React 19 markers found - assuming legacy React 17 project"
- **Migration UI Not Showing** (`projectsview.ts`):
- Added listener for `'runtimeDetectionComplete'` event
- Project list now re-renders after async runtime detection completes
- Legacy badges and migrate buttons appear correctly for React 17 projects
@@ -213,12 +431,14 @@ packages/noodl-editor/src/editor/src/views/migration/steps/FailedStep.module.scs
- Webpack cache required clearing after fix
**Technical Notes:**
- safeLog pattern: `try { console.log(...args); } catch (e) { /* ignore EPIPE */ }`
- Runtime detection is async - UI must re-render after detection completes
- Webpack caches SCSS files aggressively - cache clearing may be needed after SCSS fixes
- The `runtimeDetectionComplete` event fires after `detectAllProjectRuntimes()` completes
**Files Modified:**
```
packages/noodl-editor/src/main/src/cloud-function-server.js
packages/noodl-editor/src/editor/src/models/migration/ProjectScanner.ts
@@ -233,13 +453,16 @@ packages/noodl-editor/src/editor/src/views/migration/MigrationWizard.module.scss
#### 2024-12-14
**Added:**
- Extended `DialogLayerModel.tsx` with generic `showDialog()` method:
- Accepts render function `(close: () => void) => JSX.Element`
- Options include `onClose` callback for cleanup
- Enables mounting custom React components (like MigrationWizard) as dialogs
- Type: `ShowDialogOptions` interface added
- Extended `LocalProjectsModel.ts` with runtime detection:
- `RuntimeVersionInfo` import from migration/types
- `detectRuntimeVersion` import from migration/ProjectScanner
- `ProjectItemWithRuntime` interface extending ProjectItem with runtimeInfo
@@ -255,6 +478,7 @@ packages/noodl-editor/src/editor/src/views/migration/MigrationWizard.module.scss
- `clearRuntimeCache(projectPath)` - Clear cache after migration
- Updated `projectsview.html` template with legacy project indicators:
- `data-class="isLegacy:projects-item--legacy"` conditional styling
- Legacy badge with warning SVG icon (positioned top-right)
- Legacy actions overlay with "Migrate Project" and "Open Read-Only" buttons
@@ -262,6 +486,7 @@ packages/noodl-editor/src/editor/src/views/migration/MigrationWizard.module.scss
- Detecting spinner with `data-class="isDetecting:projects-item-detecting"`
- Added CSS styles in `projectsview.css`:
- `.projects-item--legacy` - Orange border for legacy projects
- `.projects-item-legacy-badge` - Top-right warning badge
- `.projects-item-legacy-actions` - Hover overlay with migration buttons
@@ -282,6 +507,7 @@ packages/noodl-editor/src/editor/src/views/migration/MigrationWizard.module.scss
- `onOpenReadOnlyClicked()` - Opens project normally (banner display deferred)
**Technical Notes:**
- DialogLayerModel uses existing Modal wrapper pattern with custom render function
- Runtime detection uses in-memory cache to avoid persistence to localStorage
- Template binding uses jQuery-based View system with `data-*` attributes
@@ -290,6 +516,7 @@ packages/noodl-editor/src/editor/src/views/migration/MigrationWizard.module.scss
- ToastLayer.showSuccess() used for migration completion notification
**Files Modified:**
```
packages/noodl-editor/src/editor/src/models/DialogLayerModel.tsx
packages/noodl-editor/src/editor/src/utils/LocalProjectsModel.ts
@@ -299,6 +526,7 @@ packages/noodl-editor/src/editor/src/views/projectsview.ts
```
**Remaining for Future Sessions:**
- EditorBanner component for legacy read-only mode warning (Post-Migration UX)
- wire open project flow for legacy detection (auto-detect on existing project open)
@@ -309,7 +537,9 @@ packages/noodl-editor/src/editor/src/views/projectsview.ts
#### 2024-12-14
**Added:**
- Created `packages/noodl-editor/src/editor/src/views/migration/` directory with:
- `MigrationWizard.tsx` - Main wizard container component:
- Uses Modal component from @noodl-core-ui
- useReducer for local state management
@@ -350,6 +580,7 @@ packages/noodl-editor/src/editor/src/views/projectsview.ts
- `steps/FailedStep.module.scss`
**Technical Notes:**
- Text component uses `className` not `UNSAFE_className` for styling
- Text component uses `textType` prop (TextType.Secondary, TextType.Shy) not variants
- TextInput onChange expects standard React ChangeEventHandler<HTMLInputElement>
@@ -359,6 +590,7 @@ packages/noodl-editor/src/editor/src/views/projectsview.ts
- SVG icons defined inline in each component for self-containment
**Files Created:**
```
packages/noodl-editor/src/editor/src/views/migration/
├── MigrationWizard.tsx
@@ -380,6 +612,7 @@ packages/noodl-editor/src/editor/src/views/migration/
```
**Remaining for Session 2:**
- DialogLayerModel integration for showing wizard (deferred to Session 3)
---
@@ -389,6 +622,7 @@ packages/noodl-editor/src/editor/src/views/migration/
#### 2024-12-13
**Added:**
- Created CHECKLIST.md for tracking implementation progress
- Created CHANGELOG.md for documenting changes
- Created `packages/noodl-editor/src/editor/src/models/migration/` directory with:
@@ -413,12 +647,14 @@ packages/noodl-editor/src/editor/src/views/migration/
- `index.ts` - Clean module exports
**Technical Notes:**
- IFileSystem interface from `@noodl/platform` uses `readFile(path)` with single argument (no encoding)
- IFileSystem doesn't expose file stat/birthtime - creation date heuristic relies on project.json metadata
- Migration phases: copying → automatic → ai-assisted → finalizing
- Default AI budget: $5 max per session, $1 pause increments
**Files Created:**
```
packages/noodl-editor/src/editor/src/models/migration/
├── index.ts
@@ -434,6 +670,7 @@ packages/noodl-editor/src/editor/src/models/migration/
This changelog tracks the implementation of the React 19 Migration System feature, which allows users to safely upgrade legacy Noodl projects (React 17) to the new OpenNoodl runtime (React 19), with optional AI-assisted code migration.
### Feature Specs
- [00-OVERVIEW.md](./00-OVERVIEW.md) - Feature summary and architecture
- [01-PROJECT-DETECTION.md](./01-PROJECT-DETECTION.md) - Detecting legacy projects
- [02-MIGRATION-WIZARD.md](./02-MIGRATION-WIZARD.md) - Step-by-step wizard UI
@@ -442,6 +679,7 @@ This changelog tracks the implementation of the React 19 Migration System featur
- [05-NEW-PROJECT-NOTICE.md](./05-NEW-PROJECT-NOTICE.md) - New project messaging
### Implementation Sessions
1. **Session 1**: Foundation + Detection (types, scanner, models)
2. **Session 2**: Wizard UI (basic flow without AI)
3. **Session 3**: Projects View Integration (legacy badges, buttons)

View File

@@ -1,6 +1,7 @@
# React 19 Migration System - Implementation Checklist
## Session 1: Foundation + Detection
- [x] Create migration types file (`models/migration/types.ts`)
- [x] Create ProjectScanner.ts (detection logic with 5-tier checks)
- [ ] Update ProjectModel with migration fields (deferred - not needed for initial wizard)
@@ -10,10 +11,11 @@
- [x] Create index.ts module exports
## Session 2: Wizard UI (Basic Flow)
- [x] MigrationWizard.tsx container
- [x] WizardProgress.tsx component
- [x] ConfirmStep.tsx component
- [x] ScanningStep.tsx component
- [x] ScanningStep.tsx component
- [x] ReportStep.tsx component
- [x] CompleteStep.tsx component
- [x] FailedStep.tsx component
@@ -22,6 +24,7 @@
- [x] DialogLayerModel integration for showing wizard (completed in Session 3)
## Session 3: Projects View Integration
- [x] DialogLayerModel.showDialog() generic method
- [x] LocalProjectsModel runtime detection with cache
- [x] Update projectsview.html template with legacy badges
@@ -35,17 +38,22 @@
- [ ] Wire auto-detect on existing project open - deferred to Post-Migration UX
## Session 4: AI Migration + Polish
- [ ] claudeClient.ts (Anthropic API integration)
- [ ] keyStorage.ts (encrypted API key storage)
- [ ] AIConfigPanel.tsx (API key + budget UI)
- [ ] BudgetController.ts (spending limits)
- [ ] BudgetApprovalDialog.tsx
- [ ] Integration into wizard flow
- [ ] MigratingStep.tsx with AI progress
- [x] claudeClient.ts (Anthropic API integration) - Completed Session 9
- [x] keyStorage.ts (encrypted API key storage) - Completed Session 9
- [x] claudePrompts.ts (system prompts and templates) - Completed Session 9
- [x] AIConfigPanel.tsx (API key + budget UI) - Completed Session 9
- [x] BudgetController.ts (spending limits) - Completed Session 9
- [x] BudgetApprovalDialog.tsx - Completed Session 9
- [x] AIMigrationOrchestrator.ts (multi-component coordination) - Completed Session 9
- [x] MigratingStep.tsx with AI progress - Completed Session 10
- [x] ReportStep.tsx AI configuration support - Completed Session 10
- [x] Integration into wizard flow (wire MigrationWizard.tsx) - Completed Session 11
- [ ] Post-migration component status badges
- [ ] MigrationNotesPanel.tsx
## Post-Migration UX
- [ ] Component panel status indicators
- [ ] Migration notes display
- [ ] Dismiss functionality
@@ -53,6 +61,7 @@
- [ ] Component filter by migration status
## Polish Items
- [ ] New project dialog React 19 notice
- [ ] Welcome dialog for version updates
- [ ] Documentation links throughout UI