From 4a1080d5474d2ad5972ac88c2ad53f130ed21103 Mon Sep 17 00:00:00 2001 From: Richard Osborne Date: Wed, 7 Jan 2026 20:28:40 +0100 Subject: [PATCH] Refactored dev-docs folder after multiple additions to organise correctly --- .../README.md | 282 ++ .../PROGRESS.md | 59 + .../QUICK-START.md | 0 .../README.md | 0 .../CHANGELOG.md | 0 .../NOTES.md | 0 .../POTENTIAL-SOLUTIONS.md | 0 .../README.md | 0 .../USAGE-GUIDE.md | 0 .../CHECKLIST.md | 0 .../TASK-009-verification-checklist/README.md | 0 .../EventListenerTest.tsx | 0 .../README.md | 0 .../GOLDEN-PATTERN.md | 0 .../README.md | 0 .../README.md | 0 .../VERIFICATION-GUIDE.md | 0 .../phase-1-dependency-updates/PROGRESS.md | 106 + .../DRAFT-CONCEPT.md | 1178 ++++++ .../PROGRESS.md | 202 ++ .../phase-10-ai-powered-development/README.md | 3159 +++++++++++++++++ .../TASK-10A-DRAFT.md | 1259 +++++++ .../tasks/phase-2-react-migration/PROGRESS.md | 60 + .../phase-3-editor-ux-overhaul/PROGRESS.md | 66 + .../DASH-001B-create-project-modal.md | 415 +++ .../DASH-001B-electron-store-migration.md | 198 ++ .../DASH-001B-remove-list-view.md | 298 ++ .../DASH-001B-service-integration.md | 247 ++ .../TASK-001B-launcher-fixes/README.md | 169 + .../phase-3.5-realtime-agentic-ui/PROGRESS.md | 58 + .../PROGRESS.md | 180 + .../PROGRESS.md | 111 + dev-docs/tasks/phase-6-uba-system/PROGRESS.md | 57 + dev-docs/tasks/phase-6-uba-system/README.md | 96 + .../phase-6-uba-system/UBA-001-FOUNDATION.md | 1798 ++++++++++ .../phase-6-uba-system/UBA-002-FIELD-TYPES.md | 1792 ++++++++++ .../UBA-003-DEBUG-SYSTEM.md | 1701 +++++++++ .../phase-6-uba-system/UBA-004-POLISH.md | 871 +++++ .../UBA-005-REFERENCE-BACKEND.md | 1910 ++++++++++ .../phase-6-uba-system/UBA-006-COMMUNITY.md | 1016 ++++++ .../CODE-001-nodegx-core-library.md | 0 .../CODE-002-visual-node-generator.md | 0 .../CODE-003-state-store-generator.md | 0 .../CODE-004-logic-node-generator.md | 0 .../CODE-005-event-system-generator.md | 0 .../CODE-006-project-scaffolding.md | 0 .../CODE-007-cli-integration.md | 228 ++ .../CODE-008-node-comments-export.md | 0 .../CODE-EXPORT-overview.md | 0 .../CODE-REFERENCE-noodl-nodes.md | 0 .../tasks/phase-7-code-export/PROGRESS.md | 70 + .../tasks/phase-8-distribution/PROGRESS.md | 153 + .../README.md} | 4 +- .../TASK-7.1-rebrand-nodegex.md | 0 .../TASK-7.2-macos-signing.md | 0 .../TASK-7.3-auto-update-config.md | 0 .../TASK-7.4-linux-distribution.md | 0 .../TASK-7.5-github-actions.md | 0 .../CLEANUP-SUBTASKS}/COLORS-RED-MINIMAL.md | 0 .../DESIGN-SYSTEM-MODERNISATION.md | 0 .../CLEANUP-SUBTASKS}/INDEX.md | 0 .../CHANGELOG.md | 0 .../TASK-000A-token-consolidation/OVERVIEW.md | 0 .../CHANGELOG.md | 0 .../OVERVIEW.md | 0 .../CHANGELOG.md | 0 .../OVERVIEW.md | 0 .../CHANGELOG.md | 0 .../OVERVIEW.md | 0 .../TASK-000E-typography-spacing/CHANGELOG.md | 0 .../TASK-000E-typography-spacing/OVERVIEW.md | 0 .../CHANGELOG.md | 0 .../OVERVIEW.md | 0 .../CHANGELOG.md | 0 .../OVERVIEW.md | 0 .../OVERVIEW.md | 0 .../CHANGELOG.md | 0 .../CHECKLIST.md | 0 .../NOTES.md | 0 .../README.md | 0 .../TASK-000I-A-visual-polish.md | 0 .../TASK-000I-B-node-comments.md | 0 .../TASK-000I-C-port-organization.md | 0 .../CHANGELOG.md | 0 .../CHECKLIST.md | 0 .../NOTES.md | 0 .../README.md | 0 .../SUBTASK-001-smart-frames.md | 0 .../SUBTASK-002-canvas-navigation.md | 0 .../SUBTASK-003-vertical-snap-push.md | 0 .../SUBTASK-004-connection-labels.md | 0 .../tasks/phase-9-styles-overhaul/PROGRESS.md | 116 + .../QUICK-REFERENCE.md | 0 .../README.md} | 6 +- .../README.md | 0 .../STYLE-002-element-configs/README.md | 0 .../STYLE-003-presets/README.md | 0 .../STYLE-004-property-panel/README.md | 0 .../STYLE-005-suggestions/README.md | 0 .../WIZARD-001-project-creation/README.md | 0 .../WIZARD-001.md} | 0 package.json | 2 +- .../preview/launcher/Launcher/Launcher.tsx | 27 +- .../launcher/Launcher/LauncherContext.tsx | 9 +- .../CreateProjectModal.module.scss | 74 + .../CreateProjectModal/CreateProjectModal.tsx | 117 + .../components/CreateProjectModal/index.ts | 2 + .../ProjectList/ProjectList.module.scss | 29 - .../ProjectList/ProjectList.stories.tsx | 129 - .../components/ProjectList/ProjectList.tsx | 66 - .../ProjectList/ProjectListHeader.module.scss | 32 - .../ProjectList/ProjectListHeader.tsx | 74 - .../ProjectList/ProjectListRow.module.scss | 29 - .../components/ProjectList/ProjectListRow.tsx | 177 - .../Launcher/components/ProjectList/index.ts | 8 - .../ViewModeToggle/ViewModeToggle.module.scss | 7 - .../ViewModeToggle/ViewModeToggle.tsx | 55 - .../components/ViewModeToggle/index.ts | 2 - .../launcher/Launcher/hooks/useProjectList.ts | 135 - .../Launcher/hooks/useProjectOrganization.ts | 27 +- .../launcher/Launcher/views/Projects.tsx | 154 +- .../src/pages/ProjectsPage/ProjectsPage.tsx | 112 +- .../services/ProjectOrganizationService.ts | 37 +- .../editor/src/utils/LocalProjectsModel.ts | 55 +- scripts/clean-electron.js | 189 + 125 files changed, 18456 insertions(+), 957 deletions(-) create mode 100644 dev-docs/tasks/TASK-REORG-documentation-cleanup/README.md create mode 100644 dev-docs/tasks/phase-0-foundation-stabilisation/PROGRESS.md rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/QUICK-START.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/README.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-008-eventdispatcher-react-investigation/CHANGELOG.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-008-eventdispatcher-react-investigation/NOTES.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-008-eventdispatcher-react-investigation/POTENTIAL-SOLUTIONS.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-008-eventdispatcher-react-investigation/README.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-008-eventdispatcher-react-investigation/USAGE-GUIDE.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-009-verification-checklist/CHECKLIST.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-009-verification-checklist/README.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-010-eventlistener-verification/EventListenerTest.tsx (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-010-eventlistener-verification/README.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-011-react-event-pattern-guide/GOLDEN-PATTERN.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-011-react-event-pattern-guide/README.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/TASK-012-foundation-health-check/README.md (100%) rename dev-docs/tasks/{phase-0-foundation-stabalisation => phase-0-foundation-stabilisation}/VERIFICATION-GUIDE.md (100%) create mode 100644 dev-docs/tasks/phase-1-dependency-updates/PROGRESS.md create mode 100644 dev-docs/tasks/phase-10-ai-powered-development/DRAFT-CONCEPT.md create mode 100644 dev-docs/tasks/phase-10-ai-powered-development/PROGRESS.md create mode 100644 dev-docs/tasks/phase-10-ai-powered-development/README.md create mode 100644 dev-docs/tasks/phase-10-ai-powered-development/TASK-10A-DRAFT.md create mode 100644 dev-docs/tasks/phase-2-react-migration/PROGRESS.md create mode 100644 dev-docs/tasks/phase-3-editor-ux-overhaul/PROGRESS.md create mode 100644 dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-001B-launcher-fixes/DASH-001B-create-project-modal.md create mode 100644 dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-001B-launcher-fixes/DASH-001B-electron-store-migration.md create mode 100644 dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-001B-launcher-fixes/DASH-001B-remove-list-view.md create mode 100644 dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-001B-launcher-fixes/DASH-001B-service-integration.md create mode 100644 dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-001B-launcher-fixes/README.md create mode 100644 dev-docs/tasks/phase-3.5-realtime-agentic-ui/PROGRESS.md create mode 100644 dev-docs/tasks/phase-4-canvas-visualisation-views/PROGRESS.md create mode 100644 dev-docs/tasks/phase-5-multi-target-deployment/PROGRESS.md create mode 100644 dev-docs/tasks/phase-6-uba-system/PROGRESS.md create mode 100644 dev-docs/tasks/phase-6-uba-system/README.md create mode 100644 dev-docs/tasks/phase-6-uba-system/UBA-001-FOUNDATION.md create mode 100644 dev-docs/tasks/phase-6-uba-system/UBA-002-FIELD-TYPES.md create mode 100644 dev-docs/tasks/phase-6-uba-system/UBA-003-DEBUG-SYSTEM.md create mode 100644 dev-docs/tasks/phase-6-uba-system/UBA-004-POLISH.md create mode 100644 dev-docs/tasks/phase-6-uba-system/UBA-005-REFERENCE-BACKEND.md create mode 100644 dev-docs/tasks/phase-6-uba-system/UBA-006-COMMUNITY.md rename dev-docs/tasks/{phase-6-code-export => phase-7-code-export}/CODE-001-nodegx-core-library.md (100%) rename dev-docs/tasks/{phase-6-code-export => phase-7-code-export}/CODE-002-visual-node-generator.md (100%) rename dev-docs/tasks/{phase-6-code-export => phase-7-code-export}/CODE-003-state-store-generator.md (100%) rename dev-docs/tasks/{phase-6-code-export => phase-7-code-export}/CODE-004-logic-node-generator.md (100%) rename dev-docs/tasks/{phase-6-code-export => phase-7-code-export}/CODE-005-event-system-generator.md (100%) rename dev-docs/tasks/{phase-6-code-export => phase-7-code-export}/CODE-006-project-scaffolding.md (100%) create mode 100644 dev-docs/tasks/phase-7-code-export/CODE-007-cli-integration.md rename dev-docs/tasks/{phase-6-code-export => phase-7-code-export}/CODE-008-node-comments-export.md (100%) rename dev-docs/tasks/{phase-6-code-export => phase-7-code-export}/CODE-EXPORT-overview.md (100%) rename dev-docs/tasks/{phase-6-code-export => phase-7-code-export}/CODE-REFERENCE-noodl-nodes.md (100%) create mode 100644 dev-docs/tasks/phase-7-code-export/PROGRESS.md create mode 100644 dev-docs/tasks/phase-8-distribution/PROGRESS.md rename dev-docs/tasks/{phase-7-auto-update-and-distribution/PHASE-7-OVERVIEW.md => phase-8-distribution/README.md} (98%) rename dev-docs/tasks/{phase-7-auto-update-and-distribution => phase-8-distribution}/TASK-7.1-rebrand-nodegex.md (100%) rename dev-docs/tasks/{phase-7-auto-update-and-distribution => phase-8-distribution}/TASK-7.2-macos-signing.md (100%) rename dev-docs/tasks/{phase-7-auto-update-and-distribution => phase-8-distribution}/TASK-7.3-auto-update-config.md (100%) rename dev-docs/tasks/{phase-7-auto-update-and-distribution => phase-8-distribution}/TASK-7.4-linux-distribution.md (100%) rename dev-docs/tasks/{phase-7-auto-update-and-distribution => phase-8-distribution}/TASK-7.5-github-actions.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/COLORS-RED-MINIMAL.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/DESIGN-SYSTEM-MODERNISATION.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/INDEX.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000A-token-consolidation/CHANGELOG.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000A-token-consolidation/OVERVIEW.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000B-hardcoded-colors-legacy/CHANGELOG.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000B-hardcoded-colors-legacy/OVERVIEW.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000C-hardcoded-colors-nodegraph/CHANGELOG.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000C-hardcoded-colors-nodegraph/OVERVIEW.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000D-hardcoded-colors-coreui/CHANGELOG.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000D-hardcoded-colors-coreui/OVERVIEW.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000E-typography-spacing/CHANGELOG.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000E-typography-spacing/OVERVIEW.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000F-component-buttons-inputs/CHANGELOG.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000F-component-buttons-inputs/OVERVIEW.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000G-component-dialogs-panels/CHANGELOG.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000G-component-dialogs-panels/OVERVIEW.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000H-migration-wizard-polish/OVERVIEW.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000I-node-graph-visual-improvements/CHANGELOG.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000I-node-graph-visual-improvements/CHECKLIST.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000I-node-graph-visual-improvements/NOTES.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000I-node-graph-visual-improvements/README.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000I-node-graph-visual-improvements/TASK-000I-A-visual-polish.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000I-node-graph-visual-improvements/TASK-000I-B-node-comments.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000I-node-graph-visual-improvements/TASK-000I-C-port-organization.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000J-canvas-organisation-system/CHANGELOG.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000J-canvas-organisation-system/CHECKLIST.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000J-canvas-organisation-system/NOTES.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000J-canvas-organisation-system/README.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000J-canvas-organisation-system/SUBTASK-001-smart-frames.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000J-canvas-organisation-system/SUBTASK-002-canvas-navigation.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000J-canvas-organisation-system/SUBTASK-003-vertical-snap-push.md (100%) rename dev-docs/tasks/{phase-3-editor-ux-overhaul/TASK-000-styles-overhaul => phase-9-styles-overhaul/CLEANUP-SUBTASKS}/TASK-000J-canvas-organisation-system/SUBTASK-004-connection-labels.md (100%) create mode 100644 dev-docs/tasks/phase-9-styles-overhaul/PROGRESS.md rename dev-docs/tasks/{phase-8-styles-overhaul => phase-9-styles-overhaul}/QUICK-REFERENCE.md (100%) rename dev-docs/tasks/{phase-8-styles-overhaul/PHASE-8-OVERVIEW.md => phase-9-styles-overhaul/README.md} (98%) rename dev-docs/tasks/{phase-8-styles-overhaul => phase-9-styles-overhaul}/STYLE-001-token-system-enhancement/README.md (100%) rename dev-docs/tasks/{phase-8-styles-overhaul => phase-9-styles-overhaul}/STYLE-002-element-configs/README.md (100%) rename dev-docs/tasks/{phase-8-styles-overhaul => phase-9-styles-overhaul}/STYLE-003-presets/README.md (100%) rename dev-docs/tasks/{phase-8-styles-overhaul => phase-9-styles-overhaul}/STYLE-004-property-panel/README.md (100%) rename dev-docs/tasks/{phase-8-styles-overhaul => phase-9-styles-overhaul}/STYLE-005-suggestions/README.md (100%) rename dev-docs/tasks/{phase-8-styles-overhaul => phase-9-styles-overhaul}/WIZARD-001-project-creation/README.md (100%) rename dev-docs/tasks/{phase-8-styles-overhaul/README.md => phase-9-styles-overhaul/WIZARD-001.md} (100%) create mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/CreateProjectModal/CreateProjectModal.module.scss create mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/CreateProjectModal/CreateProjectModal.tsx create mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/CreateProjectModal/index.ts delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectList.module.scss delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectList.stories.tsx delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectList.tsx delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectListHeader.module.scss delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectListHeader.tsx delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectListRow.module.scss delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/ProjectListRow.tsx delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/ProjectList/index.ts delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/ViewModeToggle/ViewModeToggle.module.scss delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/ViewModeToggle/ViewModeToggle.tsx delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/components/ViewModeToggle/index.ts delete mode 100644 packages/noodl-core-ui/src/preview/launcher/Launcher/hooks/useProjectList.ts create mode 100644 scripts/clean-electron.js diff --git a/dev-docs/tasks/TASK-REORG-documentation-cleanup/README.md b/dev-docs/tasks/TASK-REORG-documentation-cleanup/README.md new file mode 100644 index 0000000..95ef504 --- /dev/null +++ b/dev-docs/tasks/TASK-REORG-documentation-cleanup/README.md @@ -0,0 +1,282 @@ +# TASK-REORG: Documentation Structure Cleanup + +**Task ID:** TASK-REORG +**Created:** 2026-01-07 +**Status:** 🟑 In Progress +**Priority:** HIGH +**Effort:** 2-4 hours + +--- + +## Problem Statement + +The task documentation has become disorganized over time with: + +1. **Misplaced Content** - Phase 3 TASK-008 "granular-deployment" contains UBA (Universal Backend Adapter) content, not project file structure +2. **Wrong Numbering** - UBA files named "PHASE-6A-6F" but located in Phase 3, while actual Phase 6 is Code Export +3. **Duplicate Topics** - Styles work in both Phase 3 TASK-000 AND Phase 8 +4. **Broken References** - Phase 9 references "Phase 6 UBA" which doesn't exist as a separate phase +5. **Typo in Folder Name** - "stabalisation" instead of "stabilisation" +6. **Missing Progress Tracking** - No easy way to see completion status of each phase +7. **Incorrect README** - Phase 8 README contains WIZARD-001 content, not phase overview + +--- + +## Current vs Target Structure + +### Phase Mapping + +| New # | Current Location | New Location | Change Type | +| ------- | --------------------------------------------- | ---------------------------------- | ------------------------ | +| **0** | phase-0-foundation-stabalisation | phase-0-foundation-stabilisation | RENAME (fix typo) | +| **1** | phase-1-dependency-updates | phase-1-dependency-updates | KEEP | +| **2** | phase-2-react-migration | phase-2-react-migration | KEEP | +| **3** | phase-3-editor-ux-overhaul | phase-3-editor-ux-overhaul | MODIFY (remove TASK-008) | +| **3.5** | phase-3.5-realtime-agentic-ui | phase-3.5-realtime-agentic-ui | KEEP | +| **4** | phase-4-canvas-visualisation-views | phase-4-canvas-visualisation-views | KEEP | +| **5** | phase-5-multi-target-deployment | phase-5-multi-target-deployment | KEEP | +| **6** | phase-3.../TASK-008-granular-deployment | phase-6-uba-system | NEW (move UBA here) | +| **7** | phase-6-code-export | phase-7-code-export | RENUMBER | +| **8** | phase-7-auto-update-and-distribution | phase-8-distribution | RENUMBER | +| **9** | phase-3.../TASK-000 + phase-8-styles-overhaul | phase-9-styles-overhaul | MERGE | +| **10** | phase-9-ai-powered-development | phase-10-ai-powered-development | RENUMBER | + +--- + +## Execution Checklist + +### Phase 1: Create New Phase 6 (UBA System) + +- [ ] Create folder `dev-docs/tasks/phase-6-uba-system/` +- [ ] Create `phase-6-uba-system/README.md` (UBA overview) +- [ ] Move `phase-3.../TASK-008-granular-deployment/PHASE-6A-FOUNDATION.md` β†’ `phase-6-uba-system/UBA-001-FOUNDATION.md` +- [ ] Move `phase-3.../TASK-008-granular-deployment/PHASE-6B-FIELD-TYPES.md` β†’ `phase-6-uba-system/UBA-002-FIELD-TYPES.md` +- [ ] Move `phase-3.../TASK-008-granular-deployment/PHASE-6C-DEBUG-SYSTEM.md` β†’ `phase-6-uba-system/UBA-003-DEBUG-SYSTEM.md` +- [ ] Move `phase-3.../TASK-008-granular-deployment/PHASE-6D-POLISH.md` β†’ `phase-6-uba-system/UBA-004-POLISH.md` +- [ ] Move `phase-3.../TASK-008-granular-deployment/PHASE-6E-REFERENCE-BACKEND.md` β†’ `phase-6-uba-system/UBA-005-REFERENCE-BACKEND.md` +- [ ] Move `phase-3.../TASK-008-granular-deployment/PHASE-6F-COMMUNITY.md` β†’ `phase-6-uba-system/UBA-006-COMMUNITY.md` +- [ ] Delete empty `phase-3-editor-ux-overhaul/TASK-008-granular-deployment/` folder +- [ ] Create `phase-6-uba-system/PROGRESS.md` + +### Phase 2: Renumber Existing Phases + +- [ ] Rename `phase-6-code-export/` β†’ `phase-7-code-export/` +- [ ] Update any internal references in Phase 7 files +- [ ] Rename `phase-7-auto-update-and-distribution/` β†’ `phase-8-distribution/` +- [ ] Update any internal references in Phase 8 files + +### Phase 3: Merge Styles Content + +- [ ] Create `phase-9-styles-overhaul/` (new merged folder) +- [ ] Move `phase-8-styles-overhaul/PHASE-8-OVERVIEW.md` β†’ `phase-9-styles-overhaul/README.md` +- [ ] Move `phase-8-styles-overhaul/QUICK-REFERENCE.md` β†’ `phase-9-styles-overhaul/QUICK-REFERENCE.md` +- [ ] Move `phase-8-styles-overhaul/STYLE-001-*` through `STYLE-005-*` folders β†’ `phase-9-styles-overhaul/` +- [ ] Move `phase-8-styles-overhaul/WIZARD-001-*` β†’ `phase-9-styles-overhaul/` (keep together with styles) +- [ ] Move `phase-3-editor-ux-overhaul/TASK-000-styles-overhaul/` β†’ `phase-9-styles-overhaul/CLEANUP-SUBTASKS/` (legacy cleanup tasks) +- [ ] Delete old `phase-8-styles-overhaul/` folder +- [ ] Create `phase-9-styles-overhaul/PROGRESS.md` + +### Phase 4: Renumber AI Phase + +- [ ] Rename `phase-9-ai-powered-development/` β†’ `phase-10-ai-powered-development/` +- [ ] Update references to "Phase 9" β†’ "Phase 10" within files +- [ ] Update Phase 6 UBA references (now correct!) +- [ ] Create `phase-10-ai-powered-development/PROGRESS.md` + +### Phase 5: Fix Phase 0 Typo + +- [ ] Rename `phase-0-foundation-stabalisation/` β†’ `phase-0-foundation-stabilisation/` +- [ ] Update any references to the old folder name + +### Phase 6: Create PROGRESS.md Files + +Create `PROGRESS.md` in each phase root: + +- [ ] `phase-0-foundation-stabilisation/PROGRESS.md` +- [ ] `phase-1-dependency-updates/PROGRESS.md` +- [ ] `phase-2-react-migration/PROGRESS.md` +- [ ] `phase-3-editor-ux-overhaul/PROGRESS.md` +- [ ] `phase-3.5-realtime-agentic-ui/PROGRESS.md` +- [ ] `phase-4-canvas-visualisation-views/PROGRESS.md` +- [ ] `phase-5-multi-target-deployment/PROGRESS.md` +- [ ] `phase-6-uba-system/PROGRESS.md` (created in Phase 1) +- [ ] `phase-7-code-export/PROGRESS.md` +- [ ] `phase-8-distribution/PROGRESS.md` +- [ ] `phase-9-styles-overhaul/PROGRESS.md` (created in Phase 3) +- [ ] `phase-10-ai-powered-development/PROGRESS.md` (created in Phase 4) + +### Phase 7: Update Cross-References + +- [ ] Search all `.md` files for "phase-6" and update to "phase-7" (code export) +- [ ] Search all `.md` files for "phase-7" and update to "phase-8" (distribution) +- [ ] Search all `.md` files for "phase-8" and update to "phase-9" (styles) +- [ ] Search all `.md` files for "phase-9" and update to "phase-10" (AI) +- [ ] Search for "Phase 6 UBA" or "Phase 6 (UBA)" and verify points to new phase-6 +- [ ] Search for "stabalisation" and fix typo +- [ ] Update `.clinerules` if it references specific phase numbers + +### Phase 8: Verification + +- [ ] All folders exist with correct names +- [ ] All PROGRESS.md files created +- [ ] No orphaned files or broken links +- [ ] README in each phase root is correct content +- [ ] Git commit with descriptive message + +--- + +## PROGRESS.md Template + +Use this template for all `PROGRESS.md` files: + +```markdown +# Phase X: [Phase Name] - Progress Tracker + +**Last Updated:** YYYY-MM-DD +**Overall Status:** πŸ”΄ Not Started | 🟑 In Progress | 🟒 Complete + +--- + +## Quick Summary + +| Metric | Value | +| ------------ | ------ | +| Total Tasks | X | +| Completed | X | +| In Progress | X | +| Not Started | X | +| **Progress** | **X%** | + +--- + +## Task Status + +| Task | Name | Status | Notes | +| -------- | ------ | -------------- | --------------- | +| TASK-001 | [Name] | πŸ”΄ Not Started | | +| TASK-002 | [Name] | 🟑 In Progress | 50% complete | +| TASK-003 | [Name] | 🟒 Complete | Done 2026-01-05 | + +--- + +## Status Legend + +- πŸ”΄ **Not Started** - Work has not begun +- 🟑 **In Progress** - Actively being worked on +- 🟒 **Complete** - Finished and verified +- ⏸️ **Blocked** - Waiting on dependency +- πŸ”΅ **Planned** - Scheduled but not started + +--- + +## Recent Updates + +| Date | Update | +| ---------- | ----------------------- | +| YYYY-MM-DD | [Description of change] | + +--- + +## Dependencies + +List any external dependencies or blocking items here. + +--- + +## Notes + +Additional context or important information about this phase. +``` + +--- + +## Final Phase Structure + +After reorganization: + +``` +dev-docs/tasks/ +β”œβ”€β”€ TASK-REORG-documentation-cleanup/ # This task (can be archived after) +β”œβ”€β”€ phase-0-foundation-stabilisation/ # Fixed typo +β”‚ └── PROGRESS.md +β”œβ”€β”€ phase-1-dependency-updates/ +β”‚ └── PROGRESS.md +β”œβ”€β”€ phase-2-react-migration/ +β”‚ └── PROGRESS.md +β”œβ”€β”€ phase-3-editor-ux-overhaul/ # TASK-008 removed (moved to Phase 6) +β”‚ └── PROGRESS.md +β”œβ”€β”€ phase-3.5-realtime-agentic-ui/ +β”‚ └── PROGRESS.md +β”œβ”€β”€ phase-4-canvas-visualisation-views/ +β”‚ └── PROGRESS.md +β”œβ”€β”€ phase-5-multi-target-deployment/ +β”‚ └── PROGRESS.md +β”œβ”€β”€ phase-6-uba-system/ # NEW - UBA content from old TASK-008 +β”‚ β”œβ”€β”€ README.md +β”‚ β”œβ”€β”€ PROGRESS.md +β”‚ β”œβ”€β”€ UBA-001-FOUNDATION.md +β”‚ β”œβ”€β”€ UBA-002-FIELD-TYPES.md +β”‚ β”œβ”€β”€ UBA-003-DEBUG-SYSTEM.md +β”‚ β”œβ”€β”€ UBA-004-POLISH.md +β”‚ β”œβ”€β”€ UBA-005-REFERENCE-BACKEND.md +β”‚ └── UBA-006-COMMUNITY.md +β”œβ”€β”€ phase-7-code-export/ # Renumbered from old Phase 6 +β”‚ └── PROGRESS.md +β”œβ”€β”€ phase-8-distribution/ # Renumbered from old Phase 7 +β”‚ └── PROGRESS.md +β”œβ”€β”€ phase-9-styles-overhaul/ # Merged Phase 3 TASK-000 + old Phase 8 +β”‚ β”œβ”€β”€ README.md +β”‚ β”œβ”€β”€ PROGRESS.md +β”‚ β”œβ”€β”€ QUICK-REFERENCE.md +β”‚ β”œβ”€β”€ STYLE-001-*/ +β”‚ β”œβ”€β”€ STYLE-002-*/ +β”‚ β”œβ”€β”€ STYLE-003-*/ +β”‚ β”œβ”€β”€ STYLE-004-*/ +β”‚ β”œβ”€β”€ STYLE-005-*/ +β”‚ β”œβ”€β”€ WIZARD-001-*/ +β”‚ └── CLEANUP-SUBTASKS/ # From old Phase 3 TASK-000 +└── phase-10-ai-powered-development/ # Renumbered from old Phase 9 + β”œβ”€β”€ README.md + β”œβ”€β”€ PROGRESS.md + β”œβ”€β”€ DRAFT-CONCEPT.md + └── TASK-9A-DRAFT.md # Will need internal renumber to TASK-10A +``` + +--- + +## Success Criteria + +- [ ] All 12 phase folders have correct names +- [ ] All 12 phase folders have PROGRESS.md +- [ ] No orphaned content (nothing lost in moves) +- [ ] All cross-references updated +- [ ] No typos in folder names +- [ ] UBA content cleanly separated into Phase 6 +- [ ] Styles content merged into Phase 9 +- [ ] Phase 10 (AI) references correct Phase 6 (UBA) for dependencies + +--- + +## Notes + +- This reorganization is a **documentation-only** change - no code is modified +- Git history will show moves as delete+create, which is fine +- Consider a single commit with clear message: "docs: reorganize phase structure" +- After completion, update `.clinerules` if needed +- Archive this TASK-REORG folder or move to `completed/` subfolder + +--- + +## Estimated Time + +| Section | Estimate | +| ------------------------ | ------------ | +| Create Phase 6 (UBA) | 30 min | +| Renumber Phases 7-8 | 15 min | +| Merge Styles | 30 min | +| Renumber AI Phase | 15 min | +| Fix Phase 0 typo | 5 min | +| Create PROGRESS.md files | 45 min | +| Update cross-references | 30 min | +| Verification | 15 min | +| **Total** | **~3 hours** | diff --git a/dev-docs/tasks/phase-0-foundation-stabilisation/PROGRESS.md b/dev-docs/tasks/phase-0-foundation-stabilisation/PROGRESS.md new file mode 100644 index 0000000..701c111 --- /dev/null +++ b/dev-docs/tasks/phase-0-foundation-stabilisation/PROGRESS.md @@ -0,0 +1,59 @@ +# Phase 0: Foundation Stabilisation - Progress Tracker + +**Last Updated:** 2026-01-07 +**Overall Status:** 🟑 In Progress + +--- + +## Quick Summary + +| Metric | Value | +| ------------ | ------- | +| Total Tasks | 5 | +| Completed | 2 | +| In Progress | 2 | +| Not Started | 1 | +| **Progress** | **40%** | + +--- + +## Task Status + +| Task | Name | Status | Notes | +| -------- | ----------------------------------- | -------------- | ------------------------------------------ | +| TASK-008 | EventDispatcher React Investigation | πŸ”΄ Not Started | Investigation needed but never started | +| TASK-009 | Webpack Cache Elimination | 🟑 In Progress | Awaiting user verification (3x test) | +| TASK-010 | EventListener Verification | 🟑 In Progress | Ready for user testing (6/9 items pending) | +| TASK-011 | React Event Pattern Guide | 🟒 Complete | Guide written | +| TASK-012 | Foundation Health Check | 🟒 Complete | Health check script created | + +--- + +## Status Legend + +- πŸ”΄ **Not Started** - Work has not begun +- 🟑 **In Progress** - Actively being worked on +- 🟒 **Complete** - Finished and verified +- ⏸️ **Blocked** - Waiting on dependency +- πŸ”΅ **Planned** - Scheduled but not started + +--- + +## Recent Updates + +| Date | Update | +| ---------- | ---------------------------------------------------- | +| 2026-01-07 | Audit corrected task statuses (was incorrectly 100%) | +| 2026-01-07 | Phase marked complete, docs reorganized (incorrect) | + +--- + +## Dependencies + +None - this is the foundation phase. + +--- + +## Notes + +This phase established critical patterns for React/EventDispatcher integration that all subsequent phases must follow. diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/QUICK-START.md b/dev-docs/tasks/phase-0-foundation-stabilisation/QUICK-START.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/QUICK-START.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/QUICK-START.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/README.md b/dev-docs/tasks/phase-0-foundation-stabilisation/README.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/README.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/README.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-008-eventdispatcher-react-investigation/CHANGELOG.md b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-008-eventdispatcher-react-investigation/CHANGELOG.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-008-eventdispatcher-react-investigation/CHANGELOG.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-008-eventdispatcher-react-investigation/CHANGELOG.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-008-eventdispatcher-react-investigation/NOTES.md b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-008-eventdispatcher-react-investigation/NOTES.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-008-eventdispatcher-react-investigation/NOTES.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-008-eventdispatcher-react-investigation/NOTES.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-008-eventdispatcher-react-investigation/POTENTIAL-SOLUTIONS.md b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-008-eventdispatcher-react-investigation/POTENTIAL-SOLUTIONS.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-008-eventdispatcher-react-investigation/POTENTIAL-SOLUTIONS.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-008-eventdispatcher-react-investigation/POTENTIAL-SOLUTIONS.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-008-eventdispatcher-react-investigation/README.md b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-008-eventdispatcher-react-investigation/README.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-008-eventdispatcher-react-investigation/README.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-008-eventdispatcher-react-investigation/README.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-008-eventdispatcher-react-investigation/USAGE-GUIDE.md b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-008-eventdispatcher-react-investigation/USAGE-GUIDE.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-008-eventdispatcher-react-investigation/USAGE-GUIDE.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-008-eventdispatcher-react-investigation/USAGE-GUIDE.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-009-verification-checklist/CHECKLIST.md b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-009-verification-checklist/CHECKLIST.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-009-verification-checklist/CHECKLIST.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-009-verification-checklist/CHECKLIST.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-009-verification-checklist/README.md b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-009-verification-checklist/README.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-009-verification-checklist/README.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-009-verification-checklist/README.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-010-eventlistener-verification/EventListenerTest.tsx b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-010-eventlistener-verification/EventListenerTest.tsx similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-010-eventlistener-verification/EventListenerTest.tsx rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-010-eventlistener-verification/EventListenerTest.tsx diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-010-eventlistener-verification/README.md b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-010-eventlistener-verification/README.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-010-eventlistener-verification/README.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-010-eventlistener-verification/README.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-011-react-event-pattern-guide/GOLDEN-PATTERN.md b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-011-react-event-pattern-guide/GOLDEN-PATTERN.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-011-react-event-pattern-guide/GOLDEN-PATTERN.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-011-react-event-pattern-guide/GOLDEN-PATTERN.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-011-react-event-pattern-guide/README.md b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-011-react-event-pattern-guide/README.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-011-react-event-pattern-guide/README.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-011-react-event-pattern-guide/README.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/TASK-012-foundation-health-check/README.md b/dev-docs/tasks/phase-0-foundation-stabilisation/TASK-012-foundation-health-check/README.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/TASK-012-foundation-health-check/README.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/TASK-012-foundation-health-check/README.md diff --git a/dev-docs/tasks/phase-0-foundation-stabalisation/VERIFICATION-GUIDE.md b/dev-docs/tasks/phase-0-foundation-stabilisation/VERIFICATION-GUIDE.md similarity index 100% rename from dev-docs/tasks/phase-0-foundation-stabalisation/VERIFICATION-GUIDE.md rename to dev-docs/tasks/phase-0-foundation-stabilisation/VERIFICATION-GUIDE.md diff --git a/dev-docs/tasks/phase-1-dependency-updates/PROGRESS.md b/dev-docs/tasks/phase-1-dependency-updates/PROGRESS.md new file mode 100644 index 0000000..bc3b251 --- /dev/null +++ b/dev-docs/tasks/phase-1-dependency-updates/PROGRESS.md @@ -0,0 +1,106 @@ +# Phase 1: Dependency Updates - Progress Tracker + +**Last Updated:** 2026-01-07 +**Overall Status:** 🟑 Mostly Complete (Core work done, one task planned only) + +--- + +## Quick Summary + +| Metric | Value | +| ------------ | ------- | +| Total Tasks | 7 | +| Completed | 5 | +| In Progress | 0 | +| Not Started | 2 | +| **Progress** | **71%** | + +--- + +## Task Status + +| Task | Name | Status | Notes | +| --------- | ------------------------- | -------------- | --------------------------------------------- | +| TASK-000 | Dependency Analysis | 🟒 Complete | Analysis done | +| TASK-001 | Dependency Updates | 🟒 Complete | Core deps updated | +| TASK-001B | React 19 Migration | 🟒 Complete | Migrated to React 19 (48 createRoot usages) | +| TASK-002 | Legacy Project Migration | πŸ”΄ Not Started | **Planning only** - noodl-cli not implemented | +| TASK-003 | TypeScript Config Cleanup | 🟒 Complete | Option B implemented (global path aliases) | +| TASK-004 | Storybook 8 Migration | 🟒 Complete | 92 stories migrated to CSF3 | +| TASK-006 | TypeScript 5 Upgrade | πŸ”΄ Not Started | Required for Zod v4 compatibility | + +--- + +## Status Legend + +- πŸ”΄ **Not Started** - Work has not begun +- 🟑 **In Progress** - Actively being worked on +- 🟒 **Complete** - Finished and verified +- ⏸️ **Blocked** - Waiting on dependency +- πŸ”΅ **Planned** - Scheduled but not started + +--- + +## Code Verification Notes + +### Verified 2026-01-07 + +**TASK-001B (React 19 Migration)**: + +- βœ… 48 files using `createRoot` from react-dom/client +- βœ… No legacy `ReactDOM.render` calls in production code (only in migration tool for detection) + +**TASK-003 (TypeScript Config Cleanup)**: + +- βœ… Root tsconfig.json has global path aliases (Option B implemented) +- βœ… Includes: @noodl-core-ui/_, @noodl-hooks/_, @noodl-utils/_, @noodl-models/_, etc. + +**TASK-004 (Storybook 8 Migration)**: + +- βœ… 92 story files using CSF3 format (Meta, StoryObj) +- βœ… 0 files using old CSF2 format (ComponentStory, ComponentMeta) + +**TASK-002 (Legacy Project Migration)**: + +- ❌ `packages/noodl-cli/` does not exist +- ❌ No MigrationDialog component created +- ⚠️ Previous status was incorrect - this task has comprehensive planning docs but no implementation + +**TASK-006 (TypeScript 5 Upgrade)**: + +- ❌ Not previously tracked in PROGRESS.md +- Required for Zod v4 and modern @ai-sdk/\* packages + +--- + +## Recent Updates + +| Date | Update | +| ---------- | ----------------------------------------------------------------- | +| 2026-01-07 | Corrected TASK-002 status (was incorrectly marked complete) | +| 2026-01-07 | Added TASK-006 (TypeScript 5 Upgrade) - was missing from tracking | +| 2026-01-07 | Verified actual code state for TASK-001B, TASK-003, TASK-004 | + +--- + +## Dependencies + +Depends on: Phase 0 (Foundation) + +--- + +## Notes + +### Completed Work + +React 19 migration, Storybook 8 CSF3 migration, and TypeScript config cleanup are all verified complete in the codebase. + +### Outstanding Items + +1. **TASK-002 (Legacy Project Migration)**: Has detailed planning documentation but no implementation. The `noodl-cli` package and migration tooling were never created. + +2. **TASK-006 (TypeScript 5 Upgrade)**: New task required for Zod v4 compatibility. Currently using TypeScript 4.9.5 with `transpileOnly: true` workaround in webpack. + +### Documentation vs Reality + +Task README files have unchecked checkboxes even though work was completed - the checkboxes track planned files rather than actual completion. Code verification is the source of truth. diff --git a/dev-docs/tasks/phase-10-ai-powered-development/DRAFT-CONCEPT.md b/dev-docs/tasks/phase-10-ai-powered-development/DRAFT-CONCEPT.md new file mode 100644 index 0000000..cf795a8 --- /dev/null +++ b/dev-docs/tasks/phase-10-ai-powered-development/DRAFT-CONCEPT.md @@ -0,0 +1,1178 @@ +# Phase 9+: AI-Powered Creation System + +## "I Described a Backend and It Built Itself" + +**Status:** BLUE SKY / PANDORA'S BOX +**Priority:** WORLD DOMINATION +**Risk Level:** πŸ”₯πŸ”₯πŸ”₯πŸ”₯πŸ”₯ (Heads May Literally Explode) +**Dependencies:** Phase 6 UBA complete, Sanity check optional + +--- + +## The Vision + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ +β”‚ User: "I need a backend that uses Claude to generate web components β”‚ +β”‚ for my clients. I want endpoints to create, save, and retrieve β”‚ +β”‚ components from a Postgres database." β”‚ +β”‚ β”‚ +β”‚ AI: "I'll create a Python/FastAPI backend with Anthropic SDK, β”‚ +β”‚ SQLAlchemy for Postgres, and expose these endpoints via UBA..." β”‚ +β”‚ β”‚ +β”‚ [Vibe coding in progress...] β”‚ +β”‚ [Generating UBA schema...] β”‚ +β”‚ [Building Docker image...] β”‚ +β”‚ [Spinning up container...] β”‚ +β”‚ β”‚ +β”‚ AI: "Done. Check your Backend Services panel. I've created: β”‚ +β”‚ - /generate endpoint for Claude component generation β”‚ +β”‚ - /save endpoint for persisting to Postgres β”‚ +β”‚ - /retrieve endpoint for loading saved components β”‚ +β”‚ - A config panel for your API keys and database settings β”‚ +β”‚ - Debug streaming so you can watch Claude think" β”‚ +β”‚ β”‚ +β”‚ User: [head explodes] β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## Part 1: The Backend Creation AI + +### What It Does + +User describes backend needs in natural language β†’ AI: + +1. Analyzes requirements +2. Chooses optimal tech stack +3. Writes the backend code +4. Generates UBA schema YAML +5. Creates Dockerfile +6. Spins up container +7. Registers with Nodegx +8. Config panel appears + +### The Conversation Flow + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Backend Creator AI [New Chat] β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ User: I need a backend that: β”‚ +β”‚ - Calls Claude to generate React components from descriptions β”‚ +β”‚ - Saves generated components to a database β”‚ +β”‚ - Has version history for each component β”‚ +β”‚ - Can retrieve and diff previous versions β”‚ +β”‚ - Sends me a Slack notification when generation completes β”‚ +β”‚ β”‚ +β”‚ AI: Great! Let me understand your requirements: β”‚ +β”‚ β”‚ +β”‚ Core Features: β”‚ +β”‚ βœ“ AI generation (Claude API) β”‚ +β”‚ βœ“ Persistent storage (needs database) β”‚ +β”‚ βœ“ Version history (need versioning strategy) β”‚ +β”‚ βœ“ Diff capability (text diff algorithm) β”‚ +β”‚ βœ“ Notifications (Slack webhook) β”‚ +β”‚ β”‚ +β”‚ Recommended Stack: β”‚ +β”‚ β€’ Python 3.11 + FastAPI (best Anthropic SDK support) β”‚ +β”‚ β€’ PostgreSQL (robust, supports JSONB for components) β”‚ +β”‚ β€’ SQLAlchemy + Alembic (ORM + migrations) β”‚ +β”‚ β€’ Redis (optional: caching, rate limiting) β”‚ +β”‚ β”‚ +β”‚ Estimated Endpoints: β”‚ +β”‚ β€’ POST /generate - Generate component from description β”‚ +β”‚ β€’ GET /components - List all components β”‚ +β”‚ β€’ GET /components/{id} - Get component with versions β”‚ +β”‚ β€’ GET /components/{id}/versions - Version history β”‚ +β”‚ β€’ GET /components/{id}/diff/{v1}/{v2} - Diff two versions β”‚ +β”‚ β€’ POST /components/{id}/regenerate - Regenerate with feedback β”‚ +β”‚ β”‚ +β”‚ Should I proceed with this architecture? β”‚ +β”‚ β”‚ +β”‚ User: Yes, but also add the ability to export as a zip file β”‚ +β”‚ β”‚ +β”‚ AI: Added: β”‚ +β”‚ β€’ GET /components/{id}/export - Download as zip β”‚ +β”‚ β€’ GET /export/bulk - Export multiple components β”‚ +β”‚ β”‚ +β”‚ Creating your backend now... β”‚ +β”‚ β”‚ +β”‚ [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ] 100% β”‚ +β”‚ β”‚ +β”‚ βœ“ Created project structure β”‚ +β”‚ βœ“ Generated FastAPI application β”‚ +β”‚ βœ“ Created database models β”‚ +β”‚ βœ“ Generated UBA schema (12 config fields) β”‚ +β”‚ βœ“ Created Dockerfile β”‚ +β”‚ βœ“ Built image: nodegx-user-backend-abc123 β”‚ +β”‚ βœ“ Container running on port 8042 β”‚ +β”‚ βœ“ Registered with Nodegx β”‚ +β”‚ β”‚ +β”‚ Your backend is ready! Check the Backend Services panel. β”‚ +β”‚ You'll need to configure: β”‚ +β”‚ β€’ Anthropic API key β”‚ +β”‚ β€’ PostgreSQL connection (or I can spin up a container) β”‚ +β”‚ β€’ Slack webhook URL β”‚ +β”‚ β”‚ +β”‚ User: Spin up Postgres too β”‚ +β”‚ β”‚ +β”‚ AI: Done. PostgreSQL container running. β”‚ +β”‚ Database auto-configured in your backend settings. β”‚ +β”‚ Connection string saved securely. β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Generated Project Structure + +``` +user-backend-abc123/ +β”œβ”€β”€ docker-compose.yml # Backend + Postgres + Redis +β”œβ”€β”€ Dockerfile +β”œβ”€β”€ nodegx-schema.yaml # UBA schema for config panel +β”œβ”€β”€ requirements.txt +β”œβ”€β”€ alembic/ # Database migrations +β”‚ └── versions/ +β”œβ”€β”€ app/ +β”‚ β”œβ”€β”€ main.py # FastAPI app +β”‚ β”œβ”€β”€ config.py # Nodegx config integration +β”‚ β”œβ”€β”€ models/ +β”‚ β”‚ β”œβ”€β”€ component.py # SQLAlchemy models +β”‚ β”‚ └── version.py +β”‚ β”œβ”€β”€ routers/ +β”‚ β”‚ β”œβ”€β”€ generate.py # /generate endpoints +β”‚ β”‚ β”œβ”€β”€ components.py # CRUD endpoints +β”‚ β”‚ └── export.py # Export endpoints +β”‚ β”œβ”€β”€ services/ +β”‚ β”‚ β”œβ”€β”€ claude.py # Anthropic integration +β”‚ β”‚ β”œβ”€β”€ versioning.py # Version management +β”‚ β”‚ β”œβ”€β”€ diff.py # Diff generation +β”‚ β”‚ └── slack.py # Notifications +β”‚ └── nodegx/ +β”‚ β”œβ”€β”€ config_handler.py # Receives Nodegx config +β”‚ └── debug_emitter.py # Debug streaming +└── tests/ + └── ... +``` + +### Auto-Generated UBA Schema + +```yaml +# nodegx-schema.yaml (AI-generated) +schema_version: '1.0' + +backend: + id: 'component-generator-abc123' + name: 'Component Generator' + description: 'AI-powered React component generation with versioning' + version: '1.0.0' + + endpoints: + config: '/nodegx/config' + health: '/health' + debug_stream: '/nodegx/debug' + + capabilities: + hot_reload: true + debug: true + +sections: + - id: 'ai' + name: 'AI Configuration' + icon: 'cpu' + fields: + - id: 'anthropic_api_key' + type: 'secret' + name: 'Anthropic API Key' + required: true + + - id: 'model' + type: 'select' + name: 'Claude Model' + options: + - value: 'claude-sonnet-4-20250514' + label: 'Claude Sonnet 4' + - value: 'claude-opus-4-20250514' + label: 'Claude Opus 4' + default: 'claude-sonnet-4-20250514' + + - id: 'max_tokens' + type: 'number' + name: 'Max Response Tokens' + default: 4096 + + - id: 'system_prompt' + type: 'prompt' + name: 'Component Generation Prompt' + rows: 10 + default: | + You are a React component generator. Create clean, + modern React components using TypeScript and Tailwind CSS. + + - id: 'database' + name: 'Database' + icon: 'database' + fields: + - id: 'connection_mode' + type: 'select' + name: 'Database Mode' + options: + - value: 'managed' + label: 'Nodegx Managed (Docker)' + - value: 'external' + label: 'External Database' + default: 'managed' + + - id: 'external_url' + type: 'secret' + name: 'PostgreSQL Connection URL' + visible_when: + field: 'database.connection_mode' + equals: 'external' + + - id: 'notifications' + name: 'Notifications' + icon: 'bell' + fields: + - id: 'slack_enabled' + type: 'boolean' + name: 'Enable Slack Notifications' + default: false + + - id: 'slack_webhook' + type: 'secret' + name: 'Slack Webhook URL' + visible_when: + field: 'notifications.slack_enabled' + equals: true + + - id: 'notify_on' + type: 'multi_select' + name: 'Notify On' + visible_when: + field: 'notifications.slack_enabled' + equals: true + options: + - value: 'generation_complete' + label: 'Generation Complete' + - value: 'generation_error' + label: 'Generation Error' + - value: 'export' + label: 'Component Exported' + default: ['generation_complete', 'generation_error'] + + - id: 'advanced' + name: 'Advanced' + icon: 'settings' + collapsed: true + fields: + - id: 'rate_limit' + type: 'number' + name: 'Rate Limit (requests/minute)' + default: 10 + + - id: 'cache_ttl' + type: 'number' + name: 'Cache TTL (seconds)' + default: 3600 + + - id: 'version_retention' + type: 'number' + name: 'Version Retention Count' + description: 'How many versions to keep per component' + default: 50 + +debug: + enabled: true + event_types: + - id: 'generation_start' + name: 'Generation Started' + - id: 'claude_call' + name: 'Claude API Call' + - id: 'generation_complete' + name: 'Generation Complete' + - id: 'db_operation' + name: 'Database Operation' +``` + +### The AI's Toolset + +The Backend Creator AI needs these tools: + +```typescript +interface BackendCreatorTools { + // Analysis + analyzeRequirements(description: string): RequirementAnalysis; + suggestArchitecture(requirements: RequirementAnalysis): Architecture; + + // Code Generation + generateProjectStructure(architecture: Architecture): FileTree; + generateFile(path: string, purpose: string): string; + generateUBASchema(endpoints: Endpoint[], config: ConfigNeeds[]): string; + + // Docker + generateDockerfile(stack: TechStack): string; + generateDockerCompose(services: Service[]): string; + buildImage(projectPath: string): ImageId; + runContainer(imageId: string, ports: PortMapping[]): ContainerId; + + // Nodegx Integration + registerBackend(url: string, schema: UBASchema): BackendId; + + // Iteration + readFile(path: string): string; + modifyFile(path: string, changes: string): void; + runTests(projectPath: string): TestResult; + getLogs(containerId: string): string[]; +} +``` + +### Follow-up Conversation Support + +The AI maintains conversation context to allow iterative refinement: + +``` +User: "Actually, can you add rate limiting per user, not global?" + +AI: "I'll modify the rate limiting to be per-user based on the + X-User-ID header. Updating..." + + [Modified: app/middleware/rate_limit.py] + [Modified: nodegx-schema.yaml - added user_id_header field] + [Rebuilding container...] + + "Done. The config panel now has a 'User ID Header' field. + Rate limits are tracked per unique user." +``` + +--- + +## Part 2: The Frontend AI Assistant + +### The Problem: One Giant JSON + +Current Nodegx project structure: + +``` +project/ +└── project.json # 50,000+ lines, EVERYTHING in one file +``` + +This is **impossible** for AI assistance because: + +- Can't fit in context window +- Can't target specific components +- Every change risks corrupting unrelated things +- No diff-friendly structure + +### The Solution: Component-Based File Structure + +Proposed new structure: + +``` +project/ +β”œβ”€β”€ nodegx.config.json # Project metadata, settings +β”œβ”€β”€ routes.json # Route definitions +β”œβ”€β”€ components/ +β”‚ β”œβ”€β”€ _index.json # Component registry +β”‚ β”œβ”€β”€ HomePage/ +β”‚ β”‚ β”œβ”€β”€ component.json # Component definition +β”‚ β”‚ β”œβ”€β”€ nodes.json # Node graph +β”‚ β”‚ β”œβ”€β”€ connections.json # Wiring +β”‚ β”‚ └── styles.json # Component-specific styles +β”‚ β”œβ”€β”€ UserProfile/ +β”‚ β”‚ β”œβ”€β”€ component.json +β”‚ β”‚ β”œβ”€β”€ nodes.json +β”‚ β”‚ └── connections.json +β”‚ └── shared/ +β”‚ β”œβ”€β”€ Header/ +β”‚ β”œβ”€β”€ Footer/ +β”‚ └── Button/ +β”œβ”€β”€ models/ +β”‚ β”œβ”€β”€ _index.json # Model registry +β”‚ β”œβ”€β”€ User.json +β”‚ └── Product.json +β”œβ”€β”€ styles/ +β”‚ β”œβ”€β”€ global.json # Global styles +β”‚ └── themes/ +β”‚ β”œβ”€β”€ light.json +β”‚ └── dark.json +└── assets/ + └── ... +``` + +### Component File Format + +```json +// components/UserProfile/component.json +{ + "id": "user-profile-abc123", + "name": "UserProfile", + "type": "visual", + "created": "2026-01-07T14:30:00Z", + "modified": "2026-01-07T15:45:00Z", + "description": "Displays user profile with avatar, name, and bio", + + "inputs": [ + { "name": "userId", "type": "string", "required": true }, + { "name": "showAvatar", "type": "boolean", "default": true } + ], + + "outputs": [ + { "name": "onEdit", "type": "signal" }, + { "name": "onLogout", "type": "signal" } + ], + + "dependencies": ["components/shared/Avatar", "components/shared/Button", "models/User"] +} +``` + +```json +// components/UserProfile/nodes.json +{ + "nodes": [ + { + "id": "node-1", + "type": "Group", + "label": "Profile Container", + "properties": { + "layout": "column", + "padding": "16px", + "gap": "12px" + }, + "children": ["node-2", "node-3", "node-4"] + }, + { + "id": "node-2", + "type": "component:shared/Avatar", + "label": "User Avatar", + "properties": { + "size": "large" + } + }, + { + "id": "node-3", + "type": "Text", + "label": "User Name", + "properties": { + "variant": "heading", + "text": "" + } + } + // ... more nodes + ] +} +``` + +```json +// components/UserProfile/connections.json +{ + "connections": [ + { + "from": { "node": "input:userId", "port": "value" }, + "to": { "node": "fetch-user", "port": "userId" } + }, + { + "from": { "node": "fetch-user", "port": "result.name" }, + "to": { "node": "node-3", "port": "text" } + }, + { + "from": { "node": "fetch-user", "port": "result.avatarUrl" }, + "to": { "node": "node-2", "port": "src" } + } + ] +} +``` + +### Migration Strategy + +``` +Phase 1: Add export capability + - Export existing project to new format + - Import back to old format + - Validate round-trip + +Phase 2: Dual format support + - Editor can open both formats + - Auto-save in new format + - Migration wizard + +Phase 3: New format default + - New projects use new format + - Old projects auto-migrate on open + - Deprecation warnings +``` + +### The Frontend AI Assistant + +With component-based files, the AI can now: + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Frontend AI Assistant β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ User: "Add a loading spinner to the UserProfile component while β”‚ +β”‚ fetching user data" β”‚ +β”‚ β”‚ +β”‚ AI: Let me check the UserProfile component... β”‚ +β”‚ β”‚ +β”‚ [Reading components/UserProfile/component.json] β”‚ +β”‚ [Reading components/UserProfile/nodes.json] β”‚ +β”‚ [Reading components/UserProfile/connections.json] β”‚ +β”‚ β”‚ +β”‚ I see you're fetching user data via a REST node. I'll: β”‚ +β”‚ 1. Add a loading state variable β”‚ +β”‚ 2. Add a Spinner component (from shared library) β”‚ +β”‚ 3. Show spinner while fetch is pending β”‚ +β”‚ 4. Hide spinner and show content when complete β”‚ +β”‚ β”‚ +β”‚ [Modified: components/UserProfile/nodes.json] β”‚ +β”‚ - Added: Condition node for loading state β”‚ +β”‚ - Added: Spinner component reference β”‚ +β”‚ β”‚ +β”‚ [Modified: components/UserProfile/connections.json] β”‚ +β”‚ - Connected: fetch.isPending β†’ condition.condition β”‚ +β”‚ - Connected: condition.true β†’ spinner.visible β”‚ +β”‚ - Connected: condition.false β†’ content.visible β”‚ +β”‚ β”‚ +β”‚ Done! The component now shows a spinner during data fetch. β”‚ +β”‚ Would you like me to customize the spinner appearance? β”‚ +β”‚ β”‚ +β”‚ User: "Yes, make it match our brand blue color" β”‚ +β”‚ β”‚ +β”‚ AI: [Reading styles/themes/light.json for brand colors] β”‚ +β”‚ β”‚ +β”‚ Found your brand blue: #3B82F6 β”‚ +β”‚ β”‚ +β”‚ [Modified: components/UserProfile/nodes.json] β”‚ +β”‚ - Updated: Spinner color to use design token β”‚ +β”‚ β”‚ +β”‚ Done! The spinner now uses your brand blue. β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### AI Tools for Frontend Assistance + +```typescript +interface FrontendAssistantTools { + // Project Navigation + listComponents(): ComponentSummary[]; + listModels(): ModelSummary[]; + getComponentDependencyGraph(): DependencyGraph; + + // Component Operations + readComponent(componentPath: string): ComponentDefinition; + readComponentNodes(componentPath: string): NodeGraph; + readComponentConnections(componentPath: string): Connections; + + // Modifications + addNode(componentPath: string, node: Node): void; + removeNode(componentPath: string, nodeId: string): void; + updateNodeProperty(componentPath: string, nodeId: string, property: string, value: any): void; + addConnection(componentPath: string, connection: Connection): void; + removeConnection(componentPath: string, connectionId: string): void; + + // Creation + createComponent(name: string, template?: string): ComponentPath; + duplicateComponent(source: string, newName: string): ComponentPath; + + // Understanding + explainComponent(componentPath: string): string; + findSimilarComponents(description: string): ComponentPath[]; + suggestImprovements(componentPath: string): Suggestion[]; + + // Validation + validateComponent(componentPath: string): ValidationResult; + checkConnections(componentPath: string): ConnectionIssue[]; +} +``` + +--- + +## Part 3: The Unified AI Architecture + +### System Overview + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Nodegx AI System β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ User Input │───▢│ AI Orchestrator │───▢│ Tool Execution β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β–Ό β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Conversation Memory β”‚ β”‚ +β”‚ β”‚ (prompt caching, history) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ Tools Available: β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Frontend β”‚ β”‚ Backend β”‚ β”‚ Docker β”‚ β”‚ File β”‚ β”‚ +β”‚ β”‚ Tools β”‚ β”‚ Tools β”‚ β”‚ Tools β”‚ β”‚ System β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ UBA β”‚ β”‚ Database β”‚ β”‚ Git β”‚ β”‚ Testing β”‚ β”‚ +β”‚ β”‚ Tools β”‚ β”‚ Tools β”‚ β”‚ Tools β”‚ β”‚ Tools β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### The Orchestrator + +```python +# Conceptual architecture + +class NodgexAIOrchestrator: + """ + Central AI system that routes requests to appropriate specialists + and maintains conversation context. + """ + + def __init__(self): + self.frontend_agent = FrontendAssistant() + self.backend_agent = BackendCreator() + self.conversation_memory = ConversationMemory() + self.tool_executor = ToolExecutor() + + async def process(self, user_message: str, context: ProjectContext) -> Response: + # Add to conversation memory + self.conversation_memory.add_user_message(user_message) + + # Classify intent + intent = await self.classify_intent(user_message) + + # Route to appropriate agent + if intent.type == "frontend": + response = await self.frontend_agent.process( + user_message, + context, + self.conversation_memory + ) + elif intent.type == "backend": + response = await self.backend_agent.process( + user_message, + context, + self.conversation_memory + ) + elif intent.type == "mixed": + # Coordinate both agents + response = await self.coordinate_agents( + user_message, + context, + self.conversation_memory + ) + + # Add response to memory + self.conversation_memory.add_assistant_message(response) + + return response +``` + +### Prompt Caching Strategy + +For efficient token usage: + +```python +class ConversationMemory: + """ + Manages conversation history with intelligent caching + """ + + def __init__(self): + self.messages: List[Message] = [] + self.project_context_cache: Dict[str, CachedContext] = {} + self.max_context_tokens = 100000 + + def get_context_for_request(self, request_type: str) -> List[Message]: + """ + Build context for LLM request with caching + """ + + # Static system prompt (cacheable) + system_prompt = self.get_system_prompt(request_type) + + # Project structure summary (cache for 5 min) + project_summary = self.get_cached_project_summary() + + # Relevant conversation history (last N turns) + recent_history = self.get_recent_history(turns=10) + + # Component-specific context (cache per component) + if request_type == "frontend": + component_context = self.get_component_context() + + return [ + {"role": "system", "content": system_prompt, "cache_control": {"type": "ephemeral"}}, + {"role": "user", "content": project_summary, "cache_control": {"type": "ephemeral"}}, + *recent_history, + {"role": "user", "content": component_context} if component_context else None + ] + + def summarize_old_messages(self): + """ + When conversation gets long, summarize older messages + """ + if len(self.messages) > 20: + old_messages = self.messages[:-10] + summary = self.llm.summarize(old_messages) + + # Replace old messages with summary + self.messages = [ + {"role": "system", "content": f"Previous conversation summary: {summary}"}, + *self.messages[-10:] + ] +``` + +### Tool Execution Pattern + +```python +class ToolExecutor: + """ + Executes tools requested by AI agents + """ + + def __init__(self): + self.tools = { + # Frontend tools + "list_components": self.list_components, + "read_component": self.read_component, + "modify_node": self.modify_node, + "add_connection": self.add_connection, + + # Backend tools + "generate_file": self.generate_file, + "build_docker": self.build_docker, + "run_container": self.run_container, + + # Shared tools + "read_file": self.read_file, + "write_file": self.write_file, + "run_command": self.run_command, + } + + async def execute(self, tool_name: str, params: Dict) -> ToolResult: + if tool_name not in self.tools: + return ToolResult(success=False, error=f"Unknown tool: {tool_name}") + + try: + result = await self.tools[tool_name](**params) + return ToolResult(success=True, data=result) + except Exception as e: + return ToolResult(success=False, error=str(e)) +``` + +--- + +## Part 4: OSS Options for Implementation + +### Option A: LangGraph (Recommended) + +We already have experience with LangGraph from Erleah. Benefits: + +- Stateful graph-based agent architecture +- Built-in persistence for conversation memory +- Easy tool integration +- Streaming support +- Python ecosystem + +```python +from langgraph.graph import StateGraph +from langgraph.checkpoint import MemorySaver + +class NodegxAssistantGraph: + def __init__(self): + self.graph = StateGraph(AssistantState) + + # Add nodes + self.graph.add_node("classify", self.classify_intent) + self.graph.add_node("frontend", self.frontend_agent) + self.graph.add_node("backend", self.backend_agent) + self.graph.add_node("execute_tools", self.execute_tools) + self.graph.add_node("respond", self.generate_response) + + # Add edges + self.graph.add_conditional_edges( + "classify", + self.route_to_agent, + { + "frontend": "frontend", + "backend": "backend" + } + ) + + # Compile with memory + self.memory = MemorySaver() + self.app = self.graph.compile(checkpointer=self.memory) +``` + +### Option B: Custom with Anthropic Tools + +Simpler, direct integration with Claude: + +```python +from anthropic import Anthropic + +class NodegxAssistant: + def __init__(self): + self.client = Anthropic() + self.tools = self.define_tools() + + def define_tools(self): + return [ + { + "name": "read_component", + "description": "Read a Nodegx component's definition", + "input_schema": { + "type": "object", + "properties": { + "component_path": {"type": "string"} + }, + "required": ["component_path"] + } + }, + # ... more tools + ] + + async def process(self, message: str, history: List[Dict]): + response = await self.client.messages.create( + model="claude-sonnet-4-20250514", + max_tokens=4096, + system=SYSTEM_PROMPT, + tools=self.tools, + messages=[*history, {"role": "user", "content": message}] + ) + + # Handle tool calls + while response.stop_reason == "tool_use": + tool_results = await self.execute_tool_calls(response.content) + response = await self.client.messages.create( + model="claude-sonnet-4-20250514", + max_tokens=4096, + tools=self.tools, + messages=[ + *history, + {"role": "user", "content": message}, + {"role": "assistant", "content": response.content}, + {"role": "user", "content": tool_results} + ] + ) + + return response +``` + +### Option C: Cline/Aider Integration + +Use existing AI coding assistants: + +- Cline already works with VS Code +- Could wrap Cline's core for Nodegx +- Benefit from existing file management + +But: Would need significant customization for Nodegx's visual paradigm. + +### Recommendation + +**Use LangGraph** with custom Nodegx-specific tools: + +- Proven architecture from Erleah +- Good balance of flexibility and structure +- Python ecosystem for backend creation +- Can add specialized agents for different tasks +- Built-in conversation memory + +--- + +## Part 5: Implementation Roadmap + +### Phase 9A: Project Structure Modernization (4 weeks) + +**Goal:** Enable AI assistance by restructuring project files + +``` +Week 1-2: Design & Export +- Design new file structure +- Build export from old format to new +- Validate structure works for AI access + +Week 3-4: Editor Support +- Add support for new format in editor +- Migration wizard +- Backward compatibility layer +``` + +### Phase 9B: Frontend AI Assistant (6 weeks) + +**Goal:** AI that can modify frontend components + +``` +Week 1-2: Tool Implementation +- Component reading tools +- Component modification tools +- Validation tools + +Week 3-4: Agent Development +- LangGraph agent setup +- Conversation memory +- Prompt engineering + +Week 5-6: Integration & Polish +- Editor UI for assistant +- Streaming responses +- Error handling +``` + +### Phase 9C: Backend Creation AI (8 weeks) + +**Goal:** AI that can create backends from scratch + +``` +Week 1-2: Code Generation +- Project structure templates +- FastAPI/Express generators +- UBA schema generator + +Week 3-4: Docker Integration +- Dockerfile generation +- docker-compose generation +- Container management + +Week 5-6: Agent Development +- Requirements analysis +- Architecture decisions +- Iterative refinement + +Week 7-8: Integration +- Nodegx registration +- End-to-end flow +- Testing +``` + +### Phase 9D: Unified Experience (4 weeks) + +**Goal:** Seamless AI assistance across frontend and backend + +``` +Week 1-2: Orchestration +- Intent classification +- Agent coordination +- Context sharing + +Week 3-4: Polish +- Unified UI +- Performance optimization +- Documentation +``` + +--- + +## Part 6: The User Experience + +### The AI Panel + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Nodegx AI Assistant [New] [History] [βš™]β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Quick Actions: β”‚ β”‚ +β”‚ β”‚ [+ Create Component] [+ Create Backend] [✨ Improve Selected] β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ You β”‚ I need a component that displays a list of products β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”˜ with filters for category and price range β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ AI β”‚ I'll create a ProductList component with: β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β€’ Category dropdown filter β”‚ β”‚ +β”‚ β”‚ β€’ Price range slider β”‚ β”‚ +β”‚ β”‚ β€’ Grid layout for products β”‚ β”‚ +β”‚ β”‚ β€’ Loading and empty states β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Creating component... β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ βœ“ Created components/ProductList/ β”‚ β”‚ +β”‚ β”‚ βœ“ Added 12 nodes β”‚ β”‚ +β”‚ β”‚ βœ“ Connected to Products model β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ [View Component] [Modify] [Undo] β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ You β”‚ Now I need a backend to fetch products from an β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”˜ external API and cache them in Redis β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ AI β”‚ I'll create a Product API backend with: β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β€’ External API fetching β”‚ β”‚ +β”‚ β”‚ β€’ Redis caching layer β”‚ β”‚ +β”‚ β”‚ β€’ Configurable TTL β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Building backend... β”‚ β”‚ +β”‚ β”‚ [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘] 40% β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ [ ] [Send] [🎀] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Context Menu Integration + +Right-click on any component in the canvas: + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Cut ⌘X β”‚ +β”‚ Copy ⌘C β”‚ +β”‚ Paste ⌘V β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ πŸ€– Ask AI about this... β”‚ +β”‚ ✨ Improve with AI β”‚ +β”‚ πŸ“ Document with AI β”‚ +β”‚ πŸ” Explain this component β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Delete ⌫ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## Part 7: Risk Analysis + +### Technical Risks + +| Risk | Severity | Mitigation | +| ------------------------------------- | -------- | -------------------------------------------- | +| AI generates broken code | HIGH | Validation layers, sandboxed execution, undo | +| Token costs explode | HIGH | Aggressive caching, smart context management | +| Hallucination creates wrong structure | MEDIUM | Schema validation, type checking | +| Docker security vulnerabilities | HIGH | Container isolation, resource limits | +| Conversation memory grows unbounded | MEDIUM | Summarization, sliding window | + +### Product Risks + +| Risk | Severity | Mitigation | +| ----------------------------------- | -------- | ------------------------------------------- | +| Users over-rely on AI | MEDIUM | Education, progressive disclosure | +| AI creates unmaintainable spaghetti | HIGH | Best practices enforcement, code review AI | +| Support burden increases | MEDIUM | Self-service docs, AI explains its own work | +| Competitive copying | LOW | Speed of execution, community building | + +### The "Too Powerful" Risk + +This is genuinely powerful. Mitigations: + +1. **Guardrails** - AI can't access sensitive data, network restrictions +2. **Audit trail** - Log all AI actions for review +3. **Human approval** - Require confirmation for destructive actions +4. **Sandboxing** - Generated backends run in isolated containers +5. **Rate limiting** - Prevent runaway generation + +--- + +## Part 8: Success Metrics + +### Phase 9 Success Looks Like + +**Quantitative:** + +- 80% of new projects use AI assistant +- Average time to create backend: 5 minutes (from 2 hours) +- AI-created components work first try: 70% +- User retention increases 40% + +**Qualitative:** + +- "I described what I needed and it just worked" +- "I haven't written a backend in months" +- "The AI understands my project better than I do" + +### The "Head Explodes" Moment + +When a user: + +1. Describes a complex backend in plain English +2. Watches it build itself in real-time +3. Sees the config panel appear automatically +4. Connects their frontend to it immediately +5. Has a working full-stack app in 15 minutes + +That's the moment. + +--- + +## Summary + +This is Pandora's Box, but it's also the future. The combination of: + +- **UBA** (any backend can integrate) +- **AI Backend Creator** (any backend can be generated) +- **AI Frontend Assistant** (any component can be modified) +- **Docker** (everything runs anywhere) + +...creates a system where the line between "describing what you want" and "having what you want" becomes nearly invisible. + +The technical challenges are significant but solvable: + +1. Restructure project files β†’ enables AI access +2. Build LangGraph agents β†’ enables intelligent automation +3. Integrate Docker β†’ enables isolated execution +4. Create unified UX β†’ enables seamless experience + +Is it too powerful? Maybe. But the alternative is that someone else builds it first. + +**The question isn't whether to build it. The question is how fast can we move.** + +--- + +## Next Steps + +1. **Immediate:** Complete UBA (Phase 6) - the foundation +2. **Q2 2026:** Project restructuring (Phase 9A) +3. **Q3 2026:** Frontend AI Assistant (Phase 9B) +4. **Q4 2026:** Backend Creation AI (Phase 9C) +5. **Q1 2027:** World domination (Phase 9D) + +_"The best way to predict the future is to build it."_ + +--- + +## Appendix: Competitive Analysis + +Nobody else has this exact combination: + +| Platform | Visual Dev | AI Assist | Backend Create | Config UI | +| ----------- | ---------- | --------- | -------------- | --------- | +| Retool | βœ“ | Partial | βœ— | βœ— | +| Webflow | βœ“ | βœ— | βœ— | βœ— | +| Bubble | βœ“ | Partial | βœ— | βœ— | +| FlutterFlow | βœ“ | Partial | βœ— | βœ— | +| v0 | βœ— | βœ“ | βœ— | βœ— | +| Bolt | βœ— | βœ“ | Partial | βœ— | +| **Nodegx** | βœ“ | βœ“ | βœ“ | βœ“ | + +The full stack, AI-powered, visual development platform with universal backend integration. + +That's the vision. Let's build it. diff --git a/dev-docs/tasks/phase-10-ai-powered-development/PROGRESS.md b/dev-docs/tasks/phase-10-ai-powered-development/PROGRESS.md new file mode 100644 index 0000000..1ae83cb --- /dev/null +++ b/dev-docs/tasks/phase-10-ai-powered-development/PROGRESS.md @@ -0,0 +1,202 @@ +# Phase 10: AI-Powered Development - Progress Tracker + +**Last Updated:** 2026-01-07 +**Overall Status:** πŸ”΄ Not Started + +--- + +## Quick Summary + +| Metric | Value | +| ------------ | ------ | +| Total Tasks | 42 | +| Completed | 0 | +| In Progress | 0 | +| Not Started | 42 | +| **Progress** | **0%** | + +--- + +## Sub-Phase Overview + +| Sub-Phase | Name | Tasks | Effort | Status | +| --------- | ------------------------------- | ----- | ------------- | -------------- | +| **10A** | Project Structure Modernization | 9 | 80-110 hours | πŸ”΄ Not Started | +| **10B** | Frontend AI Assistant | 8 | 100-130 hours | πŸ”΄ Not Started | +| **10C** | Backend Creation AI | 10 | 140-180 hours | πŸ”΄ Not Started | +| **10D** | Unified AI Experience | 6 | 60-80 hours | πŸ”΄ Not Started | +| **10E** | DEPLOY System Updates | 4 | 20-30 hours | πŸ”΄ Not Started | +| **10F** | Legacy Migration System | 5 | 40-50 hours | πŸ”΄ Not Started | + +**Total Effort Estimate:** 400-550 hours (24-32 weeks) + +--- + +## Phase 10A: Project Structure Modernization + +**Status:** πŸ”΄ Not Started +**Priority:** CRITICAL - Blocks all AI features + +Transform the monolithic `project.json` into a component-per-file structure that AI can understand and edit. + +| Task | Name | Effort | Status | +| ---------- | ----------------------- | ------ | -------------- | +| STRUCT-001 | JSON Schema Definition | 12-16h | πŸ”΄ Not Started | +| STRUCT-002 | Export Engine Core | 16-20h | πŸ”΄ Not Started | +| STRUCT-003 | Import Engine Core | 16-20h | πŸ”΄ Not Started | +| STRUCT-004 | Editor Format Detection | 6-8h | πŸ”΄ Not Started | +| STRUCT-005 | Lazy Component Loading | 12-16h | πŸ”΄ Not Started | +| STRUCT-006 | Component-Level Save | 12-16h | πŸ”΄ Not Started | +| STRUCT-007 | Migration Wizard UI | 10-14h | πŸ”΄ Not Started | +| STRUCT-008 | Testing & Validation | 16-20h | πŸ”΄ Not Started | +| STRUCT-009 | Documentation | 6-8h | πŸ”΄ Not Started | + +--- + +## Phase 10B: Frontend AI Assistant + +**Status:** πŸ”΄ Not Started +**Depends on:** Phase 10A complete + +Build an AI assistant that can understand, navigate, and modify frontend components using natural language. + +| Task | Name | Effort | Status | +| ------ | ----------------------------- | ------ | -------------- | +| AI-001 | Component Reading Tools | 12-16h | πŸ”΄ Not Started | +| AI-002 | Component Modification Tools | 16-20h | πŸ”΄ Not Started | +| AI-003 | LangGraph Agent Setup | 16-20h | πŸ”΄ Not Started | +| AI-004 | Conversation Memory & Caching | 12-16h | πŸ”΄ Not Started | +| AI-005 | AI Panel UI | 16-20h | πŸ”΄ Not Started | +| AI-006 | Context Menu Integration | 8-10h | πŸ”΄ Not Started | +| AI-007 | Streaming Responses | 8-10h | πŸ”΄ Not Started | +| AI-008 | Error Handling & Recovery | 8-10h | πŸ”΄ Not Started | + +--- + +## Phase 10C: Backend Creation AI + +**Status:** πŸ”΄ Not Started +**Depends on:** Phase 10B started + +AI-powered backend code generation with Docker integration. + +| Task | Name | Effort | Status | +| -------- | ------------------------- | ------ | -------------- | +| BACK-001 | Requirements Analyzer | 16-20h | πŸ”΄ Not Started | +| BACK-002 | Architecture Planner | 12-16h | πŸ”΄ Not Started | +| BACK-003 | Code Generation Engine | 24-30h | πŸ”΄ Not Started | +| BACK-004 | UBA Schema Generator | 12-16h | πŸ”΄ Not Started | +| BACK-005 | Docker Integration | 16-20h | πŸ”΄ Not Started | +| BACK-006 | Container Management | 12-16h | πŸ”΄ Not Started | +| BACK-007 | Backend Agent (LangGraph) | 16-20h | πŸ”΄ Not Started | +| BACK-008 | Iterative Refinement | 12-16h | πŸ”΄ Not Started | +| BACK-009 | Backend Templates | 12-16h | πŸ”΄ Not Started | +| BACK-010 | Testing & Validation | 16-20h | πŸ”΄ Not Started | + +--- + +## Phase 10D: Unified AI Experience + +**Status:** πŸ”΄ Not Started +**Depends on:** Phase 10B and 10C substantially complete + +Unified chat experience across frontend and backend AI. + +| Task | Name | Effort | Status | +| --------- | ------------------------- | ------ | -------------- | +| UNIFY-001 | AI Orchestrator | 16-20h | πŸ”΄ Not Started | +| UNIFY-002 | Intent Classification | 8-12h | πŸ”΄ Not Started | +| UNIFY-003 | Cross-Agent Context | 12-16h | πŸ”΄ Not Started | +| UNIFY-004 | Unified Chat UI | 10-14h | πŸ”΄ Not Started | +| UNIFY-005 | AI Settings & Preferences | 6-8h | πŸ”΄ Not Started | +| UNIFY-006 | Usage Analytics | 8-10h | πŸ”΄ Not Started | + +--- + +## Phase 10E: DEPLOY System Updates + +**Status:** πŸ”΄ Not Started +**Can proceed after:** Phase 10A STRUCT-004 + +Update deployment system to work with new project structure and AI features. + +| Task | Name | Effort | Status | +| ----------------- | ------------------------------- | ------ | -------------- | +| DEPLOY-UPDATE-001 | V2 Project Format Support | 8-10h | πŸ”΄ Not Started | +| DEPLOY-UPDATE-002 | AI-Generated Backend Deploy | 6-8h | πŸ”΄ Not Started | +| DEPLOY-UPDATE-003 | Preview Deploys with AI Changes | 4-6h | πŸ”΄ Not Started | +| DEPLOY-UPDATE-004 | Environment Variables for AI | 4-6h | πŸ”΄ Not Started | + +--- + +## Phase 10F: Legacy Migration System + +**Status:** πŸ”΄ Not Started +**Can proceed in parallel with:** Phase 10A after STRUCT-003 + +Automatic migration from legacy project.json to new V2 format. + +| Task | Name | Effort | Status | +| ----------- | ------------------------------ | ------ | -------------- | +| MIGRATE-001 | Project Analysis Engine | 10-12h | πŸ”΄ Not Started | +| MIGRATE-002 | Pre-Migration Warning UI | 8-10h | πŸ”΄ Not Started | +| MIGRATE-003 | Integration with Import Flow | 10-12h | πŸ”΄ Not Started | +| MIGRATE-004 | Incremental Migration | 8-10h | πŸ”΄ Not Started | +| MIGRATE-005 | Migration Testing & Validation | 10-12h | πŸ”΄ Not Started | + +--- + +## Critical Path + +``` +STRUCT-001 β†’ STRUCT-002 β†’ STRUCT-003 β†’ STRUCT-004 β†’ STRUCT-005 β†’ STRUCT-006 + ↓ + MIGRATE-001 β†’ MIGRATE-002 β†’ MIGRATE-003 + ↓ + AI-001 β†’ AI-002 β†’ AI-003 β†’ AI-004 β†’ AI-005 + ↓ + BACK-001 β†’ BACK-002 β†’ ... β†’ BACK-010 + ↓ + UNIFY-001 β†’ UNIFY-002 β†’ ... β†’ UNIFY-006 +``` + +--- + +## Status Legend + +- πŸ”΄ **Not Started** - Work has not begun +- 🟑 **In Progress** - Actively being worked on +- 🟒 **Complete** - Finished and verified + +--- + +## Recent Updates + +| Date | Update | +| ---------- | ---------------------------------------------------------------- | +| 2026-01-07 | Updated PROGRESS.md to reflect full 42-task scope from README.md | +| 2026-01-07 | Renumbered from Phase 9 to Phase 10 | + +--- + +## Dependencies + +- **Phase 6 (UBA)**: Recommended but not blocking for 10A +- **Phase 3 (Editor UX)**: Some UI patterns may be reused + +--- + +## Notes + +This phase is the FOUNDATIONAL phase for AI vibe coding! + +**Phase 10A (Project Structure)** is critical - transforms the monolithic 50,000+ line project.json into a component-per-file structure that AI can understand and edit. + +Key features: + +- Components stored as individual JSON files (~3000 tokens each) +- AI can edit single components without loading entire project +- Enables AI-driven development workflows +- Foundation for future AI assistant features + +See README.md for full task specifications and implementation details. diff --git a/dev-docs/tasks/phase-10-ai-powered-development/README.md b/dev-docs/tasks/phase-10-ai-powered-development/README.md new file mode 100644 index 0000000..725c05b --- /dev/null +++ b/dev-docs/tasks/phase-10-ai-powered-development/README.md @@ -0,0 +1,3159 @@ +# PHASE 10: AI-Powered Development Platform + +## Complete Task Documentation + +**Status:** BLUE SKY β†’ CONCRETE TASKS +**Total Duration:** 24-32 weeks +**Total Effort:** 400-550 hours +**Dependencies:** Phase 6 (UBA) recommended but not blocking for 10A + +--- + +## Phase Overview + +| Phase | Name | Duration | Tasks | Effort | +| ------- | ------------------------------- | ---------- | -------- | ------------- | +| **10A** | Project Structure Modernization | 6-8 weeks | 9 tasks | 80-110 hours | +| **10B** | Frontend AI Assistant | 6-8 weeks | 8 tasks | 100-130 hours | +| **10C** | Backend Creation AI | 8-10 weeks | 10 tasks | 140-180 hours | + + 9A: Project Structure ──────────────────────────────┐ + β”‚ β”‚ + β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + ↓ ↓ ↓ + 9B: Frontend AI 9F: Migration System 9E: DEPLOY Updates + β”‚ β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + ↓ β”‚ + 9C: Backend AI β”‚ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ + 9D: Unified Experience + +``` + +--- + +# PHASE 10A: PROJECT STRUCTURE MODERNIZATION +| **10D** | Unified AI Experience | 4-6 weeks | 6 tasks | 60-80 hours | +| **10E** | DEPLOY System Updates | 1-2 weeks | 4 tasks | 20-30 hours | +| **10F** | Legacy Migration System | 2-3 weeks | 5 tasks | 40-50 hours | + +``` + +PHASE 10 DEPENDENCY GRAPH + + 10A: Project Structure ─────────────────────────────┐ + β”‚ β”‚ + β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + ↓ ↓ ↓ + 10B: Frontend AI 10F: Migration System 10E: DEPLOY Updates + β”‚ β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + ↓ β”‚ + 10C: Backend AI β”‚ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ + 10D: Unified Experience + +``` + +--- + +# PHASE 10A: PROJECT STRUCTURE MODERNIZATION +======================== + + 9A: Project Structure ──────────────────────────────┐ + β”‚ β”‚ + β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ + ↓ ↓ ↓ + 9B: Frontend AI 9F: Migration System 9E: DEPLOY Updates + β”‚ β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ + ↓ β”‚ + 9C: Backend AI β”‚ + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ + 9D: Unified Experience +``` + +--- + +# PHASE 10A: PROJECT STRUCTURE MODERNIZATION + +## Overview + +Transform the monolithic `project.json` into a React-style component file structure to enable AI assistance, improve Git collaboration, and enhance performance. + +**Duration:** 6-8 weeks +**Total Effort:** 80-110 hours +**Priority:** CRITICAL - Blocks all AI features +**Depends on:** Phase 6 (UBA) recommended but not blocking + +### The Problem + +``` +Current: Single project.json with 50,000+ lines + - Can't fit in AI context window + - 200,000 tokens to read entire project + - Any edit risks corrupting unrelated components + - Git diffs are meaningless + +Target: Component-based file structure + - 3,000 tokens to read one component + - Surgical AI modifications + - Meaningful Git diffs + - 10x faster operations +``` + +### Target Structure + +``` +project/ +β”œβ”€β”€ nodegx.project.json # Project metadata (~100 lines) +β”œβ”€β”€ nodegx.routes.json # Route definitions +β”œβ”€β”€ nodegx.styles.json # Global styles +β”œβ”€β”€ components/ +β”‚ β”œβ”€β”€ _registry.json # Component index +β”‚ β”œβ”€β”€ App/ +β”‚ β”‚ β”œβ”€β”€ component.json # Metadata, ports +β”‚ β”‚ β”œβ”€β”€ nodes.json # Node graph +β”‚ β”‚ └── connections.json # Wiring +β”‚ β”œβ”€β”€ pages/ +β”‚ β”‚ β”œβ”€β”€ HomePage/ +β”‚ β”‚ └── ProfilePage/ +β”‚ └── shared/ +β”‚ β”œβ”€β”€ Button/ +β”‚ └── Avatar/ +└── models/ + β”œβ”€β”€ _registry.json + └── User.json +``` + +--- + +## STRUCT-001: JSON Schema Definition + +**Effort:** 12-16 hours (3 days) +**Priority:** Critical +**Blocks:** All other STRUCT tasks + +### Description + +Define formal JSON schemas for all new file formats. These schemas enable validation, IDE support, and serve as documentation. + +### Deliverables + +``` +schemas/ +β”œβ”€β”€ project-v2.schema.json # Root project file +β”œβ”€β”€ component.schema.json # Component metadata +β”œβ”€β”€ nodes.schema.json # Node definitions +β”œβ”€β”€ connections.schema.json # Connection definitions +β”œβ”€β”€ registry.schema.json # Component registry +β”œβ”€β”€ routes.schema.json # Route definitions +β”œβ”€β”€ styles.schema.json # Global styles +└── model.schema.json # Model definitions +``` + +### Schema: component.json + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://nodegx.dev/schemas/component-v2.json", + "title": "Nodegx Component", + "type": "object", + "required": ["id", "name", "type"], + "properties": { + "id": { + "type": "string", + "pattern": "^comp_[a-z0-9_]+$", + "description": "Unique component identifier" + }, + "name": { + "type": "string", + "description": "Component name (folder name)" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "path": { + "type": "string", + "description": "Original Noodl path for backward compatibility" + }, + "type": { + "type": "string", + "enum": ["root", "page", "visual", "logic", "cloud"], + "description": "Component type" + }, + "description": { + "type": "string" + }, + "category": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { "type": "string" } + }, + "ports": { + "type": "object", + "properties": { + "inputs": { + "type": "array", + "items": { "$ref": "#/definitions/port" } + }, + "outputs": { + "type": "array", + "items": { "$ref": "#/definitions/port" } + } + } + }, + "dependencies": { + "type": "array", + "items": { "type": "string" }, + "description": "Paths to components this component uses" + }, + "created": { + "type": "string", + "format": "date-time" + }, + "modified": { + "type": "string", + "format": "date-time" + } + }, + "definitions": { + "port": { + "type": "object", + "required": ["name", "type"], + "properties": { + "name": { "type": "string" }, + "type": { "type": "string" }, + "displayName": { "type": "string" }, + "description": { "type": "string" }, + "default": {}, + "required": { "type": "boolean" } + } + } + } +} +``` + +### Schema: nodes.json + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://nodegx.dev/schemas/nodes-v2.json", + "title": "Nodegx Component Nodes", + "type": "object", + "required": ["componentId", "nodes"], + "properties": { + "componentId": { + "type": "string", + "description": "Reference to parent component" + }, + "version": { + "type": "integer", + "description": "Schema version for migrations" + }, + "nodes": { + "type": "array", + "items": { "$ref": "#/definitions/node" } + } + }, + "definitions": { + "node": { + "type": "object", + "required": ["id", "type"], + "properties": { + "id": { "type": "string" }, + "type": { "type": "string" }, + "label": { "type": "string" }, + "position": { + "type": "object", + "properties": { + "x": { "type": "number" }, + "y": { "type": "number" } + } + }, + "parent": { "type": "string" }, + "children": { + "type": "array", + "items": { "type": "string" } + }, + "properties": { "type": "object" }, + "ports": { "type": "array" }, + "dynamicports": { "type": "array" }, + "states": { "type": "object" }, + "metadata": { "type": "object" } + } + } + } +} +``` + +### Schema: connections.json + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://nodegx.dev/schemas/connections-v2.json", + "title": "Nodegx Component Connections", + "type": "object", + "required": ["componentId", "connections"], + "properties": { + "componentId": { "type": "string" }, + "version": { "type": "integer" }, + "connections": { + "type": "array", + "items": { "$ref": "#/definitions/connection" } + } + }, + "definitions": { + "connection": { + "type": "object", + "required": ["id", "from", "to"], + "properties": { + "id": { "type": "string" }, + "from": { + "type": "object", + "required": ["node", "port"], + "properties": { + "node": { "type": "string" }, + "port": { "type": "string" } + } + }, + "to": { + "type": "object", + "required": ["node", "port"], + "properties": { + "node": { "type": "string" }, + "port": { "type": "string" } + } + } + } + } + } +} +``` + +### Implementation Steps + +1. Study existing project.json structure exhaustively +2. Map all node types and their serialization +3. Design schemas with backward compatibility +4. Create JSON Schema files +5. Build validation utilities using Ajv +6. Test against 10+ real projects + +### Acceptance Criteria + +- [ ] All 8 schema files defined +- [ ] Schemas published to `/schemas` endpoint +- [ ] Validation utility created and tested +- [ ] IDE autocomplete works with schemas +- [ ] 100% coverage of existing node types +- [ ] Edge cases documented + +### Files to Create + +``` +packages/noodl-editor/src/schemas/ +β”œβ”€β”€ index.ts # Schema exports +β”œβ”€β”€ project-v2.schema.json +β”œβ”€β”€ component.schema.json +β”œβ”€β”€ nodes.schema.json +β”œβ”€β”€ connections.schema.json +β”œβ”€β”€ registry.schema.json +β”œβ”€β”€ routes.schema.json +β”œβ”€β”€ styles.schema.json +β”œβ”€β”€ model.schema.json +└── validator.ts # Ajv validation wrapper +``` + +--- + +## STRUCT-002: Export Engine Core + +**Effort:** 16-20 hours (4 days) +**Priority:** Critical +**Depends on:** STRUCT-001 +**Blocks:** STRUCT-003, STRUCT-006 + +### Description + +Build the engine that converts legacy `project.json` to the new multi-file format. + +### Core Class + +```typescript +// packages/noodl-editor/src/editor/src/services/ProjectStructure/Exporter.ts + +import * as path from 'path'; +import { validateSchema } from '@nodegx/schemas'; +import * as fs from 'fs-extra'; + +import { LegacyProject, LegacyComponent } from './types/legacy'; +import { ModernProject, ComponentFiles } from './types/modern'; + +export interface ExportOptions { + outputDir: string; + preserveOriginalPaths: boolean; + validateOutput: boolean; + onProgress?: (percent: number, message: string) => void; +} + +export interface ExportResult { + success: boolean; + componentsExported: number; + modelsExported: number; + warnings: string[]; + errors: string[]; + outputPath: string; +} + +export class ProjectExporter { + private options: ExportOptions; + + constructor(options: ExportOptions) { + this.options = options; + } + + async export(project: LegacyProject): Promise { + const result: ExportResult = { + success: false, + componentsExported: 0, + modelsExported: 0, + warnings: [], + errors: [], + outputPath: this.options.outputDir + }; + + try { + this.report(0, 'Starting export...'); + + // 1. Create output directory structure + await this.createDirectoryStructure(); + this.report(5, 'Directory structure created'); + + // 2. Export project metadata + await this.exportProjectMetadata(project); + this.report(10, 'Project metadata exported'); + + // 3. Export components + const componentCount = Object.keys(project.components || {}).length; + let processed = 0; + + const registry: ComponentRegistry = { + version: 1, + lastUpdated: new Date().toISOString(), + components: {}, + stats: { totalComponents: 0, totalNodes: 0, totalConnections: 0 } + }; + + for (const [legacyPath, component] of Object.entries(project.components || {})) { + try { + const componentResult = await this.exportComponent(legacyPath, component); + registry.components[componentResult.name] = componentResult.registryEntry; + registry.stats.totalComponents++; + registry.stats.totalNodes += componentResult.nodeCount; + registry.stats.totalConnections += componentResult.connectionCount; + result.componentsExported++; + } catch (error) { + result.warnings.push(`Failed to export component ${legacyPath}: ${error.message}`); + } + + processed++; + this.report(10 + (processed / componentCount) * 70, `Exported ${processed}/${componentCount} components`); + } + + // 4. Write registry + await this.writeRegistry(registry); + this.report(85, 'Registry written'); + + // 5. Export models + await this.exportModels(project); + this.report(90, 'Models exported'); + + // 6. Export styles + await this.exportStyles(project); + this.report(95, 'Styles exported'); + + // 7. Validate if requested + if (this.options.validateOutput) { + const validation = await this.validateExport(); + result.warnings.push(...validation.warnings); + if (validation.errors.length > 0) { + result.errors.push(...validation.errors); + result.success = false; + return result; + } + } + + this.report(100, 'Export complete'); + result.success = true; + } catch (error) { + result.errors.push(`Export failed: ${error.message}`); + result.success = false; + } + + return result; + } + + private async exportComponent(legacyPath: string, component: LegacyComponent): Promise { + // Convert path: "/#__cloud__/SendGrid/Send Email" β†’ "cloud/SendGrid/SendEmail" + const folderPath = this.normalizePath(legacyPath); + const outputDir = path.join(this.options.outputDir, 'components', folderPath); + + await fs.mkdir(outputDir, { recursive: true }); + + // Extract and write component.json + const componentMeta = this.extractComponentMeta(legacyPath, component); + await this.atomicWrite(path.join(outputDir, 'component.json'), JSON.stringify(componentMeta, null, 2)); + + // Extract and write nodes.json + const nodes = this.extractNodes(component); + await this.atomicWrite(path.join(outputDir, 'nodes.json'), JSON.stringify(nodes, null, 2)); + + // Extract and write connections.json + const connections = this.extractConnections(component); + await this.atomicWrite(path.join(outputDir, 'connections.json'), JSON.stringify(connections, null, 2)); + + // Write variants if exist + if (component.variants && Object.keys(component.variants).length > 0) { + await this.atomicWrite(path.join(outputDir, 'variants.json'), JSON.stringify(component.variants, null, 2)); + } + + return { + name: this.getComponentName(legacyPath), + path: folderPath, + nodeCount: nodes.nodes.length, + connectionCount: connections.connections.length, + registryEntry: { + path: folderPath, + type: this.inferComponentType(legacyPath, component), + created: new Date().toISOString(), + modified: new Date().toISOString(), + nodeCount: nodes.nodes.length, + connectionCount: connections.connections.length + } + }; + } + + private extractComponentMeta(legacyPath: string, component: LegacyComponent): ComponentMeta { + return { + id: component.id || this.generateId(), + name: this.getComponentName(legacyPath), + displayName: component.name || this.getDisplayName(legacyPath), + path: legacyPath, // PRESERVE original path for cross-component references! + type: this.inferComponentType(legacyPath, component), + ports: { + inputs: this.extractPorts(component, 'input'), + outputs: this.extractPorts(component, 'output') + }, + dependencies: this.extractDependencies(component), + created: new Date().toISOString(), + modified: new Date().toISOString() + }; + } + + private extractNodes(component: LegacyComponent): NodesFile { + const nodes = (component.graph?.roots || []).map((node) => ({ + id: node.id, + type: node.type, // Keep EXACTLY as-is for component references + label: node.label, + position: { x: node.x, y: node.y }, + parent: node.parent, + children: node.children || [], + properties: node.parameters || {}, + ports: node.ports || [], + dynamicports: node.dynamicports || [], + states: node.states, + metadata: node.metadata + })); + + return { + componentId: component.id, + version: 1, + nodes + }; + } + + private extractConnections(component: LegacyComponent): ConnectionsFile { + const connections = (component.graph?.connections || []).map((conn, index) => ({ + id: conn.id || `conn_${index}`, + from: { + node: conn.fromId, + port: conn.fromProperty + }, + to: { + node: conn.toId, + port: conn.toProperty + } + })); + + return { + componentId: component.id, + version: 1, + connections + }; + } + + private normalizePath(legacyPath: string): string { + // "/#__cloud__/SendGrid/Send Email" β†’ "cloud/SendGrid/SendEmail" + return legacyPath + .replace(/^\/#?/, '') // Remove leading /# or / + .replace(/__cloud__/g, 'cloud') // Normalize cloud prefix + .replace(/\s+/g, '') // Remove spaces + .replace(/[^a-zA-Z0-9/]/g, '_'); // Replace special chars + } + + private async atomicWrite(filePath: string, content: string): Promise { + const tempPath = `${filePath}.tmp`; + const backupPath = `${filePath}.backup`; + + try { + await fs.writeFile(tempPath, content); + + // Verify write + const verify = await fs.readFile(tempPath, 'utf-8'); + if (verify !== content) { + throw new Error('Write verification failed'); + } + + // Backup existing + if (await fs.pathExists(filePath)) { + await fs.rename(filePath, backupPath); + } + + // Atomic rename + await fs.rename(tempPath, filePath); + + // Remove backup on success + if (await fs.pathExists(backupPath)) { + await fs.unlink(backupPath); + } + } catch (error) { + // Restore from backup + if (await fs.pathExists(backupPath)) { + await fs.rename(backupPath, filePath); + } + throw error; + } + } + + private report(percent: number, message: string): void { + this.options.onProgress?.(percent, message); + } +} +``` + +### Implementation Steps + +1. Create type definitions for legacy and modern formats +2. Implement core Exporter class +3. Implement path normalization (handle special chars) +4. Implement atomic file writes +5. Implement metadata extraction +6. Implement node extraction (preserve all fields) +7. Implement connection extraction +8. Implement registry generation +9. Add progress reporting +10. Test with 10+ real projects + +### Acceptance Criteria + +- [ ] Exports all component types correctly +- [ ] Preserves all node properties and metadata +- [ ] Preserves all connections +- [ ] Handles special characters in paths +- [ ] Handles deeply nested components +- [ ] Atomic writes prevent corruption +- [ ] Progress reporting works +- [ ] Performance: <30 seconds for 200 components + +### Test Cases + +```typescript +describe('ProjectExporter', () => { + it('should export simple project', async () => { + const result = await exporter.export(simpleProject); + expect(result.success).toBe(true); + expect(result.componentsExported).toBe(5); + }); + + it('should handle cloud components', async () => { + const result = await exporter.export(cloudProject); + expect(result.success).toBe(true); + // Check cloud/ directory created + }); + + it('should preserve original paths for references', async () => { + const result = await exporter.export(projectWithRefs); + const componentMeta = await readJSON('components/Header/component.json'); + expect(componentMeta.path).toBe('/#Header'); // Original preserved + }); + + it('should handle special characters in names', async () => { + const result = await exporter.export(projectWithSpecialChars); + // Verify folders created without errors + }); + + it('should preserve AI metadata', async () => { + const result = await exporter.export(projectWithAIHistory); + const nodes = await readJSON('components/Function/nodes.json'); + expect(nodes.nodes[0].metadata.prompt.history).toBeDefined(); + }); +}); +``` + +--- + +## STRUCT-003: Import Engine Core + +**Effort:** 16-20 hours (4 days) +**Priority:** Critical +**Depends on:** STRUCT-001, STRUCT-002 +**Blocks:** STRUCT-004 + +### Description + +Build the engine that converts the new multi-file format back to legacy `project.json` for runtime compatibility. + +### Core Class + +```typescript +// packages/noodl-editor/src/editor/src/services/ProjectStructure/Importer.ts + +export class ProjectImporter { + async import(projectDir: string): Promise { + // 1. Read project metadata + const projectMeta = await this.readProjectFile(projectDir); + + // 2. Read registry + const registry = await this.readRegistry(projectDir); + + // 3. Import all components + const components: Record = {}; + + for (const [name, info] of Object.entries(registry.components)) { + const componentDir = path.join(projectDir, 'components', info.path); + const legacyPath = await this.getLegacyPath(componentDir); + components[legacyPath] = await this.importComponent(componentDir); + } + + // 4. Import models + const models = await this.importModels(projectDir); + + // 5. Import styles + const styles = await this.importStyles(projectDir); + + // 6. Reconstruct full project + return { + name: projectMeta.name, + version: projectMeta.version, + components, + variants: await this.importVariants(projectDir), + styles, + cloudservices: projectMeta.cloudservices, + metadata: projectMeta.metadata + }; + } + + async importComponent(componentDir: string): Promise { + const meta = await this.readJSON(path.join(componentDir, 'component.json')); + const nodes = await this.readJSON(path.join(componentDir, 'nodes.json')); + const connections = await this.readJSON(path.join(componentDir, 'connections.json')); + + // Reconstruct legacy format + return { + id: meta.id, + name: meta.displayName, + graph: { + roots: nodes.nodes.map((node) => ({ + id: node.id, + type: node.type, + label: node.label, + x: node.position?.x || 0, + y: node.position?.y || 0, + parameters: node.properties, + ports: node.ports, + dynamicports: node.dynamicports, + children: node.children, + metadata: node.metadata, + states: node.states + })), + connections: connections.connections.map((conn) => ({ + fromId: conn.from.node, + fromProperty: conn.from.port, + toId: conn.to.node, + toProperty: conn.to.port + })) + } + // ... other legacy fields + }; + } + + async importSingleComponent(componentPath: string): Promise { + // For incremental imports - load just one component + return this.importComponent(componentPath); + } +} +``` + +### Round-Trip Validation + +```typescript +// packages/noodl-editor/src/editor/src/services/ProjectStructure/Validator.ts + +export class RoundTripValidator { + async validate(original: LegacyProject, imported: LegacyProject): Promise { + const errors: string[] = []; + const warnings: string[] = []; + + // 1. Component count + const origCount = Object.keys(original.components || {}).length; + const impCount = Object.keys(imported.components || {}).length; + if (origCount !== impCount) { + errors.push(`Component count mismatch: ${origCount} β†’ ${impCount}`); + } + + // 2. Deep compare each component + for (const [path, origComp] of Object.entries(original.components || {})) { + const impComp = imported.components[path]; + + if (!impComp) { + errors.push(`Missing component: ${path}`); + continue; + } + + // Node count + const origNodes = origComp.graph?.roots?.length || 0; + const impNodes = impComp.graph?.roots?.length || 0; + if (origNodes !== impNodes) { + errors.push(`Node count mismatch in ${path}: ${origNodes} β†’ ${impNodes}`); + } + + // Connection count + const origConns = origComp.graph?.connections?.length || 0; + const impConns = impComp.graph?.connections?.length || 0; + if (origConns !== impConns) { + errors.push(`Connection count mismatch in ${path}: ${origConns} β†’ ${impConns}`); + } + + // Deep compare nodes + for (const origNode of origComp.graph?.roots || []) { + const impNode = impComp.graph?.roots?.find((n) => n.id === origNode.id); + if (!impNode) { + errors.push(`Missing node ${origNode.id} in ${path}`); + continue; + } + + // Type must match exactly + if (origNode.type !== impNode.type) { + errors.push(`Node type mismatch: ${origNode.type} β†’ ${impNode.type}`); + } + + // Metadata must be preserved + if (!deepEqual(origNode.metadata, impNode.metadata)) { + warnings.push(`Metadata changed for node ${origNode.id} in ${path}`); + } + } + } + + return { + valid: errors.length === 0, + errors, + warnings + }; + } +} +``` + +### Acceptance Criteria + +- [ ] Imports all components correctly +- [ ] Reconstructs legacy format exactly +- [ ] Round-trip validation passes for all test projects +- [ ] Single component import works +- [ ] Performance: <5 seconds for 200 components +- [ ] Handles missing files gracefully + +--- + +## STRUCT-004: Editor Format Detection + +**Effort:** 6-8 hours (1.5 days) +**Priority:** High +**Depends on:** STRUCT-003 + +### Description + +Add automatic detection of project format (legacy vs v2) when opening projects. + +### Implementation + +```typescript +// packages/noodl-editor/src/editor/src/services/ProjectStructure/FormatDetector.ts + +export enum ProjectFormat { + LEGACY = 'legacy', + V2 = 'v2', + UNKNOWN = 'unknown' +} + +export interface FormatDetectionResult { + format: ProjectFormat; + confidence: 'high' | 'medium' | 'low'; + details: { + hasProjectJson: boolean; + hasNodgexProject: boolean; + hasComponentsDir: boolean; + hasRegistry: boolean; + }; +} + +export class FormatDetector { + async detect(projectPath: string): Promise { + const details = { + hasProjectJson: await fs.pathExists(path.join(projectPath, 'project.json')), + hasNodgexProject: await fs.pathExists(path.join(projectPath, 'nodegx.project.json')), + hasComponentsDir: await fs.pathExists(path.join(projectPath, 'components')), + hasRegistry: await fs.pathExists(path.join(projectPath, 'components', '_registry.json')) + }; + + // V2 format: has nodegx.project.json + components directory + if (details.hasNodgexProject && details.hasComponentsDir && details.hasRegistry) { + return { format: ProjectFormat.V2, confidence: 'high', details }; + } + + // Legacy format: has project.json only + if (details.hasProjectJson && !details.hasNodgexProject) { + return { format: ProjectFormat.LEGACY, confidence: 'high', details }; + } + + // Mixed or unknown + if (details.hasProjectJson && details.hasNodgexProject) { + // Both exist - prefer V2 but warn + return { format: ProjectFormat.V2, confidence: 'medium', details }; + } + + return { format: ProjectFormat.UNKNOWN, confidence: 'low', details }; + } +} +``` + +### Integration with Project Loading + +```typescript +// packages/noodl-editor/src/editor/src/models/projectmodel.ts + +class ProjectModel { + private format: ProjectFormat = ProjectFormat.LEGACY; + private formatDetector = new FormatDetector(); + + async loadProject(projectPath: string): Promise { + const detection = await this.formatDetector.detect(projectPath); + this.format = detection.format; + + if (detection.confidence !== 'high') { + console.warn(`Project format detection confidence: ${detection.confidence}`); + } + + if (this.format === ProjectFormat.V2) { + await this.loadV2Project(projectPath); + } else if (this.format === ProjectFormat.LEGACY) { + await this.loadLegacyProject(projectPath); + } else { + throw new Error('Unknown project format'); + } + } + + private async loadV2Project(projectPath: string): Promise { + // Only load metadata and registry - components on demand + this.metadata = await this.loadProjectMeta(projectPath); + this.registry = await this.loadRegistry(projectPath); + // Components loaded lazily via getComponent() + } +} +``` + +### Acceptance Criteria + +- [ ] Correctly identifies legacy format +- [ ] Correctly identifies V2 format +- [ ] Handles mixed/corrupted states +- [ ] Reports confidence level +- [ ] Integrates with project loading + +--- + +## STRUCT-005: Lazy Component Loading + +**Effort:** 12-16 hours (3 days) +**Priority:** High +**Depends on:** STRUCT-004 + +### Description + +Implement on-demand component loading for V2 format projects to reduce memory usage and improve startup time. + +### Implementation + +```typescript +// packages/noodl-editor/src/editor/src/services/ProjectStructure/ComponentLoader.ts + +export class ComponentLoader { + private cache: Map = new Map(); + private maxCacheAge = 5 * 60 * 1000; // 5 minutes + private maxCacheSize = 50; // components + + async loadComponent(projectPath: string, componentPath: string): Promise { + const cacheKey = `${projectPath}:${componentPath}`; + + // Check cache + const cached = this.cache.get(cacheKey); + if (cached && Date.now() - cached.loadedAt < this.maxCacheAge) { + return cached.component; + } + + // Load from files + const componentDir = path.join(projectPath, 'components', componentPath); + + const [meta, nodes, connections] = await Promise.all([ + this.readJSON(path.join(componentDir, 'component.json')), + this.readJSON(path.join(componentDir, 'nodes.json')), + this.readJSON(path.join(componentDir, 'connections.json')) + ]); + + const component = this.reconstructComponent(meta, nodes, connections); + + // Update cache + this.cache.set(cacheKey, { component, loadedAt: Date.now() }); + this.pruneCache(); + + return component; + } + + async preloadComponents(projectPath: string, componentPaths: string[]): Promise { + // Parallel loading for known needed components + await Promise.all(componentPaths.map((p) => this.loadComponent(projectPath, p))); + } + + invalidate(componentPath?: string): void { + if (componentPath) { + // Invalidate specific component + for (const key of this.cache.keys()) { + if (key.includes(componentPath)) { + this.cache.delete(key); + } + } + } else { + // Invalidate all + this.cache.clear(); + } + } + + private pruneCache(): void { + if (this.cache.size > this.maxCacheSize) { + // Remove oldest entries + const entries = Array.from(this.cache.entries()).sort((a, b) => a[1].loadedAt - b[1].loadedAt); + + const toRemove = entries.slice(0, this.cache.size - this.maxCacheSize); + toRemove.forEach(([key]) => this.cache.delete(key)); + } + } +} +``` + +### Acceptance Criteria + +- [ ] Components load on demand +- [ ] Cache improves repeated access +- [ ] Cache eviction works correctly +- [ ] Memory usage stays bounded +- [ ] Parallel preloading works +- [ ] Cache invalidation works + +--- + +## STRUCT-006: Component-Level Save + +**Effort:** 12-16 hours (3 days) +**Priority:** High +**Depends on:** STRUCT-002, STRUCT-005 + +### Description + +Implement saving changes to individual component files instead of rewriting the entire project. + +### Implementation + +```typescript +// packages/noodl-editor/src/editor/src/services/ProjectStructure/ComponentSaver.ts + +export class ComponentSaver { + private pendingWrites: Map = new Map(); + private writeDebounce = 500; // ms + + async saveComponent(projectPath: string, componentPath: string, component: Component): Promise { + const componentDir = path.join(projectPath, 'components', componentPath); + + // Ensure directory exists + await fs.mkdir(componentDir, { recursive: true }); + + // Prepare files + const meta = this.extractMeta(component); + const nodes = this.extractNodes(component); + const connections = this.extractConnections(component); + + // Atomic writes + await Promise.all([ + this.atomicWrite(path.join(componentDir, 'component.json'), JSON.stringify(meta, null, 2)), + this.atomicWrite(path.join(componentDir, 'nodes.json'), JSON.stringify(nodes, null, 2)), + this.atomicWrite(path.join(componentDir, 'connections.json'), JSON.stringify(connections, null, 2)) + ]); + + // Update registry + await this.updateRegistry(projectPath, componentPath, component); + } + + async saveComponentDebounced(projectPath: string, componentPath: string, component: Component): Promise { + const key = `${projectPath}:${componentPath}`; + + this.pendingWrites.set(key, { + content: JSON.stringify(component), + timestamp: Date.now() + }); + + // Debounced write + setTimeout(async () => { + const pending = this.pendingWrites.get(key); + if (pending && Date.now() - pending.timestamp >= this.writeDebounce) { + this.pendingWrites.delete(key); + await this.saveComponent(projectPath, componentPath, JSON.parse(pending.content)); + } + }, this.writeDebounce); + } + + private async updateRegistry(projectPath: string, componentPath: string, component: Component): Promise { + const registryPath = path.join(projectPath, 'components', '_registry.json'); + const registry = await this.readJSON(registryPath); + + registry.components[componentPath] = { + ...registry.components[componentPath], + modified: new Date().toISOString(), + nodeCount: component.graph?.roots?.length || 0, + connectionCount: component.graph?.connections?.length || 0 + }; + + registry.lastUpdated = new Date().toISOString(); + + await this.atomicWrite(registryPath, JSON.stringify(registry, null, 2)); + } +} +``` + +### Acceptance Criteria + +- [ ] Single component saves work +- [ ] Atomic writes prevent corruption +- [ ] Registry updates correctly +- [ ] Debouncing prevents excessive writes +- [ ] Auto-save integration works +- [ ] Performance: <100ms per component + +--- + +## STRUCT-007: Migration Wizard UI + +**Effort:** 10-14 hours (2.5 days) +**Priority:** Medium +**Depends on:** STRUCT-002, STRUCT-003 + +### Description + +Create a user-friendly wizard for migrating projects from legacy to V2 format. + +### UI Design + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Project Structure Migration β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ Your project uses the legacy single-file format. Migrating to the new β”‚ +β”‚ format enables powerful features: β”‚ +β”‚ β”‚ +β”‚ βœ“ AI-powered editing assistance β”‚ +β”‚ βœ“ Better Git collaboration (meaningful diffs) β”‚ +β”‚ βœ“ 10x faster project loading β”‚ +β”‚ βœ“ Component-level version history β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Project Analysis β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Project: My Conference App β”‚ β”‚ +β”‚ β”‚ Components: 54 β”‚ β”‚ +β”‚ β”‚ Total Nodes: 3,420 β”‚ β”‚ +β”‚ β”‚ Current Size: 2.4 MB β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Estimated time: ~30 seconds β”‚ β”‚ +β”‚ β”‚ New size: ~2.6 MB (54 files) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ ⚠️ Pre-flight Checks β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ βœ“ All 54 components can be parsed β”‚ β”‚ +β”‚ β”‚ βœ“ No circular reference issues detected β”‚ β”‚ +β”‚ β”‚ βœ“ All node types supported β”‚ β”‚ +β”‚ β”‚ ⚠ 2 components have very long paths (may be truncated) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β˜‘ Create backup before migration (recommended) β”‚ +β”‚ ☐ Delete legacy project.json after successful migration β”‚ +β”‚ β”‚ +β”‚ β”‚ +β”‚ [Cancel] [Start Migration] β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Progress View + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Migration in Progress β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 65% β”‚ +β”‚ β”‚ +β”‚ Current step: Exporting components/pages/SchedulePage... β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Progress Log [β–Ό] β”‚ β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ +β”‚ β”‚ βœ“ Created backup: project_backup_20260107_143022.json β”‚ β”‚ +β”‚ β”‚ βœ“ Created directory structure β”‚ β”‚ +β”‚ β”‚ βœ“ Exported project metadata β”‚ β”‚ +β”‚ β”‚ βœ“ Exported 32/54 components β”‚ β”‚ +β”‚ β”‚ β†’ Exporting components/pages/SchedulePage... β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ [Cancel Migration] β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Component Implementation + +```typescript +// packages/noodl-editor/src/editor/src/views/MigrationWizard/MigrationWizard.tsx + +interface MigrationWizardProps { + projectPath: string; + onComplete: (success: boolean) => void; + onCancel: () => void; +} + +export function MigrationWizard({ projectPath, onComplete, onCancel }: MigrationWizardProps) { + const [step, setStep] = useState<'analysis' | 'progress' | 'complete' | 'error'>('analysis'); + const [analysis, setAnalysis] = useState(null); + const [progress, setProgress] = useState(0); + const [progressMessage, setProgressMessage] = useState(''); + const [error, setError] = useState(null); + const [createBackup, setCreateBackup] = useState(true); + const [deleteLegacy, setDeleteLegacy] = useState(false); + + useEffect(() => { + // Run analysis on mount + analyzeProject(projectPath).then(setAnalysis); + }, [projectPath]); + + const startMigration = async () => { + setStep('progress'); + + try { + if (createBackup) { + setProgressMessage('Creating backup...'); + await createProjectBackup(projectPath); + } + + const exporter = new ProjectExporter({ + outputDir: projectPath, + preserveOriginalPaths: true, + validateOutput: true, + onProgress: (percent, message) => { + setProgress(percent); + setProgressMessage(message); + } + }); + + const result = await exporter.export(await loadLegacyProject(projectPath)); + + if (result.success) { + if (deleteLegacy) { + await fs.unlink(path.join(projectPath, 'project.json')); + } + setStep('complete'); + onComplete(true); + } else { + setError(result.errors.join('\n')); + setStep('error'); + } + } catch (err) { + setError(err.message); + setStep('error'); + } + }; + + // ... render logic +} +``` + +### Acceptance Criteria + +- [ ] Analysis shows project statistics +- [ ] Pre-flight checks identify issues +- [ ] Progress indicator is accurate +- [ ] Backup creation works +- [ ] Cancel mid-migration works (with rollback) +- [ ] Error handling shows clear messages +- [ ] Success message with next steps + +--- + +## STRUCT-008: Testing & Validation + +**Effort:** 16-20 hours (4 days) +**Priority:** High +**Depends on:** All other STRUCT tasks + +### Description + +Comprehensive testing of the entire structure system with real projects. + +### Test Suite + +```typescript +// packages/noodl-editor/tests/structure/ + +describe('Project Structure Migration', () => { + describe('Schema Validation', () => { + it('should validate component.json schema'); + it('should validate nodes.json schema'); + it('should validate connections.json schema'); + it('should reject invalid schemas with clear errors'); + }); + + describe('Export Engine', () => { + it('should export minimal project'); + it('should export complex project with 200+ components'); + it('should handle cloud components'); + it('should handle special characters in paths'); + it('should preserve all AI metadata'); + it('should preserve dynamic ports'); + it('should preserve component references'); + it('should generate valid registry'); + }); + + describe('Import Engine', () => { + it('should import exported project'); + it('should reconstruct exact legacy format'); + it('should pass round-trip validation'); + it('should import single component'); + }); + + describe('Round-Trip Validation', () => { + testProjects.forEach((project) => { + it(`should pass round-trip for ${project.name}`, async () => { + const original = await loadProject(project.path); + const exported = await exportProject(original); + const imported = await importProject(exported); + + const validation = await validateRoundTrip(original, imported); + expect(validation.valid).toBe(true); + expect(validation.errors).toHaveLength(0); + }); + }); + }); + + describe('Performance', () => { + it('should export 200 components in <30 seconds'); + it('should import 200 components in <5 seconds'); + it('should load single component in <100ms'); + it('should save single component in <100ms'); + }); + + describe('Edge Cases', () => { + it('should handle empty project'); + it('should handle project with no connections'); + it('should handle circular component references'); + it('should handle very deep nesting'); + it('should handle components with 1000+ nodes'); + it('should handle unicode in component names'); + }); +}); +``` + +### Real Project Test Set + +Collect 10+ real Noodl projects for testing: + +- Small project (5-10 components) +- Medium project (50-100 components) +- Large project (200+ components) +- Project with cloud functions +- Project with AI-generated code +- Project with complex nesting +- Project with special characters +- Project from old Noodl version + +### Acceptance Criteria + +- [ ] 100% pass rate on unit tests +- [ ] 100% pass rate on integration tests +- [ ] All real projects pass round-trip +- [ ] Performance benchmarks pass +- [ ] Edge cases handled + +--- + +## STRUCT-009: Documentation + +**Effort:** 6-8 hours (1.5 days) +**Priority:** Medium +**Depends on:** All other STRUCT tasks + +### Documentation Files + +``` +docs/ +β”œβ”€β”€ structure/ +β”‚ β”œβ”€β”€ overview.md # Why we did this +β”‚ β”œβ”€β”€ file-formats.md # Detailed format specs +β”‚ β”œβ”€β”€ migration-guide.md # How to migrate +β”‚ β”œβ”€β”€ troubleshooting.md # Common issues +β”‚ └── api-reference.md # For developers +└── schemas/ + └── README.md # Schema documentation +``` + +### Acceptance Criteria + +- [ ] Overview explains benefits +- [ ] File formats fully documented +- [ ] Migration guide is step-by-step +- [ ] Troubleshooting covers common issues +- [ ] API reference for developers + +--- + +# PHASE 10B: FRONTEND AI ASSISTANT + +## Overview + +Build an AI assistant that can understand, navigate, and modify Nodegx frontend components using natural language. + +**Duration:** 6-8 weeks +**Total Effort:** 100-130 hours +**Priority:** HIGH +**Depends on:** PHASE 10A complete + +### Vision + +``` +User: "Add a loading spinner to the UserProfile component while fetching data" + +AI: [Reading components/UserProfile/...] + + I'll add a loading state with spinner: + - Added condition node for loading state + - Added Spinner component from shared library + - Connected fetch.isPending β†’ spinner.visible + + [Modified: components/UserProfile/nodes.json] + [Modified: components/UserProfile/connections.json] + + Done! The component now shows a spinner during fetch. +``` + +--- + +## AI-001: Component Reading Tools + +**Effort:** 12-16 hours (3 days) +**Priority:** Critical + +### Description + +Create tools that allow AI to read and understand component structure. + +### Tool Definitions + +```typescript +// packages/noodl-editor/src/editor/src/services/AI/tools/ComponentTools.ts + +export const componentTools = [ + { + name: 'list_components', + description: 'List all components in the project with summary info', + parameters: { + type: 'object', + properties: { + filter: { + type: 'string', + description: 'Optional filter: "pages", "shared", "cloud", or path prefix' + } + } + }, + execute: async ({ filter }) => { + const registry = await loadRegistry(); + let components = Object.entries(registry.components); + + if (filter) { + components = components.filter(([path]) => path.includes(filter) || path.startsWith(filter)); + } + + return components.map(([path, info]) => ({ + path, + type: info.type, + nodeCount: info.nodeCount, + modified: info.modified + })); + } + }, + + { + name: 'read_component', + description: 'Read complete component definition including metadata, nodes, and connections', + parameters: { + type: 'object', + properties: { + componentPath: { + type: 'string', + description: 'Path to component, e.g., "pages/HomePage" or "shared/Button"' + } + }, + required: ['componentPath'] + }, + execute: async ({ componentPath }) => { + const componentDir = path.join(projectPath, 'components', componentPath); + + const [meta, nodes, connections] = await Promise.all([ + readJSON(path.join(componentDir, 'component.json')), + readJSON(path.join(componentDir, 'nodes.json')), + readJSON(path.join(componentDir, 'connections.json')) + ]); + + return { meta, nodes, connections }; + } + }, + + { + name: 'get_component_dependencies', + description: 'Get all components that this component depends on', + parameters: { + type: 'object', + properties: { + componentPath: { type: 'string' } + }, + required: ['componentPath'] + }, + execute: async ({ componentPath }) => { + const meta = await readComponentMeta(componentPath); + return { + direct: meta.dependencies, + transitive: await getTransitiveDependencies(componentPath) + }; + } + }, + + { + name: 'find_components_using', + description: 'Find all components that use a specific component or model', + parameters: { + type: 'object', + properties: { + targetPath: { type: 'string' }, + targetType: { type: 'string', enum: ['component', 'model'] } + }, + required: ['targetPath'] + }, + execute: async ({ targetPath, targetType }) => { + // Search through all component.json for dependencies + const registry = await loadRegistry(); + const using: string[] = []; + + for (const [path] of Object.entries(registry.components)) { + const meta = await readComponentMeta(path); + if (meta.dependencies?.includes(targetPath)) { + using.push(path); + } + } + + return using; + } + }, + + { + name: 'explain_component', + description: 'Generate a natural language explanation of what a component does', + parameters: { + type: 'object', + properties: { + componentPath: { type: 'string' } + }, + required: ['componentPath'] + }, + execute: async ({ componentPath }) => { + const { meta, nodes, connections } = await readFullComponent(componentPath); + + // Analyze structure + const analysis = { + inputPorts: meta.ports?.inputs || [], + outputPorts: meta.ports?.outputs || [], + visualNodes: nodes.nodes.filter((n) => isVisualNode(n.type)), + logicNodes: nodes.nodes.filter((n) => isLogicNode(n.type)), + dataNodes: nodes.nodes.filter((n) => isDataNode(n.type)), + componentRefs: nodes.nodes.filter((n) => n.type.startsWith('component:')) + }; + + return analysis; + } + } +]; +``` + +### Acceptance Criteria + +- [ ] All 5 reading tools implemented +- [ ] Tools return properly structured data +- [ ] Error handling for missing components +- [ ] Performance: each tool <500ms + +--- + +## AI-002: Component Modification Tools + +**Effort:** 16-20 hours (4 days) +**Priority:** Critical + +### Tool Definitions + +```typescript +export const modificationTools = [ + { + name: 'add_node', + description: 'Add a new node to a component', + parameters: { + type: 'object', + properties: { + componentPath: { type: 'string' }, + node: { + type: 'object', + properties: { + type: { type: 'string' }, + label: { type: 'string' }, + parent: { type: 'string' }, + position: { + type: 'object', + properties: { x: { type: 'number' }, y: { type: 'number' } } + }, + properties: { type: 'object' } + }, + required: ['type'] + } + }, + required: ['componentPath', 'node'] + }, + execute: async ({ componentPath, node }) => { + const nodes = await readNodes(componentPath); + + const newNode = { + id: generateNodeId(), + ...node, + position: node.position || calculatePosition(nodes, node.parent) + }; + + nodes.nodes.push(newNode); + + // Update parent's children if specified + if (node.parent) { + const parent = nodes.nodes.find((n) => n.id === node.parent); + if (parent) { + parent.children = parent.children || []; + parent.children.push(newNode.id); + } + } + + await saveNodes(componentPath, nodes); + + return { success: true, nodeId: newNode.id }; + } + }, + + { + name: 'update_node_property', + description: 'Update a property on an existing node', + parameters: { + type: 'object', + properties: { + componentPath: { type: 'string' }, + nodeId: { type: 'string' }, + property: { type: 'string' }, + value: {} + }, + required: ['componentPath', 'nodeId', 'property', 'value'] + }, + execute: async ({ componentPath, nodeId, property, value }) => { + const nodes = await readNodes(componentPath); + const node = nodes.nodes.find((n) => n.id === nodeId); + + if (!node) { + return { success: false, error: `Node ${nodeId} not found` }; + } + + node.properties = node.properties || {}; + node.properties[property] = value; + + await saveNodes(componentPath, nodes); + + return { success: true }; + } + }, + + { + name: 'add_connection', + description: 'Add a connection between two nodes', + parameters: { + type: 'object', + properties: { + componentPath: { type: 'string' }, + from: { + type: 'object', + properties: { + node: { type: 'string' }, + port: { type: 'string' } + }, + required: ['node', 'port'] + }, + to: { + type: 'object', + properties: { + node: { type: 'string' }, + port: { type: 'string' } + }, + required: ['node', 'port'] + } + }, + required: ['componentPath', 'from', 'to'] + }, + execute: async ({ componentPath, from, to }) => { + const connections = await readConnections(componentPath); + + const newConnection = { + id: generateConnectionId(), + from, + to + }; + + connections.connections.push(newConnection); + await saveConnections(componentPath, connections); + + return { success: true, connectionId: newConnection.id }; + } + }, + + { + name: 'remove_node', + description: 'Remove a node and its connections from a component', + parameters: { + type: 'object', + properties: { + componentPath: { type: 'string' }, + nodeId: { type: 'string' } + }, + required: ['componentPath', 'nodeId'] + }, + execute: async ({ componentPath, nodeId }) => { + // Remove node + const nodes = await readNodes(componentPath); + nodes.nodes = nodes.nodes.filter((n) => n.id !== nodeId); + + // Remove from parent's children + nodes.nodes.forEach((n) => { + if (n.children?.includes(nodeId)) { + n.children = n.children.filter((c) => c !== nodeId); + } + }); + + // Remove connections + const connections = await readConnections(componentPath); + connections.connections = connections.connections.filter((c) => c.from.node !== nodeId && c.to.node !== nodeId); + + await saveNodes(componentPath, nodes); + await saveConnections(componentPath, connections); + + return { success: true }; + } + }, + + { + name: 'create_component', + description: 'Create a new component', + parameters: { + type: 'object', + properties: { + name: { type: 'string' }, + path: { type: 'string', description: 'e.g., "shared" or "pages"' }, + type: { type: 'string', enum: ['visual', 'logic', 'page'] }, + inputs: { type: 'array' }, + outputs: { type: 'array' } + }, + required: ['name'] + }, + execute: async ({ name, path: basePath, type, inputs, outputs }) => { + const componentPath = path.join(basePath || 'shared', name); + const componentDir = path.join(projectPath, 'components', componentPath); + + await fs.mkdir(componentDir, { recursive: true }); + + // Create component.json + await writeJSON(path.join(componentDir, 'component.json'), { + id: generateComponentId(), + name, + type: type || 'visual', + ports: { inputs: inputs || [], outputs: outputs || [] }, + dependencies: [], + created: new Date().toISOString(), + modified: new Date().toISOString() + }); + + // Create empty nodes.json + await writeJSON(path.join(componentDir, 'nodes.json'), { + componentId: generateComponentId(), + version: 1, + nodes: [] + }); + + // Create empty connections.json + await writeJSON(path.join(componentDir, 'connections.json'), { + componentId: generateComponentId(), + version: 1, + connections: [] + }); + + // Update registry + await updateRegistry(componentPath); + + return { success: true, componentPath }; + } + } +]; +``` + +### Acceptance Criteria + +- [ ] All modification tools implemented +- [ ] Changes persist correctly +- [ ] Undo support works +- [ ] Validation prevents invalid states +- [ ] Registry updates on changes + +--- + +## AI-003: LangGraph Agent Setup + +**Effort:** 16-20 hours (4 days) +**Priority:** Critical + +### Agent Architecture + +```typescript +// packages/noodl-editor/src/editor/src/services/AI/FrontendAgent.ts + +import { ChatAnthropic } from '@langchain/anthropic'; +import { StateGraph, MemorySaver } from '@langchain/langgraph'; + +interface AgentState { + messages: Message[]; + currentComponent: string | null; + pendingChanges: Change[]; + context: ProjectContext; +} + +export class FrontendAgent { + private graph: StateGraph; + private memory: MemorySaver; + + constructor() { + this.memory = new MemorySaver(); + this.graph = this.buildGraph(); + } + + private buildGraph(): StateGraph { + const graph = new StateGraph({ + channels: { + messages: { default: () => [] }, + currentComponent: { default: () => null }, + pendingChanges: { default: () => [] }, + context: { default: () => ({}) } + } + }); + + // Add nodes + graph.addNode('understand', this.understandRequest); + graph.addNode('gather_context', this.gatherContext); + graph.addNode('plan_changes', this.planChanges); + graph.addNode('execute_changes', this.executeChanges); + graph.addNode('respond', this.generateResponse); + + // Add edges + graph.addEdge('__start__', 'understand'); + graph.addConditionalEdges('understand', this.routeAfterUnderstand, { + needs_context: 'gather_context', + ready_to_plan: 'plan_changes', + clarify: 'respond' + }); + graph.addEdge('gather_context', 'plan_changes'); + graph.addEdge('plan_changes', 'execute_changes'); + graph.addEdge('execute_changes', 'respond'); + graph.addEdge('respond', '__end__'); + + return graph.compile({ checkpointer: this.memory }); + } + + private understandRequest = async (state: AgentState) => { + const llm = new ChatAnthropic({ model: 'claude-sonnet-4-20250514' }); + + const response = await llm.invoke([{ role: 'system', content: UNDERSTAND_PROMPT }, ...state.messages]); + + return { + ...state, + understanding: response.content + }; + }; + + private gatherContext = async (state: AgentState) => { + // Use reading tools to gather needed context + const tools = componentTools; + + // Determine what context is needed + const neededComponents = extractComponentReferences(state.understanding); + + const context = {}; + for (const comp of neededComponents) { + context[comp] = await tools.find((t) => t.name === 'read_component').execute({ componentPath: comp }); + } + + return { + ...state, + context + }; + }; + + private planChanges = async (state: AgentState) => { + const llm = new ChatAnthropic({ model: 'claude-sonnet-4-20250514' }); + + const response = await llm.invoke([ + { role: 'system', content: PLANNING_PROMPT }, + { role: 'user', content: JSON.stringify(state.context) }, + ...state.messages + ]); + + // Parse planned changes + const changes = parseChangePlan(response.content); + + return { + ...state, + pendingChanges: changes + }; + }; + + private executeChanges = async (state: AgentState) => { + const results = []; + + for (const change of state.pendingChanges) { + const tool = modificationTools.find((t) => t.name === change.tool); + if (tool) { + const result = await tool.execute(change.params); + results.push({ change, result }); + } + } + + return { + ...state, + executionResults: results + }; + }; + + async process(message: string, threadId: string): Promise { + const config = { configurable: { thread_id: threadId } }; + + const result = await this.graph.invoke( + { + messages: [{ role: 'user', content: message }] + }, + config + ); + + return { + response: result.messages[result.messages.length - 1].content, + changes: result.pendingChanges, + success: result.executionResults?.every((r) => r.result.success) + }; + } +} +``` + +### Acceptance Criteria + +- [ ] Agent processes natural language requests +- [ ] Context gathering is efficient +- [ ] Change planning is accurate +- [ ] Execution handles errors gracefully +- [ ] Conversation memory persists + +--- + +## AI-004: Conversation Memory & Caching + +**Effort:** 12-16 hours (3 days) +**Priority:** High + +### Implementation + +```typescript +// packages/noodl-editor/src/editor/src/services/AI/ConversationMemory.ts + +export class ConversationMemory { + private messages: Message[] = []; + private projectContextCache: Map = new Map(); + private maxContextTokens = 100000; + private cacheTTL = 5 * 60 * 1000; // 5 minutes + + addUserMessage(content: string): void { + this.messages.push({ role: 'user', content, timestamp: Date.now() }); + this.pruneIfNeeded(); + } + + addAssistantMessage(content: string): void { + this.messages.push({ role: 'assistant', content, timestamp: Date.now() }); + } + + getMessagesForRequest(): Message[] { + // Return messages formatted for API call + return this.messages.map((m) => ({ + role: m.role, + content: m.content + })); + } + + getCachedContext(key: string): any | null { + const cached = this.projectContextCache.get(key); + if (cached && Date.now() - cached.timestamp < this.cacheTTL) { + return cached.data; + } + return null; + } + + setCachedContext(key: string, data: any): void { + this.projectContextCache.set(key, { data, timestamp: Date.now() }); + } + + private pruneIfNeeded(): void { + // Estimate token count + const estimatedTokens = this.messages.reduce((sum, m) => sum + Math.ceil(m.content.length / 4), 0); + + if (estimatedTokens > this.maxContextTokens * 0.8) { + // Summarize older messages + this.summarizeOldMessages(); + } + } + + private async summarizeOldMessages(): Promise { + if (this.messages.length <= 10) return; + + const oldMessages = this.messages.slice(0, -10); + const recentMessages = this.messages.slice(-10); + + const summary = await this.generateSummary(oldMessages); + + this.messages = [ + { role: 'system', content: `Previous conversation summary:\n${summary}`, timestamp: Date.now() }, + ...recentMessages + ]; + } +} +``` + +### Acceptance Criteria + +- [ ] Messages persist across turns +- [ ] Context caching reduces API calls +- [ ] Token count stays within limits +- [ ] Summarization works correctly +- [ ] Cache invalidation works + +--- + +## AI-005: AI Panel UI + +**Effort:** 16-20 hours (4 days) +**Priority:** High + +### UI Component + +```typescript +// packages/noodl-editor/src/editor/src/views/AIPanel/AIPanel.tsx + +export function AIPanel() { + const [messages, setMessages] = useState([]); + const [input, setInput] = useState(''); + const [isProcessing, setIsProcessing] = useState(false); + const [pendingChanges, setPendingChanges] = useState([]); + + const agent = useFrontendAgent(); + + const handleSend = async () => { + if (!input.trim() || isProcessing) return; + + const userMessage = input; + setInput(''); + setMessages((prev) => [...prev, { role: 'user', content: userMessage }]); + setIsProcessing(true); + + try { + const response = await agent.process(userMessage); + + setMessages((prev) => [...prev, { role: 'assistant', content: response.response }]); + + if (response.changes?.length > 0) { + setPendingChanges(response.changes); + } + } catch (error) { + setMessages((prev) => [ + ...prev, + { + role: 'assistant', + content: `Error: ${error.message}`, + isError: true + } + ]); + } finally { + setIsProcessing(false); + } + }; + + return ( +
+
+

AI Assistant

+
+ + +
+
+ +
+ + +
+ +
+ {messages.map((msg, i) => ( + + ))} + {isProcessing && } +
+ + {pendingChanges.length > 0 && ( + setPendingChanges([])} + /> + )} + +
+